aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--.travis.yml31
-rw-r--r--README.md4
-rw-r--r--Vagrantfile25
-rw-r--r--build/build.xml234
-rw-r--r--build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php5
-rwxr-xr-xbuild/package.php23
-rw-r--r--phpBB/adm/index.php5
-rw-r--r--phpBB/adm/style/acp_groups.html9
-rw-r--r--phpBB/adm/style/acp_icons.html8
-rw-r--r--phpBB/adm/style/acp_permissions.html11
-rw-r--r--phpBB/adm/style/admin.css96
-rw-r--r--phpBB/adm/style/captcha_recaptcha.html26
-rw-r--r--phpBB/adm/style/install_convert.html134
-rw-r--r--phpBB/adm/style/install_error.html8
-rw-r--r--phpBB/adm/style/install_footer.html21
-rw-r--r--phpBB/adm/style/install_header.html54
-rw-r--r--phpBB/adm/style/install_install.html77
-rw-r--r--phpBB/adm/style/install_main.html6
-rw-r--r--phpBB/adm/style/install_update.html491
-rw-r--r--phpBB/adm/style/install_update_diff.html255
-rw-r--r--phpBB/adm/style/installer_convert.html87
-rw-r--r--phpBB/adm/style/installer_footer.html30
-rw-r--r--phpBB/adm/style/installer_form.html56
-rw-r--r--phpBB/adm/style/installer_header.html58
-rw-r--r--phpBB/adm/style/installer_install.html13
-rw-r--r--phpBB/adm/style/installer_main.html6
-rw-r--r--phpBB/adm/style/installer_update.html13
-rw-r--r--phpBB/adm/style/installer_update_file_status.html80
-rw-r--r--phpBB/adm/style/overall_header.html19
-rw-r--r--phpBB/adm/style/permission_mask.html21
-rw-r--r--phpBB/adm/style/tooltip.js319
-rw-r--r--phpBB/app.php4
-rw-r--r--phpBB/assets/css/font-awesome.min.css4
-rw-r--r--phpBB/assets/fonts/FontAwesome.otfbin0 -> 106260 bytes
-rw-r--r--phpBB/assets/fonts/fontawesome-webfont.eotbin0 -> 68875 bytes
-rw-r--r--phpBB/assets/fonts/fontawesome-webfont.svg640
-rw-r--r--phpBB/assets/fonts/fontawesome-webfont.ttfbin0 -> 138204 bytes
-rw-r--r--phpBB/assets/fonts/fontawesome-webfont.woffbin0 -> 81284 bytes
-rw-r--r--phpBB/assets/fonts/fontawesome-webfont.woff2bin0 -> 64464 bytes
-rw-r--r--phpBB/assets/javascript/core.js21
-rw-r--r--phpBB/assets/javascript/editor.js64
-rw-r--r--phpBB/assets/javascript/installer.js615
-rwxr-xr-xphpBB/bin/phpbbcli.php30
-rw-r--r--phpBB/common.php48
-rw-r--r--phpBB/composer.json55
-rw-r--r--phpBB/composer.lock1713
-rw-r--r--phpBB/config/auth.yml101
-rw-r--r--phpBB/config/avatar.yml68
-rw-r--r--phpBB/config/captcha.yml59
-rw-r--r--phpBB/config/console.yml141
-rw-r--r--phpBB/config/content.yml72
-rw-r--r--phpBB/config/cron.yml148
-rw-r--r--phpBB/config/db.yml78
-rw-r--r--phpBB/config/default/config.yml1
-rw-r--r--phpBB/config/default/container/parameters.yml (renamed from phpBB/config/parameters.yml)0
-rw-r--r--phpBB/config/default/container/services.yml169
-rw-r--r--phpBB/config/default/container/services_attachment.yml40
-rw-r--r--phpBB/config/default/container/services_auth.yml110
-rw-r--r--phpBB/config/default/container/services_avatar.yml72
-rw-r--r--phpBB/config/default/container/services_captcha.yml59
-rw-r--r--phpBB/config/default/container/services_console.yml271
-rw-r--r--phpBB/config/default/container/services_content.yml72
-rw-r--r--phpBB/config/default/container/services_cron.yml221
-rw-r--r--phpBB/config/default/container/services_db.yml73
-rw-r--r--phpBB/config/default/container/services_event.yml25
-rw-r--r--phpBB/config/default/container/services_feed.yml121
-rw-r--r--phpBB/config/default/container/services_files.yml57
-rw-r--r--phpBB/config/default/container/services_filesystem.yml3
-rw-r--r--phpBB/config/default/container/services_help.yml27
-rw-r--r--phpBB/config/default/container/services_hook.yml7
-rw-r--r--phpBB/config/default/container/services_http.yml23
-rw-r--r--phpBB/config/default/container/services_language.yml22
-rw-r--r--phpBB/config/default/container/services_migrator.yml64
-rw-r--r--phpBB/config/default/container/services_mimetype_guesser.yml36
-rw-r--r--phpBB/config/default/container/services_module.yml10
-rw-r--r--phpBB/config/default/container/services_notification.yml224
-rw-r--r--phpBB/config/default/container/services_password.yml124
-rw-r--r--phpBB/config/default/container/services_php.yml3
-rw-r--r--phpBB/config/default/container/services_profilefield.yml102
-rw-r--r--phpBB/config/default/container/services_report.yml53
-rw-r--r--phpBB/config/default/container/services_routing.yml79
-rw-r--r--phpBB/config/default/container/services_text_formatter.yml73
-rw-r--r--phpBB/config/default/container/services_text_reparser.yml91
-rw-r--r--phpBB/config/default/container/services_twig.yml67
-rw-r--r--phpBB/config/default/container/services_user.yml20
-rw-r--r--phpBB/config/default/container/tables.yml78
-rw-r--r--phpBB/config/default/routing/feed.yml35
-rw-r--r--phpBB/config/default/routing/help.yml7
-rw-r--r--phpBB/config/default/routing/report.yml17
-rw-r--r--phpBB/config/default/routing/routing.yml24
-rw-r--r--phpBB/config/development/config.yml13
-rw-r--r--phpBB/config/development/container/environment.yml3
-rw-r--r--phpBB/config/development/container/parameters.yml2
-rw-r--r--phpBB/config/development/container/services.yml2
-rw-r--r--phpBB/config/development/routing/environment.yml2
-rw-r--r--phpBB/config/event.yml41
-rw-r--r--phpBB/config/feed.yml113
-rw-r--r--phpBB/config/installer/config.yml2
-rw-r--r--phpBB/config/installer/container/environment.yml3
-rw-r--r--phpBB/config/installer/container/parameters.yml5
-rw-r--r--phpBB/config/installer/container/services.yml97
-rw-r--r--phpBB/config/installer/container/services_file_updater.yml38
-rw-r--r--phpBB/config/installer/container/services_install_console.yml61
-rw-r--r--phpBB/config/installer/container/services_install_controller.yml73
-rw-r--r--phpBB/config/installer/container/services_install_data.yml45
-rw-r--r--phpBB/config/installer/container/services_install_database.yml71
-rw-r--r--phpBB/config/installer/container/services_install_filesystem.yml28
-rw-r--r--phpBB/config/installer/container/services_install_finish.yml34
-rw-r--r--phpBB/config/installer/container/services_install_navigation.yml42
-rw-r--r--phpBB/config/installer/container/services_install_obtain_data.yml66
-rw-r--r--phpBB/config/installer/container/services_install_requirements.yml37
-rw-r--r--phpBB/config/installer/container/services_installer.yml119
-rw-r--r--phpBB/config/installer/container/services_update_database.yml29
-rw-r--r--phpBB/config/installer/container/services_update_filesystem.yml72
-rw-r--r--phpBB/config/installer/container/services_update_obtain_data.yml53
-rw-r--r--phpBB/config/installer/container/services_update_requirements.yml41
-rw-r--r--phpBB/config/installer/routing/environment.yml2
-rw-r--r--phpBB/config/installer/routing/installer.yml67
-rw-r--r--phpBB/config/mimetype_guesser.yml36
-rw-r--r--phpBB/config/notification.yml390
-rw-r--r--phpBB/config/password.yml124
-rw-r--r--phpBB/config/production/config.yml2
-rw-r--r--phpBB/config/production/container/environment.yml3
-rw-r--r--phpBB/config/production/container/parameters.yml2
-rw-r--r--phpBB/config/production/container/services.yml2
-rw-r--r--phpBB/config/production/routing/environment.yml2
-rw-r--r--phpBB/config/profilefield.yml102
-rw-r--r--phpBB/config/routing.yml9
-rw-r--r--phpBB/config/services.yml188
-rw-r--r--phpBB/config/tables.yml23
-rw-r--r--phpBB/config/test/config.yml5
-rw-r--r--phpBB/config/test/container/environment.yml3
-rw-r--r--phpBB/config/test/container/parameters.yml2
-rw-r--r--phpBB/config/test/container/services.yml2
-rw-r--r--phpBB/config/test/routing/environment.yml2
-rw-r--r--phpBB/config/user.yml19
-rw-r--r--phpBB/cron.php4
-rw-r--r--phpBB/develop/add_permissions.php9
-rw-r--r--phpBB/develop/benchmark.php2
-rw-r--r--phpBB/develop/check_flash_bbcodes.php8
-rw-r--r--phpBB/develop/create_schema_files.php10
-rw-r--r--phpBB/develop/create_search_index.php2
-rw-r--r--phpBB/develop/fill.php4
-rw-r--r--phpBB/develop/generate_utf_tables.php290
-rw-r--r--phpBB/develop/imageset_to_css.php2
-rw-r--r--phpBB/develop/lang_duplicates.php2
-rw-r--r--phpBB/develop/lang_migrate_help_lang.php307
-rw-r--r--phpBB/develop/mysql_upgrader.php9
-rw-r--r--phpBB/develop/unicode_testing.php37
-rw-r--r--phpBB/develop/update_email_hash.php2
-rw-r--r--phpBB/develop/utf_normalizer_test.php394
-rw-r--r--phpBB/docs/CHANGELOG.html418
-rw-r--r--phpBB/docs/FAQ.html10
-rw-r--r--phpBB/docs/INSTALL.html57
-rw-r--r--phpBB/docs/README.html35
-rw-r--r--phpBB/docs/coding-guidelines.html20
-rw-r--r--phpBB/docs/events.md257
-rw-r--r--phpBB/docs/install-config.sample.yml36
-rw-r--r--phpBB/docs/nginx.sample.conf25
-rw-r--r--phpBB/docs/update-config.sample.yml2
-rw-r--r--phpBB/docs/vagrant.md123
-rw-r--r--phpBB/download/file.php34
-rw-r--r--phpBB/faq.php95
-rw-r--r--phpBB/feed.php236
-rw-r--r--phpBB/includes/acp/acp_attachments.php137
-rw-r--r--phpBB/includes/acp/acp_ban.php3
-rw-r--r--phpBB/includes/acp/acp_bbcodes.php51
-rw-r--r--phpBB/includes/acp/acp_board.php74
-rw-r--r--phpBB/includes/acp/acp_bots.php26
-rw-r--r--phpBB/includes/acp/acp_captcha.php19
-rw-r--r--phpBB/includes/acp/acp_contact.php6
-rw-r--r--phpBB/includes/acp/acp_database.php1695
-rw-r--r--phpBB/includes/acp/acp_disallow.php11
-rw-r--r--phpBB/includes/acp/acp_email.php18
-rw-r--r--phpBB/includes/acp/acp_extensions.php16
-rw-r--r--phpBB/includes/acp/acp_forums.php232
-rw-r--r--phpBB/includes/acp/acp_groups.php90
-rw-r--r--phpBB/includes/acp/acp_icons.php68
-rw-r--r--phpBB/includes/acp/acp_inactive.php31
-rw-r--r--phpBB/includes/acp/acp_jabber.php37
-rw-r--r--phpBB/includes/acp/acp_language.php58
-rw-r--r--phpBB/includes/acp/acp_logs.php26
-rw-r--r--phpBB/includes/acp/acp_main.php57
-rw-r--r--phpBB/includes/acp/acp_modules.php643
-rw-r--r--phpBB/includes/acp/acp_permission_roles.php32
-rw-r--r--phpBB/includes/acp/acp_permissions.php81
-rw-r--r--phpBB/includes/acp/acp_php_info.php3
-rw-r--r--phpBB/includes/acp/acp_profile.php49
-rw-r--r--phpBB/includes/acp/acp_prune.php74
-rw-r--r--phpBB/includes/acp/acp_ranks.php24
-rw-r--r--phpBB/includes/acp/acp_reasons.php19
-rw-r--r--phpBB/includes/acp/acp_search.php48
-rw-r--r--phpBB/includes/acp/acp_send_statistics.php2
-rw-r--r--phpBB/includes/acp/acp_styles.php32
-rw-r--r--phpBB/includes/acp/acp_update.php5
-rw-r--r--phpBB/includes/acp/acp_users.php354
-rw-r--r--phpBB/includes/acp/acp_words.php22
-rw-r--r--phpBB/includes/acp/auth.php65
-rw-r--r--phpBB/includes/acp/info/acp_attachments.php1
-rw-r--r--phpBB/includes/acp/info/acp_ban.php1
-rw-r--r--phpBB/includes/acp/info/acp_bbcodes.php1
-rw-r--r--phpBB/includes/acp/info/acp_board.php1
-rw-r--r--phpBB/includes/acp/info/acp_bots.php1
-rw-r--r--phpBB/includes/acp/info/acp_captcha.php1
-rw-r--r--phpBB/includes/acp/info/acp_database.php1
-rw-r--r--phpBB/includes/acp/info/acp_disallow.php1
-rw-r--r--phpBB/includes/acp/info/acp_email.php1
-rw-r--r--phpBB/includes/acp/info/acp_extensions.php1
-rw-r--r--phpBB/includes/acp/info/acp_forums.php1
-rw-r--r--phpBB/includes/acp/info/acp_groups.php1
-rw-r--r--phpBB/includes/acp/info/acp_icons.php1
-rw-r--r--phpBB/includes/acp/info/acp_inactive.php1
-rw-r--r--phpBB/includes/acp/info/acp_jabber.php1
-rw-r--r--phpBB/includes/acp/info/acp_language.php1
-rw-r--r--phpBB/includes/acp/info/acp_logs.php1
-rw-r--r--phpBB/includes/acp/info/acp_main.php1
-rw-r--r--phpBB/includes/acp/info/acp_modules.php1
-rw-r--r--phpBB/includes/acp/info/acp_permission_roles.php1
-rw-r--r--phpBB/includes/acp/info/acp_permissions.php1
-rw-r--r--phpBB/includes/acp/info/acp_php_info.php1
-rw-r--r--phpBB/includes/acp/info/acp_profile.php1
-rw-r--r--phpBB/includes/acp/info/acp_prune.php1
-rw-r--r--phpBB/includes/acp/info/acp_ranks.php1
-rw-r--r--phpBB/includes/acp/info/acp_reasons.php1
-rw-r--r--phpBB/includes/acp/info/acp_search.php1
-rw-r--r--phpBB/includes/acp/info/acp_send_statistics.php1
-rw-r--r--phpBB/includes/acp/info/acp_styles.php1
-rw-r--r--phpBB/includes/acp/info/acp_update.php1
-rw-r--r--phpBB/includes/acp/info/acp_users.php1
-rw-r--r--phpBB/includes/acp/info/acp_words.php1
-rw-r--r--phpBB/includes/bbcode.php87
-rw-r--r--phpBB/includes/compatibility_globals.php76
-rw-r--r--phpBB/includes/constants.php29
-rw-r--r--phpBB/includes/functions.php1024
-rw-r--r--phpBB/includes/functions_acp.php49
-rw-r--r--phpBB/includes/functions_admin.php443
-rw-r--r--phpBB/includes/functions_compatibility.php325
-rw-r--r--phpBB/includes/functions_compress.php70
-rw-r--r--phpBB/includes/functions_content.php218
-rw-r--r--phpBB/includes/functions_convert.php79
-rw-r--r--phpBB/includes/functions_display.php123
-rw-r--r--phpBB/includes/functions_download.php102
-rw-r--r--phpBB/includes/functions_install.php545
-rw-r--r--phpBB/includes/functions_jabber.php3
-rw-r--r--phpBB/includes/functions_mcp.php64
-rw-r--r--phpBB/includes/functions_messenger.php90
-rw-r--r--phpBB/includes/functions_module.php18
-rw-r--r--phpBB/includes/functions_posting.php583
-rw-r--r--phpBB/includes/functions_privmsgs.php214
-rw-r--r--phpBB/includes/functions_transfer.php3
-rw-r--r--phpBB/includes/functions_upload.php1118
-rw-r--r--phpBB/includes/functions_url_matcher.php112
-rw-r--r--phpBB/includes/functions_user.php236
-rw-r--r--phpBB/includes/mcp/info/mcp_ban.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_logs.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_main.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_notes.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_pm_reports.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_queue.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_reports.php1
-rw-r--r--phpBB/includes/mcp/info/mcp_warn.php1
-rw-r--r--phpBB/includes/mcp/mcp_forum.php139
-rw-r--r--phpBB/includes/mcp/mcp_front.php6
-rw-r--r--phpBB/includes/mcp/mcp_logs.php33
-rw-r--r--phpBB/includes/mcp/mcp_main.php128
-rw-r--r--phpBB/includes/mcp/mcp_notes.php43
-rw-r--r--phpBB/includes/mcp/mcp_pm_reports.php14
-rw-r--r--phpBB/includes/mcp/mcp_post.php32
-rw-r--r--phpBB/includes/mcp/mcp_queue.php93
-rw-r--r--phpBB/includes/mcp/mcp_reports.php60
-rw-r--r--phpBB/includes/mcp/mcp_topic.php90
-rw-r--r--phpBB/includes/mcp/mcp_warn.php60
-rw-r--r--phpBB/includes/message_parser.php331
-rw-r--r--phpBB/includes/questionnaire/questionnaire.php5
-rw-r--r--phpBB/includes/sphinxapi.php1
-rw-r--r--phpBB/includes/startup.php43
-rw-r--r--phpBB/includes/ucp/info/ucp_attachments.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_auth_link.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_groups.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_main.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_notifications.php3
-rw-r--r--phpBB/includes/ucp/info/ucp_pm.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_prefs.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_profile.php1
-rw-r--r--phpBB/includes/ucp/info/ucp_zebra.php1
-rw-r--r--phpBB/includes/ucp/ucp_activate.php22
-rw-r--r--phpBB/includes/ucp/ucp_attachments.php22
-rw-r--r--phpBB/includes/ucp/ucp_auth_link.php1
-rw-r--r--phpBB/includes/ucp/ucp_confirm.php4
-rw-r--r--phpBB/includes/ucp/ucp_groups.php86
-rw-r--r--phpBB/includes/ucp/ucp_login_link.php5
-rw-r--r--phpBB/includes/ucp/ucp_main.php19
-rw-r--r--phpBB/includes/ucp/ucp_notifications.php20
-rw-r--r--phpBB/includes/ucp/ucp_pm.php27
-rw-r--r--phpBB/includes/ucp/ucp_pm_compose.php116
-rw-r--r--phpBB/includes/ucp/ucp_pm_options.php71
-rw-r--r--phpBB/includes/ucp/ucp_pm_viewfolder.php22
-rw-r--r--phpBB/includes/ucp/ucp_pm_viewmessage.php13
-rw-r--r--phpBB/includes/ucp/ucp_prefs.php58
-rw-r--r--phpBB/includes/ucp/ucp_profile.php229
-rw-r--r--phpBB/includes/ucp/ucp_register.php29
-rw-r--r--phpBB/includes/ucp/ucp_remind.php10
-rw-r--r--phpBB/includes/ucp/ucp_resend.php6
-rw-r--r--phpBB/includes/ucp/ucp_zebra.php4
-rw-r--r--phpBB/includes/utf/data/utf_canonical_comp.php2
-rw-r--r--phpBB/includes/utf/data/utf_canonical_decomp.php2
-rw-r--r--phpBB/includes/utf/data/utf_compatibility_decomp.php2
-rw-r--r--phpBB/includes/utf/data/utf_nfc_qc.php2
-rw-r--r--phpBB/includes/utf/data/utf_nfkc_qc.php2
-rw-r--r--phpBB/includes/utf/data/utf_normalizer_common.php4
-rw-r--r--phpBB/includes/utf/utf_normalizer.php1509
-rw-r--r--phpBB/includes/utf/utf_tools.php750
-rw-r--r--phpBB/index.php8
-rw-r--r--phpBB/install/app.php58
-rw-r--r--phpBB/install/convert/controller/convertor.php865
-rw-r--r--phpBB/install/convert/convert.php60
-rw-r--r--phpBB/install/convert/convertor.php1614
-rw-r--r--phpBB/install/convertors/convert_phpbb20.php7
-rw-r--r--phpBB/install/convertors/functions_phpbb20.php84
-rw-r--r--phpBB/install/data/confusables.php9
-rw-r--r--phpBB/install/data/new_normalizer.php197
-rw-r--r--phpBB/install/database_update.php244
-rw-r--r--phpBB/install/index.html11
-rw-r--r--phpBB/install/index.php834
-rw-r--r--phpBB/install/install_convert.php2150
-rw-r--r--phpBB/install/install_install.php2331
-rw-r--r--phpBB/install/install_main.php78
-rw-r--r--phpBB/install/install_update.php1782
-rwxr-xr-xphpBB/install/phpbbcli.php52
-rw-r--r--phpBB/install/phpinfo.php14
-rw-r--r--phpBB/install/schemas/schema_data.sql50
-rw-r--r--phpBB/install/startup.php143
-rw-r--r--phpBB/language/en/acp/attachments.php6
-rw-r--r--phpBB/language/en/acp/board.php6
-rw-r--r--phpBB/language/en/acp/common.php22
-rw-r--r--phpBB/language/en/acp/groups.php6
-rw-r--r--phpBB/language/en/acp/permissions_phpbb.php1
-rw-r--r--phpBB/language/en/captcha_recaptcha.php6
-rw-r--r--phpBB/language/en/cli.php70
-rw-r--r--phpBB/language/en/common.php13
-rw-r--r--phpBB/language/en/email/test.txt9
-rw-r--r--phpBB/language/en/help/bbcode.php66
-rw-r--r--phpBB/language/en/help/faq.php186
-rw-r--r--phpBB/language/en/help_bbcode.php115
-rw-r--r--phpBB/language/en/help_faq.php355
-rw-r--r--phpBB/language/en/install.php974
-rw-r--r--phpBB/language/en/mcp.php1
-rw-r--r--phpBB/language/en/migrator.php8
-rw-r--r--phpBB/language/en/posting.php2
-rw-r--r--phpBB/language/en/ucp.php1
-rw-r--r--phpBB/mcp.php32
-rw-r--r--phpBB/memberlist.php91
-rw-r--r--phpBB/phpbb/attachment/delete.php432
-rw-r--r--phpBB/phpbb/attachment/manager.php99
-rw-r--r--phpBB/phpbb/attachment/resync.php124
-rw-r--r--phpBB/phpbb/attachment/upload.php334
-rw-r--r--phpBB/phpbb/auth/auth.php1
-rw-r--r--phpBB/phpbb/auth/provider/db.php1
-rw-r--r--phpBB/phpbb/auth/provider/oauth/oauth.php47
-rw-r--r--phpBB/phpbb/auth/provider/oauth/service/twitter.php102
-rw-r--r--phpBB/phpbb/auth/provider/oauth/token_storage.php254
-rw-r--r--phpBB/phpbb/avatar/driver/driver.php7
-rw-r--r--phpBB/phpbb/avatar/driver/gravatar.php12
-rw-r--r--phpBB/phpbb/avatar/driver/local.php8
-rw-r--r--phpBB/phpbb/avatar/driver/remote.php40
-rw-r--r--phpBB/phpbb/avatar/driver/upload.php44
-rw-r--r--phpBB/phpbb/cache/driver/base.php16
-rw-r--r--phpBB/phpbb/cache/driver/dummy.php153
-rw-r--r--phpBB/phpbb/cache/driver/eaccelerator.php4
-rw-r--r--phpBB/phpbb/cache/driver/file.php45
-rw-r--r--phpBB/phpbb/cache/driver/memory.php16
-rw-r--r--phpBB/phpbb/cache/driver/null.php151
-rw-r--r--phpBB/phpbb/cache/service.php2
-rw-r--r--phpBB/phpbb/captcha/gd.php5
-rw-r--r--phpBB/phpbb/captcha/gd_wave.php5
-rw-r--r--phpBB/phpbb/captcha/plugins/captcha_abstract.php24
-rw-r--r--phpBB/phpbb/captcha/plugins/gd.php25
-rw-r--r--phpBB/phpbb/captcha/plugins/gd_wave.php2
-rw-r--r--phpBB/phpbb/captcha/plugins/qa.php44
-rw-r--r--phpBB/phpbb/captcha/plugins/recaptcha.php137
-rw-r--r--phpBB/phpbb/composer.json4
-rw-r--r--phpBB/phpbb/console/application.php71
-rw-r--r--phpBB/phpbb/console/command/command.php45
-rw-r--r--phpBB/phpbb/console/command/cron/run.php7
-rw-r--r--phpBB/phpbb/console/command/db/console_migrator_output_handler.php2
-rw-r--r--phpBB/phpbb/console/command/db/list_command.php73
-rw-r--r--phpBB/phpbb/console/command/db/migrate.php50
-rw-r--r--phpBB/phpbb/console/command/db/migration_command.php56
-rw-r--r--phpBB/phpbb/console/command/db/revert.php88
-rw-r--r--phpBB/phpbb/console/command/reparser/list_all.php69
-rw-r--r--phpBB/phpbb/console/command/reparser/reparse.php246
-rw-r--r--phpBB/phpbb/console/command/thumbnail/delete.php153
-rw-r--r--phpBB/phpbb/console/command/thumbnail/generate.php179
-rw-r--r--phpBB/phpbb/console/command/thumbnail/recreate.php72
-rw-r--r--phpBB/phpbb/console/command/user/activate.php218
-rw-r--r--phpBB/phpbb/console/command/user/add.php334
-rw-r--r--phpBB/phpbb/console/command/user/delete.php170
-rw-r--r--phpBB/phpbb/console/command/user/reclean.php158
-rw-r--r--phpBB/phpbb/console/exception_subscriber.php74
-rw-r--r--phpBB/phpbb/controller/exception.php2
-rw-r--r--phpBB/phpbb/controller/helper.php128
-rw-r--r--phpBB/phpbb/controller/provider.php92
-rw-r--r--phpBB/phpbb/controller/resolver.php36
-rw-r--r--phpBB/phpbb/cron/task/core/prune_forum.php2
-rw-r--r--phpBB/phpbb/cron/task/core/prune_shadow_topics.php2
-rw-r--r--phpBB/phpbb/cron/task/core/queue.php19
-rw-r--r--phpBB/phpbb/cron/task/core/tidy_plupload.php18
-rw-r--r--phpBB/phpbb/cron/task/text_reparser/reparser.php168
-rw-r--r--phpBB/phpbb/db/driver/driver.php164
-rw-r--r--phpBB/phpbb/db/driver/mssql.php476
-rw-r--r--phpBB/phpbb/db/driver/mssql_odbc.php32
-rw-r--r--phpBB/phpbb/db/driver/mssqlnative.php34
-rw-r--r--phpBB/phpbb/db/driver/mysql.php56
-rw-r--r--phpBB/phpbb/db/driver/mysqli.php49
-rw-r--r--phpBB/phpbb/db/driver/oracle.php61
-rw-r--r--phpBB/phpbb/db/driver/postgres.php45
-rw-r--r--phpBB/phpbb/db/driver/sqlite.php378
-rw-r--r--phpBB/phpbb/db/driver/sqlite3.php36
-rw-r--r--phpBB/phpbb/db/extractor/base_extractor.php252
-rw-r--r--phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php24
-rw-r--r--phpBB/phpbb/db/extractor/exception/invalid_format_exception.php22
-rw-r--r--phpBB/phpbb/db/extractor/extractor_interface.php80
-rw-r--r--phpBB/phpbb/db/extractor/factory.php75
-rw-r--r--phpBB/phpbb/db/extractor/mssql_extractor.php415
-rw-r--r--phpBB/phpbb/db/extractor/mysql_extractor.php403
-rw-r--r--phpBB/phpbb/db/extractor/oracle_extractor.php263
-rw-r--r--phpBB/phpbb/db/extractor/postgres_extractor.php339
-rw-r--r--phpBB/phpbb/db/extractor/sqlite3_extractor.php151
-rw-r--r--phpBB/phpbb/db/html_migrator_output_handler.php48
-rw-r--r--phpBB/phpbb/db/log_wrapper_migrator_output_handler.php95
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php11
-rw-r--r--phpBB/phpbb/db/migration/data/v310/dev.php11
-rw-r--r--phpBB/phpbb/db/migration/data/v310/timezone.php2
-rw-r--r--phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php1
-rw-r--r--phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php31
-rw-r--r--phpBB/phpbb/db/migration/data/v320/announce_global_permission.php43
-rw-r--r--phpBB/phpbb/db/migration/data/v320/default_data_type_ids.php361
-rw-r--r--phpBB/phpbb/db/migration/data/v320/dev.php36
-rw-r--r--phpBB/phpbb/db/migration/data/v320/font_awesome_update.php36
-rw-r--r--phpBB/phpbb/db/migration/data/v320/icons_alt.php46
-rw-r--r--phpBB/phpbb/db/migration/data/v320/log_post_id.php46
-rw-r--r--phpBB/phpbb/db/migration/data/v320/notifications_board.php75
-rw-r--r--phpBB/phpbb/db/migration/data/v320/oauth_states.php56
-rw-r--r--phpBB/phpbb/db/migration/data/v320/remote_upload_validation.php31
-rw-r--r--phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php90
-rw-r--r--phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php152
-rw-r--r--phpBB/phpbb/db/migration/data/v320/report_id_auto_increment.php46
-rw-r--r--phpBB/phpbb/db/migration/data/v320/text_reparser.php118
-rw-r--r--phpBB/phpbb/db/migration/data/v320/v320a1.php44
-rw-r--r--phpBB/phpbb/db/migration/data/v320/v320a2.php38
-rw-r--r--phpBB/phpbb/db/migration/data/v320/v320b1.php39
-rw-r--r--phpBB/phpbb/db/migration/data/v320/v320b2.php40
-rw-r--r--phpBB/phpbb/db/migration/data/v320/v320rc1.php40
-rw-r--r--phpBB/phpbb/db/migration/migration.php40
-rw-r--r--phpBB/phpbb/db/migration/migration_interface.php70
-rw-r--r--phpBB/phpbb/db/migration/profilefield_base_migration.php1
-rw-r--r--phpBB/phpbb/db/migration/schema_generator.php13
-rw-r--r--phpBB/phpbb/db/migration/tool/module.php59
-rw-r--r--phpBB/phpbb/db/migrator.php116
-rw-r--r--phpBB/phpbb/db/migrator_output_handler_interface.php31
-rw-r--r--phpBB/phpbb/db/null_migrator_output_handler.php24
-rw-r--r--phpBB/phpbb/db/output_handler/html_migrator_output_handler.php46
-rw-r--r--phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php46
-rw-r--r--phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php101
-rw-r--r--phpBB/phpbb/db/output_handler/migrator_output_handler_interface.php31
-rw-r--r--phpBB/phpbb/db/output_handler/null_migrator_output_handler.php24
-rw-r--r--phpBB/phpbb/db/tools.php2840
-rw-r--r--phpBB/phpbb/db/tools/factory.php43
-rw-r--r--phpBB/phpbb/db/tools/mssql.php794
-rw-r--r--phpBB/phpbb/db/tools/postgres.php614
-rw-r--r--phpBB/phpbb/db/tools/tools.php1918
-rw-r--r--phpBB/phpbb/db/tools/tools_interface.php202
-rw-r--r--phpBB/phpbb/debug/debug.php80
-rw-r--r--phpBB/phpbb/debug/error_handler.php31
-rw-r--r--phpBB/phpbb/di/container_builder.php705
-rw-r--r--phpBB/phpbb/di/extension/container_configuration.php52
-rw-r--r--phpBB/phpbb/di/extension/core.php107
-rw-r--r--phpBB/phpbb/di/extension/ext.php67
-rw-r--r--phpBB/phpbb/di/ordered_service_collection.php117
-rw-r--r--phpBB/phpbb/di/pass/collection_pass.php22
-rw-r--r--phpBB/phpbb/di/service_collection.php27
-rw-r--r--phpBB/phpbb/di/service_collection_iterator.php2
-rw-r--r--phpBB/phpbb/event/kernel_exception_subscriber.php24
-rw-r--r--phpBB/phpbb/event/kernel_request_subscriber.php82
-rw-r--r--phpBB/phpbb/event/kernel_terminate_subscriber.php2
-rw-r--r--phpBB/phpbb/event/md_exporter.php11
-rw-r--r--phpBB/phpbb/extension/base.php12
-rw-r--r--phpBB/phpbb/extension/di/extension_base.php138
-rw-r--r--phpBB/phpbb/extension/exception.php6
-rw-r--r--phpBB/phpbb/extension/manager.php26
-rw-r--r--phpBB/phpbb/extension/metadata_manager.php26
-rw-r--r--phpBB/phpbb/feed/attachments_base.php2
-rw-r--r--phpBB/phpbb/feed/base.php249
-rw-r--r--phpBB/phpbb/feed/controller/feed.php411
-rw-r--r--phpBB/phpbb/feed/exception/feed_exception.php21
-rw-r--r--phpBB/phpbb/feed/exception/feed_unavailable_exception.php19
-rw-r--r--phpBB/phpbb/feed/exception/no_feed_exception.php22
-rw-r--r--phpBB/phpbb/feed/exception/no_forum_exception.php22
-rw-r--r--phpBB/phpbb/feed/exception/no_topic_exception.php22
-rw-r--r--phpBB/phpbb/feed/exception/unauthorized_exception.php19
-rw-r--r--phpBB/phpbb/feed/exception/unauthorized_forum_exception.php22
-rw-r--r--phpBB/phpbb/feed/exception/unauthorized_topic_exception.php22
-rw-r--r--phpBB/phpbb/feed/factory.php127
-rw-r--r--phpBB/phpbb/feed/feed_interface.php67
-rw-r--r--phpBB/phpbb/feed/forum.php98
-rw-r--r--phpBB/phpbb/feed/forums.php49
-rw-r--r--phpBB/phpbb/feed/helper.php78
-rw-r--r--phpBB/phpbb/feed/news.php43
-rw-r--r--phpBB/phpbb/feed/overall.php46
-rw-r--r--phpBB/phpbb/feed/post_base.php39
-rw-r--r--phpBB/phpbb/feed/topic.php107
-rw-r--r--phpBB/phpbb/feed/topic_base.php38
-rw-r--r--phpBB/phpbb/feed/topics.php42
-rw-r--r--phpBB/phpbb/feed/topics_active.php58
-rw-r--r--phpBB/phpbb/files/factory.php58
-rw-r--r--phpBB/phpbb/files/filespec.php584
-rw-r--r--phpBB/phpbb/files/types/base.php65
-rw-r--r--phpBB/phpbb/files/types/form.php138
-rw-r--r--phpBB/phpbb/files/types/local.php136
-rw-r--r--phpBB/phpbb/files/types/remote.php207
-rw-r--r--phpBB/phpbb/files/types/type_interface.php38
-rw-r--r--phpBB/phpbb/files/upload.php390
-rw-r--r--phpBB/phpbb/filesystem.php35
-rw-r--r--phpBB/phpbb/filesystem/exception/filesystem_exception.php42
-rw-r--r--phpBB/phpbb/filesystem/filesystem.php916
-rw-r--r--phpBB/phpbb/filesystem/filesystem_interface.php284
-rw-r--r--phpBB/phpbb/finder.php4
-rw-r--r--phpBB/phpbb/group/helper.php40
-rw-r--r--phpBB/phpbb/help/controller/bbcode.php85
-rw-r--r--phpBB/phpbb/help/controller/controller.php76
-rw-r--r--phpBB/phpbb/help/controller/faq.php165
-rw-r--r--phpBB/phpbb/help/controller/help.php160
-rw-r--r--phpBB/phpbb/help/manager.php137
-rw-r--r--phpBB/phpbb/hook/finder.php13
-rw-r--r--phpBB/phpbb/install/console/command/install/config/show.php123
-rw-r--r--phpBB/phpbb/install/console/command/install/config/validate.php124
-rw-r--r--phpBB/phpbb/install/console/command/install/install.php207
-rw-r--r--phpBB/phpbb/install/console/command/update/config/show.php123
-rw-r--r--phpBB/phpbb/install/console/command/update/config/validate.php124
-rw-r--r--phpBB/phpbb/install/console/command/update/update.php179
-rw-r--r--phpBB/phpbb/install/controller/archive_download.php93
-rw-r--r--phpBB/phpbb/install/controller/helper.php413
-rw-r--r--phpBB/phpbb/install/controller/install.php172
-rw-r--r--phpBB/phpbb/install/controller/installer_index.php81
-rw-r--r--phpBB/phpbb/install/controller/timeout_check.php80
-rw-r--r--phpBB/phpbb/install/controller/update.php166
-rw-r--r--phpBB/phpbb/install/event/kernel_exception_subscriber.php126
-rw-r--r--phpBB/phpbb/install/exception/cannot_build_container_exception.php22
-rw-r--r--phpBB/phpbb/install/exception/file_updater_failure_exception.php22
-rw-r--r--phpBB/phpbb/install/exception/installer_config_not_writable_exception.php22
-rw-r--r--phpBB/phpbb/install/exception/installer_exception.php24
-rw-r--r--phpBB/phpbb/install/exception/invalid_dbms_exception.php22
-rw-r--r--phpBB/phpbb/install/exception/jump_to_restart_point_exception.php44
-rw-r--r--phpBB/phpbb/install/exception/resource_limit_reached_exception.php22
-rw-r--r--phpBB/phpbb/install/exception/user_interaction_required_exception.php25
-rw-r--r--phpBB/phpbb/install/helper/config.php450
-rw-r--r--phpBB/phpbb/install/helper/container_factory.php191
-rw-r--r--phpBB/phpbb/install/helper/database.php430
-rw-r--r--phpBB/phpbb/install/helper/file_updater/compression_file_updater.php133
-rw-r--r--phpBB/phpbb/install/helper/file_updater/factory.php69
-rw-r--r--phpBB/phpbb/install/helper/file_updater/file_updater.php202
-rw-r--r--phpBB/phpbb/install/helper/file_updater/file_updater_interface.php49
-rw-r--r--phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php136
-rw-r--r--phpBB/phpbb/install/helper/install_helper.php60
-rw-r--r--phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php489
-rw-r--r--phpBB/phpbb/install/helper/iohandler/cli_iohandler.php309
-rw-r--r--phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php19
-rw-r--r--phpBB/phpbb/install/helper/iohandler/factory.php79
-rw-r--r--phpBB/phpbb/install/helper/iohandler/iohandler_base.php204
-rw-r--r--phpBB/phpbb/install/helper/iohandler/iohandler_interface.php211
-rw-r--r--phpBB/phpbb/install/helper/navigation/convertor_navigation.php78
-rw-r--r--phpBB/phpbb/install/helper/navigation/install_navigation.php75
-rw-r--r--phpBB/phpbb/install/helper/navigation/main_navigation.php48
-rw-r--r--phpBB/phpbb/install/helper/navigation/navigation_interface.php43
-rw-r--r--phpBB/phpbb/install/helper/navigation/navigation_provider.php121
-rw-r--r--phpBB/phpbb/install/helper/navigation/update_navigation.php80
-rw-r--r--phpBB/phpbb/install/helper/update_helper.php113
-rw-r--r--phpBB/phpbb/install/installer.php337
-rw-r--r--phpBB/phpbb/install/installer_configuration.php143
-rw-r--r--phpBB/phpbb/install/module/install_data/module.php28
-rw-r--r--phpBB/phpbb/install/module/install_data/task/add_bots.php263
-rw-r--r--phpBB/phpbb/install/module/install_data/task/add_languages.php121
-rw-r--r--phpBB/phpbb/install/module/install_data/task/add_modules.php568
-rw-r--r--phpBB/phpbb/install/module/install_database/module.php28
-rw-r--r--phpBB/phpbb/install/module/install_database/task/add_config_settings.php372
-rw-r--r--phpBB/phpbb/install/module/install_database/task/add_default_data.php184
-rw-r--r--phpBB/phpbb/install/module/install_database/task/add_tables.php151
-rw-r--r--phpBB/phpbb/install/module/install_database/task/create_schema.php234
-rw-r--r--phpBB/phpbb/install/module/install_database/task/create_schema_file.php164
-rw-r--r--phpBB/phpbb/install/module/install_database/task/set_up_database.php164
-rw-r--r--phpBB/phpbb/install/module/install_filesystem/module.php28
-rw-r--r--phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php244
-rw-r--r--phpBB/phpbb/install/module/install_finish/module.php28
-rw-r--r--phpBB/phpbb/install/module/install_finish/task/notify_user.php174
-rw-r--r--phpBB/phpbb/install/module/install_finish/task/populate_migrations.php92
-rw-r--r--phpBB/phpbb/install/module/obtain_data/install_module.php33
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php218
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php185
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php270
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php173
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php167
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php89
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php202
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php113
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php163
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php123
-rw-r--r--phpBB/phpbb/install/module/obtain_data/update_module.php33
-rw-r--r--phpBB/phpbb/install/module/requirements/abstract_requirements_module.php71
-rw-r--r--phpBB/phpbb/install/module/requirements/install_module.php25
-rw-r--r--phpBB/phpbb/install/module/requirements/task/check_filesystem.php279
-rw-r--r--phpBB/phpbb/install/module/requirements/task/check_server_environment.php209
-rw-r--r--phpBB/phpbb/install/module/requirements/task/check_update.php195
-rw-r--r--phpBB/phpbb/install/module/requirements/update_module.php25
-rw-r--r--phpBB/phpbb/install/module/update_database/module.php33
-rw-r--r--phpBB/phpbb/install/module/update_database/task/update.php236
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/module.php33
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/diff_files.php205
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php123
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/file_check.php187
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php170
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/update_files.php294
-rw-r--r--phpBB/phpbb/install/module_base.php213
-rw-r--r--phpBB/phpbb/install/module_interface.php63
-rw-r--r--phpBB/phpbb/install/task_base.php53
-rw-r--r--phpBB/phpbb/install/task_interface.php61
-rw-r--r--phpBB/phpbb/install/updater_configuration.php40
-rw-r--r--phpBB/phpbb/language/exception/invalid_plural_rule_exception.php22
-rw-r--r--phpBB/phpbb/language/exception/language_exception.php22
-rw-r--r--phpBB/phpbb/language/exception/language_file_not_found.php22
-rw-r--r--phpBB/phpbb/language/language.php673
-rw-r--r--phpBB/phpbb/language/language_file_helper.php72
-rw-r--r--phpBB/phpbb/language/language_file_loader.php206
-rw-r--r--phpBB/phpbb/log/dummy.php81
-rw-r--r--phpBB/phpbb/log/log.php9
-rw-r--r--phpBB/phpbb/log/log_interface.php16
-rw-r--r--phpBB/phpbb/log/null.php81
-rw-r--r--phpBB/phpbb/message/topic_form.php8
-rw-r--r--phpBB/phpbb/module/exception/module_exception.php19
-rw-r--r--phpBB/phpbb/module/exception/module_not_found_exception.php19
-rw-r--r--phpBB/phpbb/module/module_manager.php564
-rw-r--r--phpBB/phpbb/notification/exception.php6
-rw-r--r--phpBB/phpbb/notification/manager.php579
-rw-r--r--phpBB/phpbb/notification/method/base.php130
-rw-r--r--phpBB/phpbb/notification/method/board.php399
-rw-r--r--phpBB/phpbb/notification/method/email.php23
-rw-r--r--phpBB/phpbb/notification/method/jabber.php25
-rw-r--r--phpBB/phpbb/notification/method/messenger_base.php25
-rw-r--r--phpBB/phpbb/notification/method/method_interface.php104
-rw-r--r--phpBB/phpbb/notification/type/admin_activate_user.php26
-rw-r--r--phpBB/phpbb/notification/type/approve_post.php25
-rw-r--r--phpBB/phpbb/notification/type/approve_topic.php26
-rw-r--r--phpBB/phpbb/notification/type/base.php170
-rw-r--r--phpBB/phpbb/notification/type/bookmark.php34
-rw-r--r--phpBB/phpbb/notification/type/disapprove_post.php29
-rw-r--r--phpBB/phpbb/notification/type/disapprove_topic.php29
-rw-r--r--phpBB/phpbb/notification/type/group_request.php18
-rw-r--r--phpBB/phpbb/notification/type/group_request_approved.php10
-rw-r--r--phpBB/phpbb/notification/type/pm.php36
-rw-r--r--phpBB/phpbb/notification/type/post.php75
-rw-r--r--phpBB/phpbb/notification/type/post_in_queue.php23
-rw-r--r--phpBB/phpbb/notification/type/quote.php60
-rw-r--r--phpBB/phpbb/notification/type/report_pm.php39
-rw-r--r--phpBB/phpbb/notification/type/report_pm_closed.php27
-rw-r--r--phpBB/phpbb/notification/type/report_post.php28
-rw-r--r--phpBB/phpbb/notification/type/report_post_closed.php27
-rw-r--r--phpBB/phpbb/notification/type/topic.php40
-rw-r--r--phpBB/phpbb/notification/type/topic_in_queue.php23
-rw-r--r--phpBB/phpbb/notification/type/type_interface.php16
-rw-r--r--phpBB/phpbb/passwords/manager.php48
-rw-r--r--phpBB/phpbb/path_helper.php15
-rw-r--r--phpBB/phpbb/permissions.php1
-rw-r--r--phpBB/phpbb/plupload/plupload.php14
-rw-r--r--phpBB/phpbb/profilefields/type/type_date.php2
-rw-r--r--phpBB/phpbb/report/controller/report.php319
-rw-r--r--phpBB/phpbb/report/exception/already_reported_exception.php19
-rw-r--r--phpBB/phpbb/report/exception/empty_report_exception.php22
-rw-r--r--phpBB/phpbb/report/exception/entity_not_found_exception.php19
-rw-r--r--phpBB/phpbb/report/exception/factory_invalid_argument_exception.php21
-rw-r--r--phpBB/phpbb/report/exception/invalid_report_exception.php21
-rw-r--r--phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php22
-rw-r--r--phpBB/phpbb/report/exception/report_permission_denied_exception.php19
-rw-r--r--phpBB/phpbb/report/handler_factory.php56
-rw-r--r--phpBB/phpbb/report/report_handler.php104
-rw-r--r--phpBB/phpbb/report/report_handler_interface.php43
-rw-r--r--phpBB/phpbb/report/report_handler_pm.php137
-rw-r--r--phpBB/phpbb/report/report_handler_post.php175
-rw-r--r--phpBB/phpbb/report/report_reason_list_provider.php78
-rw-r--r--phpBB/phpbb/request/deactivated_super_global.php2
-rw-r--r--phpBB/phpbb/request/type_cast_helper.php1
-rw-r--r--phpBB/phpbb/routing/file_locator.php33
-rw-r--r--phpBB/phpbb/routing/helper.php162
-rw-r--r--phpBB/phpbb/routing/loader_resolver.php50
-rw-r--r--phpBB/phpbb/routing/resources_locator/chained_resources_locator.php47
-rw-r--r--phpBB/phpbb/routing/resources_locator/default_resources_locator.php105
-rw-r--r--phpBB/phpbb/routing/resources_locator/installer_resources_locator.php78
-rw-r--r--phpBB/phpbb/routing/resources_locator/resources_locator_interface.php27
-rw-r--r--phpBB/phpbb/routing/router.php395
-rw-r--r--phpBB/phpbb/search/base.php2
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php6
-rw-r--r--phpBB/phpbb/search/fulltext_native.php53
-rw-r--r--phpBB/phpbb/search/fulltext_postgres.php6
-rw-r--r--phpBB/phpbb/search/fulltext_sphinx.php24
-rw-r--r--phpBB/phpbb/session.php57
-rw-r--r--phpBB/phpbb/template/asset.php15
-rw-r--r--phpBB/phpbb/template/assets_bag.php95
-rw-r--r--phpBB/phpbb/template/exception/user_object_not_available.php22
-rw-r--r--phpBB/phpbb/template/twig/environment.php104
-rw-r--r--phpBB/phpbb/template/twig/extension.php15
-rw-r--r--phpBB/phpbb/template/twig/extension/routing.php43
-rw-r--r--phpBB/phpbb/template/twig/lexer.php18
-rw-r--r--phpBB/phpbb/template/twig/loader.php32
-rw-r--r--phpBB/phpbb/template/twig/node/event.php6
-rw-r--r--phpBB/phpbb/template/twig/node/includeasset.php27
-rw-r--r--phpBB/phpbb/template/twig/node/includecss.php16
-rw-r--r--phpBB/phpbb/template/twig/node/includejs.php18
-rw-r--r--phpBB/phpbb/template/twig/twig.php63
-rw-r--r--phpBB/phpbb/textformatter/cache_interface.php31
-rw-r--r--phpBB/phpbb/textformatter/data_access.php228
-rw-r--r--phpBB/phpbb/textformatter/parser_interface.php112
-rw-r--r--phpBB/phpbb/textformatter/renderer_interface.php92
-rw-r--r--phpBB/phpbb/textformatter/s9e/factory.php618
-rw-r--r--phpBB/phpbb/textformatter/s9e/link_helper.php118
-rw-r--r--phpBB/phpbb/textformatter/s9e/parser.php397
-rw-r--r--phpBB/phpbb/textformatter/s9e/quote_helper.php81
-rw-r--r--phpBB/phpbb/textformatter/s9e/renderer.php315
-rw-r--r--phpBB/phpbb/textformatter/s9e/utils.php139
-rw-r--r--phpBB/phpbb/textformatter/utils_interface.php71
-rw-r--r--phpBB/phpbb/textreparser/base.php244
-rw-r--r--phpBB/phpbb/textreparser/manager.php128
-rw-r--r--phpBB/phpbb/textreparser/plugins/contact_admin_info.php69
-rw-r--r--phpBB/phpbb/textreparser/plugins/forum_description.php30
-rw-r--r--phpBB/phpbb/textreparser/plugins/forum_rules.php30
-rw-r--r--phpBB/phpbb/textreparser/plugins/group_description.php30
-rw-r--r--phpBB/phpbb/textreparser/plugins/pm_text.php32
-rw-r--r--phpBB/phpbb/textreparser/plugins/poll_option.php74
-rw-r--r--phpBB/phpbb/textreparser/plugins/poll_title.php42
-rw-r--r--phpBB/phpbb/textreparser/plugins/post_text.php32
-rw-r--r--phpBB/phpbb/textreparser/plugins/user_signature.php65
-rw-r--r--phpBB/phpbb/textreparser/reparser_interface.php32
-rw-r--r--phpBB/phpbb/textreparser/row_based_plugin.php117
-rw-r--r--phpBB/phpbb/tree/nestedset.php2
-rw-r--r--phpBB/phpbb/user.php340
-rw-r--r--phpBB/phpbb/user_loader.php11
-rw-r--r--phpBB/phpbb/viewonline_helper.php6
-rw-r--r--phpBB/posting.php111
-rw-r--r--phpBB/report.php323
-rw-r--r--phpBB/search.php56
-rw-r--r--phpBB/styles/all/template/feed.xml.twig37
-rw-r--r--phpBB/styles/prosilver/style.cfg4
-rw-r--r--phpBB/styles/prosilver/template/ajax.js2
-rw-r--r--phpBB/styles/prosilver/template/attachment.html79
-rw-r--r--phpBB/styles/prosilver/template/bbcode.html39
-rw-r--r--phpBB/styles/prosilver/template/captcha_recaptcha.html19
-rw-r--r--phpBB/styles/prosilver/template/confirm_delete_body.html2
-rw-r--r--phpBB/styles/prosilver/template/display_options.html27
-rw-r--r--phpBB/styles/prosilver/template/faq_body.html4
-rw-r--r--phpBB/styles/prosilver/template/forum_fn.js24
-rw-r--r--phpBB/styles/prosilver/template/forumlist_body.html61
-rw-r--r--phpBB/styles/prosilver/template/jumpbox.html35
-rw-r--r--phpBB/styles/prosilver/template/mcp_approve.html4
-rw-r--r--phpBB/styles/prosilver/template/mcp_ban.html6
-rw-r--r--phpBB/styles/prosilver/template/mcp_forum.html50
-rw-r--r--phpBB/styles/prosilver/template/mcp_front.html8
-rw-r--r--phpBB/styles/prosilver/template/mcp_header.html10
-rw-r--r--phpBB/styles/prosilver/template/mcp_logs.html21
-rw-r--r--phpBB/styles/prosilver/template/mcp_notes_front.html2
-rw-r--r--phpBB/styles/prosilver/template/mcp_notes_user.html22
-rw-r--r--phpBB/styles/prosilver/template/mcp_post.html12
-rw-r--r--phpBB/styles/prosilver/template/mcp_queue.html24
-rw-r--r--phpBB/styles/prosilver/template/mcp_reports.html26
-rw-r--r--phpBB/styles/prosilver/template/mcp_topic.html22
-rw-r--r--phpBB/styles/prosilver/template/mcp_warn_front.html2
-rw-r--r--phpBB/styles/prosilver/template/mcp_warn_list.html20
-rw-r--r--phpBB/styles/prosilver/template/mcp_warn_post.html2
-rw-r--r--phpBB/styles/prosilver/template/mcp_warn_user.html2
-rw-r--r--phpBB/styles/prosilver/template/mcp_whois.html14
-rw-r--r--phpBB/styles/prosilver/template/memberlist_body.html18
-rw-r--r--phpBB/styles/prosilver/template/memberlist_team.html2
-rw-r--r--phpBB/styles/prosilver/template/message_body.html8
-rw-r--r--phpBB/styles/prosilver/template/navbar_footer.html60
-rw-r--r--phpBB/styles/prosilver/template/navbar_header.html161
-rw-r--r--phpBB/styles/prosilver/template/notification_dropdown.html4
-rw-r--r--phpBB/styles/prosilver/template/overall_footer.html27
-rw-r--r--phpBB/styles/prosilver/template/overall_header.html34
-rw-r--r--phpBB/styles/prosilver/template/pagination.html10
-rw-r--r--phpBB/styles/prosilver/template/posting_attach_body.html10
-rw-r--r--phpBB/styles/prosilver/template/posting_buttons.html56
-rw-r--r--phpBB/styles/prosilver/template/posting_editor.html12
-rw-r--r--phpBB/styles/prosilver/template/posting_layout.html12
-rw-r--r--phpBB/styles/prosilver/template/posting_pm_layout.html4
-rw-r--r--phpBB/styles/prosilver/template/posting_review.html11
-rw-r--r--phpBB/styles/prosilver/template/posting_smilies.html8
-rw-r--r--phpBB/styles/prosilver/template/posting_topic_review.html33
-rw-r--r--phpBB/styles/prosilver/template/quickreply_editor.html2
-rw-r--r--phpBB/styles/prosilver/template/report_body.html4
-rw-r--r--phpBB/styles/prosilver/template/search_results.html122
-rw-r--r--phpBB/styles/prosilver/template/simple_footer.html16
-rw-r--r--phpBB/styles/prosilver/template/simple_header.html8
-rw-r--r--phpBB/styles/prosilver/template/timezone_option.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_attachments.html26
-rw-r--r--phpBB/styles/prosilver/template/ucp_avatar_options_local.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_groups_manage.html18
-rw-r--r--phpBB/styles/prosilver/template/ucp_groups_membership.html14
-rw-r--r--phpBB/styles/prosilver/template/ucp_header.html14
-rw-r--r--phpBB/styles/prosilver/template/ucp_main_bookmarks.html40
-rw-r--r--phpBB/styles/prosilver/template/ucp_main_front.html26
-rw-r--r--phpBB/styles/prosilver/template/ucp_main_subscribed.html59
-rw-r--r--phpBB/styles/prosilver/template/ucp_notifications.html10
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_history.html22
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_message_header.html61
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_viewfolder.html32
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_viewmessage.html51
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html8
-rw-r--r--phpBB/styles/prosilver/template/ucp_prefs_post.html12
-rw-r--r--phpBB/styles/prosilver/template/ucp_prefs_view.html14
-rw-r--r--phpBB/styles/prosilver/template/ucp_profile_reg_details.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_zebra_foes.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_zebra_friends.html2
-rw-r--r--phpBB/styles/prosilver/template/viewforum_body.html122
-rw-r--r--phpBB/styles/prosilver/template/viewonline_body.html16
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_body.html129
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_print.html8
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_topic_tools.html43
-rw-r--r--phpBB/styles/prosilver/theme/base.css115
-rw-r--r--phpBB/styles/prosilver/theme/bidi.css209
-rw-r--r--phpBB/styles/prosilver/theme/buttons.css223
-rw-r--r--phpBB/styles/prosilver/theme/colours.css627
-rw-r--r--phpBB/styles/prosilver/theme/common.css335
-rw-r--r--phpBB/styles/prosilver/theme/content.css75
-rw-r--r--phpBB/styles/prosilver/theme/cp.css76
-rw-r--r--phpBB/styles/prosilver/theme/en/stylesheet.css6
-rw-r--r--phpBB/styles/prosilver/theme/forms.css81
-rw-r--r--phpBB/styles/prosilver/theme/icons.css83
-rw-r--r--phpBB/styles/prosilver/theme/images/alert_close.pngbin2097 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/arrow_down.gifbin51 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/arrow_left.gifbin49 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/arrow_right.gifbin49 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/arrow_up.gifbin51 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/bg_button.gifbin182 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/feed.gifbin1089 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/gradient.gifbin549 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_acp.gifbin389 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_back_top.gifbin204 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_bookmark.gifbin218 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_bump.gifbin148 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_contact.pngbin340 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_delete_cookies.gifbin108 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_faq.gifbin255 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_home.gifbin306 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_logout.gifbin219 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_mark.gifbin360 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_mcp.gifbin342 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_members.gifbin264 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_notification.gifbin551 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_pages.gifbin105 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_pm.gifbin576 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_post_target.gifbin124 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_post_target_unread.gifbin89 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_print.gifbin204 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_profile.gifbin538 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_register.gifbin231 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_search.gifbin334 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_sendemail.gifbin303 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_subscribe.gifbin216 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_team.gifbin1009 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_textbox_search.gifbin335 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_attach.gifbin82 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_deleted.pngbin1205 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_latest.gifbin124 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_newest.gifbin93 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_poll.gifbin120 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_reported.gifbin246 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_topic_unapproved.gifbin253 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_ucp.gifbin254 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icon_unsubscribe.gifbin214 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icons_button.pngbin8037 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/icons_pagination.pngbin1043 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/subforum_read.gifbin124 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/images/subforum_unread.gifbin124 -> 0 bytes
-rw-r--r--phpBB/styles/prosilver/theme/imageset.css376
-rw-r--r--phpBB/styles/prosilver/theme/links.css76
-rw-r--r--phpBB/styles/prosilver/theme/normalize.css424
-rw-r--r--phpBB/styles/prosilver/theme/plupload.css10
-rw-r--r--phpBB/styles/prosilver/theme/print.css4
-rw-r--r--phpBB/styles/prosilver/theme/responsive.css884
-rw-r--r--phpBB/styles/prosilver/theme/stylesheet.css8
-rw-r--r--phpBB/styles/prosilver/theme/tweaks.css12
-rw-r--r--phpBB/styles/prosilver/theme/utilities.css66
-rw-r--r--phpBB/styles/subsilver2/style.cfg32
-rw-r--r--phpBB/styles/subsilver2/template/attachment.html125
-rw-r--r--phpBB/styles/subsilver2/template/bbcode.html69
-rw-r--r--phpBB/styles/subsilver2/template/breadcrumbs.html14
-rw-r--r--phpBB/styles/subsilver2/template/captcha_default.html17
-rw-r--r--phpBB/styles/subsilver2/template/captcha_qa.html8
-rw-r--r--phpBB/styles/subsilver2/template/captcha_recaptcha.html36
-rw-r--r--phpBB/styles/subsilver2/template/confirm_body.html28
-rw-r--r--phpBB/styles/subsilver2/template/confirm_delete_body.html55
-rw-r--r--phpBB/styles/subsilver2/template/faq_body.html63
-rw-r--r--phpBB/styles/subsilver2/template/forumlist_body.html98
-rw-r--r--phpBB/styles/subsilver2/template/index.htm16
-rw-r--r--phpBB/styles/subsilver2/template/index_body.html142
-rw-r--r--phpBB/styles/subsilver2/template/jumpbox.html19
-rw-r--r--phpBB/styles/subsilver2/template/login_body.html111
-rw-r--r--phpBB/styles/subsilver2/template/login_body_oauth.html7
-rw-r--r--phpBB/styles/subsilver2/template/login_forum.html56
-rw-r--r--phpBB/styles/subsilver2/template/mcp_approve.html49
-rw-r--r--phpBB/styles/subsilver2/template/mcp_ban.html120
-rw-r--r--phpBB/styles/subsilver2/template/mcp_footer.html27
-rw-r--r--phpBB/styles/subsilver2/template/mcp_forum.html98
-rw-r--r--phpBB/styles/subsilver2/template/mcp_front.html147
-rw-r--r--phpBB/styles/subsilver2/template/mcp_header.html60
-rw-r--r--phpBB/styles/subsilver2/template/mcp_logs.html46
-rw-r--r--phpBB/styles/subsilver2/template/mcp_message.html14
-rw-r--r--phpBB/styles/subsilver2/template/mcp_move.html48
-rw-r--r--phpBB/styles/subsilver2/template/mcp_notes_front.html22
-rw-r--r--phpBB/styles/subsilver2/template/mcp_notes_user.html125
-rw-r--r--phpBB/styles/subsilver2/template/mcp_post.html214
-rw-r--r--phpBB/styles/subsilver2/template/mcp_queue.html76
-rw-r--r--phpBB/styles/subsilver2/template/mcp_reports.html67
-rw-r--r--phpBB/styles/subsilver2/template/mcp_topic.html158
-rw-r--r--phpBB/styles/subsilver2/template/mcp_warn_front.html74
-rw-r--r--phpBB/styles/subsilver2/template/mcp_warn_list.html43
-rw-r--r--phpBB/styles/subsilver2/template/mcp_warn_post.html67
-rw-r--r--phpBB/styles/subsilver2/template/mcp_warn_user.html80
-rw-r--r--phpBB/styles/subsilver2/template/mcp_whois.html15
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_body.html117
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_email.html107
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_group.html17
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_im.html43
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_search.html129
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_team.html50
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_view.html207
-rw-r--r--phpBB/styles/subsilver2/template/message_body.html16
-rw-r--r--phpBB/styles/subsilver2/template/overall_footer.html29
-rw-r--r--phpBB/styles/subsilver2/template/overall_header.html262
-rw-r--r--phpBB/styles/subsilver2/template/pagination.html11
-rw-r--r--phpBB/styles/subsilver2/template/posting_attach_body.html83
-rw-r--r--phpBB/styles/subsilver2/template/posting_body.html434
-rw-r--r--phpBB/styles/subsilver2/template/posting_buttons.html91
-rw-r--r--phpBB/styles/subsilver2/template/posting_poll_body.html37
-rw-r--r--phpBB/styles/subsilver2/template/posting_preview.html71
-rw-r--r--phpBB/styles/subsilver2/template/posting_progress_bar.html44
-rw-r--r--phpBB/styles/subsilver2/template/posting_review.html99
-rw-r--r--phpBB/styles/subsilver2/template/posting_smilies.html38
-rw-r--r--phpBB/styles/subsilver2/template/posting_topic_review.html112
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/bool.html7
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/date.html5
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/dropdown.html5
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/int.html3
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/string.html3
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/text.html3
-rw-r--r--phpBB/styles/subsilver2/template/profilefields/url.html3
-rw-r--r--phpBB/styles/subsilver2/template/quickreply_editor.html30
-rw-r--r--phpBB/styles/subsilver2/template/report_body.html49
-rw-r--r--phpBB/styles/subsilver2/template/search_body.html110
-rw-r--r--phpBB/styles/subsilver2/template/search_results.html165
-rw-r--r--phpBB/styles/subsilver2/template/searchbox.html1
-rw-r--r--phpBB/styles/subsilver2/template/simple_footer.html15
-rw-r--r--phpBB/styles/subsilver2/template/simple_header.html23
-rw-r--r--phpBB/styles/subsilver2/template/timezone.js21
-rw-r--r--phpBB/styles/subsilver2/template/timezone_option.html28
-rw-r--r--phpBB/styles/subsilver2/template/ucp_agreement.html87
-rw-r--r--phpBB/styles/subsilver2/template/ucp_attachments.html58
-rw-r--r--phpBB/styles/subsilver2/template/ucp_auth_link.html19
-rw-r--r--phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html34
-rw-r--r--phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html13
-rw-r--r--phpBB/styles/subsilver2/template/ucp_avatar_options_local.html42
-rw-r--r--phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html10
-rw-r--r--phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html12
-rw-r--r--phpBB/styles/subsilver2/template/ucp_footer.html13
-rw-r--r--phpBB/styles/subsilver2/template/ucp_groups_manage.html229
-rw-r--r--phpBB/styles/subsilver2/template/ucp_groups_membership.html93
-rw-r--r--phpBB/styles/subsilver2/template/ucp_header.html165
-rw-r--r--phpBB/styles/subsilver2/template/ucp_login_link.html74
-rw-r--r--phpBB/styles/subsilver2/template/ucp_main_bookmarks.html86
-rw-r--r--phpBB/styles/subsilver2/template/ucp_main_drafts.html96
-rw-r--r--phpBB/styles/subsilver2/template/ucp_main_front.html74
-rw-r--r--phpBB/styles/subsilver2/template/ucp_main_subscribed.html95
-rw-r--r--phpBB/styles/subsilver2/template/ucp_notifications.html141
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_history.html86
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_message_footer.html47
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_message_header.html34
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_options.html192
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html131
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html136
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html122
-rw-r--r--phpBB/styles/subsilver2/template/ucp_prefs_personal.html71
-rw-r--r--phpBB/styles/subsilver2/template/ucp_prefs_post.html35
-rw-r--r--phpBB/styles/subsilver2/template/ucp_prefs_view.html77
-rw-r--r--phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html50
-rw-r--r--phpBB/styles/subsilver2/template/ucp_profile_avatar.html50
-rw-r--r--phpBB/styles/subsilver2/template/ucp_profile_profile_info.html44
-rw-r--r--phpBB/styles/subsilver2/template/ucp_profile_reg_details.html49
-rw-r--r--phpBB/styles/subsilver2/template/ucp_profile_signature.html132
-rw-r--r--phpBB/styles/subsilver2/template/ucp_register.html101
-rw-r--r--phpBB/styles/subsilver2/template/ucp_remind.html28
-rw-r--r--phpBB/styles/subsilver2/template/ucp_resend.html29
-rw-r--r--phpBB/styles/subsilver2/template/ucp_zebra_foes.html28
-rw-r--r--phpBB/styles/subsilver2/template/ucp_zebra_friends.html30
-rw-r--r--phpBB/styles/subsilver2/template/viewforum_body.html381
-rw-r--r--phpBB/styles/subsilver2/template/viewonline_body.html57
-rw-r--r--phpBB/styles/subsilver2/template/viewonline_whois.html12
-rw-r--r--phpBB/styles/subsilver2/template/viewtopic_body.html462
-rw-r--r--phpBB/styles/subsilver2/template/viewtopic_print.html136
-rw-r--r--phpBB/styles/subsilver2/theme/en/button_pm_new.gifbin1135 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/button_pm_reply.gifbin1667 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/button_topic_locked.gifbin1101 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/button_topic_new.gifbin1164 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/button_topic_reply.gifbin1234 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_aim.gifbin580 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_email.gifbin659 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_icq.gifbin574 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gifbin674 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_msnm.gifbin1503 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_pm.gifbin706 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_www.gifbin604 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_contact_yahoo.gifbin663 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_post_delete.gifbin314 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_post_edit.gifbin662 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_post_info.gifbin305 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_post_quote.gifbin666 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_post_report.gifbin308 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_user_offline.gifbin547 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_user_online.gifbin520 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_user_profile.gifbin667 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_user_search.gifbin608 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/icon_user_warn.gifbin673 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/en/stylesheet.css116
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_read.gifbin307 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_read_locked.gifbin304 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gifbin324 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_read_mine.gifbin328 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_unread.gifbin289 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_unread_locked.gifbin292 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gifbin308 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/announce_unread_mine.gifbin305 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/background.gifbin666 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/cellpic.gifbin722 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/cellpic1.gifbin246 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/cellpic2.jpgbin480 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/cellpic2_rtl.jpgbin601 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/cellpic3.gifbin257 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/created_by.jpgbin15319 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_link.gifbin714 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_read.gifbin677 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_read_locked.gifbin673 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_read_subforum.gifbin705 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_unread.gifbin663 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_unread_locked.gifbin660 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/forum_unread_subforum.gifbin688 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_faq.gifbin219 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_groups.gifbin222 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_login.gifbin233 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_members.gifbin223 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_message.gifbin232 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_notification.gifbin543 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_profile.gifbin238 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_register.gifbin224 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_mini_search.gifbin238 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_post_target.gifbin122 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gifbin122 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_topic_attach.gifbin217 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_topic_deleted.pngbin1205 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_topic_latest.gifbin135 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_topic_newest.gifbin133 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_topic_reported.gifbin462 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/icon_topic_unapproved.gifbin334 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/index.htm16
-rw-r--r--phpBB/styles/subsilver2/theme/images/no_avatar.gifbin930 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/poll_center.gifbin92 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/poll_left.gifbin113 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/poll_right.gifbin113 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/site_logo.gifbin7151 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/spacer.gifbin43 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_read.gifbin344 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_read_locked.gifbin338 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_read_locked_mine.gifbin336 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_read_mine.gifbin352 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_unread.gifbin325 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gifbin324 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gifbin336 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/sticky_unread_mine.gifbin339 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_moved.gifbin660 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_read.gifbin344 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_read_hot.gifbin1902 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gifbin1903 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_read_locked.gifbin333 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gifbin337 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_read_mine.gifbin350 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_unread.gifbin336 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_unread_hot.gifbin1888 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gifbin1895 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_unread_locked.gifbin459 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_unread_locked_mine.gifbin334 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/topic_unread_mine.gifbin350 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/upload_bar.gifbin12892 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/images/whosonline.gifbin929 -> 0 bytes
-rw-r--r--phpBB/styles/subsilver2/theme/stylesheet.css1256
-rw-r--r--phpBB/ucp.php16
-rw-r--r--phpBB/viewforum.php20
-rw-r--r--phpBB/viewonline.php37
-rw-r--r--phpBB/viewtopic.php44
-rw-r--r--tests/RUNNING_TESTS.md5
-rw-r--r--tests/attachment/delete_test.php127
-rw-r--r--tests/attachment/fixtures/resync.xml130
-rw-r--r--tests/attachment/manager_test.php131
-rw-r--r--tests/attachment/resync_test.php74
-rw-r--r--tests/attachment/upload_test.php429
-rw-r--r--tests/auth/provider_apache_test.php7
-rw-r--r--tests/auth/provider_db_test.php7
-rw-r--r--tests/auth/provider_oauth_token_storage_test.php12
-rw-r--r--tests/avatar/driver/barfoo.php52
-rw-r--r--tests/avatar/driver/foobar.php52
-rw-r--r--tests/avatar/manager_test.php24
-rw-r--r--tests/bbcode/parser_test.php2
-rw-r--r--tests/bbcode/url_bbcode_test.php2
-rw-r--r--tests/bootstrap.php9
-rw-r--r--tests/cache/apc_driver_test.php6
-rw-r--r--tests/cache/dummy_driver_test.php77
-rw-r--r--tests/cache/null_driver_test.php77
-rw-r--r--tests/captcha/qa_test.php13
-rw-r--r--tests/composer.json5
-rw-r--r--tests/composer.lock63
-rw-r--r--tests/compress/compress_test.php1
-rw-r--r--tests/console/cache/purge_test.php9
-rw-r--r--tests/console/config/config_test.php7
-rw-r--r--tests/console/cron/cron_list_test.php7
-rw-r--r--tests/console/cron/run_test.php15
-rw-r--r--tests/console/fixtures/png.pngbin0 -> 129 bytes
-rw-r--r--tests/console/fixtures/thumbnail.xml40
-rw-r--r--tests/console/fixtures/txt.txt2
-rw-r--r--tests/console/thumbnail_test.php122
-rw-r--r--tests/console/user/activate_test.php86
-rw-r--r--tests/console/user/add_test.php92
-rw-r--r--tests/console/user/base.php121
-rw-r--r--tests/console/user/delete_test.php93
-rw-r--r--tests/console/user/fixtures/config.xml63
-rw-r--r--tests/console/user/reclean_test.php49
-rw-r--r--tests/content_visibility/delete_post_test.php20
-rw-r--r--tests/content_visibility/get_forums_visibility_sql_test.php4
-rw-r--r--tests/content_visibility/get_global_visibility_sql_test.php4
-rw-r--r--tests/content_visibility/get_visibility_sql_test.php4
-rw-r--r--tests/content_visibility/set_post_visibility_test.php11
-rw-r--r--tests/content_visibility/set_topic_visibility_test.php7
-rw-r--r--tests/controller/common_helper_route.php135
-rw-r--r--tests/controller/config/test/routing/environment.yml (renamed from tests/controller/config/routing.yml)0
-rw-r--r--tests/controller/controller_test.php82
-rw-r--r--tests/controller/ext/vendor2/bar/config/services.yml3
-rw-r--r--tests/controller/ext/vendor2/bar/config/test/routing/environment.yml3
-rw-r--r--tests/controller/ext/vendor2/bar/controller.php18
-rw-r--r--tests/controller/ext/vendor2/foo/config/routing.yml4
-rw-r--r--tests/controller/ext/vendor2/foo/controller.php17
-rw-r--r--tests/controller/helper_route_adm_subdir_test.php1
-rw-r--r--tests/controller/helper_route_adm_test.php1
-rw-r--r--tests/controller/helper_route_root_test.php1
-rw-r--r--tests/controller/helper_route_slash_test.php1
-rw-r--r--tests/controller/helper_route_unclean_path_test.php1
-rw-r--r--tests/datetime/from_format_test.php12
-rw-r--r--tests/dbal/auto_increment_test.php5
-rw-r--r--tests/dbal/boolean_processor_test.php321
-rw-r--r--tests/dbal/connect_test.php6
-rw-r--r--tests/dbal/cross_join_test.php3
-rw-r--r--tests/dbal/db_tools_test.php11
-rw-r--r--tests/dbal/fixtures/boolean_processor.xml84
-rw-r--r--tests/dbal/migrator_test.php8
-rw-r--r--tests/dbal/migrator_tool_module_test.php15
-rw-r--r--tests/dbal/migrator_tool_permission_test.php4
-rw-r--r--tests/dbal/schema_test.php2
-rw-r--r--tests/dbal/select_test.php3
-rw-r--r--tests/dbal/write_sequence_test.php2
-rw-r--r--tests/dbal/write_test.php2
-rw-r--r--tests/di/create_container_test.php94
-rw-r--r--tests/di/fixtures/config.php4
-rw-r--r--tests/di/fixtures/config/production/config.yml2
-rw-r--r--tests/di/fixtures/config/production/container/environment.yml29
-rw-r--r--tests/di/fixtures/config/services.yml14
-rw-r--r--tests/di/fixtures/config/test/config.yml2
-rw-r--r--tests/di/fixtures/config/test/container/environment.yml26
-rw-r--r--tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml (renamed from tests/di/fixtures/ext/vendor/disabled/config/services.yml)0
-rw-r--r--tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml2
-rw-r--r--tests/di/fixtures/ext/vendor/enabled-3/config/services.yml2
-rw-r--r--tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml (renamed from tests/di/fixtures/ext/vendor/enabled/config/services.yml)0
-rw-r--r--tests/di/fixtures/ext/vendor/enabled_4/di/extension.php32
-rw-r--r--tests/di/fixtures/ext/vendor/enabled_4/environment.yml2
-rw-r--r--tests/di/fixtures/other_config/production/config.yml2
-rw-r--r--tests/di/fixtures/other_config/production/container/environment.yml29
-rw-r--r--tests/di/fixtures/other_config/services.yml14
-rw-r--r--tests/di/fixtures/other_config/test/config.yml2
-rw-r--r--tests/di/fixtures/other_config/test/container/environment.yml26
-rw-r--r--tests/di/ordered_service_collection_test.php51
-rw-r--r--tests/di/service_collection_test.php47
-rw-r--r--tests/download/http_byte_range_test.php62
-rw-r--r--tests/email/email_parsing_test.php149
-rw-r--r--tests/error_collector_test.php11
-rw-r--r--tests/event/exception_listener_test.php10
-rw-r--r--tests/event/md_exporter_test.php8
-rw-r--r--tests/extension/ext/vendor2/bar/acp/a_info.php1
-rw-r--r--tests/extension/ext/vendor2/bar/migrations/bar.php7
-rw-r--r--tests/extension/ext/vendor2/bar/migrations/foo.php54
-rw-r--r--tests/extension/ext/vendor2/foo/acp/a_info.php1
-rw-r--r--tests/extension/ext/vendor2/foo/acp/fail_info.php1
-rw-r--r--tests/extension/ext/vendor2/foo/mcp/a_info.php1
-rw-r--r--tests/extension/extension_base_test.php12
-rw-r--r--tests/extension/finder_test.php5
-rw-r--r--tests/extension/includes/acp/info/acp_foobar.php1
-rw-r--r--tests/extension/manager_test.php7
-rw-r--r--tests/extension/metadata_manager_test.php80
-rw-r--r--tests/extension/modules_test.php61
-rw-r--r--tests/files/type_foo.php31
-rw-r--r--tests/files/types_base_test.php93
-rw-r--r--tests/files/types_form_test.php172
-rw-r--r--tests/files/types_local_test.php161
-rw-r--r--tests/files/types_remote_test.php132
-rw-r--r--tests/files/upload_test.php128
-rw-r--r--tests/filesystem/clean_path_test.php2
-rw-r--r--tests/filesystem/is_absolute_test.php68
-rw-r--r--tests/filesystem/realpath_test.php90
-rw-r--r--tests/functional/browse_test.php14
-rw-r--r--tests/functional/controllers_compatibility_test.php56
-rw-r--r--tests/functional/download_test.php3
-rw-r--r--tests/functional/extension_module_test.php11
-rw-r--r--tests/functional/feed_test.php131
-rw-r--r--tests/functional/fileupload_remote_test.php74
-rw-r--r--tests/functional/fixtures/ext/foo/bar/acp/main_info.php1
-rw-r--r--tests/functional/fixtures/ext/foo/bar/config/services.yml14
-rw-r--r--tests/functional/fixtures/ext/foo/bar/ucp/main_info.php1
-rw-r--r--tests/functional/forum_style_test.php24
-rw-r--r--tests/functional/notification_test.php8
-rw-r--r--tests/functional/permission_roles_test.php84
-rw-r--r--tests/functional/plupload_test.php12
-rw-r--r--tests/functional/posting_test.php116
-rw-r--r--tests/functional/private_messages_test.php41
-rw-r--r--tests/functional/report_post_captcha_test.php7
-rw-r--r--tests/functional/search/base.php7
-rw-r--r--tests/functional/visit_installer_test.php30
-rw-r--r--tests/functions/build_hidden_fields_for_query_params_test.php2
-rw-r--r--tests/functions/build_url_test.php4
-rw-r--r--tests/functions/convert_30_dbms_to_31_test.php4
-rw-r--r--tests/functions/generate_string_list.php12
-rw-r--r--tests/functions/get_formatted_filesize_test.php2
-rw-r--r--tests/functions/get_preg_expression_test.php2
-rw-r--r--tests/functions/get_remote_file_test.php3
-rw-r--r--tests/functions/is_absolute_test.php60
-rw-r--r--tests/functions/language_select_test.php2
-rw-r--r--tests/functions/make_clickable_email_test.php3
-rw-r--r--tests/functions/make_clickable_test.php3
-rw-r--r--tests/functions/obtain_online_test.php3
-rw-r--r--tests/functions/parse_cfg_file_test.php2
-rw-r--r--tests/functions/quoteattr_test.php2
-rw-r--r--tests/functions/style_select_test.php2
-rw-r--r--tests/functions/user_delete_test.php11
-rw-r--r--tests/functions/validate_email_test.php1
-rw-r--r--tests/functions/validate_password_test.php1
-rw-r--r--tests/functions/validate_string_test.php1
-rw-r--r--tests/functions/validate_user_email_test.php1
-rw-r--r--tests/functions/validate_username_test.php2
-rw-r--r--tests/functions_acp/validate_config_vars_test.php1
-rw-r--r--tests/functions_acp/validate_range_test.php1
-rw-r--r--tests/functions_content/get_username_string_test.php3
-rw-r--r--tests/functions_content/phpbb_clean_search_string_test.php2
-rw-r--r--tests/functions_install/ignore_new_file_on_update_test.php45
-rw-r--r--tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml83
-rw-r--r--tests/functions_privmsgs/get_max_setting_from_group_test.php64
-rw-r--r--tests/functions_user/delete_user_test.php8
-rw-r--r--tests/functions_user/group_user_attributes_test.php4
-rw-r--r--tests/group/helper_test.php68
-rw-r--r--tests/groupposition/legend_test.php43
-rw-r--r--tests/groupposition/teampage_test.php51
-rw-r--r--tests/help/manager_test.php184
-rw-r--r--tests/installer/database_helper_test.php157
-rw-r--r--tests/installer/installer_config_test.php80
-rw-r--r--tests/installer/mocks/test_installer_module.php20
-rw-r--r--tests/installer/mocks/test_installer_task_mock.php44
-rw-r--r--tests/installer/module_base_test.php65
-rw-r--r--tests/installer/navigation_provider_test.php34
-rw-r--r--tests/language/language_test.php243
-rw-r--r--tests/lock/db_test.php3
-rw-r--r--tests/log/add_test.php10
-rw-r--r--tests/log/delete_test.php8
-rw-r--r--tests/log/fixtures/delete_log.xml16
-rw-r--r--tests/log/fixtures/empty_log.xml1
-rw-r--r--tests/log/fixtures/full_log.xml12
-rw-r--r--tests/log/function_add_log_test.php7
-rw-r--r--tests/log/function_view_log_test.php19
-rw-r--r--tests/migrator/convert_timezones_test.php9
-rw-r--r--tests/migrator/schema_generator_test.php5
-rw-r--r--tests/mock/container_builder.php15
-rw-r--r--tests/mock/controller_helper.php14
-rw-r--r--tests/mock/extension_manager.php2
-rw-r--r--tests/mock/fileupload.php3
-rw-r--r--tests/mock/migrator.php4
-rw-r--r--tests/mock/notification_manager.php7
-rw-r--r--tests/mock/notification_type_post.php6
-rw-r--r--tests/mock/phpbb_di_container_builder.php10
-rw-r--r--tests/mock/router.php27
-rw-r--r--tests/mock/session_testable.php2
-rw-r--r--tests/network/checkdnsrr_test.php2
-rw-r--r--tests/network/ftp_fsock_pasv_epsv_test.php1
-rw-r--r--tests/network/inet_ntop_pton_test.php2
-rw-r--r--tests/network/ip_normalise_test.php2
-rw-r--r--tests/notification/base.php67
-rw-r--r--tests/notification/convert_test.php3
-rw-r--r--tests/notification/ext/test/notification/type/test.php5
-rw-r--r--tests/notification/fixtures/services_notification.yml76
-rw-r--r--tests/notification/fixtures/submit_post_notification.type.bookmark.xml10
-rw-r--r--tests/notification/fixtures/submit_post_notification.type.post.xml14
-rw-r--r--tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml14
-rw-r--r--tests/notification/fixtures/submit_post_notification.type.quote.xml10
-rw-r--r--tests/notification/fixtures/submit_post_notification.type.topic.xml8
-rw-r--r--tests/notification/group_request_test.php11
-rw-r--r--tests/notification/manager_helper.php31
-rw-r--r--tests/notification/notification_test.php50
-rw-r--r--tests/notification/submit_post_base.php73
-rw-r--r--tests/notification/submit_post_type_quote_test.php39
-rw-r--r--tests/notification/submit_post_type_topic_test.php2
-rw-r--r--tests/notification/user_list_trim_test.php25
-rw-r--r--tests/pagination/config/test/routing/environment.yml (renamed from tests/pagination/config/routing.yml)0
-rw-r--r--tests/pagination/pagination_test.php27
-rw-r--r--tests/path_helper/path_helper_test.php47
-rw-r--r--tests/plupload/plupload_test.php8
-rw-r--r--tests/privmsgs/delete_user_pms_test.php4
-rw-r--r--tests/profilefields/type_bool_test.php7
-rw-r--r--tests/profilefields/type_date_test.php7
-rw-r--r--tests/profilefields/type_dropdown_test.php7
-rw-r--r--tests/profilefields/type_googleplus_test.php8
-rw-r--r--tests/profilefields/type_int_test.php7
-rw-r--r--tests/profilefields/type_string_test.php11
-rw-r--r--tests/profilefields/type_url_test.php9
-rw-r--r--tests/random/gen_rand_string_test.php2
-rw-r--r--tests/regex/censor_test.php16
-rw-r--r--tests/regex/email_test.php2
-rw-r--r--tests/regex/ipv4_test.php2
-rw-r--r--tests/regex/ipv6_test.php2
-rw-r--r--tests/regex/password_complexity_test.php1
-rw-r--r--tests/regex/table_prefix_test.php2
-rw-r--r--tests/regex/url_test.php2
-rw-r--r--tests/request/request_var_test.php3
-rw-r--r--tests/request/type_cast_helper_test.php2
-rw-r--r--tests/security/base.php6
-rw-r--r--tests/security/extract_current_page_test.php1
-rw-r--r--tests/security/hash_test.php2
-rw-r--r--tests/security/redirect_test.php3
-rw-r--r--tests/session/append_sid_test.php2
-rw-r--r--tests/session/check_ban_test.php5
-rw-r--r--tests/session/extract_page_test.php3
-rw-r--r--tests/session/garbage_collection_test.php1
-rw-r--r--tests/session/session_key_test.php1
-rw-r--r--tests/session/testable_factory.php6
-rw-r--r--tests/template/asset_test.php49
-rw-r--r--tests/template/includephp_test.php3
-rw-r--r--tests/template/template_allfolder_test.php31
-rw-r--r--tests/template/template_events_test.php27
-rw-r--r--tests/template/template_includecss_test.php36
-rw-r--r--tests/template/template_parser_test.php1
-rw-r--r--tests/template/template_test.php158
-rw-r--r--tests/template/template_test_case.php55
-rw-r--r--tests/template/template_test_case_with_tree.php26
-rw-r--r--tests/template/templates/loop_advanced_twig.html19
-rw-r--r--tests/template/templates/loop_expressions.html4
-rw-r--r--tests/template/templates/loop_expressions_twig.html11
-rw-r--r--tests/template/templates/loop_expressions_twig2.html11
-rw-r--r--tests/template/templates/loop_include1_twig.html1
-rw-r--r--tests/template/templates/loop_include_twig.html4
-rw-r--r--tests/template/templates/loop_nested2_twig.html6
-rw-r--r--tests/template/templates/loop_nested_deep_multilevel_ref_twig.html13
-rw-r--r--tests/template/templates/loop_nested_include1_twig.html5
-rw-r--r--tests/template/templates/loop_nested_include_twig.html4
-rw-r--r--tests/template/templates/loop_nested_multilevel_ref_twig.html10
-rw-r--r--tests/template/templates/loop_nested_twig.html6
-rw-r--r--tests/template/templates/loop_reuse_twig.html6
-rw-r--r--tests/template/templates/loop_size_twig.html39
-rw-r--r--tests/template/templates/loop_twig.html21
-rw-r--r--tests/template/templates/loop_underscore_twig.html21
-rw-r--r--tests/template/templates/loop_vars_twig.html13
-rw-r--r--tests/test_framework/mock/phpbb_mock_null_installer_task.php30
-rw-r--r--tests/test_framework/phpbb_database_test_case.php9
-rw-r--r--tests/test_framework/phpbb_database_test_connection_manager.php33
-rw-r--r--tests/test_framework/phpbb_functional_test_case.php248
-rw-r--r--tests/test_framework/phpbb_session_test_case.php3
-rw-r--r--tests/test_framework/phpbb_test_case_helpers.php304
-rw-r--r--tests/test_framework/phpbb_ui_test_case.php174
-rw-r--r--tests/text_formatter/s9e/default_formatting_test.php313
-rw-r--r--tests/text_formatter/s9e/factory_test.php263
-rw-r--r--tests/text_formatter/s9e/fixtures/default_formatting.xml466
-rw-r--r--tests/text_formatter/s9e/fixtures/default_lang.xml20
-rw-r--r--tests/text_formatter/s9e/fixtures/factory.xml115
-rw-r--r--tests/text_formatter/s9e/fixtures/inttext_token.xml27
-rw-r--r--tests/text_formatter/s9e/fixtures/local_url.xml28
-rw-r--r--tests/text_formatter/s9e/fixtures/preserve_comments.xml28
-rw-r--r--tests/text_formatter/s9e/fixtures/smilies_duplicate.xml33
-rw-r--r--tests/text_formatter/s9e/fixtures/smilies_special_chars.xml23
-rw-r--r--tests/text_formatter/s9e/fixtures/style_inheritance.xml66
-rw-r--r--tests/text_formatter/s9e/fixtures/styles.xml36
-rw-r--r--tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html40
-rw-r--r--tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html40
-rw-r--r--tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html40
-rw-r--r--tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml28
-rw-r--r--tests/text_formatter/s9e/parser_test.php258
-rw-r--r--tests/text_formatter/s9e/renderer_test.php481
-rw-r--r--tests/text_formatter/s9e/utils_test.php276
-rw-r--r--tests/text_processing/censor_text_test.php3
-rw-r--r--tests/text_processing/decode_message_test.php113
-rw-r--r--tests/text_processing/fixtures/empty.xml3
-rw-r--r--tests/text_processing/fixtures/smilies.xml443
-rw-r--r--tests/text_processing/generate_text_for_display_test.php191
-rw-r--r--tests/text_processing/generate_text_for_edit_test.php89
-rw-r--r--tests/text_processing/generate_text_for_storage_test.php178
-rw-r--r--tests/text_processing/make_clickable_test.php3
-rw-r--r--tests/text_processing/message_parser_test.php540
-rw-r--r--tests/text_processing/smilies_test.php49
-rw-r--r--tests/text_processing/strip_bbcode_test.php39
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10002.html2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10002.txt2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10122.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10122.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10268.html4
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10268.txt4
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10425.html3
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10425.txt3
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10587.html2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10587.txt2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10922.html9
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10922.txt9
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10989.html8
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-10989.txt8
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-11153.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-11153.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-11153.xml28
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-11742.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-11742.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-12195.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-12195.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-12221.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-12221.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13425.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13425.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13425.xml23
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13451.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13451.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13641.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13641.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13641.xml28
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13921.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13921.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13921.xml28
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14260.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14260.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14405.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14405.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14663.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14663.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14663.xml28
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14706.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14706.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14740.html2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14740.txt2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14740.xml40
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14846.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14846.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-14846.xml28
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-3981.before.php21
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-3981.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-3981.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7187.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7187.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7187.xml33
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7275.after.php19
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7275.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7275.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-7275.xml49
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-8419.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-8419.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-8419.xml28
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9073.html2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9073.txt2
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9073.xml14
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9377.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9377.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9377.xml41
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9791.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9791.txt1
-rw-r--r--tests/text_processing/tickets_test.php90
-rw-r--r--tests/text_reparser/base_test.php69
-rw-r--r--tests/text_reparser/fixtures/base.xml19
-rw-r--r--tests/text_reparser/fixtures/config_text.xml7
-rw-r--r--tests/text_reparser/manager_test.php117
-rw-r--r--tests/text_reparser/plugins/contact_admin_info_test.php95
-rw-r--r--tests/text_reparser/plugins/fixtures/contact_admin_info.xml23
-rw-r--r--tests/text_reparser/plugins/fixtures/forums.xml113
-rw-r--r--tests/text_reparser/plugins/fixtures/groups.xml69
-rw-r--r--tests/text_reparser/plugins/fixtures/poll_options.xml133
-rw-r--r--tests/text_reparser/plugins/fixtures/polls.xml98
-rw-r--r--tests/text_reparser/plugins/fixtures/posts.xml91
-rw-r--r--tests/text_reparser/plugins/fixtures/privmsgs.xml113
-rw-r--r--tests/text_reparser/plugins/fixtures/users.xml91
-rw-r--r--tests/text_reparser/plugins/forum_description_test.php26
-rw-r--r--tests/text_reparser/plugins/forum_rules_test.php26
-rw-r--r--tests/text_reparser/plugins/group_description_test.php26
-rw-r--r--tests/text_reparser/plugins/pm_text_test.php26
-rw-r--r--tests/text_reparser/plugins/poll_option_test.php129
-rw-r--r--tests/text_reparser/plugins/poll_title_test.php26
-rw-r--r--tests/text_reparser/plugins/post_text_test.php26
-rw-r--r--tests/text_reparser/plugins/test_row_based_plugin.php150
-rw-r--r--tests/text_reparser/plugins/user_signature_test.php26
-rw-r--r--tests/tree/nestedset_forum_base.php3
-rw-r--r--tests/ui/permission_roles_test.php90
-rw-r--r--tests/ui/quick_links_test.php1
-rw-r--r--tests/upload/filespec_test.php277
-rw-r--r--tests/upload/fileupload_test.php138
-rw-r--r--tests/upload/fixture/bmpbin0 -> 64 bytes
-rw-r--r--tests/upload/fixture/iffbin0 -> 120 bytes
-rw-r--r--tests/upload/fixture/iff_mayabin0 -> 88 bytes
-rw-r--r--tests/upload/fixture/jp2bin0 -> 528 bytes
-rw-r--r--tests/upload/fixture/jpxbin0 -> 528 bytes
-rw-r--r--tests/upload/fixture/psdbin0 -> 6374 bytes
-rw-r--r--tests/upload/fixture/tif_compressedbin0 -> 236 bytes
-rw-r--r--tests/upload/fixture/tif_msbbin0 -> 222 bytes
-rw-r--r--tests/upload/fixture/wbmpbin0 -> 5 bytes
-rw-r--r--tests/upload/imagesize_test.php97
-rw-r--r--tests/user/lang_test.php119
-rw-r--r--tests/user/user_loader_test.php2
-rw-r--r--tests/utf/normalizer_test.php327
-rw-r--r--tests/utf/utf8_clean_string_test.php2
-rw-r--r--tests/utf/utf8_wordwrap_test.php2
-rw-r--r--tests/version/version_fetch_test.php4
-rw-r--r--tests/version/version_helper_remote_test.php8
-rw-r--r--tests/version/version_test.php18
-rw-r--r--tests/viewonline/helper_test.php2
-rw-r--r--tests/wrapper/gmgetdate_test.php2
-rw-r--r--tests/wrapper/mt_rand_test.php2
-rw-r--r--tests/wrapper/phpbb_php_ini_fake.php2
-rw-r--r--tests/wrapper/phpbb_php_ini_test.php46
-rw-r--r--tests/wrapper/version_compare_test.php2
-rwxr-xr-xtravis/check-executable-files.sh7
-rwxr-xr-xtravis/check-image-icc-profiles.sh3
-rwxr-xr-xtravis/check-sami-parse-errors.sh3
-rwxr-xr-xtravis/ext-sniff.sh5
-rwxr-xr-xtravis/install-phpbb-test-dependencies.sh16
-rwxr-xr-xtravis/phing-sniff.sh3
-rwxr-xr-xtravis/setup-database.sh8
-rwxr-xr-xtravis/setup-phpbb.sh13
-rwxr-xr-xtravis/setup-webserver.sh22
-rwxr-xr-xvagrant/after.sh33
-rw-r--r--vagrant/bootstrap.yaml40
-rw-r--r--vagrant/phpbb-install-config.yml51
1548 files changed, 72964 insertions, 46074 deletions
diff --git a/.gitignore b/.gitignore
index 2b2d8d0ac6..ac29bb403c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,7 @@
!/phpBB/cache/.htaccess
!/phpBB/cache/index.html
/phpBB/composer.phar
-/phpBB/config*.php
+/phpBB/config*.php*
/phpBB/ext/*
/phpBB/files/*
/phpBB/images/avatars/gallery/*
@@ -16,9 +16,11 @@
/phpBB/store/*
/phpBB/styles/*
!/phpBB/styles/prosilver
-!/phpBB/styles/subsilver2
+!/phpBB/styles/all
/phpBB/vendor
/tests/phpbb_unit_tests.sqlite*
/tests/test_config*.php
/tests/tmp/*
/tests/vendor
+/vagrant/phpbb-install-config.yml
+.vagrant
diff --git a/.travis.yml b/.travis.yml
index a46d825612..2d88c25b34 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,12 +2,10 @@ language: php
matrix:
include:
- - php: 5.3.3
- env: DB=mysqli
- - php: 5.3
- env: DB=mysqli # MyISAM
- php: 5.4
- env: DB=mysqli
+ env: DB=none;NOTESTS=1
+ - php: 5.4
+ env: DB=mysqli # MyISAM
- php: 5.4
env: DB=mysql
- php: 5.4
@@ -22,28 +20,35 @@ matrix:
env: DB=mysqli
- php: 5.6
env: DB=mysqli
+ - php: 7.0
+ env: DB=mysqli
+ - php: 7.1
+ env: DB=mysqli
+ - php: nightly
+ env: DB=mysqli
- php: hhvm
env: DB=mysqli
allow_failures:
- php: hhvm
+ - php: nightly
fast_finish: true
services:
- redis-server
install:
- - travis/setup-phpbb.sh $DB $TRAVIS_PHP_VERSION
+ - travis/setup-phpbb.sh $DB $TRAVIS_PHP_VERSION $NOTESTS
before_script:
- - travis/setup-database.sh $DB $TRAVIS_PHP_VERSION
+ - travis/setup-database.sh $DB $TRAVIS_PHP_VERSION $NOTESTS
- phantomjs --webdriver=8910 > /dev/null &
script:
- - travis/phing-sniff.sh $DB $TRAVIS_PHP_VERSION
- - travis/check-sami-parse-errors.sh $DB $TRAVIS_PHP_VERSION
- - travis/check-image-icc-profiles.sh $DB $TRAVIS_PHP_VERSION
- - travis/check-executable-files.sh $DB $TRAVIS_PHP_VERSION ./
+ - travis/phing-sniff.sh $DB $TRAVIS_PHP_VERSION $NOTESTS
+ - travis/check-sami-parse-errors.sh $DB $TRAVIS_PHP_VERSION $NOTESTS
+ - travis/check-image-icc-profiles.sh $DB $TRAVIS_PHP_VERSION $NOTESTS
+ - travis/check-executable-files.sh $DB $TRAVIS_PHP_VERSION $NOTESTS ./
- sh -c "if [ '$SLOWTESTS' != '1' -a '$DB' = 'mysqli' ]; then phpBB/vendor/bin/phpunit tests/lint_test.php; fi"
- - sh -c "if [ '$SLOWTESTS' != '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml; fi"
+ - sh -c "if [ '$NOTESTS' != '1' -a '$SLOWTESTS' != '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml; fi"
- sh -c "if [ '$SLOWTESTS' = '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --group slow; fi"
- - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.3.3' -a '$DB' = 'mysqli' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi"
+ - sh -c "set -x;if [ '$NOTESTS' = '1' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi"
diff --git a/README.md b/README.md
index f465d7496e..63ccfedf1b 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,10 @@ To be able to run an installation from the repo (and not from a pre-built packag
3. Read our [Coding guidelines](https://wiki.phpbb.com/Coding_guidelines) and [Git Contribution Guidelines](http://wiki.phpbb.com/Git)
4. Send us a pull request
+## VAGRANT
+
+Read our [Vagrant documentation](phpBB/docs/vagrant.md) to find out how to use Vagrant to develop and contribute to phpBB.
+
## AUTOMATED TESTING
We have unit and functional tests in order to prevent regressions. You can view the bamboo continuous integration [here](http://bamboo.phpbb.com) or check our travis builds below:
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000000..ab225c9ad9
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,25 @@
+require 'json'
+require 'yaml'
+
+VAGRANTFILE_API_VERSION ||= "2"
+confDir = $confDir ||= File.expand_path("phpBB/vendor/laravel/homestead", File.dirname(__FILE__))
+
+homesteadYamlPath = "vagrant/bootstrap.yaml"
+afterScriptPath = "vagrant/after.sh"
+aliasesPath = "vagrant/aliases"
+
+require File.expand_path(confDir + '/scripts/homestead.rb')
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+ if File.exists? aliasesPath then
+ config.vm.provision "file", source: aliasesPath, destination: "~/.bash_aliases"
+ end
+
+ if File.exists? homesteadYamlPath then
+ Homestead.configure(config, YAML::load(File.read(homesteadYamlPath)))
+ end
+
+ if File.exists? afterScriptPath then
+ config.vm.provision "shell", path: afterScriptPath
+ end
+end
diff --git a/build/build.xml b/build/build.xml
index cc29aec654..9cf222ae9e 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -2,9 +2,9 @@
<project name="phpBB" description="The phpBB forum software" default="all" basedir="../">
<!-- a few settings for the build -->
- <property name="newversion" value="3.1.10" />
- <property name="prevversion" value="3.1.9" />
- <property name="olderversions" value="3.0.14, 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5, 3.1.6, 3.1.7, 3.1.7-pl1, 3.1.8" />
+ <property name="newversion" value="3.2.0-RC2-dev" />
+ <property name="prevversion" value="3.2.0-b2" />
+ <property name="olderversions" value="3.0.14, 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5, 3.1.6, 3.1.7, 3.1.7-pl1, 3.1.8, 3.1.9, 3.1.10, 3.2.0-a1, 3.2.0-a2, 3.2.0-b1" />
<!-- no configuration should be needed beyond this point -->
<property name="oldversions" value="${olderversions}, ${prevversion}" />
@@ -183,9 +183,6 @@
<exec dir="build" escape="false"
command="LC_ALL=C diff -crNEBZbd old_versions/release-${prevversion}/styles/prosilver new_version/phpBB3/styles/prosilver >
save/phpbb-${prevversion}_to_${newversion}_prosilver.patch" />
- <exec dir="build" escape="false"
- command="LC_ALL=C diff -crNEBZbd old_versions/release-${prevversion}/styles/subsilver2 new_version/phpBB3/styles/subsilver2 >
- save/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" />
<exec dir="build" escape="false"
command="git shortlog --summary --numbered release-${prevversion}...HEAD >
@@ -296,6 +293,8 @@
<delete file="${dir}/config.php" />
<delete dir="${dir}/develop" />
<delete dir="${dir}/install/data" />
+ <delete dir="${dir}/config/development" />
+ <delete dir="${dir}/config/test" />
<echo msg="Setting permissions for checkout of ${revision} in ${dir}" />
<!-- set permissions of all files to 644, directories to 755 -->
@@ -310,6 +309,50 @@
<target name="clean-vendor-dir">
<!-- Delete unrelated files from vendor/, see PHPBB3-12390 -->
+ <delete dir="${dir}/vendor/bantu/ini-get-wrapper/tests" />
+ <delete file="${dir}/vendor/bantu/ini-get-wrapper/.gitignore" />
+ <delete file="${dir}/vendor/bantu/ini-get-wrapper/.scrutinizer.yml" />
+ <delete file="${dir}/vendor/bantu/ini-get-wrapper/.travis.yml" />
+ <delete file="${dir}/vendor/bantu/ini-get-wrapper/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/bantu/ini-get-wrapper/README.md" />
+
+ <delete dir="${dir}/vendor/google/recaptcha/examples" />
+ <delete dir="${dir}/vendor/google/recaptcha/tests" />
+ <delete file="${dir}/vendor/google/recaptcha/.gitignore" />
+ <delete file="${dir}/vendor/google/recaptcha/.travis.yml" />
+ <delete file="${dir}/vendor/google/recaptcha/CONTRIBUTING.md" />
+ <delete file="${dir}/vendor/google/recaptcha/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/google/recaptcha/README.md" />
+
+ <delete dir="${dir}/vendor/guzzlehttp/guzzle/build" />
+ <delete dir="${dir}/vendor/guzzlehttp/guzzle/docs" />
+ <delete dir="${dir}/vendor/guzzlehttp/guzzle/tests" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/CHANGELOG.md" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/.editorconfig" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/.gitignore" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/Makefile" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/README.md" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/.travis.yml" />
+ <delete file="${dir}/vendor/guzzlehttp/guzzle/UPGRADING.md" />
+
+ <delete dir="${dir}/vendor/guzzlehttp/ringphp/docs" />
+ <delete dir="${dir}/vendor/guzzlehttp/ringphp/tests" />
+ <delete file="${dir}/vendor/guzzlehttp/ringphp/CHANGELOG.md" />
+ <delete file="${dir}/vendor/guzzlehttp/ringphp/.gitignore" />
+ <delete file="${dir}/vendor/guzzlehttp/ringphp/Makefile" />
+ <delete file="${dir}/vendor/guzzlehttp/ringphp/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/guzzlehttp/ringphp/README.rst" />
+ <delete file="${dir}/vendor/guzzlehttp/ringphp/.travis.yml" />
+
+ <delete dir="${dir}/vendor/guzzlehttp/streams/tests" />
+ <delete file="${dir}/vendor/guzzlehttp/streams/CHANGELOG.rst" />
+ <delete file="${dir}/vendor/guzzlehttp/streams/.gitignore" />
+ <delete file="${dir}/vendor/guzzlehttp/streams/Makefile" />
+ <delete file="${dir}/vendor/guzzlehttp/streams/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/guzzlehttp/streams/README.rst" />
+ <delete file="${dir}/vendor/guzzlehttp/streams/.travis.yml" />
+
<delete dir="${dir}/vendor/lusitanian/oauth/examples" />
<delete dir="${dir}/vendor/lusitanian/oauth/tests" />
<delete file="${dir}/vendor/lusitanian/oauth/.gitignore" />
@@ -318,69 +361,121 @@
<delete file="${dir}/vendor/lusitanian/oauth/phpunit.xml.dist" />
<delete file="${dir}/vendor/lusitanian/oauth/README.md" />
+ <delete dir="${dir}/vendor/paragonie/random_compat/dist" />
+ <delete dir="${dir}/vendor/paragonie/random_compat/other" />
+ <delete file="${dir}/vendor/paragonie/random_compat/CHANGELOG.md" />
+ <delete file="${dir}/vendor/paragonie/random_compat/ERRATA.md" />
+ <delete file="${dir}/vendor/paragonie/random_compat/README.md" />
+ <delete file="${dir}/vendor/paragonie/random_compat/SECURITY.md" />
+
+ <delete file="${dir}/vendor/patchwork/utf8/.travis.yml" />
+ <delete file="${dir}/vendor/patchwork/utf8/CHANGELOG.md" />
+ <delete file="${dir}/vendor/patchwork/utf8/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/patchwork/utf8/README.md" />
+
<delete dir="${dir}/vendor/psr/log/Psr/Log/Test" />
<delete file="${dir}/vendor/psr/log/.gitignore" />
<delete file="${dir}/vendor/psr/log/README.md" />
- <delete dir="${dir}/vendor/symfony/config/Symfony/Component/Config/Tests" />
- <delete file="${dir}/vendor/symfony/config/Symfony/Component/Config/.gitignore" />
- <delete file="${dir}/vendor/symfony/config/Symfony/Component/Config/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/config/Symfony/Component/Config/README.md" />
- <delete file="${dir}/vendor/symfony/config/Symfony/Component/Config/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/console/Symfony/Component/Console/Tests" />
- <delete file="${dir}/vendor/symfony/console/Symfony/Component/Console/.gitignore" />
- <delete file="${dir}/vendor/symfony/console/Symfony/Component/Console/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/console/Symfony/Component/Console/README.md" />
- <delete file="${dir}/vendor/symfony/console/Symfony/Component/Console/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/debug/Symfony/Component/Debug/Tests" />
- <delete file="${dir}/vendor/symfony/debug/Symfony/Component/Debug/.gitignore" />
- <delete file="${dir}/vendor/symfony/debug/Symfony/Component/Debug/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/debug/Symfony/Component/Debug/README.md" />
- <delete file="${dir}/vendor/symfony/debug/Symfony/Component/Debug/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests" />
- <delete file="${dir}/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/.gitignore" />
- <delete file="${dir}/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/README.md" />
- <delete file="${dir}/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests" />
- <delete file="${dir}/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/.gitignore" />
- <delete file="${dir}/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/README.md" />
- <delete file="${dir}/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests" />
- <delete file="${dir}/vendor/symfony/filesystem/Symfony/Component/Filesystem/.gitignore" />
- <delete file="${dir}/vendor/symfony/filesystem/Symfony/Component/Filesystem/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/filesystem/Symfony/Component/Filesystem/README.md" />
- <delete file="${dir}/vendor/symfony/filesystem/Symfony/Component/Filesystem/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Tests" />
- <delete file="${dir}/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/.gitignore" />
- <delete file="${dir}/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/README.md" />
- <delete file="${dir}/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Tests" />
- <delete file="${dir}/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/.gitignore" />
- <delete file="${dir}/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/README.md" />
- <delete file="${dir}/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/routing/Symfony/Component/Routing/Tests" />
- <delete file="${dir}/vendor/symfony/routing/Symfony/Component/Routing/.gitignore" />
- <delete file="${dir}/vendor/symfony/routing/Symfony/Component/Routing/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/routing/Symfony/Component/Routing/README.md" />
- <delete file="${dir}/vendor/symfony/routing/Symfony/Component/Routing/phpunit.xml.dist" />
-
- <delete dir="${dir}/vendor/symfony/yaml/Symfony/Component/Yaml/Tests" />
- <delete file="${dir}/vendor/symfony/yaml/Symfony/Component/Yaml/.gitignore" />
- <delete file="${dir}/vendor/symfony/yaml/Symfony/Component/Yaml/CHANGELOG.md" />
- <delete file="${dir}/vendor/symfony/yaml/Symfony/Component/Yaml/README.md" />
- <delete file="${dir}/vendor/symfony/yaml/Symfony/Component/Yaml/phpunit.xml.dist" />
+ <delete dir="${dir}/vendor/react/promise/tests" />
+ <delete file="${dir}/vendor/react/promise/CHANGELOG.md" />
+ <delete file="${dir}/vendor/react/promise/.gitignore" />
+ <delete file="${dir}/vendor/react/promise/phpunit.xml.dist" />
+ <delete file="${dir}/vendor/react/promise/README.md" />
+ <delete file="${dir}/vendor/react/promise/.travis.yml" />
+
+ <delete dir="${dir}/vendor/s9e/text-formatter/.git" />
+
+ <delete dir="${dir}/vendor/symfony/config/.git" />
+ <delete dir="${dir}/vendor/symfony/config/Tests" />
+ <delete file="${dir}/vendor/symfony/config/.gitignore" />
+ <delete file="${dir}/vendor/symfony/config/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/config/README.md" />
+ <delete file="${dir}/vendor/symfony/config/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/console/.git" />
+ <delete dir="${dir}/vendor/symfony/console/Tests" />
+ <delete file="${dir}/vendor/symfony/console/.gitignore" />
+ <delete file="${dir}/vendor/symfony/console/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/console/README.md" />
+ <delete file="${dir}/vendor/symfony/console/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/debug/.git" />
+ <delete dir="${dir}/vendor/symfony/debug/Tests" />
+ <delete file="${dir}/vendor/symfony/debug/.gitignore" />
+ <delete file="${dir}/vendor/symfony/debug/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/debug/README.md" />
+ <delete file="${dir}/vendor/symfony/debug/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/dependency-injection/.git" />
+ <delete dir="${dir}/vendor/symfony/dependency-injection/Tests" />
+ <delete file="${dir}/vendor/symfony/dependency-injection/.gitignore" />
+ <delete file="${dir}/vendor/symfony/dependency-injection/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/dependency-injection/README.md" />
+ <delete file="${dir}/vendor/symfony/dependency-injection/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/event-dispatcher/.git" />
+ <delete dir="${dir}/vendor/symfony/event-dispatcher/Tests" />
+ <delete file="${dir}/vendor/symfony/event-dispatcher/.gitignore" />
+ <delete file="${dir}/vendor/symfony/event-dispatcher/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/event-dispatcher/README.md" />
+ <delete file="${dir}/vendor/symfony/event-dispatcher/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/filesystem/.git" />
+ <delete dir="${dir}/vendor/symfony/filesystem/Tests" />
+ <delete file="${dir}/vendor/symfony/filesystem/.gitignore" />
+ <delete file="${dir}/vendor/symfony/filesystem/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/filesystem/README.md" />
+ <delete file="${dir}/vendor/symfony/filesystem/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/finder/.git" />
+ <delete dir="${dir}/vendor/symfony/finder/Tests" />
+ <delete file="${dir}/vendor/symfony/finder/.gitignore" />
+ <delete file="${dir}/vendor/symfony/finder/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/finder/README.md" />
+ <delete file="${dir}/vendor/symfony/finder/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/http-foundation/.git" />
+ <delete dir="${dir}/vendor/symfony/http-foundation/Tests" />
+ <delete file="${dir}/vendor/symfony/http-foundation/.gitignore" />
+ <delete file="${dir}/vendor/symfony/http-foundation/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/http-foundation/README.md" />
+ <delete file="${dir}/vendor/symfony/http-foundation/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/http-kernel/.git" />
+ <delete dir="${dir}/vendor/symfony/http-kernel/Tests" />
+ <delete file="${dir}/vendor/symfony/http-kernel/.gitignore" />
+ <delete file="${dir}/vendor/symfony/http-kernel/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/http-kernel/README.md" />
+ <delete file="${dir}/vendor/symfony/http-kernel/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/proxy-manager-bridge/.git" />
+ <delete dir="${dir}/vendor/symfony/proxy-manager-bridge/Tests" />
+ <delete file="${dir}/vendor/symfony/proxy-manager-bridge/.gitignore" />
+ <delete file="${dir}/vendor/symfony/proxy-manager-bridge/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/proxy-manager-bridge/README.md" />
+ <delete file="${dir}/vendor/symfony/proxy-manager-bridge/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/routing/.git" />
+ <delete dir="${dir}/vendor/symfony/routing/Tests" />
+ <delete file="${dir}/vendor/symfony/routing/.gitignore" />
+ <delete file="${dir}/vendor/symfony/routing/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/routing/README.md" />
+ <delete file="${dir}/vendor/symfony/routing/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/twig-bridge/.git" />
+ <delete dir="${dir}/vendor/symfony/twig-bridge/Tests" />
+ <delete file="${dir}/vendor/symfony/twig-bridge/.gitignore" />
+ <delete file="${dir}/vendor/symfony/twig-bridge/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/twig-bridge/README.md" />
+ <delete file="${dir}/vendor/symfony/twig-bridge/phpunit.xml.dist" />
+
+ <delete dir="${dir}/vendor/symfony/yaml/.git" />
+ <delete dir="${dir}/vendor/symfony/yaml/Tests" />
+ <delete file="${dir}/vendor/symfony/yaml/.gitignore" />
+ <delete file="${dir}/vendor/symfony/yaml/CHANGELOG.md" />
+ <delete file="${dir}/vendor/symfony/yaml/README.md" />
+ <delete file="${dir}/vendor/symfony/yaml/phpunit.xml.dist" />
<delete dir="${dir}/vendor/twig/twig/doc" />
<delete dir="${dir}/vendor/twig/twig/ext" />
@@ -391,6 +486,15 @@
<delete file="${dir}/vendor/twig/twig/CHANGELOG" />
<delete file="${dir}/vendor/twig/twig/phpunit.xml.dist" />
<delete file="${dir}/vendor/twig/twig/README.rst" />
+
+ <delete file="${dir}/vendor/zendframework/zend-code/CONTRIBUTING.md" />
+ <delete file="${dir}/vendor/zendframework/zend-code/README.md" />
+
+ <delete file="${dir}/vendor/zendframework/zend-eventmanager/CONTRIBUTING.md" />
+ <delete file="${dir}/vendor/zendframework/zend-eventmanager/README.md" />
+
+ <delete file="${dir}/vendor/zendframework/zend-stdlib/CONTRIBUTING.md" />
+ <delete file="${dir}/vendor/zendframework/zend-stdlib/README.md" />
</target>
<target name="clean-diff-dir">
diff --git a/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php b/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php
index 3125e4f05f..b3cdbf7496 100644
--- a/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php
+++ b/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php
@@ -87,6 +87,11 @@ class phpbb_Sniffs_Namespaces_UnusedUseSniff implements PHP_CodeSniffer_Sniff
$old_simple_statement = $simple_statement;
$simple_class_name_start = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($simple_statement + 1));
+
+ if ($simple_class_name_start === false) {
+ continue;
+ }
+
$simple_class_name_end = $phpcsFile->findNext($find, ($simple_statement + 1), null, true);
$simple_class_name = trim($phpcsFile->getTokensAsString($simple_class_name_start, ($simple_class_name_end - $simple_class_name_start)));
diff --git a/build/package.php b/build/package.php
index d168957ca5..178a27faad 100755
--- a/build/package.php
+++ b/build/package.php
@@ -196,9 +196,10 @@ if (sizeof($package->old_packages))
*/
$copy_relative_directories = array(
'config/' => array(
+ 'recursive' => true,
'copied' => false,
'copy' => array(
- 'config/*.yml' => 'config',
+ 'config/*' => 'config',
),
),
);
@@ -256,7 +257,15 @@ if (sizeof($package->old_packages))
}
$source_dir_files = $package->locations['old_versions'] . $package->get('simple_name') . '/' . $source_dir_files;
$destination_dir = $dest_filename_dir . '/install/update/new/' . $destination_dir;
- $package->run_command('cp ' . $source_dir_files . ' ' . $destination_dir);
+
+ if (isset($data['recursive']) && $data['recursive'])
+ {
+ $package->run_command('cp -Rp ' . $source_dir_files . ' ' . $destination_dir);
+ }
+ else
+ {
+ $package->run_command('cp ' . $source_dir_files . ' ' . $destination_dir);
+ }
}
$copy_relative_directories[$reference]['copied'] = true;
}
@@ -272,7 +281,7 @@ if (sizeof($package->old_packages))
'adm/style/admin.css' => 'adm/style',
'adm/style/admin.js' => 'adm/style',
'adm/style/ajax.js' => 'adm/style',
- 'adm/style/install_*' => 'adm/style',
+ 'adm/style/installer_*' => 'adm/style',
'assets/javascript/*' => 'assets/javascript',
);
@@ -470,22 +479,14 @@ chdir($package->get('dest_dir') . '/install');
// $package->run_command('rm -v database_update.php');
$package->run_command('rm -v install_update.php');
-chdir($package->get('dest_dir'));
-$package->run_command('mv -v styles/subsilver2 ../subsilver2');
-$package->run_command('cp -p docs/COPYING ../subsilver2/license.txt');
-
chdir($package->locations['package_dir']);
foreach ($compress_programs as $extension => $compress_command)
{
$package->begin_status('Packaging phpBB for ' . $extension);
$package->run_command('rm -v ./release_files/' . $package->get('release_filename') . ".{$extension}");
- $package->run_command('rm -v ./release_files/subsilver2_' . $package->get('new_version_number') . ".{$extension}");
// Build Package
$package->run_command("$compress_command ./release_files/" . $package->get('release_filename') . '.' . $extension . ' ' . $package->get('package_name'));
-
- // Build subSilver2 Package
- $package->run_command("$compress_command ./release_files/subsilver2_" . $package->get('new_version_number') . '.' . $extension . ' subsilver2');
}
// Microsoft Web PI packaging
diff --git a/phpBB/adm/index.php b/phpBB/adm/index.php
index 519f6c8310..d27f56f28b 100644
--- a/phpBB/adm/index.php
+++ b/phpBB/adm/index.php
@@ -41,6 +41,7 @@ if (!isset($user->data['session_admin']) || !$user->data['session_admin'])
// check specific permissions but this is a catchall
if (!$auth->acl_get('a_'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_ADMIN');
}
@@ -50,8 +51,8 @@ define('IN_ADMIN', true);
// Some oft used variables
$safe_mode = (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) === 'on') ? true : false;
$file_uploads = (@ini_get('file_uploads') == '1' || strtolower(@ini_get('file_uploads')) === 'on') ? true : false;
-$module_id = request_var('i', '');
-$mode = request_var('mode', '');
+$module_id = $request->variable('i', '');
+$mode = $request->variable('mode', '');
// Set custom style for admin area
$template->set_custom_style(array(
diff --git a/phpBB/adm/style/acp_groups.html b/phpBB/adm/style/acp_groups.html
index 1412744cc9..26d7030531 100644
--- a/phpBB/adm/style/acp_groups.html
+++ b/phpBB/adm/style/acp_groups.html
@@ -267,11 +267,12 @@
<!-- EVENT acp_groups_manage_before -->
<table class="table1">
- <col class="col1" /><col class="col1" /><col class="col2" /><col class="col2" /><col class="col2" />
+ <col class="col1" /><col class="col1" /><col class="col1" /><col class="col2" /><col class="col2" /><col class="col2" />
<thead>
<tr>
<th style="width: 50%">{L_GROUP}</th>
<th>{L_TOTAL_MEMBERS}</th>
+ <th>{L_PENDING_MEMBERS}</th>
<th colspan="2">{L_OPTIONS}</th>
<th>{L_ACTION}</th>
</tr>
@@ -281,7 +282,7 @@
<!-- IF groups.S_SPECIAL -->
<!-- IF groups.S_FIRST_ROW -->
<tr>
- <td colspan="5" class="row3">{L_NO_GROUPS_CREATED}</td>
+ <td colspan="6" class="row3">{L_NO_GROUPS_CREATED}</td>
</tr>
<!-- ENDIF -->
</tbody>
@@ -302,11 +303,12 @@
<p>{L_SPECIAL_GROUPS_EXPLAIN}</p>
<table class="table1">
- <col class="col1" /><col class="col1" /><col class="col2" /><col class="col2" /><col class="col2" />
+ <col class="col1" /><col class="col1" /><col class="col1" /><col class="col2" /><col class="col2" />
<thead>
<tr>
<th style="width: 50%">{L_GROUP}</th>
<th>{L_TOTAL_MEMBERS}</th>
+ <th>{L_PENDING_MEMBERS}</th>
<th colspan="2">{L_OPTIONS}</th>
<th>{L_ACTION}</th>
</tr>
@@ -316,6 +318,7 @@
<tr>
<td><strong>{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>
<td style="text-align: center;"><a href="{groups.U_LIST}">{L_MEMBERS}</a></td>
<td style="text-align: center;"><!-- IF not groups.S_GROUP_SPECIAL and groups.U_DELETE --><a href="{groups.U_DELETE}" data-ajax="row_delete">{L_DELETE}</a><!-- ELSE -->{L_DELETE}<!-- ENDIF --></td>
diff --git a/phpBB/adm/style/acp_icons.html b/phpBB/adm/style/acp_icons.html
index e0d2840bb5..5493cbde0a 100644
--- a/phpBB/adm/style/acp_icons.html
+++ b/phpBB/adm/style/acp_icons.html
@@ -89,6 +89,9 @@
<!-- ENDIF -->
<td>{L_WIDTH}</td>
<td>{L_HEIGHT}</td>
+ <!-- IF not S_SMILIES -->
+ <td>{L_ALT_TEXT}</td>
+ <!-- ENDIF -->
<td>{L_DISPLAY_ON_POSTING}</td>
<!-- IF ID or S_ADD -->
<td>{L_ORDER}</td>
@@ -102,7 +105,7 @@
<!-- BEGIN items -->
<tr>
- <td style="text-align: center;"><img src="{items.IMG_SRC}" alt="" title="" /><input type="hidden" name="image[{items.IMG}]" value="1" /></td>
+ <td style="text-align: center;"><img src="{items.IMG_SRC}" alt="{items.TEXT_ALT}" title="{items.TEXT_ALT}" /><input type="hidden" name="image[{items.IMG}]" value="1" /></td>
<td style="vertical-align: top;">[{items.IMG}]</td>
<!-- IF S_SMILIES -->
<td><input class="text post" type="text" name="code[{items.IMG}]" value="{items.CODE}" size="10" maxlength="50" /></td>
@@ -110,6 +113,9 @@
<!-- ENDIF -->
<td><input class="text post" type="number" min="0" max="999" name="width[{items.IMG}]" value="{items.WIDTH}" /></td>
<td><input class="text post" type="number" min="0" max="999" name="height[{items.IMG}]" value="{items.HEIGHT}" /></td>
+ <!-- IF not S_SMILIES -->
+ <td><input class="text post" type="text" name="alt[{items.IMG}]" value="{items.ALT}" size="10" maxlength="50" /></td>
+ <!-- ENDIF -->
<td>
<input type="checkbox" class="radio" name="display_on_posting[{items.IMG}]"{items.POSTING_CHECKED} onclick="toggle_select('{items.A_IMG}', this.checked, '{items.S_ROW_COUNT}');"/>
<!-- IF items.S_ID -->
diff --git a/phpBB/adm/style/acp_permissions.html b/phpBB/adm/style/acp_permissions.html
index a4d33ed78b..7766052c59 100644
--- a/phpBB/adm/style/acp_permissions.html
+++ b/phpBB/adm/style/acp_permissions.html
@@ -329,14 +329,9 @@
<br class="responsive-hide" /><br class="responsive-hide" />
<!-- include tooltip file -->
- <script type="text/javascript" src="style/tooltip.js"></script>
- <script type="text/javascript">
- // <![CDATA[
- window.onload = function(){enable_tooltips_select('set-permissions', '{LA_ROLE_DESCRIPTION}', 'role')};
- // ]]>
- </script>
-
- <form id="set-permissions" method="post" action="{U_ACTION}">
+ <!-- INCLUDEJS tooltip.js -->
+
+ <form id="set-permissions" method="post" action="{U_ACTION}" data-role-description="{L_ROLE_DESCRIPTION}">
{S_HIDDEN_FIELDS}
diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css
index 0c00e5339e..e1668bf70b 100644
--- a/phpBB/adm/style/admin.css
+++ b/phpBB/adm/style/admin.css
@@ -1782,7 +1782,7 @@ li.pagination ul {
/* Action Highlighting
---------------------------------------- */
-.successbox, .errorbox {
+.successbox, .errorbox, .warningbox {
padding: 8px;
margin: 10px 0;
color: #FFFFFF;
@@ -1806,6 +1806,10 @@ li.pagination ul {
background-color: #BC2A4D;
}
+.warningbox {
+ background-color: #fca600;
+}
+
.successbox h3, .errorbox h3 {
color: #FFFFFF;
margin: 0 0 0.5em;
@@ -1832,10 +1836,33 @@ li.pagination ul {
font-weight: bold;
}
+#log-container {
+ display: none;
+ max-height: 300px;
+ padding: 8px;
+ margin: 10px 0;
+ clear: both;
+ overflow-y: auto;
+ background-color: #FFFFFF;
+}
+
+#log-container.show_log_container {
+ display: block;
+ border: 1px solid #DBD7D1;
+}
+
+.log {
+ font-size: 0.8em;
+}
+
.notice {
background-color: #62A5CC;
}
+.download-box {
+ margin: 10px 0 10px 0;
+}
+
/* Special cases for the error page */
#errorpage #page-header a {
font-weight: bold;
@@ -1864,6 +1891,7 @@ li.pagination ul {
color: #000;
text-align: center;
border: 1px solid #AAA;
+ opacity: .95;
}
.tooltip span.top {
@@ -2441,6 +2469,39 @@ fieldset.permissions .padding {
display: none !important;
}
+.roles-options > .dropdown {
+ left: auto;
+ top: 3.2em;
+ width: 250px;
+}
+
+.roles-options {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ width: 250px;
+}
+
+.roles-options > span {
+ border: 1px solid #DEDEDE;
+ border-radius: 3px;
+ padding: 4px;
+ width: 250px;
+ display: none;
+ background: url('../images/arrow_down.gif') no-repeat 245px .7em;
+}
+
+.roles-options li {
+ list-style: none;
+}
+
+.roles-highlight {
+ background-color: #1e90ff;
+ color: #fff;
+}
+
/* Classes for additional tasks
---------------------------------------- */
@@ -2489,3 +2550,36 @@ fieldset.permissions .padding {
clear: both;
display: block;
}
+
+#progress-bar {
+ position: relative;
+ width: 90%;
+ text-align: center;
+ height: 25px;
+ margin: 20px auto;
+ border: 1px solid #cecece;
+}
+
+#progress-bar #progress-bar-text {
+ position: absolute;
+ top: 0;
+ width: 100%;
+ color: #000;
+}
+
+#progress-bar #progress-bar-filler {
+ display: block;
+ position: relative;
+ top: 0;
+ left: 0;
+ background-color: #3c84ad;
+ width: 0;
+ height: 25px;
+ overflow: hidden;
+ color: #fff;
+}
+
+#progress-bar p {
+ line-height: 25px;
+ font-weight: bold;
+}
diff --git a/phpBB/adm/style/captcha_recaptcha.html b/phpBB/adm/style/captcha_recaptcha.html
index d3038fd714..3f61c76cb1 100644
--- a/phpBB/adm/style/captcha_recaptcha.html
+++ b/phpBB/adm/style/captcha_recaptcha.html
@@ -1,32 +1,12 @@
<!-- IF S_RECAPTCHA_AVAILABLE -->
<dl>
<dd>
- <script type="text/javascript">
- // <![CDATA[
- var RecaptchaOptions = {
- lang : '{LA_RECAPTCHA_LANG}',
- theme : 'clean'
- };
- // ]]>
- </script>
- <script type="text/javascript" src="{RECAPTCHA_SERVER}/challenge?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}"></script>
- <script type="text/javascript">
- // <![CDATA[
- <!-- IF S_CONTENT_DIRECTION eq 'rtl' -->
- document.getElementById('recaptcha_table').style.direction = 'ltr';
- <!-- ENDIF -->
- // ]]>
- </script>
-
-
<noscript>
- <div>
- <object data="{RECAPTCHA_SERVER}/noscript?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}" type="text/html" height="300" width="500"></object><br />
- <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
- <input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
- </div>
+ <div>{L_RECAPTCHA_NOSCRIPT}</div>
</noscript>
+ <script src="{RECAPTCHA_SERVER}.js?hl={LA_RECAPTCHA_LANG}" async defer></script>
+ <div class="g-recaptcha" data-sitekey="{RECAPTCHA_PUBKEY}"></div>
</dd>
</dl>
<!-- ELSE -->
diff --git a/phpBB/adm/style/install_convert.html b/phpBB/adm/style/install_convert.html
deleted file mode 100644
index 7e22404f56..0000000000
--- a/phpBB/adm/style/install_convert.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<!-- IF S_NOT_INSTALLED -->
-
- <h1>{TITLE}</h1>
-
- <p>{BODY}</p>
-
-<!-- ELSE -->
-
- <form id="install_convert" method="post" action="{U_ACTION}">
-
- <h1>{TITLE}</h1>
-
- <p>{BODY}</p>
-
- <!-- IF S_ERROR_BOX -->
- <div class="errorbox">
- <h3>{ERROR_TITLE}</h3>
- <p>{ERROR_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <!-- IF S_LIST -->
- <table class="table1">
- <caption>{L_AVAILABLE_CONVERTORS}</caption>
- <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" />
- <thead>
- <tr>
- <th>{L_SOFTWARE}</th>
- <th>{L_VERSION}</th>
- <th>{L_AUTHOR}</th>
- <th>{L_OPTIONS}</th>
- </tr>
- </thead>
- <tbody>
- <!-- IF .convertors -->
- <!-- BEGIN convertors -->
- <tr>
- <td>{convertors.SOFTWARE}</td>
- <td>{convertors.VERSION}</td>
- <td>{convertors.AUTHOR}</td>
- <td><a href="{convertors.U_CONVERT}">{L_CONVERT}</a></td>
- </tr>
- <!-- END convertors -->
- <!-- ELSE -->
- <tr>
- <td>{L_NO_CONVERTORS}</td>
- <td>-</td>
- <td>-</td>
- <td>-</td>
- </tr>
- <!-- ENDIF -->
- </tbody>
- </table>
- <!-- ENDIF -->
-
- <!-- IF S_CONTINUE -->
- </form>
-
- <fieldset class="submit-buttons">
- <form method="post" action="{U_NEW_ACTION}">
- <input class="button1" type="submit" name="submit_new" value="{L_NEW}" />
- </form>
- <br />
- <form method="post" action="{U_CONTINUE_ACTION}">
- <input class="button1" type="submit" name="submit_cont" value="{L_CONTINUE}" />
- </form>
- </fieldset>
-
- <form method="post" action="{U_ACTION}">
- <!-- ENDIF -->
-
- <!-- IF .checks -->
- <fieldset>
-
- <!-- BEGIN checks -->
- <!-- IF checks.S_LEGEND -->
- <!-- IF not checks.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{checks.LEGEND}</legend>
- <!-- IF checks.LEGEND_EXPLAIN --><p>{checks.LEGEND_EXPLAIN}</p><!-- ENDIF -->
- <!-- ELSE -->
-
- <dl>
- <dt><label>{checks.TITLE}{L_COLON}</label><!-- IF checks.S_EXPLAIN --><br /><span class="explain">{checks.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{checks.RESULT}</dd>
- </dl>
- <!-- ENDIF -->
- <!-- END checks -->
-
- </fieldset>
- <!-- ENDIF -->
-
- <!-- IF .options -->
- <fieldset>
-
- <!-- BEGIN options -->
- <!-- IF options.S_LEGEND -->
- <!-- IF not options.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{options.LEGEND}</legend>
- <!-- ELSE -->
-
- <dl>
- <dt><label for="{options.KEY}">{options.TITLE}{L_COLON}</label><!-- IF options.S_EXPLAIN --><br /><span class="explain">{options.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{options.CONTENT}</dd>
- </dl>
-
- <!-- ENDIF -->
- <!-- END options -->
-
- </fieldset>
- <!-- ENDIF -->
-
- <!-- IF L_SUBMIT -->
- <!-- IF L_MESSAGE --><p>{L_MESSAGE}</p><!-- ENDIF -->
-
- <fieldset class="submit-buttons">
- {S_HIDDEN}
- <!-- IF L_SUBMIT --><input class="button1<!-- IF S_REFRESH --> disabled<!-- ENDIF -->" type="submit" id="submit" <!-- IF S_REFRESH -->disabled="disabled" <!-- ELSE --> onclick="this.className = 'button1 disabled';" onsubmit="this.disabled = 'disabled';" <!-- ENDIF -->name="submit" value="{L_SUBMIT}" /><!-- ENDIF -->
- </fieldset>
- <!-- ENDIF -->
-
- </form>
-<!-- ENDIF -->
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_error.html b/phpBB/adm/style/install_error.html
deleted file mode 100644
index 3f7c8b9ed4..0000000000
--- a/phpBB/adm/style/install_error.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<div class="errorbox">
- <h3>{MESSAGE_TITLE}</h3>
- <p>{MESSAGE_TEXT}</p>
-</div>
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html
deleted file mode 100644
index 8e7599dc3f..0000000000
--- a/phpBB/adm/style/install_footer.html
+++ /dev/null
@@ -1,21 +0,0 @@
- </div>
- </div><!-- /#main -->
- </div>
- </div><!-- /#acp -->
- </div>
-
- <div id="page-footer">
- <div class="copyright">
- Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited
- </div>
- </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">\x3C/script>');</script><!-- ENDIF -->
-<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script>
-<!-- INCLUDEJS admin.js -->
-{$SCRIPTS}
-
-</body>
-</html>
diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html
deleted file mode 100644
index cfafe7917f..0000000000
--- a/phpBB/adm/style/install_header.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8">
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-<!-- IF META -->{META}<!-- ENDIF -->
-<title>{PAGE_TITLE}</title>
-
-<link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
-</head>
-
-<body class="{S_CONTENT_DIRECTION} nojs">
-<div id="wrap">
- <div id="page-header">
- <h1>{L_INSTALL_PANEL}</h1>
- <p id="skip"><a href="#acp">{L_SKIP}</a></p>
- <!-- IF S_LANG_SELECT -->
- <form method="post" action="#">
- <fieldset class="nobg">
- <label for="language">{L_SELECT_LANG}{L_COLON}</label>
- {S_LANG_SELECT}
- <input class="button1" type="submit" id="change_lang" name="change_lang" value="{L_CHANGE}" />
- </fieldset>
- </form>
- <!-- ENDIF -->
- </div>
-
- <div id="page-body">
- <div id="tabs">
- <ul>
- <!-- BEGIN t_block1 -->
- <li class="tab<!-- IF t_block1.S_SELECTED --> activetab<!-- ENDIF -->"><a href="{t_block1.U_TITLE}">{t_block1.L_TITLE}</a></li>
- <!-- END t_block1 -->
- </ul>
- </div>
-
- <div id="acp">
- <div id="content">
- <div id="menu">
- <div class="menu-block no-header">
- <ul>
- <!-- BEGIN l_block1 -->
- <li<!-- IF l_block1.S_SELECTED --> id="activemenu"<!-- ENDIF -->><a href="{l_block1.U_TITLE}"><span>{l_block1.L_TITLE}</span></a></li>
- <!-- END l_block1 -->
- <!-- BEGIN l_block2 -->
- <li<!-- IF l_block2.S_SELECTED --> id="activemenu"<!-- ENDIF -->><span<!-- IF l_block2.S_COMPLETE --> class="completed"<!-- ENDIF -->>{l_block2.L_TITLE}</span></li>
- <!-- END l_block2 -->
- </ul>
- </div>
- </div>
-
- <div id="main" class="install-body">
- <div class="main">
diff --git a/phpBB/adm/style/install_install.html b/phpBB/adm/style/install_install.html
deleted file mode 100644
index 1a809a3588..0000000000
--- a/phpBB/adm/style/install_install.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<form id="install_install" method="post" action="{U_ACTION}" onsubmit="submit.disabled = 'disabled';">
-
-<!-- IF TITLE --><h1>{TITLE}</h1><!-- ENDIF -->
-<!-- IF BODY --><p>{BODY}</p><!-- ENDIF -->
-
-<!-- IF .checks -->
- <fieldset>
-
- <!-- BEGIN checks -->
- <!-- IF checks.S_LEGEND -->
- <!-- IF not checks.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{checks.LEGEND}</legend>
- <!-- IF checks.LEGEND_EXPLAIN --><p>{checks.LEGEND_EXPLAIN}</p><!-- ENDIF -->
- <!-- ELSE -->
-
- <dl>
- <dt>{checks.TITLE}{L_COLON}<!-- IF checks.S_EXPLAIN --><br /><span class="explain">{checks.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{checks.RESULT}</dd>
- </dl>
- <!-- ENDIF -->
- <!-- END checks -->
-
- </fieldset>
-<!-- ENDIF -->
-
-<!-- IF .options -->
- <fieldset>
-
- <!-- BEGIN options -->
- <!-- IF options.S_LEGEND -->
- <!-- IF not options.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{options.LEGEND}</legend>
- <!-- ELSE -->
-
- <dl>
- <dt><label for="{options.KEY}">{options.TITLE}{L_COLON}</label><!-- IF options.S_EXPLAIN --><br /><span class="explain">{options.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{options.CONTENT}</dd>
- </dl>
-
- <!-- ENDIF -->
- <!-- END options -->
-
- </fieldset>
-<!-- ENDIF -->
-
-<!-- IF S_SHOW_DOWNLOAD -->
- <h1>{L_DL_CONFIG}</h1>
- <p>{L_DL_CONFIG_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <legend>{L_DL_CONFIG}</legend>
- {S_HIDDEN}
- <input class="button1" type="submit" id="dlconfig" name="dlconfig" value="{L_DL_DOWNLOAD}" />&nbsp;<input class="button1" type="submit" id="dldone" name="dldone" value="{L_DL_DONE}" />
- </fieldset>
-<!-- ENDIF -->
-
-<!-- IF L_SUBMIT -->
- <fieldset class="submit-buttons">
- <legend>{L_SUBMIT}</legend>
- {S_HIDDEN}
- <!-- IF L_SUBMIT --><input class="button1" type="submit" id="submit" onclick="this.className = 'button1 disabled';" name="submit" value="{L_SUBMIT}" /><!-- ENDIF -->
- </fieldset>
-<!-- ENDIF -->
-
-</form>
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_main.html b/phpBB/adm/style/install_main.html
deleted file mode 100644
index 73e73ad578..0000000000
--- a/phpBB/adm/style/install_main.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
- <h1>{TITLE}</h1>
- <p>{BODY}</p>
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_update.html b/phpBB/adm/style/install_update.html
deleted file mode 100644
index 898233f72d..0000000000
--- a/phpBB/adm/style/install_update.html
+++ /dev/null
@@ -1,491 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
- function popup(url, width, height, name)
- {
- if (!name)
- {
- name = '_popup';
- }
-
- window.open(url.replace(/&amp;/g, '&'), name, 'height=' + height + ',resizable=yes,scrollbars=yes, width=' + width);
- return false;
- }
-
- function diff_popup(url)
- {
- popup(url, 950, 600, '_diff');
- return false;
- }
-// ]]>
-</script>
-
-<!-- IF S_ERROR -->
- <div class="errorbox" style="margin-top: 0;">
- <h3>{L_NOTICE}</h3>
- <p>{ERROR_MSG}</p>
- </div>
-<!-- ENDIF -->
-
-<!-- IF S_IN_PROGRESS -->
-
- <div class="successbox" style="margin-top: 0;">
- <h3>{L_IN_PROGRESS}</h3>
- <p>{L_IN_PROGRESS_EXPLAIN}</p>
- </div>
-
-<!-- ELSEIF S_INTRO -->
-
- <!-- IF S_WARNING -->
- <div class="successbox" style="margin-top: 0;">
- <h3>{L_NOTICE}</h3>
- <p>{WARNING_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <div class="errorbox" style="margin-top: 0;">
- <h3>{L_NOTICE}</h3>
- <p>{L_BACKUP_NOTICE}</p>
- </div>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <h1>{L_UPDATE_INSTALLATION}</h1>
- <p>{L_UPDATE_INSTALLATION_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="submit" value="{L_NEXT_STEP}" />
- </fieldset>
-
- </form>
-
-<!-- ELSEIF S_UPLOAD_SUCCESS -->
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <h1>{L_UPDATE_SUCCESS}</h1>
- <p>{L_UPDATE_SUCCESS_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="check_again" value="{L_CONTINUE_UPDATE}" />
- </fieldset>
-
- </form>
-
-<!-- ENDIF -->
-
-<!-- IF S_VERSION_CHECK -->
-
- <h1>{L_VERSION_CHECK}</h1>
-
- <p>{L_VERSION_CHECK_EXPLAIN}</p>
-
- <!-- IF S_UP_TO_DATE -->
- <div class="successbox">
- <p>{L_VERSION_UP_TO_DATE}</p>
- </div>
- <!-- ELSE -->
- <div class="errorbox">
- <p>{L_VERSION_NOT_UP_TO_DATE}</p>
- </div>
- <!-- ENDIF -->
-
- <fieldset>
- <legend></legend>
- <dl>
- <dt><label>{L_CURRENT_VERSION}</label></dt>
- <dd><strong>{CURRENT_VERSION}</strong></dd>
- </dl>
- <dl>
- <dt><label>{L_LATEST_VERSION}</label></dt>
- <dd><strong>{LATEST_VERSION}</strong></dd>
- </dl>
- <!-- IF PACKAGE_VERSION and not S_UP_TO_DATE -->
- <dl>
- <dt><label>{L_PACKAGE_UPDATES_TO}</label></dt>
- <dd><strong>{PACKAGE_VERSION}</strong></dd>
- </dl>
- <!-- ENDIF -->
- </fieldset>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <fieldset class="submit-buttons">
- <p>{L_CHECK_FILES_EXPLAIN}</p>
- <input class="button1" type="submit" name="submit" value="{L_CHECK_FILES}" />
- </fieldset>
-
- </form>
-
-<!-- ELSEIF S_DB_UPDATE -->
-
- <!-- IF not S_DB_UPDATE_FINISHED -->
-
- <h1>{L_PERFORM_DATABASE_UPDATE}</h1>
-
- <p>
- {L_PERFORM_DATABASE_UPDATE_EXPLAIN}<br />
- </p>
-
- <br /><br />
-
- <form id="install_dbupdate" method="post" action="{U_DB_UPDATE_ACTION}">
-
- <fieldset class="submit-buttons">
- <a href="{U_DB_UPDATE}" class="button1">{L_RUN_DATABASE_SCRIPT}</a>
-
- <!-- input class="button1" type="submit" name="db_update" value="{L_CHECK_UPDATE_DATABASE}" / -->
- </fieldset>
-
- </form>
-
- <!-- ELSE -->
-
- <div class="successbox">
- <h3>{L_UPDATE_SUCCESS}</h3>
- <p>{L_EVERYTHING_UP_TO_DATE}</p>
- </div>
-
- <!-- ENDIF -->
-
-<!-- ELSEIF S_FILE_CHECK -->
-
- <!-- IF S_ALL_UP_TO_DATE -->
-
- <h1>{L_UPDATE_FILE_SUCCESS}</h1>
- <p>{L_ALL_FILES_UP_TO_DATE}</p>
-
- <p>{L_UPDATE_DATABASE_EXPLAIN}</p>
-
- <form id="install_dbupdate" method="post" action="{U_DB_UPDATE_ACTION}">
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="db_update" value="{L_UPDATE_DATABASE}" />
- </fieldset>
-
- </form>
-
- <!-- ELSE -->
- <h1>{L_COLLECTED_INFORMATION}</h1>
-
- <p>{L_COLLECTED_INFORMATION_EXPLAIN}</p>
-
- <!-- IF S_NO_UPDATE_FILES -->
- <div class="errorbox">
- <h3>{L_NO_UPDATE_FILES}</h3>
-
- <p>{L_NO_UPDATE_FILES_EXPLAIN}</p><br />
-
- <strong>{NO_UPDATE_FILES}</strong>
-
- </div>
- <!-- ENDIF -->
-
- <form id="install_update" method="post" action="{U_UPDATE_ACTION}">
-
- <!-- IF .deleted -->
- <h2>{L_FILES_DELETED}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('deleted', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_DELETED_EXPLAIN}</p>
-
- <fieldset id="deleted">
- <legend><img src="{T_IMAGE_PATH}icon_delete.gif" alt="{L_STATUS_DELETED}" /></legend>
- <!-- BEGIN deleted -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF deleted.DIR_PART -->{deleted.DIR_PART}<br /><!-- ENDIF -->{deleted.FILE_PART}</strong></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}: 60%;">
- <!-- IF not deleted.S_BINARY -->[<a href="{deleted.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{deleted.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- </dl>
- <!-- END deleted -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .conflict -->
- <h2>{L_FILES_CONFLICT}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('conflict', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_CONFLICT_EXPLAIN}</p>
-
- <!-- BEGIN conflict -->
- <fieldset id="conflict">
- <legend><img src="{T_IMAGE_PATH}file_conflict.gif" alt="{L_STATUS_CONFLICT}" /></legend>
- <dl>
- <dt style="width: 60%;"><strong><!-- IF conflict.DIR_PART -->{conflict.DIR_PART}<br /><!-- ENDIF -->{conflict.FILE_PART}</strong>
- <!-- IF conflict.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{conflict.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- <!-- IF conflict.NUM_CONFLICTS --><br /><span>{L_NUM_CONFLICTS}{L_COLON} {conflict.NUM_CONFLICTS}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">
- <!-- IF not conflict.S_BINARY -->[<a href="{conflict.U_SHOW_DIFF}">{L_DOWNLOAD_CONFLICTS}</a>]<br />{L_DOWNLOAD_CONFLICTS_EXPLAIN}
- <!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- <!-- IF conflict.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{conflict.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- IF conflict.S_BINARY -->
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="1" checked="checked" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">&nbsp;</dd>
- </dl>
- <!-- ELSE -->
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="3" checked="checked" /> {L_MERGE_NEW_FILE_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_NEW_FILE}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_MODIFIED}</a>]</dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="4" /> {L_MERGE_MOD_FILE_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_MOD_FILE}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_MODIFIED}</a>]</dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="1" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_NO_MERGE_NEW}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]</dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="2" /> {L_MERGE_NO_MERGE_MOD_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_NO_MERGE_MOD}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]</dd>
- </dl>
- <!-- ENDIF -->
- </fieldset>
- <!-- END conflict -->
-
- <!-- ENDIF -->
-
- <!-- IF .new_conflict -->
- <h2>{L_FILES_NEW_CONFLICT}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('new_conflict', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_NEW_CONFLICT_EXPLAIN}</p>
-
- <fieldset id="new_conflict">
- <legend><img src="{T_IMAGE_PATH}file_new_conflict.gif" alt="{L_STATUS_NEW_CONFLICT}" /></legend>
- <!-- BEGIN new_conflict -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF new_conflict.DIR_PART -->{new_conflict.DIR_PART}<br /><!-- ENDIF -->{new_conflict.FILE_PART}</strong>
- <!-- IF new_conflict.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{new_conflict.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">
- <!-- IF not new_conflict.S_BINARY -->[<a href="{new_conflict.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new_conflict.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- <!-- IF new_conflict.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{new_conflict.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- END new_conflict -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .modified -->
- <h2>{L_FILES_MODIFIED}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('modified', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_MODIFIED_EXPLAIN}</p>
-
- <!-- BEGIN modified -->
- <fieldset id="modified">
- <legend><img src="{T_IMAGE_PATH}file_modified.gif" alt="{L_STATUS_MODIFIED}" /></legend>
- <dl>
- <dt style="width: 60%;"><strong><!-- IF modified.DIR_PART -->{modified.DIR_PART}<br /><!-- ENDIF -->{modified.FILE_PART}</strong>
- <!-- IF modified.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{modified.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">&nbsp;</dd>
- <!-- IF modified.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{modified.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="0" checked="checked" /> {L_MERGE_MODIFICATIONS_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{modified.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="1" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_VIEW_NO_MERGE_NEW}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]<!-- ELSE -->&nbsp;<!-- ENDIF --></dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="2" /> {L_MERGE_NO_MERGE_MOD_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_VIEW_NO_MERGE_MOD}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]<!-- ELSE -->&nbsp;<!-- ENDIF --></dd>
- </dl>
- </fieldset>
- <!-- END modified -->
-
- <!-- ENDIF -->
-
- <!-- IF .new -->
- <h2>{L_FILES_NEW}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('new_files', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_NEW_EXPLAIN}</p>
-
- <fieldset id="new_files" style="display: none;">
- <legend><img src="{T_IMAGE_PATH}file_new.gif" alt="{L_STATUS_NEW}" /></legend>
- <!-- BEGIN new -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF new.DIR_PART -->{new.DIR_PART}<br /><!-- ENDIF -->{new.FILE_PART}</strong>
- <!-- IF new.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{new.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">
- <!-- IF not new.S_BINARY -->[<a href="{new.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- <!-- IF new.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{new.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- END new -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .not_modified -->
- <h2>{L_FILES_NOT_MODIFIED}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('not_modified', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_NOT_MODIFIED_EXPLAIN}</p>
-
- <fieldset id="not_modified" style="display: none;">
- <legend><img src="{T_IMAGE_PATH}file_not_modified.gif" alt="{L_STATUS_NOT_MODIFIED}" /></legend>
- <!-- BEGIN not_modified -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF not_modified.DIR_PART -->{not_modified.DIR_PART}<br /><!-- ENDIF -->{not_modified.FILE_PART}</strong>
- <!-- IF not_modified.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{not_modified.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not not_modified.S_BINARY -->[<a href="{not_modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{not_modified.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
- <!-- IF not_modified.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{not_modified.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- END not_modified -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .up_to_date -->
- <h2>{L_FILES_UP_TO_DATE}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('up_to_date', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_UP_TO_DATE_EXPLAIN}</p>
-
- <fieldset id="up_to_date" style="display: none;">
- <legend><img src="{T_IMAGE_PATH}file_up_to_date.gif" alt="{L_STATUS_UP_TO_DATE}" /></legend>
- <!-- BEGIN up_to_date -->
- <dl>
- <dd class="full" style="text-align: {S_CONTENT_FLOW_BEGIN};"><strong>{up_to_date.FILENAME}</strong></dd>
- </dl>
- <!-- END up_to_date -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <br />
-
- <fieldset class="quick">
- <input class="button1" type="submit" name="check_again" value="{L_CHECK_FILES_AGAIN}" />
- </fieldset>
-
- <br />
-
- <h1>{L_UPDATE_METHOD}</h1>
-
- <p>{L_UPDATE_METHOD_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="ftp_upload" value="{L_FTP_UPDATE_METHOD}" />&nbsp; &nbsp;<input class="button1" type="submit" name="download" value="{L_DOWNLOAD_UPDATE_METHOD_BUTTON}" />
- </fieldset>
-
- </form>
-
- <!-- ENDIF -->
-
-<!-- ELSEIF S_DOWNLOAD_FILES -->
-
- <h1>{L_DOWNLOAD_UPDATE_METHOD}</h1>
-
- <p>{L_DOWNLOAD_UPDATE_METHOD_EXPLAIN}</p>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <fieldset>
- <legend>{L_SELECT_DOWNLOAD_FORMAT}</legend>
- <dl>
- <dt><label for="use_method">{L_DOWNLOAD_AS}{L_COLON}</label></dt>
- <dd>{RADIO_BUTTONS}</dd>
- </dl>
- </fieldset>
-
- <fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}
- <input type="submit" class="button2" value="{L_CONTINUE_UPDATE}" name="check_again" />&nbsp; &nbsp;<input type="submit" class="button1" value="{L_DOWNLOAD}" name="download" />
- </fieldset>
-
- </form>
-
- <br /><br />
-
- <p>{L_MAPPING_FILE_STRUCTURE}</p>
-
- <table class="table1">
- <col class="row1" /><col class="row2" /><col class="row1" />
- <thead>
- <tr>
- <th style="width: 49%">{L_ARCHIVE_FILE}</th>
- <th style="width: 2%">&nbsp;</th>
- <th style="width: 49%">{L_DESTINATION}</th>
- </tr>
- </thead>
- <tbody>
- <!-- BEGIN location -->
- <tr>
- <td>{location.SOURCE}</td>
- <td><strong>&raquo;</strong></td>
- <td>{location.DESTINATION}</td>
- </tr>
- <!-- END location -->
- </tbody>
- </table>
-
-<!-- ELSEIF S_FTP_UPLOAD -->
-
- <h1>{L_SELECT_FTP_SETTINGS}</h1>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <!-- IF S_CONNECTION_SUCCESS -->
- <div class="successbox">
- <p>{L_CONNECTION_SUCCESS}</p>
- </div>
- <!-- ELSEIF S_CONNECTION_FAILED -->
- <div class="successbox">
- <p>{L_TRY_DOWNLOAD_METHOD}</p>
-
- <fieldset class="quick">
- <input class="button1" type="submit" name="download" value="{L_TRY_DOWNLOAD_METHOD_BUTTON}" />
- </fieldset>
- </div>
-
- <div class="errorbox">
- <p>{L_CONNECTION_FAILED}<br />{ERROR_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <fieldset>
- <legend>{L_FTP_SETTINGS}</legend>
- <dl>
- <dt><label>{L_UPLOAD_METHOD}{L_COLON}</label></dt>
- <dd><strong>{UPLOAD_METHOD}</strong></dd>
- </dl>
- <!-- BEGIN data -->
- <dl>
- <dt><label for="{data.DATA}">{data.NAME}{L_COLON}</label><br /><span>{data.EXPLAIN}</span></dt>
- <dd><input type="<!-- IF data.DATA == 'password' -->password<!-- ELSE -->text<!-- ENDIF -->" id="{data.DATA}" name="{data.DATA}" value="{data.DEFAULT}" /></dd>
- </dl>
- <!-- END data -->
- </fieldset>
-
- <fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}
- <input class="button2" type="submit" name="check_again" value="{L_BACK}" />
- <input class="button1" type="submit" name="test_connection" value="{L_TEST_CONNECTION}" />
- <input class="button1" type="submit" name="submit" value="{L_UPDATE_FILES}" />
- </fieldset>
-
- </form>
-
-<!-- ENDIF -->
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_update_diff.html b/phpBB/adm/style/install_update_diff.html
deleted file mode 100644
index 324dc50d05..0000000000
--- a/phpBB/adm/style/install_update_diff.html
+++ /dev/null
@@ -1,255 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8">
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-<!-- IF META -->{META}<!-- ENDIF -->
-<title>{PAGE_TITLE}</title>
-
-<link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
-
-<script type="text/javascript">
-// <![CDATA[
-function resize_panel()
-{
- var block = document.getElementById('diff_content');
- var height;
-
- if (window.innerHeight)
- {
- height = window.innerHeight - 200;
- block.style.height = height + 'px';
- }
- else
- {
- //whatever IE needs to do this
- }
-}
-
-window.onresize = resize_panel;
-
-// ]]>
-</script>
-
-<style type="text/css">
-/* <![CDATA[ */
-
-#main, .rtl #main {
- font-size: 1em;
- line-height: 0.7em;
- margin: 0;
- padding: 0;
- width: 99%;
-}
-
-#diff_content {
- padding: 30px 10px 10px;
- overflow: hidden;
-}
-
-<!-- IF DIFF_MODE neq 'side_by_side' and DIFF_MODE neq 'raw' -->
-div#codepanel {
- width: 100%;
-}
-<!-- ELSE -->
-div#codepanel {
- background-color: #eee;
-}
-<!-- ENDIF -->
-
-<!-- IF DIFF_MODE neq 'unified' and DIFF_MODE neq 'side_by_side' -->
-div#diff_content pre {
- overflow: auto;
- height: 414px;
- width: 100% !important;
-}
-<!-- ENDIF -->
-
-<!-- IF not S_DIFF_NEW_FILE -->
-/**
-* Unified Diff
-*/
-.file {
- line-height: .7em;
- overflow: auto;
- height: 414px;
-}
-
-.diff {
- margin: 0;
-}
-
-.added {
- background-color: #dfd;
-}
-
-.removed {
- background-color: #fdd;
-}
-
-.info {
- color: #888;
-}
-
-.context {
- background-color: #eee;
-}
-
-/**
-* Inline Diff
-*/
-.ins {
- background-color: #dfd;
- text-decoration: underline;
-}
-
-.del {
- background-color: #fdd;
- text-decoration: line-through;
-}
-
-/**
-* Column Diff
-*/
-table.hrdiff {
- margin: 0 0 8px 5px;
- width: 100%;
- overflow: hidden;
- border-bottom: 1px solid #999;
- table-layout: fixed;
- background: transparent;
-}
-
-table.hrdiff th {
- text-align: left;
- width: 50%;
- color: #333;
- font-family: Verdana,Helvetica,sans-serif;
- font-size: 11px;
- border-bottom: 1px solid #999;
- border-right: 1px solid #999;
- background: #D9D9D9;
-}
-
-table.hrdiff thead th {
- font-weight: bold;
- font-size: 110%;
- padding: 2px;
-}
-
-table.hrdiff tr:first-child th {
- border-top: none;
-}
-
-table.hrdiff tbody th {
- font-size: 80%;
- border-top: 1px solid #999;
-}
-
-table.hrdiff tbody td {
- border-right: 1px solid #999;
-}
-
-table.hrdiff td pre {
- font-family: "Consolas", monospace;
- font-size: 1.1em;
- white-space: pre-wrap; /* css-3 */
- word-wrap: break-word; /* Internet Explorer 5.5+ */
-}
-
-table.hrdiff .unmodified {
- background: transparent;
-}
-
-table.hrdiff .added {
- background: #9f9;
-}
-
-table.hrdiff .added_empty {
- background: #cfc;
-}
-
-table.hrdiff .modified {
- background: #fd9;
-}
-
-table.hrdiff .removed {
- background: #f99;
-}
-
-table.hrdiff .removed_empty {
- background: #fcc;
-}
-
-table.hrdiff caption {
- caption-side: top;
- text-align: left;
- margin: 0 0 8px 5px;
- font-size: 90%;
- font-weight: bold;
- padding: 5px;
-}
-
-table.hrdiff caption span {
- height: 10px;
- width: 10px;
- line-height: 10px;
- letter-spacing: 10px;
- border: 1px solid #000;
- margin-left: 0.5em;
- vertical-align: baseline;
-}
-
-<!-- ENDIF -->
-
-/* ]]> */
-</style>
-
-</head>
-
-<!-- IF DIFF_MODE neq 'side_by_side' and DIFF_MODE neq 'raw' -->
-<body onload="resize_panel();">
-<!-- ELSE -->
-<body>
-<!-- ENDIF -->
-
-<div id="wrap">
- <div id="page-header">
-<!-- IF S_DIFF_NEW_FILE -->
-
- <h1>{L_VIEWING_FILE_CONTENTS}</h1>
-<!-- ELSE -->
- <h1>{L_VIEWING_FILE_DIFF}</h1>
-<!-- ENDIF -->
-<!-- IF not S_DIFF_NEW_FILE -->
- <p id="skip"><a href="#acp">{L_SKIP}</a></p>
- <form method="post" action="#">
- <fieldset class="quick">
- <label for="diff_mode">{L_SELECT_DIFF_MODE}{L_COLON}</label>
- <select name="diff_mode" id="diff_mode">{S_DIFF_MODE_OPTIONS}</select>
-
- <input class="button1" type="submit" id="submit" name="submit" value="{L_CHANGE}" />
- </fieldset>
- </form>
-<!-- ENDIF -->
-<!-- IF S_DIFF_CONFLICT_FILE -->
- <div style="float: {S_CONTENT_FLOW_BEGIN};"><strong>{L_NUM_CONFLICTS}{L_COLON} {NUM_CONFLICTS}</strong></div>
- <br style="clear: both;" />
-<!-- ENDIF -->
- </div>
-
- <div id="page-body">
- <div id="acp">
- <div id="codepanel">
- <div id="diff_content">
- <div id="main">
- {DIFF_CONTENT}
- </div>
- </div>
- </div>
- </div>
- </div>
-
-
-<!-- INCLUDE simple_footer.html -->
diff --git a/phpBB/adm/style/installer_convert.html b/phpBB/adm/style/installer_convert.html
new file mode 100644
index 0000000000..aa16542b6b
--- /dev/null
+++ b/phpBB/adm/style/installer_convert.html
@@ -0,0 +1,87 @@
+<!-- INCLUDE installer_header.html -->
+<!-- IF TITLE --><h1>{TITLE}</h1><!-- ENDIF -->
+<!-- IF S_ERROR_BOX -->
+<div class="errorbox">
+ <h3>{ERROR_TITLE}</h3>
+ <p>{ERROR_MSG}</p>
+</div>
+<!-- ENDIF -->
+<!-- IF .errors -->
+<div id="error-container">
+<!-- BEGIN errors -->
+ <strong>{errors.TITLE}</strong>
+ <!-- IF errors.DESCRIPTION --><p>{errors.DESCRIPTION}</p><!-- ENDIF -->
+<!-- END errors -->
+</div>
+<!-- ENDIF -->
+<!-- IF BODY --><p>{BODY}</p><!-- ENDIF -->
+<!-- IF CONTENT -->{CONTENT}<!-- ENDIF -->
+<!-- IF S_CONV_IN_PROGRESS -->
+<p class="centered-text"><a href="{U_ACTION}" class="button1<!-- IF S_REFRESH --> disabled<!-- ENDIF -->"<!-- IF S_REFRESH --> onclick="return false;"<!-- ENDIF -->>{L_SUBMIT}</a></p>
+<!-- ENDIF -->
+<!-- IF S_CONTINUE -->
+<div id="download-wrapper" class="download-box">
+ <p class="centered-text">
+ <a href="{U_NEW_ACTION}" class="button1">{L_CONVERT_NEW_CONVERSION}</a>
+ <a href="{U_CONTINUE_ACTION}" class="button1">{L_CONTINUE_OLD_CONVERSION}</a>
+ </p>
+</div>
+<!-- ENDIF -->
+<!-- IF S_LIST -->
+<table class="table1">
+ <caption>{L_AVAILABLE_CONVERTORS}</caption>
+ <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" />
+ <thead>
+ <tr>
+ <th>{L_SOFTWARE}</th>
+ <th>{L_VERSION}</th>
+ <th>{L_AUTHOR}</th>
+ <th>{L_CONVERT_OPTIONS}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <!-- IF .convertors -->
+ <!-- BEGIN convertors -->
+ <tr>
+ <td>{convertors.SOFTWARE}</td>
+ <td>{convertors.VERSION}</td>
+ <td>{convertors.AUTHOR}</td>
+ <td><a href="{convertors.U_CONVERT}">{L_CONVERT}</a></td>
+ </tr>
+ <!-- END convertors -->
+ <!-- ELSE -->
+ <tr>
+ <td>{L_NO_CONVERTORS}</td>
+ <td>-</td>
+ <td>-</td>
+ <td>-</td>
+ </tr>
+ <!-- ENDIF -->
+ </tbody>
+</table>
+<!-- ENDIF -->
+<!-- IF .checks -->
+<fieldset>
+
+ <!-- BEGIN checks -->
+ <!-- IF checks.S_LEGEND -->
+ <!-- IF not checks.S_FIRST_ROW -->
+</fieldset>
+
+<fieldset>
+ <!-- ENDIF -->
+ <legend>{checks.LEGEND}</legend>
+ <!-- IF checks.LEGEND_EXPLAIN --><p>{checks.LEGEND_EXPLAIN}</p><!-- ENDIF -->
+ <!-- ELSE -->
+
+ <dl>
+ <dt><label>{checks.TITLE}{L_COLON}</label><!-- IF checks.S_EXPLAIN --><br /><span class="explain">{checks.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
+ <dd>{checks.RESULT}</dd>
+ </dl>
+ <!-- ENDIF -->
+ <!-- END checks -->
+
+</fieldset>
+<!-- ENDIF -->
+<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/installer.js -->
+<!-- INCLUDE installer_footer.html -->
diff --git a/phpBB/adm/style/installer_footer.html b/phpBB/adm/style/installer_footer.html
new file mode 100644
index 0000000000..fefa8f6d3f
--- /dev/null
+++ b/phpBB/adm/style/installer_footer.html
@@ -0,0 +1,30 @@
+ </div>
+ </div><!-- /#main -->
+ </div>
+ </div><!-- /#acp -->
+ </div>
+
+ <div id="page-footer">
+ <div class="copyright">
+ Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited
+ </div>
+ </div>
+</div>
+
+<script type="text/javascript">
+<!--
+installLang = {
+ title: '{LA_TIMEOUT_DETECTED_TITLE}',
+ msg: '{LA_TIMEOUT_DETECTED_MESSAGE}'
+};
+//-->
+</script>
+
+<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">\x3C/script>');</script><!-- ENDIF -->
+<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script>
+<!-- INCLUDEJS admin.js -->
+{$SCRIPTS}
+
+</body>
+</html>
diff --git a/phpBB/adm/style/installer_form.html b/phpBB/adm/style/installer_form.html
new file mode 100644
index 0000000000..cc5b041fa1
--- /dev/null
+++ b/phpBB/adm/style/installer_form.html
@@ -0,0 +1,56 @@
+<form id="<!-- IF FORM_ID -->{FORM_ID}<!-- ELSE -->install_install<!-- ENDIF -->" method="POST" action="{U_ACTION}">
+<!-- IF .options -->
+<!-- IF S_NOT_ONLY_BUTTON_FORM -->
+<fieldset>
+<!-- ENDIF -->
+
+ <!-- BEGIN options -->
+ <!-- IF options.S_LEGEND -->
+ <!-- IF not options.S_FIRST_ROW -->
+ </fieldset>
+
+ <fieldset>
+ <!-- ENDIF -->
+ <legend>{options.LEGEND}</legend>
+ <!-- ELSE -->
+ <dl>
+ <dt><label for="{options.KEY}">{options.TITLE}{L_COLON}</label><!-- IF options.S_EXPLAIN --><br /><span class="explain">{options.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
+ <dd>
+ <!-- IF options.TYPE == 'text' -->
+ <input type="text" name="{options.KEY}" value="{options.DEFAULT}" />
+ <!-- ENDIF -->
+ <!-- IF options.TYPE == 'email' -->
+ <input type="email" name="{options.KEY}" value="{options.DEFAULT}" />
+ <!-- ENDIF -->
+ <!-- IF options.TYPE == 'password' -->
+ <input type="password" name="{options.KEY}" />
+ <!-- ENDIF -->
+ <!-- IF options.TYPE == 'select' -->
+ <select name="{options.KEY}">
+ <!-- BEGIN options.OPTIONS -->
+ <option value="{options.OPTIONS.value}"<!-- IF options.OPTIONS.selected --> selected<!-- ENDIF -->>{options.OPTIONS.label}</option>
+ <!-- END options.OPTIONS -->
+ </select>
+ <!-- ENDIF -->
+ <!-- IF options.TYPE == 'radio' -->
+ <!-- BEGIN options.OPTIONS -->
+ <input type="radio" name="{options.KEY}" value="{options.OPTIONS.value}" <!-- IF options.OPTIONS.selected -->checked<!-- ENDIF --> /> {options.OPTIONS.label}
+ <!-- END options.OPTIONS -->
+ <!-- ENDIF -->
+ </dd>
+ </dl>
+ <!-- ENDIF-->
+ <!-- END options -->
+<!-- IF S_NOT_ONLY_BUTTON_FORM -->
+</fieldset>
+<!-- ENDIF -->
+<!-- ENDIF -->
+<!-- IF .submit_buttons -->
+<fieldset class="submit-buttons">
+ <legend>{L_SUBMIT}</legend>
+ <!-- BEGIN submit_buttons -->
+ <input class="button1" type="submit" name="{submit_buttons.KEY}" value="{submit_buttons.TITLE}" />
+ <!-- END submit_buttons -->
+</fieldset>
+<!-- ENDIF -->
+</form>
diff --git a/phpBB/adm/style/installer_header.html b/phpBB/adm/style/installer_header.html
new file mode 100644
index 0000000000..704db9e174
--- /dev/null
+++ b/phpBB/adm/style/installer_header.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <!-- IF META -->{META}<!-- ENDIF -->
+ <title>{PAGE_TITLE}</title>
+
+ <link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
+</head>
+
+<body class="{S_CONTENT_DIRECTION} nojs">
+<div id="wrap">
+ <div id="page-header">
+ <h1>{L_INSTALL_PANEL}</h1>
+ <p id="skip"><a href="#acp">{L_SKIP}</a></p>
+ <!-- IF S_LANG_SELECT -->
+ <form method="post" action="#" id="language_selector">
+ <fieldset class="nobg">
+ <label for="language">{L_SELECT_LANG}{L_COLON}</label>
+ <select id="language" name="language">
+ <!-- BEGIN language_select_item -->
+ <option value="{language_select_item.VALUE}"<!-- IF language_select_item.SELECTED --> selected="selected"<!-- ENDIF -->>{language_select_item.NAME}</option>
+ <!-- END language_select_item -->
+ </select>
+ <input class="button1" type="submit" id="change_lang" name="change_lang" value="{L_CHANGE}" />
+ </fieldset>
+ </form>
+ <!-- ENDIF -->
+ </div>
+
+ <div id="page-body">
+ <div id="tabs">
+ <ul>
+ <!-- BEGIN t_block1 -->
+ <li class="tab<!-- IF t_block1.S_SELECTED --> activetab<!-- ENDIF -->"><a href="{t_block1.U_TITLE}">{t_block1.L_TITLE}</a></li>
+ <!-- END t_block1 -->
+ </ul>
+ </div>
+
+ <div id="acp">
+ <div id="content">
+ <div id="menu">
+ <div class="menu-block no-header">
+ <ul>
+ <!-- BEGIN l_block1 -->
+ <li<!-- IF l_block1.S_SELECTED --> id="activemenu"<!-- ENDIF -->><a href="{l_block1.U_TITLE}"><span>{l_block1.L_TITLE}</span></a></li>
+ <!-- END l_block1 -->
+ <!-- BEGIN l_block2 -->
+ <li<!-- IF l_block2.S_SELECTED --> id="activemenu"<!-- ENDIF -->><span<!-- IF l_block2.S_COMPLETE --> class="completed"<!-- ENDIF --> id="installer-stage-{l_block2.STAGE_NAME}">{l_block2.L_TITLE}</span></li>
+ <!-- END l_block2 -->
+ </ul>
+ </div>
+ </div>
+
+ <div id="main" class="install-body">
+ <div class="main">
diff --git a/phpBB/adm/style/installer_install.html b/phpBB/adm/style/installer_install.html
new file mode 100644
index 0000000000..53a91f2700
--- /dev/null
+++ b/phpBB/adm/style/installer_install.html
@@ -0,0 +1,13 @@
+<!-- INCLUDE installer_header.html -->
+<h1>{TITLE}</h1>
+<p>{CONTENT}</p>
+<!-- IF SHOW_INSTALL_START_FORM -->
+<form id="install_install" method="post" action="{U_ACTION}">
+ <fieldset class="submit-buttons">
+ <legend>{L_SUBMIT}</legend>
+ <input class="button1" name="install" type="submit" value="{L_INSTALL}" />
+ </fieldset>
+</form>
+<!-- ENDIF -->
+<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/installer.js -->
+<!-- INCLUDE installer_footer.html -->
diff --git a/phpBB/adm/style/installer_main.html b/phpBB/adm/style/installer_main.html
new file mode 100644
index 0000000000..f14fe4da70
--- /dev/null
+++ b/phpBB/adm/style/installer_main.html
@@ -0,0 +1,6 @@
+<!-- INCLUDE installer_header.html -->
+
+ <h1>{TITLE}</h1>
+ <p>{BODY}</p>
+
+<!-- INCLUDE installer_footer.html -->
diff --git a/phpBB/adm/style/installer_update.html b/phpBB/adm/style/installer_update.html
new file mode 100644
index 0000000000..48cc07f5d6
--- /dev/null
+++ b/phpBB/adm/style/installer_update.html
@@ -0,0 +1,13 @@
+<!-- INCLUDE installer_header.html -->
+<h1>{TITLE}</h1>
+<p>{CONTENT}</p>
+<!-- IF SHOW_INSTALL_START_FORM -->
+<form id="install_install" method="post" action="{U_ACTION}">
+ <fieldset class="submit-buttons">
+ <legend>{L_SUBMIT}</legend>
+ <input class="button1" name="update" type="submit" value="{L_UPDATE}" />
+ </fieldset>
+</form>
+<!-- ENDIF -->
+<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/installer.js -->
+<!-- INCLUDE installer_footer.html -->
diff --git a/phpBB/adm/style/installer_update_file_status.html b/phpBB/adm/style/installer_update_file_status.html
new file mode 100644
index 0000000000..a27bfa6a44
--- /dev/null
+++ b/phpBB/adm/style/installer_update_file_status.html
@@ -0,0 +1,80 @@
+<!-- IF .deleted -->
+<h2>{L_FILES_DELETED}</h2>
+<div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('deleted', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
+<p>{L_FILES_DELETED_EXPLAIN}</p>
+
+<fieldset id="deleted">
+ <legend><img src="{T_IMAGE_PATH}/icon_delete.gif" alt="{L_STATUS_DELETED}" /></legend>
+ <!-- BEGIN deleted -->
+ <dl>
+ <dt style="width: 100%;"><!-- IF deleted.DIR_PART -->{deleted.DIR_PART}<!-- ENDIF --><strong>{deleted.FILE_PART}</strong></dt>
+ </dl>
+ <!-- END deleted -->
+</fieldset>
+
+<!-- ENDIF -->
+
+<!-- IF .conflict -->
+<h2>{L_FILES_CONFLICT}</h2>
+<div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('conflict', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
+<p>{L_FILES_CONFLICT_EXPLAIN}</p>
+
+<fieldset id="conflict">
+ <legend><img src="{T_IMAGE_PATH}/file_conflict.gif" alt="{L_STATUS_CONFLICT}" /></legend>
+ <!-- BEGIN conflict -->
+ <dl>
+ <dt style="width: 100%;"><!-- IF conflict.DIR_PART -->{conflict.DIR_PART}<!-- ENDIF --><strong>{conflict.FILE_PART}</strong></dt>
+ </dl>
+ <!-- END conflict -->
+</fieldset>
+
+<!-- ENDIF -->
+
+<!-- IF .modified -->
+<h2>{L_FILES_MODIFIED}</h2>
+<div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('modified', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
+<p>{L_FILES_MODIFIED_EXPLAIN}</p>
+
+<fieldset id="modified">
+ <legend><img src="{T_IMAGE_PATH}/file_modified.gif" alt="{L_STATUS_MODIFIED}" /></legend>
+ <!-- BEGIN modified -->
+ <dl>
+ <dt style="width: 100%;"><!-- IF modified.DIR_PART -->{modified.DIR_PART}<!-- ENDIF --><strong>{modified.FILE_PART}</strong></dt>
+ </dl>
+ <!-- END modified -->
+</fieldset>
+
+<!-- ENDIF -->
+
+<!-- IF .new -->
+<h2>{L_FILES_NEW}</h2>
+<div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('new_files', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
+<p>{L_FILES_NEW_EXPLAIN}</p>
+
+<fieldset id="new_files" style="display: none;">
+ <legend><img src="{T_IMAGE_PATH}/file_new.gif" alt="{L_STATUS_NEW}" /></legend>
+ <!-- BEGIN new -->
+ <dl>
+ <dt style="width: 100%;"><!-- IF new.DIR_PART -->{new.DIR_PART}<!-- ENDIF --><strong>{new.FILE_PART}</strong>
+ </dt>
+ </dl>
+ <!-- END new -->
+</fieldset>
+
+<!-- ENDIF -->
+
+<!-- IF .not_modified -->
+<h2>{L_FILES_NOT_MODIFIED}</h2>
+<div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('not_modified', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
+<p>{L_FILES_NOT_MODIFIED_EXPLAIN}</p>
+
+<fieldset id="not_modified" style="display: none;">
+ <legend><img src="{T_IMAGE_PATH}/file_not_modified.gif" alt="{L_STATUS_NOT_MODIFIED}" /></legend>
+ <!-- BEGIN not_modified -->
+ <dl>
+ <dt style="width: 100%;"><!-- IF not_modified.DIR_PART -->{not_modified.DIR_PART}<!-- ENDIF --><strong>{not_modified.FILE_PART}</strong></dt>
+ </dl>
+ <!-- END not_modified -->
+</fieldset>
+
+<!-- ENDIF -->
diff --git a/phpBB/adm/style/overall_header.html b/phpBB/adm/style/overall_header.html
index d399c680ee..f227f729fd 100644
--- a/phpBB/adm/style/overall_header.html
+++ b/phpBB/adm/style/overall_header.html
@@ -50,7 +50,7 @@ function marklist(id, name, state)
}
var rb = parent.getElementsByTagName('input');
-
+
for (var r = 0; r < rb.length; r++)
{
if (rb[r].name.substr(0, name.length) == name)
@@ -104,7 +104,7 @@ function popup(url, width, height, name)
<p><a href="{U_ADM_INDEX}">{L_ADMIN_INDEX}</a> &bull; <a href="{U_INDEX}">{L_FORUM_INDEX}</a></p>
<p id="skip"><a href="#acp">{L_SKIP}</a></p>
</div>
-
+
<div id="page-body">
<div id="tabs">
<ul>
@@ -121,7 +121,7 @@ function popup(url, width, height, name)
<!-- DEFINE $LI_USED = 0 -->
<!-- BEGIN l_block1 -->
<!-- IF l_block1.S_SELECTED -->
-
+
<!-- BEGIN l_block2 -->
<!-- IF .l_block1.l_block2.l_block3 -->
<!-- IF $LI_USED --></ul></div><!-- ENDIF -->
@@ -130,13 +130,13 @@ function popup(url, width, height, name)
<ul>
<!-- DEFINE $LI_USED = 1 -->
<!-- ENDIF -->
-
+
<!-- BEGIN l_block3 -->
<li<!-- IF l_block1.l_block2.l_block3.S_SELECTED --> id="activemenu"<!-- ENDIF -->><a href="{l_block1.l_block2.l_block3.U_TITLE}"><span>{l_block1.l_block2.l_block3.L_TITLE}</span></a></li>
<!-- DEFINE $LI_USED = 1 -->
<!-- END l_block3 -->
<!-- END l_block2 -->
-
+
<!-- ENDIF -->
<!-- END l_block1 -->
<!-- IF $LI_USED -->
@@ -144,6 +144,13 @@ function popup(url, width, height, name)
</div>
<!-- ENDIF -->
</div>
-
+
<div id="main">
<div class="main">
+ {% if CONTAINER_EXCEPTION !== false %}
+ <div class="errorbox">
+ <p>{{ lang('CONTAINER_EXCEPTION') }}</p><br />
+ <p>{{ lang('EXCEPTION') }}{{ lang('COLON') }} {{ CONTAINER_EXCEPTION.getMessage() }}</p>
+ <pre>{{ CONTAINER_EXCEPTION.getTraceAsString() }}</pre>
+ </div>
+ {% endif %}
diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html
index 7b5c071693..017d29d832 100644
--- a/phpBB/adm/style/permission_mask.html
+++ b/phpBB/adm/style/permission_mask.html
@@ -39,11 +39,24 @@
</div>
<dl class="permissions-simple">
<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.S_ROLE_OPTIONS -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 20%"><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}]" onchange="set_role_settings(this.options[selectedIndex].value, 'advanced{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}'); init_colours('{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}')">{p_mask.f_mask.S_ROLE_OPTIONS}</select></dd>
- <!-- ELSE -->
+ {% 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}">
+ <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">
+ <ul class="dropdown-contents" id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" >
+ {% for role in p_mask.f_mask.role_options %}
+ <li data-id="{{ role.ID }}" data-target-id="advanced{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" data-title="{{ role.TITLE }}"{% if role.SELECTED == true %} data-selected="{{ role.SELECTED }}"{% endif %}>{{ role.ROLE_NAME }}</li>
+ {% endfor %}
+ </ul>
+ </div>
+ <input type="hidden" data-name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]"{% if p_mask.f_mask.S_ROLE_ID %}value="{{ p_mask.f_mask.S_ROLE_ID }}"{% endif %} />
+ </div>
+ </dd>
+ {% else %}
<dd>{L_NO_ROLE_AVAILABLE}</dd>
- <!-- ENDIF -->
+ {% endif %}
</dl>
<!-- ENDIF -->
diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js
index 3a89008706..65773ae14f 100644
--- a/phpBB/adm/style/tooltip.js
+++ b/phpBB/adm/style/tooltip.js
@@ -10,206 +10,207 @@ phpBB Development Team:
- further adjustements
*/
-var head_text, tooltip_mode;
+(function($) { // Avoid conflicts with other libraries
-/**
-* Enable tooltip replacements for links
-*/
-function enable_tooltips_link(id, headline, sub_id) {
- var links, i, hold;
-
- head_text = headline;
-
- if (!document.getElementById || !document.getElementsByTagName) {
- return;
- }
-
- hold = document.createElement('span');
- hold.id = '_tooltip_container';
- hold.setAttribute('id', '_tooltip_container');
- hold.style.position = 'absolute';
-
- document.getElementsByTagName('body')[0].appendChild(hold);
-
- if (id === null) {
- links = document.getElementsByTagName('a');
- } else {
- links = document.getElementById(id).getElementsByTagName('a');
- }
-
- for (i = 0; i < links.length; i++) {
- if (sub_id) {
- if (links[i].id.substr(0, sub_id.length) === sub_id) {
- prepare(links[i]);
- }
- } else {
- prepare(links[i]);
- }
- }
+'use strict';
- tooltip_mode = 'link';
-}
+var tooltips = [];
/**
-* Enable tooltip replacements for selects
+ * Enable tooltip replacements for selects
+ * @param {string} id ID tag of select
+ * @param {string} headline Text that should appear on top of tooltip
+ * @param {string} [subId] Sub ID that should only be using tooltips (optional)
*/
-function enable_tooltips_select(id, headline, sub_id) {
- var links, i, hold;
-
- head_text = headline;
-
- if (!document.getElementById || !document.getElementsByTagName) {
- return;
- }
+phpbb.enableTooltipsSelect = function (id, headline, subId) {
+ var $links, hold;
- hold = document.createElement('span');
- hold.id = '_tooltip_container';
- hold.setAttribute('id', '_tooltip_container');
- hold.style.position = 'absolute';
+ hold = $('<span />', {
+ id: '_tooltip_container',
+ css: {
+ position: 'absolute'
+ }
+ });
- document.getElementsByTagName('body')[0].appendChild(hold);
+ $('body').append(hold);
- if (id === null) {
- links = document.getElementsByTagName('option');
+ if (!id) {
+ $links = $('.roles-options li');
} else {
- links = document.getElementById(id).getElementsByTagName('option');
+ $links = $('.roles-options li', '#' + id);
}
- for (i = 0; i < links.length; i++) {
- if (sub_id) {
- if (links[i].parentNode.id.substr(0, sub_id.length) === sub_id) {
- prepare(links[i]);
+ $links.each(function () {
+ var $this = $(this);
+
+ if (subId) {
+ if ($this.parent().attr('id').substr(0, subId.length) === subId) {
+ phpbb.prepareTooltips($this, headline);
}
} else {
- prepare(links[i]);
+ phpbb.prepareTooltips($this, headline);
}
- }
-
- tooltip_mode = 'select';
-}
+ });
+};
/**
-* Prepare elements to replace
+ * Prepare elements to replace
+ *
+ * @param {jQuery} $element Element to prepare for tooltips
+ * @param {string} headText Text heading to display
*/
-function prepare(element) {
- var tooltip, text, desc, title;
+phpbb.prepareTooltips = function ($element, headText) {
+ var $tooltip, text, $desc, $title;
- text = element.getAttribute('title');
+ text = $element.attr('data-title');
if (text === null || text.length === 0) {
return;
}
- element.removeAttribute('title');
- tooltip = create_element('span', 'tooltip');
-
- title = create_element('span', 'top');
- title.appendChild(document.createTextNode(head_text));
- tooltip.appendChild(title);
-
- desc = create_element('span', 'bottom');
- desc.innerHTML = text;
- tooltip.appendChild(desc);
+ $title = $('<span />', {
+ class: 'top',
+ css: {
+ display: 'block'
+ }
+ })
+ .append(document.createTextNode(headText));
+
+ $desc = $('<span />', {
+ class: 'bottom',
+ html: text,
+ css: {
+ display: 'block'
+ }
+ });
- set_opacity(tooltip);
+ $tooltip = $('<span />', {
+ class: 'tooltip',
+ css: {
+ display: 'block'
+ }
+ })
+ .append($title)
+ .append($desc);
- element.tooltip = tooltip;
- element.onmouseover = show_tooltip;
- element.onmouseout = hide_tooltip;
-
- if (tooltip_mode === 'link') {
- element.onmousemove = locate;
- }
-}
+ tooltips[$element.attr('data-id')] = $tooltip;
+ $element.on('mouseover', phpbb.showTooltip);
+ $element.on('mouseout', phpbb.hideTooltip);
+};
/**
-* Show tooltip
+ * Show tooltip
+ *
+ * @param {object} $element Element passed by .on()
*/
-function show_tooltip(e) {
- document.getElementById('_tooltip_container').appendChild(this.tooltip);
- locate(this);
-}
+phpbb.showTooltip = function ($element) {
+ var $this = $($element.target);
+ $('#_tooltip_container').append(tooltips[$this.attr('data-id')]);
+ phpbb.positionTooltip($this);
+};
/**
-* Hide tooltip
+ * Hide tooltip
*/
-function hide_tooltip(e) {
+phpbb.hideTooltip = function () {
var d = document.getElementById('_tooltip_container');
if (d.childNodes.length > 0) {
d.removeChild(d.firstChild);
}
-}
+};
/**
-* Set opacity on tooltip element
+ * Correct positioning of tooltip container
+ *
+ * @param {jQuery} $element Tooltip element that should be positioned
*/
-function set_opacity(element) {
- element.style.filter = 'alpha(opacity:95)';
- element.style.KHTMLOpacity = '0.95';
- element.style.MozOpacity = '0.95';
- element.style.opacity = '0.95';
-}
+phpbb.positionTooltip = function ($element) {
+ var offset;
-/**
-* Create new element
-*/
-function create_element(tag, c) {
- var x = document.createElement(tag);
- x.className = c;
- x.style.display = 'block';
- return x;
-}
+ $element = $element.parent();
+ offset = $element.offset();
-/**
-* Correct positioning of tooltip container
-*/
-function locate(e) {
- var posx = 0;
- var posy = 0;
-
- e = e.parentNode;
+ $('#_tooltip_container').css({
+ top: offset.top + 30,
+ left: offset.left - 205
+ });
+};
- if (e.offsetParent) {
- for (posx = 0, posy = 0; e.offsetParent; e = e.offsetParent) {
- posx += e.offsetLeft;
- posy += e.offsetTop;
+/**
+ * Prepare roles drop down select
+ */
+phpbb.prepareRolesDropdown = function () {
+ var $options = $('.roles-options li');
+
+ // Display span and hide select
+ $('.roles-options > span').css('display', 'block');
+ $('.roles-options > select').hide();
+ $('.roles-options > input[type=hidden]').each(function () {
+ var $this = $(this);
+
+ if ($this.attr('data-name') && !$this.attr('name')) {
+ $this.attr('name', $this.attr('data-name'));
}
- } else {
- posx = e.offsetLeft;
- posy = e.offsetTop;
- }
-
- if (tooltip_mode === 'link') {
- document.getElementById('_tooltip_container').style.top=(posy+20) + 'px';
- document.getElementById('_tooltip_container').style.left=(posx-20) + 'px';
- } else {
- document.getElementById('_tooltip_container').style.top=(posy+30) + 'px';
- document.getElementById('_tooltip_container').style.left=(posx-205) + 'px';
- }
-
-/*
- if (e == null)
- {
- e = window.event;
- }
+ });
+
+ // Prepare highlighting of select options and settings update
+ $options.each(function () {
+ var $this = $(this);
+ var $rolesOptions = $this.closest('.roles-options');
+ var $span = $rolesOptions.children('span');
+
+ // Correctly show selected option
+ if (typeof $this.attr('data-selected') !== 'undefined') {
+ $rolesOptions
+ .children('span')
+ .text($this.text())
+ .attr('data-default', $this.text())
+ .attr('data-default-val', $this.attr('data-id'));
+
+ // Save default text of drop down if there is no default set yet
+ if (typeof $span.attr('data-default') === 'undefined') {
+ $span.attr('data-default', $span.text());
+ }
- if (e.pageX || e.pageY)
- {
- posx = e.pageX;
- posy = e.pageY;
- }
- else if (e.clientX || e.clientY)
- {
- if (document.documentElement.scrollTop)
- {
- posx = e.clientX+document.documentElement.scrollLeft;
- posy = e.clientY+document.documentElement.scrollTop;
- }
- else
- {
- posx = e.clientX+document.body.scrollLeft;
- posy = e.clientY+document.body.scrollTop;
+ // Prepare resetting drop down on form reset
+ $this.closest('form').on('reset', function () {
+ $span.text($span.attr('data-default'));
+ $rolesOptions.children('input[type=hidden]')
+ .val($span.attr('data-default-val'));
+ });
}
- }
-*/
-}
+
+ $this.on('mouseover', function () {
+ var $this = $(this);
+ $options.removeClass('roles-highlight');
+ $this.addClass('roles-highlight');
+ }).on('click', function () {
+ var $this = $(this);
+ var $rolesOptions = $this.closest('.roles-options');
+
+ // Update settings
+ set_role_settings($this.attr('data-id'), $this.attr('data-target-id'));
+ init_colours($this.attr('data-target-id').replace('advanced', ''));
+
+ // Set selected setting
+ $rolesOptions.children('span')
+ .text($this.text());
+ $rolesOptions.children('input[type=hidden]')
+ .val($this.attr('data-id'));
+
+ // Trigger hiding of selection options
+ $('body').trigger('click');
+ });
+ });
+};
+
+// Run onload functions for RolesDropdown and tooltips
+$(function() {
+ // Enable tooltips
+ phpbb.enableTooltipsSelect('set-permissions', $('#set-permissions').attr('data-role-description'), 'role');
+
+ // Prepare dropdown
+ phpbb.prepareRolesDropdown();
+});
+
+})(jQuery); // Avoid conflicts with other libraries
diff --git a/phpBB/app.php b/phpBB/app.php
index d9250adc75..4873fb10c3 100644
--- a/phpBB/app.php
+++ b/phpBB/app.php
@@ -21,14 +21,16 @@ define('IN_PHPBB', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
-include($phpbb_root_path . 'includes/functions_url_matcher.' . $phpEx);
// Start session management
$user->session_begin();
$auth->acl($user->data);
$user->setup('app');
+/* @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */
$http_kernel = $phpbb_container->get('http_kernel');
+
+/* @var $symfony_request \phpbb\symfony_request */
$symfony_request = $phpbb_container->get('symfony_request');
$response = $http_kernel->handle($symfony_request);
$response->send();
diff --git a/phpBB/assets/css/font-awesome.min.css b/phpBB/assets/css/font-awesome.min.css
new file mode 100644
index 0000000000..9c24364d62
--- /dev/null
+++ b/phpBB/assets/css/font-awesome.min.css
@@ -0,0 +1,4 @@
+/*!
+ * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} \ No newline at end of file
diff --git a/phpBB/assets/fonts/FontAwesome.otf b/phpBB/assets/fonts/FontAwesome.otf
new file mode 100644
index 0000000000..681bdd4d4c
--- /dev/null
+++ b/phpBB/assets/fonts/FontAwesome.otf
Binary files differ
diff --git a/phpBB/assets/fonts/fontawesome-webfont.eot b/phpBB/assets/fonts/fontawesome-webfont.eot
new file mode 100644
index 0000000000..a30335d748
--- /dev/null
+++ b/phpBB/assets/fonts/fontawesome-webfont.eot
Binary files differ
diff --git a/phpBB/assets/fonts/fontawesome-webfont.svg b/phpBB/assets/fonts/fontawesome-webfont.svg
new file mode 100644
index 0000000000..6fd19abcb9
--- /dev/null
+++ b/phpBB/assets/fonts/fontawesome-webfont.svg
@@ -0,0 +1,640 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
+<metadata></metadata>
+<defs>
+<font id="fontawesomeregular" horiz-adv-x="1536" >
+<font-face units-per-em="1792" ascent="1536" descent="-256" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode=" " horiz-adv-x="448" />
+<glyph unicode="&#x09;" horiz-adv-x="448" />
+<glyph unicode="&#xa0;" horiz-adv-x="448" />
+<glyph unicode="&#xa8;" horiz-adv-x="1792" />
+<glyph unicode="&#xa9;" horiz-adv-x="1792" />
+<glyph unicode="&#xae;" horiz-adv-x="1792" />
+<glyph unicode="&#xb4;" horiz-adv-x="1792" />
+<glyph unicode="&#xc6;" horiz-adv-x="1792" />
+<glyph unicode="&#xd8;" horiz-adv-x="1792" />
+<glyph unicode="&#x2000;" horiz-adv-x="768" />
+<glyph unicode="&#x2001;" horiz-adv-x="1537" />
+<glyph unicode="&#x2002;" horiz-adv-x="768" />
+<glyph unicode="&#x2003;" horiz-adv-x="1537" />
+<glyph unicode="&#x2004;" horiz-adv-x="512" />
+<glyph unicode="&#x2005;" horiz-adv-x="384" />
+<glyph unicode="&#x2006;" horiz-adv-x="256" />
+<glyph unicode="&#x2007;" horiz-adv-x="256" />
+<glyph unicode="&#x2008;" horiz-adv-x="192" />
+<glyph unicode="&#x2009;" horiz-adv-x="307" />
+<glyph unicode="&#x200a;" horiz-adv-x="85" />
+<glyph unicode="&#x202f;" horiz-adv-x="307" />
+<glyph unicode="&#x205f;" horiz-adv-x="384" />
+<glyph unicode="&#x2122;" horiz-adv-x="1792" />
+<glyph unicode="&#x221e;" horiz-adv-x="1792" />
+<glyph unicode="&#x2260;" horiz-adv-x="1792" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
+<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
+<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+<glyph unicode="&#xf016;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z " />
+<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
+<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
+<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
+<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
+<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57 q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -4 -0.5 -13t-0.5 -13q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5 q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
+<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142 q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5 t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68.5 -0.5t67.5 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5 t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
+<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q6 2 81.5 21.5t111.5 37.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5 q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
+<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2 t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5 q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
+<glyph unicode="&#xf035;" d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1 t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5 t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49 t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
+<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" />
+<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
+<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
+<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
+<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
+<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
+<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
+<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+<glyph unicode="&#xf053;" horiz-adv-x="1280" d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf054;" horiz-adv-x="1280" d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
+<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
+<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
+<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
+<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
+<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf077;" horiz-adv-x="1792" d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
+<glyph unicode="&#xf078;" horiz-adv-x="1792" d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
+<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
+<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45 t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf080;" horiz-adv-x="2048" d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
+<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
+<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
+<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf092;" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
+<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
+<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
+<glyph unicode="&#xf09a;" horiz-adv-x="1024" d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
+<glyph unicode="&#xf09b;" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" />
+<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
+<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+<glyph unicode="&#xf0a2;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5 t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
+<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
+<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
+<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " />
+<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
+<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
+<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
+<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
+<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
+<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
+<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" />
+<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
+<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
+<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" />
+<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf0d4;" d="M829 318q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5zM755 863q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5 t-57.5 96.5t-17.5 106q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107zM861 1120l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95 q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83zM1152 672h128v64h-128v128h-64v-128 h-128v-64h128v-160h64v160zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M735 740q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4 q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65t-59.5 -61.5t-24.5 -66zM589 836q38 0 78 16.5t66 43.5q53 57 53 159q0 58 -17 125t-48.5 129.5 t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26zM591 -37q58 0 111.5 13t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2 q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5zM1401 839h213v-108h-213v-219h-105v219h-212v108h212v217h105v-217z" />
+<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
+<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
+<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
+<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
+<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
+<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
+<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" />
+<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
+<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
+<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
+<glyph unicode="&#xf0f3;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5 t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0f6;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704 q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
+<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" />
+<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
+<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
+<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
+<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
+<glyph unicode="&#xf110;" horiz-adv-x="1792" d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5 q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
+<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
+<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " />
+<glyph unicode="&#xf116;" horiz-adv-x="1792" />
+<glyph unicode="&#xf117;" horiz-adv-x="1792" />
+<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
+<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" />
+<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
+<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
+<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
+<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
+<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
+<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
+<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
+<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" />
+<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" />
+<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
+<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
+<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
+<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
+<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
+<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
+<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
+<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
+<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
+<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" />
+<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" />
+<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
+<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
+<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
+<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
+<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
+<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
+<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" />
+<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
+<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
+<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
+<glyph unicode="&#xf15b;" d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
+<glyph unicode="&#xf15c;" d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
+<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" />
+<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" />
+<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
+<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
+<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
+<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
+<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
+<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" />
+<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
+<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
+<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" />
+<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
+<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
+<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
+<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14 q78 2 134 29z" />
+<glyph unicode="&#xf174;" d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
+<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
+<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
+<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
+<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
+<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
+<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
+<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
+<glyph unicode="&#xf180;" horiz-adv-x="1280" d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324 l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
+<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
+<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
+<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
+<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" />
+<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
+<glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
+<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
+<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " />
+<glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
+<glyph unicode="&#xf194;" d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179 q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf197;" horiz-adv-x="2176" d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40 t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29 q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
+<glyph unicode="&#xf198;" horiz-adv-x="1664" d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9 q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102 t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
+<glyph unicode="&#xf199;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69 q-46 32 -141.5 92.5t-142.5 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13 t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
+<glyph unicode="&#xf19a;" horiz-adv-x="1792" d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5 t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21 t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286 t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273 t273 -182.5t331.5 -68z" />
+<glyph unicode="&#xf19b;" horiz-adv-x="1792" d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
+<glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
+<glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
+<glyph unicode="&#xf19e;" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
+<glyph unicode="&#xf1a0;" horiz-adv-x="1280" d="M981 197q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13t99 39t73 73t27.5 109zM864 1055 q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5q53 56 53 159zM752 1536h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5 t-59.5 -93t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5 t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32z" />
+<glyph unicode="&#xf1a1;" horiz-adv-x="1792" d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26 t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37 q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191 t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf1a2;" d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54 q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83 q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1a3;" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf1a4;" horiz-adv-x="1920" d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328 v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
+<glyph unicode="&#xf1a5;" d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
+<glyph unicode="&#xf1a6;" horiz-adv-x="2048" d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123 v-369h123z" />
+<glyph unicode="&#xf1a7;" d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101 v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1a8;" horiz-adv-x="2038" d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14 q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24 q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33 q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5 t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43 q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5 t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13 t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
+<glyph unicode="&#xf1a9;" d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10 q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14 q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14 t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44 q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
+<glyph unicode="&#xf1aa;" d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5 t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5 q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126 t135.5 51q85 0 145 -60.5t60 -145.5z" />
+<glyph unicode="&#xf1ab;" d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5 q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28 q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11 q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q106 35 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5 q20 0 20 -21v-418z" />
+<glyph unicode="&#xf1ac;" horiz-adv-x="1792" d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48 l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23 t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128 q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128 q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
+<glyph unicode="&#xf1ad;" d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9 t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9 t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9 t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
+<glyph unicode="&#xf1ae;" horiz-adv-x="1280" d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68t68 28t68 -28l228 -228h368l228 228q28 28 68 28t68 -28t28 -68t-28 -68zM864 1152q0 -93 -65.5 -158.5 t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf1b0;" horiz-adv-x="1664" d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5 q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819 q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5 t100.5 134t141.5 55.5z" />
+<glyph unicode="&#xf1b1;" horiz-adv-x="768" d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
+<glyph unicode="&#xf1b2;" horiz-adv-x="1792" d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z " />
+<glyph unicode="&#xf1b3;" horiz-adv-x="2304" d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67 t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-5 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70 v-400l434 -186q36 -16 57 -48t21 -70z" />
+<glyph unicode="&#xf1b4;" horiz-adv-x="2048" d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658 q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204 q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
+<glyph unicode="&#xf1b5;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5 t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217 t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
+<glyph unicode="&#xf1b6;" horiz-adv-x="1792" d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5 q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89 q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
+<glyph unicode="&#xf1b7;" d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5 q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5 q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z " />
+<glyph unicode="&#xf1b8;" horiz-adv-x="1792" d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188 l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5 t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1 q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
+<glyph unicode="&#xf1b9;" horiz-adv-x="2048" d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384 q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5 l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf1ba;" horiz-adv-x="2048" d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5 t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
+<glyph unicode="&#xf1bb;" d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384 q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
+<glyph unicode="&#xf1bc;" d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64 q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37 q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf1bd;" horiz-adv-x="1024" d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
+<glyph unicode="&#xf1be;" horiz-adv-x="2304" d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11 q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245 q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785 l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242 q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236q0 -11 -8 -19 t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786q-13 2 -22 11t-9 22v899 q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
+<glyph unicode="&#xf1c0;" d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127 t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5 t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
+<glyph unicode="&#xf1c1;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197 q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8 q-1 1 -1 2t-0.5 1.5t-0.5 1.5q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
+<glyph unicode="&#xf1c2;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4l-3 21q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5t-3.5 -21.5l-4 -21h-4l-2 21 q-2 26 -7 46l-99 438h90v107h-300z" />
+<glyph unicode="&#xf1c3;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107 h-290v-107h68l189 -272l-194 -283h-68z" />
+<glyph unicode="&#xf1c4;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
+<glyph unicode="&#xf1c5;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
+<glyph unicode="&#xf1c6;" d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400 v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79 q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
+<glyph unicode="&#xf1c7;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5 q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
+<glyph unicode="&#xf1c8;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
+<glyph unicode="&#xf1c9;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243 l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
+<glyph unicode="&#xf1ca;" d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406 q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
+<glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
+<glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" />
+<glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
+<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5z" />
+<glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
+<glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf1d2;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1d3;" horiz-adv-x="1792" d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58 q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47 q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171 v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
+<glyph unicode="&#xf1d4;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1d5;" horiz-adv-x="1280" d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5 t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153 t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
+<glyph unicode="&#xf1d6;" horiz-adv-x="1792" d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5 q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20 t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5 t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
+<glyph unicode="&#xf1d7;" horiz-adv-x="2048" d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25 q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5 q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109 q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
+<glyph unicode="&#xf1d8;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
+<glyph unicode="&#xf1d9;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137 l863 639l-478 -797z" />
+<glyph unicode="&#xf1da;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23 t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf1db;" d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf1dc;" horiz-adv-x="1792" d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15 t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2 t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160 q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5 q0 -26 -12 -48t-36 -22z" />
+<glyph unicode="&#xf1dd;" horiz-adv-x="1280" d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179 q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
+<glyph unicode="&#xf1de;" d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
+<glyph unicode="&#xf1e0;" d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5 t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
+<glyph unicode="&#xf1e1;" d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5 t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1e2;" horiz-adv-x="1792" d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5 t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91 q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9 t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+<glyph unicode="&#xf1e3;" horiz-adv-x="1792" d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323 l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
+<glyph unicode="&#xf1e4;" horiz-adv-x="1792" d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23 zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5 t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
+<glyph unicode="&#xf1e5;" horiz-adv-x="1792" d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf1e6;" horiz-adv-x="1792" d="M1755 1083q37 -37 37 -90t-37 -91l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234l401 400 q38 37 91 37t90 -37z" />
+<glyph unicode="&#xf1e7;" horiz-adv-x="1792" d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5 t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q3 -2 11 -7 t11 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
+<glyph unicode="&#xf1e8;" horiz-adv-x="1792" d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
+<glyph unicode="&#xf1e9;" d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36 q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q70 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5 t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87 q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
+<glyph unicode="&#xf1ea;" horiz-adv-x="2048" d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19 t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
+<glyph unicode="&#xf1eb;" horiz-adv-x="2048" d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121 q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
+<glyph unicode="&#xf1ec;" horiz-adv-x="1792" d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38 h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf1ed;" d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246 q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598 q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
+<glyph unicode="&#xf1ee;" horiz-adv-x="1792" d="M602 949q19 -61 31 -123.5t17 -141.5t-14 -159t-62 -145q-21 81 -67 157t-95.5 127t-99 90.5t-78.5 57.5t-33 19q-62 34 -81.5 100t14.5 128t101 81.5t129 -14.5q138 -83 238 -177zM927 1236q11 -25 20.5 -46t36.5 -100.5t42.5 -150.5t25.5 -179.5t0 -205.5t-47.5 -209.5 t-105.5 -208.5q-51 -72 -138 -72q-54 0 -98 31q-57 40 -69 109t28 127q60 85 81 195t13 199.5t-32 180.5t-39 128t-22 52q-31 63 -8.5 129.5t85.5 97.5q34 17 75 17q47 0 88.5 -25t63.5 -69zM1248 567q-17 -160 -72 -311q-17 131 -63 246q25 174 -5 361q-27 178 -94 342 q114 -90 212 -211q9 -37 15 -80q26 -179 7 -347zM1520 1440q9 -17 23.5 -49.5t43.5 -117.5t50.5 -178t34 -227.5t5 -269t-47 -300t-112.5 -323.5q-22 -48 -66 -75.5t-95 -27.5q-39 0 -74 16q-67 31 -92.5 100t4.5 136q58 126 90 257.5t37.5 239.5t-3.5 213.5t-26.5 180.5 t-38.5 138.5t-32.5 90t-15.5 32.5q-34 65 -11.5 135.5t87.5 104.5q37 20 81 20q49 0 91.5 -25.5t66.5 -70.5z" />
+<glyph unicode="&#xf1f0;" horiz-adv-x="2304" d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27 q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128 q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf1f1;" horiz-adv-x="2304" d="M671 603h-13q-47 0 -47 -32q0 -22 20 -22q17 0 28 15t12 39zM1066 639h62v3q1 4 0.5 6.5t-1 7t-2 8t-4.5 6.5t-7.5 5t-11.5 2q-28 0 -36 -38zM1606 603h-12q-48 0 -48 -32q0 -22 20 -22q17 0 28 15t12 39zM1925 629q0 41 -30 41q-19 0 -31 -20t-12 -51q0 -42 28 -42 q20 0 32.5 20t12.5 52zM480 770h87l-44 -262h-56l32 201l-71 -201h-39l-4 200l-34 -200h-53l44 262h81l2 -163zM733 663q0 -6 -4 -42q-16 -101 -17 -113h-47l1 22q-20 -26 -58 -26q-23 0 -37.5 16t-14.5 42q0 39 26 60.5t73 21.5q14 0 23 -1q0 3 0.5 5.5t1 4.5t0.5 3 q0 20 -36 20q-29 0 -59 -10q0 4 7 48q38 11 67 11q74 0 74 -62zM889 721l-8 -49q-22 3 -41 3q-27 0 -27 -17q0 -8 4.5 -12t21.5 -11q40 -19 40 -60q0 -72 -87 -71q-34 0 -58 6q0 2 7 49q29 -8 51 -8q32 0 32 19q0 7 -4.5 11.5t-21.5 12.5q-43 20 -43 59q0 72 84 72 q30 0 50 -4zM977 721h28l-7 -52h-29q-2 -17 -6.5 -40.5t-7 -38.5t-2.5 -18q0 -16 19 -16q8 0 16 2l-8 -47q-21 -7 -40 -7q-43 0 -45 47q0 12 8 56q3 20 25 146h55zM1180 648q0 -23 -7 -52h-111q-3 -22 10 -33t38 -11q30 0 58 14l-9 -54q-30 -8 -57 -8q-95 0 -95 95 q0 55 27.5 90.5t69.5 35.5q35 0 55.5 -21t20.5 -56zM1319 722q-13 -23 -22 -62q-22 2 -31 -24t-25 -128h-56l3 14q22 130 29 199h51l-3 -33q14 21 25.5 29.5t28.5 4.5zM1506 763l-9 -57q-28 14 -50 14q-31 0 -51 -27.5t-20 -70.5q0 -30 13.5 -47t38.5 -17q21 0 48 13 l-10 -59q-28 -8 -50 -8q-45 0 -71.5 30.5t-26.5 82.5q0 70 35.5 114.5t91.5 44.5q26 0 61 -13zM1668 663q0 -18 -4 -42q-13 -79 -17 -113h-46l1 22q-20 -26 -59 -26q-23 0 -37 16t-14 42q0 39 25.5 60.5t72.5 21.5q15 0 23 -1q2 7 2 13q0 20 -36 20q-29 0 -59 -10q0 4 8 48 q38 11 67 11q73 0 73 -62zM1809 722q-14 -24 -21 -62q-23 2 -31.5 -23t-25.5 -129h-56l3 14q19 104 29 199h52q0 -11 -4 -33q15 21 26.5 29.5t27.5 4.5zM1950 770h56l-43 -262h-53l3 19q-23 -23 -52 -23q-31 0 -49.5 24t-18.5 64q0 53 27.5 92t64.5 39q31 0 53 -29z M2061 640q0 148 -72.5 273t-198 198t-273.5 73q-181 0 -328 -110q127 -116 171 -284h-50q-44 150 -158 253q-114 -103 -158 -253h-50q44 168 171 284q-147 110 -328 110q-148 0 -273.5 -73t-198 -198t-72.5 -273t72.5 -273t198 -198t273.5 -73q181 0 328 110 q-120 111 -165 264h50q46 -138 152 -233q106 95 152 233h50q-45 -153 -165 -264q147 -110 328 -110q148 0 273.5 73t198 198t72.5 273zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf1f2;" horiz-adv-x="2304" d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42 q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604 v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569 q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73 t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
+<glyph unicode="&#xf1f3;" horiz-adv-x="2304" d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260 l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279 v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040 q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168 q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5 t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21 h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5 t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
+<glyph unicode="&#xf1f4;" horiz-adv-x="2304" d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16 t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76 q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59 t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489 l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66 q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf1f5;" horiz-adv-x="2304" d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109 q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118 q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151 q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31 q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf1f6;" horiz-adv-x="2048" d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5 l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5 l418 363q10 8 23.5 7t21.5 -11z" />
+<glyph unicode="&#xf1f7;" horiz-adv-x="2048" d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128 q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161 q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
+<glyph unicode="&#xf1f8;" horiz-adv-x="1408" d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167 q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf1f9;" d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5 t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf1fa;" d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53 q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24 t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61 t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
+<glyph unicode="&#xf1fb;" horiz-adv-x="1792" d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10 t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
+<glyph unicode="&#xf1fc;" horiz-adv-x="1792" d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5 t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
+<glyph unicode="&#xf1fd;" horiz-adv-x="1792" d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11t55.5 -11t52.5 -38q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5t47 37.5 q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-35 0 -55.5 11t-52.5 38q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38t-58 27 t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448h256v448 h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51 t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
+<glyph unicode="&#xf1fe;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
+<glyph unicode="&#xf200;" horiz-adv-x="1792" d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf201;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9 t9 -23z" />
+<glyph unicode="&#xf202;" horiz-adv-x="1792" d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20 q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50 t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1 q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
+<glyph unicode="&#xf203;" d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73 q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110 q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf204;" horiz-adv-x="2048" d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5 t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5 t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
+<glyph unicode="&#xf205;" horiz-adv-x="2048" d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5 t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
+<glyph unicode="&#xf206;" horiz-adv-x="2304" d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94 q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469 q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400 q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
+<glyph unicode="&#xf207;" d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5 h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
+<glyph unicode="&#xf208;" horiz-adv-x="2048" d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327 q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5 q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
+<glyph unicode="&#xf209;" horiz-adv-x="1280" d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q18 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119 t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5 t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14 q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88 q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5 t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
+<glyph unicode="&#xf20a;" horiz-adv-x="2048" d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206 q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307 t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14 t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
+<glyph unicode="&#xf20b;" d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5 t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf20c;" d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55 q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410 q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
+<glyph unicode="&#xf20d;" d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
+<glyph unicode="&#xf20e;" horiz-adv-x="2048" d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335 q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5 q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360q2 0 4.5 -1t5.5 -2.5l5 -2.5l188 199v347l-187 194 q-13 -8 -29 -10zM986 1438h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13 zM552 226h402l64 66l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224 l213 -225zM1023 946l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196 l-48 -227l130 227h-82zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
+<glyph unicode="&#xf210;" d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
+<glyph unicode="&#xf211;" d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384 q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
+<glyph unicode="&#xf212;" horiz-adv-x="2048" d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021 q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25 q209 0 374 -102q172 107 374 102z" />
+<glyph unicode="&#xf213;" horiz-adv-x="2048" d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101 q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284 q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
+<glyph unicode="&#xf214;" d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34 l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114 v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378 v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51 h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5 t-43 -34t-16.5 -53.5z" />
+<glyph unicode="&#xf215;" horiz-adv-x="2048" d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832 q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
+<glyph unicode="&#xf216;" horiz-adv-x="2048" d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126.5t-103.5 132.5t-108.5 126t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5 t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113 t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5 q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
+<glyph unicode="&#xf217;" horiz-adv-x="1664" d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920 q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf218;" horiz-adv-x="1664" d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920 q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf219;" horiz-adv-x="2048" d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20 l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
+<glyph unicode="&#xf21a;" horiz-adv-x="2048" d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83 q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314 v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
+<glyph unicode="&#xf21b;" d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14 t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5 q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31 t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
+<glyph unicode="&#xf21c;" horiz-adv-x="2304" d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5 t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105 l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226 t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
+<glyph unicode="&#xf21d;" d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12 q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384 q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf21e;" horiz-adv-x="1792" d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221 q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124 t127 -344z" />
+<glyph unicode="&#xf221;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292 q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
+<glyph unicode="&#xf222;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5 q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf223;" horiz-adv-x="1280" d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5 t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf224;" d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf225;" horiz-adv-x="1792" d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9 t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf226;" horiz-adv-x="1792" d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23 t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391 q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391 q0 -226 -154 -391q103 -57 218 -57z" />
+<glyph unicode="&#xf227;" horiz-adv-x="1920" d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230 q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9 t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128 q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -29 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
+<glyph unicode="&#xf228;" horiz-adv-x="2048" d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23 t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9 t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5 t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
+<glyph unicode="&#xf229;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5 t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22a;" horiz-adv-x="1280" d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22 t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5 t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22b;" horiz-adv-x="2048" d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5 t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5 t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22c;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22d;" horiz-adv-x="1280" d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123 t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
+<glyph unicode="&#xf22e;" horiz-adv-x="1792" />
+<glyph unicode="&#xf22f;" horiz-adv-x="1792" />
+<glyph unicode="&#xf230;" d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
+<glyph unicode="&#xf231;" horiz-adv-x="1280" d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5 l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5 q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
+<glyph unicode="&#xf232;" d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5 t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233 l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
+<glyph unicode="&#xf233;" horiz-adv-x="1792" d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216 q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+<glyph unicode="&#xf234;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5 t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
+<glyph unicode="&#xf235;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136 q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69 t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
+<glyph unicode="&#xf236;" horiz-adv-x="2048" d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704 q-26 0 -45 -19t-19 -45v-384h1152z" />
+<glyph unicode="&#xf237;" d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+<glyph unicode="&#xf238;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56 t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
+<glyph unicode="&#xf239;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47 t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
+<glyph unicode="&#xf23a;" horiz-adv-x="1792" d="M1792 204v-209h-642v209h134v926h-6l-314 -1135h-243l-310 1135h-8v-926h135v-209h-538v209h69q21 0 43 19.5t22 37.5v881q0 18 -22 40t-43 22h-69v209h672l221 -821h6l223 821h670v-209h-71q-19 0 -41 -22t-22 -40v-881q0 -18 21.5 -37.5t41.5 -19.5h71z" />
+<glyph unicode="&#xf23b;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+<glyph unicode="&#xf23c;" horiz-adv-x="2296" d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5 q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5 q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42 q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37 q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5 q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139 q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 4 5 8q16 18 60 23h13q5 18 19 30t33 8 t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132 q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132 q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-106 2 -211 0v1q-1 -27 2.5 -86 t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103 q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34l3 9v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4l-10 -2.5t-12 -2 l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-2 0 -3 -0.5t-3 -0.5h-3q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130t-73 70 q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -2 -1 -5t-1 -4q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150 q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12 q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
+<glyph unicode="&#xf23d;" horiz-adv-x="2304" d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5 t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5 t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
+<glyph unicode="&#xf23e;" horiz-adv-x="1792" d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348 t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23 t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512 q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
+<glyph unicode="&#xf240;" horiz-adv-x="2304" d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113 v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf241;" horiz-adv-x="2304" d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf242;" horiz-adv-x="2304" d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf243;" horiz-adv-x="2304" d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf244;" horiz-adv-x="2304" d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23 v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf245;" horiz-adv-x="1280" d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
+<glyph unicode="&#xf246;" horiz-adv-x="1024" d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
+<glyph unicode="&#xf247;" horiz-adv-x="2048" d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128 h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+<glyph unicode="&#xf248;" horiz-adv-x="2304" d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256 v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
+<glyph unicode="&#xf249;" d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
+<glyph unicode="&#xf24a;" d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68 z" />
+<glyph unicode="&#xf24b;" horiz-adv-x="2304" d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5 t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88 t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90 t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf24c;" horiz-adv-x="2304" d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294 t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf24d;" horiz-adv-x="1792" d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113 zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf24e;" horiz-adv-x="2304" d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64 q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91 t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5 t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
+<glyph unicode="&#xf250;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5 t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+<glyph unicode="&#xf251;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
+<glyph unicode="&#xf252;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
+<glyph unicode="&#xf253;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196 h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+<glyph unicode="&#xf254;" d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87 t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9 h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
+<glyph unicode="&#xf255;" d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25 q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27 t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21 q72 69 174 69z" />
+<glyph unicode="&#xf256;" horiz-adv-x="1792" d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33 t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52 h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
+<glyph unicode="&#xf257;" horiz-adv-x="1792" d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668 q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17 t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5 t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5 q0 -42 -23 -78t-61 -53l-310 -141h91z" />
+<glyph unicode="&#xf258;" horiz-adv-x="2048" d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32 q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68 q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
+<glyph unicode="&#xf259;" horiz-adv-x="2048" d="M816 1408q-48 0 -79.5 -34t-31.5 -82q0 -14 3 -28l150 -624h-26l-116 482q-9 38 -39.5 62t-69.5 24q-47 0 -79 -34t-32 -81q0 -11 4 -29q3 -13 39 -161t68 -282t32 -138v-227l-307 230q-34 26 -77 26q-52 0 -89.5 -36.5t-37.5 -88.5q0 -67 56 -110l507 -379 q34 -26 76 -26h694q33 0 59 20.5t34 52.5l100 401q8 30 10 88t9 86l116 478q3 12 3 26q0 46 -33 79t-80 33q-38 0 -69 -25.5t-40 -62.5l-99 -408h-26l132 547q3 14 3 28q0 47 -32 80t-80 33q-38 0 -68.5 -24t-39.5 -62l-145 -602h-127l-164 682q-9 38 -39.5 62t-68.5 24z M1461 -256h-694q-85 0 -153 51l-507 380q-50 38 -78.5 94t-28.5 118q0 105 75 179t180 74q25 0 49.5 -5.5t41.5 -11t41 -20.5t35 -23t38.5 -29.5t37.5 -28.5l-123 512q-7 35 -7 59q0 93 60 162t152 79q14 87 80.5 144.5t155.5 57.5q83 0 148 -51.5t85 -132.5l103 -428 l83 348q20 81 85 132.5t148 51.5q87 0 152.5 -54t82.5 -139q93 -10 155 -78t62 -161q0 -30 -7 -57l-116 -477q-5 -22 -5 -67q0 -51 -13 -108l-101 -401q-19 -75 -79.5 -122.5t-137.5 -47.5z" />
+<glyph unicode="&#xf25a;" horiz-adv-x="1792" d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5 q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5 v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32 v-384h32z" />
+<glyph unicode="&#xf25b;" d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181 v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46 q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5 q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308 q0 -53 37.5 -90.5t90.5 -37.5h668z" />
+<glyph unicode="&#xf25c;" horiz-adv-x="1973" d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5 t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141 q13 0 22 -8.5t10 -20.5z" />
+<glyph unicode="&#xf25d;" horiz-adv-x="1792" d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109 t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640 q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf25e;" horiz-adv-x="1792" d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78 q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5 t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376 q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
+<glyph unicode="&#xf260;" horiz-adv-x="2048" d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+<glyph unicode="&#xf261;" horiz-adv-x="1792" d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf262;" horiz-adv-x="2304" d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57 t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197 t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5 t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5 t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5 q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
+<glyph unicode="&#xf263;" horiz-adv-x="1280" d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5 t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94 q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
+<glyph unicode="&#xf264;" d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32 q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5 zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf265;" horiz-adv-x="1720" d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33 l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
+<glyph unicode="&#xf266;" horiz-adv-x="2304" d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540 q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81 l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
+<glyph unicode="&#xf267;" horiz-adv-x="1792" d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640 q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5 t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5 t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5 t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191 t191 -286t71 -348z" />
+<glyph unicode="&#xf268;" horiz-adv-x="1792" d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962 q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
+<glyph unicode="&#xf269;" horiz-adv-x="1792" d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5 q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5 q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
+<glyph unicode="&#xf26a;" d="M768 -92q77 0 139.5 63t100.5 166t59 234.5t21 268.5t-21 268.5t-59 234.5t-100.5 166t-139.5 63t-139.5 -63t-100.5 -166t-59 -234.5t-21 -268.5t21 -268.5t59 -234.5t100.5 -166t139.5 -63zM768 -256q-184 0 -333 77t-240 203t-141 287t-50 329t50 329t141 287t240 203 t333 77q148 0 274 -50t214.5 -136t151.5 -201t92.5 -244t29.5 -265t-29.5 -265t-92.5 -244t-151.5 -201t-214.5 -136t-274 -50z" />
+<glyph unicode="&#xf26b;" horiz-adv-x="1792" d="M716 -69q-143 35 -261.5 114t-197.5 191q-139 -300 -17 -398q26 -21 85 -24.5t127.5 9.5t141 41.5t122.5 66.5zM693 762h452q0 108 -61.5 169t-168.5 61q-103 0 -162.5 -62.5t-59.5 -167.5zM1724 1137h-34q26 102 22.5 170t-25 110t-63.5 57t-93.5 11t-115 -26.5 t-128.5 -56.5t-134 -79q129 -37 238.5 -113.5t185 -179t110 -231.5t15.5 -262h-1005q0 -60 10 -106t34 -85t69.5 -60t112.5 -21q87 0 142.5 44t72.5 122h540q-71 -230 -281.5 -377t-477.5 -147q-83 0 -159 15q-35 -40 -151 -94t-248 -78t-219 35q-78 60 -100 159t7 214 t88 242t143.5 248t173.5 226.5t177.5 183.5t156.5 112v24q-120 -37 -258.5 -137.5t-240.5 -207t-159 -195.5q4 106 34 201t80 169t118 135.5t147.5 100.5t168 65.5t180.5 29.5t185 -8q310 186 503 189h7q57 0 103 -18q80 -30 98 -132.5t-30 -248.5z" />
+<glyph unicode="&#xf26c;" horiz-adv-x="2048" d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23 v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf26d;" horiz-adv-x="1792" d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34 h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100 q-68 175 -180 287z" />
+<glyph unicode="&#xf26e;" horiz-adv-x="2304" d="M1391 390v0l-1 1q-15 18 -34.5 37.5t-62.5 57.5t-93.5 62t-95.5 24q-48 0 -83 -21.5t-51 -54t-23 -59t-7 -47.5v0v0q0 -21 7 -48t23 -59t51 -53.5t83 -21.5q45 0 95.5 24t94 62.5t62 57t34.5 37.5zM2103 390q0 21 -7 47.5t-23 59t-51 54t-83 21.5q-45 0 -95.5 -24 t-94 -62.5t-62 -57t-34.5 -37.5l-1 -1v0v0l1 -1q15 -18 34.5 -37.5t62.5 -57.5t93.5 -62t95.5 -24q48 0 83 21.5t51 53.5t23 59t7 48zM2304 393q0 -69 -24 -137.5t-68 -126t-116 -93.5t-159 -36q-68 0 -134 24t-113.5 58.5t-84.5 69.5t-59.5 59t-25.5 24t-22.5 -24 t-54.5 -58.5t-81.5 -69.5t-115 -59t-143.5 -24q-65 0 -123.5 22.5t-96.5 54t-66.5 66.5t-41 59.5t-12.5 32.5q0 -8 -8.5 -26.5t-25 -45.5t-47 -55t-69 -52.5t-96.5 -40t-125 -15.5q-71 0 -130 15.5t-98.5 39.5t-70.5 56.5t-48 63.5t-27.5 63.5t-14 54t-3.5 36.5h217 q0 -55 49 -107.5t126 -52.5q79 0 134.5 67t55.5 148q0 80 -52 136.5t-138 56.5q-5 0 -13 -0.5t-31 -5t-43 -12t-42 -24.5t-34 -40h-195l102 583h602v-174h-445q-27 -159 -41 -248q4 0 16.5 13t31.5 28.5t65 28.5t108 13t114 -20.5t82.5 -49.5t51.5 -58.5t31 -50t11 -20.5 t13 25t36.5 60.5t60.5 71.5t97 61t133 25t140.5 -25t115.5 -60.5t83.5 -71.5t56.5 -61t21 -25q2 0 22 25t56 60.5t83.5 71.5t115.5 61t140 25q92 0 164.5 -35t115.5 -93t65 -125t22 -137z" />
+<glyph unicode="&#xf270;" horiz-adv-x="1792" d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30 q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57 t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133 q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
+<glyph unicode="&#xf271;" horiz-adv-x="1792" d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9 h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224 v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
+<glyph unicode="&#xf272;" horiz-adv-x="1792" d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23 t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf273;" horiz-adv-x="1792" d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf274;" horiz-adv-x="1792" d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23 t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf275;" horiz-adv-x="1792" d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
+<glyph unicode="&#xf276;" horiz-adv-x="1024" d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q61 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249 q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
+<glyph unicode="&#xf277;" horiz-adv-x="1792" d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768 q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
+<glyph unicode="&#xf278;" horiz-adv-x="2048" d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173 v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+<glyph unicode="&#xf279;" horiz-adv-x="1792" d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472 q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
+<glyph unicode="&#xf27a;" horiz-adv-x="1792" d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37 t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf27b;" horiz-adv-x="1792" d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5 t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51 t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
+<glyph unicode="&#xf27c;" horiz-adv-x="1024" d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+<glyph unicode="&#xf27d;" horiz-adv-x="1792" d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246 q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
+<glyph unicode="&#xf27e;" d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+<glyph unicode="&#xf280;" d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72 h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275 l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
+<glyph unicode="&#xf281;" horiz-adv-x="1792" />
+<glyph unicode="&#xf282;" horiz-adv-x="1792" />
+<glyph unicode="&#xf283;" horiz-adv-x="1792" />
+<glyph unicode="&#xf284;" horiz-adv-x="1792" />
+<glyph unicode="&#xf285;" horiz-adv-x="1792" />
+<glyph unicode="&#xf286;" horiz-adv-x="1792" />
+<glyph unicode="&#xf287;" horiz-adv-x="1792" />
+<glyph unicode="&#xf288;" horiz-adv-x="1792" />
+<glyph unicode="&#xf289;" horiz-adv-x="1792" />
+<glyph unicode="&#xf28a;" horiz-adv-x="1792" />
+<glyph unicode="&#xf28b;" horiz-adv-x="1792" />
+<glyph unicode="&#xf28c;" horiz-adv-x="1792" />
+<glyph unicode="&#xf28d;" horiz-adv-x="1792" />
+<glyph unicode="&#xf28e;" horiz-adv-x="1792" />
+<glyph unicode="&#xf500;" horiz-adv-x="1792" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/phpBB/assets/fonts/fontawesome-webfont.ttf b/phpBB/assets/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000000..d7994e1308
--- /dev/null
+++ b/phpBB/assets/fonts/fontawesome-webfont.ttf
Binary files differ
diff --git a/phpBB/assets/fonts/fontawesome-webfont.woff b/phpBB/assets/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000000..6fd4ede0f3
--- /dev/null
+++ b/phpBB/assets/fonts/fontawesome-webfont.woff
Binary files differ
diff --git a/phpBB/assets/fonts/fontawesome-webfont.woff2 b/phpBB/assets/fonts/fontawesome-webfont.woff2
new file mode 100644
index 0000000000..5560193ccc
--- /dev/null
+++ b/phpBB/assets/fonts/fontawesome-webfont.woff2
Binary files differ
diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js
index f7ace80705..b00da3caff 100644
--- a/phpBB/assets/javascript/core.js
+++ b/phpBB/assets/javascript/core.js
@@ -27,7 +27,10 @@ phpbb.isTouch = (window && typeof window.ontouchstart !== 'undefined');
*/
phpbb.loadingIndicator = function() {
if (!$loadingIndicator) {
- $loadingIndicator = $('<div />', { id: 'loading_indicator' });
+ $loadingIndicator = $('<div />', {
+ id: 'loading_indicator',
+ class: 'loading_indicator',
+ });
$loadingIndicator.appendTo('#page-footer');
}
@@ -958,12 +961,6 @@ phpbb.addAjaxCallback('toggle_link', function() {
$anchor.each(function() {
var $this = $(this);
- // Toggle link text
- toggleText = $this.attr('data-toggle-text');
- $this.attr('data-toggle-text', $this.text());
- $this.attr('title', $.trim(toggleText));
- $this.text(toggleText);
-
// Toggle link url
toggleUrl = $this.attr('data-toggle-url');
$this.attr('data-toggle-url', $this.attr('href'));
@@ -971,8 +968,14 @@ phpbb.addAjaxCallback('toggle_link', function() {
// Toggle class of link parent
toggleClass = $this.attr('data-toggle-class');
- $this.attr('data-toggle-class', $this.parent().attr('class'));
- $this.parent().attr('class', toggleClass);
+ $this.attr('data-toggle-class', $this.children().attr('class'));
+ $this.children('.icon').attr('class', toggleClass);
+
+ // Toggle link text
+ toggleText = $this.attr('data-toggle-text');
+ $this.attr('data-toggle-text', $this.children('span').text());
+ $this.attr('title', $.trim(toggleText));
+ $this.children('span').text(toggleText);
});
});
diff --git a/phpBB/assets/javascript/editor.js b/phpBB/assets/javascript/editor.js
index 3abf5c84f4..332ab42e37 100644
--- a/phpBB/assets/javascript/editor.js
+++ b/phpBB/assets/javascript/editor.js
@@ -111,7 +111,6 @@ function bbfontstyle(bbopen, bbclose) {
}
textarea.focus();
- return;
}
/**
@@ -167,7 +166,7 @@ function attachInline(index, filename) {
/**
* Add quote text to message
*/
-function addquote(post_id, username, l_wrote) {
+function addquote(post_id, username, l_wrote, attributes) {
var message_name = 'message_' + post_id;
var theSelection = '';
var divarea = false;
@@ -177,6 +176,9 @@ function addquote(post_id, username, l_wrote) {
// Backwards compatibility
l_wrote = 'wrote';
}
+ if (typeof attributes !== 'object') {
+ attributes = {};
+ }
if (document.all) {
divarea = document.all[message_name];
@@ -213,7 +215,8 @@ function addquote(post_id, username, l_wrote) {
if (theSelection) {
if (bbcodeEnabled) {
- insert_text('[quote="' + username + '"]' + theSelection + '[/quote]');
+ attributes.author = username;
+ insert_text(generateQuote(theSelection, attributes));
} else {
insert_text(username + ' ' + l_wrote + ':' + '\n');
var lines = split_lines(theSelection);
@@ -222,8 +225,61 @@ function addquote(post_id, username, l_wrote) {
}
}
}
+}
- return;
+/**
+* Create a quote block for given text
+*
+* Possible attributes:
+* - author: author's name (usually a username)
+* - post_id: post_id of the post being quoted
+* - user_id: user_id of the user being quoted
+* - time: timestamp of the original message
+*
+* @param {!string} text Quote's text
+* @param {!Object} attributes Quote's attributes
+* @return {!string} Quote block to be used in a new post/text
+*/
+function generateQuote(text, attributes) {
+ text = text.replace(/^\s+/, '').replace(/\s+$/, '');
+ var quote = '[quote';
+ if (attributes.author) {
+ // Add the author as the BBCode's default attribute
+ quote += '=' + formatAttributeValue(attributes.author);
+ delete attributes.author;
+ }
+ for (var name in attributes) {
+ if (attributes.hasOwnProperty(name)) {
+ var value = attributes[name];
+ quote += ' ' + name + '=' + formatAttributeValue(value.toString());
+ }
+ }
+ quote += ']';
+ var newline = ((quote + text + '[/quote]').length > 80 || text.indexOf('\n') > -1) ? '\n' : '';
+ quote += newline + text + newline + '[/quote]';
+
+ return quote;
+}
+
+/**
+* Format given string to be used as an attribute value
+*
+* Will return the string as-is if it can be used in a BBCode without quotes. Otherwise,
+* it will use either single- or double- quotes depending on whichever requires less escaping.
+* Quotes and backslashes are escaped with backslashes where necessary
+*
+* @param {!string} str Original string
+* @return {!string} Same string if possible, escaped string within quotes otherwise
+*/
+function formatAttributeValue(str) {
+ if (!/[ "'\\\]]/.test(str)) {
+ // Return as-is if it contains none of: space, ' " \ or ]
+ return str;
+ }
+ var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'",
+ doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"';
+
+ return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted;
}
function split_lines(text) {
diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js
new file mode 100644
index 0000000000..a11b76b863
--- /dev/null
+++ b/phpBB/assets/javascript/installer.js
@@ -0,0 +1,615 @@
+/**
+ * Installer's AJAX frontend handler
+ */
+
+(function($) { // Avoid conflicts with other libraries
+ 'use strict';
+
+ // Installer variables
+ var pollTimer = null;
+ var nextReadPosition = 0;
+ var progressBarTriggered = false;
+ var progressTimer = null;
+ var currentProgress = 0;
+ var refreshRequested = false;
+ var transmissionOver = false;
+ var statusCount = 0;
+
+ // Template related variables
+ var $contentWrapper = $('.install-body').find('.main');
+
+ // Intercept form submits
+ interceptFormSubmit($('#install_install'));
+
+ /**
+ * Creates an XHR object
+ *
+ * jQuery cannot be used as the response is streamed, and
+ * as of now, jQuery does not provide access to the response until
+ * the connection is not closed.
+ *
+ * @return XMLHttpRequest
+ */
+ function createXhrObject() {
+ return new XMLHttpRequest();
+ }
+
+ /**
+ * Displays error, warning and log messages
+ *
+ * @param type
+ * @param messages
+ */
+ function addMessage(type, messages) {
+ // Get message containers
+ var $errorContainer = $('#error-container');
+ var $warningContainer = $('#warning-container');
+ var $logContainer = $('#log-container');
+
+ var $title, $description, $msgElement, arraySize = messages.length;
+ for (var i = 0; i < arraySize; i++) {
+ $msgElement = $('<div />');
+ $title = $('<strong />');
+ $title.text(messages[i].title);
+ $msgElement.append($title);
+
+ if (messages[i].hasOwnProperty('description')) {
+ $description = $('<p />');
+ $description.html(messages[i].description);
+ $msgElement.append($description);
+ }
+
+ switch (type) {
+ case 'error':
+ $msgElement.addClass('errorbox');
+ $errorContainer.append($msgElement);
+ break;
+ case 'warning':
+ $msgElement.addClass('warningbox');
+ $warningContainer.append($msgElement);
+ break;
+ case 'log':
+ $msgElement.addClass('log');
+ $logContainer.prepend($msgElement);
+ $logContainer.addClass('show_log_container');
+ break;
+ case 'success':
+ $msgElement.addClass('successbox');
+ $errorContainer.prepend($msgElement);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Render a download box
+ */
+ function addDownloadBox(downloadArray)
+ {
+ var $downloadContainer = $('#download-wrapper');
+ var $downloadBox, $title, $content, $link;
+
+ for (var i = 0; i < downloadArray.length; i++) {
+ $downloadBox = $('<div />');
+ $downloadBox.addClass('download-box');
+
+ $title = $('<strong />');
+ $title.text(downloadArray[i].title);
+ $downloadBox.append($title);
+
+ if (downloadArray[i].hasOwnProperty('msg')) {
+ $content = $('<p />');
+ $content.text(downloadArray[i].msg);
+ $downloadBox.append($content);
+ }
+
+ $link = $('<a />');
+ $link.addClass('button1');
+ $link.attr('href', downloadArray[i].href);
+ $link.text(downloadArray[i].download);
+ $downloadBox.append($link);
+
+ $downloadContainer.append($downloadBox);
+ }
+ }
+
+ /**
+ * Render update files' status
+ */
+ function addUpdateFileStatus(fileStatus)
+ {
+ var $statusContainer = $('#file-status-wrapper');
+ $statusContainer.html(fileStatus);
+ }
+
+ /**
+ * Displays a form from the response
+ *
+ * @param formHtml
+ */
+ function addForm(formHtml) {
+ var $formContainer = $('#form-wrapper');
+ $formContainer.html(formHtml);
+ var $form = $('#install_install');
+ interceptFormSubmit($form);
+ }
+
+ /**
+ * Handles navigation status updates
+ *
+ * @param navObj
+ */
+ function updateNavbarStatus(navObj) {
+ var navID, $stage, $stageListItem, $active;
+ $active = $('#activemenu');
+
+ if (navObj.hasOwnProperty('finished')) {
+ // This should be an Array
+ var navItems = navObj.finished;
+
+ for (var i = 0; i < navItems.length; i++) {
+ navID = 'installer-stage-' + navItems[i];
+ $stage = $('#' + navID);
+ $stageListItem = $stage.parent();
+
+ if ($active.length && $active.is($stageListItem)) {
+ $active.removeAttr('id');
+ }
+
+ $stage.addClass('completed');
+ }
+ }
+
+ if (navObj.hasOwnProperty('active')) {
+ navID = 'installer-stage-' + navObj.active;
+ $stage = $('#' + navID);
+ $stageListItem = $stage.parent();
+
+ if ($active.length && !$active.is($stageListItem)) {
+ $active.removeAttr('id');
+ }
+
+ $stageListItem.attr('id', 'activemenu');
+ }
+ }
+
+ /**
+ * Renders progress bar
+ *
+ * @param progressObject
+ */
+ function setProgress(progressObject) {
+ var $statusText, $progressBar, $progressText, $progressFiller, $progressFillerText;
+
+ if (progressObject.task_name.length) {
+ if (!progressBarTriggered) {
+ // Create progress bar
+ var $progressBarWrapper = $('#progress-bar-container');
+
+ // Create progress bar elements
+ $progressBar = $('<div />');
+ $progressBar.attr('id', 'progress-bar');
+ $progressText = $('<p />');
+ $progressText.attr('id', 'progress-bar-text');
+ $progressFiller = $('<div />');
+ $progressFiller.attr('id', 'progress-bar-filler');
+ $progressFillerText = $('<p />');
+ $progressFillerText.attr('id', 'progress-bar-filler-text');
+
+ $statusText = $('<p />');
+ $statusText.attr('id', 'progress-status-text');
+
+ $progressFiller.append($progressFillerText);
+ $progressBar.append($progressText);
+ $progressBar.append($progressFiller);
+
+ $progressBarWrapper.append($statusText);
+ $progressBarWrapper.append($progressBar);
+
+ $progressFillerText.css('width', $progressBar.width());
+
+ progressBarTriggered = true;
+ } else if (progressObject.hasOwnProperty('restart')) {
+ clearInterval(progressTimer);
+
+ $progressFiller = $('#progress-bar-filler');
+ $progressFillerText = $('#progress-bar-filler-text');
+ $progressText = $('#progress-bar-text');
+ $statusText = $('#progress-status-text');
+
+ $progressText.text('0%');
+ $progressFillerText.text('0%');
+ $progressFiller.css('width', '0%');
+
+ currentProgress = 0;
+ } else {
+ $statusText = $('#progress-status-text');
+ }
+
+ // Update progress bar
+ $statusText.text(progressObject.task_name + '…');
+ incrementProgressBar(Math.round(progressObject.task_num / progressObject.task_count * 100));
+ }
+ }
+
+ // Set cookies
+ function setCookies(cookies) {
+ var cookie;
+
+ for (var i = 0; i < cookies.length; i++) {
+ // Set cookie name and value
+ cookie = encodeURIComponent(cookies[i].name) + '=' + encodeURIComponent(cookies[i].value);
+ // Set path
+ cookie += '; path=/';
+ document.cookie = cookie;
+ }
+ }
+
+ // Redirects user
+ function redirect(url, use_ajax) {
+ if (use_ajax) {
+ resetPolling();
+
+ var xhReq = createXhrObject();
+ xhReq.open('GET', url, true);
+ xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ xhReq.send();
+
+ startPolling(xhReq);
+ } else {
+ window.location.href = url;
+ }
+ }
+
+ /**
+ * Parse messages from the response object
+ *
+ * @param messageJSON
+ */
+ function parseMessage(messageJSON) {
+ $('#loading_indicator').css('display', 'none');
+ var responseObject;
+
+ try {
+ responseObject = JSON.parse(messageJSON);
+ } catch (err) {
+ if (window.console) {
+ console.log('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
+ } else {
+ alert('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
+ }
+
+ resetPolling();
+ return;
+ }
+
+ // Parse object
+ if (responseObject.hasOwnProperty('errors')) {
+ addMessage('error', responseObject.errors);
+ }
+
+ if (responseObject.hasOwnProperty('warnings')) {
+ addMessage('warning', responseObject.warnings);
+ }
+
+ if (responseObject.hasOwnProperty('logs')) {
+ addMessage('log', responseObject.logs);
+ }
+
+ if (responseObject.hasOwnProperty('success')) {
+ addMessage('success', responseObject.success);
+ }
+
+ if (responseObject.hasOwnProperty('form')) {
+ addForm(responseObject.form);
+ }
+
+ if (responseObject.hasOwnProperty('progress')) {
+ setProgress(responseObject.progress);
+ }
+
+ if (responseObject.hasOwnProperty('download')) {
+ addDownloadBox(responseObject.download);
+ }
+
+ if (responseObject.hasOwnProperty('file_status')) {
+ addUpdateFileStatus(responseObject.file_status);
+ }
+
+ if (responseObject.hasOwnProperty('nav')) {
+ updateNavbarStatus(responseObject.nav);
+ }
+
+ if (responseObject.hasOwnProperty('cookies')) {
+ setCookies(responseObject.cookies);
+ }
+
+ if (responseObject.hasOwnProperty('refresh')) {
+ refreshRequested = true;
+ }
+
+ if (responseObject.hasOwnProperty('redirect')) {
+ redirect(responseObject.redirect.url, responseObject.redirect.use_ajax);
+ }
+
+ if (responseObject.hasOwnProperty('over')) {
+ if (responseObject.over) {
+ transmissionOver = true;
+ }
+ }
+ }
+
+ /**
+ * Processes status data
+ *
+ * @param status
+ */
+ function processTimeoutResponse(status) {
+ if (statusCount === 12) { // 1 minute hard cap
+ status = 'fail';
+ }
+
+ if (status === 'continue') {
+ refreshRequested = false;
+ doRefresh();
+ } else if (status === 'running') {
+ statusCount++;
+ $('#loading_indicator').css('display', 'block');
+ setTimeout(queryInstallerStatus, 5000);
+ } else {
+ $('#loading_indicator').css('display', 'none');
+ addMessage('error',
+ [{
+ title: installLang.title,
+ description: installLang.msg
+ }]
+ );
+ }
+ }
+
+ /**
+ * Queries the installer's status
+ */
+ function queryInstallerStatus() {
+ var url = $(location).attr('pathname');
+ var lookUp = 'install/app.php';
+ var position = url.indexOf(lookUp);
+
+ if (position === -1) {
+ lookUp = 'install';
+ position = url.indexOf(lookUp);
+
+ if (position === -1) {
+ return false;
+ }
+ }
+
+ url = url.substring(0, position) + lookUp + '/installer/status';
+ $.getJSON(url, function(data) {
+ processTimeoutResponse(data.status);
+ });
+ }
+
+ /**
+ * Process updates in streamed response
+ *
+ * @param xhReq XHR object
+ */
+ function pollContent(xhReq) {
+ var messages = xhReq.responseText;
+ var msgSeparator = '}\n\n';
+ var unprocessed, messageEndIndex, endOfMessageIndex, message;
+
+ do {
+ unprocessed = messages.substring(nextReadPosition);
+ messageEndIndex = unprocessed.indexOf(msgSeparator);
+
+ if (messageEndIndex !== -1) {
+ endOfMessageIndex = messageEndIndex + msgSeparator.length;
+ message = unprocessed.substring(0, endOfMessageIndex);
+ parseMessage($.trim(message));
+ nextReadPosition += endOfMessageIndex;
+ }
+ } while (messageEndIndex !== -1);
+
+ if (xhReq.readyState === 4) {
+ $('#loading_indicator').css('display', 'none');
+ resetPolling();
+
+ var timeoutDetected = !transmissionOver;
+
+ if (refreshRequested) {
+ refreshRequested = false;
+ doRefresh();
+ }
+
+ if (timeoutDetected) {
+ statusCount = 0;
+ queryInstallerStatus();
+ }
+ }
+ }
+
+ /**
+ * Animates the progress bar
+ *
+ * @param $progressText
+ * @param $progressFiller
+ * @param $progressFillerText
+ * @param progressLimit
+ */
+ function incrementFiller($progressText, $progressFiller, $progressFillerText, progressLimit) {
+ if (currentProgress >= progressLimit || currentProgress >= 100) {
+ clearInterval(progressTimer);
+ return;
+ }
+
+ var $progressBar = $('#progress-bar');
+
+ currentProgress++;
+ $progressFillerText.css('width', $progressBar.width());
+ $progressFillerText.text(currentProgress + '%');
+ $progressText.text(currentProgress + '%');
+ $progressFiller.css('width', currentProgress + '%');
+ }
+
+ /**
+ * Wrapper function for progress bar rendering and animating
+ *
+ * @param progressLimit
+ */
+ function incrementProgressBar(progressLimit) {
+ var $progressFiller = $('#progress-bar-filler');
+ var $progressFillerText = $('#progress-bar-filler-text');
+ var $progressText = $('#progress-bar-text');
+ var progressStart = $progressFiller.width() / $progressFiller.offsetParent().width() * 100;
+ currentProgress = Math.floor(progressStart);
+
+ clearInterval(progressTimer);
+ progressTimer = setInterval(function() {
+ incrementFiller($progressText, $progressFiller, $progressFillerText, progressLimit);
+ }, 10);
+ }
+
+ /**
+ * Resets the polling timer
+ */
+ function resetPolling() {
+ clearInterval(pollTimer);
+ nextReadPosition = 0;
+ }
+
+ /**
+ * Sets up timer for processing the streamed HTTP response
+ *
+ * @param xhReq
+ */
+ function startPolling(xhReq) {
+ resetPolling();
+ transmissionOver = false;
+ pollTimer = setInterval(function () {
+ pollContent(xhReq);
+ }, 250);
+ }
+
+ /**
+ * Refresh page
+ */
+ function doRefresh() {
+ resetPolling();
+
+ var xhReq = createXhrObject();
+ xhReq.open('GET', $(location).attr('pathname'), true);
+ xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ xhReq.send();
+
+ startPolling(xhReq);
+ }
+
+ /**
+ * Renders the AJAX UI layout
+ */
+ function setupAjaxLayout() {
+ progressBarTriggered = false;
+
+ // Clear content
+ $contentWrapper.html('');
+
+ var $header = $('<div />');
+ $header.attr('id', 'header-container');
+ $contentWrapper.append($header);
+
+ var $description = $('<div />');
+ $description.attr('id', 'description-container');
+ $contentWrapper.append($description);
+
+ var $errorContainer = $('<div />');
+ $errorContainer.attr('id', 'error-container');
+ $contentWrapper.append($errorContainer);
+
+ var $warningContainer = $('<div />');
+ $warningContainer.attr('id', 'warning-container');
+ $contentWrapper.append($warningContainer);
+
+ var $progressContainer = $('<div />');
+ $progressContainer.attr('id', 'progress-bar-container');
+ $contentWrapper.append($progressContainer);
+
+ var $logContainer = $('<div />');
+ $logContainer.attr('id', 'log-container');
+ $contentWrapper.append($logContainer);
+
+ var $installerContentWrapper = $('<div />');
+ $installerContentWrapper.attr('id', 'content-container');
+ $contentWrapper.append($installerContentWrapper);
+
+ var $installerDownloadWrapper = $('<div />');
+ $installerDownloadWrapper.attr('id', 'download-wrapper');
+ $installerContentWrapper.append($installerDownloadWrapper);
+
+ var $updaterFileStatusWrapper = $('<div />');
+ $updaterFileStatusWrapper.attr('id', 'file-status-wrapper');
+ $installerContentWrapper.append($updaterFileStatusWrapper);
+
+ var $formWrapper = $('<div />');
+ $formWrapper.attr('id', 'form-wrapper');
+ $installerContentWrapper.append($formWrapper);
+
+ var $spinner = $('<div />');
+ $spinner.attr('id', 'loading_indicator');
+ $spinner.html('&nbsp;');
+ $contentWrapper.append($spinner);
+ }
+
+ // Submits a form
+ function submitForm($form, $submitBtn) {
+ $form.css('display', 'none');
+
+ var xhReq = createXhrObject();
+ xhReq.open('POST', $form.attr('action'), true);
+ xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+ xhReq.send(getFormFields($form, $submitBtn));
+
+ // Disable language selector
+ $('#language_selector :input, label').css('display', 'none');
+
+ // Clear content
+ setupAjaxLayout();
+ $('#loading_indicator').css('display', 'block');
+
+ startPolling(xhReq);
+ }
+
+ /**
+ * Add submit button to the POST information
+ *
+ * @param $form
+ * @param $submitBtn
+ *
+ * @returns {*}
+ */
+ function getFormFields($form, $submitBtn) {
+ var formData = $form.serialize();
+ formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '=';
+ formData += encodeURIComponent($submitBtn.attr('value'));
+
+ return formData;
+ }
+
+ /**
+ * Intercept form submit events and determine the submit button used
+ *
+ * @param $form
+ */
+ function interceptFormSubmit($form) {
+ if (!$form.length) {
+ return;
+ }
+
+ $form.find(':submit').bind('click', function (event) {
+ event.preventDefault();
+ submitForm($form, $(this));
+ });
+ }
+})(jQuery); // Avoid conflicts with other libraries
diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php
index 239dd3932b..2bca6e7b89 100755
--- a/phpBB/bin/phpbbcli.php
+++ b/phpBB/bin/phpbbcli.php
@@ -21,6 +21,7 @@ if (php_sapi_name() != 'cli')
}
define('IN_PHPBB', true);
+
$phpbb_root_path = __DIR__ . '/../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
require($phpbb_root_path . 'includes/startup.' . $phpEx);
@@ -32,38 +33,55 @@ $phpbb_class_loader->register();
$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
extract($phpbb_config_php_file->get_all());
+if (!defined('PHPBB_ENVIRONMENT'))
+{
+ @define('PHPBB_ENVIRONMENT', 'production');
+}
+
require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/functions.' . $phpEx);
require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
+require($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx);
-$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
-$phpbb_container_builder->set_dump_container(false);
+$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+$phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file);
$input = new ArgvInput();
+if ($input->hasParameterOption(array('--env')))
+{
+ $phpbb_container_builder->with_environment($input->getParameterOption('--env'));
+}
+
if ($input->hasParameterOption(array('--safe-mode')))
{
- $phpbb_container_builder->set_use_extensions(false);
- $phpbb_container_builder->set_dump_container(false);
+ $phpbb_container_builder->without_extensions();
+ $phpbb_container_builder->without_cache();
}
else
{
$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
$phpbb_class_loader_ext->register();
- phpbb_load_extensions_autoloaders($phpbb_root_path);
}
$phpbb_container = $phpbb_container_builder->get_container();
$phpbb_container->get('request')->enable_super_globals();
require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx);
+register_compatibility_globals();
+
+/* @var $user \phpbb\user */
$user = $phpbb_container->get('user');
$user->data['user_id'] = ANONYMOUS;
$user->ip = '127.0.0.1';
$user->add_lang('acp/common');
$user->add_lang('cli');
-$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $user);
+/* @var $lang \phpbb\language\language */
+$lang = $phpbb_container->get('language');
+
+$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $lang);
+$application->setDispatcher($phpbb_container->get('dispatcher'));
$application->register_container_commands($phpbb_container->get('console.command_collection'));
$application->run($input);
diff --git a/phpBB/common.php b/phpBB/common.php
index 71d501e926..d12966168b 100644
--- a/phpBB/common.php
+++ b/phpBB/common.php
@@ -12,7 +12,7 @@
*/
/**
-* Minimum Requirement: PHP 5.3.3
+* Minimum Requirement: PHP 5.3.9
*/
if (!defined('IN_PHPBB'))
@@ -29,6 +29,11 @@ $phpbb_class_loader->register();
$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
extract($phpbb_config_php_file->get_all());
+if (!defined('PHPBB_ENVIRONMENT'))
+{
+ @define('PHPBB_ENVIRONMENT', 'production');
+}
+
if (!defined('PHPBB_INSTALLED'))
{
// Redirect the user to the installer
@@ -53,14 +58,14 @@ if (!defined('PHPBB_INSTALLED'))
}
// $phpbb_root_path accounts for redirects from e.g. /adm
- $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/index.' . $phpEx;
+ $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/app.' . $phpEx;
// Replace any number of consecutive backslashes and/or slashes with a single slash
// (could happen on some proxy setups and/or Windows servers)
$script_path = preg_replace('#[\\\\/]{2,}#', '/', $script_path);
// Eliminate . and .. from the path
require($phpbb_root_path . 'phpbb/filesystem.' . $phpEx);
- $phpbb_filesystem = new phpbb\filesystem();
+ $phpbb_filesystem = new phpbb\filesystem\filesystem();
$script_path = $phpbb_filesystem->clean_path($script_path);
$url = (($secure) ? 'https://' : 'http://') . $server_name;
@@ -91,26 +96,51 @@ include($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx);
require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
+if (PHPBB_ENVIRONMENT === 'development')
+{
+ \phpbb\debug\debug::enable();
+}
+else
+{
+ set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
+}
$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
$phpbb_class_loader_ext->register();
-phpbb_load_extensions_autoloaders($phpbb_root_path);
-
// Set up container
-$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
-$phpbb_container = $phpbb_container_builder->get_container();
+try
+{
+ $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
+}
+catch (InvalidArgumentException $e)
+{
+ if (PHPBB_ENVIRONMENT !== 'development')
+ {
+ trigger_error(
+ 'The requested environment ' . PHPBB_ENVIRONMENT . ' is not available.',
+ E_USER_ERROR
+ );
+ }
+ else
+ {
+ throw $e;
+ }
+}
$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx);
+register_compatibility_globals();
+
// Add own hook handler
require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
$phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
+
+/* @var $phpbb_hook_finder \phpbb\hook\finder */
$phpbb_hook_finder = $phpbb_container->get('hook_finder');
foreach ($phpbb_hook_finder->find() as $hook)
diff --git a/phpBB/composer.json b/phpBB/composer.json
index 6b3a2c9918..ca6eb449bb 100644
--- a/phpBB/composer.json
+++ b/phpBB/composer.json
@@ -25,36 +25,51 @@
"phpbb/phpbb-core": "self.version"
},
"require": {
- "php": ">=5.3.3,<7.0",
- "lusitanian/oauth": "0.2.*",
- "symfony/config": "2.3.*",
- "symfony/console": "2.3.*",
- "symfony/dependency-injection": "2.3.*",
- "symfony/event-dispatcher": "2.3.*",
- "symfony/http-kernel": "2.3.*",
- "symfony/routing": "2.3.*",
- "symfony/yaml": "2.3.*",
- "twig/twig": "1.*"
+ "php": ">=5.4",
+ "bantu/ini-get-wrapper": "1.0.*",
+ "google/recaptcha": "~1.1",
+ "guzzlehttp/guzzle": "~5.3",
+ "lusitanian/oauth": "^0.8.1",
+ "marc1706/fast-image-size": "^1.1",
+ "paragonie/random_compat": "^2.0",
+ "patchwork/utf8": "^1.1",
+ "s9e/text-formatter": "~0.8.0",
+ "symfony/config": "^2.8",
+ "symfony/console": "^2.8",
+ "symfony/debug": "^2.8",
+ "symfony/dependency-injection": "^2.8",
+ "symfony/event-dispatcher": "^2.8",
+ "symfony/filesystem": "^2.8",
+ "symfony/finder": "^2.8",
+ "symfony/http-foundation": "^2.8",
+ "symfony/http-kernel": "^2.8",
+ "symfony/proxy-manager-bridge": "^2.8",
+ "symfony/routing": "^2.8",
+ "symfony/twig-bridge": "^2.8",
+ "symfony/yaml": "^2.8",
+ "twig/twig": "^1.0"
},
"require-dev": {
- "fabpot/goutte": "1.0.*",
+ "fabpot/goutte": "~2.0",
+ "facebook/webdriver": "~1.1",
+ "laravel/homestead": "~2.2",
"phing/phing": "2.4.*",
"phpunit/dbunit": "1.3.*",
"phpunit/phpunit": "4.1.*",
"sami/sami": "1.*",
"squizlabs/php_codesniffer": "2.*",
- "symfony/browser-kit": "2.3.*",
- "symfony/css-selector": "2.3.*",
- "symfony/debug": "2.3.*",
- "symfony/dom-crawler": "2.3.*",
- "symfony/filesystem": "2.3.*",
- "symfony/finder": "2.3.*",
- "symfony/http-foundation": "2.3.*",
- "symfony/process": "2.3.*"
+ "symfony/browser-kit": "^2.8",
+ "symfony/css-selector": "^2.8",
+ "symfony/dom-crawler": "^2.8"
},
"extra": {
"branch-alias": {
- "dev-master": "3.1.x-dev"
+ "dev-master": "3.2.x-dev"
+ }
+ },
+ "config": {
+ "platform": {
+ "php": "5.4"
}
}
}
diff --git a/phpBB/composer.lock b/phpBB/composer.lock
index 5d6b1ba7a7..158a4e24a9 100644
--- a/phpBB/composer.lock
+++ b/phpBB/composer.lock
@@ -4,21 +4,291 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "33fa9de480a8a9c8f7e3f2926cd4c034",
- "content-hash": "2d9c1857e65554ceb4cfa435495df188",
+ "hash": "f8c36b90de055ba0b43285a066e66805",
+ "content-hash": "1968761eb0667a7c4745caaf65992fe3",
"packages": [
{
+ "name": "bantu/ini-get-wrapper",
+ "version": "v1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/bantuXorg/php-ini-get-wrapper.git",
+ "reference": "4770c7feab370c62e23db4f31c112b7c6d90aee2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/bantuXorg/php-ini-get-wrapper/zipball/4770c7feab370c62e23db4f31c112b7c6d90aee2",
+ "reference": "4770c7feab370c62e23db4f31c112b7c6d90aee2",
+ "shasum": ""
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "bantu\\IniGetWrapper\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Convenience wrapper around ini_get()",
+ "time": "2014-09-15 13:12:35"
+ },
+ {
+ "name": "google/recaptcha",
+ "version": "1.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/google/recaptcha.git",
+ "reference": "2b7e00566afca82a38a1d3adb8e42c118006296e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/google/recaptcha/zipball/2b7e00566afca82a38a1d3adb8e42c118006296e",
+ "reference": "2b7e00566afca82a38a1d3adb8e42c118006296e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.5.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "ReCaptcha\\": "src/ReCaptcha"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Client library for reCAPTCHA, a free service that protect websites from spam and abuse.",
+ "homepage": "http://www.google.com/recaptcha/",
+ "keywords": [
+ "Abuse",
+ "captcha",
+ "recaptcha",
+ "spam"
+ ],
+ "time": "2015-09-02 17:23:59"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "5.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/70f1fa53b71c4647bf2762c09068a95f77e12fb8",
+ "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/ringphp": "^1.1",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2016-07-15 19:28:39"
+ },
+ {
+ "name": "guzzlehttp/ringphp",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/RingPHP.git",
+ "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
+ "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/streams": "~3.0",
+ "php": ">=5.4.0",
+ "react/promise": "~2.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0"
+ },
+ "suggest": {
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Ring\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "guzzlehttp/streams",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/streams.git",
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Stream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Provides a simple abstraction over streams of data",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "Guzzle",
+ "stream"
+ ],
+ "time": "2014-10-12 19:18:40"
+ },
+ {
+ "name": "ircmaxell/password-compat",
+ "version": "v1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ircmaxell/password_compat.git",
+ "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
+ "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
+ "shasum": ""
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/password.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Anthony Ferrara",
+ "email": "ircmaxell@php.net",
+ "homepage": "http://blog.ircmaxell.com"
+ }
+ ],
+ "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+ "homepage": "https://github.com/ircmaxell/password_compat",
+ "keywords": [
+ "hashing",
+ "password"
+ ],
+ "time": "2014-11-20 16:49:30"
+ },
+ {
"name": "lusitanian/oauth",
- "version": "v0.2.5",
+ "version": "v0.8.9",
"source": {
"type": "git",
"url": "https://github.com/Lusitanian/PHPoAuthLib.git",
- "reference": "27e375e13e1badcd6dca7fb47b154b3c48fdec0c"
+ "reference": "29bda6e176df6c292a9b1c43ae8a44d56a87c30b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/27e375e13e1badcd6dca7fb47b154b3c48fdec0c",
- "reference": "27e375e13e1badcd6dca7fb47b154b3c48fdec0c",
+ "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/29bda6e176df6c292a9b1c43ae8a44d56a87c30b",
+ "reference": "29bda6e176df6c292a9b1c43ae8a44d56a87c30b",
"shasum": ""
},
"require": {
@@ -27,9 +297,11 @@
"require-dev": {
"phpunit/phpunit": "3.7.*",
"predis/predis": "0.8.*@dev",
+ "squizlabs/php_codesniffer": "2.*",
"symfony/http-foundation": "~2.1"
},
"suggest": {
+ "ext-openssl": "Allows for usage of secure connections with the stream-based HTTP client.",
"predis/predis": "Allows using the Redis storage backend.",
"symfony/http-foundation": "Allows using the Symfony Session storage backend."
},
@@ -55,10 +327,12 @@
"email": "david@daviddesberg.com"
},
{
+ "name": "Elliot Chance",
+ "email": "elliotchance@gmail.com"
+ },
+ {
"name": "Pieter Hordijk",
- "email": "info@pieterhordijk.com",
- "homepage": "https://pieterhordijk.com",
- "role": "developer"
+ "email": "info@pieterhordijk.com"
}
],
"description": "PHP 5.3+ oAuth 1/2 Library",
@@ -68,26 +342,255 @@
"oauth",
"security"
],
- "time": "2013-12-25 20:05:42"
+ "time": "2016-02-24 00:20:18"
+ },
+ {
+ "name": "marc1706/fast-image-size",
+ "version": "v1.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/marc1706/fast-image-size.git",
+ "reference": "8bb644f8f767c5763acd61140045a78d10e1eb06"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/8bb644f8f767c5763acd61140045a78d10e1eb06",
+ "reference": "8bb644f8f767c5763acd61140045a78d10e1eb06",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "FastImageSize\\": "lib",
+ "FastImageSize\\tests\\": "tests"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marc Alexander",
+ "email": "admin@m-a-styles.de",
+ "homepage": "https://www.m-a-styles.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "fast-image-size is a PHP library that does almost everything PHP's getimagesize() does but without the large overhead of downloading the complete file.",
+ "homepage": "https://www.m-a-styles.de",
+ "keywords": [
+ "fast",
+ "getimagesize",
+ "image",
+ "imagesize",
+ "php",
+ "size"
+ ],
+ "time": "2016-10-30 19:00:39"
+ },
+ {
+ "name": "ocramius/proxy-manager",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Ocramius/ProxyManager.git",
+ "reference": "57e9272ec0e8deccf09421596e0e2252df440e11"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/57e9272ec0e8deccf09421596e0e2252df440e11",
+ "reference": "57e9272ec0e8deccf09421596e0e2252df440e11",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "zendframework/zend-code": ">2.2.5,<3.0"
+ },
+ "require-dev": {
+ "ext-phar": "*",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "1.5.*"
+ },
+ "suggest": {
+ "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects",
+ "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)",
+ "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)",
+ "zendframework/zend-stdlib": "To use the hydrator proxy",
+ "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "ProxyManager\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies",
+ "homepage": "https://github.com/Ocramius/ProxyManager",
+ "keywords": [
+ "aop",
+ "lazy loading",
+ "proxy",
+ "proxy pattern",
+ "service proxies"
+ ],
+ "time": "2015-08-09 04:28:19"
+ },
+ {
+ "name": "paragonie/random_compat",
+ "version": "v2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "c0125896dbb151380ab47e96c621741e79623beb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c0125896dbb151380ab47e96c621741e79623beb",
+ "reference": "c0125896dbb151380ab47e96c621741e79623beb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/random.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "pseudorandom",
+ "random"
+ ],
+ "time": "2016-10-17 15:23:22"
+ },
+ {
+ "name": "patchwork/utf8",
+ "version": "v1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/tchwork/utf8.git",
+ "reference": "30ec6451aec7d2536f0af8fe535f70c764f2c47a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/tchwork/utf8/zipball/30ec6451aec7d2536f0af8fe535f70c764f2c47a",
+ "reference": "30ec6451aec7d2536f0af8fe535f70c764f2c47a",
+ "shasum": ""
+ },
+ "require": {
+ "lib-pcre": ">=7.3",
+ "php": ">=5.3.0"
+ },
+ "suggest": {
+ "ext-iconv": "Use iconv for best performance",
+ "ext-intl": "Use Intl for best performance",
+ "ext-mbstring": "Use Mbstring for best performance",
+ "ext-wfio": "Use WFIO for UTF-8 filesystem access on Windows"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Patchwork\\": "src/Patchwork/"
+ },
+ "classmap": [
+ "src/Normalizer.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "(Apache-2.0 or GPL-2.0)"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ }
+ ],
+ "description": "Portable and performant UTF-8, Unicode and Grapheme Clusters for PHP",
+ "homepage": "https://github.com/tchwork/utf8",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "time": "2016-05-18 13:57:10"
},
{
"name": "psr/log",
- "version": "1.0.0",
+ "version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
+ "require": {
+ "php": ">=5.3.0"
+ },
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"autoload": {
- "psr-0": {
- "Psr\\Log\\": ""
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -101,40 +604,147 @@
}
],
"description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
- "time": "2012-12-21 11:40:51"
+ "time": "2016-10-10 12:19:37"
+ },
+ {
+ "name": "react/promise",
+ "version": "v2.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/promise.git",
+ "reference": "8025426794f1944de806618671d4fa476dc7626f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/8025426794f1944de806618671d4fa476dc7626f",
+ "reference": "8025426794f1944de806618671d4fa476dc7626f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com"
+ }
+ ],
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "time": "2016-05-03 17:50:52"
+ },
+ {
+ "name": "s9e/text-formatter",
+ "version": "0.8.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/s9e/TextFormatter.git",
+ "reference": "34668fccbe259fbca0331e7a34409c4502ee71bd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/34668fccbe259fbca0331e7a34409c4502ee71bd",
+ "reference": "34668fccbe259fbca0331e7a34409c4502ee71bd",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-filter": "*",
+ "lib-pcre": ">=7.2",
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-curl": "Improves the performance of the MediaEmbed plugin and some JavaScript minifiers",
+ "ext-intl": "Allows international URLs to be accepted by the URL filter",
+ "ext-json": "Enables the generation of a JavaScript parser",
+ "ext-mbstring": "Improves the performance of the PHP renderer",
+ "ext-tokenizer": "Improves the performance of the PHP renderer",
+ "ext-xsl": "Enables the XSLT renderer",
+ "ext-zlib": "Enables gzip compression when scraping content via the MediaEmbed plugin"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "s9e\\TextFormatter\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Multi-purpose text formatting and markup library. Plugins offer support for BBCodes, Markdown, emoticons, HTML, embedding media (YouTube, etc...), enhanced typography and more.",
+ "homepage": "https://github.com/s9e/TextFormatter/",
+ "keywords": [
+ "bbcode",
+ "bbcodes",
+ "blog",
+ "censor",
+ "embed",
+ "emoji",
+ "emoticons",
+ "engine",
+ "forum",
+ "html",
+ "markdown",
+ "markup",
+ "media",
+ "parser",
+ "shortcodes"
+ ],
+ "time": "2016-11-02 08:14:58"
},
{
"name": "symfony/config",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Config",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "16a645cef1c09ebfc907d3c9b3e9f5836a7d4d3b"
+ "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/16a645cef1c09ebfc907d3c9b3e9f5836a7d4d3b",
- "reference": "16a645cef1c09ebfc907d3c9b3e9f5836a7d4d3b",
+ "url": "https://api.github.com/repos/symfony/config/zipball/f8b1922bbda9d2ac86aecd649399040bce849fde",
+ "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde",
"shasum": ""
},
"require": {
- "php": ">=5.3.3",
- "symfony/filesystem": "~2.3"
+ "php": ">=5.3.9",
+ "symfony/filesystem": "~2.3|~3.0.0"
+ },
+ "suggest": {
+ "symfony/yaml": "To use the yaml reference dumper"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Config\\": ""
},
"exclude-from-classmap": [
@@ -157,40 +767,45 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2016-05-30 08:14:41"
+ "time": "2016-09-14 20:31:12"
},
{
"name": "symfony/console",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Console",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "20c12c6d6c5a087a66d4e77999451713a92a3507"
+ "reference": "7350016c8abcab897046f1aead2b766b84d3eff8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/20c12c6d6c5a087a66d4e77999451713a92a3507",
- "reference": "20c12c6d6c5a087a66d4e77999451713a92a3507",
+ "url": "https://api.github.com/repos/symfony/console/zipball/7350016c8abcab897046f1aead2b766b84d3eff8",
+ "reference": "7350016c8abcab897046f1aead2b766b84d3eff8",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9",
+ "symfony/debug": "~2.7,>=2.7.2|~3.0.0",
+ "symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
- "symfony/event-dispatcher": "~2.1"
+ "psr/log": "~1.0",
+ "symfony/event-dispatcher": "~2.1|~3.0.0",
+ "symfony/process": "~2.1|~3.0.0"
},
"suggest": {
- "symfony/event-dispatcher": ""
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
@@ -213,46 +828,41 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2016-05-26 08:04:58"
+ "time": "2016-10-06 01:43:09"
},
{
"name": "symfony/debug",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Debug",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "863d29c31a1ddfcf1faedf5f8362f392e3261632"
+ "reference": "8c29235936a47473af16fb91c7c4b7b193c5693c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/863d29c31a1ddfcf1faedf5f8362f392e3261632",
- "reference": "863d29c31a1ddfcf1faedf5f8362f392e3261632",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/8c29235936a47473af16fb91c7c4b7b193c5693c",
+ "reference": "8c29235936a47473af16fb91c7c4b7b193c5693c",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9",
+ "psr/log": "~1.0"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
- "symfony/http-foundation": "~2.1",
- "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2"
- },
- "suggest": {
- "symfony/class-loader": "",
- "symfony/http-foundation": "",
- "symfony/http-kernel": ""
+ "symfony/class-loader": "~2.2|~3.0.0",
+ "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2|~3.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
@@ -275,43 +885,47 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2016-03-30 09:02:35"
+ "time": "2016-09-06 10:55:00"
},
{
"name": "symfony/dependency-injection",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/DependencyInjection",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "06265ee128644eb70356bd72ab28c9ded6618d19"
+ "reference": "3d61c765daa1a5832f1d7c767f48886b8d8ea64c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/06265ee128644eb70356bd72ab28c9ded6618d19",
- "reference": "06265ee128644eb70356bd72ab28c9ded6618d19",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/3d61c765daa1a5832f1d7c767f48886b8d8ea64c",
+ "reference": "3d61c765daa1a5832f1d7c767f48886b8d8ea64c",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
+ },
+ "conflict": {
+ "symfony/expression-language": "<2.6"
},
"require-dev": {
- "symfony/config": "~2.2",
- "symfony/yaml": "~2.1"
+ "symfony/config": "~2.2|~3.0.0",
+ "symfony/expression-language": "~2.6|~3.0.0",
+ "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7"
},
"suggest": {
"symfony/config": "",
+ "symfony/expression-language": "For using expressions in service container configuration",
"symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
"symfony/yaml": ""
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\DependencyInjection\\": ""
},
"exclude-from-classmap": [
@@ -334,28 +948,31 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2016-05-30 08:31:06"
+ "time": "2016-10-24 15:52:36"
},
{
"name": "symfony/event-dispatcher",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/EventDispatcher",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "fd6d162d97bf3e6060622e5c015af39ca72e33bc"
+ "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fd6d162d97bf3e6060622e5c015af39ca72e33bc",
- "reference": "fd6d162d97bf3e6060622e5c015af39ca72e33bc",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
+ "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
},
"require-dev": {
- "symfony/dependency-injection": "~2.0,>=2.0.5"
+ "psr/log": "~1.0",
+ "symfony/config": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/dependency-injection": "~2.6|~3.0.0",
+ "symfony/expression-language": "~2.6|~3.0.0",
+ "symfony/stopwatch": "~2.3|~3.0.0"
},
"suggest": {
"symfony/dependency-injection": "",
@@ -364,11 +981,11 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
@@ -391,34 +1008,33 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2016-04-04 09:22:54"
+ "time": "2016-10-13 01:43:15"
},
{
"name": "symfony/filesystem",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Filesystem",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "8fd9cd1da0afe63f0d9d4f27875782a2b7d590d3"
+ "reference": "a3784111af9f95f102b6411548376e1ae7c93898"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/8fd9cd1da0afe63f0d9d4f27875782a2b7d590d3",
- "reference": "8fd9cd1da0afe63f0d9d4f27875782a2b7d590d3",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/a3784111af9f95f102b6411548376e1ae7c93898",
+ "reference": "a3784111af9f95f102b6411548376e1ae7c93898",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
@@ -441,40 +1057,90 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2016-04-12 15:20:10"
+ "time": "2016-10-18 04:28:30"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v2.8.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "bc24c8f5674c6f6841f2856b70e5d60784be5691"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/bc24c8f5674c6f6841f2856b70e5d60784be5691",
+ "reference": "bc24c8f5674c6f6841f2856b70e5d60784be5691",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Finder Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-28 00:10:16"
},
{
"name": "symfony/http-foundation",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/HttpFoundation",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "9f4dbb1f3e3cad22d9462e0306c9c71212458f61"
+ "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9f4dbb1f3e3cad22d9462e0306c9c71212458f61",
- "reference": "9f4dbb1f3e3cad22d9462e0306c9c71212458f61",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a6e6c34d337f3c74c39b29c5f54d33023de8897c",
+ "reference": "a6e6c34d337f3c74c39b29c5f54d33023de8897c",
"shasum": ""
},
"require": {
- "php": ">=5.3.3",
- "symfony/polyfill-mbstring": "~1.1"
+ "php": ">=5.3.9",
+ "symfony/polyfill-mbstring": "~1.1",
+ "symfony/polyfill-php54": "~1.0",
+ "symfony/polyfill-php55": "~1.0"
+ },
+ "require-dev": {
+ "symfony/expression-language": "~2.4|~3.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\HttpFoundation\\": ""
},
- "classmap": [
- "Symfony/Component/HttpFoundation/Resources/stubs"
- ],
"exclude-from-classmap": [
"/Tests/"
]
@@ -495,43 +1161,48 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
- "time": "2016-05-13 15:22:39"
+ "time": "2016-10-24 15:52:36"
},
{
"name": "symfony/http-kernel",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/HttpKernel",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "57e0329236e8edf2b0e683043c604f7c9aba9398"
+ "reference": "ba7249f746da1544512c942c50ef3bc4026296e6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/57e0329236e8edf2b0e683043c604f7c9aba9398",
- "reference": "57e0329236e8edf2b0e683043c604f7c9aba9398",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ba7249f746da1544512c942c50ef3bc4026296e6",
+ "reference": "ba7249f746da1544512c942c50ef3bc4026296e6",
"shasum": ""
},
"require": {
- "php": ">=5.3.3",
+ "php": ">=5.3.9",
"psr/log": "~1.0",
- "symfony/debug": "~2.3.24|~2.5.9|~2.6,>=2.6.2",
- "symfony/event-dispatcher": "~2.1",
- "symfony/http-foundation": "~2.3,>=2.3.4"
+ "symfony/debug": "~2.6,>=2.6.2",
+ "symfony/event-dispatcher": "~2.6,>=2.6.7|~3.0.0",
+ "symfony/http-foundation": "~2.7.20|~2.8.13|~3.1.6"
+ },
+ "conflict": {
+ "symfony/config": "<2.7"
},
"require-dev": {
- "symfony/browser-kit": "~2.3",
- "symfony/class-loader": "~2.1",
- "symfony/config": "~2.0,>=2.0.5",
- "symfony/console": "~2.2",
- "symfony/css-selector": "~2.0,>=2.0.5",
- "symfony/dependency-injection": "~2.2",
- "symfony/dom-crawler": "~2.0,>=2.0.5",
- "symfony/finder": "~2.0,>=2.0.5",
- "symfony/process": "~2.0,>=2.0.5",
- "symfony/routing": "~2.2",
- "symfony/stopwatch": "~2.3",
- "symfony/templating": "~2.2"
+ "symfony/browser-kit": "~2.3|~3.0.0",
+ "symfony/class-loader": "~2.1|~3.0.0",
+ "symfony/config": "~2.8",
+ "symfony/console": "~2.3|~3.0.0",
+ "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/dependency-injection": "~2.8|~3.0.0",
+ "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/expression-language": "~2.4|~3.0.0",
+ "symfony/finder": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/process": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/routing": "~2.8|~3.0.0",
+ "symfony/stopwatch": "~2.3|~3.0.0",
+ "symfony/templating": "~2.2|~3.0.0",
+ "symfony/translation": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/var-dumper": "~2.6|~3.0.0"
},
"suggest": {
"symfony/browser-kit": "",
@@ -539,16 +1210,17 @@
"symfony/config": "",
"symfony/console": "",
"symfony/dependency-injection": "",
- "symfony/finder": ""
+ "symfony/finder": "",
+ "symfony/var-dumper": ""
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\HttpKernel\\": ""
},
"exclude-from-classmap": [
@@ -571,7 +1243,7 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
- "time": "2016-05-30 08:41:10"
+ "time": "2016-10-27 02:18:22"
},
{
"name": "symfony/polyfill-mbstring",
@@ -633,43 +1305,218 @@
"time": "2016-05-18 14:26:46"
},
{
+ "name": "symfony/polyfill-php54",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php54.git",
+ "reference": "34d761992f6f2cc6092cc0e5e93f38b53ba5e4f1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/34d761992f6f2cc6092cc0e5e93f38b53ba5e4f1",
+ "reference": "34d761992f6f2cc6092cc0e5e93f38b53ba5e4f1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php54\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 5.4+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2016-05-18 14:26:46"
+ },
+ {
+ "name": "symfony/polyfill-php55",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php55.git",
+ "reference": "bf2ff9ad6be1a4772cb873e4eea94d70daa95c6d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/bf2ff9ad6be1a4772cb873e4eea94d70daa95c6d",
+ "reference": "bf2ff9ad6be1a4772cb873e4eea94d70daa95c6d",
+ "shasum": ""
+ },
+ "require": {
+ "ircmaxell/password-compat": "~1.0",
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php55\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 5.5+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2016-05-18 14:26:46"
+ },
+ {
+ "name": "symfony/proxy-manager-bridge",
+ "version": "v2.8.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/proxy-manager-bridge.git",
+ "reference": "69922100cdfe37bc9c0429cab5bd523e861e562e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/69922100cdfe37bc9c0429cab5bd523e861e562e",
+ "reference": "69922100cdfe37bc9c0429cab5bd523e861e562e",
+ "shasum": ""
+ },
+ "require": {
+ "ocramius/proxy-manager": "~0.4|~1.0|~2.0",
+ "php": ">=5.3.9",
+ "symfony/dependency-injection": "~2.8|~3.0.0"
+ },
+ "require-dev": {
+ "symfony/config": "~2.3|~3.0.0"
+ },
+ "type": "symfony-bridge",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\ProxyManager\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony ProxyManager Bridge",
+ "homepage": "https://symfony.com",
+ "time": "2016-10-03 15:49:46"
+ },
+ {
"name": "symfony/routing",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Routing",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "5b8a2bb7569df81401171829498809e90d6e446c"
+ "reference": "6cee3ed22c778a7410119a3d51a20f60252a156c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/5b8a2bb7569df81401171829498809e90d6e446c",
- "reference": "5b8a2bb7569df81401171829498809e90d6e446c",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/6cee3ed22c778a7410119a3d51a20f60252a156c",
+ "reference": "6cee3ed22c778a7410119a3d51a20f60252a156c",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
+ },
+ "conflict": {
+ "symfony/config": "<2.7"
},
"require-dev": {
+ "doctrine/annotations": "~1.0",
"doctrine/common": "~2.2",
"psr/log": "~1.0",
- "symfony/config": "~2.2",
- "symfony/http-foundation": "~2.3",
- "symfony/yaml": "~2.0,>=2.0.5"
+ "symfony/config": "~2.7|~3.0.0",
+ "symfony/expression-language": "~2.4|~3.0.0",
+ "symfony/http-foundation": "~2.3|~3.0.0",
+ "symfony/yaml": "~2.0,>=2.0.5|~3.0.0"
},
"suggest": {
- "doctrine/common": "",
- "symfony/config": "",
- "symfony/yaml": ""
+ "doctrine/annotations": "For using the annotation loader",
+ "symfony/config": "For using the all-in-one router or any loader",
+ "symfony/dependency-injection": "For loading routes from a service",
+ "symfony/expression-language": "For using expression matching",
+ "symfony/http-foundation": "For using a Symfony Request object",
+ "symfony/yaml": "For using the YAML loader"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Routing\\": ""
},
"exclude-from-classmap": [
@@ -692,34 +1539,120 @@
],
"description": "Symfony Routing Component",
"homepage": "https://symfony.com",
- "time": "2016-05-29 10:13:06"
+ "keywords": [
+ "router",
+ "routing",
+ "uri",
+ "url"
+ ],
+ "time": "2016-08-16 14:56:08"
+ },
+ {
+ "name": "symfony/twig-bridge",
+ "version": "v2.8.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/twig-bridge.git",
+ "reference": "b9df700554a19c9c00c662f2cd9fb3f03c0d4bcf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/b9df700554a19c9c00c662f2cd9fb3f03c0d4bcf",
+ "reference": "b9df700554a19c9c00c662f2cd9fb3f03c0d4bcf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9",
+ "twig/twig": "~1.27|~2.0"
+ },
+ "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.4",
+ "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-acl": "~2.6|~3.0.0",
+ "symfony/stopwatch": "~2.2|~3.0.0",
+ "symfony/templating": "~2.1|~3.0.0",
+ "symfony/translation": "~2.7|~3.0.0",
+ "symfony/var-dumper": "~2.7.16|~2.8.9|~3.0.9",
+ "symfony/yaml": "~2.0,>=2.0.5|~3.0.0"
+ },
+ "suggest": {
+ "symfony/asset": "For using the AssetExtension",
+ "symfony/expression-language": "For using the ExpressionExtension",
+ "symfony/finder": "",
+ "symfony/form": "For using the FormExtension",
+ "symfony/http-kernel": "For using the HttpKernelExtension",
+ "symfony/routing": "For using the RoutingExtension",
+ "symfony/security": "For using the SecurityExtension",
+ "symfony/stopwatch": "For using the StopwatchExtension",
+ "symfony/templating": "For using the TwigEngine",
+ "symfony/translation": "For using the TranslationExtension",
+ "symfony/var-dumper": "For using the DumpExtension",
+ "symfony/yaml": "For using the YamlExtension"
+ },
+ "type": "symfony-bridge",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\Twig\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Twig Bridge",
+ "homepage": "https://symfony.com",
+ "time": "2016-10-24 15:52:36"
},
{
"name": "symfony/yaml",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Yaml",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "2cb5f366f9e0df014fc93de46cc416ba0a3055f8"
+ "reference": "396784cd06b91f3db576f248f2402d547a077787"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/2cb5f366f9e0df014fc93de46cc416ba0a3055f8",
- "reference": "2cb5f366f9e0df014fc93de46cc416ba0a3055f8",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/396784cd06b91f3db576f248f2402d547a077787",
+ "reference": "396784cd06b91f3db576f248f2402d547a077787",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
@@ -742,20 +1675,20 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2016-05-30 08:10:17"
+ "time": "2016-10-21 20:59:10"
},
{
"name": "twig/twig",
- "version": "v1.24.1",
+ "version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512"
+ "reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512",
- "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
+ "reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
"shasum": ""
},
"require": {
@@ -768,7 +1701,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.24-dev"
+ "dev-master": "1.27-dev"
}
},
"autoload": {
@@ -803,245 +1736,285 @@
"keywords": [
"templating"
],
- "time": "2016-05-30 09:11:59"
- }
- ],
- "packages-dev": [
+ "time": "2016-10-25 19:17:17"
+ },
{
- "name": "fabpot/goutte",
- "version": "v1.0.7",
+ "name": "zendframework/zend-code",
+ "version": "2.5.1",
"source": {
"type": "git",
- "url": "https://github.com/FriendsOfPHP/Goutte.git",
- "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625"
+ "url": "https://github.com/zendframework/zend-code.git",
+ "reference": "5d998f261ec2a55171c71da57a11622745680153"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625",
- "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625",
+ "url": "https://api.github.com/repos/zendframework/zend-code/zipball/5d998f261ec2a55171c71da57a11622745680153",
+ "reference": "5d998f261ec2a55171c71da57a11622745680153",
"shasum": ""
},
"require": {
- "ext-curl": "*",
- "guzzle/http": "~3.1",
- "php": ">=5.3.0",
- "symfony/browser-kit": "~2.1",
- "symfony/css-selector": "~2.1",
- "symfony/dom-crawler": "~2.1",
- "symfony/finder": "~2.1",
- "symfony/process": "~2.1"
+ "php": ">=5.3.23",
+ "zendframework/zend-eventmanager": "~2.5"
},
"require-dev": {
- "guzzle/plugin-history": "~3.1",
- "guzzle/plugin-mock": "~3.1"
+ "doctrine/common": ">=2.1",
+ "fabpot/php-cs-fixer": "1.7.*",
+ "phpunit/phpunit": "~4.0",
+ "zendframework/zend-stdlib": "~2.5",
+ "zendframework/zend-version": "~2.5"
},
- "type": "application",
+ "suggest": {
+ "doctrine/common": "Doctrine\\Common >=2.1 for annotation features",
+ "zendframework/zend-stdlib": "Zend\\Stdlib component"
+ },
+ "type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-master": "2.5-dev",
+ "dev-develop": "2.6-dev"
}
},
"autoload": {
- "psr-0": {
- "Goutte": "."
+ "psr-4": {
+ "Zend\\Code\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
+ "BSD-3-Clause"
],
- "description": "A simple PHP Web Scraper",
- "homepage": "https://github.com/fabpot/Goutte",
+ "description": "provides facilities to generate arbitrary code using an object oriented interface",
+ "homepage": "https://github.com/zendframework/zend-code",
"keywords": [
- "scraper"
+ "code",
+ "zf2"
],
- "time": "2014-10-09 15:52:51"
+ "time": "2015-06-03 15:31:59"
},
{
- "name": "guzzle/common",
- "version": "v3.9.2",
- "target-dir": "Guzzle/Common",
+ "name": "zendframework/zend-eventmanager",
+ "version": "2.5.1",
"source": {
"type": "git",
- "url": "https://github.com/Guzzle3/common.git",
- "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc"
+ "url": "https://github.com/zendframework/zend-eventmanager.git",
+ "reference": "d94a16039144936f107f906896349900fd634443"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Guzzle3/common/zipball/2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc",
- "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc",
+ "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/d94a16039144936f107f906896349900fd634443",
+ "reference": "d94a16039144936f107f906896349900fd634443",
"shasum": ""
},
"require": {
- "php": ">=5.3.2",
- "symfony/event-dispatcher": ">=2.1"
+ "php": ">=5.3.23",
+ "zendframework/zend-stdlib": "~2.5"
+ },
+ "require-dev": {
+ "fabpot/php-cs-fixer": "1.7.*",
+ "phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.7-dev"
+ "dev-master": "2.5-dev",
+ "dev-develop": "2.6-dev"
}
},
"autoload": {
- "psr-0": {
- "Guzzle\\Common": ""
+ "psr-4": {
+ "Zend\\EventManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
- "description": "Common libraries used by Guzzle",
- "homepage": "http://guzzlephp.org/",
+ "homepage": "https://github.com/zendframework/zend-eventmanager",
"keywords": [
- "collection",
- "common",
- "event",
- "exception"
+ "eventmanager",
+ "zf2"
],
- "abandoned": "guzzle/guzzle",
- "time": "2014-08-11 04:32:36"
+ "time": "2015-06-03 15:32:01"
},
{
- "name": "guzzle/http",
- "version": "v3.9.2",
- "target-dir": "Guzzle/Http",
+ "name": "zendframework/zend-stdlib",
+ "version": "2.5.1",
"source": {
"type": "git",
- "url": "https://github.com/Guzzle3/http.git",
- "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5"
+ "url": "https://github.com/zendframework/zend-stdlib.git",
+ "reference": "cc8e90a60dd5d44b9730b77d07b97550091da1ae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Guzzle3/http/zipball/1e8dd1e2ba9dc42332396f39fbfab950b2301dc5",
- "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5",
+ "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/cc8e90a60dd5d44b9730b77d07b97550091da1ae",
+ "reference": "cc8e90a60dd5d44b9730b77d07b97550091da1ae",
"shasum": ""
},
"require": {
- "guzzle/common": "self.version",
- "guzzle/parser": "self.version",
- "guzzle/stream": "self.version",
- "php": ">=5.3.2"
+ "php": ">=5.3.23"
+ },
+ "require-dev": {
+ "fabpot/php-cs-fixer": "1.7.*",
+ "phpunit/phpunit": "~4.0",
+ "zendframework/zend-config": "~2.5",
+ "zendframework/zend-eventmanager": "~2.5",
+ "zendframework/zend-filter": "~2.5",
+ "zendframework/zend-inputfilter": "~2.5",
+ "zendframework/zend-serializer": "~2.5",
+ "zendframework/zend-servicemanager": "~2.5"
},
"suggest": {
- "ext-curl": "*"
+ "zendframework/zend-eventmanager": "To support aggregate hydrator usage",
+ "zendframework/zend-filter": "To support naming strategy hydrator usage",
+ "zendframework/zend-serializer": "Zend\\Serializer component",
+ "zendframework/zend-servicemanager": "To support hydrator plugin manager usage"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.7-dev"
+ "dev-master": "2.5-dev",
+ "dev-develop": "2.6-dev"
}
},
"autoload": {
- "psr-0": {
- "Guzzle\\Http": ""
+ "psr-4": {
+ "Zend\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
- }
+ "BSD-3-Clause"
],
- "description": "HTTP libraries used by Guzzle",
- "homepage": "http://guzzlephp.org/",
+ "homepage": "https://github.com/zendframework/zend-stdlib",
"keywords": [
- "Guzzle",
- "client",
- "curl",
- "http",
- "http client"
+ "stdlib",
+ "zf2"
],
- "abandoned": "guzzle/guzzle",
- "time": "2014-08-11 04:32:36"
- },
+ "time": "2015-06-03 15:32:03"
+ }
+ ],
+ "packages-dev": [
{
- "name": "guzzle/parser",
- "version": "v3.9.2",
- "target-dir": "Guzzle/Parser",
+ "name": "fabpot/goutte",
+ "version": "v2.0.4",
"source": {
"type": "git",
- "url": "https://github.com/Guzzle3/parser.git",
- "reference": "6874d171318a8e93eb6d224cf85e4678490b625c"
+ "url": "https://github.com/FriendsOfPHP/Goutte.git",
+ "reference": "0ad3ee6dc2d0aaa832a80041a1e09bf394e99802"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Guzzle3/parser/zipball/6874d171318a8e93eb6d224cf85e4678490b625c",
- "reference": "6874d171318a8e93eb6d224cf85e4678490b625c",
+ "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/0ad3ee6dc2d0aaa832a80041a1e09bf394e99802",
+ "reference": "0ad3ee6dc2d0aaa832a80041a1e09bf394e99802",
"shasum": ""
},
"require": {
- "php": ">=5.3.2"
+ "guzzlehttp/guzzle": ">=4,<6",
+ "php": ">=5.4.0",
+ "symfony/browser-kit": "~2.1",
+ "symfony/css-selector": "~2.1",
+ "symfony/dom-crawler": "~2.1"
},
- "type": "library",
+ "type": "application",
"extra": {
"branch-alias": {
- "dev-master": "3.7-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
- "psr-0": {
- "Guzzle\\Parser": ""
+ "psr-4": {
+ "Goutte\\": "Goutte"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "Interchangeable parsers used by Guzzle",
- "homepage": "http://guzzlephp.org/",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "A simple PHP Web Scraper",
+ "homepage": "https://github.com/FriendsOfPHP/Goutte",
"keywords": [
- "URI Template",
- "cookie",
- "http",
- "message",
- "url"
+ "scraper"
],
- "abandoned": "guzzle/guzzle",
- "time": "2014-02-05 18:29:46"
+ "time": "2015-05-05 21:14:57"
},
{
- "name": "guzzle/stream",
- "version": "v3.9.2",
- "target-dir": "Guzzle/Stream",
+ "name": "facebook/webdriver",
+ "version": "1.1.3",
"source": {
"type": "git",
- "url": "https://github.com/Guzzle3/stream.git",
- "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0"
+ "url": "https://github.com/facebook/php-webdriver.git",
+ "reference": "b7186fb1bcfda956d237f59face250d06ef47253"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Guzzle3/stream/zipball/60c7fed02e98d2c518dae8f97874c8f4622100f0",
- "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0",
+ "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/b7186fb1bcfda956d237f59face250d06ef47253",
+ "reference": "b7186fb1bcfda956d237f59face250d06ef47253",
"shasum": ""
},
"require": {
- "guzzle/common": "self.version",
- "php": ">=5.3.2"
+ "ext-curl": "*",
+ "php": ">=5.3.19"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^1.11",
+ "phpunit/phpunit": "4.6.* || ~5.0",
+ "squizlabs/php_codesniffer": "^2.6"
},
"suggest": {
- "guzzle/http": "To convert Guzzle request objects to PHP streams"
+ "phpdocumentor/phpdocumentor": "2.*"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.7-dev"
+ "autoload": {
+ "psr-4": {
+ "Facebook\\WebDriver\\": "lib/"
}
},
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "A PHP client for WebDriver",
+ "homepage": "https://github.com/facebook/php-webdriver",
+ "keywords": [
+ "facebook",
+ "php",
+ "selenium",
+ "webdriver"
+ ],
+ "time": "2016-08-10 00:44:08"
+ },
+ {
+ "name": "laravel/homestead",
+ "version": "v2.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/homestead.git",
+ "reference": "f4e45f895d8707042c2d0698627d33c484e7c6ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/homestead/zipball/f4e45f895d8707042c2d0698627d33c484e7c6ba",
+ "reference": "f4e45f895d8707042c2d0698627d33c484e7c6ba",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4",
+ "symfony/console": "~2.0 || ~3.0",
+ "symfony/process": "~2.0 || ~3.0"
+ },
+ "bin": [
+ "homestead"
+ ],
+ "type": "library",
"autoload": {
- "psr-0": {
- "Guzzle\\Stream": ""
+ "psr-4": {
+ "Laravel\\Homestead\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1050,33 +2023,25 @@
],
"authors": [
{
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
+ "name": "Taylor Otwell",
+ "email": "taylorotwell@gmail.com"
}
],
- "description": "Guzzle stream wrapper component",
- "homepage": "http://guzzlephp.org/",
- "keywords": [
- "Guzzle",
- "component",
- "stream"
- ],
- "abandoned": "guzzle/guzzle",
- "time": "2014-05-01 21:36:02"
+ "description": "A virtual machine for web artisans.",
+ "time": "2016-09-17 04:42:33"
},
{
"name": "michelf/php-markdown",
- "version": "1.6.0",
+ "version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
- "reference": "156e56ee036505ec637d761ee62dc425d807183c"
+ "reference": "1f51cc520948f66cd2af8cbc45a5ee175e774220"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c",
- "reference": "156e56ee036505ec637d761ee62dc425d807183c",
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/1f51cc520948f66cd2af8cbc45a5ee175e774220",
+ "reference": "1f51cc520948f66cd2af8cbc45a5ee175e774220",
"shasum": ""
},
"require": {
@@ -1114,7 +2079,7 @@
"keywords": [
"markdown"
],
- "time": "2015-12-24 01:37:31"
+ "time": "2016-10-29 18:58:20"
},
{
"name": "nikic/php-parser",
@@ -1679,9 +2644,7 @@
"authors": [
{
"name": "Fabien Potencier",
- "email": "fabien@symfony.com",
- "homepage": "http://fabien.potencier.org",
- "role": "Lead Developer"
+ "email": "fabien@symfony.com"
}
],
"description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
@@ -1867,23 +2830,23 @@
},
{
"name": "sebastian/environment",
- "version": "1.3.7",
+ "version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
+ "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
- "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
+ "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^5.3.3 || ^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.4"
+ "phpunit/phpunit": "^4.8 || ^5.0"
},
"type": "library",
"extra": {
@@ -1913,7 +2876,7 @@
"environment",
"hhvm"
],
- "time": "2016-05-17 03:18:57"
+ "time": "2016-08-18 05:49:44"
},
{
"name": "sebastian/exporter",
@@ -2072,16 +3035,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "2.6.2",
+ "version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83"
+ "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4edb770cb853def6e60c93abb088ad5ac2010c83",
- "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
+ "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
"shasum": ""
},
"require": {
@@ -2146,30 +3109,29 @@
"phpcs",
"standards"
],
- "time": "2016-07-13 23:29:13"
+ "time": "2016-09-01 23:53:02"
},
{
"name": "symfony/browser-kit",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/BrowserKit",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
- "reference": "0fca8e3490f003262258dcf67c329691913642e5"
+ "reference": "165bf6d1e72cd72f2fe170a070aa2a1f17f2d744"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/browser-kit/zipball/0fca8e3490f003262258dcf67c329691913642e5",
- "reference": "0fca8e3490f003262258dcf67c329691913642e5",
+ "url": "https://api.github.com/repos/symfony/browser-kit/zipball/165bf6d1e72cd72f2fe170a070aa2a1f17f2d744",
+ "reference": "165bf6d1e72cd72f2fe170a070aa2a1f17f2d744",
"shasum": ""
},
"require": {
- "php": ">=5.3.3",
- "symfony/dom-crawler": "~2.0,>=2.0.5"
+ "php": ">=5.3.9",
+ "symfony/dom-crawler": "~2.1|~3.0.0"
},
"require-dev": {
- "symfony/css-selector": "~2.0,>=2.0.5",
- "symfony/process": "~2.3.34|~2.7,>=2.7.6"
+ "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/process": "~2.3.34|~2.7,>=2.7.6|~3.0.0"
},
"suggest": {
"symfony/process": ""
@@ -2177,11 +3139,11 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\BrowserKit\\": ""
},
"exclude-from-classmap": [
@@ -2204,34 +3166,33 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
- "time": "2016-03-04 07:12:06"
+ "time": "2016-09-06 10:55:00"
},
{
"name": "symfony/css-selector",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/CssSelector",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "e750fff4bd738e54414fbfdd48ede6b0e99ab808"
+ "reference": "71c8c3a04c126300c37089b1baa7c6322dfb845f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/e750fff4bd738e54414fbfdd48ede6b0e99ab808",
- "reference": "e750fff4bd738e54414fbfdd48ede6b0e99ab808",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/71c8c3a04c126300c37089b1baa7c6322dfb845f",
+ "reference": "71c8c3a04c126300c37089b1baa7c6322dfb845f",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\CssSelector\\": ""
},
"exclude-from-classmap": [
@@ -2258,28 +3219,28 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
- "time": "2016-03-04 07:12:06"
+ "time": "2016-09-06 10:55:00"
},
{
"name": "symfony/dom-crawler",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/DomCrawler",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "b1a52aeafe4dd31914c75e72fc9b9ca3a3e5981d"
+ "reference": "a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b1a52aeafe4dd31914c75e72fc9b9ca3a3e5981d",
- "reference": "b1a52aeafe4dd31914c75e72fc9b9ca3a3e5981d",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4",
+ "reference": "a94f3fe6f179d6453e5ed8188cf4bfdf933d85f4",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9",
+ "symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
- "symfony/css-selector": "~2.0,>=2.0.5"
+ "symfony/css-selector": "~2.8|~3.0.0"
},
"suggest": {
"symfony/css-selector": ""
@@ -2287,11 +3248,11 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\DomCrawler\\": ""
},
"exclude-from-classmap": [
@@ -2314,84 +3275,33 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
- "time": "2016-04-06 13:13:46"
- },
- {
- "name": "symfony/finder",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Finder",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/finder.git",
- "reference": "dce4b58434fc1cbd66e3006e539bb53074dfea82"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/dce4b58434fc1cbd66e3006e539bb53074dfea82",
- "reference": "dce4b58434fc1cbd66e3006e539bb53074dfea82",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.3-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\Finder\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Finder Component",
- "homepage": "https://symfony.com",
- "time": "2016-05-13 14:58:35"
+ "time": "2016-10-18 15:35:45"
},
{
"name": "symfony/process",
- "version": "v2.3.42",
- "target-dir": "Symfony/Component/Process",
+ "version": "v2.8.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "89aced1438655ad81fc828c2e2e555e9b88fef3b"
+ "reference": "024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/89aced1438655ad81fc828c2e2e555e9b88fef3b",
- "reference": "89aced1438655ad81fc828c2e2e555e9b88fef3b",
+ "url": "https://api.github.com/repos/symfony/process/zipball/024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f",
+ "reference": "024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
@@ -2414,7 +3324,7 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2016-03-31 08:39:43"
+ "time": "2016-09-29 14:03:54"
}
],
"aliases": [],
@@ -2423,7 +3333,10 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=5.3.3,<7.0"
+ "php": ">=5.4"
},
- "platform-dev": []
+ "platform-dev": [],
+ "platform-overrides": {
+ "php": "5.4"
+ }
}
diff --git a/phpBB/config/auth.yml b/phpBB/config/auth.yml
deleted file mode 100644
index ef06080d38..0000000000
--- a/phpBB/config/auth.yml
+++ /dev/null
@@ -1,101 +0,0 @@
-services:
-# ----- Auth management -----
- auth:
- class: phpbb\auth\auth
-
-# ----- Auth providers -----
- auth.provider_collection:
- class: phpbb\auth\provider_collection
- arguments:
- - @service_container
- - @config
- tags:
- - { name: service_collection, tag: auth.provider }
-
- auth.provider.db:
- class: phpbb\auth\provider\db
- arguments:
- - @dbal.conn
- - @config
- - @passwords.manager
- - @request
- - @user
- - @service_container
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: auth.provider }
-
- auth.provider.apache:
- class: phpbb\auth\provider\apache
- arguments:
- - @dbal.conn
- - @config
- - @passwords.manager
- - @request
- - @user
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: auth.provider }
-
- auth.provider.ldap:
- class: phpbb\auth\provider\ldap
- arguments:
- - @dbal.conn
- - @config
- - @passwords.manager
- - @user
- tags:
- - { name: auth.provider }
-
- auth.provider.oauth:
- class: phpbb\auth\provider\oauth\oauth
- arguments:
- - @dbal.conn
- - @config
- - @passwords.manager
- - @request
- - @user
- - %tables.auth_provider_oauth_token_storage%
- - %tables.auth_provider_oauth_account_assoc%
- - @auth.provider.oauth.service_collection
- - %tables.users%
- - @service_container
- - @dispatcher
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: auth.provider }
-
-# ----- OAuth services providers -----
- auth.provider.oauth.service_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: auth.provider.oauth.service }
-
- auth.provider.oauth.service.bitly:
- class: phpbb\auth\provider\oauth\service\bitly
- arguments:
- - @config
- - @request
- tags:
- - { name: auth.provider.oauth.service }
-
- auth.provider.oauth.service.facebook:
- class: phpbb\auth\provider\oauth\service\facebook
- arguments:
- - @config
- - @request
- tags:
- - { name: auth.provider.oauth.service }
-
- auth.provider.oauth.service.google:
- class: phpbb\auth\provider\oauth\service\google
- arguments:
- - @config
- - @request
- tags:
- - { name: auth.provider.oauth.service }
diff --git a/phpBB/config/avatar.yml b/phpBB/config/avatar.yml
deleted file mode 100644
index b0dca137b0..0000000000
--- a/phpBB/config/avatar.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-services:
- avatar.manager:
- class: phpbb\avatar\manager
- arguments:
- - @config
- - @avatar.driver_collection
-
-# ----- Avatar drivers -----
- avatar.driver_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: avatar.driver }
-
- avatar.driver.gravatar:
- class: phpbb\avatar\driver\gravatar
- arguments:
- - @config
- - %core.root_path%
- - %core.php_ext%
- - @path_helper
- - @cache.driver
- calls:
- - [set_name, [avatar.driver.gravatar]]
- tags:
- - { name: avatar.driver }
-
- avatar.driver.local:
- class: phpbb\avatar\driver\local
- arguments:
- - @config
- - %core.root_path%
- - %core.php_ext%
- - @path_helper
- - @cache.driver
- calls:
- - [set_name, [avatar.driver.local]]
- tags:
- - { name: avatar.driver }
-
- avatar.driver.remote:
- class: phpbb\avatar\driver\remote
- arguments:
- - @config
- - %core.root_path%
- - %core.php_ext%
- - @path_helper
- - @cache.driver
- calls:
- - [set_name, [avatar.driver.remote]]
- tags:
- - { name: avatar.driver }
-
- avatar.driver.upload:
- class: phpbb\avatar\driver\upload
- arguments:
- - @config
- - %core.root_path%
- - %core.php_ext%
- - @path_helper
- - @mimetype.guesser
- - @dispatcher
- - @cache.driver
- calls:
- - [set_name, [avatar.driver.upload]]
- tags:
- - { name: avatar.driver }
diff --git a/phpBB/config/captcha.yml b/phpBB/config/captcha.yml
deleted file mode 100644
index e3f617e909..0000000000
--- a/phpBB/config/captcha.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-services:
- captcha.factory:
- class: phpbb\captcha\factory
- arguments:
- - @service_container
- - @captcha.plugins.service_collection
-
-# ----- Captcha plugins -----
-# Scope MUST be prototype for all the plugins to work.
- captcha.plugins.service_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: captcha.plugins }
-
- core.captcha.plugins.gd:
- class: phpbb\captcha\plugins\gd
- scope: prototype
- calls:
- - [set_name, [core.captcha.plugins.gd]]
- tags:
- - { name: captcha.plugins }
-
- core.captcha.plugins.gd_wave:
- class: phpbb\captcha\plugins\gd_wave
- scope: prototype
- calls:
- - [set_name, [core.captcha.plugins.gd_wave]]
- tags:
- - { name: captcha.plugins }
-
- core.captcha.plugins.nogd:
- class: phpbb\captcha\plugins\nogd
- scope: prototype
- calls:
- - [set_name, [core.captcha.plugins.nogd]]
- tags:
- - { name: captcha.plugins }
-
- core.captcha.plugins.qa:
- class: phpbb\captcha\plugins\qa
- scope: prototype
- arguments:
- - %tables.captcha_qa_questions%
- - %tables.captcha_qa_answers%
- - %tables.captcha_qa_confirm%
- calls:
- - [set_name, [core.captcha.plugins.qa]]
- tags:
- - { name: captcha.plugins }
-
- core.captcha.plugins.recaptcha:
- class: phpbb\captcha\plugins\recaptcha
- scope: prototype
- calls:
- - [set_name, [core.captcha.plugins.recaptcha]]
- tags:
- - { name: captcha.plugins }
diff --git a/phpBB/config/console.yml b/phpBB/config/console.yml
deleted file mode 100644
index 1e18a7dd37..0000000000
--- a/phpBB/config/console.yml
+++ /dev/null
@@ -1,141 +0,0 @@
-services:
- console.command_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: console.command }
-
- console.command.cache.purge:
- class: phpbb\console\command\cache\purge
- arguments:
- - @user
- - @cache.driver
- - @dbal.conn
- - @auth
- - @log
- - @config
- tags:
- - { name: console.command }
-
- console.command.config.delete:
- class: phpbb\console\command\config\delete
- arguments:
- - @user
- - @config
- tags:
- - { name: console.command }
-
- console.command.config.increment:
- class: phpbb\console\command\config\increment
- arguments:
- - @user
- - @config
- tags:
- - { name: console.command }
-
- console.command.config.get:
- class: phpbb\console\command\config\get
- arguments:
- - @user
- - @config
- tags:
- - { name: console.command }
-
- console.command.config.set:
- class: phpbb\console\command\config\set
- arguments:
- - @user
- - @config
- tags:
- - { name: console.command }
-
- console.command.config.set_atomic:
- class: phpbb\console\command\config\set_atomic
- arguments:
- - @user
- - @config
- tags:
- - { name: console.command }
-
- console.command.cron.list:
- class: phpbb\console\command\cron\cron_list
- arguments:
- - @user
- - @cron.manager
- tags:
- - { name: console.command }
-
- console.command.cron.run:
- class: phpbb\console\command\cron\run
- arguments:
- - @user
- - @cron.manager
- - @cron.lock_db
- tags:
- - { name: console.command }
-
- console.command.db.migrate:
- class: phpbb\console\command\db\migrate
- arguments:
- - @user
- - @migrator
- - @ext.manager
- - @config
- - @cache
- - @log
- - %core.root_path%
- tags:
- - { name: console.command }
-
- console.command.dev.migration_tips:
- class: phpbb\console\command\dev\migration_tips
- arguments:
- - @user
- - @ext.manager
- tags:
- - { name: console.command }
-
- console.command.extension.disable:
- class: phpbb\console\command\extension\disable
- arguments:
- - @user
- - @ext.manager
- - @log
- tags:
- - { name: console.command }
-
- console.command.extension.enable:
- class: phpbb\console\command\extension\enable
- arguments:
- - @user
- - @ext.manager
- - @log
- tags:
- - { name: console.command }
-
- console.command.extension.purge:
- class: phpbb\console\command\extension\purge
- arguments:
- - @user
- - @ext.manager
- - @log
- tags:
- - { name: console.command }
-
- console.command.extension.show:
- class: phpbb\console\command\extension\show
- arguments:
- - @user
- - @ext.manager
- - @log
- tags:
- - { name: console.command }
-
- console.command.fixup.recalculate_email_hash:
- class: phpbb\console\command\fixup\recalculate_email_hash
- arguments:
- - @user
- - @dbal.conn
- tags:
- - { name: console.command }
diff --git a/phpBB/config/content.yml b/phpBB/config/content.yml
deleted file mode 100644
index 4d9ee31335..0000000000
--- a/phpBB/config/content.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-services:
- content.visibility:
- class: phpbb\content_visibility
- arguments:
- - @auth
- - @config
- - @dispatcher
- - @dbal.conn
- - @user
- - %core.root_path%
- - %core.php_ext%
- - %tables.forums%
- - %tables.posts%
- - %tables.topics%
- - %tables.users%
-
- groupposition.legend:
- class: phpbb\groupposition\legend
- arguments:
- - @dbal.conn
- - @user
-
- groupposition.teampage:
- class: phpbb\groupposition\teampage
- arguments:
- - @dbal.conn
- - @user
- - @cache.driver
-
- message.form.admin:
- class: phpbb\message\admin_form
- arguments:
- - @auth
- - @config
- - @config_text
- - @dbal.conn
- - @user
- - %core.root_path%
- - %core.php_ext%
-
- message.form.topic:
- class: phpbb\message\topic_form
- arguments:
- - @auth
- - @config
- - @dbal.conn
- - @user
- - %core.root_path%
- - %core.php_ext%
-
- message.form.user:
- class: phpbb\message\user_form
- arguments:
- - @auth
- - @config
- - @dbal.conn
- - @user
- - %core.root_path%
- - %core.php_ext%
-
- pagination:
- class: phpbb\pagination
- arguments:
- - @template
- - @user
- - @controller.helper
- - @dispatcher
-
- viewonline_helper:
- class: phpbb\viewonline_helper
- arguments:
- - @filesystem
diff --git a/phpBB/config/cron.yml b/phpBB/config/cron.yml
deleted file mode 100644
index c5b88df181..0000000000
--- a/phpBB/config/cron.yml
+++ /dev/null
@@ -1,148 +0,0 @@
-services:
- cron.manager:
- class: phpbb\cron\manager
- arguments:
- - @cron.task_collection
- - %core.root_path%
- - %core.php_ext%
-
- cron.lock_db:
- class: phpbb\lock\db
- arguments:
- - cron_lock
- - @config
- - @dbal.conn
-
-# ----- Cron tasks -----
- cron.task_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: cron.task }
-
- cron.task.core.prune_all_forums:
- class: phpbb\cron\task\core\prune_all_forums
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @config
- - @dbal.conn
- calls:
- - [set_name, [cron.task.core.prune_all_forums]]
- tags:
- - { name: cron.task }
-
- cron.task.core.prune_forum:
- class: phpbb\cron\task\core\prune_forum
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @config
- - @dbal.conn
- calls:
- - [set_name, [cron.task.core.prune_forum]]
- tags:
- - { name: cron.task }
-
- cron.task.core.prune_shadow_topics:
- class: phpbb\cron\task\core\prune_shadow_topics
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @config
- - @dbal.conn
- - @log
- - @user
- calls:
- - [set_name, [cron.task.core.prune_shadow_topics]]
- tags:
- - { name: cron.task }
-
- cron.task.core.prune_notifications:
- class: phpbb\cron\task\core\prune_notifications
- arguments:
- - @config
- - @notification_manager
- calls:
- - [set_name, [cron.task.core.prune_notifications]]
- tags:
- - { name: cron.task }
-
- cron.task.core.queue:
- class: phpbb\cron\task\core\queue
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @config
- calls:
- - [set_name, [cron.task.core.queue]]
- tags:
- - { name: cron.task }
-
- cron.task.core.tidy_cache:
- class: phpbb\cron\task\core\tidy_cache
- arguments:
- - @config
- - @cache.driver
- calls:
- - [set_name, [cron.task.core.tidy_cache]]
- tags:
- - { name: cron.task }
-
- cron.task.core.tidy_database:
- class: phpbb\cron\task\core\tidy_database
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @config
- calls:
- - [set_name, [cron.task.core.tidy_database]]
- tags:
- - { name: cron.task }
-
- cron.task.core.tidy_plupload:
- class: phpbb\cron\task\core\tidy_plupload
- arguments:
- - %core.root_path%
- - @config
- calls:
- - [set_name, [cron.task.core.tidy_plupload]]
- tags:
- - { name: cron.task }
-
- cron.task.core.tidy_search:
- class: phpbb\cron\task\core\tidy_search
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @auth
- - @config
- - @dbal.conn
- - @user
- - @dispatcher
- calls:
- - [set_name, [cron.task.core.tidy_search]]
- tags:
- - { name: cron.task }
-
- cron.task.core.tidy_sessions:
- class: phpbb\cron\task\core\tidy_sessions
- arguments:
- - @config
- - @user
- calls:
- - [set_name, [cron.task.core.tidy_sessions]]
- tags:
- - { name: cron.task }
-
- cron.task.core.tidy_warnings:
- class: phpbb\cron\task\core\tidy_warnings
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @config
- calls:
- - [set_name, [cron.task.core.tidy_warnings]]
- tags:
- - { name: cron.task }
diff --git a/phpBB/config/db.yml b/phpBB/config/db.yml
deleted file mode 100644
index d11669d8a3..0000000000
--- a/phpBB/config/db.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-services:
- dbal.conn:
- class: phpbb\db\driver\factory
- arguments:
- - @service_container
-
- dbal.conn.driver:
- class: %dbal.driver.class%
- calls:
- - [sql_connect, [%dbal.dbhost%, %dbal.dbuser%, %dbal.dbpasswd%, %dbal.dbname%, %dbal.dbport%, false, %dbal.new_link%]]
-
- dbal.tools:
- class: phpbb\db\tools
- arguments:
- - @dbal.conn
-
-# ----- Migrator -----
- migrator:
- class: phpbb\db\migrator
- arguments:
- - @service_container
- - @config
- - @dbal.conn
- - @dbal.tools
- - %tables.migrations%
- - %core.root_path%
- - %core.php_ext%
- - %core.table_prefix%
- - @migrator.tool_collection
- - @migrator.helper
-
- migrator.helper:
- class: phpbb\db\migration\helper
-
-# ----- Migrator's tools -----
- migrator.tool_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: migrator.tool }
-
- migrator.tool.config:
- class: phpbb\db\migration\tool\config
- arguments:
- - @config
- tags:
- - { name: migrator.tool }
-
- migrator.tool.config_text:
- class: phpbb\db\migration\tool\config_text
- arguments:
- - @config_text
- tags:
- - { name: migrator.tool }
-
- migrator.tool.module:
- class: phpbb\db\migration\tool\module
- arguments:
- - @dbal.conn
- - @cache
- - @user
- - %core.root_path%
- - %core.php_ext%
- - %tables.modules%
- tags:
- - { name: migrator.tool }
-
- migrator.tool.permission:
- class: phpbb\db\migration\tool\permission
- arguments:
- - @dbal.conn
- - @cache
- - @auth
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: migrator.tool }
diff --git a/phpBB/config/default/config.yml b/phpBB/config/default/config.yml
new file mode 100644
index 0000000000..e8d0536287
--- /dev/null
+++ b/phpBB/config/default/config.yml
@@ -0,0 +1 @@
+# phpBB's config file (This line is needed because of the packager)
diff --git a/phpBB/config/parameters.yml b/phpBB/config/default/container/parameters.yml
index 8ecc1428f4..8ecc1428f4 100644
--- a/phpBB/config/parameters.yml
+++ b/phpBB/config/default/container/parameters.yml
diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml
new file mode 100644
index 0000000000..2ccda6a38e
--- /dev/null
+++ b/phpBB/config/default/container/services.yml
@@ -0,0 +1,169 @@
+imports:
+ - { resource: services_attachment.yml }
+ - { resource: services_auth.yml }
+ - { resource: services_avatar.yml }
+ - { resource: services_captcha.yml }
+ - { resource: services_console.yml }
+ - { resource: services_content.yml }
+ - { resource: services_cron.yml }
+ - { resource: services_db.yml }
+ - { resource: services_event.yml }
+ - { resource: services_feed.yml }
+ - { resource: services_files.yml }
+ - { resource: services_filesystem.yml }
+ - { resource: services_help.yml }
+ - { resource: services_hook.yml }
+ - { resource: services_http.yml }
+ - { resource: services_language.yml }
+ - { resource: services_migrator.yml }
+ - { resource: services_mimetype_guesser.yml }
+ - { resource: services_module.yml }
+ - { resource: services_notification.yml }
+ - { resource: services_password.yml }
+ - { resource: services_php.yml }
+ - { resource: services_profilefield.yml }
+ - { resource: services_report.yml }
+ - { resource: services_routing.yml }
+ - { resource: services_text_formatter.yml }
+ - { resource: services_text_reparser.yml }
+ - { resource: services_twig.yml }
+ - { resource: services_user.yml }
+
+ - { resource: tables.yml }
+ - { resource: parameters.yml }
+
+services:
+ cache:
+ class: phpbb\cache\service
+ arguments:
+ - '@cache.driver'
+ - '@config'
+ - '@dbal.conn'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ cache.driver:
+ class: '%cache.driver.class%'
+
+ class_loader:
+ class: phpbb\class_loader
+ arguments:
+ - phpbb\
+ - '%core.root_path%includes/'
+ - '%core.php_ext%'
+ calls:
+ - [register, []]
+ - [set_cache, ['@cache.driver']]
+
+ class_loader.ext:
+ class: phpbb\class_loader
+ arguments:
+ - \
+ - '%core.root_path%ext/'
+ - '%core.php_ext%'
+ calls:
+ - [register, []]
+ - [set_cache, ['@cache.driver']]
+
+ config:
+ class: phpbb\config\db
+ arguments:
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '%tables.config%'
+
+ config.php:
+ synthetic: true
+
+ config_text:
+ class: phpbb\config\db_text
+ arguments:
+ - '@dbal.conn'
+ - '%tables.config_text%'
+
+ controller.helper:
+ class: phpbb\controller\helper
+ arguments:
+ - '@template'
+ - '@user'
+ - '@config'
+ - '@symfony_request'
+ - '@request'
+ - '@routing.helper'
+
+ controller.resolver:
+ class: phpbb\controller\resolver
+ arguments:
+ - '@service_container'
+ - '%core.root_path%'
+ - '@template'
+
+ ext.manager:
+ class: phpbb\extension\manager
+ arguments:
+ - '@service_container'
+ - '@dbal.conn'
+ - '@config'
+ - '@filesystem'
+ - '%tables.ext%'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@cache.driver'
+
+ file_downloader:
+ class: phpbb\file_downloader
+
+ file_locator:
+ class: phpbb\routing\file_locator
+ arguments:
+ - '@filesystem'
+ - '%core.root_path%'
+
+ group_helper:
+ class: phpbb\group\helper
+ arguments:
+ - '@language'
+
+ log:
+ class: phpbb\log\log
+ arguments:
+ - '@dbal.conn'
+ - '@user'
+ - '@auth'
+ - '@dispatcher'
+ - '%core.root_path%'
+ - '%core.adm_relative_path%'
+ - '%core.php_ext%'
+ - '%tables.log%'
+
+ path_helper:
+ class: phpbb\path_helper
+ arguments:
+ - '@symfony_request'
+ - '@filesystem'
+ - '@request'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%core.adm_relative_path%'
+
+ plupload:
+ class: phpbb\plupload\plupload
+ arguments:
+ - '%core.root_path%'
+ - '@config'
+ - '@request'
+ - '@user'
+ - '@php_ini'
+ - '@mimetype.guesser'
+
+ upload_imagesize:
+ class: FastImageSize\FastImageSize
+
+ version_helper:
+ class: phpbb\version_helper
+ shared: false
+ arguments:
+ - '@cache'
+ - '@config'
+ - '@file_downloader'
+ - '@user'
diff --git a/phpBB/config/default/container/services_attachment.yml b/phpBB/config/default/container/services_attachment.yml
new file mode 100644
index 0000000000..c56ced21f4
--- /dev/null
+++ b/phpBB/config/default/container/services_attachment.yml
@@ -0,0 +1,40 @@
+services:
+ attachment.delete:
+ class: phpbb\attachment\delete
+ shared: false
+ arguments:
+ - '@config'
+ - '@dbal.conn'
+ - '@dispatcher'
+ - '@filesystem'
+ - '@attachment.resync'
+ - '%core.root_path%'
+
+ attachment.manager:
+ class: phpbb\attachment\manager
+ shared: false
+ arguments:
+ - '@attachment.delete'
+ - '@attachment.resync'
+ - '@attachment.upload'
+
+ attachment.resync:
+ class: phpbb\attachment\resync
+ shared: false
+ arguments:
+ - '@dbal.conn'
+
+ attachment.upload:
+ class: phpbb\attachment\upload
+ shared: false
+ arguments:
+ - '@auth'
+ - '@cache'
+ - '@config'
+ - '@files.upload'
+ - '@language'
+ - '@mimetype.guesser'
+ - '@dispatcher'
+ - '@plupload'
+ - '@user'
+ - '%core.root_path%'
diff --git a/phpBB/config/default/container/services_auth.yml b/phpBB/config/default/container/services_auth.yml
new file mode 100644
index 0000000000..ed8dc90a74
--- /dev/null
+++ b/phpBB/config/default/container/services_auth.yml
@@ -0,0 +1,110 @@
+services:
+# ----- Auth management -----
+ auth:
+ class: phpbb\auth\auth
+
+# ----- Auth providers -----
+ auth.provider_collection:
+ class: phpbb\auth\provider_collection
+ arguments:
+ - '@service_container'
+ - '@config'
+ tags:
+ - { name: service_collection, tag: auth.provider }
+
+ auth.provider.db:
+ class: phpbb\auth\provider\db
+ arguments:
+ - '@dbal.conn'
+ - '@config'
+ - '@passwords.manager'
+ - '@request'
+ - '@user'
+ - '@service_container'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: auth.provider }
+
+ auth.provider.apache:
+ class: phpbb\auth\provider\apache
+ arguments:
+ - '@dbal.conn'
+ - '@config'
+ - '@passwords.manager'
+ - '@request'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: auth.provider }
+
+ auth.provider.ldap:
+ class: phpbb\auth\provider\ldap
+ arguments:
+ - '@dbal.conn'
+ - '@config'
+ - '@passwords.manager'
+ - '@user'
+ tags:
+ - { name: auth.provider }
+
+ auth.provider.oauth:
+ class: phpbb\auth\provider\oauth\oauth
+ arguments:
+ - '@dbal.conn'
+ - '@config'
+ - '@passwords.manager'
+ - '@request'
+ - '@user'
+ - '%tables.auth_provider_oauth_token_storage%'
+ - '%tables.auth_provider_oauth_states%'
+ - '%tables.auth_provider_oauth_account_assoc%'
+ - '@auth.provider.oauth.service_collection'
+ - '%tables.users%'
+ - '@service_container'
+ - '@dispatcher'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: auth.provider }
+
+# ----- OAuth services providers -----
+ auth.provider.oauth.service_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: auth.provider.oauth.service }
+
+ auth.provider.oauth.service.bitly:
+ class: phpbb\auth\provider\oauth\service\bitly
+ arguments:
+ - '@config'
+ - '@request'
+ tags:
+ - { name: auth.provider.oauth.service }
+
+ auth.provider.oauth.service.facebook:
+ class: phpbb\auth\provider\oauth\service\facebook
+ arguments:
+ - '@config'
+ - '@request'
+ tags:
+ - { name: auth.provider.oauth.service }
+
+ auth.provider.oauth.service.google:
+ class: phpbb\auth\provider\oauth\service\google
+ arguments:
+ - '@config'
+ - '@request'
+ tags:
+ - { name: auth.provider.oauth.service }
+
+ auth.provider.oauth.service.twitter:
+ class: phpbb\auth\provider\oauth\service\twitter
+ arguments:
+ - '@config'
+ - '@request'
+ tags:
+ - { name: auth.provider.oauth.service }
diff --git a/phpBB/config/default/container/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml
new file mode 100644
index 0000000000..6cc38516ae
--- /dev/null
+++ b/phpBB/config/default/container/services_avatar.yml
@@ -0,0 +1,72 @@
+services:
+ avatar.manager:
+ class: phpbb\avatar\manager
+ arguments:
+ - '@config'
+ - '@avatar.driver_collection'
+
+# ----- Avatar drivers -----
+ avatar.driver_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: avatar.driver }
+
+ avatar.driver.gravatar:
+ class: phpbb\avatar\driver\gravatar
+ arguments:
+ - '@config'
+ - '@upload_imagesize'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@path_helper'
+ - '@cache.driver'
+ calls:
+ - [set_name, [avatar.driver.gravatar]]
+ tags:
+ - { name: avatar.driver }
+
+ avatar.driver.local:
+ class: phpbb\avatar\driver\local
+ arguments:
+ - '@config'
+ - '@upload_imagesize'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@path_helper'
+ - '@cache.driver'
+ calls:
+ - [set_name, [avatar.driver.local]]
+ tags:
+ - { name: avatar.driver }
+
+ avatar.driver.remote:
+ class: phpbb\avatar\driver\remote
+ arguments:
+ - '@config'
+ - '@upload_imagesize'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@path_helper'
+ - '@cache.driver'
+ calls:
+ - [set_name, [avatar.driver.remote]]
+ tags:
+ - { name: avatar.driver }
+
+ avatar.driver.upload:
+ class: phpbb\avatar\driver\upload
+ arguments:
+ - '@config'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@filesystem'
+ - '@path_helper'
+ - '@dispatcher'
+ - '@files.factory'
+ - '@cache.driver'
+ calls:
+ - [set_name, [avatar.driver.upload]]
+ tags:
+ - { name: avatar.driver }
diff --git a/phpBB/config/default/container/services_captcha.yml b/phpBB/config/default/container/services_captcha.yml
new file mode 100644
index 0000000000..e462c43bb8
--- /dev/null
+++ b/phpBB/config/default/container/services_captcha.yml
@@ -0,0 +1,59 @@
+services:
+ captcha.factory:
+ class: phpbb\captcha\factory
+ arguments:
+ - '@service_container'
+ - '@captcha.plugins.service_collection'
+
+# ----- Captcha plugins -----
+# Service MUST NOT be shared for all the plugins to work.
+ captcha.plugins.service_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: captcha.plugins }
+
+ core.captcha.plugins.gd:
+ class: phpbb\captcha\plugins\gd
+ shared: false
+ calls:
+ - [set_name, [core.captcha.plugins.gd]]
+ tags:
+ - { name: captcha.plugins }
+
+ core.captcha.plugins.gd_wave:
+ class: phpbb\captcha\plugins\gd_wave
+ shared: false
+ calls:
+ - [set_name, [core.captcha.plugins.gd_wave]]
+ tags:
+ - { name: captcha.plugins }
+
+ core.captcha.plugins.nogd:
+ class: phpbb\captcha\plugins\nogd
+ shared: false
+ calls:
+ - [set_name, [core.captcha.plugins.nogd]]
+ tags:
+ - { name: captcha.plugins }
+
+ core.captcha.plugins.qa:
+ class: phpbb\captcha\plugins\qa
+ shared: false
+ arguments:
+ - '%tables.captcha_qa_questions%'
+ - '%tables.captcha_qa_answers%'
+ - '%tables.captcha_qa_confirm%'
+ calls:
+ - [set_name, [core.captcha.plugins.qa]]
+ tags:
+ - { name: captcha.plugins }
+
+ core.captcha.plugins.recaptcha:
+ class: phpbb\captcha\plugins\recaptcha
+ shared: false
+ calls:
+ - [set_name, [core.captcha.plugins.recaptcha]]
+ tags:
+ - { name: captcha.plugins }
diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml
new file mode 100644
index 0000000000..3f27ee666a
--- /dev/null
+++ b/phpBB/config/default/container/services_console.yml
@@ -0,0 +1,271 @@
+services:
+ console.exception_subscriber:
+ class: phpbb\console\exception_subscriber
+ arguments:
+ - '@language'
+ - '%debug.exceptions%'
+ tags:
+ - { name: kernel.event_subscriber }
+
+ console.command_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: console.command }
+
+ console.command.cache.purge:
+ class: phpbb\console\command\cache\purge
+ arguments:
+ - '@user'
+ - '@cache.driver'
+ - '@dbal.conn'
+ - '@auth'
+ - '@log'
+ - '@config'
+ tags:
+ - { name: console.command }
+
+ console.command.config.delete:
+ class: phpbb\console\command\config\delete
+ arguments:
+ - '@user'
+ - '@config'
+ tags:
+ - { name: console.command }
+
+ console.command.config.increment:
+ class: phpbb\console\command\config\increment
+ arguments:
+ - '@user'
+ - '@config'
+ tags:
+ - { name: console.command }
+
+ console.command.config.get:
+ class: phpbb\console\command\config\get
+ arguments:
+ - '@user'
+ - '@config'
+ tags:
+ - { name: console.command }
+
+ console.command.config.set:
+ class: phpbb\console\command\config\set
+ arguments:
+ - '@user'
+ - '@config'
+ tags:
+ - { name: console.command }
+
+ console.command.config.set_atomic:
+ class: phpbb\console\command\config\set_atomic
+ arguments:
+ - '@user'
+ - '@config'
+ tags:
+ - { name: console.command }
+
+ console.command.cron.list:
+ class: phpbb\console\command\cron\cron_list
+ arguments:
+ - '@user'
+ - '@cron.manager'
+ tags:
+ - { name: console.command }
+
+ console.command.cron.run:
+ class: phpbb\console\command\cron\run
+ arguments:
+ - '@user'
+ - '@cron.manager'
+ - '@cron.lock_db'
+ tags:
+ - { name: console.command }
+
+ console.command.db.list:
+ class: phpbb\console\command\db\list_command
+ arguments:
+ - '@user'
+ - '@migrator'
+ - '@ext.manager'
+ - '@config'
+ - '@cache'
+ tags:
+ - { name: console.command }
+
+ console.command.db.migrate:
+ class: phpbb\console\command\db\migrate
+ arguments:
+ - '@user'
+ - '@language'
+ - '@migrator'
+ - '@ext.manager'
+ - '@config'
+ - '@cache'
+ - '@log'
+ - '@filesystem'
+ - '%core.root_path%'
+ tags:
+ - { name: console.command }
+
+ console.command.db.revert:
+ class: phpbb\console\command\db\revert
+ arguments:
+ - '@user'
+ - '@language'
+ - '@migrator'
+ - '@ext.manager'
+ - '@config'
+ - '@cache'
+ - '@filesystem'
+ - '%core.root_path%'
+ tags:
+ - { name: console.command }
+
+ console.command.dev.migration_tips:
+ class: phpbb\console\command\dev\migration_tips
+ arguments:
+ - '@user'
+ - '@ext.manager'
+ tags:
+ - { name: console.command }
+
+ console.command.extension.disable:
+ class: phpbb\console\command\extension\disable
+ arguments:
+ - '@user'
+ - '@ext.manager'
+ - '@log'
+ tags:
+ - { name: console.command }
+
+ console.command.extension.enable:
+ class: phpbb\console\command\extension\enable
+ arguments:
+ - '@user'
+ - '@ext.manager'
+ - '@log'
+ tags:
+ - { name: console.command }
+
+ console.command.extension.purge:
+ class: phpbb\console\command\extension\purge
+ arguments:
+ - '@user'
+ - '@ext.manager'
+ - '@log'
+ tags:
+ - { name: console.command }
+
+ console.command.extension.show:
+ class: phpbb\console\command\extension\show
+ arguments:
+ - '@user'
+ - '@ext.manager'
+ - '@log'
+ tags:
+ - { name: console.command }
+
+ console.command.fixup.recalculate_email_hash:
+ class: phpbb\console\command\fixup\recalculate_email_hash
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ tags:
+ - { name: console.command }
+
+ console.command.reparser.list:
+ class: phpbb\console\command\reparser\list_all
+ arguments:
+ - '@user'
+ - '@text_reparser_collection'
+ tags:
+ - { name: console.command }
+
+ console.command.reparser.reparse:
+ class: phpbb\console\command\reparser\reparse
+ arguments:
+ - '@user'
+ - '@text_reparser.lock'
+ - '@text_reparser.manager'
+ - '@text_reparser_collection'
+ tags:
+ - { name: console.command }
+
+ console.command.thumbnail.delete:
+ class: phpbb\console\command\thumbnail\delete
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ - '%core.root_path%'
+ tags:
+ - { name: console.command }
+
+ console.command.thumbnail.generate:
+ class: phpbb\console\command\thumbnail\generate
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ - '@cache'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: console.command }
+
+ console.command.thumbnail.recreate:
+ class: phpbb\console\command\thumbnail\recreate
+ arguments:
+ - '@user'
+ tags:
+ - { name: console.command }
+
+ console.command.user.activate:
+ class: phpbb\console\command\user\activate
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ - '@config'
+ - '@language'
+ - '@log'
+ - '@notification_manager'
+ - '@user_loader'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: console.command }
+
+ console.command.user.add:
+ class: phpbb\console\command\user\add
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ - '@config'
+ - '@language'
+ - '@passwords.manager'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: console.command }
+
+ console.command.user.delete:
+ class: phpbb\console\command\user\delete
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ - '@language'
+ - '@log'
+ - '@user_loader'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: console.command }
+
+ console.command.user.reclean:
+ class: phpbb\console\command\user\reclean
+ arguments:
+ - '@user'
+ - '@dbal.conn'
+ - '@language'
+ tags:
+ - { name: console.command }
diff --git a/phpBB/config/default/container/services_content.yml b/phpBB/config/default/container/services_content.yml
new file mode 100644
index 0000000000..602fd25f4e
--- /dev/null
+++ b/phpBB/config/default/container/services_content.yml
@@ -0,0 +1,72 @@
+services:
+ content.visibility:
+ class: phpbb\content_visibility
+ arguments:
+ - '@auth'
+ - '@config'
+ - '@dispatcher'
+ - '@dbal.conn'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%tables.forums%'
+ - '%tables.posts%'
+ - '%tables.topics%'
+ - '%tables.users%'
+
+ groupposition.legend:
+ class: phpbb\groupposition\legend
+ arguments:
+ - '@dbal.conn'
+ - '@user'
+
+ groupposition.teampage:
+ class: phpbb\groupposition\teampage
+ arguments:
+ - '@dbal.conn'
+ - '@user'
+ - '@cache.driver'
+
+ message.form.admin:
+ class: phpbb\message\admin_form
+ arguments:
+ - '@auth'
+ - '@config'
+ - '@config_text'
+ - '@dbal.conn'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ message.form.topic:
+ class: phpbb\message\topic_form
+ arguments:
+ - '@auth'
+ - '@config'
+ - '@dbal.conn'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ message.form.user:
+ class: phpbb\message\user_form
+ arguments:
+ - '@auth'
+ - '@config'
+ - '@dbal.conn'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ pagination:
+ class: phpbb\pagination
+ arguments:
+ - '@template'
+ - '@user'
+ - '@controller.helper'
+ - '@dispatcher'
+
+ viewonline_helper:
+ class: phpbb\viewonline_helper
+ arguments:
+ - '@filesystem'
diff --git a/phpBB/config/default/container/services_cron.yml b/phpBB/config/default/container/services_cron.yml
new file mode 100644
index 0000000000..0b95a96190
--- /dev/null
+++ b/phpBB/config/default/container/services_cron.yml
@@ -0,0 +1,221 @@
+services:
+ cron.manager:
+ class: phpbb\cron\manager
+ arguments:
+ - '@cron.task_collection'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ cron.lock_db:
+ class: phpbb\lock\db
+ arguments:
+ - cron_lock
+ - '@config'
+ - '@dbal.conn'
+
+# ----- Cron tasks -----
+ cron.task_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: cron.task }
+
+ cron.task.core.prune_all_forums:
+ class: phpbb\cron\task\core\prune_all_forums
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@config'
+ - '@dbal.conn'
+ calls:
+ - [set_name, [cron.task.core.prune_all_forums]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.prune_forum:
+ class: phpbb\cron\task\core\prune_forum
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@config'
+ - '@dbal.conn'
+ calls:
+ - [set_name, [cron.task.core.prune_forum]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.prune_shadow_topics:
+ class: phpbb\cron\task\core\prune_shadow_topics
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@config'
+ - '@dbal.conn'
+ - '@log'
+ - '@user'
+ calls:
+ - [set_name, [cron.task.core.prune_shadow_topics]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.prune_notifications:
+ class: phpbb\cron\task\core\prune_notifications
+ arguments:
+ - '@config'
+ - '@notification_manager'
+ calls:
+ - [set_name, [cron.task.core.prune_notifications]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.queue:
+ class: phpbb\cron\task\core\queue
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@config'
+ - '%core.cache_dir%'
+ calls:
+ - [set_name, [cron.task.core.queue]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.tidy_cache:
+ class: phpbb\cron\task\core\tidy_cache
+ arguments:
+ - '@config'
+ - '@cache.driver'
+ calls:
+ - [set_name, [cron.task.core.tidy_cache]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.tidy_database:
+ class: phpbb\cron\task\core\tidy_database
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@config'
+ calls:
+ - [set_name, [cron.task.core.tidy_database]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.tidy_plupload:
+ class: phpbb\cron\task\core\tidy_plupload
+ arguments:
+ - '%core.root_path%'
+ - '@config'
+ - '@log'
+ - '@user'
+ calls:
+ - [set_name, [cron.task.core.tidy_plupload]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.tidy_search:
+ class: phpbb\cron\task\core\tidy_search
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@auth'
+ - '@config'
+ - '@dbal.conn'
+ - '@user'
+ - '@dispatcher'
+ calls:
+ - [set_name, [cron.task.core.tidy_search]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.tidy_sessions:
+ class: phpbb\cron\task\core\tidy_sessions
+ arguments:
+ - '@config'
+ - '@user'
+ calls:
+ - [set_name, [cron.task.core.tidy_sessions]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.core.tidy_warnings:
+ class: phpbb\cron\task\core\tidy_warnings
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@config'
+ calls:
+ - [set_name, [cron.task.core.tidy_warnings]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.text_reparser.pm_text:
+ class: phpbb\cron\task\text_reparser\reparser
+ arguments:
+ - '@config'
+ - '@config_text'
+ - '@text_reparser.lock'
+ - '@text_reparser.manager'
+ - '@text_reparser_collection'
+ calls:
+ - [set_name, [cron.task.text_reparser.pm_text]]
+ - [set_reparser, [text_reparser.pm_text]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.text_reparser.poll_option:
+ class: phpbb\cron\task\text_reparser\reparser
+ arguments:
+ - '@config'
+ - '@config_text'
+ - '@text_reparser.lock'
+ - '@text_reparser.manager'
+ - '@text_reparser_collection'
+ calls:
+ - [set_name, [cron.task.text_reparser.poll_option]]
+ - [set_reparser, [text_reparser.poll_option]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.text_reparser.poll_title:
+ class: phpbb\cron\task\text_reparser\reparser
+ arguments:
+ - '@config'
+ - '@config_text'
+ - '@text_reparser.lock'
+ - '@text_reparser.manager'
+ - '@text_reparser_collection'
+ calls:
+ - [set_name, [cron.task.text_reparser.poll_title]]
+ - [set_reparser, [text_reparser.poll_title]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.text_reparser.post_text:
+ class: phpbb\cron\task\text_reparser\reparser
+ arguments:
+ - '@config'
+ - '@config_text'
+ - '@text_reparser.lock'
+ - '@text_reparser.manager'
+ - '@text_reparser_collection'
+ calls:
+ - [set_name, [cron.task.text_reparser.post_text]]
+ - [set_reparser, [text_reparser.post_text]]
+ tags:
+ - { name: cron.task }
+
+ cron.task.text_reparser.user_signature:
+ class: phpbb\cron\task\text_reparser\reparser
+ arguments:
+ - '@config'
+ - '@config_text'
+ - '@text_reparser.lock'
+ - '@text_reparser.manager'
+ - '@text_reparser_collection'
+ calls:
+ - [set_name, [cron.task.text_reparser.user_signature]]
+ - [set_reparser, [text_reparser.user_signature]]
+ tags:
+ - { name: cron.task }
diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml
new file mode 100644
index 0000000000..d7a8238400
--- /dev/null
+++ b/phpBB/config/default/container/services_db.yml
@@ -0,0 +1,73 @@
+services:
+ dbal.conn:
+ class: phpbb\db\driver\factory
+ arguments:
+ - '@service_container'
+
+ dbal.conn.driver:
+ class: '%dbal.driver.class%'
+ calls:
+ - [sql_connect, ['%dbal.dbhost%', '%dbal.dbuser%', '%dbal.dbpasswd%', '%dbal.dbname%', '%dbal.dbport%', false, '%dbal.new_link%']]
+
+# ----- DB Tools -----
+ dbal.tools.factory:
+ class: phpbb\db\tools\factory
+
+ dbal.tools:
+ class: phpbb\db\tools\tools_interface
+ factory: ['@dbal.tools.factory', get]
+ arguments:
+ - '@dbal.conn.driver'
+
+# ----- DB Extractor -----
+ dbal.extractor.factory:
+ class: phpbb\db\extractor\factory
+ arguments:
+ - '@dbal.conn.driver'
+ - '@service_container'
+
+ dbal.extractor:
+ class: phpbb\db\extractor\extractor_interface
+ factory: ['@dbal.extractor.factory', get]
+
+# ----- DB Extractors for different drivers -----
+# Service MUST NOT be shared for all the handlers to work correctly.
+ dbal.extractor.extractors.mssql_extractor:
+ class: phpbb\db\extractor\mssql_extractor
+ shared: false
+ arguments:
+ - '%core.root_path%'
+ - '@request'
+ - '@dbal.conn.driver'
+
+ dbal.extractor.extractors.mysql_extractor:
+ class: phpbb\db\extractor\mysql_extractor
+ shared: false
+ arguments:
+ - '%core.root_path%'
+ - '@request'
+ - '@dbal.conn.driver'
+
+ dbal.extractor.extractors.oracle_extractor:
+ class: phpbb\db\extractor\oracle_extractor
+ shared: false
+ arguments:
+ - '%core.root_path%'
+ - '@request'
+ - '@dbal.conn.driver'
+
+ dbal.extractor.extractors.postgres_extractor:
+ class: phpbb\db\extractor\postgres_extractor
+ shared: false
+ arguments:
+ - '%core.root_path%'
+ - '@request'
+ - '@dbal.conn.driver'
+
+ dbal.extractor.extractors.sqlite3_extractor:
+ class: phpbb\db\extractor\sqlite3_extractor
+ shared: false
+ arguments:
+ - '%core.root_path%'
+ - '@request'
+ - '@dbal.conn.driver'
diff --git a/phpBB/config/default/container/services_event.yml b/phpBB/config/default/container/services_event.yml
new file mode 100644
index 0000000000..8a55b933ac
--- /dev/null
+++ b/phpBB/config/default/container/services_event.yml
@@ -0,0 +1,25 @@
+services:
+ dispatcher:
+ class: phpbb\event\dispatcher
+ arguments:
+ - '@service_container'
+
+ kernel_exception_subscriber:
+ class: phpbb\event\kernel_exception_subscriber
+ arguments:
+ - '@template'
+ - '@language'
+ tags:
+ - { name: kernel.event_subscriber }
+
+ kernel_terminate_subscriber:
+ class: phpbb\event\kernel_terminate_subscriber
+ tags:
+ - { name: kernel.event_subscriber }
+
+ symfony_response_listener:
+ class: Symfony\Component\HttpKernel\EventListener\ResponseListener
+ arguments:
+ - UTF-8
+ tags:
+ - { name: kernel.event_subscriber }
diff --git a/phpBB/config/default/container/services_feed.yml b/phpBB/config/default/container/services_feed.yml
new file mode 100644
index 0000000000..d3e7924f2f
--- /dev/null
+++ b/phpBB/config/default/container/services_feed.yml
@@ -0,0 +1,121 @@
+services:
+ phpbb.feed.controller:
+ class: phpbb\feed\controller\feed
+ arguments:
+ - '@template.twig.environment'
+ - '@symfony_request'
+ - '@controller.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@service_container'
+ - '@feed.helper'
+ - '@user'
+ - '@auth'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.helper:
+ class: phpbb\feed\helper
+ arguments:
+ - '@config'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ feed.forum:
+ class: phpbb\feed\forum
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.forums:
+ class: phpbb\feed\forums
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.news:
+ class: phpbb\feed\news
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.overall:
+ class: phpbb\feed\overall
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.topic:
+ class: phpbb\feed\topic
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.topics:
+ class: phpbb\feed\topics
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
+
+ feed.topics_active:
+ class: phpbb\feed\topics_active
+ shared: false
+ arguments:
+ - '@feed.helper'
+ - '@config'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@auth'
+ - '@content.visibility'
+ - '@dispatcher'
+ - '%core.php_ext%'
diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml
new file mode 100644
index 0000000000..ba1fdb4c9a
--- /dev/null
+++ b/phpBB/config/default/container/services_files.yml
@@ -0,0 +1,57 @@
+services:
+ files.factory:
+ class: phpbb\files\factory
+ arguments:
+ - '@service_container'
+
+ files.filespec:
+ class: phpbb\files\filespec
+ shared: false
+ arguments:
+ - '@filesystem'
+ - '@language'
+ - '@php_ini'
+ - '@upload_imagesize'
+ - '%core.root_path%'
+ - '@mimetype.guesser'
+ - '@plupload'
+
+ files.upload:
+ class: phpbb\files\upload
+ shared: false
+ arguments:
+ - '@filesystem'
+ - '@files.factory'
+ - '@language'
+ - '@php_ini'
+ - '@request'
+
+ files.types.form:
+ class: phpbb\files\types\form
+ shared: false
+ arguments:
+ - '@files.factory'
+ - '@language'
+ - '@php_ini'
+ - '@plupload'
+ - '@request'
+
+ files.types.local:
+ class: phpbb\files\types\local
+ shared: false
+ arguments:
+ - '@files.factory'
+ - '@language'
+ - '@php_ini'
+ - '@request'
+
+ files.types.remote:
+ class: phpbb\files\types\remote
+ shared: false
+ arguments:
+ - '@config'
+ - '@files.factory'
+ - '@language'
+ - '@php_ini'
+ - '@request'
+ - '%core.root_path%'
diff --git a/phpBB/config/default/container/services_filesystem.yml b/phpBB/config/default/container/services_filesystem.yml
new file mode 100644
index 0000000000..828f9076dd
--- /dev/null
+++ b/phpBB/config/default/container/services_filesystem.yml
@@ -0,0 +1,3 @@
+services:
+ filesystem:
+ class: phpbb\filesystem\filesystem
diff --git a/phpBB/config/default/container/services_help.yml b/phpBB/config/default/container/services_help.yml
new file mode 100644
index 0000000000..1bff001523
--- /dev/null
+++ b/phpBB/config/default/container/services_help.yml
@@ -0,0 +1,27 @@
+services:
+ phpbb.help.manager:
+ class: phpbb\help\manager
+ arguments:
+ - '@dispatcher'
+ - '@language'
+ - '@template'
+
+ phpbb.help.controller.bbcode:
+ class: phpbb\help\controller\bbcode
+ arguments:
+ - '@controller.helper'
+ - '@phpbb.help.manager'
+ - '@template'
+ - '@language'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ phpbb.help.controller.faq:
+ class: phpbb\help\controller\faq
+ arguments:
+ - '@controller.helper'
+ - '@phpbb.help.manager'
+ - '@template'
+ - '@language'
+ - '%core.root_path%'
+ - '%core.php_ext%'
diff --git a/phpBB/config/default/container/services_hook.yml b/phpBB/config/default/container/services_hook.yml
new file mode 100644
index 0000000000..10a84184a0
--- /dev/null
+++ b/phpBB/config/default/container/services_hook.yml
@@ -0,0 +1,7 @@
+services:
+ hook_finder:
+ class: phpbb\hook\finder
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '@cache.driver'
diff --git a/phpBB/config/default/container/services_http.yml b/phpBB/config/default/container/services_http.yml
new file mode 100644
index 0000000000..49cfbf5b84
--- /dev/null
+++ b/phpBB/config/default/container/services_http.yml
@@ -0,0 +1,23 @@
+services:
+ http_kernel:
+ class: Symfony\Component\HttpKernel\HttpKernel
+ arguments:
+ - '@dispatcher'
+ - '@controller.resolver'
+ - '@request_stack'
+
+ # WARNING: The Symfony request does not escape the input and should be used very carefully
+ # prefer the phpbb request (service @request) as possible
+ symfony_request:
+ class: phpbb\symfony_request
+ arguments:
+ - '@request'
+
+ request_stack:
+ class: Symfony\Component\HttpFoundation\RequestStack
+
+ request:
+ class: phpbb\request\request
+ arguments:
+ - null
+ - '%core.disable_super_globals%'
diff --git a/phpBB/config/default/container/services_language.yml b/phpBB/config/default/container/services_language.yml
new file mode 100644
index 0000000000..8201fbf9b6
--- /dev/null
+++ b/phpBB/config/default/container/services_language.yml
@@ -0,0 +1,22 @@
+services:
+ language.helper.language_file:
+ class: phpbb\language\language_file_helper
+ arguments:
+ - '%core.root_path%'
+
+ language:
+ class: phpbb\language\language
+ arguments:
+ - '@language.loader'
+
+ language.loader_abstract:
+ abstract: true
+ class: phpbb\language\language_file_loader
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ language.loader:
+ parent: language.loader_abstract
+ calls:
+ - [set_extension_manager, ['@ext.manager']]
diff --git a/phpBB/config/default/container/services_migrator.yml b/phpBB/config/default/container/services_migrator.yml
new file mode 100644
index 0000000000..c63b087adb
--- /dev/null
+++ b/phpBB/config/default/container/services_migrator.yml
@@ -0,0 +1,64 @@
+services:
+# ----- Migrator -----
+ migrator:
+ class: phpbb\db\migrator
+ arguments:
+ - '@service_container'
+ - '@config'
+ - '@dbal.conn'
+ - '@dbal.tools'
+ - '%tables.migrations%'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%core.table_prefix%'
+ - '@migrator.tool_collection'
+ - '@migrator.helper'
+
+ migrator.helper:
+ class: phpbb\db\migration\helper
+
+# ----- Migrator's tools -----
+ migrator.tool_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: migrator.tool }
+
+ migrator.tool.config:
+ class: phpbb\db\migration\tool\config
+ arguments:
+ - '@config'
+ tags:
+ - { name: migrator.tool }
+
+ migrator.tool.config_text:
+ class: phpbb\db\migration\tool\config_text
+ arguments:
+ - '@config_text'
+ tags:
+ - { name: migrator.tool }
+
+ migrator.tool.module:
+ class: phpbb\db\migration\tool\module
+ arguments:
+ - '@dbal.conn'
+ - '@cache'
+ - '@user'
+ - '@module.manager'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%tables.modules%'
+ tags:
+ - { name: migrator.tool }
+
+ migrator.tool.permission:
+ class: phpbb\db\migration\tool\permission
+ arguments:
+ - '@dbal.conn'
+ - '@cache'
+ - '@auth'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: migrator.tool }
diff --git a/phpBB/config/default/container/services_mimetype_guesser.yml b/phpBB/config/default/container/services_mimetype_guesser.yml
new file mode 100644
index 0000000000..432470d40c
--- /dev/null
+++ b/phpBB/config/default/container/services_mimetype_guesser.yml
@@ -0,0 +1,36 @@
+services:
+ mimetype.guesser_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: mimetype.guessers }
+
+ mimetype.fileinfo_mimetype_guesser:
+ class: Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser
+ tags:
+ - { name: mimetype.guessers }
+
+ mimetype.filebinary_mimetype_guesser:
+ class: Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser
+ tags:
+ - { name: mimetype.guessers }
+
+ mimetype.content_guesser:
+ class: phpbb\mimetype\content_guesser
+ calls:
+ - [set_priority, ['%mimetype.guesser.priority.low%']]
+ tags:
+ - { name: mimetype.guessers }
+
+ mimetype.extension_guesser:
+ class: phpbb\mimetype\extension_guesser
+ calls:
+ - [set_priority, ['%mimetype.guesser.priority.lowest%']]
+ tags:
+ - { name: mimetype.guessers }
+
+ mimetype.guesser:
+ class: phpbb\mimetype\guesser
+ arguments:
+ - '@mimetype.guesser_collection'
diff --git a/phpBB/config/default/container/services_module.yml b/phpBB/config/default/container/services_module.yml
new file mode 100644
index 0000000000..a057e55239
--- /dev/null
+++ b/phpBB/config/default/container/services_module.yml
@@ -0,0 +1,10 @@
+services:
+ module.manager:
+ class: phpbb\module\module_manager
+ arguments:
+ - '@cache.driver'
+ - '@dbal.conn'
+ - '@ext.manager'
+ - '%tables.modules%'
+ - '%core.root_path%'
+ - '%core.php_ext%'
diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml
new file mode 100644
index 0000000000..6c3cea3dbc
--- /dev/null
+++ b/phpBB/config/default/container/services_notification.yml
@@ -0,0 +1,224 @@
+services:
+ notification_manager:
+ class: phpbb\notification\manager
+ arguments:
+ - '@notification.type_collection'
+ - '@notification.method_collection'
+ - '@service_container'
+ - '@user_loader'
+ - '@dispatcher'
+ - '@dbal.conn'
+ - '@cache'
+ - '@language'
+ - '@user'
+ - '%tables.notification_types%'
+ - '%tables.user_notifications%'
+
+# ----- Notification's types -----
+# Service MUST NOT be shared for all the plugins to work.
+ notification.type_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: notification.type }
+
+ notification.type.base:
+ abstract: true
+ arguments:
+ - '@dbal.conn'
+ - '@language'
+ - '@user'
+ - '@auth'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%tables.user_notifications%'
+
+ notification.type.admin_activate_user:
+ class: phpbb\notification\type\admin_activate_user
+ shared: false
+ parent: notification.type.base
+ calls:
+ - [set_user_loader, ['@user_loader']]
+ - [set_config, ['@config']]
+ tags:
+ - { name: notification.type }
+
+ notification.type.approve_post:
+ class: phpbb\notification\type\approve_post
+ shared: false
+ parent: notification.type.post
+ tags:
+ - { name: notification.type }
+
+ notification.type.approve_topic:
+ class: phpbb\notification\type\approve_topic
+ shared: false
+ parent: notification.type.topic
+ tags:
+ - { name: notification.type }
+
+ notification.type.bookmark:
+ class: phpbb\notification\type\bookmark
+ shared: false
+ parent: notification.type.post
+ tags:
+ - { name: notification.type }
+
+ notification.type.disapprove_post:
+ class: phpbb\notification\type\disapprove_post
+ shared: false
+ parent: notification.type.post
+ tags:
+ - { name: notification.type }
+
+ notification.type.disapprove_topic:
+ class: phpbb\notification\type\disapprove_topic
+ shared: false
+ parent: notification.type.topic
+ tags:
+ - { name: notification.type }
+
+ notification.type.group_request:
+ class: phpbb\notification\type\group_request
+ shared: false
+ parent: notification.type.base
+ calls:
+ - [set_user_loader, ['@user_loader']]
+ tags:
+ - { name: notification.type }
+
+ notification.type.group_request_approved:
+ class: phpbb\notification\type\group_request_approved
+ shared: false
+ parent: notification.type.base
+ tags:
+ - { name: notification.type }
+
+ notification.type.pm:
+ class: phpbb\notification\type\pm
+ shared: false
+ parent: notification.type.base
+ calls:
+ - [set_user_loader, ['@user_loader']]
+ - [set_config, ['@config']]
+ tags:
+ - { name: notification.type }
+
+ notification.type.post:
+ class: phpbb\notification\type\post
+ shared: false
+ parent: notification.type.base
+ calls:
+ - [set_user_loader, ['@user_loader']]
+ - [set_config, ['@config']]
+ tags:
+ - { name: notification.type }
+
+ notification.type.post_in_queue:
+ class: phpbb\notification\type\post_in_queue
+ shared: false
+ parent: notification.type.post
+ tags:
+ - { name: notification.type }
+
+ notification.type.quote:
+ class: phpbb\notification\type\quote
+ shared: false
+ parent: notification.type.post
+ calls:
+ - [set_utils, ['@text_formatter.utils']]
+ tags:
+ - { name: notification.type }
+
+ notification.type.report_pm:
+ class: phpbb\notification\type\report_pm
+ shared: false
+ parent: notification.type.pm
+ tags:
+ - { name: notification.type }
+
+ notification.type.report_pm_closed:
+ class: phpbb\notification\type\report_pm_closed
+ shared: false
+ parent: notification.type.pm
+ tags:
+ - { name: notification.type }
+
+ notification.type.report_post:
+ class: phpbb\notification\type\report_post
+ shared: false
+ parent: notification.type.post
+ tags:
+ - { name: notification.type }
+
+ notification.type.report_post_closed:
+ class: phpbb\notification\type\report_post_closed
+ shared: false
+ parent: notification.type.post
+ tags:
+ - { name: notification.type }
+
+ notification.type.topic:
+ class: phpbb\notification\type\topic
+ shared: false
+ parent: notification.type.base
+ calls:
+ - [set_user_loader, ['@user_loader']]
+ - [set_config, ['@config']]
+ tags:
+ - { name: notification.type }
+
+ notification.type.topic_in_queue:
+ class: phpbb\notification\type\topic_in_queue
+ shared: false
+ parent: notification.type.topic
+ tags:
+ - { name: notification.type }
+
+# ----- Notification's methods -----
+# Service MUST NOT be shared for all the plugins to work.
+ notification.method_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: notification.method }
+
+ notification.method.board:
+ class: phpbb\notification\method\board
+ shared: false
+ arguments:
+ - '@user_loader'
+ - '@dbal.conn'
+ - '@cache.driver'
+ - '@user'
+ - '@config'
+ - '%tables.notification_types%'
+ - '%tables.notifications%'
+ tags:
+ - { name: notification.method }
+
+ notification.method.email:
+ class: phpbb\notification\method\email
+ shared: false
+ arguments:
+ - '@user_loader'
+ - '@user'
+ - '@config'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: notification.method }
+
+ notification.method.jabber:
+ class: phpbb\notification\method\jabber
+ shared: false
+ arguments:
+ - '@user_loader'
+ - '@user'
+ - '@config'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: notification.method }
diff --git a/phpBB/config/default/container/services_password.yml b/phpBB/config/default/container/services_password.yml
new file mode 100644
index 0000000000..82850dc2a7
--- /dev/null
+++ b/phpBB/config/default/container/services_password.yml
@@ -0,0 +1,124 @@
+services:
+# ----- Password management -----
+ passwords.manager:
+ class: phpbb\passwords\manager
+ arguments:
+ - '@config'
+ - '@passwords.driver_collection'
+ - '@passwords.helper'
+ - '%passwords.algorithms%'
+
+ passwords.helper:
+ class: phpbb\passwords\helper
+
+ passwords.driver_helper:
+ class: phpbb\passwords\driver\helper
+ arguments:
+ - '@config'
+
+# ----- Password's drivers -----
+ passwords.driver_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: passwords.driver }
+
+ passwords.driver.bcrypt:
+ class: phpbb\passwords\driver\bcrypt
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.bcrypt_2y:
+ class: phpbb\passwords\driver\bcrypt_2y
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.bcrypt_wcf2:
+ class: phpbb\passwords\driver\bcrypt_wcf2
+ arguments:
+ - '@passwords.driver.bcrypt'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.salted_md5:
+ class: phpbb\passwords\driver\salted_md5
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.phpass:
+ class: phpbb\passwords\driver\phpass
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.convert_password:
+ class: phpbb\passwords\driver\convert_password
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.sha1_smf:
+ class: phpbb\passwords\driver\sha1_smf
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.sha1_wcf1:
+ class: phpbb\passwords\driver\sha1_wcf1
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.sha1:
+ class: phpbb\passwords\driver\sha1
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.md5_phpbb2:
+ class: phpbb\passwords\driver\md5_phpbb2
+ arguments:
+ - '@request'
+ - '@passwords.driver.salted_md5'
+ - '@passwords.driver_helper'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.md5_mybb:
+ class: phpbb\passwords\driver\md5_mybb
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.md5_vb:
+ class: phpbb\passwords\driver\md5_vb
+ arguments:
+ - '@config'
+ - '@passwords.driver_helper'
+ tags:
+ - { name: passwords.driver }
diff --git a/phpBB/config/default/container/services_php.yml b/phpBB/config/default/container/services_php.yml
new file mode 100644
index 0000000000..29349960f3
--- /dev/null
+++ b/phpBB/config/default/container/services_php.yml
@@ -0,0 +1,3 @@
+services:
+ php_ini:
+ class: bantu\IniGetWrapper\IniGetWrapper
diff --git a/phpBB/config/default/container/services_profilefield.yml b/phpBB/config/default/container/services_profilefield.yml
new file mode 100644
index 0000000000..90b22836e5
--- /dev/null
+++ b/phpBB/config/default/container/services_profilefield.yml
@@ -0,0 +1,102 @@
+services:
+ profilefields.manager:
+ class: phpbb\profilefields\manager
+ arguments:
+ - '@auth'
+ - '@dbal.conn'
+ - '@dispatcher'
+ - '@request'
+ - '@template'
+ - '@profilefields.type_collection'
+ - '@user'
+ - '%tables.profile_fields%'
+ - '%tables.profile_fields_language%'
+ - '%tables.profile_fields_data%'
+
+ profilefields.lang_helper:
+ class: phpbb\profilefields\lang_helper
+ arguments:
+ - '@dbal.conn'
+ - '%tables.profile_fields_options_language%'
+
+# ----- Profile fields types -----
+ profilefields.type_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: profilefield.type }
+
+ profilefields.type.bool:
+ class: phpbb\profilefields\type\type_bool
+ arguments:
+ - '@profilefields.lang_helper'
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.date:
+ class: phpbb\profilefields\type\type_date
+ arguments:
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.dropdown:
+ class: phpbb\profilefields\type\type_dropdown
+ arguments:
+ - '@profilefields.lang_helper'
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.googleplus:
+ class: phpbb\profilefields\type\type_googleplus
+ arguments:
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.int:
+ class: phpbb\profilefields\type\type_int
+ arguments:
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.string:
+ class: phpbb\profilefields\type\type_string
+ arguments:
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.text:
+ class: phpbb\profilefields\type\type_text
+ arguments:
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
+
+ profilefields.type.url:
+ class: phpbb\profilefields\type\type_url
+ arguments:
+ - '@request'
+ - '@template'
+ - '@user'
+ tags:
+ - { name: profilefield.type }
diff --git a/phpBB/config/default/container/services_report.yml b/phpBB/config/default/container/services_report.yml
new file mode 100644
index 0000000000..2c5b3bf3d5
--- /dev/null
+++ b/phpBB/config/default/container/services_report.yml
@@ -0,0 +1,53 @@
+services:
+# ----- Report controller -----
+ phpbb.report.controller:
+ class: phpbb\report\controller\report
+ arguments:
+ - '@config'
+ - '@user'
+ - '@template'
+ - '@controller.helper'
+ - '@request'
+ - '@captcha.factory'
+ - '@phpbb.report.handler_factory'
+ - '@phpbb.report.report_reason_list_provider'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+# ----- Report handler factory -----
+ phpbb.report.handler_factory:
+ class: phpbb\report\handler_factory
+ arguments:
+ - '@service_container'
+
+# ----- Report UI provider -----
+ phpbb.report.report_reason_list_provider:
+ class: phpbb\report\report_reason_list_provider
+ arguments:
+ - '@dbal.conn.driver'
+ - '@template'
+ - '@user'
+
+# ----- Report handlers -----
+# Service MUST NOT be shared for all the handlers to work correctly.
+ phpbb.report.handlers.report_handler_pm:
+ class: phpbb\report\report_handler_pm
+ shared: false
+ arguments:
+ - '@dbal.conn.driver'
+ - '@dispatcher'
+ - '@config'
+ - '@auth'
+ - '@user'
+ - '@notification_manager'
+
+ phpbb.report.handlers.report_handler_post:
+ class: phpbb\report\report_handler_post
+ shared: false
+ arguments:
+ - '@dbal.conn.driver'
+ - '@dispatcher'
+ - '@config'
+ - '@auth'
+ - '@user'
+ - '@notification_manager'
diff --git a/phpBB/config/default/container/services_routing.yml b/phpBB/config/default/container/services_routing.yml
new file mode 100644
index 0000000000..3048145a2f
--- /dev/null
+++ b/phpBB/config/default/container/services_routing.yml
@@ -0,0 +1,79 @@
+services:
+ router:
+ class: phpbb\routing\router
+ arguments:
+ - '@service_container'
+ - '@routing.chained_resources_locator'
+ - '@routing.delegated_loader'
+ - '%core.php_ext%'
+ - '%core.cache_dir%'
+
+ router.listener:
+ class: Symfony\Component\HttpKernel\EventListener\RouterListener
+ arguments:
+ - '@router'
+ - null
+ - null
+ - '@request_stack'
+ tags:
+ - { name: kernel.event_subscriber }
+
+ routing.helper:
+ class: phpbb\routing\helper
+ arguments:
+ - '@config'
+ - '@router'
+ - '@symfony_request'
+ - '@request'
+ - '@filesystem'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+# ---- Route loaders ----
+
+ routing.delegated_loader:
+ class: Symfony\Component\Config\Loader\DelegatingLoader
+ arguments:
+ - '@routing.resolver'
+
+ routing.resolver:
+ class: phpbb\routing\loader_resolver
+ arguments:
+ - '@routing.loader.collection'
+
+ routing.loader.collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: routing.loader }
+
+ routing.loader.yaml:
+ class: Symfony\Component\Routing\Loader\YamlFileLoader
+ arguments:
+ - '@file_locator'
+ tags:
+ - { name: routing.loader }
+
+# ---- Resources Locators ----
+
+ routing.chained_resources_locator:
+ class: phpbb\routing\resources_locator\chained_resources_locator
+ arguments:
+ - '@routing.resources_locator.collection'
+
+ routing.resources_locator.collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: routing.resources_locator }
+
+ routing.resources_locator.default:
+ class: phpbb\routing\resources_locator\default_resources_locator
+ arguments:
+ - '%core.root_path%'
+ - '%core.environment%'
+ - '@ext.manager'
+ tags:
+ - { name: routing.resources_locator }
diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml
new file mode 100644
index 0000000000..a9f2efdb16
--- /dev/null
+++ b/phpBB/config/default/container/services_text_formatter.yml
@@ -0,0 +1,73 @@
+parameters:
+ text_formatter.cache.dir: '%core.cache_dir%'
+ text_formatter.cache.parser.key: _text_formatter_parser
+ text_formatter.cache.renderer.key: _text_formatter_renderer
+
+services:
+ text_formatter.cache:
+ alias: text_formatter.s9e.factory
+
+ text_formatter.data_access:
+ class: phpbb\textformatter\data_access
+ arguments:
+ - '@dbal.conn'
+ - '%tables.bbcodes%'
+ - '%tables.smilies%'
+ - '%tables.styles%'
+ - '%tables.words%'
+ - '%core.root_path%styles/'
+
+ text_formatter.parser:
+ alias: text_formatter.s9e.parser
+
+ text_formatter.renderer:
+ alias: text_formatter.s9e.renderer
+
+ text_formatter.utils:
+ alias: text_formatter.s9e.utils
+
+ text_formatter.s9e.factory:
+ class: phpbb\textformatter\s9e\factory
+ arguments:
+ - '@text_formatter.data_access'
+ - '@cache.driver'
+ - '@dispatcher'
+ - '@config'
+ - '@text_formatter.s9e.link_helper'
+ - '%text_formatter.cache.dir%'
+ - '%text_formatter.cache.parser.key%'
+ - '%text_formatter.cache.renderer.key%'
+
+ text_formatter.s9e.link_helper:
+ class: phpbb\textformatter\s9e\link_helper
+
+ text_formatter.s9e.parser:
+ class: phpbb\textformatter\s9e\parser
+ arguments:
+ - '@cache.driver'
+ - '%text_formatter.cache.parser.key%'
+ - '@text_formatter.s9e.factory'
+ - '@dispatcher'
+
+ text_formatter.s9e.quote_helper:
+ class: phpbb\textformatter\s9e\quote_helper
+ arguments:
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ text_formatter.s9e.renderer:
+ class: phpbb\textformatter\s9e\renderer
+ arguments:
+ - '@cache.driver'
+ - '%text_formatter.cache.dir%'
+ - '%text_formatter.cache.renderer.key%'
+ - '@text_formatter.s9e.factory'
+ - '@dispatcher'
+ calls:
+ - [configure_quote_helper, ['@text_formatter.s9e.quote_helper']]
+ - [configure_smilies_path, ['@config', '@path_helper']]
+ - [configure_user, ['@user', '@config', '@auth']]
+
+ text_formatter.s9e.utils:
+ class: phpbb\textformatter\s9e\utils
diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml
new file mode 100644
index 0000000000..6b0353cf5b
--- /dev/null
+++ b/phpBB/config/default/container/services_text_reparser.yml
@@ -0,0 +1,91 @@
+services:
+ text_reparser.manager:
+ class: phpbb\textreparser\manager
+ arguments:
+ - '@config'
+ - '@config_text'
+ - '@text_reparser_collection'
+
+ text_reparser.lock:
+ class: phpbb\lock\db
+ arguments:
+ - reparse_lock
+ - '@config'
+ - '@dbal.conn'
+
+ text_reparser_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: text_reparser.plugin }
+
+ text_reparser.contact_admin_info:
+ class: phpbb\textreparser\plugins\contact_admin_info
+ arguments:
+ - '@config_text'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.forum_description:
+ class: phpbb\textreparser\plugins\forum_description
+ arguments:
+ - '@dbal.conn'
+ - '%tables.forums%'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.forum_rules:
+ class: phpbb\textreparser\plugins\forum_rules
+ arguments:
+ - '@dbal.conn'
+ - '%tables.forums%'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.group_description:
+ class: phpbb\textreparser\plugins\group_description
+ arguments:
+ - '@dbal.conn'
+ - '%tables.groups%'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.pm_text:
+ class: phpbb\textreparser\plugins\pm_text
+ arguments:
+ - '@dbal.conn'
+ - '%tables.privmsgs%'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.poll_option:
+ class: phpbb\textreparser\plugins\poll_option
+ arguments:
+ - '@dbal.conn'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.poll_title:
+ class: phpbb\textreparser\plugins\poll_title
+ arguments:
+ - '@dbal.conn'
+ - '%tables.topics%'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.post_text:
+ class: phpbb\textreparser\plugins\post_text
+ arguments:
+ - '@dbal.conn'
+ - '%tables.posts%'
+ tags:
+ - { name: text_reparser.plugin }
+
+ text_reparser.user_signature:
+ class: phpbb\textreparser\plugins\user_signature
+ arguments:
+ - '@dbal.conn'
+ - '%tables.users%'
+ tags:
+ - { name: text_reparser.plugin }
diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml
new file mode 100644
index 0000000000..3ca6d62c07
--- /dev/null
+++ b/phpBB/config/default/container/services_twig.yml
@@ -0,0 +1,67 @@
+parameters:
+ core.template.cache_path: '%core.cache_dir%twig/'
+
+services:
+ template.twig.environment:
+ class: phpbb\template\twig\environment
+ arguments:
+ - '@config'
+ - '@filesystem'
+ - '@path_helper'
+ - '%core.template.cache_path%'
+ - '@ext.manager'
+ - '@template.twig.loader'
+ - []
+ calls:
+ - [setLexer, ['@template.twig.lexer']]
+
+ template.twig.lexer:
+ class: phpbb\template\twig\lexer
+ lazy: true
+ arguments:
+ - '@template.twig.environment'
+
+ template.twig.loader:
+ class: phpbb\template\twig\loader
+ arguments:
+ - '@filesystem'
+
+ template.twig.extensions.collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: twig.extension }
+
+ template.twig.extensions.phpbb:
+ class: phpbb\template\twig\extension
+ arguments:
+ - '@template_context'
+ - '@language'
+ tags:
+ - { name: twig.extension }
+
+ template.twig.extensions.routing:
+ class: phpbb\template\twig\extension\routing
+ arguments:
+ - '@routing.helper'
+ tags:
+ - { name: twig.extension }
+
+ template.twig.extensions.debug:
+ class: Twig_Extension_Debug
+
+ template:
+ class: phpbb\template\twig\twig
+ arguments:
+ - '@path_helper'
+ - '@config'
+ - '@template_context'
+ - '@template.twig.environment'
+ - '%core.template.cache_path%'
+ - '@user'
+ - '@template.twig.extensions.collection'
+ - '@ext.manager'
+
+ template_context:
+ class: phpbb\template\context
diff --git a/phpBB/config/default/container/services_user.yml b/phpBB/config/default/container/services_user.yml
new file mode 100644
index 0000000000..7e634c60c3
--- /dev/null
+++ b/phpBB/config/default/container/services_user.yml
@@ -0,0 +1,20 @@
+services:
+ acl.permissions:
+ class: phpbb\permissions
+ arguments:
+ - '@dispatcher'
+ - '@user'
+
+ user:
+ class: phpbb\user
+ arguments:
+ - '@language'
+ - '%datetime.class%'
+
+ user_loader:
+ class: phpbb\user_loader
+ arguments:
+ - '@dbal.conn'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%tables.users%'
diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml
new file mode 100644
index 0000000000..4aed35710b
--- /dev/null
+++ b/phpBB/config/default/container/tables.yml
@@ -0,0 +1,78 @@
+parameters:
+ tables.acl_groups: '%core.table_prefix%acl_groups'
+ tables.acl_options: '%core.table_prefix%acl_options'
+ tables.acl_roles: '%core.table_prefix%acl_roles'
+ tables.acl_roles_data: '%core.table_prefix%acl_roles_data'
+ tables.acl_users: '%core.table_prefix%acl_users'
+ tables.attachments: '%core.table_prefix%attachments'
+ tables.auth_provider_oauth_token_storage: '%core.table_prefix%oauth_tokens'
+ tables.auth_provider_oauth_states: '%core.table_prefix%oauth_states'
+ tables.auth_provider_oauth_account_assoc: '%core.table_prefix%oauth_accounts'
+ tables.banlist: '%core.table_prefix%banlist'
+ tables.bbcodes: '%core.table_prefix%bbcodes'
+ tables.bookmarks: '%core.table_prefix%bookmarks'
+ tables.bots: '%core.table_prefix%bots'
+ tables.captcha_qa_questions: '%core.table_prefix%captcha_questions'
+ tables.captcha_qa_answers: '%core.table_prefix%captcha_answers'
+ tables.captcha_qa_confirm: '%core.table_prefix%qa_confirm'
+ tables.config: '%core.table_prefix%config'
+ tables.config_text: '%core.table_prefix%config_text'
+ tables.confirm: '%core.table_prefix%confirm'
+ tables.disallow: '%core.table_prefix%disallow'
+ tables.drafts: '%core.table_prefix%drafts'
+ tables.ext: '%core.table_prefix%ext'
+ tables.extensions: '%core.table_prefix%extensions'
+ tables.extension_groups: '%core.table_prefix%extension_groups'
+ tables.forums: '%core.table_prefix%forums'
+ tables.forums_access: '%core.table_prefix%forums_access'
+ tables.forums_track: '%core.table_prefix%forums_track'
+ tables.forums_watch: '%core.table_prefix%forums_watch'
+ tables.groups: '%core.table_prefix%groups'
+ tables.icons: '%core.table_prefix%icons'
+ tables.lang: '%core.table_prefix%lang'
+ tables.log: '%core.table_prefix%log'
+ tables.login_attempts: '%core.table_prefix%login_attempts'
+ tables.migrations: '%core.table_prefix%migrations'
+ tables.moderator_cache: '%core.table_prefix%moderator_cache'
+ tables.modules: '%core.table_prefix%modules'
+ tables.notification_types: '%core.table_prefix%notification_types'
+ tables.notifications: '%core.table_prefix%notifications'
+ tables.poll_options: '%core.table_prefix%poll_options'
+ tables.poll_votes: '%core.table_prefix%poll_votes'
+ tables.posts: '%core.table_prefix%posts'
+ tables.privmsgs: '%core.table_prefix%privmsgs'
+ tables.privmsgs_folder: '%core.table_prefix%privmsgs_folder'
+ tables.privmsgs_rules: '%core.table_prefix%privmsgs_rules'
+ tables.privmsgs_to: '%core.table_prefix%privmsgs_to'
+ tables.profile_fields: '%core.table_prefix%profile_fields'
+ tables.profile_fields_data: '%core.table_prefix%profile_fields_data'
+ tables.profile_fields_options_language: '%core.table_prefix%profile_fields_lang'
+ tables.profile_fields_language: '%core.table_prefix%profile_lang'
+ tables.ranks: '%core.table_prefix%ranks'
+ tables.reports: '%core.table_prefix%reports'
+ tables.reports_reasons: '%core.table_prefix%reports_reasons'
+ tables.search_results: '%core.table_prefix%search_results'
+ tables.search_wordlist: '%core.table_prefix%search_wordlist'
+ tables.search_wordmatch: '%core.table_prefix%search_wordmatch'
+ tables.sessions: '%core.table_prefix%sessions'
+ tables.sessions_keys: '%core.table_prefix%sessions_keys'
+ tables.sitelist: '%core.table_prefix%sitelist'
+ tables.smilies: '%core.table_prefix%smilies'
+ tables.sphinx: '%core.table_prefix%sphinx'
+ tables.styles: '%core.table_prefix%styles'
+ tables.styles_template: '%core.table_prefix%styles_template'
+ tables.styles_template_data: '%core.table_prefix%styles_template_data'
+ tables.styles_theme: '%core.table_prefix%styles_theme'
+ tables.styles_imageset: '%core.table_prefix%styles_imageset'
+ tables.styles_imageset_data: '%core.table_prefix%styles_imageset_data'
+ tables.teampage: '%core.table_prefix%teampage'
+ tables.topics: '%core.table_prefix%topics'
+ tables.topics_posted: '%core.table_prefix%topics_posted'
+ tables.topics_track: '%core.table_prefix%topics_track'
+ tables.topics_watch: '%core.table_prefix%topics_watch'
+ tables.user_group: '%core.table_prefix%user_group'
+ tables.user_notifications: '%core.table_prefix%user_notifications'
+ tables.users: '%core.table_prefix%users'
+ tables.warnings: '%core.table_prefix%warnings'
+ tables.words: '%core.table_prefix%words'
+ tables.zebra: '%core.table_prefix%zebra'
diff --git a/phpBB/config/default/routing/feed.yml b/phpBB/config/default/routing/feed.yml
new file mode 100644
index 0000000000..22c9ea5755
--- /dev/null
+++ b/phpBB/config/default/routing/feed.yml
@@ -0,0 +1,35 @@
+phpbb_feed_forums:
+ path: /forums
+ defaults: { _controller: phpbb.feed.controller:forums }
+
+phpbb_feed_news:
+ path: /news
+ defaults: { _controller: phpbb.feed.controller:news }
+
+phpbb_feed_topics:
+ path: /topics
+ defaults: { _controller: phpbb.feed.controller:topics }
+
+phpbb_feed_topics_active:
+ path: /topics_active
+ defaults: { _controller: phpbb.feed.controller:topics_active }
+
+phpbb_feed_topics_new:
+ path: /topics_new
+ defaults: { _controller: phpbb.feed.controller:topics_new }
+
+phpbb_feed_forum:
+ path: /forum/{forum_id}
+ defaults: { _controller: phpbb.feed.controller:forum }
+ requirements:
+ forum_id: \d+
+
+phpbb_feed_topic:
+ path: /topic/{topic_id}
+ defaults: { _controller: phpbb.feed.controller:topic }
+ requirements:
+ topic_id: \d+
+
+phpbb_feed_overall:
+ path: /{mode}
+ defaults: { _controller: phpbb.feed.controller:overall }
diff --git a/phpBB/config/default/routing/help.yml b/phpBB/config/default/routing/help.yml
new file mode 100644
index 0000000000..8d43839d1e
--- /dev/null
+++ b/phpBB/config/default/routing/help.yml
@@ -0,0 +1,7 @@
+phpbb_help_bbcode_controller:
+ path: /bbcode
+ defaults: { _controller: phpbb.help.controller.bbcode:handle }
+
+phpbb_help_faq_controller:
+ path: /faq
+ defaults: { _controller: phpbb.help.controller.faq:handle }
diff --git a/phpBB/config/default/routing/report.yml b/phpBB/config/default/routing/report.yml
new file mode 100644
index 0000000000..c386770e42
--- /dev/null
+++ b/phpBB/config/default/routing/report.yml
@@ -0,0 +1,17 @@
+phpbb_report_pm_controller:
+ path: /pm/{id}/report
+ methods: [GET, POST]
+ defaults:
+ _controller: phpbb.report.controller:handle
+ mode: 'pm'
+ requirements:
+ id: \d+
+
+phpbb_report_post_controller:
+ path: /post/{id}/report
+ methods: [GET, POST]
+ defaults:
+ _controller: phpbb.report.controller:handle
+ mode: 'post'
+ requirements:
+ id: \d+
diff --git a/phpBB/config/default/routing/routing.yml b/phpBB/config/default/routing/routing.yml
new file mode 100644
index 0000000000..f381f024ad
--- /dev/null
+++ b/phpBB/config/default/routing/routing.yml
@@ -0,0 +1,24 @@
+# Structure:
+#
+# foo_controller:
+# path: /foo
+# defaults: { _controller: foo_sevice:method }
+#
+# The above will be accessed via app.php?controller=foo and it will
+# instantiate the 'foo_service' service and call the 'method' method.
+#
+
+phpbb_feed_routing:
+ resource: feed.yml
+ prefix: /feed
+
+phpbb_feed_index:
+ path: /feed
+ defaults: { _controller: phpbb.feed.controller:overall }
+
+phpbb_help_routing:
+ resource: help.yml
+ prefix: /help
+
+phpbb_report_routing:
+ resource: report.yml
diff --git a/phpBB/config/development/config.yml b/phpBB/config/development/config.yml
new file mode 100644
index 0000000000..f39eb52e73
--- /dev/null
+++ b/phpBB/config/development/config.yml
@@ -0,0 +1,13 @@
+imports:
+ - { resource: ../default/config.yml }
+
+core:
+ require_dev_dependencies: true
+
+ debug:
+ exceptions: true
+
+ twig:
+ debug: true
+ auto_reload: true
+ enable_debug_extension: true
diff --git a/phpBB/config/development/container/environment.yml b/phpBB/config/development/container/environment.yml
new file mode 100644
index 0000000000..40a3c7a683
--- /dev/null
+++ b/phpBB/config/development/container/environment.yml
@@ -0,0 +1,3 @@
+imports:
+ - { resource: services.yml }
+ - { resource: parameters.yml }
diff --git a/phpBB/config/development/container/parameters.yml b/phpBB/config/development/container/parameters.yml
new file mode 100644
index 0000000000..0447646806
--- /dev/null
+++ b/phpBB/config/development/container/parameters.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../../default/container/parameters.yml }
diff --git a/phpBB/config/development/container/services.yml b/phpBB/config/development/container/services.yml
new file mode 100644
index 0000000000..b302f0f966
--- /dev/null
+++ b/phpBB/config/development/container/services.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../../default/container/services.yml }
diff --git a/phpBB/config/development/routing/environment.yml b/phpBB/config/development/routing/environment.yml
new file mode 100644
index 0000000000..301183bbae
--- /dev/null
+++ b/phpBB/config/development/routing/environment.yml
@@ -0,0 +1,2 @@
+core.default:
+ resource: ../../default/routing/routing.yml
diff --git a/phpBB/config/event.yml b/phpBB/config/event.yml
deleted file mode 100644
index 7bc4cb0042..0000000000
--- a/phpBB/config/event.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-services:
- dispatcher:
- class: phpbb\event\dispatcher
- arguments:
- - @service_container
-
- hook_finder:
- class: phpbb\hook\finder
- arguments:
- - %core.root_path%
- - %core.php_ext%
- - @cache.driver
-
- kernel_request_subscriber:
- class: phpbb\event\kernel_request_subscriber
- arguments:
- - @ext.manager
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: kernel.event_subscriber }
-
- kernel_exception_subscriber:
- class: phpbb\event\kernel_exception_subscriber
- arguments:
- - @template
- - @user
- tags:
- - { name: kernel.event_subscriber }
-
- kernel_terminate_subscriber:
- class: phpbb\event\kernel_terminate_subscriber
- tags:
- - { name: kernel.event_subscriber }
-
- symfony_response_listener:
- class: Symfony\Component\HttpKernel\EventListener\ResponseListener
- arguments:
- - UTF-8
- tags:
- - { name: kernel.event_subscriber }
diff --git a/phpBB/config/feed.yml b/phpBB/config/feed.yml
deleted file mode 100644
index b69f80b2c5..0000000000
--- a/phpBB/config/feed.yml
+++ /dev/null
@@ -1,113 +0,0 @@
-services:
- feed.helper:
- class: phpbb\feed\helper
- arguments:
- - @config
- - @user
- - %core.root_path%
- - %core.php_ext%
-
- feed.factory:
- class: phpbb\feed\factory
- arguments:
- - @service_container
- - @config
- - @dbal.conn
-
- feed.forum:
- class: phpbb\feed\forum
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
-
- feed.forums:
- class: phpbb\feed\forums
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
-
- feed.news:
- class: phpbb\feed\news
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
-
- feed.overall:
- class: phpbb\feed\overall
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
-
- feed.topic:
- class: phpbb\feed\topic
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
-
- feed.topics:
- class: phpbb\feed\topics
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
-
- feed.topics_active:
- class: phpbb\feed\topics_active
- scope: prototype
- arguments:
- - @feed.helper
- - @config
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @content.visibility
- - @dispatcher
- - %core.php_ext%
diff --git a/phpBB/config/installer/config.yml b/phpBB/config/installer/config.yml
new file mode 100644
index 0000000000..979dbbcdd9
--- /dev/null
+++ b/phpBB/config/installer/config.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../default/config.yml }
diff --git a/phpBB/config/installer/container/environment.yml b/phpBB/config/installer/container/environment.yml
new file mode 100644
index 0000000000..40a3c7a683
--- /dev/null
+++ b/phpBB/config/installer/container/environment.yml
@@ -0,0 +1,3 @@
+imports:
+ - { resource: services.yml }
+ - { resource: parameters.yml }
diff --git a/phpBB/config/installer/container/parameters.yml b/phpBB/config/installer/container/parameters.yml
new file mode 100644
index 0000000000..f11f7e2d84
--- /dev/null
+++ b/phpBB/config/installer/container/parameters.yml
@@ -0,0 +1,5 @@
+imports:
+ - { resource: ../../default/container/parameters.yml }
+
+parameters:
+ installer.create_config_file.options: []
diff --git a/phpBB/config/installer/container/services.yml b/phpBB/config/installer/container/services.yml
new file mode 100644
index 0000000000..4c3ed3bfcb
--- /dev/null
+++ b/phpBB/config/installer/container/services.yml
@@ -0,0 +1,97 @@
+imports:
+ - { resource: services_installer.yml }
+ - { resource: ../../default/container/services_event.yml }
+ - { resource: ../../default/container/services_filesystem.yml }
+ - { resource: ../../default/container/services_http.yml }
+ - { resource: ../../default/container/services_language.yml }
+ - { resource: ../../default/container/services_php.yml }
+ - { resource: ../../default/container/services_routing.yml }
+ - { resource: ../../default/container/services_twig.yml }
+
+services:
+ cache.driver:
+ class: '%cache.driver.class%'
+ arguments:
+ - '%core.cache_dir%'
+
+ config:
+ class: phpbb\config\config
+ arguments:
+ -
+ rand_seed: 'installer_seed'
+ rand_seed_last_update: 0
+
+ controller.resolver:
+ class: phpbb\controller\resolver
+ arguments:
+ - '@service_container'
+ - '%core.root_path%'
+ - '@template'
+
+ file_locator:
+ class: phpbb\routing\file_locator
+ arguments:
+ - '@filesystem'
+ - '%core.root_path%'
+
+ kernel_exception_subscriber:
+ class: phpbb\install\event\kernel_exception_subscriber
+ arguments:
+ - '@phpbb.installer.controller.helper'
+ - '@language'
+ - '@template'
+ tags:
+ - { name: kernel.event_subscriber }
+
+ language.loader:
+ parent: language.loader_abstract
+
+ path_helper:
+ class: phpbb\path_helper
+ arguments:
+ - '@symfony_request'
+ - '@filesystem'
+ - '@request'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ routing.resources_locator.default:
+ class: phpbb\routing\resources_locator\installer_resources_locator
+ arguments:
+ - '@filesystem'
+ - '%core.root_path%'
+ - '%core.environment%'
+ tags:
+ - { name: routing.resources_locator }
+
+ template:
+ class: phpbb\template\twig\twig
+ arguments:
+ - '@path_helper'
+ - '@config'
+ - '@template_context'
+ - '@template.twig.environment'
+ - '%core.template.cache_path%'
+ - null
+ - '@template.twig.extensions.collection'
+
+ template.twig.environment:
+ class: phpbb\template\twig\environment
+ arguments:
+ - '@config'
+ - '@filesystem'
+ - '@path_helper'
+ - '%core.template.cache_path%'
+ - null
+ - '@template.twig.loader'
+ - []
+ calls:
+ - [setLexer, ['@template.twig.lexer']]
+
+ console.exception_subscriber:
+ class: phpbb\console\exception_subscriber
+ arguments:
+ - '@language'
+ - '%debug.exceptions%'
+ tags:
+ - { name: kernel.event_subscriber }
diff --git a/phpBB/config/installer/container/services_file_updater.yml b/phpBB/config/installer/container/services_file_updater.yml
new file mode 100644
index 0000000000..9d39bb8b89
--- /dev/null
+++ b/phpBB/config/installer/container/services_file_updater.yml
@@ -0,0 +1,38 @@
+services:
+ installer.file_updater.factory:
+ class: phpbb\install\helper\file_updater\factory
+ arguments:
+ - '@installer.file_updater.collection'
+
+ installer.file_updater.collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: file_updater }
+
+ installer.file_updater.compress:
+ class: phpbb\install\helper\file_updater\compression_file_updater
+ arguments:
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: file_updater }
+
+ installer.file_updater.ftp:
+ class: phpbb\install\helper\file_updater\ftp_file_updater
+ arguments:
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: file_updater }
+
+ installer.file_updater.file:
+ class: phpbb\install\helper\file_updater\file_updater
+ arguments:
+ - '@filesystem'
+ - '%core.root_path%'
+ tags:
+ - { name: file_updater }
diff --git a/phpBB/config/installer/container/services_install_console.yml b/phpBB/config/installer/container/services_install_console.yml
new file mode 100644
index 0000000000..41d3aa4c1b
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_console.yml
@@ -0,0 +1,61 @@
+services:
+ console.installer.command_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: console.installer.command }
+
+ console.installer.command.install:
+ class: phpbb\install\console\command\install\install
+ arguments:
+ - '@language'
+ - '@installer.helper.iohandler_factory'
+ - '@installer.installer.install'
+ - '@installer.helper.install_helper'
+ tags:
+ - { name: console.installer.command }
+
+ console.installer.command.config.show:
+ class: phpbb\install\console\command\install\config\show
+ arguments:
+ - '@language'
+ - '@installer.helper.iohandler_factory'
+ tags:
+ - { name: console.installer.command }
+
+
+ console.installer.command.config.validate:
+ class: phpbb\install\console\command\install\config\validate
+ arguments:
+ - '@language'
+ - '@installer.helper.iohandler_factory'
+ tags:
+ - { name: console.installer.command }
+
+ console.updater.command.update:
+ class: phpbb\install\console\command\update\update
+ arguments:
+ - '@language'
+ - '@installer.helper.iohandler_factory'
+ - '@installer.installer.update'
+ - '@installer.helper.install_helper'
+ tags:
+ - { name: console.installer.command }
+
+ console.updater.command.config.show:
+ class: phpbb\install\console\command\update\config\show
+ arguments:
+ - '@language'
+ - '@installer.helper.iohandler_factory'
+ tags:
+ - { name: console.installer.command }
+
+
+ console.updater.command.config.validate:
+ class: phpbb\install\console\command\update\config\validate
+ arguments:
+ - '@language'
+ - '@installer.helper.iohandler_factory'
+ tags:
+ - { name: console.installer.command }
diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml
new file mode 100644
index 0000000000..5aaba0f47f
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_controller.yml
@@ -0,0 +1,73 @@
+services:
+ phpbb.installer.controller.welcome:
+ class: phpbb\install\controller\installer_index
+ arguments:
+ - '@phpbb.installer.controller.helper'
+ - '@language'
+ - '@template'
+ - '%core.root_path%'
+
+ phpbb.installer.controller.helper:
+ class: phpbb\install\controller\helper
+ arguments:
+ - '@installer.helper.config'
+ - '@language'
+ - '@language.helper.language_file'
+ - '@installer.navigation.provider'
+ - '@template'
+ - '@path_helper'
+ - '@request'
+ - '@symfony_request'
+ - '@router'
+ - '%core.root_path%'
+
+ phpbb.installer.controller.install:
+ class: phpbb\install\controller\install
+ arguments:
+ - '@phpbb.installer.controller.helper'
+ - '@installer.helper.iohandler_factory'
+ - '@installer.navigation.provider'
+ - '@language'
+ - '@template'
+ - '@request'
+ - '@installer.installer.install'
+ - '@installer.helper.install_helper'
+
+ phpbb.installer.controller.update:
+ class: phpbb\install\controller\update
+ arguments:
+ - '@phpbb.installer.controller.helper'
+ - '@installer.installer.update'
+ - '@installer.helper.install_helper'
+ - '@installer.helper.iohandler_factory'
+ - '@language'
+ - '@installer.navigation.provider'
+ - '@request'
+ - '@template'
+
+ phpbb.installer.controller.file_downloader:
+ class: phpbb\install\controller\archive_download
+ arguments:
+ - '@installer.helper.config'
+
+ phpbb.installer.controller.convert:
+ class: phpbb\convert\controller\convertor
+ arguments:
+ - '@cache.driver'
+ - '@installer.helper.container_factory'
+ - '@installer.helper.database'
+ - '@phpbb.installer.controller.helper'
+ - '@installer.helper.install_helper'
+ - '@installer.helper.iohandler_factory'
+ - '@language'
+ - '@installer.navigation.provider'
+ - '@request'
+ - '@template'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ phpbb.installer.controller.status:
+ class: phpbb\install\controller\timeout_check
+ arguments:
+ - '@phpbb.installer.controller.helper'
+ - '%core.root_path%'
diff --git a/phpBB/config/installer/container/services_install_data.yml b/phpBB/config/installer/container/services_install_data.yml
new file mode 100644
index 0000000000..df63d16d0d
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_data.yml
@@ -0,0 +1,45 @@
+services:
+ installer.install_data.add_bots:
+ class: phpbb\install\module\install_data\task\add_bots
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.container_factory'
+ - '@language'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: install_data_install, order: 20 }
+
+ installer.install_data.add_languages:
+ class: phpbb\install\module\install_data\task\add_languages
+ arguments:
+ - '@installer.helper.iohandler'
+ - '@installer.helper.container_factory'
+ - '@language.helper.language_file'
+ tags:
+ - { name: install_data_install, order: 10 }
+
+ installer.install_data.add_modules:
+ class: phpbb\install\module\install_data\task\add_modules
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.container_factory'
+ tags:
+ - { name: install_data_install, order: 30 }
+
+ installer.module.data_install_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: install_data_install, class_name_aware: true }
+
+ installer.module.data_install:
+ class: phpbb\install\module\install_data\module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.data_install_collection'
+ tags:
+ - { name: installer_install_module, order: 50 }
diff --git a/phpBB/config/installer/container/services_install_database.yml b/phpBB/config/installer/container/services_install_database.yml
new file mode 100644
index 0000000000..33f596506d
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_database.yml
@@ -0,0 +1,71 @@
+services:
+ installer.install_database.create_schema_file:
+ class: phpbb\install\module\install_database\task\create_schema_file
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.database'
+ - '@filesystem'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: install_database_install, order: 10 }
+
+ installer.install_database.set_up_database:
+ class: phpbb\install\module\install_database\task\set_up_database
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.database'
+ - '@filesystem'
+ - '@installer.helper.iohandler'
+ - '%core.root_path%'
+ tags:
+ - { name: install_database_install, order: 20 }
+
+ installer.install_database.add_tables:
+ class: phpbb\install\module\install_database\task\add_tables
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.database'
+ - '@filesystem'
+ - '%core.root_path%'
+ tags:
+ - { name: install_database_install, order: 30 }
+
+ installer.install_database.add_default_data:
+ class: phpbb\install\module\install_database\task\add_default_data
+ arguments:
+ - '@installer.helper.database'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.container_factory'
+ - '@language'
+ - '%core.root_path%'
+ tags:
+ - { name: install_database_install, order: 40 }
+
+ installer.install_database.add_config_settings:
+ class: phpbb\install\module\install_database\task\add_config_settings
+ arguments:
+ - '@filesystem'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.container_factory'
+ - '@language'
+ - '%core.root_path%'
+ tags:
+ - { name: install_database_install, order: 50 }
+
+ installer.module.install_database_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: install_database_install, class_name_aware: true }
+
+ installer.module.database_install:
+ class: phpbb\install\module\install_database\module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.install_database_collection'
+ tags:
+ - { name: installer_install_module, order: 40 }
diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml
new file mode 100644
index 0000000000..65b2a6eddd
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_filesystem.yml
@@ -0,0 +1,28 @@
+services:
+ installer.install_filesystem.create_config_file:
+ class: phpbb\install\module\install_filesystem\task\create_config_file
+ arguments:
+ - '@filesystem'
+ - '@installer.helper.config'
+ - '@installer.helper.database'
+ - '@installer.helper.iohandler'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - '%installer.create_config_file.options%'
+ tags:
+ - { name: install_filesystem_install, order: 10 }
+
+ installer.module.install_filesystem_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: install_filesystem_install, class_name_aware: true }
+
+ installer.module.filesystem_install:
+ class: phpbb\install\module\install_filesystem\module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.install_filesystem_collection'
+ tags:
+ - { name: installer_install_module, order: 30 }
diff --git a/phpBB/config/installer/container/services_install_finish.yml b/phpBB/config/installer/container/services_install_finish.yml
new file mode 100644
index 0000000000..8b06ad7d97
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_finish.yml
@@ -0,0 +1,34 @@
+services:
+ installer.install_finish.populate_migrations:
+ class: phpbb\install\module\install_finish\task\populate_migrations
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.container_factory'
+ tags:
+ - { name: install_finish, order: 10 }
+
+ installer.install_finish.notify_user:
+ class: phpbb\install\module\install_finish\task\notify_user
+ arguments:
+ - '@installer.helper.container_factory'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: install_finish, order: 20 }
+
+ installer.module.install_finish_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: install_finish, class_name_aware: true }
+
+ installer.module.finish_install:
+ class: phpbb\install\module\install_finish\module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.install_finish_collection'
+ tags:
+ - { name: installer_install_module, order: 60 }
diff --git a/phpBB/config/installer/container/services_install_navigation.yml b/phpBB/config/installer/container/services_install_navigation.yml
new file mode 100644
index 0000000000..d7151eb1c6
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_navigation.yml
@@ -0,0 +1,42 @@
+services:
+ installer.navigation.provider:
+ class: phpbb\install\helper\navigation\navigation_provider
+ arguments:
+ - '@installer.navigation.service_collection'
+
+ installer.navigation.service_collection:
+ class: phpbb\di\service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: installer.navigation }
+
+ installer.navigation.main_navigation:
+ class: phpbb\install\helper\navigation\main_navigation
+ shared: false
+ tags:
+ - { name: installer.navigation }
+
+ installer.navigation.install_navigation:
+ class: phpbb\install\helper\navigation\install_navigation
+ arguments:
+ - '@installer.helper.install_helper'
+ shared: false
+ tags:
+ - { name: installer.navigation }
+
+ installer.navigation.update_navigation:
+ class: phpbb\install\helper\navigation\update_navigation
+ arguments:
+ - '@installer.helper.install_helper'
+ shared: false
+ tags:
+ - { name: installer.navigation }
+
+ installer.navigation.convertor_navigation:
+ class: phpbb\install\helper\navigation\convertor_navigation
+ arguments:
+ - '@installer.helper.install_helper'
+ shared: false
+ tags:
+ - { name: installer.navigation }
diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml
new file mode 100644
index 0000000000..cd8d0c8072
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_obtain_data.yml
@@ -0,0 +1,66 @@
+services:
+ installer.obtain_data.obtain_admin_data:
+ class: phpbb\install\module\obtain_data\task\obtain_admin_data
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ tags:
+ - { name: install_obtain_data, order: 10 }
+
+ installer.obtain_data.obtain_board_data:
+ class: phpbb\install\module\obtain_data\task\obtain_board_data
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@language.helper.language_file'
+ tags:
+ - { name: install_obtain_data, order: 50 }
+
+ installer.obtain_data.obtain_database_data:
+ class: phpbb\install\module\obtain_data\task\obtain_database_data
+ arguments:
+ - '@installer.helper.database'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ tags:
+ - { name: install_obtain_data, order: 20 }
+
+ installer.obtain_data.obtain_email_data:
+ class: phpbb\install\module\obtain_data\task\obtain_email_data
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ 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:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ tags:
+ - { name: install_obtain_data, order: 30 }
+
+ installer.module.install_obtain_data_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: install_obtain_data, class_name_aware: true }
+
+ installer.module.obtain_data_install:
+ class: phpbb\install\module\obtain_data\install_module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.install_obtain_data_collection'
+ - true
+ - false
+ tags:
+ - { name: installer_install_module, order: 20 }
diff --git a/phpBB/config/installer/container/services_install_requirements.yml b/phpBB/config/installer/container/services_install_requirements.yml
new file mode 100644
index 0000000000..c03eb1fb93
--- /dev/null
+++ b/phpBB/config/installer/container/services_install_requirements.yml
@@ -0,0 +1,37 @@
+services:
+ installer.requirements.check_filesystem:
+ class: phpbb\install\module\requirements\task\check_filesystem
+ arguments:
+ - '@filesystem'
+ - '@installer.helper.iohandler'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: installer_requirements, order: 10 }
+
+ installer.requirements.check_server_environment:
+ class: phpbb\install\module\requirements\task\check_server_environment
+ arguments:
+ - '@installer.helper.database'
+ - '@installer.helper.iohandler'
+ tags:
+ - { name: installer_requirements, order: 20 }
+ - { name: update_requirements, order: 20 }
+
+ installer.module.install_requirements_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: installer_requirements, class_name_aware: true }
+
+# Please note, that the name of this module is hard coded in the installer service
+ installer.module.requirements_install:
+ class: phpbb\install\module\requirements\install_module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.install_requirements_collection'
+ - true
+ - false
+ tags:
+ - { name: installer_install_module, order: 10 }
diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml
new file mode 100644
index 0000000000..57181b21d4
--- /dev/null
+++ b/phpBB/config/installer/container/services_installer.yml
@@ -0,0 +1,119 @@
+imports:
+ - { resource: services_file_updater.yml }
+ - { resource: services_install_console.yml }
+ - { resource: services_install_controller.yml }
+ - { resource: services_install_data.yml }
+ - { resource: services_install_database.yml }
+ - { resource: services_install_filesystem.yml }
+ - { resource: services_install_finish.yml }
+ - { resource: services_install_navigation.yml }
+ - { resource: services_install_obtain_data.yml }
+ - { resource: services_install_requirements.yml }
+ - { resource: services_update_database.yml }
+ - { resource: services_update_filesystem.yml }
+ - { resource: services_update_obtain_data.yml }
+ - { resource: services_update_requirements.yml }
+
+services:
+# -------- Installer helpers ------------------------
+ installer.helper.config:
+ class: phpbb\install\helper\config
+ arguments:
+ - '@filesystem'
+ - '@php_ini'
+ - '%core.root_path%'
+
+ installer.helper.database:
+ class: phpbb\install\helper\database
+ arguments:
+ - '@filesystem'
+ - '%core.root_path%'
+
+ installer.helper.iohandler_factory:
+ class: phpbb\install\helper\iohandler\factory
+ arguments:
+ - '@service_container'
+
+ installer.helper.iohandler_abstract:
+ abstract: true
+ calls:
+ - [set_language, ['@language']]
+
+ installer.helper.iohandler_ajax:
+ class: phpbb\install\helper\iohandler\ajax_iohandler
+ parent: installer.helper.iohandler_abstract
+ arguments:
+ - '@path_helper'
+ - '@request'
+ - '@template'
+ - '@router'
+ - '%core.root_path%'
+
+ installer.helper.iohandler_cli:
+ class: phpbb\install\helper\iohandler\cli_iohandler
+ parent: installer.helper.iohandler_abstract
+
+ installer.helper.iohandler:
+ class: phpbb\install\helper\iohandler\iohandler_interface
+ factory: ['@installer.helper.iohandler_factory', get]
+
+ installer.helper.container_factory:
+ class: phpbb\install\helper\container_factory
+ arguments:
+ - '@language'
+ - '@request'
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ installer.helper.install_helper:
+ class: phpbb\install\helper\install_helper
+ arguments:
+ - '%core.root_path%'
+ - '%core.php_ext%'
+
+ installer.helper.update_helper:
+ class: phpbb\install\helper\update_helper
+ arguments:
+ - '%core.root_path%'
+
+# -------- Installer --------------------------------
+ installer.module_base:
+ abstract: true
+ calls:
+ - [setup, ['@installer.helper.config', '@installer.helper.iohandler']]
+
+ installer.installer.abstract:
+ class: phpbb\install\installer
+ abstract: true
+ arguments:
+ - '@cache.driver'
+ - '@installer.helper.config'
+ - '@path_helper'
+ - '@installer.helper.container_factory'
+
+ installer.install.module_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: installer_install_module }
+
+ installer.update.module_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: installer_update_module }
+
+ installer.installer.install:
+ parent: installer.installer.abstract
+ calls:
+ - [set_modules, ['@installer.install.module_collection']]
+ - [set_purge_cache_before, [false]]
+
+ installer.installer.update:
+ parent: installer.installer.abstract
+ calls:
+ - [set_modules, ['@installer.update.module_collection']]
+ - [set_purge_cache_before, [true]]
diff --git a/phpBB/config/installer/container/services_update_database.yml b/phpBB/config/installer/container/services_update_database.yml
new file mode 100644
index 0000000000..9cb9cb9abf
--- /dev/null
+++ b/phpBB/config/installer/container/services_update_database.yml
@@ -0,0 +1,29 @@
+services:
+ installer.update_database.update_task:
+ class: phpbb\install\module\update_database\task\update
+ arguments:
+ - '@installer.helper.container_factory'
+ - '@filesystem'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@language'
+ - '%core.root_path%'
+ tags:
+ - { name: update_database_task, order: 10 }
+
+ installer.module.update_database_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: update_database_task, class_name_aware: true }
+
+ installer.module.update_database:
+ class: phpbb\install\module\update_database\module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.update_database_collection'
+ - true
+ - false
+ tags:
+ - { name: installer_update_module, order: 40 }
diff --git a/phpBB/config/installer/container/services_update_filesystem.yml b/phpBB/config/installer/container/services_update_filesystem.yml
new file mode 100644
index 0000000000..c0a04676f6
--- /dev/null
+++ b/phpBB/config/installer/container/services_update_filesystem.yml
@@ -0,0 +1,72 @@
+services:
+ installer.update_filesystem.check_task:
+ class: phpbb\install\module\update_filesystem\task\file_check
+ arguments:
+ - '@filesystem'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ tags:
+ - { name: update_filesystem, order: 10 }
+
+ installer.update_filesystem.diff_files:
+ class: phpbb\install\module\update_filesystem\task\diff_files
+ arguments:
+ - '@installer.helper.container_factory'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: update_filesystem, order: 20 }
+
+ installer.update_filesystem.show_file_status:
+ class: phpbb\install\module\update_filesystem\task\show_file_status
+ arguments:
+ - '@installer.helper.container_factory'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@filesystem'
+ - '@installer.file_updater.factory'
+ tags:
+ - { name: update_filesystem, order: 30 }
+
+ installer.update_filesystem.update_files:
+ class: phpbb\install\module\update_filesystem\task\update_files
+ arguments:
+ - '@installer.helper.container_factory'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.file_updater.factory'
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ tags:
+ - { name: update_filesystem, order: 40 }
+
+ installer.update_filesystem.download_updated_files:
+ class: phpbb\install\module\update_filesystem\task\download_updated_files
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@filesystem'
+ tags:
+ - { name: update_filesystem, order: 50 }
+
+ installer.module.update_filesystem_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: update_filesystem, class_name_aware: true }
+
+ installer.module.filesystem_update:
+ class: phpbb\install\module\update_filesystem\module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.update_filesystem_collection'
+ - true
+ - false
+ tags:
+ - { name: installer_update_module, order: 30 }
diff --git a/phpBB/config/installer/container/services_update_obtain_data.yml b/phpBB/config/installer/container/services_update_obtain_data.yml
new file mode 100644
index 0000000000..999976aed0
--- /dev/null
+++ b/phpBB/config/installer/container/services_update_obtain_data.yml
@@ -0,0 +1,53 @@
+services:
+ installer.obtain_data.update_options:
+ class: phpbb\install\module\obtain_data\task\obtain_update_settings
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ tags:
+ - { name: update_obtain_data, order: 10 }
+
+ installer.obtain_data.file_updater_method:
+ class: phpbb\install\module\obtain_data\task\obtain_file_updater_method
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ tags:
+ - { name: update_obtain_data, order: 20 }
+
+ installer.obtain_data.update_files:
+ class: phpbb\install\module\obtain_data\task\obtain_update_files
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: update_obtain_data, order: 30 }
+
+ installer.obtain_data.update_ftp_settings:
+ class: phpbb\install\module\obtain_data\task\obtain_update_ftp_data
+ arguments:
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.update_helper'
+ - '%core.php_ext%'
+ tags:
+ - { name: update_obtain_data, order: 40 }
+
+ installer.module.update_obtain_data_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: update_obtain_data, class_name_aware: true }
+
+ installer.module.obtain_data_update:
+ class: phpbb\install\module\obtain_data\update_module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.update_obtain_data_collection'
+ - true
+ - false
+ tags:
+ - { name: installer_update_module, order: 20 }
diff --git a/phpBB/config/installer/container/services_update_requirements.yml b/phpBB/config/installer/container/services_update_requirements.yml
new file mode 100644
index 0000000000..6b851de78b
--- /dev/null
+++ b/phpBB/config/installer/container/services_update_requirements.yml
@@ -0,0 +1,41 @@
+services:
+ installer.requirements.check_filesystem_update:
+ class: phpbb\install\module\requirements\task\check_filesystem
+ arguments:
+ - '@filesystem'
+ - '@installer.helper.iohandler'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ - false
+ tags:
+ - { name: update_requirements, order: 10 }
+
+ installer.requirements.update_requirements:
+ class: phpbb\install\module\requirements\task\check_update
+ arguments:
+ - '@installer.helper.container_factory'
+ - '@filesystem'
+ - '@installer.helper.config'
+ - '@installer.helper.iohandler'
+ - '@installer.helper.update_helper'
+ - '%core.root_path%'
+ - '%core.php_ext%'
+ tags:
+ - { name: update_requirements, order: 30 }
+
+ installer.module.update_requirements_collection:
+ class: phpbb\di\ordered_service_collection
+ arguments:
+ - '@service_container'
+ tags:
+ - { name: service_collection, tag: update_requirements, class_name_aware: true }
+
+ installer.module.requirements_update:
+ class: phpbb\install\module\requirements\update_module
+ parent: installer.module_base
+ arguments:
+ - '@installer.module.update_requirements_collection'
+ - true
+ - false
+ tags:
+ - { name: installer_update_module, order: 10 }
diff --git a/phpBB/config/installer/routing/environment.yml b/phpBB/config/installer/routing/environment.yml
new file mode 100644
index 0000000000..7a1f588fa1
--- /dev/null
+++ b/phpBB/config/installer/routing/environment.yml
@@ -0,0 +1,2 @@
+core.default:
+ resource: installer.yml
diff --git a/phpBB/config/installer/routing/installer.yml b/phpBB/config/installer/routing/installer.yml
new file mode 100644
index 0000000000..66b8893ad9
--- /dev/null
+++ b/phpBB/config/installer/routing/installer.yml
@@ -0,0 +1,67 @@
+phpbb_installer_index:
+ path: /
+ defaults:
+ _controller: phpbb.installer.controller.welcome:handle
+ mode: 'intro'
+
+phpbb_installer_license:
+ path: /license
+ defaults:
+ _controller: phpbb.installer.controller.welcome:handle
+ mode: 'license'
+
+phpbb_installer_support:
+ path: /support
+ defaults:
+ _controller: phpbb.installer.controller.welcome:handle
+ mode: 'support'
+
+phpbb_installer_install:
+ path: /install
+ defaults:
+ _controller: phpbb.installer.controller.install:handle
+
+phpbb_installer_update:
+ path: /update
+ defaults:
+ _controller: phpbb.installer.controller.update:handle
+
+phpbb_installer_update_file_download:
+ path: /download/updated
+ defaults:
+ _controller: phpbb.installer.controller.file_downloader:update_archive
+
+phpbb_installer_update_conflict_download:
+ path: /download/conflict
+ defaults:
+ _controller: phpbb.installer.controller.file_downloader:conflict_archive
+
+phpbb_convert_intro:
+ path: /convert/{start_new}
+ defaults:
+ _controller: phpbb.installer.controller.convert:intro
+ start_new: 0
+
+phpbb_convert_settings:
+ path: /convert/settings/{converter}
+ defaults:
+ _controller: phpbb.installer.controller.convert:settings
+ requirements:
+ converter: "[a-zA-Z0-9_]+"
+
+phpbb_convert_convert:
+ path: /convert/in_progress/{converter}
+ defaults:
+ _controller: phpbb.installer.controller.convert:convert
+ requirements:
+ converter: "[a-zA-Z0-9_]+"
+
+phpbb_convert_finish:
+ path: /convert/finished
+ defaults:
+ _controller: phpbb.installer.controller.convert:finish
+
+phpbb_installer_status:
+ path: /installer/status
+ defaults:
+ _controller: phpbb.installer.controller.status:status
diff --git a/phpBB/config/mimetype_guesser.yml b/phpBB/config/mimetype_guesser.yml
deleted file mode 100644
index 2e89ed3c1f..0000000000
--- a/phpBB/config/mimetype_guesser.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-services:
- mimetype.guesser_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: mimetype.guessers }
-
- mimetype.fileinfo_mimetype_guesser:
- class: Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser
- tags:
- - { name: mimetype.guessers }
-
- mimetype.filebinary_mimetype_guesser:
- class: Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser
- tags:
- - { name: mimetype.guessers }
-
- mimetype.content_guesser:
- class: phpbb\mimetype\content_guesser
- calls:
- - [set_priority, [%mimetype.guesser.priority.low%]]
- tags:
- - { name: mimetype.guessers }
-
- mimetype.extension_guesser:
- class: phpbb\mimetype\extension_guesser
- calls:
- - [set_priority, [%mimetype.guesser.priority.lowest%]]
- tags:
- - { name: mimetype.guessers }
-
- mimetype.guesser:
- class: phpbb\mimetype\guesser
- arguments:
- - @mimetype.guesser_collection
diff --git a/phpBB/config/notification.yml b/phpBB/config/notification.yml
deleted file mode 100644
index b17a172fb5..0000000000
--- a/phpBB/config/notification.yml
+++ /dev/null
@@ -1,390 +0,0 @@
-services:
- notification_manager:
- class: phpbb\notification\manager
- arguments:
- - @notification.type_collection
- - @notification.method_collection
- - @service_container
- - @user_loader
- - @config
- - @dispatcher
- - @dbal.conn
- - @cache
- - @user
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
-
-# ----- Notification's types -----
-# Scope MUST be prototype for all the plugins to work.
- notification.type_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: notification.type }
-
- notification.type.approve_post:
- class: phpbb\notification\type\approve_post
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.approve_topic:
- class: phpbb\notification\type\approve_topic
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.bookmark:
- class: phpbb\notification\type\bookmark
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.disapprove_post:
- class: phpbb\notification\type\disapprove_post
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.disapprove_topic:
- class: phpbb\notification\type\disapprove_topic
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.group_request:
- class: phpbb\notification\type\group_request
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.group_request_approved:
- class: phpbb\notification\type\group_request_approved
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.pm:
- class: phpbb\notification\type\pm
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.post:
- class: phpbb\notification\type\post
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.post_in_queue:
- class: phpbb\notification\type\post_in_queue
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.quote:
- class: phpbb\notification\type\quote
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.report_pm:
- class: phpbb\notification\type\report_pm
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.report_pm_closed:
- class: phpbb\notification\type\report_pm_closed
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.report_post:
- class: phpbb\notification\type\report_post
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.report_post_closed:
- class: phpbb\notification\type\report_post_closed
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.topic:
- class: phpbb\notification\type\topic
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.topic_in_queue:
- class: phpbb\notification\type\topic_in_queue
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
- notification.type.admin_activate_user:
- class: phpbb\notification\type\admin_activate_user
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- - %tables.notification_types%
- - %tables.notifications%
- - %tables.user_notifications%
- tags:
- - { name: notification.type }
-
-# ----- Notification's methods -----
-# Scope MUST be prototype for all the plugins to work.
- notification.method_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: notification.method }
-
- notification.method.email:
- class: phpbb\notification\method\email
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: notification.method }
-
- notification.method.jabber:
- class: phpbb\notification\method\jabber
- scope: prototype
- arguments:
- - @user_loader
- - @dbal.conn
- - @cache.driver
- - @user
- - @auth
- - @config
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: notification.method }
diff --git a/phpBB/config/password.yml b/phpBB/config/password.yml
deleted file mode 100644
index cb45ec3d42..0000000000
--- a/phpBB/config/password.yml
+++ /dev/null
@@ -1,124 +0,0 @@
-services:
-# ----- Password management -----
- passwords.manager:
- class: phpbb\passwords\manager
- arguments:
- - @config
- - @passwords.driver_collection
- - @passwords.helper
- - %passwords.algorithms%
-
- passwords.helper:
- class: phpbb\passwords\helper
-
- passwords.driver_helper:
- class: phpbb\passwords\driver\helper
- arguments:
- - @config
-
-# ----- Password's drivers -----
- passwords.driver_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: passwords.driver }
-
- passwords.driver.bcrypt:
- class: phpbb\passwords\driver\bcrypt
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.bcrypt_2y:
- class: phpbb\passwords\driver\bcrypt_2y
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.bcrypt_wcf2:
- class: phpbb\passwords\driver\bcrypt_wcf2
- arguments:
- - @passwords.driver.bcrypt
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.salted_md5:
- class: phpbb\passwords\driver\salted_md5
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.phpass:
- class: phpbb\passwords\driver\phpass
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.convert_password:
- class: phpbb\passwords\driver\convert_password
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.sha1_smf:
- class: phpbb\passwords\driver\sha1_smf
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.sha1_wcf1:
- class: phpbb\passwords\driver\sha1_wcf1
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.sha1:
- class: phpbb\passwords\driver\sha1
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.md5_phpbb2:
- class: phpbb\passwords\driver\md5_phpbb2
- arguments:
- - @request
- - @passwords.driver.salted_md5
- - @passwords.driver_helper
- - %core.root_path%
- - %core.php_ext%
- tags:
- - { name: passwords.driver }
-
- passwords.driver.md5_mybb:
- class: phpbb\passwords\driver\md5_mybb
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
-
- passwords.driver.md5_vb:
- class: phpbb\passwords\driver\md5_vb
- arguments:
- - @config
- - @passwords.driver_helper
- tags:
- - { name: passwords.driver }
diff --git a/phpBB/config/production/config.yml b/phpBB/config/production/config.yml
new file mode 100644
index 0000000000..979dbbcdd9
--- /dev/null
+++ b/phpBB/config/production/config.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../default/config.yml }
diff --git a/phpBB/config/production/container/environment.yml b/phpBB/config/production/container/environment.yml
new file mode 100644
index 0000000000..40a3c7a683
--- /dev/null
+++ b/phpBB/config/production/container/environment.yml
@@ -0,0 +1,3 @@
+imports:
+ - { resource: services.yml }
+ - { resource: parameters.yml }
diff --git a/phpBB/config/production/container/parameters.yml b/phpBB/config/production/container/parameters.yml
new file mode 100644
index 0000000000..0447646806
--- /dev/null
+++ b/phpBB/config/production/container/parameters.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../../default/container/parameters.yml }
diff --git a/phpBB/config/production/container/services.yml b/phpBB/config/production/container/services.yml
new file mode 100644
index 0000000000..b302f0f966
--- /dev/null
+++ b/phpBB/config/production/container/services.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../../default/container/services.yml }
diff --git a/phpBB/config/production/routing/environment.yml b/phpBB/config/production/routing/environment.yml
new file mode 100644
index 0000000000..301183bbae
--- /dev/null
+++ b/phpBB/config/production/routing/environment.yml
@@ -0,0 +1,2 @@
+core.default:
+ resource: ../../default/routing/routing.yml
diff --git a/phpBB/config/profilefield.yml b/phpBB/config/profilefield.yml
deleted file mode 100644
index 5ccfef9148..0000000000
--- a/phpBB/config/profilefield.yml
+++ /dev/null
@@ -1,102 +0,0 @@
-services:
- profilefields.manager:
- class: phpbb\profilefields\manager
- arguments:
- - @auth
- - @dbal.conn
- - @dispatcher
- - @request
- - @template
- - @profilefields.type_collection
- - @user
- - %tables.profile_fields%
- - %tables.profile_fields_language%
- - %tables.profile_fields_data%
-
- profilefields.lang_helper:
- class: phpbb\profilefields\lang_helper
- arguments:
- - @dbal.conn
- - %tables.profile_fields_options_language%
-
-# ----- Profile fields types -----
- profilefields.type_collection:
- class: phpbb\di\service_collection
- arguments:
- - @service_container
- tags:
- - { name: service_collection, tag: profilefield.type }
-
- profilefields.type.bool:
- class: phpbb\profilefields\type\type_bool
- arguments:
- - @profilefields.lang_helper
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.date:
- class: phpbb\profilefields\type\type_date
- arguments:
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.dropdown:
- class: phpbb\profilefields\type\type_dropdown
- arguments:
- - @profilefields.lang_helper
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.googleplus:
- class: phpbb\profilefields\type\type_googleplus
- arguments:
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.int:
- class: phpbb\profilefields\type\type_int
- arguments:
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.string:
- class: phpbb\profilefields\type\type_string
- arguments:
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.text:
- class: phpbb\profilefields\type\type_text
- arguments:
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
-
- profilefields.type.url:
- class: phpbb\profilefields\type\type_url
- arguments:
- - @request
- - @template
- - @user
- tags:
- - { name: profilefield.type }
diff --git a/phpBB/config/routing.yml b/phpBB/config/routing.yml
deleted file mode 100644
index 94146e1ec2..0000000000
--- a/phpBB/config/routing.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-# Structure:
-#
-# foo_controller:
-# path: /foo
-# defaults: { _controller: foo_sevice:method }
-#
-# The above will be accessed via app.php?controller=foo and it will
-# instantiate the "foo_service" service and call the "method" method.
-#
diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml
deleted file mode 100644
index 8667cbbf84..0000000000
--- a/phpBB/config/services.yml
+++ /dev/null
@@ -1,188 +0,0 @@
-imports:
- - { resource: auth.yml }
- - { resource: avatar.yml }
- - { resource: captcha.yml }
- - { resource: console.yml }
- - { resource: content.yml }
- - { resource: cron.yml }
- - { resource: db.yml }
- - { resource: event.yml }
- - { resource: feed.yml }
- - { resource: mimetype_guesser.yml }
- - { resource: notification.yml }
- - { resource: password.yml }
- - { resource: profilefield.yml }
- - { resource: user.yml }
-
- - { resource: tables.yml }
- - { resource: parameters.yml }
-
-services:
- cache:
- class: phpbb\cache\service
- arguments:
- - @cache.driver
- - @config
- - @dbal.conn
- - %core.root_path%
- - %core.php_ext%
-
- cache.driver:
- class: %cache.driver.class%
-
- class_loader:
- class: phpbb\class_loader
- arguments:
- - phpbb\
- - %core.root_path%includes/
- - %core.php_ext%
- calls:
- - [register, []]
- - [set_cache, [@cache.driver]]
-
- class_loader.ext:
- class: phpbb\class_loader
- arguments:
- - \
- - %core.root_path%ext/
- - %core.php_ext%
- calls:
- - [register, []]
- - [set_cache, [@cache.driver]]
-
- config:
- class: phpbb\config\db
- arguments:
- - @dbal.conn
- - @cache.driver
- - %tables.config%
-
- config.php:
- synthetic: true
-
- config_text:
- class: phpbb\config\db_text
- arguments:
- - @dbal.conn
- - %tables.config_text%
-
- controller.helper:
- class: phpbb\controller\helper
- arguments:
- - @template
- - @user
- - @config
- - @controller.provider
- - @ext.manager
- - @symfony_request
- - @request
- - @filesystem
- - %core.root_path%
- - %core.php_ext%
-
- controller.resolver:
- class: phpbb\controller\resolver
- arguments:
- - @user
- - @service_container
- - %core.root_path%
- - @template
-
- controller.provider:
- class: phpbb\controller\provider
- calls:
- - [find, [%core.root_path%]]
-
- ext.manager:
- class: phpbb\extension\manager
- arguments:
- - @service_container
- - @dbal.conn
- - @config
- - @filesystem
- - @user
- - %tables.ext%
- - %core.root_path%
- - %core.php_ext%
- - @cache.driver
-
- filesystem:
- class: phpbb\filesystem
-
- file_downloader:
- class: phpbb\file_downloader
-
- http_kernel:
- class: Symfony\Component\HttpKernel\HttpKernel
- arguments:
- - @dispatcher
- - @controller.resolver
-
- log:
- class: phpbb\log\log
- arguments:
- - @dbal.conn
- - @user
- - @auth
- - @dispatcher
- - %core.root_path%
- - %core.adm_relative_path%
- - %core.php_ext%
- - %tables.log%
-
- path_helper:
- class: phpbb\path_helper
- arguments:
- - @symfony_request
- - @filesystem
- - @request
- - %core.root_path%
- - %core.php_ext%
- - %core.adm_relative_path%
-
- php_ini:
- class: phpbb\php\ini
-
- plupload:
- class: phpbb\plupload\plupload
- arguments:
- - %core.root_path%
- - @config
- - @request
- - @user
- - @php_ini
- - @mimetype.guesser
-
- request:
- class: phpbb\request\request
- arguments:
- - null
- - %core.disable_super_globals%
-
- # WARNING: The Symfony request does not escape the input and should be used very carefully
- # prefer the phpbb request (service @request) as possible
- symfony_request:
- class: phpbb\symfony_request
- arguments:
- - @request
-
- template:
- class: phpbb\template\twig\twig
- arguments:
- - @path_helper
- - @config
- - @user
- - @template_context
- - @ext.manager
-
- template_context:
- class: phpbb\template\context
-
- version_helper:
- class: phpbb\version_helper
- scope: prototype
- arguments:
- - @cache
- - @config
- - @file_downloader
- - @user
diff --git a/phpBB/config/tables.yml b/phpBB/config/tables.yml
deleted file mode 100644
index 2fe2a33be8..0000000000
--- a/phpBB/config/tables.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-parameters:
- tables.auth_provider_oauth_token_storage: %core.table_prefix%oauth_tokens
- tables.auth_provider_oauth_account_assoc: %core.table_prefix%oauth_accounts
- tables.captcha_qa_questions: %core.table_prefix%captcha_questions
- tables.captcha_qa_answers: %core.table_prefix%captcha_answers
- tables.captcha_qa_confirm: %core.table_prefix%qa_confirm
- tables.config: %core.table_prefix%config
- tables.config_text: %core.table_prefix%config_text
- tables.ext: %core.table_prefix%ext
- tables.forums: %core.table_prefix%forums
- tables.log: %core.table_prefix%log
- tables.migrations: %core.table_prefix%migrations
- tables.modules: %core.table_prefix%modules
- tables.notification_types: %core.table_prefix%notification_types
- tables.notifications: %core.table_prefix%notifications
- tables.profile_fields: %core.table_prefix%profile_fields
- tables.profile_fields_data: %core.table_prefix%profile_fields_data
- tables.profile_fields_options_language: %core.table_prefix%profile_fields_lang
- tables.profile_fields_language: %core.table_prefix%profile_lang
- tables.posts: %core.table_prefix%posts
- tables.topics: %core.table_prefix%topics
- tables.user_notifications: %core.table_prefix%user_notifications
- tables.users: %core.table_prefix%users
diff --git a/phpBB/config/test/config.yml b/phpBB/config/test/config.yml
new file mode 100644
index 0000000000..1c17b08931
--- /dev/null
+++ b/phpBB/config/test/config.yml
@@ -0,0 +1,5 @@
+imports:
+ - { resource: ../default/config.yml }
+
+core:
+ require_dev_dependencies: true
diff --git a/phpBB/config/test/container/environment.yml b/phpBB/config/test/container/environment.yml
new file mode 100644
index 0000000000..40a3c7a683
--- /dev/null
+++ b/phpBB/config/test/container/environment.yml
@@ -0,0 +1,3 @@
+imports:
+ - { resource: services.yml }
+ - { resource: parameters.yml }
diff --git a/phpBB/config/test/container/parameters.yml b/phpBB/config/test/container/parameters.yml
new file mode 100644
index 0000000000..0447646806
--- /dev/null
+++ b/phpBB/config/test/container/parameters.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../../default/container/parameters.yml }
diff --git a/phpBB/config/test/container/services.yml b/phpBB/config/test/container/services.yml
new file mode 100644
index 0000000000..b302f0f966
--- /dev/null
+++ b/phpBB/config/test/container/services.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../../default/container/services.yml }
diff --git a/phpBB/config/test/routing/environment.yml b/phpBB/config/test/routing/environment.yml
new file mode 100644
index 0000000000..301183bbae
--- /dev/null
+++ b/phpBB/config/test/routing/environment.yml
@@ -0,0 +1,2 @@
+core.default:
+ resource: ../../default/routing/routing.yml
diff --git a/phpBB/config/user.yml b/phpBB/config/user.yml
deleted file mode 100644
index 1ca853ea45..0000000000
--- a/phpBB/config/user.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-services:
- acl.permissions:
- class: phpbb\permissions
- arguments:
- - @dispatcher
- - @user
-
- user:
- class: phpbb\user
- arguments:
- - %datetime.class%
-
- user_loader:
- class: phpbb\user_loader
- arguments:
- - @dbal.conn
- - %core.root_path%
- - %core.php_ext%
- - %tables.users%
diff --git a/phpBB/cron.php b/phpBB/cron.php
index aed68f6aeb..2f519947aa 100644
--- a/phpBB/cron.php
+++ b/phpBB/cron.php
@@ -42,14 +42,16 @@ function output_image()
//
// Attempt to alleviate the problem by doing setup outside of the lock as much as possible.
-$cron_type = request_var('cron_type', '');
+$cron_type = $request->variable('cron_type', '');
// Comment this line out for debugging so the page does not return an image.
output_image();
+/* @var $cron_lock \phpbb\lock\db */
$cron_lock = $phpbb_container->get('cron.lock_db');
if ($cron_lock->acquire())
{
+ /* @var $cron \phpbb\cron\manager */
$cron = $phpbb_container->get('cron.manager');
$task = $cron->find_task($cron_type);
diff --git a/phpBB/develop/add_permissions.php b/phpBB/develop/add_permissions.php
index a5279f8f13..c575729d91 100644
--- a/phpBB/develop/add_permissions.php
+++ b/phpBB/develop/add_permissions.php
@@ -64,6 +64,7 @@ $f_permissions = array(
'f_vote' => array(1, 0),
'f_votechg' => array(1, 0),
'f_announce'=> array(1, 0),
+ 'f_announce_global' => array(1, 0),
'f_sticky' => array(1, 0),
'f_attach' => array(1, 0),
'f_download'=> array(1, 0),
@@ -378,8 +379,6 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting)
$sql = 'VALUES ' . implode(', ', preg_replace('#^(.*?)$#', '(\1)', $sql_subary));
break;
- case 'mssql':
- case 'sqlite':
case 'sqlite3':
$sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary));
break;
@@ -388,7 +387,7 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting)
foreach ($sql_subary as $sql)
{
$sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) VALUES ($sql)";
- $result = $db->sql_query($sql);
+ $db->sql_query($sql);
$sql = '';
}
}
@@ -396,7 +395,7 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting)
if ($sql != '')
{
$sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) $sql";
- $result = $db->sql_query($sql);
+ $db->sql_query($sql);
}
break;
@@ -404,7 +403,7 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting)
case 'delete':
foreach ($sql_subary as $sql)
{
- $result = $db->sql_query($sql);
+ $db->sql_query($sql);
$sql = '';
}
break;
diff --git a/phpBB/develop/benchmark.php b/phpBB/develop/benchmark.php
index c3cf90773e..631b7d05ca 100644
--- a/phpBB/develop/benchmark.php
+++ b/phpBB/develop/benchmark.php
@@ -143,7 +143,7 @@ function filldb($newposts)
if ((rand(0,30) < 1) || ($forum_topic_count[$forum] == 0))
{
// create a new topic 1 in 30 times (or when there are none);
- $topic = make_topic($userid, "Testing topic $i", $forum);
+ make_topic($userid, "Testing topic $i", $forum);
$forum_topic_count[$forum]++;
}
else
diff --git a/phpBB/develop/check_flash_bbcodes.php b/phpBB/develop/check_flash_bbcodes.php
index 6e1b415bb6..5dc112bfc0 100644
--- a/phpBB/develop/check_flash_bbcodes.php
+++ b/phpBB/develop/check_flash_bbcodes.php
@@ -140,8 +140,12 @@ function html_entity_decode_utf8($string)
static $trans_tbl;
// replace numeric entities
- $string = preg_replace('~&#x([0-9a-f]+);~ei', 'code2utf8(hexdec("\\1"))', $string);
- $string = preg_replace('~&#([0-9]+);~e', 'code2utf8(\\1)', $string);
+ $string = preg_replace_callback('~&#x([0-9a-f]+);~i', function ($match) {
+ return code2utf8(hexdec($match[1]));
+ }, $string);
+ $string = preg_replace_callback('~&#([0-9]+);~', function ($match) {
+ return code2utf8($match[1]);
+ }, $string);
// replace literal entities
if (!isset($trans_tbl))
diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php
index 60ffe04330..6e0a082045 100644
--- a/phpBB/develop/create_schema_files.php
+++ b/phpBB/develop/create_schema_files.php
@@ -38,18 +38,22 @@ define('IN_PHPBB', true);
$phpbb_root_path = dirname(__FILE__) . '/../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
+include($phpbb_root_path . 'vendor/autoload.php');
include($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
$phpbb_class_loader->register();
-$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path);
+$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path);
$classes = $finder->core_path('phpbb/')
->directory('/db/migration/data')
->get_classes();
-$db = new \phpbb\db\driver\sqlite();
-$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix);
+$db = new \phpbb\db\driver\sqlite3();
+$factory = new \phpbb\db\tools\factory();
+$db_tools = $factory->get($db, true);
+
+$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);
$schema_data = $schema_generator->get_schema();
$fp = fopen($schema_path . 'schema.json', 'wb');
diff --git a/phpBB/develop/create_search_index.php b/phpBB/develop/create_search_index.php
index 9b79a35a84..6ef200699c 100644
--- a/phpBB/develop/create_search_index.php
+++ b/phpBB/develop/create_search_index.php
@@ -132,7 +132,7 @@ else
$search->tidy();
-add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $search_name);
+$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($search_name));
echo $user->lang['SEARCH_INDEX_CREATED'] . "\n";
echo 'Peak Memory Usage: ' . get_formatted_filesize(memory_get_peak_usage()) . "\n";
diff --git a/phpBB/develop/fill.php b/phpBB/develop/fill.php
index 6d08e9c206..2aaafe1e38 100644
--- a/phpBB/develop/fill.php
+++ b/phpBB/develop/fill.php
@@ -42,8 +42,8 @@ $posts_per_topic = 500;
// general vars
-$mode = request_var('mode', 'generate');
-$start = request_var('start', 0);
+$mode = $request->variable('mode', 'generate');
+$start = $request->variable('start', 0);
switch ($mode)
{
diff --git a/phpBB/develop/generate_utf_tables.php b/phpBB/develop/generate_utf_tables.php
index 16a449679b..888c07676d 100644
--- a/phpBB/develop/generate_utf_tables.php
+++ b/phpBB/develop/generate_utf_tables.php
@@ -32,262 +32,11 @@ $phpbb_root_path = '../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
echo "Checking for required files\n";
-download('http://www.unicode.org/Public/UNIDATA/CompositionExclusions.txt');
-download('http://www.unicode.org/Public/UNIDATA/DerivedNormalizationProps.txt');
download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt');
echo "\n";
-require_once($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
-$file_contents = array();
-
-/**
-* Generate some Hangul/Jamo stuff
-*/
-echo "\nGenerating Hangul and Jamo tables\n";
-for ($i = 0; $i < UNICODE_HANGUL_LCOUNT; ++$i)
-{
- $utf_char = cp_to_utf(UNICODE_HANGUL_LBASE + $i);
- $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i * UNICODE_HANGUL_VCOUNT * UNICODE_HANGUL_TCOUNT + UNICODE_HANGUL_SBASE;
- $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_L;
-}
-
-for ($i = 0; $i < UNICODE_HANGUL_VCOUNT; ++$i)
-{
- $utf_char = cp_to_utf(UNICODE_HANGUL_VBASE + $i);
- $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i * UNICODE_HANGUL_TCOUNT;
- $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_V;
-}
-
-for ($i = 0; $i < UNICODE_HANGUL_TCOUNT; ++$i)
-{
- $utf_char = cp_to_utf(UNICODE_HANGUL_TBASE + $i);
- $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i;
- $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_T;
-}
-
-/**
-* Load the CompositionExclusions table
-*/
-echo "Loading CompositionExclusion\n";
-$fp = fopen('CompositionExclusions.txt', 'rt');
-
-$exclude = array();
-while (!feof($fp))
-{
- $line = fgets($fp, 1024);
-
- if (!strpos(' 0123456789ABCDEFabcdef', $line[0]))
- {
- continue;
- }
-
- $cp = strtok($line, ' ');
-
- if ($pos = strpos($cp, '..'))
- {
- $start = hexdec(substr($cp, 0, $pos));
- $end = hexdec(substr($cp, $pos + 2));
-
- for ($i = $start; $i < $end; ++$i)
- {
- $exclude[$i] = 1;
- }
- }
- else
- {
- $exclude[hexdec($cp)] = 1;
- }
-}
-fclose($fp);
-
-/**
-* Load QuickCheck tables
-*/
-echo "Generating QuickCheck tables\n";
-$fp = fopen('DerivedNormalizationProps.txt', 'rt');
-
-while (!feof($fp))
-{
- $line = fgets($fp, 1024);
-
- if (!strpos(' 0123456789ABCDEFabcdef', $line[0]))
- {
- continue;
- }
-
- $p = array_map('trim', explode(';', strtok($line, '#')));
-
- /**
- * Capture only NFC_QC, NFKC_QC
- */
- if (!preg_match('#^NFK?C_QC$#', $p[1]))
- {
- continue;
- }
-
- if ($pos = strpos($p[0], '..'))
- {
- $start = hexdec(substr($p[0], 0, $pos));
- $end = hexdec(substr($p[0], $pos + 2));
- }
- else
- {
- $start = $end = hexdec($p[0]);
- }
-
- if ($start >= UTF8_HANGUL_FIRST && $end <= UTF8_HANGUL_LAST)
- {
- /**
- * We do not store Hangul syllables in the array
- */
- continue;
- }
-
- if ($p[2] == 'M')
- {
- $val = UNICODE_QC_MAYBE;
- }
- else
- {
- $val = UNICODE_QC_NO;
- }
-
- if ($p[1] == 'NFKC_QC')
- {
- $file = 'utf_nfkc_qc';
- }
- else
- {
- $file = 'utf_nfc_qc';
- }
-
- for ($i = $start; $i <= $end; ++$i)
- {
- /**
- * The vars have the same name as the file: $utf_nfc_qc is in utf_nfc_qc.php
- */
- $file_contents[$file][$file][cp_to_utf($i)] = $val;
- }
-}
-fclose($fp);
-
/**
-* Do mappings
-*/
-echo "Loading Unicode decomposition mappings\n";
-$fp = fopen($phpbb_root_path . 'develop/UnicodeData.txt', 'rt');
-
-$map = array();
-while (!feof($fp))
-{
- $p = explode(';', fgets($fp, 1024));
- $cp = hexdec($p[0]);
-
- if (!empty($p[3]))
- {
- /**
- * Store combining class > 0
- */
- $file_contents['utf_normalizer_common']['utf_combining_class'][cp_to_utf($cp)] = (int) $p[3];
- }
-
- if (!isset($p[5]) || !preg_match_all('#[0-9A-F]+#', strip_tags($p[5]), $m))
- {
- continue;
- }
-
- if (strpos($p[5], '>'))
- {
- $map['NFKD'][$cp] = implode(' ', array_map('hexdec', $m[0]));
- }
- else
- {
- $map['NFD'][$cp] = $map['NFKD'][$cp] = implode(' ', array_map('hexdec', $m[0]));
- }
-}
-fclose($fp);
-
-/**
-* Build the canonical composition table
-*/
-echo "Generating the Canonical Composition table\n";
-foreach ($map['NFD'] as $cp => $decomp_seq)
-{
- if (!strpos($decomp_seq, ' ') || isset($exclude[$cp]))
- {
- /**
- * Singletons are excluded from canonical composition
- */
- continue;
- }
-
- $utf_seq = implode('', array_map('cp_to_utf', explode(' ', $decomp_seq)));
-
- if (!isset($file_contents['utf_canonical_comp']['utf_canonical_comp'][$utf_seq]))
- {
- $file_contents['utf_canonical_comp']['utf_canonical_comp'][$utf_seq] = cp_to_utf($cp);
- }
-}
-
-/**
-* Decompose the NF[K]D mappings recursively and prepare the file contents
-*/
-echo "Generating the Canonical and Compatibility Decomposition tables\n\n";
-foreach ($map as $type => $decomp_map)
-{
- foreach ($decomp_map as $cp => $decomp_seq)
- {
- $decomp_map[$cp] = decompose($decomp_map, $decomp_seq);
- }
- unset($decomp_seq);
-
- if ($type == 'NFKD')
- {
- $file = 'utf_compatibility_decomp';
- $var = 'utf_compatibility_decomp';
- }
- else
- {
- $file = 'utf_canonical_decomp';
- $var = 'utf_canonical_decomp';
- }
-
- /**
- * Generate the corresponding file
- */
- foreach ($decomp_map as $cp => $decomp_seq)
- {
- $file_contents[$file][$var][cp_to_utf($cp)] = implode('', array_map('cp_to_utf', explode(' ', $decomp_seq)));
- }
-}
-
-/**
-* Generate and/or alter the files
-*/
-foreach ($file_contents as $file => $contents)
-{
- /**
- * Generate a new file
- */
- echo "Writing to $file.$phpEx\n";
-
- if (!$fp = fopen($phpbb_root_path . 'includes/utf/data/' . $file . '.' . $phpEx, 'wb'))
- {
- trigger_error('Cannot open ' . $file . ' for write');
- }
-
- fwrite($fp, '<?php');
- foreach ($contents as $var => $val)
- {
- fwrite($fp, "\n\$GLOBALS[" . my_var_export($var) . ']=' . my_var_export($val) . ";");
- }
- fclose($fp);
-}
-
-echo "\n*** UTF-8 normalization tables done\n\n";
-
-/**
-* Now we'll generate the files needed by the search indexer
+* Generate the files needed by the search indexer
*/
echo "Generating search indexer tables\n";
@@ -425,32 +174,6 @@ die("\nAll done!\n");
////////////////////////////////////////////////////////////////////////////////
/**
-* Decompose a sequence recusively
-*
-* @param array $decomp_map Decomposition mapping, passed by reference
-* @param string $decomp_seq Decomposition sequence as decimal codepoints separated with a space
-* @return string Decomposition sequence, fully decomposed
-*/
-function decompose(&$decomp_map, $decomp_seq)
-{
- $ret = array();
- foreach (explode(' ', $decomp_seq) as $cp)
- {
- if (isset($decomp_map[$cp]))
- {
- $ret[] = decompose($decomp_map, $decomp_map[$cp]);
- }
- else
- {
- $ret[] = $cp;
- }
- }
-
- return implode(' ', $ret);
-}
-
-
-/**
* Return a parsable string representation of a variable
*
* This is function is limited to array/strings/integers
@@ -538,17 +261,6 @@ function hex_to_utf($hex)
}
/**
-* Return a UTF string formed from a sequence of codepoints in hexadecimal
-*
-* @param string $seq Sequence of codepoints, separated with a space
-* @return string UTF-8 string
-*/
-function hexseq_to_utf($seq)
-{
- return implode('', array_map('hex_to_utf', explode(' ', $seq)));
-}
-
-/**
* Convert a codepoint to a UTF-8 char
*
* @param integer $cp Unicode codepoint
diff --git a/phpBB/develop/imageset_to_css.php b/phpBB/develop/imageset_to_css.php
index d49fe9c741..bbe7c31c83 100644
--- a/phpBB/develop/imageset_to_css.php
+++ b/phpBB/develop/imageset_to_css.php
@@ -7,7 +7,7 @@
*/
$phpbb_root_path = '../';
-$style = 'subsilver2';
+$style = 'prosilver';
$imageset_path = $phpbb_root_path . 'styles/' . $style . '/imageset';
$theme_path = $phpbb_root_path . 'styles/' . $style . '/theme';
diff --git a/phpBB/develop/lang_duplicates.php b/phpBB/develop/lang_duplicates.php
index 5981882292..7a74b1088a 100644
--- a/phpBB/develop/lang_duplicates.php
+++ b/phpBB/develop/lang_duplicates.php
@@ -29,7 +29,7 @@ $phpEx = substr(strrchr(__FILE__, '.'), 1);
$phpbb_root_path='./../';
include($phpbb_root_path . 'common.'.$phpEx);
-$mode = request_var('mode', '');
+$mode = $request->variable('mode', '');
$modules = find_modules($phpbb_root_path . 'language/en');
diff --git a/phpBB/develop/lang_migrate_help_lang.php b/phpBB/develop/lang_migrate_help_lang.php
new file mode 100644
index 0000000000..81b71398e1
--- /dev/null
+++ b/phpBB/develop/lang_migrate_help_lang.php
@@ -0,0 +1,307 @@
+<?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.
+ *
+ */
+
+define('LANGUAGE_TO_MIGRATE', 'en');
+
+# NO CHANGES BELOW THIS LINE
+
+define('IN_PHPBB', true);
+$phpEx = substr(strrchr(__FILE__, '.'), 1);
+$phpbb_root_path = './../';
+include($phpbb_root_path . 'common.'.$phpEx);
+
+$help_bbcode = load_help('bbcode');
+$lang_bbcode = array(
+ 'HELP_BBCODE_BLOCK_INTRO' => $help_bbcode[0][1],
+ 'HELP_BBCODE_INTRO_BBCODE_QUESTION' => $help_bbcode[1][0],
+ 'HELP_BBCODE_INTRO_BBCODE_ANSWER' => $help_bbcode[1][1],
+
+ 'HELP_BBCODE_BLOCK_TEXT' => $help_bbcode[2][1],
+ 'HELP_BBCODE_TEXT_BASIC_QUESTION' => $help_bbcode[3][0],
+ 'HELP_BBCODE_TEXT_BASIC_ANSWER' => $help_bbcode[3][1],
+ 'HELP_BBCODE_TEXT_COLOR_QUESTION' => $help_bbcode[4][0],
+ 'HELP_BBCODE_TEXT_COLOR_ANSWER' => $help_bbcode[4][1],
+ 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => $help_bbcode[5][0],
+ 'HELP_BBCODE_TEXT_COMBINE_ANSWER' => $help_bbcode[5][1],
+
+ 'HELP_BBCODE_BLOCK_QUOTES' => $help_bbcode[6][1],
+ 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => $help_bbcode[7][0],
+ 'HELP_BBCODE_QUOTES_TEXT_ANSWER' => $help_bbcode[7][1],
+ 'HELP_BBCODE_QUOTES_CODE_QUESTION' => $help_bbcode[8][0],
+ 'HELP_BBCODE_QUOTES_CODE_ANSWER' => $help_bbcode[8][1],
+
+ 'HELP_BBCODE_BLOCK_LISTS' => $help_bbcode[9][1],
+ 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => $help_bbcode[10][0],
+ 'HELP_BBCODE_LISTS_UNORDERER_ANSWER' => $help_bbcode[10][1],
+ 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => $help_bbcode[11][0],
+ 'HELP_BBCODE_LISTS_ORDERER_ANSWER' => $help_bbcode[11][1],
+
+ 'HELP_BBCODE_BLOCK_LINKS' => $help_bbcode[13][1],
+ 'HELP_BBCODE_LINKS_BASIC_QUESTION' => $help_bbcode[14][0],
+ 'HELP_BBCODE_LINKS_BASIC_ANSWER' => $help_bbcode[14][1],
+
+ 'HELP_BBCODE_BLOCK_IMAGES' => $help_bbcode[15][1],
+ 'HELP_BBCODE_IMAGES_BASIC_QUESTION' => $help_bbcode[16][0],
+ 'HELP_BBCODE_IMAGES_BASIC_ANSWER' => $help_bbcode[16][1],
+ 'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => $help_bbcode[17][0],
+ 'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER' => $help_bbcode[17][1],
+
+ 'HELP_BBCODE_BLOCK_OTHERS' => $help_bbcode[18][1],
+ 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => $help_bbcode[19][0],
+ 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER' => $help_bbcode[19][1],
+);
+write_help('bbcode', $lang_bbcode);
+
+$help_phpbb = load_help('faq');
+$lang_phpbb = array(
+ 'HELP_FAQ_BLOCK_LOGIN' => $help_phpbb[0][1],
+ 'HELP_FAQ_LOGIN_REGISTER_QUESTION' => $help_phpbb[1][0],
+ 'HELP_FAQ_LOGIN_REGISTER_ANSWER' => $help_phpbb[1][1],
+ 'HELP_FAQ_LOGIN_COPPA_QUESTION' => $help_phpbb[2][0],
+ 'HELP_FAQ_LOGIN_COPPA_ANSWER' => $help_phpbb[2][1],
+ 'HELP_FAQ_LOGIN_CANNOT_REGISTER_QUESTION' => $help_phpbb[3][0],
+ 'HELP_FAQ_LOGIN_CANNOT_REGISTER_ANSWER' => $help_phpbb[3][1],
+ 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_QUESTION' => $help_phpbb[4][0],
+ 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_ANSWER' => $help_phpbb[4][1],
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_QUESTION' => $help_phpbb[5][0],
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANSWER' => $help_phpbb[5][1],
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_QUESTION' => $help_phpbb[6][0],
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_ANSWER' => $help_phpbb[6][1],
+ 'HELP_FAQ_LOGIN_LOST_PASSWORD_QUESTION' => $help_phpbb[7][0],
+ 'HELP_FAQ_LOGIN_LOST_PASSWORD_ANSWER' => $help_phpbb[7][1],
+ 'HELP_FAQ_LOGIN_AUTO_LOGOUT_QUESTION' => $help_phpbb[8][0],
+ 'HELP_FAQ_LOGIN_AUTO_LOGOUT_ANSWER' => $help_phpbb[8][1],
+ 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => $help_phpbb[9][0],
+ 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER' => $help_phpbb[9][1],
+
+ 'HELP_FAQ_BLOCK_USERSETTINGS' => $help_phpbb[10][1],
+ 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_QUESTION' => $help_phpbb[11][0],
+ 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_ANSWER' => $help_phpbb[11][1],
+ 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_QUESTION' => $help_phpbb[12][0],
+ 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_ANSWER' => $help_phpbb[12][1],
+ 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => $help_phpbb[13][0],
+ 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER' => $help_phpbb[13][1],
+ 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => $help_phpbb[14][0],
+ 'HELP_FAQ_USERSETTINGS_SERVERTIME_ANSWER' => $help_phpbb[14][1],
+ 'HELP_FAQ_USERSETTINGS_LANGUAGE_QUESTION' => $help_phpbb[15][0],
+ 'HELP_FAQ_USERSETTINGS_LANGUAGE_ANSWER' => $help_phpbb[15][1],
+ 'HELP_FAQ_USERSETTINGS_AVATAR_QUESTION' => $help_phpbb[16][0],
+ 'HELP_FAQ_USERSETTINGS_AVATAR_ANSWER' => $help_phpbb[16][1],
+ 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_QUESTION' => $help_phpbb[17][0],
+ 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_ANSWER' => $help_phpbb[17][1],
+ 'HELP_FAQ_USERSETTINGS_RANK_QUESTION' => $help_phpbb[18][0],
+ 'HELP_FAQ_USERSETTINGS_RANK_ANSWER' => $help_phpbb[18][1],
+ 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_QUESTION' => $help_phpbb[19][0],
+ 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_ANSWER' => $help_phpbb[19][1],
+
+ 'HELP_FAQ_BLOCK_POSTING' => $help_phpbb[20][1],
+ 'HELP_FAQ_POSTING_CREATE_QUESTION' => $help_phpbb[21][0],
+ 'HELP_FAQ_POSTING_CREATE_ANSWER' => $help_phpbb[21][1],
+ 'HELP_FAQ_POSTING_EDIT_DELETE_QUESTION' => $help_phpbb[22][0],
+ 'HELP_FAQ_POSTING_EDIT_DELETE_ANSWER' => $help_phpbb[22][1],
+ 'HELP_FAQ_POSTING_SIGNATURE_QUESTION' => $help_phpbb[23][0],
+ 'HELP_FAQ_POSTING_SIGNATURE_ANSWER' => $help_phpbb[23][1],
+ 'HELP_FAQ_POSTING_POLL_CREATE_QUESTION' => $help_phpbb[24][0],
+ 'HELP_FAQ_POSTING_POLL_CREATE_ANSWER' => $help_phpbb[24][1],
+ 'HELP_FAQ_POSTING_POLL_ADD_QUESTION' => $help_phpbb[25][0],
+ 'HELP_FAQ_POSTING_POLL_ADD_ANSWER' => $help_phpbb[25][1],
+ 'HELP_FAQ_POSTING_POLL_EDIT_QUESTION' => $help_phpbb[26][0],
+ 'HELP_FAQ_POSTING_POLL_EDIT_ANSWER' => $help_phpbb[26][1],
+ 'HELP_FAQ_POSTING_FORUM_RESTRICTED_QUESTION' => $help_phpbb[27][0],
+ 'HELP_FAQ_POSTING_FORUM_RESTRICTED_ANSWER' => $help_phpbb[27][1],
+ 'HELP_FAQ_POSTING_NO_ATTACHMENTS_QUESTION' => $help_phpbb[28][0],
+ 'HELP_FAQ_POSTING_NO_ATTACHMENTS_ANSWER' => $help_phpbb[28][1],
+ 'HELP_FAQ_POSTING_WARNING_QUESTION' => $help_phpbb[29][0],
+ 'HELP_FAQ_POSTING_WARNING_ANSWER' => $help_phpbb[29][1],
+ 'HELP_FAQ_POSTING_REPORT_QUESTION' => $help_phpbb[30][0],
+ 'HELP_FAQ_POSTING_REPORT_ANSWER' => $help_phpbb[30][1],
+ 'HELP_FAQ_POSTING_DRAFT_QUESTION' => $help_phpbb[31][0],
+ 'HELP_FAQ_POSTING_DRAFT_ANSWER' => $help_phpbb[31][1],
+ 'HELP_FAQ_POSTING_QUEUE_QUESTION' => $help_phpbb[32][0],
+ 'HELP_FAQ_POSTING_QUEUE_ANSWER' => $help_phpbb[32][1],
+ 'HELP_FAQ_POSTING_BUMP_QUESTION' => $help_phpbb[33][0],
+ 'HELP_FAQ_POSTING_BUMP_ANSWER' => $help_phpbb[33][1],
+
+ 'HELP_FAQ_BLOCK_FORMATTING' => $help_phpbb[34][1],
+ 'HELP_FAQ_FORMATTING_BBOCDE_QUESTION' => $help_phpbb[35][0],
+ 'HELP_FAQ_FORMATTING_BBOCDE_ANSWER' => $help_phpbb[35][1],
+ 'HELP_FAQ_FORMATTING_HTML_QUESTION' => $help_phpbb[36][0],
+ 'HELP_FAQ_FORMATTING_HTML_ANSWER' => $help_phpbb[36][1],
+ 'HELP_FAQ_FORMATTING_SMILIES_QUESTION' => $help_phpbb[37][0],
+ 'HELP_FAQ_FORMATTING_SMILIES_ANSWER' => $help_phpbb[37][1],
+ 'HELP_FAQ_FORMATTING_IMAGES_QUESTION' => $help_phpbb[38][0],
+ 'HELP_FAQ_FORMATTING_IMAGES_ANSWER' => $help_phpbb[38][1],
+ 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_QUESTION' => $help_phpbb[39][0],
+ 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_ANSWER' => $help_phpbb[39][1],
+ 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_QUESTION' => $help_phpbb[40][0],
+ 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_ANSWER' => $help_phpbb[40][1],
+ 'HELP_FAQ_FORMATTING_STICKIES_QUESTION' => $help_phpbb[41][0],
+ 'HELP_FAQ_FORMATTING_STICKIES_ANSWER' => $help_phpbb[41][1],
+ 'HELP_FAQ_FORMATTING_LOCKED_QUESTION' => $help_phpbb[42][0],
+ 'HELP_FAQ_FORMATTING_LOCKED_ANSWER' => $help_phpbb[42][1],
+ 'HELP_FAQ_FORMATTING_ICONS_QUESTION' => $help_phpbb[43][0],
+ 'HELP_FAQ_FORMATTING_ICONS_ANSWER' => $help_phpbb[43][1],
+
+ 'HELP_FAQ_BLOCK_GROUPS' => $help_phpbb[45][1],
+ 'HELP_FAQ_GROUPS_ADMINISTRATORS_QUESTION' => $help_phpbb[46][0],
+ 'HELP_FAQ_GROUPS_ADMINISTRATORS_ANSWER' => $help_phpbb[46][1],
+ 'HELP_FAQ_GROUPS_MODERATORS_QUESTION' => $help_phpbb[47][0],
+ 'HELP_FAQ_GROUPS_MODERATORS_ANSWER' => $help_phpbb[47][1],
+ 'HELP_FAQ_GROUPS_USERGROUPS_QUESTION' => $help_phpbb[48][0],
+ 'HELP_FAQ_GROUPS_USERGROUPS_ANSWER' => $help_phpbb[48][1],
+ 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_QUESTION' => $help_phpbb[49][0],
+ 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_ANSWER' => $help_phpbb[49][1],
+ 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_QUESTION' => $help_phpbb[50][0],
+ 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_ANSWER' => $help_phpbb[50][1],
+ 'HELP_FAQ_GROUPS_COLORS_QUESTION' => $help_phpbb[51][0],
+ 'HELP_FAQ_GROUPS_COLORS_ANSWER' => $help_phpbb[51][1],
+ 'HELP_FAQ_GROUPS_DEFAULT_QUESTION' => $help_phpbb[52][0],
+ 'HELP_FAQ_GROUPS_DEFAULT_ANSWER' => $help_phpbb[52][1],
+ 'HELP_FAQ_GROUPS_TEAM_QUESTION' => $help_phpbb[53][0],
+ 'HELP_FAQ_GROUPS_TEAM_ANSWER' => $help_phpbb[53][1],
+
+ 'HELP_FAQ_BLOCK_PMS' => $help_phpbb[54][1],
+ 'HELP_FAQ_PMS_CANNOT_SEND_QUESTION' => $help_phpbb[55][0],
+ 'HELP_FAQ_PMS_CANNOT_SEND_ANSWER' => $help_phpbb[55][1],
+ 'HELP_FAQ_PMS_UNWANTED_QUESTION' => $help_phpbb[56][0],
+ 'HELP_FAQ_PMS_UNWANTED_ANSWER' => $help_phpbb[56][1],
+ 'HELP_FAQ_PMS_SPAM_QUESTION' => $help_phpbb[57][0],
+ 'HELP_FAQ_PMS_SPAM_ANSWER' => $help_phpbb[57][1],
+
+ 'HELP_FAQ_BLOCK_FRIENDS' => $help_phpbb[58][1],
+ 'HELP_FAQ_FRIENDS_BASIC_QUESTION' => $help_phpbb[59][0],
+ 'HELP_FAQ_FRIENDS_BASIC_ANSWER' => $help_phpbb[59][1],
+ 'HELP_FAQ_FRIENDS_MANAGE_QUESTION' => $help_phpbb[60][0],
+ 'HELP_FAQ_FRIENDS_MANAGE_ANSWER' => $help_phpbb[60][1],
+
+ 'HELP_FAQ_BLOCK_SEARCH' => $help_phpbb[61][1],
+ 'HELP_FAQ_SEARCH_FORUM_QUESTION' => $help_phpbb[62][0],
+ 'HELP_FAQ_SEARCH_FORUM_ANSWER' => $help_phpbb[62][1],
+ 'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => $help_phpbb[63][0],
+ 'HELP_FAQ_SEARCH_NO_RESULT_ANSWER' => $help_phpbb[63][1],
+ 'HELP_FAQ_SEARCH_BLANK_QUESTION' => $help_phpbb[64][0],
+ 'HELP_FAQ_SEARCH_BLANK_ANSWER' => $help_phpbb[64][1],
+ 'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => $help_phpbb[65][0],
+ 'HELP_FAQ_SEARCH_MEMBERS_ANSWER' => $help_phpbb[65][1],
+ 'HELP_FAQ_SEARCH_OWN_QUESTION' => $help_phpbb[66][0],
+ 'HELP_FAQ_SEARCH_OWN_ANSWER' => $help_phpbb[66][1],
+
+ 'HELP_FAQ_BLOCK_BOOKMARKS' => $help_phpbb[67][1],
+ 'HELP_FAQ_BOOKMARKS_DIFFERENCE_QUESTION' => $help_phpbb[68][0],
+ 'HELP_FAQ_BOOKMARKS_DIFFERENCE_ANSWER' => $help_phpbb[68][1],
+ 'HELP_FAQ_BOOKMARKS_TOPIC_QUESTION' => $help_phpbb[69][0],
+ 'HELP_FAQ_BOOKMARKS_TOPIC_ANSWER' => $help_phpbb[69][1],
+ 'HELP_FAQ_BOOKMARKS_FORUM_QUESTION' => $help_phpbb[70][0],
+ 'HELP_FAQ_BOOKMARKS_FORUM_ANSWER' => $help_phpbb[70][1],
+ 'HELP_FAQ_BOOKMARKS_REMOVE_QUESTION' => $help_phpbb[71][0],
+ 'HELP_FAQ_BOOKMARKS_REMOVE_ANSWER' => $help_phpbb[71][1],
+
+ 'HELP_FAQ_BLOCK_ATTACHMENTS' => $help_phpbb[72][1],
+ 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => $help_phpbb[73][0],
+ 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER' => $help_phpbb[73][1],
+ 'HELP_FAQ_ATTACHMENTS_OWN_QUESTION' => $help_phpbb[74][0],
+ 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER' => $help_phpbb[74][1],
+
+ 'HELP_FAQ_BLOCK_ISSUES' => $help_phpbb[75][1],
+ 'HELP_FAQ_ISSUES_WHOIS_PHPBB_QUESTION' => $help_phpbb[76][0],
+ 'HELP_FAQ_ISSUES_WHOIS_PHPBB_ANSWER' => $help_phpbb[76][1],
+ 'HELP_FAQ_ISSUES_FEATURE_QUESTION' => $help_phpbb[77][0],
+ 'HELP_FAQ_ISSUES_FEATURE_ANSWER' => $help_phpbb[77][1],
+ 'HELP_FAQ_ISSUES_LEGAL_QUESTION' => $help_phpbb[78][0],
+ 'HELP_FAQ_ISSUES_LEGAL_ANSWER' => $help_phpbb[78][1],
+ 'HELP_FAQ_ISSUES_ADMIN_QUESTION' => $help_phpbb[79][0],
+ 'HELP_FAQ_ISSUES_ADMIN_ANSWER' => $help_phpbb[79][1],
+
+);
+write_help('faq', $lang_phpbb);
+
+trigger_error('Successfully migrated help_bbcode and help_faq to help/bbcode and help/phpbb');
+
+/**
+ * @param string $help
+ * @return array
+ */
+function load_help($help)
+{
+ global $phpbb_root_path;
+ include($phpbb_root_path . 'language/' . LANGUAGE_TO_MIGRATE . '/help_' . $help . '.php');
+ return $help;
+}
+
+/**
+ * @param string $help
+ * @param array $lang
+ */
+function write_help($help, array $lang)
+{
+ global $phpbb_root_path;
+ $fp = fopen($phpbb_root_path . 'language/' . LANGUAGE_TO_MIGRATE . '/help/' . $help . '.php', 'wb');
+ fwrite($fp, get_language_file_header());
+ fwrite($fp, '$lang = array_merge($lang, array(' . "\n");
+
+ $last_key = '';
+ ksort($lang);
+ foreach ($lang as $key => $translation)
+ {
+ $key_sections = explode('_', $key, 4);
+ unset($key_sections[3]);
+ $key_start = implode('_', $key_sections);
+
+ if ($last_key !== '' && $key_start !== $last_key)
+ {
+ fwrite($fp, "\n");
+ }
+ fwrite($fp, "\t'" . $key . "'\t=> '" . $translation . "',\n");
+ $last_key = $key_start;
+ }
+
+ fwrite($fp, '));' . "\n");
+ #fwrite($fp, $lang);
+ fclose($fp);
+}
+
+/**
+ * @return string
+ */
+function get_language_file_header()
+{
+ return <<<EOT
+<?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.
+ *
+ */
+
+/**
+ * DO NOT CHANGE
+ */
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+if (empty(\$lang) || !is_array(\$lang))
+{
+ \$lang = array();
+}
+
+
+EOT;
+}
diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php
index 698be9d303..276c010e84 100644
--- a/phpBB/develop/mysql_upgrader.php
+++ b/phpBB/develop/mysql_upgrader.php
@@ -62,14 +62,17 @@ echo "USE $dbname;$newline$newline";
@set_time_limit(0);
-$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path);
+$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path);
$classes = $finder->core_path('phpbb/')
->directory('/db/migration/data')
->get_classes();
-$schema_generator = new \phpbb\db\migration\schema_generator($classes, $config, $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix);
+$factory = new \phpbb\db\tools\factory();
+$db_tools = $factory->get($db, true);
+
+$schema_generator = new \phpbb\db\migration\schema_generator($classes, $config, $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);
$schema_data = $schema_generator->get_schema();
-$dbms_type_map = \phpbb\db\tools::get_dbms_type_map();
+$dbms_type_map = \phpbb\db\tools\tools::get_dbms_type_map();
foreach ($schema_data as $table_name => $table_data)
{
diff --git a/phpBB/develop/unicode_testing.php b/phpBB/develop/unicode_testing.php
index ec3c71d078..01586ca09b 100644
--- a/phpBB/develop/unicode_testing.php
+++ b/phpBB/develop/unicode_testing.php
@@ -19,7 +19,7 @@ if (!headers_sent())
function unicode_to_utf8($string)
{
$utf8 = '';
- $chars = array();
+
for ($i = 0; $i < strlen($string); $i++)
{
if (isset($string[$i + 5]) && substr($string, $i, 2) == '\\u' && ctype_xdigit(substr($string, $i + 2, 4)))
@@ -81,38 +81,3 @@ function utf8_to_unicode_callback($m)
{
return '\u' . str_pad(base_convert(utf8_ord($m[0]), 10, 16), 4, '0', STR_PAD_LEFT) . '';
}
-
-/**
-* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings
-* to be in NFKC
-*
-* @param mixed $strings a string or an array of strings to normalize
-* @return mixed the normalized content, preserving array keys if array given.
-*/
-function utf8_normalize_nfkc($strings)
-{
- if (empty($strings))
- {
- return $strings;
- }
-
- if (!class_exists('utf_normalizer'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
- }
-
- if (!is_array($strings))
- {
- utf_normalizer::nfkc($strings);
- }
- else if (is_array($strings))
- {
- foreach ($strings as $key => $string)
- {
- utf_normalizer::nfkc($strings[$key]);
- }
- }
-
- return $strings;
-}
diff --git a/phpBB/develop/update_email_hash.php b/phpBB/develop/update_email_hash.php
index 57aebe3ca0..c149900d64 100644
--- a/phpBB/develop/update_email_hash.php
+++ b/phpBB/develop/update_email_hash.php
@@ -19,7 +19,7 @@ $user->session_begin();
$auth->acl($user->data);
$user->setup();
-$start = request_var('start', 0);
+$start = $request->variable('start', 0);
$num_items = 1000;
echo '<br />Updating user email hashes' . "\n";
diff --git a/phpBB/develop/utf_normalizer_test.php b/phpBB/develop/utf_normalizer_test.php
deleted file mode 100644
index 27ff786db7..0000000000
--- a/phpBB/develop/utf_normalizer_test.php
+++ /dev/null
@@ -1,394 +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.
-*
-*/
-
-if (php_sapi_name() != 'cli')
-{
- die("This program must be run from the command line.\n");
-}
-
-//
-// Security message:
-//
-// This script is potentially dangerous.
-// Remove or comment the next line (die(".... ) to enable this script.
-// Do NOT FORGET to either remove this script or disable it after you have used it.
-//
-die("Please read the first lines of this script for instructions on how to enable it");
-
-set_time_limit(0);
-error_reporting(E_ALL);
-
-define('IN_PHPBB', true);
-$phpbb_root_path = '../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-
-/**
-* Let's download some files we need
-*/
-download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt');
-download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt');
-
-/**
-* Those are the tests we run
-*/
-$test_suite = array(
- /**
- * NFC
- * c2 == NFC(c1) == NFC(c2) == NFC(c3)
- * c4 == NFC(c4) == NFC(c5)
- */
- 'NFC' => array(
- 'c2' => array('c1', 'c2', 'c3'),
- 'c4' => array('c4', 'c5')
- ),
-
- /**
- * NFD
- * c3 == NFD(c1) == NFD(c2) == NFD(c3)
- * c5 == NFD(c4) == NFD(c5)
- */
- 'NFD' => array(
- 'c3' => array('c1', 'c2', 'c3'),
- 'c5' => array('c4', 'c5')
- ),
-
- /**
- * NFKC
- * c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
- */
- 'NFKC' => array(
- 'c4' => array('c1', 'c2', 'c3', 'c4', 'c5')
- ),
-
- /**
- * NFKD
- * c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
- */
- 'NFKD' => array(
- 'c5' => array('c1', 'c2', 'c3', 'c4', 'c5')
- )
-);
-
-require_once($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
-
-$i = $n = 0;
-$failed = false;
-$tested_chars = array();
-
-$fp = fopen($phpbb_root_path . 'develop/NormalizationTest.txt', 'rb');
-while (!feof($fp))
-{
- $line = fgets($fp);
- ++$n;
-
- if ($line[0] == '@')
- {
- if ($i)
- {
- echo "done\n";
- }
-
- $i = 0;
- echo "\n", substr($line, 1), "\n\n";
- continue;
- }
-
- if (!strpos(' 0123456789ABCDEF', $line[0]))
- {
- continue;
- }
-
- if (++$i % 100 == 0)
- {
- echo $i, ' ';
- }
-
- list($c1, $c2, $c3, $c4, $c5) = explode(';', $line);
-
- if (!strpos($c1, ' '))
- {
- /**
- * We are currently testing a single character, we add it to the list of
- * characters we have processed so that we can exclude it when testing
- * for invariants
- */
- $tested_chars[$c1] = 1;
- }
-
- foreach ($test_suite as $form => $serie)
- {
- foreach ($serie as $expected => $tests)
- {
- $hex_expected = ${$expected};
- $utf_expected = hexseq_to_utf($hex_expected);
-
- foreach ($tests as $test)
- {
- $utf_result = $utf_expected;
- call_user_func(array('utf_normalizer', $form), $utf_result);
-
- if (strcmp($utf_expected, $utf_result))
- {
- $failed = true;
- $hex_result = utf_to_hexseq($utf_result);
-
- echo "\nFAILED $expected == $form($test) ($hex_expected != $hex_result)";
- }
- }
- }
-
- if ($failed)
- {
- die("\n\nFailed at line $n\n");
- }
- }
-}
-fclose($fp);
-
-/**
-* Test for invariants
-*/
-echo "\n\nTesting for invariants...\n\n";
-
-$fp = fopen($phpbb_root_path . 'develop/UnicodeData.txt', 'rt');
-
-$n = 0;
-while (!feof($fp))
-{
- if (++$n % 100 == 0)
- {
- echo $n, ' ';
- }
-
- $line = fgets($fp, 1024);
-
- if (!$pos = strpos($line, ';'))
- {
- continue;
- }
-
- $hex_tested = $hex_expected = substr($line, 0, $pos);
-
- if (isset($tested_chars[$hex_tested]))
- {
- continue;
- }
-
- $utf_expected = hex_to_utf($hex_expected);
-
- if ($utf_expected >= UTF8_SURROGATE_FIRST
- && $utf_expected <= UTF8_SURROGATE_LAST)
- {
- /**
- * Surrogates are illegal on their own, we expect the normalizer
- * to return a replacement char
- */
- $utf_expected = UTF8_REPLACEMENT;
- $hex_expected = utf_to_hexseq($utf_expected);
- }
-
- foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form)
- {
- $utf_result = $utf_expected;
- utf_normalizer::$form($utf_result);
- $hex_result = utf_to_hexseq($utf_result);
-// echo "$form($utf_expected) == $utf_result\n";
-
- if (strcmp($utf_expected, $utf_result))
- {
- $failed = 1;
-
- echo "\nFAILED $hex_expected == $form($hex_tested) ($hex_expected != $hex_result)";
- }
- }
-
- if ($failed)
- {
- die("\n\nFailed at line $n\n");
- }
-}
-fclose($fp);
-
-die("\n\nALL TESTS PASSED SUCCESSFULLY\n");
-
-/**
-* Download a file to the develop/ dir
-*
-* @param string $url URL of the file to download
-* @return null
-*/
-function download($url)
-{
- global $phpbb_root_path;
-
- if (file_exists($phpbb_root_path . 'develop/' . basename($url)))
- {
- return;
- }
-
- echo 'Downloading from ', $url, ' ';
-
- if (!$fpr = fopen($url, 'rb'))
- {
- die("Can't download from $url\nPlease download it yourself and put it in the develop/ dir, kthxbai");
- }
-
- if (!$fpw = fopen($phpbb_root_path . 'develop/' . basename($url), 'wb'))
- {
- die("Can't open develop/" . basename($url) . " for output... please check your permissions or something");
- }
-
- $i = 0;
- $chunk = 32768;
- $done = '';
-
- while (!feof($fpr))
- {
- $i += fwrite($fpw, fread($fpr, $chunk));
- echo str_repeat("\x08", strlen($done));
-
- $done = ($i >> 10) . ' KiB';
- echo $done;
- }
- fclose($fpr);
- fclose($fpw);
-
- echo "\n";
-}
-
-/**
-* Convert a UTF string to a sequence of codepoints in hexadecimal
-*
-* @param string $utf UTF string
-* @return integer Unicode codepoints in hex
-*/
-function utf_to_hexseq($str)
-{
- $pos = 0;
- $len = strlen($str);
- $ret = array();
-
- while ($pos < $len)
- {
- $c = $str[$pos];
- switch ($c & "\xF0")
- {
- case "\xC0":
- case "\xD0":
- $utf_char = substr($str, $pos, 2);
- $pos += 2;
- break;
-
- case "\xE0":
- $utf_char = substr($str, $pos, 3);
- $pos += 3;
- break;
-
- case "\xF0":
- $utf_char = substr($str, $pos, 4);
- $pos += 4;
- break;
-
- default:
- $utf_char = $c;
- ++$pos;
- }
-
- $hex = dechex(utf_to_cp($utf_char));
-
- if (!isset($hex[3]))
- {
- $hex = substr('000' . $hex, -4);
- }
-
- $ret[] = $hex;
- }
-
- return strtr(implode(' ', $ret), 'abcdef', 'ABCDEF');
-}
-
-/**
-* Convert a UTF-8 char to its codepoint
-*
-* @param string $utf_char UTF-8 char
-* @return integer Unicode codepoint
-*/
-function utf_to_cp($utf_char)
-{
- switch (strlen($utf_char))
- {
- case 1:
- return ord($utf_char);
-
- case 2:
- return ((ord($utf_char[0]) & 0x1F) << 6) | (ord($utf_char[1]) & 0x3F);
-
- case 3:
- return ((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F);
-
- case 4:
- return ((ord($utf_char[0]) & 0x07) << 18) | ((ord($utf_char[1]) & 0x3F) << 12) | ((ord($utf_char[2]) & 0x3F) << 6) | (ord($utf_char[3]) & 0x3F);
-
- default:
- die('UTF-8 chars can only be 1-4 bytes long');
- }
-}
-
-/**
-* Return a UTF string formed from a sequence of codepoints in hexadecimal
-*
-* @param string $seq Sequence of codepoints, separated with a space
-* @return string UTF-8 string
-*/
-function hexseq_to_utf($seq)
-{
- return implode('', array_map('hex_to_utf', explode(' ', $seq)));
-}
-
-/**
-* Convert a codepoint in hexadecimal to a UTF-8 char
-*
-* @param string $hex Codepoint, in hexadecimal
-* @return string UTF-8 char
-*/
-function hex_to_utf($hex)
-{
- return cp_to_utf(hexdec($hex));
-}
-
-/**
-* Convert a codepoint to a UTF-8 char
-*
-* @param integer $cp Unicode codepoint
-* @return string UTF-8 string
-*/
-function cp_to_utf($cp)
-{
- if ($cp > 0xFFFF)
- {
- return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
- }
- else if ($cp > 0x7FF)
- {
- return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
- }
- else if ($cp > 0x7F)
- {
- return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
- }
- else
- {
- return chr($cp);
- }
-}
diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index 394d9536e8..f907585e28 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="" />
-<meta name="description" content="phpBB 3.1.x Changelog" />
+<meta name="description" content="phpBB 3.2.x Changelog" />
<title>phpBB &bull; Changelog</title>
<link href="assets/css/stylesheet.css" rel="stylesheet" type="text/css" media="screen" />
@@ -21,7 +21,7 @@
<div id="doc-description">
<a href="../index.php" id="logo"><img src="assets/images/site_logo.gif" alt="" /></a>
- <h1>phpBB 3.1.x Changelog</h1>
+ <h1>phpBB 3.2.x Changelog</h1>
<p style="display: none;"><a href="#start_here">Skip</a></p>
</div>
@@ -36,7 +36,7 @@
<!-- BEGIN DOCUMENT -->
<p class="paragraph main-description">
- This is a non-exhaustive (but still near complete) changelog for phpBB 3.1.x including release candidate versions.
+ This is a non-exhaustive (but still near complete) changelog for phpBB 3.2.x including release candidate versions.
Our thanks to all those people who've contributed bug reports and code fixes.
</p>
@@ -50,6 +50,11 @@
<ol>
<li><a href="#changelog">Changelog</a>
<ul>
+ <li><a href="#v320b2">Changes since 3.2.0-b2</a></li>
+ <li><a href="#v320b1">Changes since 3.2.0-b1</a></li>
+ <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="#v319">Changes since 3.1.9</a></li>
<li><a href="#v318">Changes since 3.1.8</a></li>
<li><a href="#v317pl1">Changes since 3.1.7-PL1</a></li>
@@ -117,7 +122,411 @@
<div class="paragraph">
<div class="inner">
-<div class="content">
+ <div class="content">
+ <a name="v320b2"></a><h3>Changes since 3.2.0-b2</h3>
+ <h4>Bug</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9435">PHPBB3-9435</a>] - &quot;magic numbers&quot; in message_parser.php/bbcode.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13616">PHPBB3-13616</a>] - Pass lexer directly to TWIG environment</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13972">PHPBB3-13972</a>] - 3.1.5 - Waiting time conflict</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14136">PHPBB3-14136</a>] - IE compatibility meta is missing in overall_header.html</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14198">PHPBB3-14198</a>] - Container cache filename doesn't depend on the build options</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14260">PHPBB3-14260</a>] - Right parenthesis breaks (some?) magic URLs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14318">PHPBB3-14318</a>] - Board Notifications Config Migration Not Working</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14329">PHPBB3-14329</a>] - Updater Cannot remove files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14381">PHPBB3-14381</a>] - Text Reparser fails with empty sql fields</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14393">PHPBB3-14393</a>] - Update 3.2.0a1 to 3.2.0a2 --&gt; Error: CANNOT_DELETE_FILES </li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14426">PHPBB3-14426</a>] - viewtopic error posts bbcode pregmatch</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14481">PHPBB3-14481</a>] - phpBB does not obey HTTP_X_FORWARDED_PORT header</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14497">PHPBB3-14497</a>] - Update nginx sample config for new installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14527">PHPBB3-14527</a>] - Dataloss caused by link shortening</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14528">PHPBB3-14528</a>] - Structured data - breadcrumbs error</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14530">PHPBB3-14530</a>] - Signature parsing inconsistant</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14532">PHPBB3-14532</a>] - Database column default incorrectly escaped on MSSQL</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14550">PHPBB3-14550</a>] - function unique_id()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14555">PHPBB3-14555</a>] - Inconsistent usage of the cache directory</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14559">PHPBB3-14559</a>] - Attachments' behaviour in quotes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14562">PHPBB3-14562</a>] - Extension's permissions don't have language fallback</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14564">PHPBB3-14564</a>] - config cookie domain is empty</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14569">PHPBB3-14569</a>] - Add a method for console progress bar initialisation</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14572">PHPBB3-14572</a>] - Quote notifications deleted on edit</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14576">PHPBB3-14576</a>] - Functional Test Framework should include functions.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14577">PHPBB3-14577</a>] - Stop using sizeof() inside for() loop</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14589">PHPBB3-14589</a>] - Requirements test showing required text for &quot;yellow/amber&quot; (optional) requirements</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14590">PHPBB3-14590</a>] - Installer gets stuck at sending notification e-mail</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14591">PHPBB3-14591</a>] - Some installation data not being inserted when running under MS SQL Server</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14607">PHPBB3-14607</a>] - Missing Auto Increment in Report Table</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14619">PHPBB3-14619</a>] - docs/ folder need work to change 3.1.x to 3.2.x in readme, install, changelog etc</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14648">PHPBB3-14648</a>] - Users don't receive default notifications if another setting is set.</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14649">PHPBB3-14649</a>] - Missing variable within event</li>
+ </ul>
+ <h4>Improvement</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13502">PHPBB3-13502</a>] - controller resolver should handle callable functions and objects</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14540">PHPBB3-14540</a>] - Adjust class recursive_dot_prefix_filter_iterator to increase performance</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14561">PHPBB3-14561</a>] - Add additional commands for user actions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14664">PHPBB3-14664</a>] - Fix PHPDoc comment in cron manager</li>
+ </ul>
+ <h4>New Feature</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12684">PHPBB3-12684</a>] - Add a command to add a user from the CLI</li>
+ </ul>
+ <h4>Task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13969">PHPBB3-13969</a>] - Remove old help_* language files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14565">PHPBB3-14565</a>] - Updates composer to 1.0.0-b2</li>
+ </ul>
+
+ <a name="v320b1"></a><h3>Changes since 3.2.0-b1</h3>
+ <h4>Bug</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14307">PHPBB3-14307</a>] - Incorrect wording used in installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14315">PHPBB3-14315</a>] - Changing multiple forum permissions at once forces identical permissions on all groups</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14416">PHPBB3-14416</a>] - navlnks in header have incorrect tool tip styling</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14431">PHPBB3-14431</a>] - Remote avatar uploading does not support https</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14440">PHPBB3-14440</a>] - Paths can break for extensions with deep route patterns/paths</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14460">PHPBB3-14460</a>] - Use the selected language in AJAX pages as well in the installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14461">PHPBB3-14461</a>] - Text reparser migration might finish too late</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14488">PHPBB3-14488</a>] - Grab correct session ID in ui tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14489">PHPBB3-14489</a>] - Extension compiler pass cannot find class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14503">PHPBB3-14503</a>] - Allow superglobals in installer cli</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14510">PHPBB3-14510</a>] - Prevent infinite loop in adding bots task</li>
+ </ul>
+ <h4>Improvement</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14312">PHPBB3-14312</a>] - Allow installer updating only without updating files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14448">PHPBB3-14448</a>] - Use guzzle for remote files uploading</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14462">PHPBB3-14462</a>] - Add further measures to prevent timeouts in the installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14478">PHPBB3-14478</a>] - Move facebook/webdriver to main composer.json</li>
+ </ul>
+ <h4>New Feature</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14499">PHPBB3-14499</a>] - CLI updater</li>
+ </ul>
+ <h4>Task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14447">PHPBB3-14447</a>] - Cleanup whitespaces in Prosilver</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14477">PHPBB3-14477</a>] - Update text formatter to latest release</li>
+ </ul>
+
+ <a name="v320a2"></a><h3>Changes since 3.2.0-a2</h3>
+ <h4>Bug</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10628">PHPBB3-10628</a>] - http:// prepended to &quot;www.&quot; urls (but not reflected in preview)</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11875">PHPBB3-11875</a>] - mediumint(8) too small for post_id</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12221">PHPBB3-12221</a>] - URLs Containing javascript: are Garbled</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14129">PHPBB3-14129</a>] - Adding custom extensions autoloaders feature slow downs the board</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14321">PHPBB3-14321</a>] - Fatal error on download the merged conflicts archive during update from 3.1.6 to 3.2-a1</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14323">PHPBB3-14323</a>] - Long urls are no longer shortened</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14368">PHPBB3-14368</a>] - Post Editors Text Should Be Black, Not Blue</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14371">PHPBB3-14371</a>] - Small fix for the aligment quick links</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14373">PHPBB3-14373</a>] - Do not use strpos() on arrays in iohandler_base::add_error_message()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14378">PHPBB3-14378</a>] - Maintain consistent template var paths in 3.2 installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14380">PHPBB3-14380</a>] - Maintain consistent template var paths in 3.2 installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14402">PHPBB3-14402</a>] - Tidy plupload cron should not rely on user id/ip being available</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14403">PHPBB3-14403</a>] - phpbb\log should still work even when no user data is given</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14405">PHPBB3-14405</a>] - Text processor parses invalid use of url bbcode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14419">PHPBB3-14419</a>] - Update composer dependencies and fix outdated composer lock file</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14420">PHPBB3-14420</a>] - Search Results pagination not up to date / broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14428">PHPBB3-14428</a>] - Use other links for files remote test</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14431">PHPBB3-14431</a>] - Remote avatar uploading does not support https</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14432">PHPBB3-14432</a>] - The lang() function needs to handle key array</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14434">PHPBB3-14434</a>] - Schema generator fails if extensions have non-migrations in migrations dir</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14436">PHPBB3-14436</a>] - Default data type migration misses oauth_states dependency</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14442">PHPBB3-14442</a>] - Use Goutte ~2.0 after allowing PHP &gt;= 5.4</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14444">PHPBB3-14444</a>] - Fatal error in functions_messenger.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14446">PHPBB3-14446</a>] - Add predefined placeholder variables to twig</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14452">PHPBB3-14452</a>] - Undefined $progressFillerText in installer.js</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14453">PHPBB3-14453</a>] - Missing dependency in the text_reparser migration</li>
+ </ul>
+ <h4>Improvement</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13454">PHPBB3-13454</a>] - Remove unused variables, globals, parameters</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13733">PHPBB3-13733</a>] - Allow non-migration files inside migrations folder</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14177">PHPBB3-14177</a>] - Catch exceptions and display a nice error page</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14253">PHPBB3-14253</a>] - Show group requests pending aproval at the ACP groups summary</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14377">PHPBB3-14377</a>] - Allow extensions to register custom compiler pass</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14418">PHPBB3-14418</a>] - Add missing language string PM_TOOLS</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14445">PHPBB3-14445</a>] - Force page refresh before the installer generates the schema</li>
+ </ul>
+ <h4>Task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14250">PHPBB3-14250</a>] - Review/bump composer dependencies</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14262">PHPBB3-14262</a>] - Move converter code into a controller</li>
+ </ul>
+
+ <a name="v320a1"></a><h3>Changes since 3.2.0-a1</h3>
+ <h4>Bug</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9791">PHPBB3-9791</a>] - invalid [] - chars on search URI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13451">PHPBB3-13451</a>] - A very long string inside message crashes PHP</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14273">PHPBB3-14273</a>] - Unnecessary core.root_path dependency in files.upload service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14293">PHPBB3-14293</a>] - Responsive .postbody width not expanding</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14295">PHPBB3-14295</a>] - Icon on left side of &quot;Post awaiting approval&quot; inside messages is missing</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14311">PHPBB3-14311</a>] - Installer error messages not being reported back to client properly</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14317">PHPBB3-14317</a>] - Run lang_migrate_help_lang script on master</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14320">PHPBB3-14320</a>] - Language selector is broken in the installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14325">PHPBB3-14325</a>] - Renamed Event Variables Backwards Incompatible</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14326">PHPBB3-14326</a>] - Diffed files are not decoded at update</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14339">PHPBB3-14339</a>] - State support for PHP 7.0 in docs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14344">PHPBB3-14344</a>] - Improve formatting of errors during install</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14345">PHPBB3-14345</a>] - Check if message description exists in install cli iohandler</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14349">PHPBB3-14349</a>] - Improve error messages and remove output of suppressed messages</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14350">PHPBB3-14350</a>] - Remove duplicate semi-colon from functions_user</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14358">PHPBB3-14358</a>] - Fatal error when running create_schema_files.php (missing composer autoloader)</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14359">PHPBB3-14359</a>] - Wrong service definition for console.command.reparser.reparse</li>
+ </ul>
+ <h4>Improvement</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12649">PHPBB3-12649</a>] - Change sort &amp; display options in footers to dropdown menu</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14257">PHPBB3-14257</a>] - Reparse after update</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14269">PHPBB3-14269</a>] - Use http_exceptions instead of die() in installer controllers</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14310">PHPBB3-14310</a>] - Progress bar in new installer not very clear</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14340">PHPBB3-14340</a>] - Revert the workaround fix for segmentation fault error on phpBB 3.2 PHP 7 tests</li>
+ </ul>
+ <h4>Task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14247">PHPBB3-14247</a>] - Usage of @ at begining of an unquoted string in a yaml file is deprecated</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14341">PHPBB3-14341</a>] - Update to Symfony 2.8</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14348">PHPBB3-14348</a>] - Add an index.html to the install folder</li>
+ </ul>
+
+ <a name="v31x"></a><h3>Changes since 3.1.x</h3>
+ <h4>Bug</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-6466">PHPBB3-6466</a>] - Permission Role Tooltips do not display in Safari</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7187">PHPBB3-7187</a>] - Quote smilies error</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7275">PHPBB3-7275</a>] - Custom bbodes trim('${1}')</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8064">PHPBB3-8064</a>] - forum author sort not using username_clean</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8419">PHPBB3-8419</a>] - custom tag eats up space character</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8420">PHPBB3-8420</a>] - emoticon removes space before itself when using preview</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8613">PHPBB3-8613</a>] - BBCode_uid- and censor-bug</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9073">PHPBB3-9073</a>] - Word censoring in URLs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9109">PHPBB3-9109</a>] - Maximum allowed recepients restriction precedence</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9377">PHPBB3-9377</a>] - Custom BB Code Nesting</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10002">PHPBB3-10002</a>] - (incomplete) BBCode usage of [quote] - and [list] - forces closing [/list] - and [/quote] -s, ultimately breaking HTML/Design</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10388">PHPBB3-10388</a>] - Template engine should use json_encode() to properly escape JS properties</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10572">PHPBB3-10572</a>] - Unguarded includes in acp/</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10989">PHPBB3-10989</a>] - Bug in BBCode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11444">PHPBB3-11444</a>] - Unnecessary notify column in phpbb_user_notifications table</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11967">PHPBB3-11967</a>] - Notification settings are not respected</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12143">PHPBB3-12143</a>] - Untranslated group name from index if not special group</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12195">PHPBB3-12195</a>] - Double-slash URLs not supported</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12387">PHPBB3-12387</a>] - mysqli_free_result is called with false value</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12554">PHPBB3-12554</a>] - Quotes do not display correctly as list elements</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12698">PHPBB3-12698</a>] - Replace all instances of magic numbers with constants in javascript</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12957">PHPBB3-12957</a>] - The template engine is not constructed properly in install/index</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12974">PHPBB3-12974</a>] - Update nightly version of develop to 3.2.0-a1-dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13101">PHPBB3-13101</a>] - Remove WLM contact from profile</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13238">PHPBB3-13238</a>] - \phpbb\db\migration\data\v310\mysql_fulltext_drop tries to drop non existent indexes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13359">PHPBB3-13359</a>] - Develop tests fail due to wrong template set up in tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13362">PHPBB3-13362</a>] - The whole cache dir (excluding the .htaccess and index.html files) should be ignored by git</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13371">PHPBB3-13371</a>] - Lang vars not loaded during install process</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13372">PHPBB3-13372</a>] - Environment Bug - Routing broken for extensions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13377">PHPBB3-13377</a>] - Function decode_message() incorrectly decodes www type URLs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13425">PHPBB3-13425</a>] - Smiley code at start of text being quoted doesn't show smiley image in quote</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13513">PHPBB3-13513</a>] - Mixed routing file paths in the router</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13555">PHPBB3-13555</a>] - Poll options preview rendered incorrectly by &lt;br /&gt; collision</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13619">PHPBB3-13619</a>] - Remove unneeded folders/files from vendor folder in release package</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13638">PHPBB3-13638</a>] - INCLUDECSS and INCLUDEJS Broken in 3.2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13670">PHPBB3-13670</a>] - Fix fatal function name must be a string in functional tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13680">PHPBB3-13680</a>] - Notification for a quote within a quote</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13718">PHPBB3-13718</a>] - Spambot countermeasures/CAPTCHA admin panel won't load</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13749">PHPBB3-13749</a>] - Add missing slash to base uri in helper route tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13766">PHPBB3-13766</a>] - Missing style_parent_id in textformater's data_access::get_styles()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13769">PHPBB3-13769</a>] - bin/phpbbcli.php ignores PHPBB_ENVIRONMENT constant from config.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13772">PHPBB3-13772</a>] - Error in @param variable type for phpbb\passwords\manager</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13782">PHPBB3-13782</a>] - ACM null caching driver class is named with the reserved word 'null'</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13792">PHPBB3-13792</a>] - Travis fails installing hhvm-nigthly</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13814">PHPBB3-13814</a>] - phpbb_is_writable() method of the new filesystem class truncates files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13825">PHPBB3-13825</a>] - create_thumbnail() incorrectly calls phpbb\filesystem::phpbb_chmod</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13828">PHPBB3-13828</a>] - Rename null driver to dummy for PHP7 compatibility in tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13829">PHPBB3-13829</a>] - Router requires cache directory to be writable</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13839">PHPBB3-13839</a>] - Failing test when the phpBB root directory isn't named phpbb</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13849">PHPBB3-13849</a>] - Development environment broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13860">PHPBB3-13860</a>] - Array to string conversion in parser service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13871">PHPBB3-13871</a>] - Call to a member function realpath() on a non-object in functions.php on line 3474</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13875">PHPBB3-13875</a>] - Lint test should ignore cache, ext, and store folder</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13890">PHPBB3-13890</a>] - Failling tests in master</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13896">PHPBB3-13896</a>] - Coding style issue in master</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13897">PHPBB3-13897</a>] - Non-existent environment causes fatal error</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13906">PHPBB3-13906</a>] - BBCodes in signatures are not correctly parsed in post preview</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13990">PHPBB3-13990</a>] - Reparse markup inside of forum rules/description</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13993">PHPBB3-13993</a>] - Signature Editing Broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14008">PHPBB3-14008</a>] - Do not add a user_id value to quotes from guests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14033">PHPBB3-14033</a>] - Correct docblock errors</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14034">PHPBB3-14034</a>] - Fix reparser names that contain &quot;text_reparser&quot; in the middle</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14036">PHPBB3-14036</a>] - Replace path_helper with a mock</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14052">PHPBB3-14052</a>] - New installer - The commands are not translated</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14074">PHPBB3-14074</a>] - Not possible to clear notification (mark as read)</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14076">PHPBB3-14076</a>] - Notifications settings are not correctly handled when a non default setting is set</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14078">PHPBB3-14078</a>] - Notification related sql general error on submission of editing post</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14079">PHPBB3-14079</a>] - Cannot mark notification as read from the dropdown</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14094">PHPBB3-14094</a>] - Current master branch is getting segmentation fault error on PHP 7 tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14128">PHPBB3-14128</a>] - Image posting overflow regression</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14137">PHPBB3-14137</a>] - Fix Notification Menu Settings spacing issue caused by new jump-box improvements</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14138">PHPBB3-14138</a>] - Use span tags instead of abbr tags in the footer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14165">PHPBB3-14165</a>] - Fix layout of ucp/mcp after 14139</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14178">PHPBB3-14178</a>] - Installer database helper tests fail if sqlite3 is not present</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14180">PHPBB3-14180</a>] - Use unix line ending in files classes tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14182">PHPBB3-14182</a>] - Move the v310\notifications_board migration to v320\notifications_board</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14183">PHPBB3-14183</a>] - Remove deprecated max-device-width</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14193">PHPBB3-14193</a>] - Custom BBCode Buttons Broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14194">PHPBB3-14194</a>] - Responsive Quick Links Menu Broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14195">PHPBB3-14195</a>] - Plupload Attachments Not Quite Working</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14199">PHPBB3-14199</a>] - We need to hide icons from screen readers</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14202">PHPBB3-14202</a>] - Add missing sr-only classes to icons</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14216">PHPBB3-14216</a>] - Do not run thumbnail test if gd is not enabled</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14221">PHPBB3-14221</a>] - Fix viewforum header issue</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14222">PHPBB3-14222</a>] - ACP users page tries to cast deactivated_super_global to int</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14225">PHPBB3-14225</a>] - Inject the resolver in routing loaders when using them</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14230">PHPBB3-14230</a>] - Unread posts' icons don't have different color in viewtopic</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14234">PHPBB3-14234</a>] - Do not use references in trigger_event()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14235">PHPBB3-14235</a>] - Font Awesome not available with simple_header.html</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14240">PHPBB3-14240</a>] - Always include all config files in the update package</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14274">PHPBB3-14274</a>] - New installer has weak inclusion of user functions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14277">PHPBB3-14277</a>] - Don't use user_id in migrations as it is not defined</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14278">PHPBB3-14278</a>] - Don't use user_id in installer if not available</li>
+ </ul>
+ <h4>Improvement</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8672">PHPBB3-8672</a>] - No file size limit in getimagesize() and remote upload</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8708">PHPBB3-8708</a>] - Splitting global announcements from f_announce</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9485">PHPBB3-9485</a>] - Please include link to specific post in moderator's activity logs.</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10268">PHPBB3-10268</a>] - extend function make_clickable() to also recognize semicolons as leading URL borders</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10620">PHPBB3-10620</a>] - Quote tag improvement</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10922">PHPBB3-10922</a>] - Allow parameters for [email] - BBCode content instead of addresses only</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11649">PHPBB3-11649</a>] - Move construction of twig environment to DIC</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11742">PHPBB3-11742</a>] - BBCode 'code' doesn't support tabs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12466">PHPBB3-12466</a>] - Move classes from acp_database.php to their own files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12487">PHPBB3-12487</a>] - Update PHP code</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12608">PHPBB3-12608</a>] - Improve notifications drop-down menu styling in header</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12654">PHPBB3-12654</a>] - Improve header search-box styling</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12681">PHPBB3-12681</a>] - Cache the compiled routes and dump the url_generator</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12719">PHPBB3-12719</a>] - Convert to Normalize &amp; SUITCSS - base for reset</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12745">PHPBB3-12745</a>] - Allow Emoji characters in posts</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12769">PHPBB3-12769</a>] - Add and use Font-Awesome to handle proSilver icons</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12821">PHPBB3-12821</a>] - Use CSS instead of images for gradients</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12958">PHPBB3-12958</a>] - Remove subsilver2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13063">PHPBB3-13063</a>] - Move functions_url_matcher to a proper class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13132">PHPBB3-13132</a>] - Twig: move the loops content from loops. to the root context</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13137">PHPBB3-13137</a>] - Remove schema.json from repository</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13178">PHPBB3-13178</a>] - Allow posting Emoji characters if the database supports it</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13206">PHPBB3-13206</a>] - DEBUG mode should automatically recompile stale style components</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13266">PHPBB3-13266</a>] - Enabling twig dump function if DEBUG is defined</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13388">PHPBB3-13388</a>] - Integrate routing and di parameters resolution</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13450">PHPBB3-13450</a>] - Type-hint return value of $phpbb_container-&gt;get()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13455">PHPBB3-13455</a>] - Change request_var() calls with $request-&gt;variable()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13468">PHPBB3-13468</a>] - Change add_log() calls with $phpbb_log-&gt;add()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13494">PHPBB3-13494</a>] - Replace set_config() calls with $config-&gt;set()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13496">PHPBB3-13496</a>] - Replace set_config_count() calls with $config-&gt;increment()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13497">PHPBB3-13497</a>] - Change get_tables() calls with $db_tools-&gt;sql_list_tables()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13498">PHPBB3-13498</a>] - Change get_user_avatar() calls with phpbb_get_avatar()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13499">PHPBB3-13499</a>] - Move get_remote_file() to functions_compatibility.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13595">PHPBB3-13595</a>] - Remove unused instances of the bbcode class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13614">PHPBB3-13614</a>] - Remove phpbb_pcre_utf8_support() and assume Unicode is supported by PCRE</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13652">PHPBB3-13652</a>] - Extend SQL query builder functionality</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13697">PHPBB3-13697</a>] - Rewriting/moving file system functions to filesystem class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13740">PHPBB3-13740</a>] - Refactoring installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13762">PHPBB3-13762</a>] - Moving translation loading and language related functions into a service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13770">PHPBB3-13770</a>] - Make DI Container builder constructor dependency free</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13789">PHPBB3-13789</a>] - Implement Googles noCAPTCHA reCAPTCHA</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13801">PHPBB3-13801</a>] - Decouple the user object from the text_formatter.s9e.parser service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13803">PHPBB3-13803</a>] - Implement a generic and scalable way to reparse rich text</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13805">PHPBB3-13805</a>] - Make generate_text_for_storage() match the signature and feature set of message_parser::parse()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13844">PHPBB3-13844</a>] - Replace help_ language magic with a help manager and normal language files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13847">PHPBB3-13847</a>] - Move quote generation to text_formatter.utils</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13891">PHPBB3-13891</a>] - Add CLI commands for reparsing text</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13901">PHPBB3-13901</a>] - Give quotes more whitespace in the posting form for readability</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13902">PHPBB3-13902</a>] - Increase the CSS margin around blockquote</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13904">PHPBB3-13904</a>] - Refactor attachment upload functions into service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13921">PHPBB3-13921</a>] - Try harder to fix block elements BBCodes used inside of inline elements BBCodes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13946">PHPBB3-13946</a>] - Increase the CSS margin around [code] - and [list] -</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13970">PHPBB3-13970</a>] - Save the value of the optional parameter in [code] - BBCode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13986">PHPBB3-13986</a>] - Add --resume option to reparser CLI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13987">PHPBB3-13987</a>] - Add --dry-run option to reparser CLI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14000">PHPBB3-14000</a>] - Make it possible to use emojis in posts</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14097">PHPBB3-14097</a>] - Catch and show all exceptions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14107">PHPBB3-14107</a>] - dropdown rendering on rtl</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14124">PHPBB3-14124</a>] - Automatically translate exception in CLI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14139">PHPBB3-14139</a>] - stop styling IDs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14157">PHPBB3-14157</a>] - Allow administrators to set an alt attribute for topic icons</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14162">PHPBB3-14162</a>] - Add CLI commands to manage migrations</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14168">PHPBB3-14168</a>] - Refactor attachment management functions into classes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14174">PHPBB3-14174</a>] - issues in language\en\install_new.php </li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14175">PHPBB3-14175</a>] - Refactor responsive implementation for easier manipulation</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14206">PHPBB3-14206</a>] - Fix jumpbox incosistencies</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14220">PHPBB3-14220</a>] - Adding routing file locator and route loader services</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14231">PHPBB3-14231</a>] - Fix double home icon in breadcrumbs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14237">PHPBB3-14237</a>] - Use language class in the notifications component</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14264">PHPBB3-14264</a>] - Don't use constants in textreparser plugins</li>
+ </ul>
+ <h4>New Feature</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10165">PHPBB3-10165</a>] - Send test email feature on email settings ACP page</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11768">PHPBB3-11768</a>] - Integrate s9e\TextFormatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12516">PHPBB3-12516</a>] - Always preview signature in UCP/ACP module</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12620">PHPBB3-12620</a>] - Allow the user to define multiples environments</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12692">PHPBB3-12692</a>] - Add a console command to manage the thumbnail</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13329">PHPBB3-13329</a>] - Rely on Intl and mbstring, use patchwork/utf8 as fallback</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13641">PHPBB3-13641</a>] - problem with custom BBCode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13961">PHPBB3-13961</a>] - Add orderable service collections</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14125">PHPBB3-14125</a>] - Add --env option to all CLI commands</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14158">PHPBB3-14158</a>] - Add a lang_array function to the language service to avoid using call_user_func</li>
+ </ul>
+ <h4>Sub-task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12577">PHPBB3-12577</a>] - Use a lazy service to delay the construction of the passwords_manager</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12581">PHPBB3-12581</a>] - Use the proxy pattern for the template lexer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12632">PHPBB3-12632</a>] - Use a twig.debug environment config value to enable Twig debug</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12633">PHPBB3-12633</a>] - Add debug.template.events</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12699">PHPBB3-12699</a>] - Replace instances in the message textarea keydown callback</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13421">PHPBB3-13421</a>] - Create an interface for db\tools.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13487">PHPBB3-13487</a>] - Add factory for db tool class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13645">PHPBB3-13645</a>] - Moving feeds to controllers</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13647">PHPBB3-13647</a>] - Move FAQ to controller</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13654">PHPBB3-13654</a>] - Moving reports to controller</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13881">PHPBB3-13881</a>] - Unify quote removal in 3.1 and 3.2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13935">PHPBB3-13935</a>] - Allow more admin-configurable schemes in post links</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14039">PHPBB3-14039</a>] - Refactoring the updater</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14044">PHPBB3-14044</a>] - Deduplicate the installers</li>
+ </ul>
+ <h4>Task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9457">PHPBB3-9457</a>] - [Accessibility] - Add WAI-ARIA landmarks to the Prosilver template files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11528">PHPBB3-11528</a>] - Use mink for acceptance tests involving javascript execution</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12384">PHPBB3-12384</a>] - Run Travis CI HHVM tests against MySQLi instead of MySQL</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12505">PHPBB3-12505</a>] - Remove outdated media handling in attachment.html</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12564">PHPBB3-12564</a>] - Remove obsolete version definitions from module info files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12916">PHPBB3-12916</a>] - Add separate nightly builds for 3.1 and 3.2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13130">PHPBB3-13130</a>] - Update dependencies to Symfony 2.5</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13139">PHPBB3-13139</a>] - Update Twig to 1.18.0</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13363">PHPBB3-13363</a>] - Replace phpbb\php\ini with composer package bantu/ini-get-wrapper</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13407">PHPBB3-13407</a>] - Update Symfony Components to 2.7.x</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13572">PHPBB3-13572</a>] - Upgrade composer to 1.0.0-alpha9</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13634">PHPBB3-13634</a>] - Update README to show new branch names</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13725">PHPBB3-13725</a>] - Coding guidelines: static public</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13767">PHPBB3-13767</a>] - Remove .git from vendor/s9e/text-formatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13768">PHPBB3-13768</a>] - Update to Symfony 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13774">PHPBB3-13774</a>] - Update s9e\TextFormatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13777">PHPBB3-13777</a>] - Move acp/modules module handling code into a service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13793">PHPBB3-13793</a>] - Remove message translation from exceptions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13800">PHPBB3-13800</a>] - Make extension manager an optional dependency for the router</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13804">PHPBB3-13804</a>] - Make template's user dependency optional</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13832">PHPBB3-13832</a>] - Replace use of deprecated e modifier of preg_replace in bbcode functions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13985">PHPBB3-13985</a>] - Update s9e\TextFormatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14015">PHPBB3-14015</a>] - Update Symfony to the latest 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14053">PHPBB3-14053</a>] - Remove @covers annotations from installer config test</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14056">PHPBB3-14056</a>] - Keep install schema resources in the install folder</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14096">PHPBB3-14096</a>] - Update Symfony to the latest 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14140">PHPBB3-14140</a>] - Update Symfony to benefit from improvement to the console component</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14150">PHPBB3-14150</a>] - Update fast-image-size to newest release</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14205">PHPBB3-14205</a>] - Bump PHP requirement to 5.4</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14238">PHPBB3-14238</a>] - Update Symfony to the latest 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14243">PHPBB3-14243</a>] - Exclude every .git directory from the pakages</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14256">PHPBB3-14256</a>] - Remove PHP7 from the allowed failures</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14265">PHPBB3-14265</a>] - Make all tables available in the container</li>
+ </ul>
<a name="v319"></a><h3>Changes since 3.1.9</h3>
@@ -415,7 +824,6 @@
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14140">PHPBB3-14140</a>] - Update Symfony to benefit from improvement to the console component</li>
</ul>
-
<a name="v315"></a><h3>Changes since 3.1.5</h3>
<h4>Bug</h4>
diff --git a/phpBB/docs/FAQ.html b/phpBB/docs/FAQ.html
index 5f3a425cda..09ee6c1ddd 100644
--- a/phpBB/docs/FAQ.html
+++ b/phpBB/docs/FAQ.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="" />
-<meta name="description" content="phpBB 3.1.x frequently asked questions" />
+<meta name="description" content="phpBB 3.2.x frequently asked questions" />
<title>phpBB &bull; FAQ</title>
<link href="assets/css/stylesheet.css" rel="stylesheet" type="text/css" media="screen" />
@@ -21,8 +21,8 @@
<div id="doc-description">
<a href="../index.php" id="logo"><img src="assets/images/site_logo.gif" alt="" /></a>
- <h1>phpBB 3.1.x FAQ</h1>
- <p>phpBB 3.1.x frequently asked questions</p>
+ <h1>phpBB 3.2.x FAQ</h1>
+ <p>phpBB 3.2.x frequently asked questions</p>
<p style="display: none;"><a href="#start_here">Skip</a></p>
</div>
@@ -249,7 +249,7 @@ I want to sue you because i think you host an illegal board!</h2>
<div class="content">
-<p>Please read the paragraph about permissions in our extensive <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">online documentation</a>.</p>
+<p>Please read the paragraph about permissions in our extensive <a href="https://www.phpbb.com/support/docs/en/3.2/ug/">online documentation</a>.</p>
</div>
@@ -305,7 +305,7 @@ I want to sue you because i think you host an illegal board!</h2>
<div class="content">
-<p>Please read our <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">extensive user documentation</a> first, it may just explain what you want to know.</p>
+<p>Please read our <a href="https://www.phpbb.com/support/docs/en/3.2/ug/">extensive user documentation</a> first, it may just explain what you want to know.</p>
<p>Feel free to search our community forum for the information you require. <strong>PLEASE DO NOT</strong> post your question without having first used search, chances are someone has already asked and answered your question. You can find our board here:</p>
diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html
index 9f8bbe74b8..748ae69cf7 100644
--- a/phpBB/docs/INSTALL.html
+++ b/phpBB/docs/INSTALL.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="" />
-<meta name="description" content="phpBB 3.1.x Installation, updating and conversion informations" />
+<meta name="description" content="phpBB 3.2.x Installation, updating and conversion informations" />
<title>phpBB &bull; Install</title>
<link href="assets/css/stylesheet.css" rel="stylesheet" type="text/css" media="screen" />
@@ -21,8 +21,8 @@
<div id="doc-description">
<a href="../index.php" id="logo"><img src="assets/images/site_logo.gif" alt="" /></a>
- <h1>phpBB 3.1.x Install</h1>
- <p>phpBB 3.1.x Installation, updating and conversion informations</p>
+ <h1>phpBB 3.2.x Install</h1>
+ <p>phpBB 3.2.x Installation, updating and conversion informations</p>
<p style="display: none;"><a href="#start_here">Skip</a></p>
</div>
@@ -59,7 +59,7 @@
<li><a href="#quickinstall">Quick install</a></li>
<li><a href="#require">Requirements</a></li>
<li><a href="#install">New installation</a></li>
- <li><a href="#update">Updating from stable releases of phpBB 3.1.x</a>
+ <li><a href="#update">Updating from stable releases of phpBB 3.2.x</a>
<ol style="list-style-type: lower-roman;">
<li><a href="#update_full">Full package</a></li>
<li><a href="#update_files">Changed files</a></li>
@@ -68,8 +68,8 @@
<li><a href="#update_all">All package types</a></li>
</ol>
</li>
- <li><a href="#update30">Updating from phpBB 3.0.x to phpBB 3.1.x</a></li>
- <li><a href="#convert">Conversion from phpBB 2.0.x to phpBB 3.1.x</a>
+ <li><a href="#update30_31">Updating from phpBB 3.0.x/3.1.x to phpBB 3.2.x</a></li>
+ <li><a href="#convert">Conversion from phpBB 2.0.x to phpBB 3.2.x</a>
<ol style="list-style-type: lower-roman;">
<li><a href="#prereq">Requirements before converting</a></li>
<li><a href="#conversion">Converting</a></li>
@@ -109,7 +109,7 @@
<li>Change the permissions on config.php to be writable by all (666 or -rw-rw-rw- within your FTP Client)</li>
<li>Change the permissions on the following directories to be writable by all (777 or -rwxrwxrwx within your FTP Client):<br />
<code>store/</code>, <code>cache/</code>, <code>files/</code> and <code>images/avatars/upload/</code>.</li>
- <li>Point your web browser to the location where you uploaded the phpBB3 files with the addition of <code>install/index.php</code> or simply <code>install/</code>, e.g. <code>http://www.example.com/phpBB3/install/index.php</code>, <code>http://www.example.com/forum/install/</code>.</li>
+ <li>Point your web browser to the location where you uploaded the phpBB3 files with the addition of <code>install/app.php</code> or simply <code>install/</code>, e.g. <code>http://www.example.com/phpBB3/install/app.php</code>, <code>http://www.example.com/forum/install/</code>.</li>
<li>Click the <strong><em>INSTALL</em></strong> tab, follow the steps and fill out all the requested information.</li>
<li>Change the permissions on config.php to be writable only by yourself (644 or -rw-r--r-- within your FTP Client)</li>
<li>phpBB3 should now be available, please <strong>MAKE SURE</strong> you read at least <a href="#postinstall">Section 6</a> below for important, security related post-installation instructions, and also take note of <a href="#anti_spam">Section 7</a> regarding anti-spam measures.</li>
@@ -133,7 +133,7 @@
<div class="content">
- <p>phpBB 3.1.x has a few requirements which must be met before you are able to install and use it.</p>
+ <p>phpBB 3.2.x has a few requirements which must be met before you are able to install and use it.</p>
<ul>
<li>A webserver or web hosting account running on any major Operating System with support for PHP</li>
@@ -142,13 +142,12 @@
<li>MySQL 3.23 or above (MySQLi supported)</li>
<li>MariaDB 5.1 or above</li>
<li>PostgreSQL 8.3+</li>
- <li>SQLite 2.8.2+</li>
<li>SQLite 3.6.15+</li>
- <li>MS SQL Server 2000 or above (directly or via ODBC or the native adapter)</li>
+ <li>MS SQL Server 2000 or above (via ODBC or the native adapter)</li>
<li>Oracle</li>
</ul>
</li>
- <li><strong>PHP 5.3.3+</strong> and <strong>PHP < 7.0</strong> with support for the database you intend to use.</li>
+ <li><strong>PHP 5.4.0+</strong> with support for the database you intend to use.</li>
<li>The following PHP modules are required:
<ul>
<li>json</li>
@@ -166,7 +165,7 @@
</li>
</ul>
- <p>If your server or hosting account does not meet the requirements above then you will be unable to install phpBB 3.1.x.</p>
+ <p>If your server or hosting account does not meet the requirements above then you will be unable to install phpBB 3.2.x.</p>
</div>
@@ -192,7 +191,7 @@
<p>phpBB comes supplied with British English as its standard language. However, a number of separate packs for different languages are available. If you are not a native English speaker you may wish to install one or more of these packages before continuing. The installation process below will allow you to select a default language from those available (you can, of course, change this default at a later stage). For more details on language packs, where to obtain them and how to install them please see the <a href="README.html#i18n">README</a>.</p>
- <p>Once all the files have been uploaded to your site, you should point your browser at this location with the addition of <code>/install/</code>. For example, if your domain name is <code>www.example.com</code> and you placed the phpBB files in the directory <code>/phpBB3</code> off your web root you would enter <code>http://www.example.com/phpBB3/install/</code> or (alternatively) <code>http://www.example.com/phpBB3/install/index.php</code> into your browser. When you have done this, you should see the <strong><em>phpBB Introduction</em></strong> screen appear.</p>
+ <p>Once all the files have been uploaded to your site, you should point your browser at this location with the addition of <code>/install/</code>. For example, if your domain name is <code>www.example.com</code> and you placed the phpBB files in the directory <code>/phpBB3</code> off your web root you would enter <code>http://www.example.com/phpBB3/install/</code> or (alternatively) <code>http://www.example.com/phpBB3/install/app.php</code> into your browser. When you have done this, you should see the <strong><em>phpBB Introduction</em></strong> screen appear.</p>
<h4>Introduction:</h4>
@@ -257,7 +256,7 @@
<hr />
- <a name="update"></a><h2>4. Updating from stable releases of phpBB 3.1.x</h2>
+ <a name="update"></a><h2>4. Updating from stable releases of phpBB 3.2.x</h2>
<div class="paragraph">
<div class="inner">
@@ -272,17 +271,17 @@
<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>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> and <code>images/</code> directories in place. 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 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>You should now run <code>install/database_update.php</code> which, depending on your previous version, 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 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>Once <code>install/database_update.php</code> has completed, you may proceed to the Administration Control Panel and then remove the install directory as advised.</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>
<a name="update_files"></a><h3>4.ii. Changed files</h3>
<p>This package is meant for those wanting to only replace the files that were changed between a previous version and the latest version.</p>
- <p>This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have <strong>3.1.0</strong> you should select the appropriate <code>phpBB-3.1.1-files.zip/tar.bz2</code> file.</p>
+ <p>This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have <strong>3.2.0</strong> you should select the appropriate <code>phpBB-3.2.1-files.zip/tar.bz2</code> file.</p>
<p>The directory structure has been preserved, enabling you (if you wish) to simply upload the uncompressed contents of the archive to the appropriate location on your server, i.e. simply overwrite the existing files with the new versions. Do not forget that if you have installed any modifications (MODs) these files will overwrite the originals, possibly destroying them in the process. You will need to re-add MODs to any affected file before uploading.</p>
@@ -292,9 +291,9 @@
<p>The patch file package is for those wanting to update through the patch application, and should only be used by those who are comfortable with it.</p>
- <p>The patch file is one solution for those with many Modifications (MODs) or other changes and do not want to re-add them back to all the changed files. To use this you will need command line access to a standard UNIX type <strong>patch</strong> application. If you do not have access to such an application, but still want to use this update approach, we strongly recommend the <a href="#update_auto">Automatic update package</a> explained below. It is also the recommended update method.</p>
+ <p>The patch file is one solution for those with changes in to the phpBB core files and do not want to re-add them back to all the changed files. To use this you will need command line access to a standard UNIX type <strong>patch</strong> application. If you do not have access to such an application, but still want to use this update approach, we strongly recommend the <a href="#update_auto">Automatic update package</a> explained below. It is also the recommended update method.</p>
- <p>A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is <strong>3.1.0</strong>, you need the <code>phpBB-3.1.1-patch.zip/tar.bz2</code> file. Place the correct patch in the parent directory containing the phpBB core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: <code>patch -cl -d [PHPBB DIRECTORY] -p1 &lt; [PATCH NAME]</code> (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.</p>
+ <p>A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is <strong>3.2.0</strong>, you need the <code>phpBB-3.2.1-patch.zip/tar.bz2</code> file. Place the correct patch in the parent directory containing the phpBB core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: <code>patch -cl -d [PHPBB DIRECTORY] -p1 &lt; [PATCH NAME]</code> (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.</p>
<p>If you do get failures, you should look at using the <a href="#update_files">Changed Files</a> package to replace the files which failed to patch. Please note that you will need to manually re-add any MODs to these particular files. Alternatively, if you know how, you can examine the .rej files to determine what failed where and make manual adjustments to the relevant source.</p>
@@ -304,7 +303,7 @@
<p>This update method is the recommended method for updating. 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.1.5</strong>, you need the <code>phpBB-3.1.5_to_3.1.6.zip/tar.bz2</code> file.</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>
<p>To perform the update, either follow the instructions from the <strong>Administration Control Panel-&gt;System</strong> Tab - this should point out that you are running an outdated version and will guide you through the update - or follow the instructions listed below.</p>
@@ -322,7 +321,7 @@
<p>If you have non-English language packs installed, you may want to see if a new version has been made available. A number of missing strings may have been added which, though not essential, may be beneficial to users. Please note that at this time not all language packs have been updated so you should be prepared to periodically check for updates.</p>
- <p>These update methods will only update the standard styles, <code>prosilver</code> and <code>subsilver2</code>, any other styles you have installed for your board will usually also need to be updated.</p>
+ <p>These update methods will only update the standard style <code>prosilver</code>, any other styles you have installed for your board will usually also need to be updated.</p>
</div>
@@ -333,16 +332,16 @@
<hr />
- <a name="update30"></a><h2>5. Updating from phpBB 3.0.x to phpBB 3.1.x</h2>
+ <a name="update30_31"></a><h2>5. Updating from phpBB 3.0.x/3.1x to phpBB 3.2.x</h2>
<div class="paragraph">
<div class="inner"><span class="corners-top"><span></span></span>
<div class="content">
- <p>Updating from phpBB 3.0.x to 3.1.x is just the same as <a href="#update">updating from stable releases of phpBB 3.1.x</a></p>
+ <p>Updating from phpBB 3.0.x or 3.1.x to 3.2.x is just the same as <a href="#update">updating from stable releases of phpBB 3.2.x</a></p>
- <p>However you can also start with a new set of phpBB 3.1.x files.</p>
+ <p>However you can also start with a new set of phpBB 3.2.x files.</p>
<ol>
<li>Delete all files <strong>EXCEPT</strong> for the following:
@@ -352,10 +351,12 @@
<li>The <code>images/</code> directory</li>
<li>The <code>files/</code> directory</li>
<li>The <code>store/</code> directory</li>
+ <li>(The <code>ext/</code> directory</li>
</ul></li>
- <li>Upload the contents of the 3.1.x Full Package into your forum's directory. Make sure the root level .htaccess file is included in the upload.</li>
- <li>Browse to install/database_update.php</li>
+ <li>Upload the contents of the 3.2.x Full Package into your forum's directory. Make sure the root level .htaccess file is included in the upload.</li>
+ <li>Browse to <code>/install/app.php/update</code></li>
+ <li>Read the notice <em>Update database only</em> and press <strong>Submit</strong></li>
<li>Delete the <code>install/</code> directory</li>
</ol>
</div>
@@ -367,7 +368,7 @@
<hr />
- <a name="convert"></a><h2>6. Conversion from phpBB 2.0.x to phpBB 3.1.x</h2>
+ <a name="convert"></a><h2>6. Conversion from phpBB 2.0.x to phpBB 3.2.x</h2>
<div class="paragraph">
<div class="inner">
diff --git a/phpBB/docs/README.html b/phpBB/docs/README.html
index 38f74c199a..7fd80b3c2d 100644
--- a/phpBB/docs/README.html
+++ b/phpBB/docs/README.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="" />
-<meta name="description" content="phpBB 3.1.x Readme" />
+<meta name="description" content="phpBB 3.2.x Readme" />
<title>phpBB &bull; Readme</title>
<link href="assets/css/stylesheet.css" rel="stylesheet" type="text/css" media="screen" />
@@ -21,7 +21,7 @@
<div id="doc-description">
<a href="../index.php" id="logo"><img src="assets/images/site_logo.gif" alt="" /></a>
- <h1>phpBB 3.1.x Readme</h1>
+ <h1>phpBB 3.2.x Readme</h1>
<p style="display: none;"><a href="#start_here">Skip</a></p>
</div>
@@ -91,24 +91,23 @@
<div class="content">
<p>Installation, update and conversion instructions can be found in the <a href="INSTALL.html">INSTALL</a> document in this directory. If you are intending on converting from a phpBB 2.0.x or 3.0.x installation we highly recommend that you backup any existing data before proceeding!</p>
- <p>Users of phpBB 3.0 and 3.1 Beta versions cannot directly update.</p>
+ <p>Users of phpBB 3.0, 3.1 and 3.2 Beta versions cannot directly update.</p>
<p>Please note that we don't support the following installation types:</p>
<ul>
- <li>Updates from phpBB 3.0 Beta versions to phpBB 3.0 RC1 and higher</li>
- <li>Updates from phpBB 3.1 Beta versions to phpBB 3.1 RC1 and higher</li>
- <li>Conversions from phpBB 2.0.x to phpBB 3.0 or 3.1 Beta versions</li>
- <li>phpBB 3.0 or 3.1 Beta installations</li>
+ <li>Updates from phpBB Beta versions and lower to phpBB Release Candidates and higher</li>
+ <li>Conversions from phpBB 2.0.x to phpBB 3.0 Beta, 3.1 Beta and 3.2 Beta versions</li>
+ <li>phpBB 3.0 Beta, 3.1 Beta or 3.2 beta installations</li>
</ul>
<p>We give support for the following installation types:</p>
<ul>
- <li>Updates from phpBB 3.0 RC1 and 3.1 RC1 to the latest version</li>
+ <li>Updates from phpBB 3.0 RC1, 3.1 RC1 and 3.2 RC1 to the latest version</li>
<li>Note: if using the <em>Automatic Update Package</em>, updates are supported from phpBB 3.0.2 onward. To update a pre-3.0.2 installation, first update to 3.0.2 and then update to the current version.</li>
<li>Conversions from phpBB 2.0.x to the latest version</li>
- <li>New installations of phpBB 3.0.x - only the latest released version</li>
<li>New installations of phpBB 3.1.x - only the latest released version</li>
+ <li>New installations of phpBB 3.2.x - only the latest released version</li>
</ul>
</div>
@@ -131,7 +130,7 @@
<a name="i18n"></a><h3>2.i. Languages (Internationalisation - i18n)</h3>
- <p>A number of language packs with included style localisations are available. You can find them listed in the <a href="https://www.phpbb.com/languages/">Language Packs</a> pages of our downloads section or from the <a href="https://www.phpbb.com/customise/db/language_packs-25/">Language Packs</a> section of the <a href="https://www.phpbb.com/customise/db/">Customisation Database</a>.</p>
+ <p>A number of language packs with included style localisations are available. You can find them listed in the <a href="https://www.phpbb.com/languages/">Language Packs</a> pages of our downloads section or from the <a href="https://www.phpbb.com/customise/db/language_packs-25">Language Packs</a> section of the <a href="https://www.phpbb.com/customise/db/">Customisation Database</a>.</p>
<p>For more information about language packs, please see: <a href="https://www.phpbb.com/languages/">https://www.phpbb.com/languages/</a></p>
@@ -139,7 +138,7 @@
<p>Installation of these packages is straightforward: simply download the required language pack, uncompress (unzip) it and via FTP transfer the included <code>language</code> and <code>styles</code> folders to the root of your board installation. The language can then be installed via the Administration Control Panel of your board: <code>Customise tab -&gt; Language management -&gt; Language packs</code>. A more detailed description of the process is in the Knowledge Base article, <a href="https://www.phpbb.com/kb/article/how-to-install-a-language-pack/">How to Install a Language Pack</a>.</p>
- <p>If your language is not available, please visit our <a href="https://www.phpbb.com/community/viewforum.php?f=491">[3.1.x] Translations</a> forum where you will find topics on translations in progress. Should you wish to volunteer to translate a language not currently available or assist in maintaining an existing language pack, you can <a href="https://www.phpbb.com/languages/apply.php">Apply to become a translator</a>.</p>
+ <p>If your language is not available, please visit our <a href="https://www.phpbb.com/community/viewforum.php?f=566">[3.2.x] Translations</a> forum where you will find topics on translations in progress. Should you wish to volunteer to translate a language not currently available or assist in maintaining an existing language pack, you can <a href="https://www.phpbb.com/languages/apply.php">Apply to become a translator</a>.</p>
<a name="styles"></a><h3>2.ii. Styles</h3>
@@ -185,7 +184,7 @@
<p>Comprehensive documentation is now available on the phpBB website:</p>
- <p><a href="https://www.phpbb.com/support/docs/en/3.1/ug/">https://www.phpbb.com/support/docs/en/3.1/ug/</a></p>
+ <p><a href="https://www.phpbb.com/support/docs/en/3.2/ug/">https://www.phpbb.com/support/docs/en/3.2/ug/</a></p>
<p>This covers everything from installation to setting permissions and managing users.</p>
@@ -225,7 +224,7 @@
<div class="content">
- <p>This is a stable release of phpBB. The 3.1.x line is feature frozen, with point releases principally including fixes for bugs and security issues. Feature alterations and minor feature additions may be done if deemed absolutely required. The next major release will be phpBB 3.2 which is currently under development. Please do not post questions asking when 3.2 will be available, no release date has been set.</p>
+ <p>This is a stable release of phpBB. The 3.2.x line is feature frozen, with point releases principally including fixes for bugs and security issues. Feature alterations and minor feature additions may be done if deemed absolutely required. The next major release will be phpBB 3.3 which is currently under development. Please do not post questions asking when 3.3 will be available, no release date has been set.</p>
<p>Those interested in the development of phpBB should keep an eye on the development forums to see how things are progressing:</p>
@@ -266,15 +265,15 @@
<ul>
<li>Your server type/version, e.g. Apache 2.2.3, IIS 7, Sambar, etc.</li>
- <li>PHP version and mode of operation, e.g. PHP 5.3.3 as a module, PHP 5.4.0 running as CGI, etc.</li>
- <li>DB type/version, e.g. MySQL 5.0.77, PostgreSQL 9.0.6, MSSQL Server 2000 SP1, etc.</li>
+ <li>PHP version and mode of operation, e.g. PHP 5.4.0 as a module, PHP 5.4.0 running as CGI, etc.</li>
+ <li>DB type/version, e.g. MySQL 5.0.77, PostgreSQL 9.0.6, MSSQL Server 2000 (via ODBC), etc.</li>
</ul>
<p>The relevant database type/version is listed within the administration control panel.</p>
<p>Please be as detailed as you can in your report, and if possible, list the steps required to duplicate the problem. If you have a patch that fixes the issue, please attach it to the ticket or submit a pull request to our repository <a href="https://github.com/phpbb/phpbb">on GitHub</a>.</p>
- <p>If you create a patch, it is very much appreciated (but not required) if you follow the phpBB coding guidelines. Please note that the coding guidelines are somewhat different between different versions of phpBB. For phpBB 3.1.x the coding guidelines may be found here: <a href="http://area51.phpbb.com/docs/31x/coding-guidelines.html">http://area51.phpbb.com/docs/31x/coding-guidelines.html</a></p>
+ <p>If you create a patch, it is very much appreciated (but not required) if you follow the phpBB coding guidelines. Please note that the coding guidelines are somewhat different between different versions of phpBB. For phpBB 3.2.x the coding guidelines may be found here: <a href="http://area51.phpbb.com/docs/32x/coding-guidelines.html">http://area51.phpbb.com/docs/32x/coding-guidelines.html</a></p>
<p>Once a bug has been submitted you will be emailed any follow up comments added to it. <strong>Please</strong> if you are requested to supply additional information, do so! It is frustrating for us to receive bug reports, ask for additional information but get nothing. In these cases we have a policy of closing the bug, which may leave a very real problem in place. Obviously we would rather not have this situation arise.</p>
@@ -324,11 +323,11 @@
<div class="content">
- <p>phpBB 3.1.x takes advantage of new features added in PHP 5.3. We recommend that you upgrade to the latest stable release of PHP5 to run phpBB. The minimum version required is PHP 5.3.3 and the maximum supported version is any version prior to PHP 7.0.</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.0 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, MSSQL Server 2000, PostgreSQL 8.x, Oracle 8, SQLite 2 and SQLite 3. Versions of PHP used range from 5.3.x to 5.4.x without problem.</p>
+ <p>This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, 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>
<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 56b71006c7..9b5c668880 100644
--- a/phpBB/docs/coding-guidelines.html
+++ b/phpBB/docs/coding-guidelines.html
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="" />
-<meta name="description" content="Ascraeus coding guidelines document" />
+<meta name="description" content="Rhea coding guidelines document" />
<title>phpBB3 &bull; Coding Guidelines</title>
<link href="assets/css/stylesheet.css" rel="stylesheet" type="text/css" media="screen" />
@@ -22,7 +22,7 @@
<div id="doc-description">
<a href="../index.php" id="logo"><img src="assets/images/site_logo.gif" alt="" /></a>
<h1>Coding Guidelines</h1>
- <p>Ascraeus coding guidelines document</p>
+ <p>Rhea coding guidelines document</p>
<p style="display: none;"><a href="#start_here">Skip</a></p>
</div>
@@ -37,7 +37,7 @@
<!-- BEGIN DOCUMENT -->
<p class="paragraph main-description">
- These are the phpBB Coding Guidelines for Ascraeus, all attempts should be made to follow them as closely as possible.
+ These are the phpBB Coding Guidelines for Rhea, all attempts should be made to follow them as closely as possible.
</p>
<h1>Coding Guidelines</h1>
@@ -1184,8 +1184,8 @@ append_sid(&quot;{$phpbb_root_path}memberlist.$phpEx&quot;, 'mode=group&amp;amp;
# General Information about this style
name = prosilver_duplicate
copyright = © phpBB Limited, 2007
-style_version = 3.1.0
-phpbb_version = 3.1.0
+style_version = 3.2.0
+phpbb_version = 3.2.0
# Defining a different template bitfield
# template_bitfield = lNg=
@@ -1674,8 +1674,8 @@ div
# General Information about this style
name = Custom Style
copyright = © phpBB Limited, 2007
-style_version = 3.1.0-b1
-phpbb_version = 3.1.0-b1
+style_version = 3.2.0-b1
+phpbb_version = 3.2.0-b1
# Defining a different template bitfield
# template_bitfield = lNg=
@@ -1722,7 +1722,7 @@ This may span multiple lines.
+ first/file/path.html
+ second/file/path.html
* Purpose: Same as above.
-* Since: 3.1.0-b1
+* Since: 3.2.0-b1
</pre></div>
<li>An event that is found multiple times in a file should have the number of instances in parenthesis next to the filename.
<div class="codebox"><pre>event_name
@@ -1731,7 +1731,7 @@ This may span multiple lines.
+ first/file/path.html (2)
+ second/file/path.html
* Purpose: Same as above.
-* Since: 3.1.0-b1
+* Since: 3.2.0-b1
</pre></div></li>
<li>An actual example event documentation:
<div class="codebox"><pre>forumlist_body_last_post_title_prepend
@@ -1740,7 +1740,7 @@ This may span multiple lines.
+ styles/prosilver/template/forumlist_body.html
+ styles/subsilver2/template/forumlist_body.html
* Purpose: Add content before the post title of the latest post in a forum on the forum list.
-* Since: 3.1.0-a1
+* Since: 3.2.0-a1
</pre></div></ul><br />
</div>
diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md
index 0ebaf8f3e0..a939c6ff7e 100644
--- a/phpBB/docs/events.md
+++ b/phpBB/docs/events.md
@@ -564,7 +564,6 @@ attachment_file_after
===
* Locations:
+ styles/prosilver/template/attachment.html
- + styles/subsilver2/template/attachment.html
* Since: 3.1.6-RC1
* Purpose: Add content after the attachment.
@@ -572,7 +571,6 @@ attachment_file_append
===
* Locations:
+ styles/prosilver/template/attachment.html
- + styles/subsilver2/template/attachment.html
* Since: 3.1.6-RC1
* Purpose: Add custom attachment types displaying to the bottom of attachment block.
@@ -580,7 +578,6 @@ attachment_file_before
===
* Locations:
+ styles/prosilver/template/attachment.html
- + styles/subsilver2/template/attachment.html
* Since: 3.1.6-RC1
* Purpose: Add content before the attachment.
@@ -588,7 +585,6 @@ attachment_file_prepend
===
* Locations:
+ styles/prosilver/template/attachment.html
- + styles/subsilver2/template/attachment.html
* Since: 3.1.6-RC1
* Purpose: Add custom attachment types displaying to the top of attachment block.
@@ -596,7 +592,6 @@ forumlist_body_category_header_after
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-a4
* Purpose: Add content after the header of the category on the forum list.
@@ -604,7 +599,6 @@ forumlist_body_category_header_before
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-a4
* Purpose: Add content before the header of the category on the forum list.
@@ -626,7 +620,6 @@ forumlist_body_forum_row_after
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-RC5
* Purpose: Add content after the forum list item.
@@ -634,7 +627,6 @@ forumlist_body_forum_row_append
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-RC5
* Purpose: Add content at the start of the forum list item.
@@ -642,7 +634,6 @@ forumlist_body_forum_row_before
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-RC5
* Purpose: Add content before the forum list item.
@@ -650,7 +641,6 @@ forumlist_body_forum_row_prepend
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-RC5
* Purpose: Add content at the end of the forum list item.
@@ -658,7 +648,6 @@ forumlist_body_last_post_title_prepend
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-a1
* Purpose: Add content before the post title of the latest post in a forum on the forum list.
@@ -666,7 +655,6 @@ forumlist_body_subforums_after
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-a4
* Purpose: Add content after the list of subforums (if any) for each forum on the forum list.
@@ -674,7 +662,6 @@ forumlist_body_subforums_before
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-a4
* Purpose: Add content before the list of subforums (if any) for each forum on the forum list.
@@ -682,7 +669,6 @@ forumlist_body_last_row_after
===
* Locations:
+ styles/prosilver/template/forumlist_body.html
- + styles/subsilver2/template/forumlist_body.html
* Since: 3.1.0-b2
* Purpose: Add content after the very last row of the forum list.
@@ -690,7 +676,6 @@ index_body_block_birthday_append
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Append content to the birthday list on the Board index
@@ -698,7 +683,6 @@ index_body_block_birthday_prepend
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Prepend content to the birthday list on the Board index
@@ -706,7 +690,6 @@ index_body_block_online_append
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Append content to the online list on the Board index
@@ -714,7 +697,6 @@ index_body_block_online_prepend
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Prepend content to the online list on the Board index
@@ -722,7 +704,6 @@ index_body_block_stats_append
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Append content to the statistics list on the Board index
@@ -730,7 +711,6 @@ index_body_block_stats_prepend
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Prepend content to the statistics list on the Board index
@@ -738,7 +718,6 @@ index_body_forumlist_body_after
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.1
* Purpose: Add content after the forum list body on the index page
@@ -746,7 +725,6 @@ index_body_markforums_after
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-RC2
* Purpose: Add content after the mark-read link above the forum list on Board index
@@ -754,7 +732,6 @@ index_body_markforums_before
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-RC2
* Purpose: Add content before the mark-read link above the forum list on Board index
@@ -762,7 +739,6 @@ index_body_stat_blocks_after
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Add new statistic blocks below the Who Is Online and Board Statistics blocks
@@ -770,7 +746,6 @@ index_body_stat_blocks_before
===
* Locations:
+ styles/prosilver/template/index_body.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-a1
* Purpose: Add new statistic blocks above the Who Is Online and Board Statistics blocks
@@ -778,7 +753,6 @@ mcp_ban_fields_after
===
* Locations:
+ styles/prosilver/template/mcp_ban.html
- + styles/subsilver2/template/mcp_ban.html
* Since: 3.1.0-RC3
* Purpose: Add additional fields to the ban form in MCP
@@ -786,7 +760,6 @@ mcp_ban_fields_before
===
* Locations:
+ styles/prosilver/template/mcp_ban.html
- + styles/subsilver2/template/mcp_ban.html
* Since: 3.1.0-RC3
* Purpose: Add additional fields to the ban form in MCP
@@ -794,7 +767,6 @@ mcp_ban_unban_after
===
* Locations:
+ styles/prosilver/template/mcp_ban.html
- + styles/subsilver2/template/mcp_ban.html
* Since: 3.1.0-RC3
* Purpose: Add additional fields to the unban form in MCP
@@ -802,7 +774,6 @@ mcp_ban_unban_before
===
* Locations:
+ styles/prosilver/template/mcp_ban.html
- + styles/subsilver2/template/mcp_ban.html
* Since: 3.1.0-RC3
* Purpose: Add additional fields to the unban form in MCP
@@ -810,7 +781,6 @@ mcp_forum_actions_after
===
* Locations:
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.11-RC1
* Purpose: Add some information after actions fieldset
@@ -818,7 +788,6 @@ mcp_forum_actions_before
===
* Locations:
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.11-RC1
* Purpose: Add some information before actions fieldset
@@ -826,7 +795,6 @@ mcp_forum_topic_title_before
===
* Locations:
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.6-RC1
* Purpose: Add some information before the topic title
@@ -834,7 +802,6 @@ mcp_forum_topic_title_after
===
* Locations:
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.6-RC1
* Purpose: Add some information after the topic title
@@ -842,7 +809,6 @@ mcp_front_latest_logs_after
===
* Locations:
+ styles/prosilver/template/mcp_front.html
- + styles/subsilver2/template/mcp_front.html
* Since: 3.1.3-RC1
* Purpose: Add content after latest logs list
@@ -850,7 +816,6 @@ mcp_front_latest_logs_before
===
* Locations:
+ styles/prosilver/template/mcp_front.html
- + styles/subsilver2/template/mcp_front.html
* Since: 3.1.3-RC1
* Purpose: Add content before latest logs list
@@ -858,7 +823,6 @@ mcp_front_latest_reported_before
===
* Locations:
+ styles/prosilver/template/mcp_front.html
- + styles/subsilver2/template/mcp_front.html
* Since: 3.1.3-RC1
* Purpose: Add content before latest reported posts list
@@ -866,7 +830,6 @@ mcp_front_latest_reported_pms_before
===
* Locations:
+ styles/prosilver/template/mcp_front.html
- + styles/subsilver2/template/mcp_front.html
* Since: 3.1.3-RC1
* Purpose: Add content before latest reported private messages list
@@ -874,7 +837,6 @@ mcp_front_latest_unapproved_before
===
* Locations:
+ styles/prosilver/template/mcp_front.html
- + styles/subsilver2/template/mcp_front.html
* Since: 3.1.3-RC1
* Purpose: Add content before latest unapproved posts list
@@ -882,7 +844,6 @@ mcp_move_before
===
* Locations:
+ styles/prosilver/template/mcp_move.html
- + styles/subsilver2/template/mcp_move.html
* Since: 3.1.10-RC1
* Purpose: Add content before move topic/post form
@@ -890,7 +851,6 @@ mcp_post_additional_options
===
* Locations:
+ styles/prosilver/template/mcp_post.html
- + styles/subsilver2/template/mcp_post.html
* Since: 3.1.5-RC1
* Purpose: Add content within the list of post moderation actions
@@ -898,7 +858,6 @@ mcp_topic_options_after
===
* Locations:
+ styles/prosilver/template/mcp_topic.html
- + styles/subsilver2/template/mcp_topic.html
* Since: 3.1.6-RC1
* Purpose: Add some options (field, checkbox, ...) after the subject field when split a subject
@@ -906,7 +865,6 @@ mcp_topic_options_before
===
* Locations:
+ styles/prosilver/template/mcp_topic.html
- + styles/subsilver2/template/mcp_topic.html
* Since: 3.1.6-RC1
* Purpose: Add some options (field, checkbox, ...) before the subject field when split a subject
@@ -914,7 +872,6 @@ mcp_topic_postrow_post_details_after
===
* Locations:
+ styles/prosilver/template/mcp_topic.html
- + styles/subsilver2/template/mcp_topic.html
* Since: 3.1.10-RC1
* Purpose: Add content after post details in topic moderation
@@ -922,7 +879,6 @@ mcp_topic_postrow_post_details_before
===
* Locations:
+ styles/prosilver/template/mcp_topic.html
- + styles/subsilver2/template/mcp_topic.html
* Since: 3.1.10-RC1
* Purpose: Add content before post details in topic moderation
@@ -930,7 +886,6 @@ mcp_topic_topic_title_after
===
* Locations:
+ styles/prosilver/template/mcp_topic.html
- + styles/subsilver2/template/mcp_topic.html
* Since: 3.1.6-RC1
* Purpose: Add some information after the topic title
@@ -938,7 +893,6 @@ mcp_topic_topic_title_before
===
* Locations:
+ styles/prosilver/template/mcp_topic.html
- + styles/subsilver2/template/mcp_topic.html
* Since: 3.1.6-RC1
* Purpose: Add some information before the topic title
@@ -946,7 +900,6 @@ mcp_warn_post_add_warning_field_after
===
* Locations:
+ styles/prosilver/template/mcp_warn_post.html
- + styles/subsilver2/template/mcp_warn_post.html
* Since: 3.1.0-RC4
* Purpose: Add content during warning for a post - after add warning field.
@@ -954,7 +907,6 @@ mcp_warn_post_add_warning_field_before
===
* Locations:
+ styles/prosilver/template/mcp_warn_post.html
- + styles/subsilver2/template/mcp_warn_post.html
* Since: 3.1.0-RC4
* Purpose: Add content during warning for a post - before add warning field.
@@ -962,7 +914,6 @@ mcp_warn_user_add_warning_field_after
===
* Locations:
+ styles/prosilver/template/mcp_warn_user.html
- + styles/subsilver2/template/mcp_warn_user.html
* Since: 3.1.0-RC4
* Purpose: Add content during warning a user - after add warning field.
@@ -970,7 +921,6 @@ mcp_warn_user_add_warning_field_before
===
* Locations:
+ styles/prosilver/template/mcp_warn_user.html
- + styles/subsilver2/template/mcp_warn_user.html
* Since: 3.1.0-RC4
* Purpose: Add content during warning a user - before add warning field.
@@ -978,7 +928,6 @@ memberlist_body_rank_append
===
* Locations:
+ styles/prosilver/template/memberlist_body.html
- + styles/subsilver2/template/memberlist_body.html
* Since: 3.1.6-RC1
* Purpose: Add information after rank in memberlist. Works in
all display modes (leader, group and normal memberlist).
@@ -987,7 +936,6 @@ memberlist_body_rank_prepend
===
* Locations:
+ styles/prosilver/template/memberlist_body.html
- + styles/subsilver2/template/memberlist_body.html
* Since: 3.1.6-RC1
* Purpose: Add information before rank in memberlist. Works in
all display modes (leader, group and normal memberlist).
@@ -996,7 +944,6 @@ memberlist_body_username_append
===
* Locations:
+ styles/prosilver/template/memberlist_body.html
- + styles/subsilver2/template/memberlist_body.html
* Since: 3.1.0-a1
* Purpose: Add information after every username in the memberlist. Works in
all display modes (leader, group and normal memberlist).
@@ -1005,7 +952,6 @@ memberlist_body_username_prepend
===
* Locations:
+ styles/prosilver/template/memberlist_body.html
- + styles/subsilver2/template/memberlist_body.html
* Since: 3.1.0-a1
* Purpose: Add information before every username in the memberlist. Works in
all display modes (leader, group and normal memberlist).
@@ -1014,7 +960,6 @@ memberlist_email_before
===
* Locations:
+ styles/prosilver/template/memberlist_email.html
- + styles/subsilver2/template/memberlist_email.html
* Since: 3.1.10-RC1
* Purpose: Allow adding customizations before the memberlist_email form.
@@ -1022,7 +967,6 @@ memberlist_search_fields_after
===
* Locations:
+ styles/prosilver/template/memberlist_search.html
- + styles/subsilver2/template/memberlist_search.html
* Since: 3.1.2-RC1
* Purpose: Add information after the search fields column.
@@ -1030,7 +974,6 @@ memberlist_search_fields_before
===
* Locations:
+ styles/prosilver/template/memberlist_search.html
- + styles/subsilver2/template/memberlist_search.html
* Since: 3.1.2-RC1
* Purpose: Add information before the search fields column.
@@ -1038,7 +981,6 @@ memberlist_search_sorting_options_before
===
* Locations:
+ styles/prosilver/template/memberlist_search.html
- + styles/subsilver2/template/memberlist_search.html
* Since: 3.1.2-RC1
* Purpose: Add information before the search sorting options field.
@@ -1046,7 +988,6 @@ memberlist_view_contact_after
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.0-b2
* Purpose: Add content after the user contact part of any user profile
@@ -1054,7 +995,6 @@ memberlist_view_contact_before
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.0-b2
* Purpose: Add content before the user contact part of any user profile
@@ -1062,7 +1002,6 @@ memberlist_view_contact_custom_fields_after
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.9-RC1
* Purpose: Add content after the user contact related custom fields
@@ -1070,7 +1009,6 @@ memberlist_view_contact_custom_fields_before
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.9-RC1
* Purpose: Add content before the user contact related custom fields
@@ -1078,7 +1016,6 @@ memberlist_view_content_append
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.0-b2
* Purpose: Add custom content to the user profile view after the main content
@@ -1086,7 +1023,6 @@ memberlist_view_content_prepend
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.0-b3
* Purpose: Add custom content to the user profile view before the main content
@@ -1094,7 +1030,6 @@ memberlist_view_non_contact_custom_fields_after
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.9-RC1
* Purpose: Add content after the user not contact related custom fields
@@ -1102,17 +1037,9 @@ memberlist_view_non_contact_custom_fields_before
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.9-RC1
* Purpose: Add content before the user not contact related custom fields
-memberlist_view_rank_after
-===
-* Locations:
- + styles/subsilver2/template/memberlist_view.html
-* Since: 3.1.6-RC1
-* Purpose: Add information after rank in memberlist
-
memberlist_view_rank_avatar_after
===
* Locations:
@@ -1127,13 +1054,6 @@ memberlist_view_rank_avatar_before
* Since: 3.1.6-RC1
* Purpose: Add information before rank in memberlist (with avatar)
-memberlist_view_rank_before
-===
-* Locations:
- + styles/subsilver2/template/memberlist_view.html
-* Since: 3.1.6-RC1
-* Purpose: Add information after rank in memberlist
-
memberlist_view_rank_no_avatar_after
===
* Locations:
@@ -1152,7 +1072,6 @@ memberlist_view_user_statistics_after
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.0-a1
* Purpose: Add entries after the user statistics part of any user profile
@@ -1160,7 +1079,6 @@ memberlist_view_user_statistics_before
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.0-a1
* Purpose: Add entries before the user statistics part of any user profile
@@ -1168,7 +1086,6 @@ memberlist_view_zebra_after
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.9-RC1
* Purpose: Add content after the user friends/foes links
@@ -1176,7 +1093,6 @@ memberlist_view_zebra_before
===
* Locations:
+ styles/prosilver/template/memberlist_view.html
- + styles/subsilver2/template/memberlist_view.html
* Since: 3.1.9-RC1
* Purpose: Add content before the user friends/foes links
@@ -1247,7 +1163,6 @@ overall_footer_after
===
* Locations:
+ styles/prosilver/template/overall_footer.html
- + styles/subsilver2/template/overall_footer.html
* Since: 3.1.0-a1
* Purpose: Add content at the end of the file, directly prior to the `</body>` tag
@@ -1255,7 +1170,6 @@ overall_footer_body_after
===
* Locations:
+ styles/prosilver/template/overall_footer.html
- + styles/subsilver2/template/overall_footer.html
* Since: 3.1.3-RC1
* Purpose: Add content before the `</body>` tag but after the $SCRIPTS var, i.e. after the js scripts have been loaded
@@ -1263,7 +1177,6 @@ overall_footer_breadcrumb_append
===
* Locations:
+ styles/prosilver/template/navbar_footer.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-a1
* Purpose: Add links to the list of breadcrumbs in the footer
@@ -1271,7 +1184,6 @@ overall_footer_breadcrumb_prepend
===
* Locations:
+ styles/prosilver/template/navbar_footer.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-RC3
* Purpose: Add links to the list of breadcrumbs in the footer (after site-home, but before board-index)
@@ -1279,7 +1191,6 @@ overall_footer_content_after
===
* Locations:
+ styles/prosilver/template/overall_footer.html
- + styles/subsilver2/template/overall_footer.html
* Since: 3.1.0-a3
* Purpose: Add content on all pages after the main content, before the footer
@@ -1287,7 +1198,6 @@ overall_footer_copyright_append
===
* Locations:
+ styles/prosilver/template/overall_footer.html
- + styles/subsilver2/template/overall_footer.html
* Since: 3.1.0-a1
* Purpose: Add content after the copyright line (no new line by default), before the ACP link
@@ -1295,7 +1205,6 @@ overall_footer_copyright_prepend
===
* Locations:
+ styles/prosilver/template/overall_footer.html
- + styles/subsilver2/template/overall_footer.html
* Since: 3.1.0-a1
* Purpose: Add content before the copyright line
@@ -1303,7 +1212,6 @@ overall_footer_page_body_after
===
* Locations:
+ styles/prosilver/template/overall_footer.html
- + styles/subsilver2/template/overall_footer.html
* Since: 3.1.0-b3
* Purpose: Add content after the page-body, but before the footer
@@ -1311,7 +1219,6 @@ overall_footer_teamlink_after
===
* Locations:
+ styles/prosilver/template/navbar_footer.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Add contents after the team-link in the footer
@@ -1319,7 +1226,6 @@ overall_footer_teamlink_before
===
* Locations:
+ styles/prosilver/template/navbar_footer.html
- + styles/subsilver2/template/index_body.html
* Since: 3.1.0-b3
* Purpose: Add contents before the team-link in the footer
@@ -1327,7 +1233,6 @@ overall_footer_timezone_after
===
* Locations:
+ styles/prosilver/template/navbar_footer.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-b3
* Purpose: Add content to the navbar in the page footer, after "Timezone"
@@ -1335,7 +1240,6 @@ overall_footer_timezone_before
===
* Locations:
+ styles/prosilver/template/navbar_footer.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-b3
* Purpose: Add content to the navbar in the page footer, before "Timezone"
@@ -1343,7 +1247,6 @@ overall_header_body_before
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-b2
* Purpose: Add content to the header body
@@ -1351,7 +1254,6 @@ overall_header_breadcrumb_append
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-a1
* Purpose: Add links to the list of breadcrumbs in the header
@@ -1359,7 +1261,6 @@ overall_header_breadcrumb_prepend
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-RC3
* Purpose: Add links to the list of breadcrumbs in the header (after site-home, but before board-index)
@@ -1367,7 +1268,6 @@ overall_header_breadcrumbs_after
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-RC3
* Purpose: Add content after the breadcrumbs (outside of the breadcrumbs container)
@@ -1375,7 +1275,6 @@ overall_header_breadcrumbs_before
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-RC3
* Purpose: Add content before the breadcrumbs (outside of the breadcrumbs container)
@@ -1383,7 +1282,6 @@ overall_header_content_before
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-a3
* Purpose: Add content on all pages before the main content, after the header
@@ -1391,7 +1289,6 @@ overall_header_feeds
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.6-RC1
* Purpose: Add custom feeds
@@ -1399,7 +1296,6 @@ overall_header_head_append
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-a1
* Purpose: Add asset calls directly before the `</head>` tag
@@ -1421,7 +1317,6 @@ overall_header_navbar_before
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.4-RC1
* Purpose: Add content before the navigation bar
@@ -1429,7 +1324,6 @@ overall_header_navigation_append
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-a1
* Purpose: Add links after the navigation links in the header
@@ -1437,7 +1331,6 @@ overall_header_navigation_prepend
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-a1
* Purpose: Add links before the navigation links in the header
@@ -1445,7 +1338,6 @@ overall_header_navlink_append
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-b3
* Purpose: Add content after each individual navlink (breadcrumb)
@@ -1453,7 +1345,6 @@ overall_header_navlink_prepend
===
* Locations:
+ styles/prosilver/template/navbar_header.html
- + styles/subsilver2/template/breadcrumbs.html
* Since: 3.1.0-b3
* Purpose: Add content before each individual navlink (breadcrumb)
@@ -1461,7 +1352,6 @@ overall_header_page_body_before
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-b3
* Purpose: Add content after the page-header, but before the page-body
@@ -1483,7 +1373,6 @@ overall_header_stylesheets_after
===
* Locations:
+ styles/prosilver/template/overall_header.html
- + styles/subsilver2/template/overall_header.html
* Since: 3.1.0-RC3
* Purpose: Add asset calls after stylesheets within the `</head>` tag.
Note that INCLUDECSS will not work with this event.
@@ -1499,7 +1388,6 @@ posting_editor_bbcode_status_after
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.4-RC1
* Purpose: Add content after bbcode status
@@ -1507,7 +1395,6 @@ posting_editor_buttons_after
===
* Locations:
+ styles/prosilver/template/posting_buttons.html
- + styles/subsilver2/template/posting_buttons.html
* Since: 3.1.0-a3
* Purpose: Add content after the BBCode posting buttons
@@ -1515,7 +1402,6 @@ posting_editor_buttons_before
===
* Locations:
+ styles/prosilver/template/posting_buttons.html
- + styles/subsilver2/template/posting_buttons.html
* Since: 3.1.0-a3
* Purpose: Add content before the BBCode posting buttons
@@ -1523,7 +1409,6 @@ posting_editor_buttons_custom_tags_before
===
* Locations:
+ styles/prosilver/template/posting_buttons.html
- + styles/subsilver2/template/posting_buttons.html
* Since: 3.1.2-RC1
* Purpose: Add content inside the BBCode posting buttons and before the customs BBCode
@@ -1531,7 +1416,6 @@ posting_editor_message_after
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.0-a2
* Purpose: Add field (e.g. textbox) to the posting screen after the message
@@ -1539,7 +1423,6 @@ posting_editor_message_before
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.0-a2
* Purpose: Add field (e.g. textbox) to the posting screen before the message
@@ -1547,7 +1430,6 @@ posting_editor_options_prepend
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.0-a1
* Purpose: Add posting options on the posting screen
@@ -1555,7 +1437,6 @@ posting_editor_smilies_after
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.4-RC1
* Purpose: Add content after smilies
@@ -1563,7 +1444,6 @@ posting_editor_smilies_before
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.4-RC1
* Purpose: Add content before the smilies
@@ -1571,7 +1451,6 @@ posting_editor_subject_after
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.0-a2
* Purpose: Add field (e.g. textbox) to the posting screen after the subject
@@ -1579,7 +1458,6 @@ posting_editor_subject_append
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.10-RC1
* Purpose: Add field, text, etc. to the posting after the subject text box
@@ -1587,7 +1465,6 @@ posting_editor_subject_before
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.0-a2
* Purpose: Add field (e.g. textbox) to the posting screen before the subject
@@ -1595,7 +1472,6 @@ posting_editor_subject_prepend
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.10-RC1
* Purpose: Add field, text, etc. to the posting before the subject text box
@@ -1603,7 +1479,6 @@ posting_editor_submit_buttons
===
* Locations:
+ styles/prosilver/template/posting_editor.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.6-RC1
* Purpose: Add custom buttons in the posting editor
@@ -1618,7 +1493,6 @@ posting_pm_header_find_username_after
===
* Locations:
+ styles/prosilver/template/posting_pm_header.html
- + styles/subsilver2/template/ucp_header.html
* Since: 3.1.0-RC4
* Purpose: Add content after the find username link on composing pm
@@ -1626,7 +1500,6 @@ posting_pm_header_find_username_before
===
* Locations:
+ styles/prosilver/template/posting_pm_header.html
- + styles/subsilver2/template/ucp_header.html
* Since: 3.1.0-RC4
* Purpose: Add content before the find username link on composing pm
@@ -1648,7 +1521,6 @@ posting_poll_body_options_after
===
* Locations:
+ styles/prosilver/template/posting_poll_body.html
- + styles/subsilver2/template/posting_poll_body.html
* Since: 3.1.4-RC1
* Purpose: Add content after the poll options on creating a poll
@@ -1656,7 +1528,6 @@ posting_preview_poll_after
===
* Locations:
+ styles/prosilver/template/posting_preview.html
- + styles/subsilver2/template/posting_preview.html
* Since: 3.1.7-RC1
* Purpose: Add content after the poll preview block
@@ -1664,7 +1535,6 @@ posting_topic_review_row_post_details_after
===
* Locations:
+ styles/prosilver/template/posting_topic_review.html
- + styles/subsilver2/template/posting_topic_review.html
* Since: 3.1.10-RC1
* Purpose: Add content after post details in topic review
@@ -1672,7 +1542,6 @@ posting_topic_review_row_post_details_before
===
* Locations:
+ styles/prosilver/template/posting_topic_review.html
- + styles/subsilver2/template/posting_topic_review.html
* Since: 3.1.10-RC1
* Purpose: Add content before post details in topic review
@@ -1680,7 +1549,6 @@ posting_topic_title_after
===
* Locations:
+ styles/prosilver/template/posting_layout.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.7-RC1
* Purpose: Allows to add some information after the topic title in the posting form
@@ -1688,7 +1556,6 @@ posting_topic_title_before
===
* Locations:
+ styles/prosilver/template/posting_layout.html
- + styles/subsilver2/template/posting_body.html
* Since: 3.1.6-RC1
* Purpose: Allows to add some information on the left of the topic title in the posting form
@@ -1696,7 +1563,6 @@ quickreply_editor_panel_after
===
* Locations:
+ styles/prosilver/template/quickreply_editor.html
- + styles/subsilver2/template/quickreply_editor.html
* Since: 3.1.0-b2
* Purpose: Add content after the quick reply panel (but inside the form)
@@ -1704,7 +1570,6 @@ quickreply_editor_panel_before
===
* Locations:
+ styles/prosilver/template/quickreply_editor.html
- + styles/subsilver2/template/quickreply_editor.html
* Since: 3.1.0-b2
* Purpose: Add content before the quick reply panel (but inside the form)
@@ -1712,7 +1577,6 @@ quickreply_editor_message_after
===
* Locations:
+ styles/prosilver/template/quickreply_editor.html
- + styles/subsilver2/template/quickreply_editor.html
* Since: 3.1.0-a4
* Purpose: Add content after the quick reply textbox
@@ -1720,7 +1584,6 @@ quickreply_editor_message_before
===
* Locations:
+ styles/prosilver/template/quickreply_editor.html
- + styles/subsilver2/template/quickreply_editor.html
* Since: 3.1.0-a4
* Purpose: Add content before the quick reply textbox
@@ -1728,7 +1591,6 @@ quickreply_editor_subject_before
===
* Locations:
+ styles/prosilver/template/quickreply_editor.html
- + styles/subsilver2/template/quickreply_editor.html
* Since: 3.1.7-RC1
* Purpose: Add content before the quick reply subject textbox
@@ -1736,7 +1598,6 @@ search_body_form_after
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content after the search form
@@ -1744,7 +1605,6 @@ search_body_form_before
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.5-RC1
* Purpose: Add content before the search form
@@ -1752,7 +1612,6 @@ search_body_recent_search_after
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content after the recent search queries list
@@ -1760,7 +1619,6 @@ search_body_recent_search_before
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content before the recent search queries list
@@ -1768,7 +1626,6 @@ search_body_search_display_options_append
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Put content at the bottom of the search query display options fields set
@@ -1776,7 +1633,6 @@ search_body_search_display_options_prepend
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Put content at the top of the search query display options fields set
@@ -1784,7 +1640,6 @@ search_body_search_options_after
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content after the search query options fields set
@@ -1792,7 +1647,6 @@ search_body_search_options_append
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Put content at the bottom of the search query options fields set
@@ -1800,7 +1654,6 @@ search_body_search_options_before
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content before the search query options fields set
@@ -1808,7 +1661,6 @@ search_body_search_options_prepend
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Put content at the top of the search query options fields set
@@ -1816,7 +1668,6 @@ search_body_search_query_after
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content after the search query fields set
@@ -1824,7 +1675,6 @@ search_body_search_query_append
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Put content at the bottom of the search query fields set
@@ -1832,7 +1682,6 @@ search_body_search_query_before
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Add content before the search query fields set
@@ -1840,7 +1689,6 @@ search_body_search_query_prepend
===
* Locations:
+ styles/prosilver/template/search_body.html
- + styles/subsilver2/template/search_body.html
* Since: 3.1.7-RC1
* Purpose: Put content at the top of the search query fields set
@@ -1848,7 +1696,6 @@ search_results_header_after
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.4-RC1
* Purpose: Add content after the header of the search results
@@ -1856,7 +1703,6 @@ search_results_header_before
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.4-RC1
* Purpose: Add content before the header of the search results.
@@ -1864,7 +1710,6 @@ search_results_post_after
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.0-b3
* Purpose: Add data after search result posts
@@ -1872,7 +1717,6 @@ search_results_post_before
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.0-b3
* Purpose: Add data before search result posts
@@ -1894,7 +1738,6 @@ search_results_searchbox_after
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.4-RC1
* Purpose: Add content right after the searchbox of the search results.
@@ -1902,7 +1745,6 @@ search_results_topic_after
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.0-b4
* Purpose: Add data after search result topics
@@ -1910,7 +1752,6 @@ search_results_topic_before
===
* Locations:
+ styles/prosilver/template/search_results.html
- + styles/subsilver2/template/search_results.html
* Since: 3.1.0-b4
* Purpose: Add data before search result topics
@@ -1918,7 +1759,6 @@ simple_footer_after
===
* Locations:
+ styles/prosilver/template/simple_footer.html
- + styles/subsilver2/template/simple_footer.html
* Since: 3.1.0-a1
* Purpose: Add content directly prior to the `</body>` tag of the simple footer
@@ -1926,7 +1766,6 @@ simple_header_body_before
===
* Locations:
+ styles/prosilver/template/simple_header.html
- + styles/subsilver2/template/simple_header.html
* Since: 3.1.0-b2
* Purpose: Add content to the header body
@@ -1934,7 +1773,6 @@ simple_header_head_append
===
* Locations:
+ styles/prosilver/template/simple_header.html
- + styles/subsilver2/template/simple_header.html
* Since: 3.1.0-b4
* Purpose: Add asset calls directly before the `</head>` tag
@@ -1942,7 +1780,6 @@ simple_header_stylesheets_after
===
* Locations:
+ styles/prosilver/template/simple_header.html
- + styles/subsilver2/template/simple_header.html
* Since: 3.1.0-RC3
* Purpose: Add asset calls after stylesheets within the `</head>` tag.
Note that INCLUDECSS will not work with this event.
@@ -1953,9 +1790,6 @@ topiclist_row_prepend
+ styles/prosilver/template/search_results.html
+ styles/prosilver/template/viewforum_body.html
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/search_results.html
- + styles/subsilver2/template/viewforum_body.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.0-a1
* Changed: 3.1.6-RC1 Added event to mcp_forum.html
* Purpose: Add content into topic rows (inside the elements containing topic titles)
@@ -1966,9 +1800,6 @@ topiclist_row_append
+ styles/prosilver/template/search_results.html
+ styles/prosilver/template/viewforum_body.html
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/search_results.html
- + styles/subsilver2/template/viewforum_body.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.0-a1
* Changed: 3.1.6-RC1 Added event to mcp_forum.html
* Purpose: Add content into topic rows (inside the elements containing topic titles)
@@ -1979,9 +1810,6 @@ topiclist_row_topic_title_after
+ styles/prosilver/template/search_results.html
+ styles/prosilver/template/viewforum_body.html
+ styles/prosilver/template/mcp_forum.html
- + styles/subsilver2/template/search_results.html
- + styles/subsilver2/template/viewforum_body.html
- + styles/subsilver2/template/mcp_forum.html
* Since: 3.1.10-RC1
* Purpose: Add content into topic rows (after the elements containing the topic titles)
@@ -1989,7 +1817,6 @@ ucp_agreement_terms_after
===
* Locations:
+ styles/prosilver/template/ucp_agreement.html
- + styles/subsilver2/template/ucp_agreement.html
* Since: 3.1.0-b3
* Purpose: Add content after the terms of agreement text at user registration
@@ -1997,7 +1824,6 @@ ucp_agreement_terms_before
===
* Locations:
+ styles/prosilver/template/ucp_agreement.html
- + styles/subsilver2/template/ucp_agreement.html
* Since: 3.1.0-b3
* Purpose: Add content before the terms of agreement text at user registration
@@ -2005,7 +1831,6 @@ ucp_main_front_user_activity_after
===
* Locations:
+ styles/prosilver/template/ucp_main_front.html
- + styles/subsilver2/template/ucp_main_front.html
* Since: 3.1.6-RC1
* Purpose: Add content right after the user activity info viewing UCP front page
@@ -2013,7 +1838,6 @@ ucp_main_front_user_activity_before
===
* Locations:
+ styles/prosilver/template/ucp_main_front.html
- + styles/subsilver2/template/ucp_main_front.html
* Since: 3.1.6-RC1
* Purpose: Add content right before the user activity info viewing UCP front page
@@ -2021,7 +1845,6 @@ ucp_pm_history_post_buttons_after
===
* Locations:
+ styles/prosilver/template/ucp_pm_history.html
- + styles/subsilver2/template/ucp_pm_history.html
* Since: 3.1.6-RC1
* Purpose: Add post button to private messages in history review (next to quote etc), at
the end of the list.
@@ -2030,7 +1853,6 @@ ucp_pm_history_post_buttons_before
===
* Locations:
+ styles/prosilver/template/ucp_pm_history.html
- + styles/subsilver2/template/ucp_pm_history.html
* Since: 3.1.6-RC1
* Purpose: Add post button to private messages in history review (next to quote etc), at
the start of the list.
@@ -2055,7 +1877,6 @@ ucp_pm_history_review_after
===
* Locations:
+ styles/prosilver/template/ucp_pm_history.html
- + styles/subsilver2/template/ucp_pm_history.html
* Since: 3.1.6-RC1
* Purpose: Add content after the private messages history review.
@@ -2063,7 +1884,6 @@ ucp_pm_history_review_before
===
* Locations:
+ styles/prosilver/template/ucp_pm_history.html
- + styles/subsilver2/template/ucp_pm_history.html
* Since: 3.1.6-RC1
* Purpose: Add content before the private messages history review.
@@ -2117,7 +1937,6 @@ ucp_pm_viewmessage_post_buttons_after
===
* Locations:
+ styles/prosilver/template/ucp_pm_viewmessage.html
- + styles/subsilver2/template/ucp_pm_viewmessage.html
* Since: 3.1.0-RC3
* Purpose: Add post button to private messages (next to edit, quote etc), at
the end of the list.
@@ -2126,7 +1945,6 @@ ucp_pm_viewmessage_post_buttons_before
===
* Locations:
+ styles/prosilver/template/ucp_pm_viewmessage.html
- + styles/subsilver2/template/ucp_pm_viewmessage.html
* Since: 3.1.0-RC3
* Purpose: Add post button to private messages (next to edit, quote etc), at
the start of the list.
@@ -2151,7 +1969,6 @@ ucp_pm_viewmessage_print_head_append
===
* Locations:
+ styles/prosilver/template/ucp_pm_viewmessage_print.html
- + styles/subsilver2/template/ucp_pm_viewmessage_print.html
* Since: 3.1.0-a1
* Purpose: Add asset calls directly before the `</head>` tag of the Print PM screen
@@ -2175,7 +1992,6 @@ ucp_prefs_personal_prepend
===
* Locations:
+ styles/prosilver/template/ucp_prefs_personal.html
- + styles/subsilver2/template/ucp_prefs_personal.html
* Since: 3.1.0-a1
* Purpose: Add user options to the top of the Edit Global Settings block
@@ -2183,7 +1999,6 @@ ucp_prefs_personal_append
===
* Locations:
+ styles/prosilver/template/ucp_prefs_personal.html
- + styles/subsilver2/template/ucp_prefs_personal.html
* Since: 3.1.0-a1
* Purpose: Add user options to the bottom of the Edit Global Settings block
@@ -2191,7 +2006,6 @@ ucp_prefs_post_prepend
===
* Locations:
+ styles/prosilver/template/ucp_prefs_post.html
- + styles/subsilver2/template/ucp_prefs_post.html
* Since: 3.1.0-a1
* Purpose: Add user options to the top of the Edit Posting Defaults block
@@ -2199,7 +2013,6 @@ ucp_prefs_post_append
===
* Locations:
+ styles/prosilver/template/ucp_prefs_post.html
- + styles/subsilver2/template/ucp_prefs_post.html
* Since: 3.1.0-a1
* Purpose: Add user options to the bottom of the Edit Posting Defaults block
@@ -2207,7 +2020,6 @@ ucp_prefs_view_radio_buttons_prepend
===
* Locations:
+ styles/prosilver/template/ucp_prefs_view.html
- + styles/subsilver2/template/ucp_prefs_view.html
* Since: 3.1.0-a1
* Purpose: Add options to the top of the radio buttons block of the Edit
Display Options screen
@@ -2216,7 +2028,6 @@ ucp_prefs_view_radio_buttons_append
===
* Locations:
+ styles/prosilver/template/ucp_prefs_view.html
- + styles/subsilver2/template/ucp_prefs_view.html
* Since: 3.1.0-a1
* Purpose: Add options to the bottom of the radio buttons block of the Edit
Display Options screen
@@ -2225,7 +2036,6 @@ ucp_prefs_view_select_menu_prepend
===
* Locations:
+ styles/prosilver/template/ucp_prefs_view.html
- + styles/subsilver2/template/ucp_prefs_view.html
* Since: 3.1.0-a1
* Purpose: Add options to the top of the drop-down lists block of the Edit
Display Options screen
@@ -2234,7 +2044,6 @@ ucp_prefs_view_select_menu_append
===
* Locations:
+ styles/prosilver/template/ucp_prefs_view.html
- + styles/subsilver2/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
@@ -2243,7 +2052,6 @@ ucp_profile_profile_info_before
===
* Locations:
+ styles/prosilver/template/ucp_profile_profile_info.html
- + styles/subsilver2/template/ucp_profile_profile_info.html
* Since: 3.1.4-RC1
* Purpose: Add options in profile page fieldset - before jabber field.
@@ -2251,7 +2059,6 @@ ucp_profile_profile_info_after
===
* Locations:
+ styles/prosilver/template/ucp_profile_profile_info.html
- + styles/subsilver2/template/ucp_profile_profile_info.html
* Since: 3.1.4-RC1
* Purpose: Add options in profile page fieldset - after custom profile fields.
@@ -2259,7 +2066,6 @@ ucp_profile_register_details_before
===
* Locations:
+ styles/prosilver/template/ucp_profile_reg_details.html
- + styles/subsilver2/template/ucp_profile_reg_details.html
* Since: 3.1.4-RC1
* Purpose: Add options in profile page fieldset - before first field.
@@ -2267,7 +2073,6 @@ ucp_profile_register_details_after
===
* Locations:
+ styles/prosilver/template/ucp_profile_reg_details.html
- + styles/subsilver2/template/ucp_profile_reg_details.html
* Since: 3.1.4-RC1
* Purpose: Add options in profile page fieldset - after confirm password field.
@@ -2275,7 +2080,6 @@ ucp_register_credentials_before
===
* Locations:
+ styles/prosilver/template/ucp_register.html
- + styles/subsilver2/template/ucp_register.html
* Since: 3.1.0-b5
* Purpose: Add options in registration page fieldset - before first field.
@@ -2283,7 +2087,6 @@ ucp_register_profile_fields_after
===
* Locations:
+ styles/prosilver/template/ucp_register.html
- + styles/subsilver2/template/ucp_register.html
* Since: 3.1.0-b5
* Purpose: Add options in registration page fieldset - after last field.
@@ -2291,7 +2094,6 @@ ucp_register_credentials_after
===
* Locations:
+ styles/prosilver/template/ucp_register.html
- + styles/subsilver2/template/ucp_register.html
* Since: 3.1.0-b5
* Purpose: Add options in registration page fieldset - after password field.
@@ -2299,7 +2101,6 @@ ucp_register_options_before
===
* Locations:
+ styles/prosilver/template/ucp_register.html
- + styles/subsilver2/template/ucp_register.html
* Since: 3.1.0-b5
* Purpose: Add options in registration page fieldset - before language selector.
@@ -2307,7 +2108,6 @@ ucp_register_profile_fields_before
===
* Locations:
+ styles/prosilver/template/ucp_register.html
- + styles/subsilver2/template/ucp_register.html
* Since: 3.1.0-b5
* Purpose: Add options in registration page fieldset - before profile fields.
@@ -2315,7 +2115,6 @@ ucp_friend_list_before
===
* Locations:
+ styles/prosilver/template/ucp_zebra_friends.html
- + styles/subsilver2/template/ucp_zebra_friends.html
* Since: 3.1.0-a4
* Purpose: Add optional elements before list of friends in UCP
@@ -2323,7 +2122,6 @@ ucp_friend_list_after
===
* Locations:
+ styles/prosilver/template/ucp_zebra_friends.html
- + styles/subsilver2/template/ucp_zebra_friends.html
* Since: 3.1.0-a4
* Purpose: Add optional elements after list of friends in UCP
@@ -2331,7 +2129,6 @@ viewforum_body_topic_row_after
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.7-RC1
* Purpose: Add content after the topic list item.
@@ -2339,7 +2136,6 @@ viewforum_body_topic_row_append
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.7-RC1
* Purpose: Add content at the start of the topic list item.
@@ -2347,7 +2143,6 @@ viewforum_body_topic_row_before
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.7-RC1
* Purpose: Add content before the topic list item.
@@ -2355,7 +2150,6 @@ viewforum_body_topic_row_prepend
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.7-RC1
* Purpose: Add content at the end of the topic list item.
@@ -2363,7 +2157,6 @@ viewforum_body_topicrow_row_before
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.10-RC1
* Purpose: Add content before list of topics.
@@ -2371,7 +2164,6 @@ viewforum_buttons_bottom_before
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons before New Topic button on the bottom of the topic's list
@@ -2379,7 +2171,6 @@ viewforum_buttons_bottom_after
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons after New Topic button on the bottom of the topic's list
@@ -2387,7 +2178,6 @@ viewforum_buttons_top_before
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons before New Topic button on the top of the topic's list
@@ -2395,7 +2185,6 @@ viewforum_buttons_top_after
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons after New Topic button on the top of the topic's list
@@ -2403,7 +2192,6 @@ viewtopic_buttons_bottom_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons before Post Reply button on the bottom of the posts's list
@@ -2411,7 +2199,6 @@ viewtopic_buttons_bottom_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons after Post Reply button on the bottom of the posts's list
@@ -2419,7 +2206,6 @@ viewtopic_buttons_top_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons before Post Reply button on the top of the posts's list
@@ -2427,7 +2213,6 @@ viewtopic_buttons_top_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC5
* Purpose: Add buttons after Post Reply button on the top of the posts's list
@@ -2449,7 +2234,6 @@ viewforum_forum_name_append
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.0-b3
* Purpose: Add content directly after the forum name link on the View forum screen
@@ -2457,7 +2241,6 @@ viewforum_forum_name_prepend
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.0-b3
* Purpose: Add content directly before the forum name link on the View forum screen
@@ -2465,7 +2248,6 @@ viewforum_forum_title_after
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.5-RC1
* Purpose: Add content directly after the forum title on the View forum screen
@@ -2473,7 +2255,6 @@ viewforum_forum_title_before
===
* Locations:
+ styles/prosilver/template/viewforum_body.html
- + styles/subsilver2/template/viewforum_body.html
* Since: 3.1.5-RC1
* Purpose: Add content directly before the forum title on the View forum screen
@@ -2481,7 +2262,6 @@ viewtopic_print_head_append
===
* Locations:
+ styles/prosilver/template/viewtopic_print.html
- + styles/subsilver2/template/viewtopic_print.html
* Since: 3.1.0-a1
* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen
@@ -2489,7 +2269,6 @@ viewtopic_body_pagination_top_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.4-RC1
* Purpose: Add content after the pagination at top
@@ -2497,7 +2276,6 @@ viewtopic_body_avatar_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC3
* Purpose: Add content right after the avatar when viewing topics
@@ -2505,7 +2283,6 @@ viewtopic_body_avatar_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC3
* Purpose: Add content right before the avatar when viewing topics
@@ -2529,17 +2306,14 @@ viewtopic_body_footer_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a1
* Purpose: Add content to the bottom of the View topic screen below the posts
-and quick reply, directly before the jumpbox in Prosilver, breadcrumbs in
-Subsilver2.
+and quick reply, directly before the jumpbox in Prosilver.
viewtopic_body_poll_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.6-RC1
* Purpose: Add content after the poll panel.
@@ -2547,7 +2321,6 @@ viewtopic_body_poll_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.6-RC1
* Purpose: Add content before the poll panel.
@@ -2555,7 +2328,6 @@ viewtopic_body_poll_option_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b3
* Purpose: Add content after the poll option
the list.
@@ -2564,7 +2336,6 @@ viewtopic_body_poll_option_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b3
* Purpose: Add content before the poll option
the list.
@@ -2573,7 +2344,6 @@ viewtopic_body_poll_question_append
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b3
* Purpose: Add content directly after the poll question on the View topic screen
@@ -2581,7 +2351,6 @@ viewtopic_body_poll_question_prepend
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b3
* Purpose: Add content directly before the poll question on the View topic screen
@@ -2589,7 +2358,6 @@ viewtopic_body_post_author_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.3-RC1
* Purpose: Add content directly after the post author on the view topic screen
@@ -2597,7 +2365,6 @@ viewtopic_body_post_author_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.3-RC1
* Purpose: Add content directly before the post author on the view topic screen
@@ -2605,7 +2372,6 @@ viewtopic_body_post_buttons_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a1
* Purpose: Add post button to posts (next to edit, quote etc), at the end of
the list.
@@ -2614,7 +2380,6 @@ viewtopic_body_post_buttons_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a1
* Purpose: Add post button to posts (next to edit, quote etc), at the start of
the list.
@@ -2639,7 +2404,6 @@ viewtopic_body_post_subject_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.7-RC1
* Purpose: Add data before post icon and subject
@@ -2647,7 +2411,6 @@ viewtopic_body_postrow_back2top_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.8-RC1
* Purpose: Add content to the post's bottom after the back to top link
@@ -2655,7 +2418,6 @@ viewtopic_body_postrow_back2top_append
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.8-RC1
* Purpose: Add content to the post's bottom directly after the back to top link
@@ -2663,7 +2425,6 @@ viewtopic_body_postrow_back2top_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.8-RC1
* Purpose: Add content to the post's bottom before the back to top link
@@ -2671,7 +2432,6 @@ viewtopic_body_postrow_back2top_prepend
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.8-RC1
* Purpose: Add content to the post's bottom directly before the back to top link
@@ -2679,7 +2439,6 @@ viewtopic_body_postrow_custom_fields_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a1
* Purpose: Add data after the custom fields on the user profile when viewing
a post
@@ -2688,7 +2447,6 @@ viewtopic_body_postrow_custom_fields_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a1
* Purpose: Add data before the custom fields on the user profile when viewing
a post
@@ -2697,7 +2455,6 @@ viewtopic_body_postrow_post_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a4
* Purpose: Add data after posts
@@ -2705,7 +2462,6 @@ viewtopic_body_postrow_post_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a4
* Purpose: Add data before posts
@@ -2713,7 +2469,6 @@ viewtopic_body_postrow_post_content_footer
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-RC4
* Purpose: Add data at the end of the posts.
@@ -2721,7 +2476,6 @@ viewtopic_body_postrow_post_details_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.4-RC1
* Purpose: Add content after the post details
@@ -2729,7 +2483,6 @@ viewtopic_body_postrow_post_details_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.4-RC1
* Purpose: Add content before the post details
@@ -2737,7 +2490,6 @@ viewtopic_body_postrow_post_notices_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b2
* Purpose: Add posts specific custom notices at the notices bottom.
@@ -2745,7 +2497,6 @@ viewtopic_body_postrow_post_notices_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b2
* Purpose: Add posts specific custom notices at the notices top.
@@ -2753,7 +2504,6 @@ viewtopic_body_postrow_rank_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.6-RC1
* Purpose: Add data after the rank on the user profile when viewing
a post
@@ -2762,7 +2512,6 @@ viewtopic_body_postrow_rank_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.6-RC1
* Purpose: Add data before the rank on the user profile when viewing
a post
@@ -2771,7 +2520,6 @@ viewtopic_body_topic_actions_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a4
* Purpose: Add data before the topic actions buttons (after the posts sorting options)
@@ -2779,7 +2527,6 @@ viewtopic_topic_title_after
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/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)
@@ -2787,7 +2534,6 @@ viewtopic_topic_title_append
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-b3
* Purpose: Add content directly after the topic title link on the View topic screen
@@ -2795,7 +2541,6 @@ viewtopic_topic_title_prepend
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
- + styles/subsilver2/template/viewtopic_body.html
* Since: 3.1.0-a1
* Purpose: Add content directly before the topic title link on the View topic screen
diff --git a/phpBB/docs/install-config.sample.yml b/phpBB/docs/install-config.sample.yml
new file mode 100644
index 0000000000..47c0324599
--- /dev/null
+++ b/phpBB/docs/install-config.sample.yml
@@ -0,0 +1,36 @@
+installer:
+ admin:
+ name: admin
+ password: adminadmin
+ email: admin@example.org
+
+ board:
+ lang: en
+ name: My Board
+ description: My amazing new phpBB board
+
+ database:
+ dbms: sqlite3
+ dbhost: /tmp/phpbb.sqlite3
+ dbport: ~
+ dbuser: ~
+ dbpasswd: ~
+ dbname: ~
+ table_prefix: phpbb_
+
+ email:
+ enabled: false
+ smtp_delivery : ~
+ smtp_host: ~
+ smtp_port: ~
+ smtp_auth: ~
+ smtp_user: ~
+ smtp_pass: ~
+
+ server:
+ cookie_secure: false
+ server_protocol: http://
+ force_server_vars: false
+ server_name: localhost
+ server_port: 80
+ script_path: /
diff --git a/phpBB/docs/nginx.sample.conf b/phpBB/docs/nginx.sample.conf
index 2ead3552fd..c415720e9c 100644
--- a/phpBB/docs/nginx.sample.conf
+++ b/phpBB/docs/nginx.sample.conf
@@ -62,7 +62,7 @@ http {
root /path/to/phpbb;
location / {
- # phpbb uses index.htm
+ # phpBB uses index.htm
index index.php index.html index.htm;
try_files $uri $uri/ @rewriteapp;
}
@@ -92,6 +92,29 @@ http {
fastcgi_pass php;
}
+ # Correctly pass scripts for installer
+ location /install/ {
+ # phpBB uses index.htm
+ try_files $uri $uri/ @rewrite_installapp;
+
+ # Pass the php scripts to fastcgi server specified in upstream declaration.
+ location ~ \.php(/|$) {
+ # Unmodified fastcgi_params from nginx distribution.
+ include fastcgi_params;
+ # Necessary for php.
+ fastcgi_split_path_info ^(.+\.php)(/.*)$;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
+ fastcgi_param DOCUMENT_ROOT $realpath_root;
+ try_files $uri $uri/ /install/app.php$is_args$args;
+ fastcgi_pass php;
+ }
+ }
+
+ location @rewrite_installapp {
+ rewrite ^(.*)$ /install/app.php/$1 last;
+ }
+
# Deny access to version control system directories.
location ~ /\.svn|/\.git {
deny all;
diff --git a/phpBB/docs/update-config.sample.yml b/phpBB/docs/update-config.sample.yml
new file mode 100644
index 0000000000..f3b52a8c01
--- /dev/null
+++ b/phpBB/docs/update-config.sample.yml
@@ -0,0 +1,2 @@
+updater:
+ type: all
diff --git a/phpBB/docs/vagrant.md b/phpBB/docs/vagrant.md
new file mode 100644
index 0000000000..ac318270c1
--- /dev/null
+++ b/phpBB/docs/vagrant.md
@@ -0,0 +1,123 @@
+## Using Vagrant with phpBB
+
+phpBB includes support for Vagrant. This allows developers and contributors to run phpBB without the need to set up their own local web server with traditional WAMP/MAMP stacks. It also provides a consistent environment between developers for writing and debugging code changes more productively.
+
+phpBB uses the [Laravel/Homestead](https://laravel.com/docs/5.1/homestead) Vagrant box. It runs a Linux server with Ubuntu 14.04, PHP 5.6, Nginx, SQLite3, MySQL, and a whole lot more (complete specs below).
+
+## Get Started
+
+* Download and Install [Vagrant](https://www.vagrantup.com/downloads.html)
+* Download and Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
+* Run `vagrant up` from the root of your cloned fork of the phpBB Git repository
+
+```sh
+$ vagrant up
+```
+
+* Access phpBB at `http://192.168.10.10/`
+* Username: **admin**
+* Password: **adminadmin**
+
+## Additional commands:
+* Access your Linux server from the command line:
+
+```sh
+$ vagrant ssh
+```
+
+* Pause your server:
+
+```sh
+$ vagrant suspend
+```
+
+* Shut down your server:
+
+```sh
+$ vagrant halt
+```
+
+* Delete and remove your server:
+
+```sh
+$ vagrant destroy
+```
+
+> Note: destroying the vagrant server will remove all traces of the VM from your computer, reclaiming any disk space used by it. However, it also means the next time you vagrant up, you will be creating a brand new VM with a fresh install of phpBB and a new database.
+
+## Customising the phpBB configuration
+
+By default, phpBB is pre-configured to install with a MySQL database. You can, however, switch to PostegreSQL or SQLite3 by editing the `phpbb-install-config.yml` file in the vagrant directory. The next time you run `vagrant up` (or `vagrant provision`) it will be installed under the new configuration.
+
+If you prefer to access phpBB from the more friendly URL `http://phpbb.app` then you must update your computer's hosts file. This file is typically located at `/etc/hosts` for Mac/Linux or `C:\Windows\System32\drivers\etc\hosts` for Windows. Open this file and add the following line to it, at the very bottom, and save.
+
+```
+192.168.10.10 phpbb.app
+```
+
+## How it all works
+
+When you vagrant up, the Laravel/Homestead box is transparently loaded as a Virtual Machine on your computer (this may take several minutes the very first time while it downloads the VM image to your computer). Your local phpBB repository clone is mirrored/shared with the VM, so you can work on the phpBB code on your computer, and see the changes immediately when you browse to phpBB at the URL provided by the VM.
+
+This is very similar to traditional methods of working with a local WAMP/MAMP stack, except the webserver is now being provided by a VM of a Linux server. The advantages here are the exact same Linux server environment is being used by everybody who uses Vagrant with phpBB, so there will be consist behaviour unlike when everybody is developing on different versions of PHP, server configurations, etc.
+
+The environment is also "sandboxed" from your system. This means you don't need to worry about adjusting your own computer's internal PHP settings, setting up databases, or doing damage to your system or to phpBB. Other than the phpBB codebase, which lives on your computer, all execution is taking place within the VM and you can at any time, halt or destroy the VM and start a brand new one.
+
+There are some caveats, however. You can only run one vagrant VM for the phpBB repository. And of course, the database will be destroyed when you vagrant destroy. If the database is important, you should SSH into your vagrant VM and export/import the DB as needed using SSH commands.
+
+For example, to export/import a MySQL database (using phpBB's `store` directory):
+
+SSH into the VM
+
+```sh
+$ vagrant ssh
+```
+
+Export MySQL:
+
+```sh
+$ mysqldump -uhomestead -psecret phpbb > /home/vagrant/phpbb/phpBB/store/phpbb.sql
+```
+
+Import MySQL:
+
+```sh
+$ mysql -uhomestead -psecret phpbb < /home/vagrant/phpbb/phpBB/store/phpbb.sql
+```
+
+---
+
+## About the Laravel/Homestead box
+
+### Included Software
+
+* Ubuntu 14.04
+* Git
+* PHP 5.6
+* HHVM
+* Nginx
+* MySQL
+* Sqlite3
+* Postgres
+* Composer
+* Node (With PM2, Bower, Grunt, and Gulp)
+* Redis
+* Memcached
+* Beanstalkd
+* Blackfire Profiler
+
+### MySQL Access
+
+- Hostname: 127.0.0.1
+- Username: homestead
+- Password: secret
+- Database: phpbb
+- Port: 3306
+
+### PostgreSQL Access
+
+- Hostname: 127.0.0.1
+- Username: homestead
+- Password: secret
+- Database: phpbb
+- Port: 5432
diff --git a/phpBB/download/file.php b/phpBB/download/file.php
index 56ea273d5c..7a20145968 100644
--- a/phpBB/download/file.php
+++ b/phpBB/download/file.php
@@ -42,6 +42,11 @@ if (isset($_GET['avatar']))
$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
extract($phpbb_config_php_file->get_all());
+ if (!defined('PHPBB_ENVIRONMENT'))
+ {
+ @define('PHPBB_ENVIRONMENT', 'production');
+ }
+
if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
{
exit;
@@ -56,40 +61,45 @@ if (isset($_GET['avatar']))
$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
$phpbb_class_loader_ext->register();
- phpbb_load_extensions_autoloaders($phpbb_root_path);
-
// Set up container
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
- $phpbb_container = $phpbb_container_builder->get_container();
+ $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
// set up caching
+ /* @var $cache \phpbb\cache\service */
$cache = $phpbb_container->get('cache');
+ /* @var $phpbb_dispatcher \phpbb\event\dispatcher */
$phpbb_dispatcher = $phpbb_container->get('dispatcher');
+
+ /* @var $request \phpbb\request\request_interface */
$request = $phpbb_container->get('request');
+
+ /* @var $db \phpbb\db\driver\driver_interface */
$db = $phpbb_container->get('dbal.conn');
+
+ /* @var $phpbb_log \phpbb\log\log_interface */
$phpbb_log = $phpbb_container->get('log');
unset($dbpasswd);
- request_var('', 0, false, false, $request);
-
+ /* @var $config \phpbb\config\config */
$config = $phpbb_container->get('config');
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
// load extensions
+ /* @var $phpbb_extension_manager \phpbb\extension\manager */
$phpbb_extension_manager = $phpbb_container->get('ext.manager');
// worst-case default
$browser = strtolower($request->header('User-Agent', 'msie 6.0'));
+ /* @var $phpbb_avatar_manager \phpbb\avatar\manager */
$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
- $filename = request_var('avatar', '');
+ $filename = $request->variable('avatar', '');
$avatar_group = false;
$exit = false;
@@ -140,9 +150,9 @@ if (isset($_GET['avatar']))
include($phpbb_root_path . 'common.' . $phpEx);
require($phpbb_root_path . 'includes/functions_download' . '.' . $phpEx);
-$attach_id = request_var('id', 0);
-$mode = request_var('mode', '');
-$thumbnail = request_var('t', false);
+$attach_id = $request->variable('id', 0);
+$mode = $request->variable('mode', '');
+$thumbnail = $request->variable('t', false);
// Start session management, do not update session page.
$user->session_begin(false);
diff --git a/phpBB/faq.php b/phpBB/faq.php
index 5fe155eab0..36a33c97a8 100644
--- a/phpBB/faq.php
+++ b/phpBB/faq.php
@@ -24,90 +24,13 @@ $user->session_begin();
$auth->acl($user->data);
$user->setup();
-$mode = request_var('mode', '');
-
-// Load the appropriate faq file
-switch ($mode)
-{
- case 'bbcode':
- $l_title = $user->lang['BBCODE_GUIDE'];
- $user->add_lang('bbcode', false, true);
- break;
-
- default:
- $page_title = $user->lang['FAQ_EXPLAIN'];
- $ext_name = $lang_file = '';
-
- /**
- * You can use this event display a custom help page
- *
- * @event core.faq_mode_validation
- * @var string page_title Title of the page
- * @var string mode FAQ that is going to be displayed
- * @var string lang_file Language file containing the help data
- * @var string ext_name Vendor and extension name where the help
- * language file can be loaded from
- * @since 3.1.4-RC1
- */
- $vars = array(
- 'page_title',
- 'mode',
- 'lang_file',
- 'ext_name',
- );
- extract($phpbb_dispatcher->trigger_event('core.faq_mode_validation', compact($vars)));
-
- $l_title = $page_title;
- $user->add_lang(($lang_file) ? $lang_file : 'faq', false, true, $ext_name);
- break;
-}
-
-// Pull the array data from the lang pack
-$switch_column = $found_switch = false;
-$help_blocks = array();
-foreach ($user->help as $help_ary)
-{
- if ($help_ary[0] == '--')
- {
- if ($help_ary[1] == '--')
- {
- $switch_column = true;
- $found_switch = true;
- continue;
- }
-
- $template->assign_block_vars('faq_block', array(
- 'BLOCK_TITLE' => $help_ary[1],
- 'SWITCH_COLUMN' => $switch_column,
- ));
-
- if ($switch_column)
- {
- $switch_column = false;
- }
- continue;
- }
-
- $template->assign_block_vars('faq_block.faq_row', array(
- 'FAQ_QUESTION' => $help_ary[0],
- 'FAQ_ANSWER' => $help_ary[1])
- );
-}
-
-// Lets build a page ...
-$template->assign_vars(array(
- 'L_FAQ_TITLE' => $l_title,
- 'L_BACK_TO_TOP' => $user->lang['BACK_TO_TOP'],
-
- 'SWITCH_COLUMN_MANUALLY' => (!$found_switch) ? true : false,
- 'S_IN_FAQ' => true,
-));
-
-page_header($l_title);
-
-$template->set_filenames(array(
- 'body' => 'faq_body.html')
+/** @var \phpbb\controller\helper $controller_helper */
+$controller_helper = $phpbb_container->get('controller.helper');
+
+$response = new \Symfony\Component\HttpFoundation\RedirectResponse(
+ $controller_helper->route(
+ $request->variable('mode', 'faq') === 'bbcode' ? 'phpbb_help_bbcode_controller' : 'phpbb_help_faq_controller'
+ ),
+ 301
);
-make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
-
-page_footer();
+$response->send();
diff --git a/phpBB/feed.php b/phpBB/feed.php
index 6fd0ed800f..1480867d6c 100644
--- a/phpBB/feed.php
+++ b/phpBB/feed.php
@@ -16,6 +16,9 @@
*
**/
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\Routing\Exception\InvalidParameterException;
+
/**
* @ignore
**/
@@ -23,234 +26,33 @@ define('IN_PHPBB', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
-include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
-
-if (!$config['feed_enable'])
-{
- trigger_error('NO_FEED_ENABLED');
-}
-
-// Start session
-$user->session_begin();
-
-if (!empty($config['feed_http_auth']) && request_var('auth', '') == 'http')
-{
- phpbb_http_login(array(
- 'auth_message' => 'Feed',
- 'viewonline' => request_var('viewonline', true),
- ));
-}
-
-$auth->acl($user->data);
-$user->setup('viewtopic');
-// Initial var setup
-$forum_id = request_var('f', 0);
-$topic_id = request_var('t', 0);
-$mode = request_var('mode', '');
+/** @var \phpbb\controller\helper $controller_helper */
+$controller_helper = $phpbb_container->get('controller.helper');
-// We do not use a template, therefore we simply define the global template variables here
-$global_vars = $item_vars = array();
-$feed_updated_time = 0;
+$forum_id = $request->variable('f', 0);
+$topic_id = $request->variable('t', 0);
+$mode = $request->variable('mode', '');
-// Generate params array for use in append_sid() to correctly link back to this page
-$params = false;
-if ($forum_id || $topic_id || $mode)
+if ($forum_id !== 0)
{
- $params = array(
- 'f' => ($forum_id) ? $forum_id : NULL,
- 't' => ($topic_id) ? $topic_id : NULL,
- 'mode' => ($mode) ? $mode : NULL,
- );
+ $url = $controller_helper->route('phpbb_feed_forum', array('forum_id' => $forum_id));
}
-
-// This boards URL
-$phpbb_feed_helper = $phpbb_container->get('feed.helper');
-$board_url = $phpbb_feed_helper->get_board_url();
-
-// Get correct feed object
-$phpbb_feed_factory = $phpbb_container->get('feed.factory');
-$feed = $phpbb_feed_factory->get_feed($mode, $forum_id, $topic_id);
-
-// No feed found
-if ($feed === false)
+else if ($topic_id !== 0)
{
- trigger_error('NO_FEED');
+ $url = $controller_helper->route('phpbb_feed_topic', array('topic_id' => $topic_id));
}
-
-// Open Feed
-$feed->open();
-
-// Iterate through items
-while ($row = $feed->get_item())
+else
{
- /**
- * Event to modify the feed row
- *
- * @event core.feed_modify_feed_row
- * @var int forum_id Forum ID
- * @var string mode Feeds mode (forums|topics|topics_new|topics_active|news)
- * @var array row Array with feed data
- * @var int topic_id Topic ID
- *
- * @since 3.1.10-RC1
- */
- $vars = array('forum_id', 'mode', 'row', 'topic_id');
- extract($phpbb_dispatcher->trigger_event('core.feed_modify_feed_row', compact($vars)));
-
- // BBCode options to correctly disable urls, smilies, bbcode...
- if ($feed->get('options') === NULL)
+ try
{
- // Allow all combinations
- $options = 7;
-
- if ($feed->get('enable_bbcode') !== NULL && $feed->get('enable_smilies') !== NULL && $feed->get('enable_magic_url') !== NULL)
- {
- $options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0);
- }
+ $url = $controller_helper->route('phpbb_feed_overall', array('mode' => $mode));
}
- else
+ catch (InvalidParameterException $e)
{
- $options = $row[$feed->get('options')];
+ $url = $controller_helper->route('phpbb_feed_index');
}
-
- $title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : '');
-
- $published = ($feed->get('published') !== NULL) ? (int) $row[$feed->get('published')] : 0;
- $updated = ($feed->get('updated') !== NULL) ? (int) $row[$feed->get('updated')] : 0;
-
- $display_attachments = ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment']) ? true : false;
-
- $item_row = array(
- 'author' => ($feed->get('creator') !== NULL) ? $row[$feed->get('creator')] : '',
- 'published' => ($published > 0) ? $phpbb_feed_helper->format_date($published) : '',
- 'updated' => ($updated > 0) ? $phpbb_feed_helper->format_date($updated) : '',
- 'link' => '',
- 'title' => censor_text($title),
- 'category' => ($config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $phpEx . '?f=' . $row['forum_id'] : '',
- 'category_name' => ($config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '',
- 'description' => censor_text($phpbb_feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], ($display_attachments ? $feed->get_attachments($row['post_id']) : array()))),
- 'statistics' => '',
- );
-
- // Adjust items, fill link, etc.
- $feed->adjust_item($item_row, $row);
-
- $item_vars[] = $item_row;
-
- $feed_updated_time = max($feed_updated_time, $published, $updated);
}
-// If we do not have any items at all, sending the current time is better than sending no time.
-if (!$feed_updated_time)
-{
- $feed_updated_time = time();
-}
-
-// Some default assignments
-// FEED_IMAGE is not used (atom)
-$global_vars = array_merge($global_vars, array(
- 'FEED_IMAGE' => '',
- 'SELF_LINK' => $phpbb_feed_helper->append_sid('feed.' . $phpEx, $params),
- 'FEED_LINK' => $board_url . '/index.' . $phpEx,
- 'FEED_TITLE' => $config['sitename'],
- 'FEED_SUBTITLE' => $config['site_desc'],
- 'FEED_UPDATED' => $phpbb_feed_helper->format_date($feed_updated_time),
- 'FEED_LANG' => $user->lang['USER_LANG'],
- 'FEED_AUTHOR' => $config['sitename'],
-));
-
-$feed->close();
-
-// Output page
-
-// gzip_compression
-if ($config['gzip_compress'])
-{
- if (@extension_loaded('zlib') && !headers_sent())
- {
- ob_start('ob_gzhandler');
- }
-}
-
-// IF debug extra is enabled and admin want to "explain" the page we need to set other headers...
-if (defined('DEBUG') && request_var('explain', 0) && $auth->acl_get('a_'))
-{
- header('Content-type: text/html; charset=UTF-8');
- header('Cache-Control: private, no-cache="set-cookie"');
- header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
-
- $mtime = explode(' ', microtime());
- $totaltime = $mtime[0] + $mtime[1] - $starttime;
-
- if (method_exists($db, 'sql_report'))
- {
- $db->sql_report('display');
- }
-
- garbage_collection();
- exit_handler();
-}
-
-header("Content-Type: application/atom+xml; charset=UTF-8");
-header("Last-Modified: " . gmdate('D, d M Y H:i:s', $feed_updated_time) . ' GMT');
-
-if (!empty($user->data['is_bot']))
-{
- // Let reverse proxies know we detected a bot.
- header('X-PHPBB-IS-BOT: yes');
-}
-
-echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
-echo '<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="' . $global_vars['FEED_LANG'] . '">' . "\n";
-echo '<link rel="self" type="application/atom+xml" href="' . $global_vars['SELF_LINK'] . '" />' . "\n\n";
-
-echo (!empty($global_vars['FEED_TITLE'])) ? '<title>' . $global_vars['FEED_TITLE'] . '</title>' . "\n" : '';
-echo (!empty($global_vars['FEED_SUBTITLE'])) ? '<subtitle>' . $global_vars['FEED_SUBTITLE'] . '</subtitle>' . "\n" : '';
-echo (!empty($global_vars['FEED_LINK'])) ? '<link href="' . $global_vars['FEED_LINK'] .'" />' . "\n" : '';
-echo '<updated>' . $global_vars['FEED_UPDATED'] . '</updated>' . "\n\n";
-
-echo '<author><name><![CDATA[' . $global_vars['FEED_AUTHOR'] . ']]></name></author>' . "\n";
-echo '<id>' . $global_vars['SELF_LINK'] . '</id>' . "\n";
-
-foreach ($item_vars as $row)
-{
- echo '<entry>' . "\n";
-
- if (!empty($row['author']))
- {
- echo '<author><name><![CDATA[' . $row['author'] . ']]></name></author>' . "\n";
- }
-
- echo '<updated>' . ((!empty($row['updated'])) ? $row['updated'] : $row['published']) . '</updated>' . "\n";
-
- if (!empty($row['published']))
- {
- echo '<published>' . $row['published'] . '</published>' . "\n";
- }
-
- echo '<id>' . $row['link'] . '</id>' . "\n";
- echo '<link href="' . $row['link'] . '"/>' . "\n";
- echo '<title type="html"><![CDATA[' . $row['title'] . ']]></title>' . "\n\n";
-
- if (!empty($row['category']) && isset($row['category_name']) && $row['category_name'] !== '')
- {
- echo '<category term="' . $row['category_name'] . '" scheme="' . $row['category'] . '" label="' . $row['category_name'] . '"/>' . "\n";
- }
-
- echo '<content type="html" xml:base="' . $row['link'] . '"><![CDATA[' . "\n";
- echo $row['description'];
-
- if (!empty($row['statistics']))
- {
- echo '<p>' . $user->lang['STATISTICS'] . ': ' . $row['statistics'] . '</p>';
- }
-
- echo '<hr />' . "\n" . ']]></content>' . "\n";
- echo '</entry>' . "\n";
-}
-
-echo '</feed>';
-
-garbage_collection();
-exit_handler();
+$response = new RedirectResponse($url, 301);
+$response->send();
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php
index e4650455c4..3cfe5de293 100644
--- a/phpBB/includes/acp/acp_attachments.php
+++ b/phpBB/includes/acp/acp_attachments.php
@@ -36,14 +36,20 @@ class acp_attachments
/** @var \phpbb\user */
protected $user;
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ /** @var \phpbb\attachment\manager */
+ protected $attachment_manager;
+
public $id;
public $u_action;
protected $new_config;
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $phpbb_container, $phpbb_dispatcher;
- global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
+ global $db, $user, $auth, $template, $cache, $phpbb_container, $phpbb_filesystem, $phpbb_dispatcher;
+ global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log, $request;
$this->id = $id;
$this->db = $db;
@@ -51,12 +57,14 @@ class acp_attachments
$this->template = $template;
$this->user = $user;
$this->phpbb_container = $phpbb_container;
+ $this->filesystem = $phpbb_filesystem;
+ $this->attachment_manager = $phpbb_container->get('attachment.manager');
$user->add_lang(array('posting', 'viewtopic', 'acp/attachments'));
$error = $notify = array();
$submit = (isset($_POST['submit'])) ? true : false;
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$form_key = 'acp_attach';
add_form_key($form_key);
@@ -175,7 +183,7 @@ class acp_attachments
extract($phpbb_dispatcher->trigger_event('core.acp_attachments_config_edit_add', compact($vars)));
$this->new_config = $config;
- $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => '')) : $this->new_config;
+ $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => '')) : $this->new_config;
$error = array();
// We validate the complete config if whished
@@ -199,13 +207,13 @@ class acp_attachments
if (in_array($config_name, array('attachment_quota', 'max_filesize', 'max_filesize_pm')))
{
- $size_var = request_var($config_name, '');
+ $size_var = $request->variable($config_name, '');
$this->new_config[$config_name] = $config_value = ($size_var == 'kb') ? round($config_value * 1024) : (($size_var == 'mb') ? round($config_value * 1048576) : $config_value);
}
if ($submit)
{
- set_config($config_name, $config_value);
+ $config->set($config_name, $config_value);
}
}
@@ -213,7 +221,7 @@ class acp_attachments
if ($submit)
{
- add_log('admin', 'LOG_CONFIG_ATTACH');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_ATTACH');
// Check Settings
$this->test_upload($error, $this->new_config['upload_path'], false);
@@ -349,8 +357,8 @@ class acp_attachments
if ($submit)
{
// Change Extensions ?
- $extension_change_list = request_var('extension_change_list', array(0));
- $group_select_list = request_var('group_select', array(0));
+ $extension_change_list = $request->variable('extension_change_list', array(0));
+ $group_select_list = $request->variable('group_select', array(0));
// Generate correct Change List
$extensions = array();
@@ -374,13 +382,13 @@ class acp_attachments
WHERE extension_id = ' . $row['extension_id'];
$db->sql_query($sql);
- add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_UPDATE', false, array($row['extension']));
}
}
$db->sql_freeresult($result);
// Delete Extension?
- $extension_id_list = request_var('extension_id_list', array(0));
+ $extension_id_list = $request->variable('extension_id_list', array(0));
if (sizeof($extension_id_list))
{
@@ -401,13 +409,13 @@ class acp_attachments
WHERE ' . $db->sql_in_set('extension_id', $extension_id_list);
$db->sql_query($sql);
- add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_DEL', false, array($extension_list));
}
}
// Add Extension?
- $add_extension = strtolower(request_var('add_extension', ''));
- $add_extension_group = request_var('add_group_select', 0);
+ $add_extension = strtolower($request->variable('add_extension', ''));
+ $add_extension_group = $request->variable('add_group_select', 0);
$add = (isset($_POST['add_extension_check'])) ? true : false;
if ($add_extension && $add)
@@ -433,7 +441,8 @@ class acp_attachments
);
$db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
- add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension);
+
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXT_ADD', false, array($add_extension));
}
}
}
@@ -490,8 +499,8 @@ class acp_attachments
if ($submit)
{
- $action = request_var('action', '');
- $group_id = request_var('g', 0);
+ $action = $request->variable('action', '');
+ $group_id = $request->variable('g', 0);
if ($action != 'add' && $action != 'edit')
{
@@ -522,7 +531,7 @@ class acp_attachments
$ext_row = array();
}
- $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
+ $group_name = $request->variable('group_name', '', true);
$new_group_name = ($action == 'add') ? $group_name : (($ext_row['group_name'] != $group_name) ? $group_name : '');
if (!$group_name)
@@ -552,12 +561,12 @@ class acp_attachments
if (!sizeof($error))
{
// Ok, build the update/insert array
- $upload_icon = request_var('upload_icon', 'no_image');
- $size_select = request_var('size_select', 'b');
- $forum_select = request_var('forum_select', false);
- $allowed_forums = request_var('allowed_forums', array(0));
+ $upload_icon = $request->variable('upload_icon', 'no_image');
+ $size_select = $request->variable('size_select', 'b');
+ $forum_select = $request->variable('forum_select', false);
+ $allowed_forums = $request->variable('allowed_forums', array(0));
$allow_in_pm = (isset($_POST['allow_in_pm'])) ? true : false;
- $max_filesize = request_var('max_filesize', 0);
+ $max_filesize = $request->variable('max_filesize', 0);
$max_filesize = ($size_select == 'kb') ? round($max_filesize * 1024) : (($size_select == 'mb') ? round($max_filesize * 1048576) : $max_filesize);
$allow_group = (isset($_POST['allow_group'])) ? true : false;
@@ -573,7 +582,7 @@ class acp_attachments
$group_ary = array(
'group_name' => $group_name,
- 'cat_id' => request_var('special_category', ATTACHMENT_CATEGORY_NONE),
+ 'cat_id' => $request->variable('special_category', ATTACHMENT_CATEGORY_NONE),
'allow_group' => ($allow_group) ? 1 : 0,
'upload_icon' => ($upload_icon == 'no_image') ? '' : $upload_icon,
'max_filesize' => $max_filesize,
@@ -598,10 +607,10 @@ class acp_attachments
}
$group_name = (isset($user->lang['EXT_GROUP_' . $group_name])) ? $user->lang['EXT_GROUP_' . $group_name] : $group_name;
- add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), false, array($group_name));
}
- $extension_list = request_var('extensions', array(0));
+ $extension_list = $request->variable('extensions', array(0));
if ($action == 'edit' && sizeof($extension_list))
{
@@ -630,13 +639,10 @@ class acp_attachments
$cat_lang = array(
ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'],
ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'],
- ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'],
- ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'],
ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'],
- ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'],
);
- $group_id = request_var('g', 0);
+ $group_id = $request->variable('g', 0);
$action = (isset($_POST['add'])) ? 'add' : $action;
switch ($action)
@@ -663,7 +669,7 @@ class acp_attachments
WHERE group_id = $group_id";
$db->sql_query($sql);
- add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_DEL', false, array($group_name));
$cache->destroy('_extensions');
@@ -704,7 +710,7 @@ class acp_attachments
if ($action == 'add')
{
$ext_group_row = array(
- 'group_name' => utf8_normalize_nfc(request_var('group_name', '', true)),
+ 'group_name' => $request->variable('group_name', '', true),
'cat_id' => 0,
'allow_group' => 1,
'allow_in_pm' => 1,
@@ -715,8 +721,6 @@ class acp_attachments
$forum_ids = array();
}
- $extensions = array();
-
$sql = 'SELECT *
FROM ' . EXTENSIONS_TABLE . "
WHERE group_id = $group_id
@@ -920,9 +924,9 @@ class acp_attachments
if ($submit)
{
- $delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array();
- $add_files = (isset($_POST['add'])) ? array_keys(request_var('add', array('' => 0))) : array();
- $post_ids = request_var('post_id', array('' => 0));
+ $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))
{
@@ -935,11 +939,11 @@ class acp_attachments
$delete_files = array();
while ($row = $db->sql_fetchrow($result))
{
- phpbb_unlink($row['physical_filename'], 'file');
+ $this->attachment_manager->unlink($row['physical_filename'], 'file');
if ($row['thumbnail'])
{
- phpbb_unlink($row['physical_filename'], 'thumbnail');
+ $this->attachment_manager->unlink($row['physical_filename'], 'thumbnail');
}
$delete_files[$row['attach_id']] = $row['real_filename'];
@@ -953,7 +957,7 @@ class acp_attachments
WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files));
$db->sql_query($sql);
- add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_ORPHAN_DEL', false, array(implode(', ', $delete_files)));
$notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode($user->lang['COMMA_SEPARATOR'], $delete_files));
}
@@ -1044,14 +1048,14 @@ class acp_attachments
$space_taken += $row['filesize'];
$files_added++;
- add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_FILEUPLOAD', false, array($post_row['post_id'], $row['real_filename']));
}
$db->sql_freeresult($result);
if ($files_added)
{
- set_config_count('upload_dir_size', $space_taken, true);
- set_config_count('num_files', $files_added, true);
+ $config->increment('upload_dir_size', $space_taken, false);
+ $config->increment('num_files', $files_added, false);
}
}
}
@@ -1088,7 +1092,7 @@ class acp_attachments
if ($submit)
{
- $delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array();
+ $delete_files = (isset($_POST['delete'])) ? array_keys($request->variable('delete', array('' => 0))) : array();
if (sizeof($delete_files))
{
@@ -1104,13 +1108,14 @@ class acp_attachments
}
$db->sql_freeresult($result);
- if ($num_deleted = delete_attachments('attach', $delete_files))
+ if ($num_deleted = $this->attachment_manager->delete('attach', $delete_files))
{
if (sizeof($delete_files) != $num_deleted)
{
$error[] = $user->lang['FILES_GONE'];
}
- add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $deleted_filenames));
+
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACHMENTS_DELETED', false, array(implode(', ', $deleted_filenames)));
$notify[] = sprintf($user->lang['LOG_ATTACHMENTS_DELETED'], implode($user->lang['COMMA_SEPARATOR'], $deleted_filenames));
}
else
@@ -1136,12 +1141,12 @@ class acp_attachments
'S_MANAGE' => true,
));
- $start = request_var('start', 0);
+ $start = $request->variable('start', 0);
// Sort keys
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 't');
- $sort_dir = request_var('sd', 'd');
+ $sort_days = $request->variable('st', 0);
+ $sort_key = $request->variable('sk', 't');
+ $sort_dir = $request->variable('sd', 'd');
// Sorting
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
@@ -1162,6 +1167,7 @@ class acp_attachments
$total_size = $stats['upload_dir_size'];
// Make sure $start is set to the last page if it exceeds the amount
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
$start = $pagination->validate_start($start, $attachments_per_page, $num_files);
@@ -1361,6 +1367,8 @@ class acp_attachments
else
{
$this->set_attachment_stats($this->get_attachment_stats());
+
+ /* @var $log \phpbb\log\log_interface */
$log = $this->phpbb_container->get('log');
$log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_RESYNC_FILES_STATS');
}
@@ -1377,10 +1385,7 @@ class acp_attachments
$types = array(
ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'],
ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'],
- ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'],
- ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'],
ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'],
- ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'],
);
if ($group_id)
@@ -1511,7 +1516,15 @@ class acp_attachments
if (!file_exists($phpbb_root_path . $upload_dir))
{
@mkdir($phpbb_root_path . $upload_dir, 0777);
- phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
}
}
@@ -1527,7 +1540,7 @@ class acp_attachments
return;
}
- if (!phpbb_is_writable($phpbb_root_path . $upload_dir))
+ if (!$this->filesystem->is_writable($phpbb_root_path . $upload_dir))
{
$error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir);
return;
@@ -1539,13 +1552,12 @@ class acp_attachments
*/
function perform_site_list()
{
- global $db, $user;
- global $request;
+ global $db, $user, $request, $phpbb_log;
if (isset($_REQUEST['securesubmit']))
{
// Grab the list of entries
- $ips = request_var('ips', '');
+ $ips = $request->variable('ips', '');
$ip_list = array_unique(explode("\n", $ips));
$ip_list_log = implode(', ', $ip_list);
@@ -1570,7 +1582,6 @@ class acp_attachments
if ($ip_2_counter == 0 && $ip_2_end == 254)
{
$ip_2_counter = 256;
- $ip_2_fragment = 256;
$iplist[] = "'$ip_1_counter.*'";
}
@@ -1583,7 +1594,6 @@ class acp_attachments
if ($ip_3_counter == 0 && $ip_3_end == 254)
{
$ip_3_counter = 256;
- $ip_3_fragment = 256;
$iplist[] = "'$ip_1_counter.$ip_2_counter.*'";
}
@@ -1596,7 +1606,6 @@ class acp_attachments
if ($ip_4_counter == 0 && $ip_4_end == 254)
{
$ip_4_counter = 256;
- $ip_4_fragment = 256;
$iplist[] = "'$ip_1_counter.$ip_2_counter.$ip_3_counter.*'";
}
@@ -1691,14 +1700,14 @@ class acp_attachments
{
// Update log
$log_entry = ($ip_exclude) ? 'LOG_DOWNLOAD_EXCLUDE_IP' : 'LOG_DOWNLOAD_IP';
- add_log('admin', $log_entry, $ip_list_log);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry, false, array($ip_list_log));
}
trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action));
}
else if (isset($_POST['unsecuresubmit']))
{
- $unip_sql = request_var('unip', array(0));
+ $unip_sql = $request->variable('unip', array(0));
if (sizeof($unip_sql))
{
@@ -1720,7 +1729,7 @@ class acp_attachments
WHERE ' . $db->sql_in_set('site_id', $unip_sql);
$db->sql_query($sql);
- add_log('admin', 'LOG_DOWNLOAD_REMOVE_IP', $l_unip_list);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DOWNLOAD_REMOVE_IP', false, array($l_unip_list));
}
trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action));
diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php
index 286bc92813..5aed78be08 100644
--- a/phpBB/includes/acp/acp_ban.php
+++ b/phpBB/includes/acp/acp_ban.php
@@ -195,7 +195,6 @@ class acp_ban
case 'user':
$field = 'username';
- $l_ban_cell = $user->lang['USERNAME'];
$sql = 'SELECT b.*, u.user_id, u.username, u.username_clean
FROM ' . BANLIST_TABLE . ' b, ' . USERS_TABLE . ' u
@@ -208,7 +207,6 @@ class acp_ban
case 'ip':
$field = 'ban_ip';
- $l_ban_cell = $user->lang['IP_HOSTNAME'];
$sql = 'SELECT *
FROM ' . BANLIST_TABLE . '
@@ -221,7 +219,6 @@ class acp_ban
case 'email':
$field = 'ban_email';
- $l_ban_cell = $user->lang['EMAIL_ADDRESS'];
$sql = 'SELECT *
FROM ' . BANLIST_TABLE . '
diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php
index c98be241e9..f958ae93c7 100644
--- a/phpBB/includes/acp/acp_bbcodes.php
+++ b/phpBB/includes/acp/acp_bbcodes.php
@@ -25,14 +25,14 @@ class acp_bbcodes
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container;
+ global $phpbb_log;
$user->add_lang('acp/posting');
// Set up general vars
- $action = request_var('action', '');
- $bbcode_id = request_var('bbcode', 0);
+ $action = $request->variable('action', '');
+ $bbcode_id = $request->variable('bbcode', 0);
$submit = $request->is_set_post('submit');
$this->tpl_name = 'acp_bbcodes';
@@ -89,11 +89,11 @@ class acp_bbcodes
// No break here
case 'create':
- $display_on_posting = request_var('display_on_posting', 0);
+ $display_on_posting = $request->variable('display_on_posting', 0);
- $bbcode_match = request_var('bbcode_match', '');
- $bbcode_tpl = htmlspecialchars_decode(utf8_normalize_nfc(request_var('bbcode_tpl', '', true)));
- $bbcode_helpline = utf8_normalize_nfc(request_var('bbcode_helpline', '', true));
+ $bbcode_match = $request->variable('bbcode_match', '');
+ $bbcode_tpl = htmlspecialchars_decode($request->variable('bbcode_tpl', '', true));
+ $bbcode_helpline = $request->variable('bbcode_helpline', '', true);
break;
}
@@ -275,6 +275,7 @@ class acp_bbcodes
$db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary));
$cache->destroy('sql', BBCODES_TABLE);
+ $phpbb_container->get('text_formatter.cache')->invalidate();
$lang = 'BBCODE_ADDED';
$log_action = 'LOG_BBCODE_ADD';
@@ -286,12 +287,13 @@ class acp_bbcodes
WHERE bbcode_id = ' . $bbcode_id;
$db->sql_query($sql);
$cache->destroy('sql', BBCODES_TABLE);
+ $phpbb_container->get('text_formatter.cache')->invalidate();
$lang = 'BBCODE_EDITED';
$log_action = 'LOG_BBCODE_EDIT';
}
- add_log('admin', $log_action, $data['bbcode_tag']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag']));
trigger_error($user->lang[$lang] . adm_back_link($this->u_action));
}
@@ -325,7 +327,8 @@ class acp_bbcodes
{
$db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");
$cache->destroy('sql', BBCODES_TABLE);
- add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']);
+ $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']));
if ($request->is_ajax())
{
@@ -419,8 +422,6 @@ class acp_bbcodes
// Allow unicode characters for URL|LOCAL_URL|RELATIVE_URL|INTTEXT tokens
$utf8 = preg_match('/(URL|LOCAL_URL|RELATIVE_URL|INTTEXT)/', $bbcode_match);
- $utf8_pcre_properties = phpbb_pcre_utf8_support();
-
$fp_match = preg_quote($bbcode_match, '!');
$fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match);
$fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1:$uid]', $fp_replace);
@@ -451,7 +452,7 @@ class acp_bbcodes
'!([a-zA-Z0-9-+.,_ ]+)!' => "$1"
),
'INTTEXT' => array(
- ($utf8_pcre_properties) ? '!([\p{L}\p{N}\-+,_. ]+)!u' : '!([a-zA-Z0-9\-+,_. ]+)!u' => "$1"
+ '!([\p{L}\p{N}\-+,_. ]+)!u' => "$1"
),
'IDENTIFIER' => array(
'!([a-zA-Z0-9-_]+)!' => "$1"
@@ -471,7 +472,7 @@ class acp_bbcodes
'EMAIL' => '(' . get_preg_expression('email') . ')',
'TEXT' => '(.*?)',
'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)',
- 'INTTEXT' => ($utf8_pcre_properties) ? '([\p{L}\p{N}\-+,_. ]+)' : '([a-zA-Z0-9\-+,_. ]+)',
+ 'INTTEXT' => '([\p{L}\p{N}\-+,_. ]+)',
'IDENTIFIER' => '([a-zA-Z0-9-_]+)',
'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)',
'NUMBER' => '([0-9]+)',
@@ -479,7 +480,7 @@ class acp_bbcodes
$pad = 0;
$modifiers = 'i';
- $modifiers .= ($utf8 && $utf8_pcre_properties) ? 'u' : '';
+ $modifiers .= ($utf8) ? 'u' : '';
if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m))
{
@@ -494,7 +495,9 @@ class acp_bbcodes
if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad))
{
$repad = $pad + sizeof(array_unique($repad[0]));
- $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace);
+ $replace = preg_replace_callback('/(?<!\\\\)\$([0-9]+)/', function ($match) use ($pad) {
+ return '${' . ($match[1] + $pad) . '}';
+ }, $replace);
$pad = $repad;
}
@@ -559,10 +562,18 @@ class acp_bbcodes
trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match);
- $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace);
- $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match);
- $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace);
+ $fp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
+ return strtolower($match[0]);
+ }, $fp_match);
+ $fp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
+ return strtolower($match[0]);
+ }, $fp_replace);
+ $sp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
+ return strtolower($match[0]);
+ }, $sp_match);
+ $sp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
+ return strtolower($match[0]);
+ }, $sp_replace);
return array(
'bbcode_tag' => $bbcode_tag,
diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php
index c8f6f426c6..02af98ec54 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -30,13 +30,12 @@ class acp_board
function main($id, $mode)
{
- global $db, $user, $auth, $template;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
- global $cache, $phpbb_container, $phpbb_dispatcher;
+ global $user, $template, $request;
+ global $config, $phpbb_root_path, $phpEx;
+ global $cache, $phpbb_container, $phpbb_dispatcher, $phpbb_log;
$user->add_lang('acp/board');
- $action = request_var('action', '');
$submit = (isset($_POST['submit']) || isset($_POST['allow_quick_reply_enable'])) ? true : false;
$form_key = 'acp_board';
@@ -94,6 +93,7 @@ class acp_board
'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_board_notifications' => array('lang' => 'ALLOW_BOARD_NOTIFICATIONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -115,6 +115,7 @@ class acp_board
break;
case 'avatar':
+ /* @var $phpbb_avatar_manager \phpbb\avatar\manager */
$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
$avatar_drivers = $phpbb_avatar_manager->get_all_drivers();
@@ -414,6 +415,7 @@ class acp_board
'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'forwarded_for_check' => array('lang' => 'FORWARDED_FOR_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'referer_validation' => array('lang' => 'REFERRER_VALID', 'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true),
+ 'remote_upload_verify' => array('lang' => 'UPLOAD_CERT_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'check_dnsbl' => array('lang' => 'CHECK_DNSBL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'email_check_mx' => array('lang' => 'EMAIL_CHECK_MX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),
@@ -446,6 +448,7 @@ class acp_board
'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'email:25:100', 'explain' => true),
'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true),
'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'send_test_email' => array('lang' => 'SEND_TEST_EMAIL', 'validate' => 'bool', 'type' => 'custom', 'method' => 'send_test_email', 'explain' => true),
'legend2' => 'SMTP_SETTINGS',
'smtp_delivery' => array('lang' => 'USE_SMTP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -483,7 +486,7 @@ class acp_board
}
$this->new_config = $config;
- $cfg_array = (isset($_REQUEST['config'])) ? utf8_normalize_nfc(request_var('config', array('' => ''), true)) : $this->new_config;
+ $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : $this->new_config;
$error = array();
// We validate the complete config if wished
@@ -539,7 +542,7 @@ class acp_board
// send the password to the output
continue;
}
- set_config($config_name, $config_value);
+ $config->set($config_name, $config_value);
if ($config_name == 'allow_quick_reply' && isset($_POST['allow_quick_reply_enable']))
{
@@ -561,6 +564,7 @@ class acp_board
if ($mode == 'auth')
{
// Retrieve a list of auth plugins and check their config values
+ /* @var $auth_providers \phpbb\auth\provider_collection */
$auth_providers = $phpbb_container->get('auth.provider_collection');
$updated_auth_settings = false;
@@ -575,7 +579,7 @@ class acp_board
{
if (!isset($config[$field]))
{
- set_config($field, '');
+ $config->set($field, '');
}
if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false)
@@ -598,7 +602,7 @@ class acp_board
if ($submit)
{
$updated_auth_settings = true;
- set_config($field, $config_value);
+ $config->set($field, $config_value);
}
}
}
@@ -615,11 +619,11 @@ class acp_board
{
foreach ($old_auth_config as $config_name => $config_value)
{
- set_config($config_name, $config_value);
+ $config->set($config_name, $config_value);
}
trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
- set_config('auth_method', basename($cfg_array['auth_method']));
+ $config->set('auth_method', basename($cfg_array['auth_method']));
}
else
{
@@ -628,9 +632,33 @@ class acp_board
}
}
+ if ($mode == 'email' && $request->is_set_post('send_test_email'))
+ {
+ if ($config['email_enable'])
+ {
+ include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
+
+ $messenger = new messenger(false);
+ $messenger->template('test');
+ $messenger->set_addresses($user->data);
+ $messenger->anti_abuse_headers($config, $user);
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($user->data['username']),
+ ));
+ $messenger->send(NOTIFY_EMAIL);
+
+ trigger_error($user->lang('TEST_EMAIL_SENT') . adm_back_link($this->u_action));
+ }
+ else
+ {
+ $user->add_lang('memberlist');
+ trigger_error($user->lang('EMAIL_DISABLED') . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+ }
+
if ($submit)
{
- add_log('admin', 'LOG_CONFIG_' . strtoupper($mode));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_' . strtoupper($mode));
$message = $user->lang('CONFIG_UPDATED');
$message_type = E_USER_NOTICE;
@@ -735,10 +763,11 @@ class acp_board
*/
function select_auth_method($selected_method, $key = '')
{
- global $phpbb_root_path, $phpEx, $phpbb_container;
+ global $phpbb_container;
- $auth_plugins = array();
+ /* @var $auth_providers \phpbb\auth\provider_collection */
$auth_providers = $phpbb_container->get('auth.provider_collection');
+ $auth_plugins = array();
foreach ($auth_providers as $key => $value)
{
@@ -914,8 +943,6 @@ class acp_board
*/
function board_disable($value, $key)
{
- global $user;
-
$radio_ary = array(1 => 'YES', 0 => 'NO');
return h_radio('config[board_disable]', $radio_ary, $value) . '<br /><input id="' . $key . '" type="text" name="config[board_disable_msg]" maxlength="255" size="40" value="' . $this->new_config['board_disable_msg'] . '" />';
@@ -1025,8 +1052,6 @@ class acp_board
*/
function select_news_forums($value, $key)
{
- global $user, $config;
-
$forum_list = make_forum_select(false, false, true, true, true, false, true);
// Build forum options
@@ -1044,8 +1069,6 @@ class acp_board
function select_exclude_forums($value, $key)
{
- global $user, $config;
-
$forum_list = make_forum_select(false, false, true, true, true, false, true);
// Build forum options
@@ -1063,10 +1086,10 @@ class acp_board
function store_feed_forums($option, $key)
{
- global $db, $cache;
+ global $db, $cache, $request;
// Get key
- $values = request_var($key, array(0 => 0));
+ $values = $request->variable($key, array(0 => 0));
// Empty option bit for all forums
$sql = 'UPDATE ' . FORUMS_TABLE . '
@@ -1101,7 +1124,7 @@ class acp_board
*/
function enable_mod_rewrite($value, $key)
{
- global $user, $config;
+ global $user;
// Determine whether mod_rewrite is enabled on the server
// NOTE: This only works on Apache servers on which PHP is NOT
@@ -1135,4 +1158,11 @@ class acp_board
return h_radio($field_name, array(1 => 'YES', 0 => 'NO'), $value) .
($message !== false ? '<br /><span>' . $user->lang($message) . '</span>' : '');
}
+
+ function send_test_email($value, $key)
+ {
+ global $user;
+
+ return '<input class="button2" type="submit" id="' . $key . '" name="' . $key . '" value="' . $user->lang['SEND_TEST_EMAIL'] . '" />';
+ }
}
diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php
index 2188b90729..e89b16663c 100644
--- a/phpBB/includes/acp/acp_bots.php
+++ b/phpBB/includes/acp/acp_bots.php
@@ -25,13 +25,13 @@ class acp_bots
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $cache, $request;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
+ global $config, $db, $user, $template, $cache, $request, $phpbb_log;
+ global $phpbb_root_path, $phpEx;
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$submit = (isset($_POST['submit'])) ? true : false;
- $mark = request_var('mark', array(0));
- $bot_id = request_var('id', 0);
+ $mark = $request->variable('mark', array(0));
+ $bot_id = $request->variable('id', 0);
if (isset($_POST['add']))
{
@@ -124,7 +124,7 @@ class acp_bots
$cache->destroy('_bots');
- add_log('admin', 'LOG_BOT_DELETE', implode(', ', $bot_name_ary));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_DELETE', false, array(implode(', ', $bot_name_ary)));
trigger_error($user->lang['BOT_DELETED'] . adm_back_link($this->u_action));
}
else
@@ -148,12 +148,12 @@ class acp_bots
}
$bot_row = array(
- 'bot_name' => utf8_normalize_nfc(request_var('bot_name', '', true)),
- 'bot_agent' => request_var('bot_agent', ''),
- 'bot_ip' => request_var('bot_ip', ''),
- 'bot_active' => request_var('bot_active', true),
- 'bot_lang' => request_var('bot_lang', $config['default_lang']),
- 'bot_style' => request_var('bot_style' , $config['default_style']),
+ 'bot_name' => $request->variable('bot_name', '', true),
+ 'bot_agent' => $request->variable('bot_agent', ''),
+ 'bot_ip' => $request->variable('bot_ip', ''),
+ 'bot_active' => $request->variable('bot_active', true),
+ 'bot_lang' => $request->variable('bot_lang', $config['default_lang']),
+ 'bot_style' => $request->variable('bot_style' , $config['default_style']),
);
if ($submit)
@@ -296,7 +296,7 @@ class acp_bots
$cache->destroy('_bots');
- add_log('admin', 'LOG_BOT_' . $log, $bot_row['bot_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_' . $log, false, array($bot_row['bot_name']));
trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action));
}
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php
index 92d5e1dda6..b49c5ca0d3 100644
--- a/phpBB/includes/acp/acp_captcha.php
+++ b/phpBB/includes/acp/acp_captcha.php
@@ -25,17 +25,18 @@ class acp_captcha
function main($id, $mode)
{
- global $request, $user, $auth, $template;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container;
+ global $user, $template, $phpbb_log, $request;
+ global $config, $phpbb_container;
$user->add_lang('acp/board');
+ /* @var $factory \phpbb\captcha\factory */
$factory = $phpbb_container->get('captcha.factory');
$captchas = $factory->get_captcha_types();
- $selected = request_var('select_captcha', $config['captcha_plugin']);
+ $selected = $request->variable('select_captcha', $config['captcha_plugin']);
$selected = (isset($captchas['available'][$selected]) || isset($captchas['unavailable'][$selected])) ? $selected : $config['captcha_plugin'];
- $configure = request_var('configure', false);
+ $configure = $request->variable('configure', false);
// Oh, they are just here for the view
if (isset($_GET['captcha_demo']))
@@ -89,7 +90,7 @@ class acp_captcha
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('main_submit', false);
+ $submit = $request->variable('main_submit', false);
$error = $cfg_array = array();
if ($submit)
@@ -125,11 +126,11 @@ class acp_captcha
$old_captcha = $factory->get_instance($config['captcha_plugin']);
$old_captcha->uninstall();
- set_config('captcha_plugin', $selected);
+ $config->set('captcha_plugin', $selected);
$new_captcha = $factory->get_instance($config['captcha_plugin']);
$new_captcha->install();
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
}
else
{
@@ -157,7 +158,7 @@ class acp_captcha
foreach ($config_vars as $config_var => $options)
{
- $template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? request_var($config_var, $options['default']) : $config[$config_var]) ;
+ $template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? $request->variable($config_var, $options['default']) : $config[$config_var]) ;
}
$template->assign_vars(array(
@@ -177,7 +178,7 @@ class acp_captcha
*/
function deliver_demo($selected)
{
- global $db, $user, $config, $phpbb_container;
+ global $phpbb_container;
$captcha = $phpbb_container->get('captcha.factory')->get_instance($selected);
$captcha->init(CONFIRM_REG);
diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php
index 4e46df21e0..1a4d5b95a3 100644
--- a/phpBB/includes/acp/acp_contact.php
+++ b/phpBB/includes/acp/acp_contact.php
@@ -48,6 +48,7 @@ class acp_contact
include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
}
+ /* @var $config_text \phpbb\config\db_text */
$config_text = $phpbb_container->get('config_text');
$contact_admin_data = $config_text->get_array(array(
@@ -104,6 +105,9 @@ class acp_contact
$contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags);
+ /** @var \phpbb\controller\helper $controller_helper */
+ $controller_helper = $phpbb_container->get('controller.helper');
+
$template->assign_vars(array(
'ERRORS' => $error,
'CONTACT_ENABLED' => $config['contact_admin_form_enable'],
@@ -115,7 +119,7 @@ class acp_contact
'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'],
'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'],
- 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
+ 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'],
'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'],
'FLASH_STATUS' => $user->lang['FLASH_IS_ON'],
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php
index dd0599e06a..00c7ef40c0 100644
--- a/phpBB/includes/acp/acp_database.php
+++ b/phpBB/includes/acp/acp_database.php
@@ -26,18 +26,17 @@ class acp_database
function main($id, $mode)
{
- global $cache, $db, $user, $auth, $template, $table_prefix;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $cache, $db, $user, $template, $table_prefix, $request;
+ global $phpbb_root_path, $phpbb_container, $phpbb_log;
- $this->db_tools = new \phpbb\db\tools($db);
+ $this->db_tools = $phpbb_container->get('dbal.tools');
$user->add_lang('acp/database');
$this->tpl_name = 'acp_database';
$this->page_title = 'ACP_DATABASE';
- $action = request_var('action', '');
- $submit = (isset($_POST['submit'])) ? true : false;
+ $action = $request->variable('action', '');
$form_key = 'acp_database';
add_form_key($form_key);
@@ -55,10 +54,10 @@ class acp_database
switch ($action)
{
case 'download':
- $type = request_var('type', '');
- $table = array_intersect($this->db_tools->sql_list_tables(), request_var('table', array('')));
- $format = request_var('method', '');
- $where = request_var('where', '');
+ $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))
{
@@ -98,36 +97,9 @@ class acp_database
$time = time();
$filename = 'backup_' . $time . '_' . unique_id();
- switch ($db->get_sql_layer())
- {
- case 'mysqli':
- case 'mysql4':
- case 'mysql':
- $extractor = new mysql_extractor($format, $filename, $time, $download, $store);
- break;
-
- case 'sqlite':
- $extractor = new sqlite_extractor($format, $filename, $time, $download, $store);
- break;
- case 'sqlite3':
- $extractor = new sqlite3_extractor($format, $filename, $time, $download, $store);
- break;
-
- case 'postgres':
- $extractor = new postgres_extractor($format, $filename, $time, $download, $store);
- break;
-
- case 'oracle':
- $extractor = new oracle_extractor($format, $filename, $time, $download, $store);
- break;
-
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $extractor = new mssql_extractor($format, $filename, $time, $download, $store);
- break;
- }
+ $extractor = $phpbb_container->get('dbal.extractor');
+ $extractor->init_extractor($format, $filename, $time, $download, $store);
$extractor->write_start($table_prefix);
@@ -143,12 +115,10 @@ class acp_database
// We might wanna empty out all that junk :D
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$extractor->flush('DELETE FROM ' . $table_name . ";\n");
break;
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n");
@@ -173,7 +143,7 @@ class acp_database
$extractor->write_end();
- add_log('admin', 'LOG_DB_BACKUP');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP');
if ($download == true)
{
@@ -229,9 +199,9 @@ class acp_database
switch ($action)
{
case 'submit':
- $delete = request_var('delete', '');
- $file = request_var('file', '');
- $download = request_var('download', '');
+ $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))
{
@@ -250,7 +220,7 @@ class acp_database
if (confirm_box(true))
{
unlink($file_name);
- add_log('admin', 'LOG_DB_DELETE');
+ $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));
}
else
@@ -333,7 +303,6 @@ class acp_database
case 'mysql':
case 'mysql4':
case 'mysqli':
- case 'sqlite':
case 'sqlite3':
while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false)
{
@@ -388,7 +357,6 @@ class acp_database
}
break;
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false)
@@ -403,7 +371,7 @@ class acp_database
// Purge the cache due to updated data
$cache->purge();
- add_log('admin', 'LOG_DB_RESTORE');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_RESTORE');
trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action));
break;
}
@@ -469,1637 +437,6 @@ class acp_database
}
}
-class base_extractor
-{
- var $fh;
- var $fp;
- var $write;
- var $close;
- var $store;
- var $download;
- var $time;
- var $format;
- var $run_comp = false;
-
- function base_extractor($format, $filename, $time, $download = false, $store = false)
- {
- global $request;
-
- $this->download = $download;
- $this->store = $store;
- $this->time = $time;
- $this->format = $format;
-
- switch ($format)
- {
- case 'text':
- $ext = '.sql';
- $open = 'fopen';
- $this->write = 'fwrite';
- $this->close = 'fclose';
- $mimetype = 'text/x-sql';
- break;
- case 'bzip2':
- $ext = '.sql.bz2';
- $open = 'bzopen';
- $this->write = 'bzwrite';
- $this->close = 'bzclose';
- $mimetype = 'application/x-bzip2';
- break;
- case 'gzip':
- $ext = '.sql.gz';
- $open = 'gzopen';
- $this->write = 'gzwrite';
- $this->close = 'gzclose';
- $mimetype = 'application/x-gzip';
- break;
- }
-
- if ($download == true)
- {
- $name = $filename . $ext;
- header('Cache-Control: private, no-cache');
- header("Content-Type: $mimetype; name=\"$name\"");
- header("Content-disposition: attachment; filename=$name");
-
- switch ($format)
- {
- case 'bzip2':
- ob_start();
- break;
-
- case 'gzip':
- if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false)
- {
- ob_start('ob_gzhandler');
- }
- else
- {
- $this->run_comp = true;
- }
- break;
- }
- }
-
- if ($store == true)
- {
- global $phpbb_root_path;
- $file = $phpbb_root_path . 'store/' . $filename . $ext;
-
- $this->fp = $open($file, 'w');
-
- if (!$this->fp)
- {
- trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
- }
- }
- }
-
- function write_end()
- {
- static $close;
-
- if ($this->store)
- {
- if ($close === null)
- {
- $close = $this->close;
- }
- $close($this->fp);
- }
-
- // bzip2 must be written all the way at the end
- if ($this->download && $this->format === 'bzip2')
- {
- $c = ob_get_clean();
- echo bzcompress($c);
- }
- }
-
- function flush($data)
- {
- static $write;
- if ($this->store === true)
- {
- if ($write === null)
- {
- $write = $this->write;
- }
- $write($this->fp, $data);
- }
-
- if ($this->download === true)
- {
- if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp))
- {
- echo $data;
- }
-
- // we can write the gzip data as soon as we get it
- if ($this->format === 'gzip')
- {
- if ($this->run_comp)
- {
- echo gzencode($data);
- }
- else
- {
- ob_flush();
- flush();
- }
- }
- }
- }
-}
-
-class mysql_extractor extends base_extractor
-{
- function write_start($table_prefix)
- {
- $sql_data = "#\n";
- $sql_data .= "# phpBB Backup Script\n";
- $sql_data .= "# Dump of tables for $table_prefix\n";
- $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
- $sql_data .= "#\n";
- $this->flush($sql_data);
- }
-
- function write_table($table_name)
- {
- global $db;
- static $new_extract;
-
- if ($new_extract === null)
- {
- if ($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>='))
- {
- $new_extract = true;
- }
- else
- {
- $new_extract = false;
- }
- }
-
- if ($new_extract)
- {
- $this->new_write_table($table_name);
- }
- else
- {
- $this->old_write_table($table_name);
- }
- }
-
- function write_data($table_name)
- {
- global $db;
- if ($db->get_sql_layer() === 'mysqli')
- {
- $this->write_data_mysqli($table_name);
- }
- else
- {
- $this->write_data_mysql($table_name);
- }
- }
-
- function write_data_mysqli($table_name)
- {
- global $db;
- $sql = "SELECT *
- FROM $table_name";
- $result = mysqli_query($db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT);
- if ($result != false)
- {
- $fields_cnt = mysqli_num_fields($result);
-
- // Get field information
- $field = mysqli_fetch_fields($result);
- $field_set = array();
-
- for ($j = 0; $j < $fields_cnt; $j++)
- {
- $field_set[] = $field[$j]->name;
- }
-
- $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
- $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
- $fields = implode(', ', $field_set);
- $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
- $first_set = true;
- $query_len = 0;
- $max_len = get_usable_memory();
-
- while ($row = mysqli_fetch_row($result))
- {
- $values = array();
- if ($first_set)
- {
- $query = $sql_data . '(';
- }
- else
- {
- $query .= ',(';
- }
-
- for ($j = 0; $j < $fields_cnt; $j++)
- {
- if (!isset($row[$j]) || is_null($row[$j]))
- {
- $values[$j] = 'NULL';
- }
- else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
- {
- $values[$j] = $row[$j];
- }
- else
- {
- $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
- }
- }
- $query .= implode(', ', $values) . ')';
-
- $query_len += strlen($query);
- if ($query_len > $max_len)
- {
- $this->flush($query . ";\n\n");
- $query = '';
- $query_len = 0;
- $first_set = true;
- }
- else
- {
- $first_set = false;
- }
- }
- mysqli_free_result($result);
-
- // check to make sure we have nothing left to flush
- if (!$first_set && $query)
- {
- $this->flush($query . ";\n\n");
- }
- }
- }
-
- function write_data_mysql($table_name)
- {
- global $db;
- $sql = "SELECT *
- FROM $table_name";
- $result = mysql_unbuffered_query($sql, $db->get_db_connect_id());
-
- if ($result != false)
- {
- $fields_cnt = mysql_num_fields($result);
-
- // Get field information
- $field = array();
- for ($i = 0; $i < $fields_cnt; $i++)
- {
- $field[] = mysql_fetch_field($result, $i);
- }
- $field_set = array();
-
- for ($j = 0; $j < $fields_cnt; $j++)
- {
- $field_set[] = $field[$j]->name;
- }
-
- $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
- $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
- $fields = implode(', ', $field_set);
- $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
- $first_set = true;
- $query_len = 0;
- $max_len = get_usable_memory();
-
- while ($row = mysql_fetch_row($result))
- {
- $values = array();
- if ($first_set)
- {
- $query = $sql_data . '(';
- }
- else
- {
- $query .= ',(';
- }
-
- for ($j = 0; $j < $fields_cnt; $j++)
- {
- if (!isset($row[$j]) || is_null($row[$j]))
- {
- $values[$j] = 'NULL';
- }
- else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
- {
- $values[$j] = $row[$j];
- }
- else
- {
- $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
- }
- }
- $query .= implode(', ', $values) . ')';
-
- $query_len += strlen($query);
- if ($query_len > $max_len)
- {
- $this->flush($query . ";\n\n");
- $query = '';
- $query_len = 0;
- $first_set = true;
- }
- else
- {
- $first_set = false;
- }
- }
- mysql_free_result($result);
-
- // check to make sure we have nothing left to flush
- if (!$first_set && $query)
- {
- $this->flush($query . ";\n\n");
- }
- }
- }
-
- function new_write_table($table_name)
- {
- global $db;
-
- $sql = 'SHOW CREATE TABLE ' . $table_name;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
-
- $sql_data = '# Table: ' . $table_name . "\n";
- $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
- $this->flush($sql_data . $row['Create Table'] . ";\n\n");
-
- $db->sql_freeresult($result);
- }
-
- function old_write_table($table_name)
- {
- global $db;
-
- $sql_data = '# Table: ' . $table_name . "\n";
- $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
- $sql_data .= "CREATE TABLE $table_name(\n";
- $rows = array();
-
- $sql = "SHOW FIELDS
- FROM $table_name";
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $line = ' ' . $row['Field'] . ' ' . $row['Type'];
-
- if (!is_null($row['Default']))
- {
- $line .= " DEFAULT '{$row['Default']}'";
- }
-
- if ($row['Null'] != 'YES')
- {
- $line .= ' NOT NULL';
- }
-
- if ($row['Extra'] != '')
- {
- $line .= ' ' . $row['Extra'];
- }
-
- $rows[] = $line;
- }
- $db->sql_freeresult($result);
-
- $sql = "SHOW KEYS
- FROM $table_name";
-
- $result = $db->sql_query($sql);
-
- $index = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $kname = $row['Key_name'];
-
- if ($kname != 'PRIMARY')
- {
- if ($row['Non_unique'] == 0)
- {
- $kname = "UNIQUE|$kname";
- }
- }
-
- if ($row['Sub_part'])
- {
- $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
- }
- $index[$kname][] = $row['Column_name'];
- }
- $db->sql_freeresult($result);
-
- foreach ($index as $key => $columns)
- {
- $line = ' ';
-
- if ($key == 'PRIMARY')
- {
- $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
- }
- else if (strpos($key, 'UNIQUE') === 0)
- {
- $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
- }
- else if (strpos($key, 'FULLTEXT') === 0)
- {
- $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
- }
- else
- {
- $line .= "KEY $key (" . implode(', ', $columns) . ')';
- }
-
- $rows[] = $line;
- }
-
- $sql_data .= implode(",\n", $rows);
- $sql_data .= "\n);\n\n";
-
- $this->flush($sql_data);
- }
-}
-
-class sqlite_extractor extends base_extractor
-{
- function write_start($prefix)
- {
- $sql_data = "--\n";
- $sql_data .= "-- phpBB Backup Script\n";
- $sql_data .= "-- Dump of tables for $prefix\n";
- $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
- $sql_data .= "--\n";
- $sql_data .= "BEGIN TRANSACTION;\n";
- $this->flush($sql_data);
- }
-
- function write_table($table_name)
- {
- global $db;
- $sql_data = '-- Table: ' . $table_name . "\n";
- $sql_data .= "DROP TABLE $table_name;\n";
-
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'table'
- AND name = '" . $db->sql_escape($table_name) . "'
- ORDER BY type DESC, name;";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- // Create Table
- $sql_data .= $row['sql'] . ";\n";
-
- $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
-
- $ar = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $ar[] = $row;
- }
- $db->sql_freeresult($result);
-
- foreach ($ar as $value)
- {
- if (strpos($value['name'], 'autoindex') !== false)
- {
- continue;
- }
-
- $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');");
-
- $fields = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $fields[] = $row['name'];
- }
- $db->sql_freeresult($result);
-
- $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
- }
-
- $this->flush($sql_data . "\n");
- }
-
- function write_data($table_name)
- {
- global $db;
-
- $col_types = sqlite_fetch_column_types($db->get_db_connect_id(), $table_name);
-
- $sql = "SELECT *
- FROM $table_name";
- $result = sqlite_unbuffered_query($db->get_db_connect_id(), $sql);
- $rows = sqlite_fetch_all($result, SQLITE_ASSOC);
- $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
- foreach ($rows as $row)
- {
- foreach ($row as $column_name => $column_data)
- {
- if (is_null($column_data))
- {
- $row[$column_name] = 'NULL';
- }
- else if ($column_data == '')
- {
- $row[$column_name] = "''";
- }
- else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false)
- {
- $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
- }
- }
- $this->flush($sql_insert . implode(', ', $row) . ");\n");
- }
- }
-
- function write_end()
- {
- $this->flush("COMMIT;\n");
- parent::write_end();
- }
-}
-
-class sqlite3_extractor extends base_extractor
-{
- function write_start($prefix)
- {
- $sql_data = "--\n";
- $sql_data .= "-- phpBB Backup Script\n";
- $sql_data .= "-- Dump of tables for $prefix\n";
- $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
- $sql_data .= "--\n";
- $sql_data .= "BEGIN TRANSACTION;\n";
- $this->flush($sql_data);
- }
-
- function write_table($table_name)
- {
- global $db;
- $sql_data = '-- Table: ' . $table_name . "\n";
- $sql_data .= "DROP TABLE $table_name;\n";
-
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'table'
- AND name = '" . $db->sql_escape($table_name) . "'
- ORDER BY name ASC;";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- // Create Table
- $sql_data .= $row['sql'] . ";\n";
-
- $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
-
- while ($row = $db->sql_fetchrow($result))
- {
- if (strpos($row['name'], 'autoindex') !== false)
- {
- continue;
- }
-
- $result2 = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($row['name']) . "');");
-
- $fields = array();
- while ($row2 = $db->sql_fetchrow($result2))
- {
- $fields[] = $row2['name'];
- }
- $db->sql_freeresult($result2);
-
- $sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
- }
- $db->sql_freeresult($result);
-
- $this->flush($sql_data . "\n");
- }
-
- function write_data($table_name)
- {
- global $db;
-
- $result = $db->sql_query("PRAGMA table_info('" . $db->sql_escape($table_name) . "');");
-
- $col_types = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $col_types[$row['name']] = $row['type'];
- }
- $db->sql_freeresult($result);
-
- $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
-
- $sql = "SELECT *
- FROM $table_name";
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- foreach ($row as $column_name => $column_data)
- {
- if (is_null($column_data))
- {
- $row[$column_name] = 'NULL';
- }
- else if ($column_data === '')
- {
- $row[$column_name] = "''";
- }
- else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false)
- {
- $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
- }
- }
- $this->flush($sql_insert . implode(', ', $row) . ");\n");
- }
- }
-
- function write_end()
- {
- $this->flush("COMMIT;\n");
- parent::write_end();
- }
-}
-
-class postgres_extractor extends base_extractor
-{
- function write_start($prefix)
- {
- $sql_data = "--\n";
- $sql_data .= "-- phpBB Backup Script\n";
- $sql_data .= "-- Dump of tables for $prefix\n";
- $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
- $sql_data .= "--\n";
- $sql_data .= "BEGIN TRANSACTION;\n";
- $this->flush($sql_data);
- }
-
- function write_table($table_name)
- {
- global $db;
- static $domains_created = array();
-
- $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default
- FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b
- WHERE a.domain_name = b.domain_name
- AND b.table_name = '{$table_name}'";
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- if (empty($domains_created[$row['domain_name']]))
- {
- $domains_created[$row['domain_name']] = true;
- //$sql_data = "DROP DOMAIN {$row['domain_name']};\n";
- $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}";
- if (!empty($row['character_maximum_length']))
- {
- $sql_data .= '(' . $row['character_maximum_length'] . ')';
- }
- $sql_data .= ' NOT NULL';
- if (!empty($row['domain_default']))
- {
- $sql_data .= ' DEFAULT ' . $row['domain_default'];
- }
- $this->flush($sql_data . ";\n");
- }
- }
- $db->sql_freeresult($result);
-
- $sql_data = '-- Table: ' . $table_name . "\n";
- $sql_data .= "DROP TABLE $table_name;\n";
- // PGSQL does not "tightly" bind sequences and tables, we must guess...
- $sql = "SELECT relname
- FROM pg_class
- WHERE relkind = 'S'
- AND relname = '{$table_name}_seq'";
- $result = $db->sql_query($sql);
- // We don't even care about storing the results. We already know the answer if we get rows back.
- if ($db->sql_fetchrow($result))
- {
- $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n";
- $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
- }
- $db->sql_freeresult($result);
-
- $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull
- FROM pg_class c, pg_attribute a, pg_type t
- WHERE c.relname = '" . $db->sql_escape($table_name) . "'
- AND a.attnum > 0
- AND a.attrelid = c.oid
- AND a.atttypid = t.oid
- ORDER BY a.attnum";
- $result = $db->sql_query($field_query);
-
- $sql_data .= "CREATE TABLE $table_name(\n";
- $lines = array();
- while ($row = $db->sql_fetchrow($result))
- {
- // Get the data from the table
- $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
- FROM pg_attrdef d, pg_class c
- WHERE (c.relname = '" . $db->sql_escape($table_name) . "')
- AND (c.oid = d.adrelid)
- AND d.adnum = " . $row['attnum'];
- $def_res = $db->sql_query($sql_get_default);
- $def_row = $db->sql_fetchrow($def_res);
- $db->sql_freeresult($def_res);
-
- if (empty($def_row))
- {
- unset($row['rowdefault']);
- }
- else
- {
- $row['rowdefault'] = $def_row['rowdefault'];
- }
-
- if ($row['type'] == 'bpchar')
- {
- // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
- $row['type'] = 'char';
- }
-
- $line = ' ' . $row['field'] . ' ' . $row['type'];
-
- if (strpos($row['type'], 'char') !== false)
- {
- if ($row['lengthvar'] > 0)
- {
- $line .= '(' . ($row['lengthvar'] - 4) . ')';
- }
- }
-
- if (strpos($row['type'], 'numeric') !== false)
- {
- $line .= '(';
- $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
- $line .= ')';
- }
-
- if (isset($row['rowdefault']))
- {
- $line .= ' DEFAULT ' . $row['rowdefault'];
- }
-
- if ($row['notnull'] == 't')
- {
- $line .= ' NOT NULL';
- }
-
- $lines[] = $line;
- }
- $db->sql_freeresult($result);
-
- // Get the listing of primary keys.
- $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key
- FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (ia.attrelid = i.indexrelid)
- AND (ta.attrelid = bc.oid)
- AND (bc.relname = '" . $db->sql_escape($table_name) . "')
- AND (ta.attrelid = i.indrelid)
- AND (ta.attnum = i.indkey[ia.attnum-1])
- ORDER BY index_name, tab_name, column_name";
-
- $result = $db->sql_query($sql_pri_keys);
-
- $index_create = $index_rows = $primary_key = array();
-
- // We do this in two steps. It makes placing the comma easier
- while ($row = $db->sql_fetchrow($result))
- {
- if ($row['primary_key'] == 't')
- {
- $primary_key[] = $row['column_name'];
- $primary_key_name = $row['index_name'];
- }
- else
- {
- // We have to store this all this info because it is possible to have a multi-column key...
- // we can loop through it again and build the statement
- $index_rows[$row['index_name']]['table'] = $table_name;
- $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false;
- $index_rows[$row['index_name']]['column_names'][] = $row['column_name'];
- }
- }
- $db->sql_freeresult($result);
-
- if (!empty($index_rows))
- {
- foreach ($index_rows as $idx_name => $props)
- {
- $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");";
- }
- }
-
- if (!empty($primary_key))
- {
- $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")";
- }
-
- // Generate constraint clauses for CHECK constraints
- $sql_checks = "SELECT conname as index_name, consrc
- FROM pg_constraint, pg_class bc
- WHERE conrelid = bc.oid
- AND bc.relname = '" . $db->sql_escape($table_name) . "'
- AND NOT EXISTS (
- SELECT *
- FROM pg_constraint as c, pg_inherits as i
- WHERE i.inhrelid = pg_constraint.conrelid
- AND c.conname = pg_constraint.conname
- AND c.consrc = pg_constraint.consrc
- AND c.conrelid = i.inhparent
- )";
- $result = $db->sql_query($sql_checks);
-
- // Add the constraints to the sql file.
- while ($row = $db->sql_fetchrow($result))
- {
- if (!is_null($row['consrc']))
- {
- $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
- }
- }
- $db->sql_freeresult($result);
-
- $sql_data .= implode(", \n", $lines);
- $sql_data .= "\n);\n";
-
- if (!empty($index_create))
- {
- $sql_data .= implode("\n", $index_create) . "\n\n";
- }
- $this->flush($sql_data);
- }
-
- function write_data($table_name)
- {
- global $db;
- // Grab all of the data from current table.
- $sql = "SELECT *
- FROM $table_name";
- $result = $db->sql_query($sql);
-
- $i_num_fields = pg_num_fields($result);
- $seq = '';
-
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $ary_type[] = pg_field_type($result, $i);
- $ary_name[] = pg_field_name($result, $i);
-
- $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
- FROM pg_attrdef d, pg_class c
- WHERE (c.relname = '{$table_name}')
- AND (c.oid = d.adrelid)
- AND d.adnum = " . strval($i + 1);
- $result2 = $db->sql_query($sql);
- if ($row = $db->sql_fetchrow($result2))
- {
- // Determine if we must reset the sequences
- if (strpos($row['rowdefault'], "nextval('") === 0)
- {
- $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n";
- }
- }
- }
-
- $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n");
- while ($row = $db->sql_fetchrow($result))
- {
- $schema_vals = array();
-
- // Build the SQL statement to recreate the data.
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $str_val = $row[$ary_name[$i]];
-
- if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
- {
- $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val));
- $str_empty = '';
- }
- else
- {
- $str_empty = '\N';
- }
-
- if (empty($str_val) && $str_val !== '0')
- {
- $str_val = $str_empty;
- }
-
- $schema_vals[] = $str_val;
- }
-
- // Take the ordered fields and their associated data and build it
- // into a valid sql statement to recreate that field in the data.
- $this->flush(implode("\t", $schema_vals) . "\n");
- }
- $db->sql_freeresult($result);
- $this->flush("\\.\n");
-
- // Write out the sequence statements
- $this->flush($seq);
- }
-
- function write_end()
- {
- $this->flush("COMMIT;\n");
- parent::write_end();
- }
-}
-
-class mssql_extractor extends base_extractor
-{
- function write_end()
- {
- $this->flush("COMMIT\nGO\n");
- parent::write_end();
- }
-
- function write_start($prefix)
- {
- $sql_data = "--\n";
- $sql_data .= "-- phpBB Backup Script\n";
- $sql_data .= "-- Dump of tables for $prefix\n";
- $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
- $sql_data .= "--\n";
- $sql_data .= "BEGIN TRANSACTION\n";
- $sql_data .= "GO\n";
- $this->flush($sql_data);
- }
-
- function write_table($table_name)
- {
- global $db;
- $sql_data = '-- Table: ' . $table_name . "\n";
- $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n";
- $sql_data .= "DROP TABLE $table_name;\n";
- $sql_data .= "GO\n";
- $sql_data .= "\nCREATE TABLE [$table_name] (\n";
- $rows = array();
-
- $text_flag = false;
-
- $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY
- FROM INFORMATION_SCHEMA.COLUMNS
- WHERE TABLE_NAME = '$table_name'";
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]";
-
- if ($row['DATA_TYPE'] == 'text')
- {
- $text_flag = true;
- }
-
- if ($row['IS_IDENTITY'])
- {
- $line .= ' IDENTITY (1 , 1)';
- }
-
- if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text')
- {
- $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')';
- }
-
- if ($row['IS_NULLABLE'] == 'YES')
- {
- $line .= ' NULL';
- }
- else
- {
- $line .= ' NOT NULL';
- }
-
- if ($row['COLUMN_DEFAULT'])
- {
- $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT'];
- }
-
- $rows[] = $line;
- }
- $db->sql_freeresult($result);
-
- $sql_data .= implode(",\n", $rows);
- $sql_data .= "\n) ON [PRIMARY]";
-
- if ($text_flag)
- {
- $sql_data .= " TEXTIMAGE_ON [PRIMARY]";
- }
-
- $sql_data .= "\nGO\n\n";
- $rows = array();
-
- $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME
- FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
- WHERE TABLE_NAME = '$table_name'";
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- if (!sizeof($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))
- {
- $sql_data .= implode(",\n", $rows);
- $sql_data .= "\n\t) ON [PRIMARY] \nGO\n";
- }
- $db->sql_freeresult($result);
-
- $index = array();
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- if ($row['TYPE'] == 3)
- {
- $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
- }
- }
- $db->sql_freeresult($result);
-
- foreach ($index as $index_name => $column_name)
- {
- $index[$index_name] = implode(', ', $column_name);
- }
-
- foreach ($index as $index_name => $columns)
- {
- $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n";
- }
- $this->flush($sql_data);
- }
-
- function write_data($table_name)
- {
- global $db;
-
- if ($db->get_sql_layer() === 'mssql')
- {
- $this->write_data_mssql($table_name);
- }
- else if ($db->get_sql_layer() === 'mssqlnative')
- {
- $this->write_data_mssqlnative($table_name);
- }
- else
- {
- $this->write_data_odbc($table_name);
- }
- }
-
- function write_data_mssql($table_name)
- {
- global $db;
- $ary_type = $ary_name = array();
- $ident_set = false;
- $sql_data = '';
-
- // Grab all of the data from current table.
- $sql = "SELECT *
- FROM $table_name";
- $result = $db->sql_query($sql);
-
- $retrieved_data = mssql_num_rows($result);
-
- $i_num_fields = mssql_num_fields($result);
-
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $ary_type[$i] = mssql_field_type($result, $i);
- $ary_name[$i] = mssql_field_name($result, $i);
- }
-
- if ($retrieved_data)
- {
- $sql = "SELECT 1 as has_identity
- FROM INFORMATION_SCHEMA.COLUMNS
- WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
- $result2 = $db->sql_query($sql);
- $row2 = $db->sql_fetchrow($result2);
- if (!empty($row2['has_identity']))
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
- $ident_set = true;
- }
- $db->sql_freeresult($result2);
- }
-
- while ($row = $db->sql_fetchrow($result))
- {
- $schema_vals = $schema_fields = array();
-
- // Build the SQL statement to recreate the data.
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $str_val = $row[$ary_name[$i]];
-
- if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
- {
- $str_quote = '';
- $str_empty = "''";
- $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
- }
- else if (preg_match('#date|timestamp#i', $ary_type[$i]))
- {
- if (empty($str_val))
- {
- $str_quote = '';
- }
- else
- {
- $str_quote = "'";
- }
- }
- else
- {
- $str_quote = '';
- $str_empty = 'NULL';
- }
-
- if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
- {
- $str_val = $str_empty;
- }
-
- $schema_vals[$i] = $str_quote . $str_val . $str_quote;
- $schema_fields[$i] = $ary_name[$i];
- }
-
- // Take the ordered fields and their associated data and build it
- // into a valid sql statement to recreate that field in the data.
- $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
-
- $this->flush($sql_data);
- $sql_data = '';
- }
- $db->sql_freeresult($result);
-
- if ($retrieved_data && $ident_set)
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
- }
- $this->flush($sql_data);
- }
-
- function write_data_mssqlnative($table_name)
- {
- global $db;
- $ary_type = $ary_name = array();
- $ident_set = false;
- $sql_data = '';
-
- // Grab all of the data from current table.
- $sql = "SELECT * FROM $table_name";
- $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
- $result = $db->sql_query($sql);
-
- $retrieved_data = $db->mssqlnative_num_rows($result);
-
- if (!$retrieved_data)
- {
- $db->sql_freeresult($result);
- return;
- }
-
- $sql = "SELECT COLUMN_NAME, DATA_TYPE
- FROM INFORMATION_SCHEMA.COLUMNS
- WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'";
- $result_fields = $db->sql_query($sql);
-
- $i_num_fields = 0;
- while ($row = $db->sql_fetchrow($result_fields))
- {
- $ary_type[$i_num_fields] = $row['DATA_TYPE'];
- $ary_name[$i_num_fields] = $row['COLUMN_NAME'];
- $i_num_fields++;
- }
- $db->sql_freeresult($result_fields);
-
- $sql = "SELECT 1 as has_identity
- FROM INFORMATION_SCHEMA.COLUMNS
- WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
- $result2 = $db->sql_query($sql);
- $row2 = $db->sql_fetchrow($result2);
-
- if (!empty($row2['has_identity']))
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
- $ident_set = true;
- }
- $db->sql_freeresult($result2);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $schema_vals = $schema_fields = array();
-
- // Build the SQL statement to recreate the data.
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $str_val = $row[$ary_name[$i]];
-
- // defaults to type number - better quote just to be safe, so check for is_int too
- if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
- {
- $str_quote = '';
- $str_empty = "''";
- $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
- }
- else if (preg_match('#date|timestamp#i', $ary_type[$i]))
- {
- if (empty($str_val))
- {
- $str_quote = '';
- }
- else
- {
- $str_quote = "'";
- }
- }
- else
- {
- $str_quote = '';
- $str_empty = 'NULL';
- }
-
- if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
- {
- $str_val = $str_empty;
- }
-
- $schema_vals[$i] = $str_quote . $str_val . $str_quote;
- $schema_fields[$i] = $ary_name[$i];
- }
-
- // Take the ordered fields and their associated data and build it
- // into a valid sql statement to recreate that field in the data.
- $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
-
- $this->flush($sql_data);
- $sql_data = '';
- }
- $db->sql_freeresult($result);
-
- if ($ident_set)
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
- }
- $this->flush($sql_data);
- }
-
- function write_data_odbc($table_name)
- {
- global $db;
- $ary_type = $ary_name = array();
- $ident_set = false;
- $sql_data = '';
-
- // Grab all of the data from current table.
- $sql = "SELECT *
- FROM $table_name";
- $result = $db->sql_query($sql);
-
- $retrieved_data = odbc_num_rows($result);
-
- if ($retrieved_data)
- {
- $sql = "SELECT 1 as has_identity
- FROM INFORMATION_SCHEMA.COLUMNS
- WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
- $result2 = $db->sql_query($sql);
- $row2 = $db->sql_fetchrow($result2);
- if (!empty($row2['has_identity']))
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
- $ident_set = true;
- }
- $db->sql_freeresult($result2);
- }
-
- $i_num_fields = odbc_num_fields($result);
-
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $ary_type[$i] = odbc_field_type($result, $i + 1);
- $ary_name[$i] = odbc_field_name($result, $i + 1);
- }
-
- while ($row = $db->sql_fetchrow($result))
- {
- $schema_vals = $schema_fields = array();
-
- // Build the SQL statement to recreate the data.
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $str_val = $row[$ary_name[$i]];
-
- if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
- {
- $str_quote = '';
- $str_empty = "''";
- $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
- }
- else if (preg_match('#date|timestamp#i', $ary_type[$i]))
- {
- if (empty($str_val))
- {
- $str_quote = '';
- }
- else
- {
- $str_quote = "'";
- }
- }
- else
- {
- $str_quote = '';
- $str_empty = 'NULL';
- }
-
- if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
- {
- $str_val = $str_empty;
- }
-
- $schema_vals[$i] = $str_quote . $str_val . $str_quote;
- $schema_fields[$i] = $ary_name[$i];
- }
-
- // Take the ordered fields and their associated data and build it
- // into a valid sql statement to recreate that field in the data.
- $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
-
- $this->flush($sql_data);
-
- $sql_data = '';
-
- }
- $db->sql_freeresult($result);
-
- if ($retrieved_data && $ident_set)
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
- }
- $this->flush($sql_data);
- }
-
-}
-
-class oracle_extractor extends base_extractor
-{
- function write_table($table_name)
- {
- global $db;
- $sql_data = '-- Table: ' . $table_name . "\n";
- $sql_data .= "DROP TABLE $table_name\n/\n";
- $sql_data .= "\nCREATE TABLE $table_name (\n";
-
- $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT
- FROM ALL_TAB_COLS
- WHERE table_name = '{$table_name}'";
- $result = $db->sql_query($sql);
-
- $rows = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $line = ' "' . $row['column_name'] . '" ' . $row['data_type'];
-
- if ($row['data_type'] !== 'CLOB')
- {
- if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR')
- {
- $line .= '(' . $row['data_precision'] . ')';
- }
- else
- {
- $line .= '(' . $row['data_length'] . ')';
- }
- }
-
- if (!empty($row['data_default']))
- {
- $line .= ' DEFAULT ' . $row['data_default'];
- }
-
- if ($row['nullable'] == 'N')
- {
- $line .= ' NOT NULL';
- }
- $rows[] = $line;
- }
- $db->sql_freeresult($result);
-
- $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
- FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
- WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
- AND B.CONSTRAINT_TYPE = 'P'
- AND A.TABLE_NAME = '{$table_name}'";
- $result = $db->sql_query($sql);
-
- $primary_key = array();
- $contraint_name = '';
- while ($row = $db->sql_fetchrow($result))
- {
- $constraint_name = '"' . $row['constraint_name'] . '"';
- $primary_key[] = '"' . $row['column_name'] . '"';
- }
- $db->sql_freeresult($result);
-
- if (sizeof($primary_key))
- {
- $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')';
- }
-
- $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
- FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
- WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
- AND B.CONSTRAINT_TYPE = 'U'
- AND A.TABLE_NAME = '{$table_name}'";
- $result = $db->sql_query($sql);
-
- $unique = array();
- $contraint_name = '';
- while ($row = $db->sql_fetchrow($result))
- {
- $constraint_name = '"' . $row['constraint_name'] . '"';
- $unique[] = '"' . $row['column_name'] . '"';
- }
- $db->sql_freeresult($result);
-
- if (sizeof($unique))
- {
- $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')';
- }
-
- $sql_data .= implode(",\n", $rows);
- $sql_data .= "\n)\n/\n";
-
- $sql = "SELECT A.REFERENCED_NAME, C.*
- FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C
- WHERE A.REFERENCED_TYPE = 'SEQUENCE'
- AND A.NAME = B.TRIGGER_NAME
- AND B.TABLE_NAME = '{$table_name}'
- AND C.SEQUENCE_NAME = A.REFERENCED_NAME";
- $result = $db->sql_query($sql);
-
- $type = request_var('type', '');
-
- while ($row = $db->sql_fetchrow($result))
- {
- $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n";
- $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\"";
-
- if ($type == 'full')
- {
- $sql_data .= ' START WITH ' . $row['last_number'];
- }
-
- $sql_data .= "\n/\n";
- }
- $db->sql_freeresult($result);
-
- $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
- FROM USER_TRIGGERS
- WHERE TABLE_NAME = '{$table_name}'";
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
- }
- $db->sql_freeresult($result);
-
- $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME
- FROM USER_INDEXES A, USER_IND_COLUMNS B
- WHERE A.UNIQUENESS = 'NONUNIQUE'
- AND A.INDEX_NAME = B.INDEX_NAME
- AND B.TABLE_NAME = '{$table_name}'";
- $result = $db->sql_query($sql);
-
- $index = array();
-
- while ($row = $db->sql_fetchrow($result))
- {
- $index[$row['index_name']][] = $row['column_name'];
- }
-
- foreach ($index as $index_name => $column_names)
- {
- $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n";
- }
- $db->sql_freeresult($result);
- $this->flush($sql_data);
- }
-
- function write_data($table_name)
- {
- global $db;
- $ary_type = $ary_name = array();
-
- // Grab all of the data from current table.
- $sql = "SELECT *
- FROM $table_name";
- $result = $db->sql_query($sql);
-
- $i_num_fields = ocinumcols($result);
-
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- $ary_type[$i] = ocicolumntype($result, $i + 1);
- $ary_name[$i] = ocicolumnname($result, $i + 1);
- }
-
- $sql_data = '';
-
- while ($row = $db->sql_fetchrow($result))
- {
- $schema_vals = $schema_fields = array();
-
- // Build the SQL statement to recreate the data.
- for ($i = 0; $i < $i_num_fields; $i++)
- {
- // Oracle uses uppercase - we use lowercase
- $str_val = $row[strtolower($ary_name[$i])];
-
- if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i]))
- {
- $str_quote = '';
- $str_empty = "''";
- $str_val = sanitize_data_oracle($str_val);
- }
- else if (preg_match('#date|timestamp#i', $ary_type[$i]))
- {
- if (empty($str_val))
- {
- $str_quote = '';
- }
- else
- {
- $str_quote = "'";
- }
- }
- else
- {
- $str_quote = '';
- $str_empty = 'NULL';
- }
-
- if (empty($str_val) && $str_val !== '0')
- {
- $str_val = $str_empty;
- }
-
- $schema_vals[$i] = $str_quote . $str_val . $str_quote;
- $schema_fields[$i] = '"' . $ary_name[$i] . '"';
- }
-
- // Take the ordered fields and their associated data and build it
- // into a valid sql statement to recreate that field in the data.
- $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n";
-
- $this->flush($sql_data);
- }
- $db->sql_freeresult($result);
- }
-
- function write_start($prefix)
- {
- $sql_data = "--\n";
- $sql_data .= "-- phpBB Backup Script\n";
- $sql_data .= "-- Dump of tables for $prefix\n";
- $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
- $sql_data .= "--\n";
- $this->flush($sql_data);
- }
-}
-
// 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)
function get_usable_memory()
{
diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php
index 5b12013708..70eb398d07 100644
--- a/phpBB/includes/acp/acp_disallow.php
+++ b/phpBB/includes/acp/acp_disallow.php
@@ -25,8 +25,7 @@ class acp_disallow
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_admin_path;
+ global $db, $user, $template, $cache, $phpbb_log, $request;
$user->add_lang('acp/posting');
@@ -47,7 +46,7 @@ class acp_disallow
if ($disallow)
{
- $disallowed_user = str_replace('*', '%', utf8_normalize_nfc(request_var('disallowed_user', '', true)));
+ $disallowed_user = str_replace('*', '%', $request->variable('disallowed_user', '', true));
if (!$disallowed_user)
{
@@ -72,13 +71,13 @@ class acp_disallow
$cache->destroy('_disallowed_usernames');
$message = $user->lang['DISALLOW_SUCCESSFUL'];
- add_log('admin', 'LOG_DISALLOW_ADD', str_replace('%', '*', $disallowed_user));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_ADD', false, array(str_replace('%', '*', $disallowed_user)));
trigger_error($message . adm_back_link($this->u_action));
}
else if ($allow)
{
- $disallowed_id = request_var('disallowed_id', 0);
+ $disallowed_id = $request->variable('disallowed_id', 0);
if (!$disallowed_id)
{
@@ -91,7 +90,7 @@ class acp_disallow
$cache->destroy('_disallowed_usernames');
- add_log('admin', 'LOG_DISALLOW_DELETE');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_DELETE');
trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action));
}
diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php
index 917d02318e..57eefad02d 100644
--- a/phpBB/includes/acp/acp_email.php
+++ b/phpBB/includes/acp/acp_email.php
@@ -25,8 +25,8 @@ class acp_email
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $cache;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $phpbb_dispatcher;
+ global $config, $db, $user, $template, $phpbb_log, $request;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_dispatcher;
$user->add_lang('acp/email');
$this->tpl_name = 'acp_email';
@@ -39,11 +39,11 @@ class acp_email
$submit = (isset($_POST['submit'])) ? true : false;
$error = array();
- $usernames = request_var('usernames', '', true);
+ $usernames = $request->variable('usernames', '', true);
$usernames = (!empty($usernames)) ? explode("\n", $usernames) : array();
- $group_id = request_var('g', 0);
- $subject = utf8_normalize_nfc(request_var('subject', '', true));
- $message = utf8_normalize_nfc(request_var('message', '', true));
+ $group_id = $request->variable('g', 0);
+ $subject = $request->variable('subject', '', true);
+ $message = $request->variable('message', '', true);
// Do the job ...
if ($submit)
@@ -51,7 +51,7 @@ class acp_email
// Error checking needs to go here ... if no subject and/or no message then skip
// over the send and return to the form
$use_queue = (isset($_POST['send_immediately'])) ? false : true;
- $priority = request_var('mail_priority_flag', MAIL_NORMAL_PRIORITY);
+ $priority = $request->variable('mail_priority_flag', MAIL_NORMAL_PRIORITY);
if (!check_form_key($form_key))
{
@@ -270,7 +270,7 @@ class acp_email
{
if (!empty($usernames))
{
- add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames)));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array(implode(', ', utf8_normalize_nfc($usernames))));
}
else
{
@@ -284,7 +284,7 @@ class acp_email
$group_name = $user->lang['ALL_USERS'];
}
- add_log('admin', 'LOG_MASS_EMAIL', $group_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array($group_name));
}
}
diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php
index 5a2ded91e2..d2e01c80cc 100644
--- a/phpBB/includes/acp/acp_extensions.php
+++ b/phpBB/includes/acp/acp_extensions.php
@@ -34,7 +34,7 @@ class acp_extensions
function main()
{
// Start the page
- global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx, $phpbb_log, $cache, $phpbb_dispatcher;
+ global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpbb_log, $cache, $phpbb_dispatcher;
$this->db = $db;
$this->config = $config;
@@ -86,7 +86,7 @@ class acp_extensions
// If they've specified an extension, let's load the metadata manager and validate it.
if ($ext_name)
{
- $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $user, $phpbb_root_path);
+ $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $phpbb_root_path);
try
{
@@ -94,7 +94,8 @@ class acp_extensions
}
catch (\phpbb\extension\exception $e)
{
- trigger_error($e, E_USER_WARNING);
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ trigger_error($message, E_USER_WARNING);
}
}
@@ -368,8 +369,9 @@ class acp_extensions
}
catch (\phpbb\extension\exception $e)
{
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
$this->template->assign_block_vars('disabled', array(
- 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e),
+ 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
'S_VERSIONCHECK' => false,
));
}
@@ -425,8 +427,9 @@ class acp_extensions
}
catch (\phpbb\extension\exception $e)
{
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
$this->template->assign_block_vars('disabled', array(
- 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e),
+ 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
'S_VERSIONCHECK' => false,
));
}
@@ -485,8 +488,9 @@ class acp_extensions
}
catch (\phpbb\extension\exception $e)
{
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
$this->template->assign_block_vars('disabled', array(
- 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e),
+ 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
'S_VERSIONCHECK' => false,
));
}
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index 1e69a4ad20..66bb630241 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -27,7 +27,7 @@ class acp_forums
function main($id, $mode)
{
global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;
- global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
+ global $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log;
$user->add_lang('acp/forums');
$this->tpl_name = 'acp_forums';
@@ -36,11 +36,11 @@ class acp_forums
$form_key = 'acp_forums';
add_form_key($form_key);
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$update = (isset($_POST['update'])) ? true : false;
- $forum_id = request_var('f', 0);
+ $forum_id = $request->variable('f', 0);
- $this->parent_id = request_var('parent_id', 0);
+ $this->parent_id = $request->variable('parent_id', 0);
$forum_data = $errors = array();
if ($update && !check_form_key($form_key))
{
@@ -52,8 +52,8 @@ class acp_forums
switch ($action)
{
case 'progress_bar':
- $start = request_var('start', 0);
- $total = request_var('total', 0);
+ $start = $request->variable('start', 0);
+ $total = $request->variable('total', 0);
$this->display_progress_bar($start, $total);
break;
@@ -83,10 +83,10 @@ class acp_forums
switch ($action)
{
case 'delete':
- $action_subforums = request_var('action_subforums', '');
- $subforums_to_id = request_var('subforums_to_id', 0);
- $action_posts = request_var('action_posts', '');
- $posts_to_id = request_var('posts_to_id', 0);
+ $action_subforums = $request->variable('action_subforums', '');
+ $subforums_to_id = $request->variable('subforums_to_id', 0);
+ $action_posts = $request->variable('action_posts', '');
+ $posts_to_id = $request->variable('posts_to_id', 0);
$errors = $this->delete_forum($forum_id, $action_posts, $action_subforums, $posts_to_id, $subforums_to_id);
@@ -112,45 +112,45 @@ class acp_forums
case 'add':
$forum_data += array(
- 'parent_id' => request_var('forum_parent_id', $this->parent_id),
- 'forum_type' => request_var('forum_type', FORUM_POST),
- 'type_action' => request_var('type_action', ''),
- 'forum_status' => request_var('forum_status', ITEM_UNLOCKED),
+ 'parent_id' => $request->variable('forum_parent_id', $this->parent_id),
+ 'forum_type' => $request->variable('forum_type', FORUM_POST),
+ 'type_action' => $request->variable('type_action', ''),
+ 'forum_status' => $request->variable('forum_status', ITEM_UNLOCKED),
'forum_parents' => '',
- 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)),
- 'forum_link' => request_var('forum_link', ''),
- 'forum_link_track' => request_var('forum_link_track', false),
- 'forum_desc' => utf8_normalize_nfc(request_var('forum_desc', '', true)),
+ 'forum_name' => $request->variable('forum_name', '', true),
+ 'forum_link' => $request->variable('forum_link', ''),
+ 'forum_link_track' => $request->variable('forum_link_track', false),
+ 'forum_desc' => $request->variable('forum_desc', '', true),
'forum_desc_uid' => '',
'forum_desc_options' => 7,
'forum_desc_bitfield' => '',
- 'forum_rules' => utf8_normalize_nfc(request_var('forum_rules', '', true)),
+ 'forum_rules' => $request->variable('forum_rules', '', true),
'forum_rules_uid' => '',
'forum_rules_options' => 7,
'forum_rules_bitfield' => '',
- 'forum_rules_link' => request_var('forum_rules_link', ''),
- 'forum_image' => request_var('forum_image', ''),
- 'forum_style' => request_var('forum_style', 0),
- 'display_subforum_list' => request_var('display_subforum_list', false),
- 'display_on_index' => request_var('display_on_index', false),
- 'forum_topics_per_page' => request_var('topics_per_page', 0),
- 'enable_indexing' => request_var('enable_indexing', true),
- 'enable_icons' => request_var('enable_icons', false),
- 'enable_prune' => request_var('enable_prune', false),
- 'enable_post_review' => request_var('enable_post_review', true),
- 'enable_quick_reply' => request_var('enable_quick_reply', false),
- 'enable_shadow_prune' => request_var('enable_shadow_prune', false),
- 'prune_days' => request_var('prune_days', 7),
- 'prune_viewed' => request_var('prune_viewed', 7),
- 'prune_freq' => request_var('prune_freq', 1),
- 'prune_old_polls' => request_var('prune_old_polls', false),
- 'prune_announce' => request_var('prune_announce', false),
- 'prune_sticky' => request_var('prune_sticky', false),
- 'prune_shadow_days' => request_var('prune_shadow_days', 7),
- 'prune_shadow_freq' => request_var('prune_shadow_freq', 1),
- 'forum_password' => request_var('forum_password', '', true),
- 'forum_password_confirm'=> request_var('forum_password_confirm', '', true),
- 'forum_password_unset' => request_var('forum_password_unset', false),
+ 'forum_rules_link' => $request->variable('forum_rules_link', ''),
+ 'forum_image' => $request->variable('forum_image', ''),
+ 'forum_style' => $request->variable('forum_style', 0),
+ 'display_subforum_list' => $request->variable('display_subforum_list', false),
+ 'display_on_index' => $request->variable('display_on_index', false),
+ 'forum_topics_per_page' => $request->variable('topics_per_page', 0),
+ 'enable_indexing' => $request->variable('enable_indexing', true),
+ 'enable_icons' => $request->variable('enable_icons', false),
+ 'enable_prune' => $request->variable('enable_prune', false),
+ 'enable_post_review' => $request->variable('enable_post_review', true),
+ 'enable_quick_reply' => $request->variable('enable_quick_reply', false),
+ 'enable_shadow_prune' => $request->variable('enable_shadow_prune', false),
+ 'prune_days' => $request->variable('prune_days', 7),
+ 'prune_viewed' => $request->variable('prune_viewed', 7),
+ 'prune_freq' => $request->variable('prune_freq', 1),
+ 'prune_old_polls' => $request->variable('prune_old_polls', false),
+ 'prune_announce' => $request->variable('prune_announce', false),
+ 'prune_sticky' => $request->variable('prune_sticky', false),
+ 'prune_shadow_days' => $request->variable('prune_shadow_days', 7),
+ 'prune_shadow_freq' => $request->variable('prune_shadow_freq', 1),
+ 'forum_password' => $request->variable('forum_password', '', true),
+ 'forum_password_confirm'=> $request->variable('forum_password_confirm', '', true),
+ 'forum_password_unset' => $request->variable('forum_password_unset', false),
);
/**
@@ -173,7 +173,7 @@ class acp_forums
// Use link_display_on_index setting if forum type is link
if ($forum_data['forum_type'] == FORUM_LINK)
{
- $forum_data['display_on_index'] = request_var('link_display_on_index', false);
+ $forum_data['display_on_index'] = $request->variable('link_display_on_index', false);
}
// Linked forums and categories are not able to be locked...
@@ -182,25 +182,25 @@ class acp_forums
$forum_data['forum_status'] = ITEM_UNLOCKED;
}
- $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? request_var('display_recent', true) : request_var('display_active', false);
+ $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? $request->variable('display_recent', true) : $request->variable('display_active', false);
// Get data for forum rules if specified...
if ($forum_data['forum_rules'])
{
- generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_parse_bbcode', false), request_var('rules_parse_urls', false), request_var('rules_parse_smilies', false));
+ generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], $request->variable('rules_parse_bbcode', false), $request->variable('rules_parse_urls', false), $request->variable('rules_parse_smilies', false));
}
// Get data for forum description if specified
if ($forum_data['forum_desc'])
{
- generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_parse_bbcode', false), request_var('desc_parse_urls', false), request_var('desc_parse_smilies', false));
+ generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], $request->variable('desc_parse_bbcode', false), $request->variable('desc_parse_urls', false), $request->variable('desc_parse_smilies', false));
}
$errors = $this->update_forum_data($forum_data);
if (!sizeof($errors))
{
- $forum_perm_from = request_var('forum_perm_from', 0);
+ $forum_perm_from = $request->variable('forum_perm_from', 0);
$cache->destroy('sql', FORUMS_TABLE);
$copied_permissions = false;
@@ -266,7 +266,7 @@ class acp_forums
if ($move_forum_name !== false)
{
- add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_' . strtoupper($action), false, array($row['forum_name'], $move_forum_name));
$cache->destroy('sql', FORUMS_TABLE);
}
@@ -311,7 +311,7 @@ class acp_forums
$row2['min_topic_id'] = (int) $row2['min_topic_id'];
$row2['max_topic_id'] = (int) $row2['max_topic_id'];
- $start = request_var('start', $row2['min_topic_id']);
+ $start = $request->variable('start', $row2['min_topic_id']);
$batch_size = 2000;
$end = $start + $batch_size;
@@ -327,7 +327,7 @@ class acp_forums
WHERE forum_id = ' . $forum_id . '
AND topic_id BETWEEN ' . $start . ' AND ' . $end;
$result = $db->sql_query($sql);
- $topics_done = request_var('topics_done', 0) + (int) $db->sql_fetchfield('num_topics');
+ $topics_done = $request->variable('topics_done', 0) + (int) $db->sql_fetchfield('num_topics');
$db->sql_freeresult($result);
$start += $batch_size;
@@ -377,7 +377,8 @@ class acp_forums
sync('forum', 'forum_id', $forum_id, false, true);
- add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_SYNC', false, array($row['forum_name']));
+
$cache->destroy('sql', FORUMS_TABLE);
$template->assign_var('L_FORUM_RESYNCED', sprintf($user->lang['FORUM_RESYNCED'], $row['forum_name']));
@@ -390,13 +391,13 @@ class acp_forums
if ($update)
{
$forum_data['forum_flags'] = 0;
- $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0;
- $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0;
- $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
- $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0;
+ $forum_data['forum_flags'] += ($request->variable('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0;
+ $forum_data['forum_flags'] += ($request->variable('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0;
+ $forum_data['forum_flags'] += ($request->variable('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
+ $forum_data['forum_flags'] += ($request->variable('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0;
$forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
- $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0;
- $forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0;
+ $forum_data['forum_flags'] += ($request->variable('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0;
+ $forum_data['forum_flags'] += ($request->variable('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0;
}
// Initialise $row, so we always have it in the event
@@ -444,7 +445,7 @@ class acp_forums
'parent_id' => $this->parent_id,
'forum_type' => FORUM_POST,
'forum_status' => ITEM_UNLOCKED,
- 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)),
+ 'forum_name' => $request->variable('forum_name', '', true),
'forum_link' => '',
'forum_link_track' => false,
'forum_desc' => '',
@@ -511,12 +512,12 @@ class acp_forums
{
if (!isset($forum_data['forum_rules_uid']))
{
- // Before we are able to display the preview and plane text, we need to parse our request_var()'d value...
+ // Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value...
$forum_data['forum_rules_uid'] = '';
$forum_data['forum_rules_bitfield'] = '';
$forum_data['forum_rules_options'] = 0;
- generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_allow_bbcode', false), request_var('rules_allow_urls', false), request_var('rules_allow_smilies', false));
+ generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], $request->variable('rules_allow_bbcode', false), $request->variable('rules_allow_urls', false), $request->variable('rules_allow_smilies', false));
}
// Generate preview content
@@ -531,12 +532,12 @@ class acp_forums
{
if (!isset($forum_data['forum_desc_uid']))
{
- // Before we are able to display the preview and plane text, we need to parse our request_var()'d value...
+ // Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value...
$forum_data['forum_desc_uid'] = '';
$forum_data['forum_desc_bitfield'] = '';
$forum_data['forum_desc_options'] = 0;
- generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_allow_bbcode', false), request_var('desc_allow_urls', false), request_var('desc_allow_smilies', false));
+ generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], $request->variable('desc_allow_bbcode', false), $request->variable('desc_allow_urls', false), $request->variable('desc_allow_smilies', false));
}
// decode...
@@ -779,7 +780,7 @@ class acp_forums
break;
case 'copy_perm':
- $forum_perm_from = request_var('forum_perm_from', 0);
+ $forum_perm_from = $request->variable('forum_perm_from', 0);
// Copy permissions?
if (!empty($forum_perm_from) && $forum_perm_from != $forum_id)
@@ -959,12 +960,13 @@ class acp_forums
/**
* Update forum data
*/
- function update_forum_data(&$forum_data)
+ function update_forum_data(&$forum_data_ary)
{
- global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;
+ global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request;
$errors = array();
+ $forum_data = $forum_data_ary;
/**
* Validate the forum data before we create/update the forum
*
@@ -976,42 +978,44 @@ class acp_forums
*/
$vars = array('forum_data', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_validate_data', compact($vars)));
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
- if ($forum_data['forum_name'] == '')
+ if ($forum_data_ary['forum_name'] == '')
{
$errors[] = $user->lang['FORUM_NAME_EMPTY'];
}
- if (utf8_strlen($forum_data['forum_desc']) > 4000)
+ if (utf8_strlen($forum_data_ary['forum_desc']) > 4000)
{
$errors[] = $user->lang['FORUM_DESC_TOO_LONG'];
}
- if (utf8_strlen($forum_data['forum_rules']) > 4000)
+ if (utf8_strlen($forum_data_ary['forum_rules']) > 4000)
{
$errors[] = $user->lang['FORUM_RULES_TOO_LONG'];
}
- if ($forum_data['forum_password'] || $forum_data['forum_password_confirm'])
+ if ($forum_data_ary['forum_password'] || $forum_data_ary['forum_password_confirm'])
{
- if ($forum_data['forum_password'] != $forum_data['forum_password_confirm'])
+ if ($forum_data_ary['forum_password'] != $forum_data_ary['forum_password_confirm'])
{
- $forum_data['forum_password'] = $forum_data['forum_password_confirm'] = '';
+ $forum_data_ary['forum_password'] = $forum_data_ary['forum_password_confirm'] = '';
$errors[] = $user->lang['FORUM_PASSWORD_MISMATCH'];
}
}
- if ($forum_data['prune_days'] < 0 || $forum_data['prune_viewed'] < 0 || $forum_data['prune_freq'] < 0)
+ if ($forum_data_ary['prune_days'] < 0 || $forum_data_ary['prune_viewed'] < 0 || $forum_data_ary['prune_freq'] < 0)
{
- $forum_data['prune_days'] = $forum_data['prune_viewed'] = $forum_data['prune_freq'] = 0;
+ $forum_data_ary['prune_days'] = $forum_data_ary['prune_viewed'] = $forum_data_ary['prune_freq'] = 0;
$errors[] = $user->lang['FORUM_DATA_NEGATIVE'];
}
$range_test_ary = array(
- array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'),
+ array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data_ary['forum_topics_per_page'], 'column_type' => 'TINT:0'),
);
- if (!empty($forum_data['forum_image']) && !file_exists($phpbb_root_path . $forum_data['forum_image']))
+ if (!empty($forum_data_ary['forum_image']) && !file_exists($phpbb_root_path . $forum_data_ary['forum_image']))
{
$errors[] = $user->lang['FORUM_IMAGE_NO_EXIST'];
}
@@ -1025,17 +1029,17 @@ class acp_forums
// 8 = prune stickies
// 16 = show active topics
// 32 = enable post review
- $forum_data['forum_flags'] = 0;
- $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
- $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
- $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
- $forum_data['forum_flags'] += ($forum_data['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0;
+ $forum_data_ary['forum_flags'] = 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0;
// Unset data that are not database fields
- $forum_data_sql = $forum_data;
+ $forum_data_sql = $forum_data_ary;
unset($forum_data_sql['forum_link_track']);
unset($forum_data_sql['prune_old_polls']);
@@ -1066,12 +1070,14 @@ class acp_forums
else
{
// Instantiate passwords manager
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
$forum_data_sql['forum_password'] = $passwords_manager->hash($forum_data_sql['forum_password']);
}
unset($forum_data_sql['forum_password_unset']);
+ $forum_data = $forum_data_ary;
/**
* Remove invalid values from forum_data_sql that should not be updated
*
@@ -1084,6 +1090,8 @@ class acp_forums
*/
$vars = array('forum_data', 'forum_data_sql');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_before', compact($vars)));
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
$is_new_forum = !isset($forum_data_sql['forum_id']);
@@ -1140,9 +1148,9 @@ class acp_forums
$sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql);
$db->sql_query($sql);
- $forum_data['forum_id'] = $db->sql_nextid();
+ $forum_data_ary['forum_id'] = $db->sql_nextid();
- add_log('admin', 'LOG_FORUM_ADD', $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_ADD', false, array($forum_data_ary['forum_name']));
}
else
{
@@ -1160,7 +1168,7 @@ class acp_forums
// we're turning a postable forum into a non-postable forum
if ($forum_data_sql['type_action'] == 'move')
{
- $to_forum_id = request_var('to_forum_id', 0);
+ $to_forum_id = $request->variable('to_forum_id', 0);
if ($to_forum_id)
{
@@ -1190,8 +1198,8 @@ class acp_forums
if ($row['right_id'] - $row['left_id'] > 1)
{
// We are turning a category into a link - but need to decide what to do with the subforums.
- $action_subforums = request_var('action_subforums', '');
- $subforums_to_id = request_var('subforums_to_id', 0);
+ $action_subforums = $request->variable('action_subforums', '');
+ $subforums_to_id = $request->variable('subforums_to_id', 0);
if ($action_subforums == 'delete')
{
@@ -1272,8 +1280,6 @@ class acp_forums
return array($user->lang['NO_FORUM']);
}
- $subforums_to_name = $_row['forum_name'];
-
$sql = 'SELECT forum_id
FROM ' . FORUMS_TABLE . "
WHERE parent_id = {$row['forum_id']}";
@@ -1357,11 +1363,12 @@ class acp_forums
$db->sql_query($sql);
// Add it back
- $forum_data['forum_id'] = $forum_id;
+ $forum_data_ary['forum_id'] = $forum_id;
- add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_EDIT', false, array($forum_data_ary['forum_name']));
}
+ $forum_data = $forum_data_ary;
/**
* Event after a forum was updated or created
*
@@ -1377,6 +1384,8 @@ class acp_forums
*/
$vars = array('forum_data', 'forum_data_sql', 'is_new_forum', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_after', compact($vars)));
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
return $errors;
}
@@ -1388,7 +1397,7 @@ class acp_forums
{
global $db, $user, $phpbb_dispatcher;
- $to_data = $moved_ids = $errors = array();
+ $errors = array();
// Check if we want to move to a parent with link type
if ($to_id > 0)
@@ -1561,7 +1570,7 @@ class acp_forums
*/
function delete_forum($forum_id, $action_posts = 'delete', $action_subforums = 'delete', $posts_to_id = 0, $subforums_to_id = 0)
{
- global $db, $user, $cache;
+ global $db, $user, $cache, $phpbb_log;
$forum_data = $this->get_forum_info($forum_id);
@@ -1758,39 +1767,39 @@ class acp_forums
switch ($log_action)
{
case 'MOVE_POSTS_MOVE_FORUMS':
- add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', $posts_to_name, $subforums_to_name, $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', false, array($posts_to_name, $subforums_to_name, $forum_data['forum_name']));
break;
case 'MOVE_POSTS_FORUMS':
- add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', $posts_to_name, $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', false, array($posts_to_name, $forum_data['forum_name']));
break;
case 'POSTS_MOVE_FORUMS':
- add_log('admin', 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name']));
break;
case '_MOVE_FORUMS':
- add_log('admin', 'LOG_FORUM_DEL_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name']));
break;
case 'MOVE_POSTS_':
- add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS', $posts_to_name, $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS', false, array($posts_to_name, $forum_data['forum_name']));
break;
case 'POSTS_FORUMS':
- add_log('admin', 'LOG_FORUM_DEL_POSTS_FORUMS', $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_FORUMS', false, array($forum_data['forum_name']));
break;
case '_FORUMS':
- add_log('admin', 'LOG_FORUM_DEL_FORUMS', $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUMS', false, array($forum_data['forum_name']));
break;
case 'POSTS_':
- add_log('admin', 'LOG_FORUM_DEL_POSTS', $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS', false, array($forum_data['forum_name']));
break;
default:
- add_log('admin', 'LOG_FORUM_DEL_FORUM', $forum_data['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUM', false, array($forum_data['forum_name']));
break;
}
@@ -1802,7 +1811,7 @@ class acp_forums
*/
function delete_forum_content($forum_id)
{
- global $db, $config, $phpbb_root_path, $phpEx, $phpbb_dispatcher;
+ global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
@@ -1823,7 +1832,10 @@ class acp_forums
}
$db->sql_freeresult($result);
- delete_attachments('topic', $topic_ids, false);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('topic', $topic_ids, false);
+ unset($attachment_manager);
// Delete shadow topics pointing to topics in this forum
delete_topic_shadows($forum_id);
@@ -1994,7 +2006,7 @@ class acp_forums
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('num_posts', (int) $row['stat'], true);
+ $config->set('num_posts', (int) $row['stat'], false);
$sql = 'SELECT COUNT(topic_id) AS stat
FROM ' . TOPICS_TABLE . '
@@ -2003,7 +2015,7 @@ class acp_forums
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('num_topics', (int) $row['stat'], true);
+ $config->set('num_topics', (int) $row['stat'], false);
$sql = 'SELECT COUNT(attach_id) as stat
FROM ' . ATTACHMENTS_TABLE;
@@ -2011,7 +2023,7 @@ class acp_forums
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('num_files', (int) $row['stat'], true);
+ $config->set('num_files', (int) $row['stat'], false);
$sql = 'SELECT SUM(filesize) as stat
FROM ' . ATTACHMENTS_TABLE;
@@ -2019,7 +2031,7 @@ class acp_forums
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('upload_dir_size', (float) $row['stat'], true);
+ $config->set('upload_dir_size', (float) $row['stat'], false);
return array();
}
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 0352f6a242..305296d013 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -26,7 +26,7 @@ class acp_groups
function main($id, $mode)
{
global $config, $db, $user, $auth, $template, $cache;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx;
global $request, $phpbb_container, $phpbb_dispatcher;
$user->add_lang('acp/groups');
@@ -48,15 +48,18 @@ class acp_groups
}
// Check and set some common vars
- $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : request_var('action', ''));
- $group_id = request_var('g', 0);
- $mark_ary = request_var('mark', array(0));
- $name_ary = request_var('usernames', '', true);
- $leader = request_var('leader', 0);
- $default = request_var('default', 0);
- $start = request_var('start', 0);
+ $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : $request->variable('action', ''));
+ $group_id = $request->variable('g', 0);
+ $mark_ary = $request->variable('mark', array(0));
+ $name_ary = $request->variable('usernames', '', true);
+ $leader = $request->variable('leader', 0);
+ $default = $request->variable('default', 0);
+ $start = $request->variable('start', 0);
$update = (isset($_POST['update'])) ? true : false;
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
// Clear some vars
$group_row = array();
@@ -101,7 +104,7 @@ class acp_groups
}
// Approve, demote or promote
- $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_name = $group_helper->get_name($group_row['group_name']);
$error = group_user_attributes($action, $group_id, $mark_ary, false, $group_name);
if (!$error)
@@ -142,7 +145,7 @@ class acp_groups
if (confirm_box(true))
{
- $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_name = $group_helper->get_name($group_row['group_name']);
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
@@ -161,7 +164,7 @@ class acp_groups
case 'set_default_on_all':
if (confirm_box(true))
{
- $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_name = $group_helper->get_name($group_row['group_name']);
$start = 0;
@@ -220,6 +223,7 @@ class acp_groups
}
else if ($action === 'delete' && $group_row['group_type'] == GROUP_SPECIAL)
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -232,6 +236,7 @@ class acp_groups
case 'delete':
if (!$auth->acl_get('a_groupdel'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -239,7 +244,7 @@ class acp_groups
break;
case 'deleteusers':
- $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_name = $group_helper->get_name($group_row['group_name']);
$error = group_user_del($group_id, $mark_ary, false, $group_name);
break;
}
@@ -283,7 +288,7 @@ class acp_groups
}
$name_ary = array_unique(explode("\n", $name_ary));
- $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_name = $group_helper->get_name($group_row['group_name']);
// Add user/s to group
if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, 0, $group_row))
@@ -303,8 +308,6 @@ class acp_groups
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
}
- $data = $submit_ary = array();
-
if ($action == 'edit' && !$group_id)
{
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
@@ -312,6 +315,7 @@ class acp_groups
if ($action == 'add' && !$auth->acl_get('a_groupadd'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -369,24 +373,24 @@ class acp_groups
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
- $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true));
- $group_type = request_var('group_type', GROUP_FREE);
+ $group_name = $request->variable('group_name', '', true);
+ $group_desc = $request->variable('group_desc', '', true);
+ $group_type = $request->variable('group_type', GROUP_FREE);
- $allow_desc_bbcode = request_var('desc_parse_bbcode', false);
- $allow_desc_urls = request_var('desc_parse_urls', false);
- $allow_desc_smilies = request_var('desc_parse_smilies', false);
+ $allow_desc_bbcode = $request->variable('desc_parse_bbcode', false);
+ $allow_desc_urls = $request->variable('desc_parse_urls', false);
+ $allow_desc_smilies = $request->variable('desc_parse_smilies', false);
$submit_ary = array(
- 'colour' => request_var('group_colour', ''),
- 'rank' => request_var('group_rank', 0),
+ 'colour' => $request->variable('group_colour', ''),
+ 'rank' => $request->variable('group_rank', 0),
'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0,
'legend' => isset($_REQUEST['group_legend']) ? 1 : 0,
'teampage' => isset($_REQUEST['group_teampage']) ? 1 : 0,
- 'message_limit' => request_var('group_message_limit', 0),
- 'max_recipients' => request_var('group_max_recipients', 0),
+ 'message_limit' => $request->variable('group_message_limit', 0),
+ 'max_recipients' => $request->variable('group_max_recipients', 0),
'founder_manage' => 0,
- 'skip_auth' => request_var('group_skip_auth', 0),
+ 'skip_auth' => $request->variable('group_skip_auth', 0),
);
if ($user->data['user_type'] == USER_FOUNDER)
@@ -555,7 +559,7 @@ class acp_groups
if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies)))
{
- $group_perm_from = request_var('group_perm_from', 0);
+ $group_perm_from = $request->variable('group_perm_from', 0);
// Copy permissions?
// If the user has the a_authgroups permission and at least one additional permission ability set the permissions are fully transferred.
@@ -625,7 +629,7 @@ class acp_groups
}
else if (!$group_id)
{
- $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
+ $group_name = $request->variable('group_name', '', true);
$group_desc_data = array(
'text' => '',
'allow_bbcode' => true,
@@ -710,12 +714,12 @@ class acp_groups
$error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
}
- $back_link = request_var('back_link', '');
+ $back_link = $request->variable('back_link', '');
switch ($back_link)
{
case 'acp_users_groups':
- $u_back = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=groups&amp;u=' . request_var('u', 0));
+ $u_back = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=groups&amp;u=' . $request->variable('u', 0));
break;
default:
@@ -734,7 +738,7 @@ class acp_groups
'S_AVATARS_ENABLED' => ($config['allow_avatar'] && $avatars_enabled),
'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name,
+ 'GROUP_NAME' => $group_helper->get_name($group_name),
'GROUP_INTERNAL_NAME' => $group_name,
'GROUP_DESC' => $group_desc_data['text'],
'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '',
@@ -816,8 +820,9 @@ class acp_groups
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $this->page_title = 'GROUP_MEMBERS';
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
+ $this->page_title = 'GROUP_MEMBERS';
// Grab the leaders - always, on every page...
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
@@ -868,7 +873,7 @@ class acp_groups
'S_GROUP_SPECIAL' => ($group_row['group_type'] == GROUP_SPECIAL) ? true : false,
'S_ACTION_OPTIONS' => $s_action_options,
- 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'],
+ 'GROUP_NAME' => $group_helper->get_name($group_row['group_name']),
'U_ACTION' => $this->u_action . "&amp;g=$group_id",
'U_BACK' => $this->u_action,
@@ -937,11 +942,12 @@ class acp_groups
// used for easy access to the data within a group
$cached_group_data[$type][$row['group_id']] = $row;
$cached_group_data[$type][$row['group_id']]['total_members'] = 0;
+ $cached_group_data[$type][$row['group_id']]['pending_members'] = 0;
}
$db->sql_freeresult($result);
// How many people are in which group?
- $sql = 'SELECT COUNT(ug.user_id) AS total_members, ug.group_id
+ $sql = 'SELECT COUNT(ug.user_id) AS total_members, SUM(ug.user_pending) AS pending_members, ug.group_id
FROM ' . USER_GROUP_TABLE . ' ug
WHERE ' . $db->sql_in_set('ug.group_id', array_keys($lookup)) . '
GROUP BY ug.group_id';
@@ -951,6 +957,7 @@ class acp_groups
{
$type = $lookup[$row['group_id']];
$cached_group_data[$type][$row['group_id']]['total_members'] = $row['total_members'];
+ $cached_group_data[$type][$row['group_id']]['pending_members'] = $row['pending_members'];
}
$db->sql_freeresult($result);
@@ -979,6 +986,7 @@ class acp_groups
'GROUP_NAME' => $group_name,
'TOTAL_MEMBERS' => $row['total_members'],
+ 'PENDING_MEMBERS' => $row['pending_members']
));
}
}
@@ -997,6 +1005,9 @@ class acp_groups
$teampage_id = $request->variable('t', 0);
$category_id = $request->variable('c', 0);
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
if ($field && !in_array($field, array('legend', 'teampage')))
{
// Invalid mode
@@ -1004,7 +1015,7 @@ class acp_groups
}
else if ($field && in_array($field, array('legend', 'teampage')))
{
-
+ /* @var $group_position \phpbb\groupposition\groupposition_interface */
$group_position = $phpbb_container->get('groupposition.' . $field);
}
@@ -1096,10 +1107,9 @@ class acp_groups
ORDER BY group_legend ASC, group_type DESC, group_name ASC';
$result = $db->sql_query($sql);
- $s_group_select_legend = '';
while ($row = $db->sql_fetchrow($result))
{
- $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $group_name = $group_helper->get_name($row['group_name']);
if ($row['group_legend'])
{
$template->assign_block_vars('legend', array(
@@ -1134,7 +1144,6 @@ class acp_groups
ORDER BY t.teampage_position ASC';
$result = $db->sql_query($sql);
- $category_data = array();
while ($row = $db->sql_fetchrow($result))
{
if ($row['teampage_id'] == $category_id)
@@ -1147,7 +1156,7 @@ class acp_groups
if ($row['group_id'])
{
- $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $group_name = $group_helper->get_name($row['group_name']);
$group_type = $user->lang[\phpbb\groupposition\teampage::group_type_language($row['group_type'])];
}
else
@@ -1177,10 +1186,9 @@ class acp_groups
ORDER BY g.group_type DESC, g.group_name ASC';
$result = $db->sql_query($sql);
- $s_group_select_teampage = '';
while ($row = $db->sql_fetchrow($result))
{
- $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $group_name = $group_helper->get_name($row['group_name']);
$template->assign_block_vars('add_teampage', array(
'GROUP_ID' => (int) $row['group_id'],
'GROUP_NAME' => $group_name,
diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php
index a0ea7dc9b1..6cd5386857 100644
--- a/phpBB/includes/acp/acp_icons.php
+++ b/phpBB/includes/acp/acp_icons.php
@@ -28,18 +28,18 @@ class acp_icons
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $template, $cache;
+ global $config, $phpbb_root_path;
global $request, $phpbb_container;
$user->add_lang('acp/posting');
// Set up general vars
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$action = (isset($_POST['add'])) ? 'add' : $action;
$action = (isset($_POST['edit'])) ? 'edit' : $action;
$action = (isset($_POST['import'])) ? 'import' : $action;
- $icon_id = request_var('id', 0);
+ $icon_id = $request->variable('id', 0);
$submit = $request->is_set_post('submit', false);
$form_key = 'acp_icons';
@@ -198,7 +198,6 @@ class acp_icons
$data = array();
$after = false;
- $display = 0;
$order_lists = array('', '');
$add_order_lists = array('', '');
$display_count = 0;
@@ -213,7 +212,6 @@ class acp_icons
if ($row[$fields . '_id'] == $icon_id)
{
$after = true;
- $display = $row['display_on_posting'];
$data[$row[$fields . '_url']] = $row;
}
else
@@ -252,7 +250,7 @@ class acp_icons
$data = $_images;
}
- $colspan = (($mode == 'smilies') ? 7 : 5);
+ $colspan = (($mode == 'smilies') ? 7 : 6);
$colspan += ($icon_id) ? 1 : 0;
$colspan += ($action == 'add') ? 2 : 0;
@@ -296,6 +294,8 @@ class acp_icons
'ID' => (isset($img_row[$fields . '_id'])) ? $img_row[$fields . '_id'] : 0,
'WIDTH' => (!empty($img_row[$fields .'_width'])) ? $img_row[$fields .'_width'] : $img_row['width'],
'HEIGHT' => (!empty($img_row[$fields .'_height'])) ? $img_row[$fields .'_height'] : $img_row['height'],
+ 'TEXT_ALT' => ($mode == 'icons' && !empty($img_row['icons_alt'])) ? $img_row['icons_alt'] : $img,
+ 'ALT' => ($mode == 'icons' && !empty($img_row['icons_alt'])) ? $img_row['icons_alt'] : '',
'POSTING_CHECKED' => (!empty($img_row['display_on_posting']) || $action == 'add') ? ' checked="checked"' : '',
));
}
@@ -335,24 +335,25 @@ class acp_icons
}
// Get items to create/modify
- $images = (isset($_POST['image'])) ? array_keys(request_var('image', array('' => 0))) : array();
+ $images = (isset($_POST['image'])) ? array_keys($request->variable('image', array('' => 0))) : array();
// Now really get the items
- $image_id = (isset($_POST['id'])) ? request_var('id', array('' => 0)) : array();
- $image_order = (isset($_POST['order'])) ? request_var('order', array('' => 0)) : array();
- $image_width = (isset($_POST['width'])) ? request_var('width', array('' => 0)) : array();
- $image_height = (isset($_POST['height'])) ? request_var('height', array('' => 0)) : array();
- $image_add = (isset($_POST['add_img'])) ? request_var('add_img', array('' => 0)) : array();
- $image_emotion = utf8_normalize_nfc(request_var('emotion', array('' => ''), true));
- $image_code = utf8_normalize_nfc(request_var('code', array('' => ''), true));
- $image_display_on_posting = (isset($_POST['display_on_posting'])) ? request_var('display_on_posting', array('' => 0)) : array();
+ $image_id = (isset($_POST['id'])) ? $request->variable('id', array('' => 0)) : array();
+ $image_order = (isset($_POST['order'])) ? $request->variable('order', array('' => 0)) : array();
+ $image_width = (isset($_POST['width'])) ? $request->variable('width', array('' => 0)) : array();
+ $image_height = (isset($_POST['height'])) ? $request->variable('height', array('' => 0)) : array();
+ $image_add = (isset($_POST['add_img'])) ? $request->variable('add_img', array('' => 0)) : array();
+ $image_emotion = $request->variable('emotion', array('' => ''), true);
+ $image_code = $request->variable('code', array('' => ''), true);
+ $image_alt = ($request->is_set_post('alt')) ? $request->variable('alt', array('' => ''), true) : array();
+ $image_display_on_posting = (isset($_POST['display_on_posting'])) ? $request->variable('display_on_posting', array('' => 0)) : array();
// Ok, add the relevant bits if we are adding new codes to existing emoticons...
if ($request->variable('add_additional_code', false, false, \phpbb\request\request_interface::POST))
{
- $add_image = request_var('add_image', '');
- $add_code = utf8_normalize_nfc(request_var('add_code', '', true));
- $add_emotion = utf8_normalize_nfc(request_var('add_emotion', '', true));
+ $add_image = $request->variable('add_image', '');
+ $add_code = $request->variable('add_code', '', true);
+ $add_emotion = $request->variable('add_emotion', '', true);
if ($add_image && $add_emotion && $add_code)
{
@@ -361,15 +362,15 @@ class acp_icons
$image_code[$add_image] = $add_code;
$image_emotion[$add_image] = $add_emotion;
- $image_width[$add_image] = request_var('add_width', 0);
- $image_height[$add_image] = request_var('add_height', 0);
+ $image_width[$add_image] = $request->variable('add_width', 0);
+ $image_height[$add_image] = $request->variable('add_height', 0);
if ($request->variable('add_display_on_posting', false, false, \phpbb\request\request_interface::POST))
{
$image_display_on_posting[$add_image] = 1;
}
- $image_order[$add_image] = request_var('add_order', 0);
+ $image_order[$add_image] = $request->variable('add_order', 0);
}
}
@@ -447,6 +448,13 @@ class acp_icons
);
}
+ if ($mode == 'icons')
+ {
+ $img_sql = array_merge($img_sql, array(
+ 'icons_alt' => $image_alt[$image])
+ );
+ }
+
// Image_order holds the 'new' order value
if (!empty($image_order[$image]))
{
@@ -495,6 +503,7 @@ class acp_icons
$cache->destroy('_icons');
$cache->destroy('sql', $table);
+ $phpbb_container->get('text_formatter.cache')->invalidate();
$level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING;
$errormsgs = '';
@@ -515,8 +524,8 @@ class acp_icons
case 'import':
- $pak = request_var('pak', '');
- $current = request_var('current', '');
+ $pak = $request->variable('pak', '');
+ $current = $request->variable('current', '');
if ($pak != '')
{
@@ -554,7 +563,6 @@ class acp_icons
{
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$db->sql_query('DELETE FROM ' . $table);
break;
@@ -675,6 +683,7 @@ class acp_icons
$cache->destroy('_icons');
$cache->destroy('sql', $table);
+ $phpbb_container->get('text_formatter.cache')->invalidate();
trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action));
}
@@ -802,6 +811,7 @@ class acp_icons
$cache->destroy('_icons');
$cache->destroy('sql', $table);
+ $phpbb_container->get('text_formatter.cache')->invalidate();
if ($request->is_ajax())
{
@@ -872,6 +882,7 @@ class acp_icons
$cache->destroy('_icons');
$cache->destroy('sql', $table);
+ $phpbb_container->get('text_formatter.cache')->invalidate();
if ($request->is_ajax())
{
@@ -927,9 +938,10 @@ class acp_icons
)
);
- $spacer = false;
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
- $pagination_start = request_var('start', 0);
+ $pagination_start = $request->variable('start', 0);
+ $spacer = false;
$item_count = $this->item_count($table);
@@ -940,7 +952,7 @@ class acp_icons
while ($row = $db->sql_fetchrow($result))
{
- $alt_text = ($mode == 'smilies') ? $row['code'] : '';
+ $alt_text = ($mode == 'smilies') ? $row['code'] : (($mode == 'icons' && !empty($row['icons_alt'])) ? $row['icons_alt'] : $row['icons_url']);
$template->assign_block_vars('items', array(
'S_SPACER' => (!$spacer && !$row['display_on_posting']) ? true : false,
diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php
index 76c7a1b277..ec256e93ef 100644
--- a/phpBB/includes/acp/acp_inactive.php
+++ b/phpBB/includes/acp/acp_inactive.php
@@ -31,8 +31,8 @@ class acp_inactive
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $phpbb_container;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
+ global $config, $db, $user, $auth, $template, $phpbb_container, $phpbb_log, $request;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx;
if (!function_exists('user_active_flip'))
{
@@ -41,24 +41,26 @@ class acp_inactive
$user->add_lang('memberlist');
- $action = request_var('action', '');
- $mark = (isset($_REQUEST['mark'])) ? request_var('mark', array(0)) : array();
- $start = request_var('start', 0);
+ $action = $request->variable('action', '');
+ $mark = (isset($_REQUEST['mark'])) ? $request->variable('mark', array(0)) : array();
+ $start = $request->variable('start', 0);
$submit = isset($_POST['submit']);
// Sort keys
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 'i');
- $sort_dir = request_var('sd', 'd');
+ $sort_days = $request->variable('st', 0);
+ $sort_key = $request->variable('sk', 'i');
+ $sort_dir = $request->variable('sd', 'd');
$form_key = 'acp_inactive';
add_form_key($form_key);
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
// We build the sort key and per page settings here, because they may be needed later
// Number of entries to display
- $per_page = request_var('users_per_page', (int) $config['topics_per_page']);
+ $per_page = $request->variable('users_per_page', (int) $config['topics_per_page']);
// Sorting
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
@@ -141,8 +143,10 @@ class acp_inactive
{
foreach ($inactive_users as $row)
{
- add_log('admin', 'LOG_USER_ACTIVE', $row['username']);
- add_log('user', $row['user_id'], 'LOG_USER_ACTIVE_USER');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($row['username']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array(
+ 'reportee_id' => $row['user_id']
+ ));
}
trigger_error(sprintf($user->lang['LOG_INACTIVE_ACTIVATE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));
@@ -160,12 +164,13 @@ class acp_inactive
{
if (!$auth->acl_get('a_userdel'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
user_delete('retain', $mark, true);
- add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_' . strtoupper($action), false, array(implode(', ', $user_affected)));
trigger_error(sprintf($user->lang['LOG_INACTIVE_DELETE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));
}
@@ -240,7 +245,7 @@ class acp_inactive
WHERE ' . $db->sql_in_set('user_id', $user_ids);
$db->sql_query($sql);
- add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_REMIND', false, array(implode(', ', $usernames)));
trigger_error(sprintf($user->lang['LOG_INACTIVE_REMIND'], implode($user->lang['COMMA_SEPARATOR'], $usernames) . ' ' . adm_back_link($this->u_action)));
}
diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php
index a482b41e1d..5dec6bb7d4 100644
--- a/phpBB/includes/acp/acp_jabber.php
+++ b/phpBB/includes/acp/acp_jabber.php
@@ -29,8 +29,8 @@ class acp_jabber
function main($id, $mode)
{
- global $db, $user, $auth, $template;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $template, $phpbb_log, $request;
+ global $config, $phpbb_root_path, $phpEx;
$user->add_lang('acp/board');
@@ -39,7 +39,6 @@ class acp_jabber
include($phpbb_root_path . 'includes/functions_jabber.' . $phpEx);
}
- $action = request_var('action', '');
$submit = (isset($_POST['submit'])) ? true : false;
if ($mode != 'settings')
@@ -50,13 +49,13 @@ class acp_jabber
$this->tpl_name = 'acp_jabber';
$this->page_title = 'ACP_JABBER_SETTINGS';
- $jab_enable = request_var('jab_enable', (bool) $config['jab_enable']);
- $jab_host = request_var('jab_host', (string) $config['jab_host']);
- $jab_port = request_var('jab_port', (int) $config['jab_port']);
- $jab_username = request_var('jab_username', (string) $config['jab_username']);
- $jab_password = request_var('jab_password', (string) $config['jab_password']);
- $jab_package_size = request_var('jab_package_size', (int) $config['jab_package_size']);
- $jab_use_ssl = request_var('jab_use_ssl', (bool) $config['jab_use_ssl']);
+ $jab_enable = $request->variable('jab_enable', (bool) $config['jab_enable']);
+ $jab_host = $request->variable('jab_host', (string) $config['jab_host']);
+ $jab_port = $request->variable('jab_port', (int) $config['jab_port']);
+ $jab_username = $request->variable('jab_username', (string) $config['jab_username']);
+ $jab_password = $request->variable('jab_password', (string) $config['jab_password']);
+ $jab_package_size = $request->variable('jab_package_size', (int) $config['jab_package_size']);
+ $jab_use_ssl = $request->variable('jab_use_ssl', (bool) $config['jab_use_ssl']);
$form_name = 'acp_jabber';
add_form_key($form_name);
@@ -68,8 +67,6 @@ class acp_jabber
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
- $error = array();
-
$message = $user->lang['JAB_SETTINGS_CHANGED'];
$log = 'JAB_SETTINGS_CHANGED';
@@ -106,18 +103,18 @@ class acp_jabber
$db->sql_query($sql);
}
- set_config('jab_enable', $jab_enable);
- set_config('jab_host', $jab_host);
- set_config('jab_port', $jab_port);
- set_config('jab_username', $jab_username);
+ $config->set('jab_enable', $jab_enable);
+ $config->set('jab_host', $jab_host);
+ $config->set('jab_port', $jab_port);
+ $config->set('jab_username', $jab_username);
if ($jab_password !== '********')
{
- set_config('jab_password', $jab_password);
+ $config->set('jab_password', $jab_password);
}
- set_config('jab_package_size', $jab_package_size);
- set_config('jab_use_ssl', $jab_use_ssl);
+ $config->set('jab_package_size', $jab_package_size);
+ $config->set('jab_use_ssl', $jab_use_ssl);
- add_log('admin', 'LOG_' . $log);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . $log);
trigger_error($message . adm_back_link($this->u_action));
}
diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php
index bddc2be9cb..4baff921b6 100644
--- a/phpBB/includes/acp/acp_language.php
+++ b/phpBB/includes/acp/acp_language.php
@@ -31,7 +31,7 @@ class acp_language
function main($id, $mode)
{
- global $config, $db, $user, $template;
+ global $config, $db, $user, $template, $phpbb_log, $phpbb_container;
global $phpbb_root_path, $phpEx, $request;
if (!function_exists('validate_language_iso_name'))
@@ -44,14 +44,14 @@ class acp_language
$action = (isset($_POST['remove_store'])) ? 'details' : $action;
$submit = (empty($action) && !isset($_POST['update']) && !isset($_POST['test_connection'])) ? false : true;
- $action = (empty($action)) ? request_var('action', '') : $action;
+ $action = (empty($action)) ? $request->variable('action', '') : $action;
$form_name = 'acp_lang';
add_form_key('acp_lang');
- $lang_id = request_var('id', 0);
+ $lang_id = $request->variable('id', 0);
- $selected_lang_file = request_var('language_file', '|common.' . $phpEx);
+ $selected_lang_file = $request->variable('language_file', '|common.' . $phpEx);
list($this->language_directory, $this->language_file) = explode('|', $selected_lang_file);
@@ -84,16 +84,16 @@ class acp_language
$db->sql_freeresult($result);
$sql_ary = array(
- 'lang_english_name' => request_var('lang_english_name', $row['lang_english_name']),
- 'lang_local_name' => utf8_normalize_nfc(request_var('lang_local_name', $row['lang_local_name'], true)),
- 'lang_author' => utf8_normalize_nfc(request_var('lang_author', $row['lang_author'], true)),
+ 'lang_english_name' => $request->variable('lang_english_name', $row['lang_english_name']),
+ 'lang_local_name' => $request->variable('lang_local_name', $row['lang_local_name'], true),
+ 'lang_author' => $request->variable('lang_author', $row['lang_author'], true),
);
$db->sql_query('UPDATE ' . LANG_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
WHERE lang_id = ' . $lang_id);
- add_log('admin', 'LOG_LANGUAGE_PACK_UPDATED', $sql_ary['lang_english_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_UPDATED', false, array($sql_ary['lang_english_name']));
trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action));
break;
@@ -227,7 +227,7 @@ class acp_language
$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
$db->sql_query($sql);
- add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
+ $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));
}
@@ -249,7 +249,7 @@ class acp_language
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $lang_iso = request_var('iso', '');
+ $lang_iso = $request->variable('iso', '');
$lang_iso = basename($lang_iso);
if (!$lang_iso || !file_exists("{$phpbb_root_path}language/$lang_iso/iso.txt"))
@@ -337,7 +337,7 @@ class acp_language
}
$db->sql_freeresult($result);
- add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_INSTALLED', false, array($lang_pack['name']));
$message = sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']);
$message .= ($notify_cpf_update) ? '<br /><br />' . $user->lang['LANGUAGE_PACK_CPF_UPDATE'] : '';
@@ -385,37 +385,19 @@ class acp_language
$db->sql_freeresult($result);
$new_ary = $iso = array();
- $dp = @opendir("{$phpbb_root_path}language");
- if ($dp)
+ /** @var \phpbb\language\language_file_helper $language_helper */
+ $language_helper = $phpbb_container->get('language.helper.language_file');
+ $iso = $language_helper->get_available_languages();
+
+ foreach ($iso as $lang_array)
{
- while (($file = readdir($dp)) !== false)
- {
- if ($file[0] == '.' || !is_dir($phpbb_root_path . 'language/' . $file))
- {
- continue;
- }
+ $lang_iso = $lang_array['iso'];
- if (file_exists("{$phpbb_root_path}language/$file/iso.txt"))
- {
- if (!in_array($file, $installed))
- {
- if ($iso = file("{$phpbb_root_path}language/$file/iso.txt"))
- {
- if (sizeof($iso) == 3)
- {
- $new_ary[$file] = array(
- 'iso' => $file,
- 'name' => trim($iso[0]),
- 'local_name'=> trim($iso[1]),
- 'author' => trim($iso[2])
- );
- }
- }
- }
- }
+ if (!in_array($lang_iso, $installed))
+ {
+ $new_ary[$lang_iso] = $lang_array;
}
- closedir($dp);
}
unset($installed);
diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php
index 80dee1d620..c33ca8c4fc 100644
--- a/phpBB/includes/acp/acp_logs.php
+++ b/phpBB/includes/acp/acp_logs.php
@@ -25,28 +25,29 @@ class acp_logs
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $phpbb_container;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $user, $auth, $template, $phpbb_container;
+ global $config;
global $request;
$user->add_lang('mcp');
// Set up general vars
- $action = request_var('action', '');
- $forum_id = request_var('f', 0);
- $topic_id = request_var('t', 0);
- $start = request_var('start', 0);
+ $action = $request->variable('action', '');
+ $forum_id = $request->variable('f', 0);
+ $start = $request->variable('start', 0);
$deletemark = $request->variable('delmarked', false, false, \phpbb\request\request_interface::POST);
$deleteall = $request->variable('delall', false, false, \phpbb\request\request_interface::POST);
- $marked = request_var('mark', array(0));
+ $marked = $request->variable('mark', array(0));
// Sort keys
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 't');
- $sort_dir = request_var('sd', 'd');
+ $sort_days = $request->variable('st', 0);
+ $sort_key = $request->variable('sk', 't');
+ $sort_dir = $request->variable('sd', 'd');
$this->tpl_name = 'acp_logs';
$this->log_type = constant('LOG_' . strtoupper($mode));
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
// Delete entries if requested and able
@@ -68,10 +69,11 @@ class acp_logs
$conditions['log_time'] = array('>=', time() - ($sort_days * 86400));
}
- $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords = $request->variable('keywords', '', true);
$conditions['keywords'] = $keywords;
}
+ /* @var $phpbb_log \phpbb\log\log_interface */
$phpbb_log = $phpbb_container->get('log');
$phpbb_log->delete($mode, $conditions);
}
@@ -105,7 +107,7 @@ class acp_logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
- $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords = $request->variable('keywords', '', true);
$keywords_param = !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
$l_title = $user->lang['ACP_' . strtoupper($mode) . '_LOGS'];
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index 848cafeb67..fe9657aecb 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -25,8 +25,8 @@ class acp_main
function main($id, $mode)
{
- global $config, $db, $cache, $user, $auth, $template, $request;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
+ global $config, $db, $cache, $user, $auth, $template, $request, $phpbb_log;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher, $phpbb_filesystem;
// Show restore permissions notice
if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm'))
@@ -53,7 +53,7 @@ class acp_main
return;
}
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
if ($action)
{
@@ -118,12 +118,13 @@ class acp_main
case 'online':
if (!$auth->acl_get('a_board'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- set_config('record_online_users', 1, true);
- set_config('record_online_date', time(), true);
- add_log('admin', 'LOG_RESET_ONLINE');
+ $config->set('record_online_users', 1, false);
+ $config->set('record_online_date', time(), false);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_ONLINE');
if ($request->is_ajax())
{
@@ -134,6 +135,7 @@ class acp_main
case 'stats':
if (!$auth->acl_get('a_board'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -141,35 +143,35 @@ class acp_main
FROM ' . POSTS_TABLE . '
WHERE post_visibility = ' . ITEM_APPROVED;
$result = $db->sql_query($sql);
- set_config('num_posts', (int) $db->sql_fetchfield('stat'), true);
+ $config->set('num_posts', (int) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
$sql = 'SELECT COUNT(topic_id) AS stat
FROM ' . TOPICS_TABLE . '
WHERE topic_visibility = ' . ITEM_APPROVED;
$result = $db->sql_query($sql);
- set_config('num_topics', (int) $db->sql_fetchfield('stat'), true);
+ $config->set('num_topics', (int) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
$sql = 'SELECT COUNT(user_id) AS stat
FROM ' . USERS_TABLE . '
WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')';
$result = $db->sql_query($sql);
- set_config('num_users', (int) $db->sql_fetchfield('stat'), true);
+ $config->set('num_users', (int) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
$sql = 'SELECT COUNT(attach_id) as stat
FROM ' . ATTACHMENTS_TABLE . '
WHERE is_orphan = 0';
$result = $db->sql_query($sql);
- set_config('num_files', (int) $db->sql_fetchfield('stat'), true);
+ $config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
$sql = 'SELECT SUM(filesize) as stat
FROM ' . ATTACHMENTS_TABLE . '
WHERE is_orphan = 0';
$result = $db->sql_query($sql);
- set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true);
+ $config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
if (!function_exists('update_last_username'))
@@ -178,7 +180,7 @@ class acp_main
}
update_last_username();
- add_log('admin', 'LOG_RESYNC_STATS');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_STATS');
if ($request->is_ajax())
{
@@ -189,6 +191,7 @@ class acp_main
case 'user':
if (!$auth->acl_get('a_board'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -215,7 +218,7 @@ class acp_main
// Still no maximum post id? Then we are finished
if (!$max_post_id)
{
- add_log('admin', 'LOG_RESYNC_POSTCOUNTS');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS');
break;
}
@@ -245,7 +248,7 @@ class acp_main
$start += $step;
}
- add_log('admin', 'LOG_RESYNC_POSTCOUNTS');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS');
if ($request->is_ajax())
{
@@ -256,11 +259,12 @@ class acp_main
case 'date':
if (!$auth->acl_get('a_board'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- set_config('board_startdate', time() - 1);
- add_log('admin', 'LOG_RESET_DATE');
+ $config->set('board_startdate', time() - 1);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_DATE');
if ($request->is_ajax())
{
@@ -271,7 +275,6 @@ class acp_main
case 'db_track':
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
break;
@@ -340,7 +343,7 @@ class acp_main
}
}
- add_log('admin', 'LOG_RESYNC_POST_MARKING');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POST_MARKING');
if ($request->is_ajax())
{
@@ -352,11 +355,16 @@ class acp_main
$config->increment('assets_version', 1);
$cache->purge();
+ // Remove old renderers from the text_formatter service. Since this
+ // operation is performed after the cache is purged, there is not "current"
+ // renderer and in effect all renderers will be purged
+ $phpbb_container->get('text_formatter.cache')->tidy();
+
// Clear permissions
$auth->acl_clear_prefetch();
phpbb_cache_moderators($db, $cache, $auth);
- add_log('admin', 'LOG_PURGE_CACHE');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_CACHE');
if ($request->is_ajax())
{
@@ -367,6 +375,7 @@ class acp_main
case 'purge_sessions':
if ((int) $user->data['user_type'] !== USER_FOUNDER)
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -376,7 +385,6 @@ class acp_main
{
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$db->sql_query("DELETE FROM $table");
break;
@@ -407,7 +415,7 @@ class acp_main
$sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary);
$db->sql_query($sql);
- add_log('admin', 'LOG_PURGE_SESSIONS');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_SESSIONS');
if ($request->is_ajax())
{
@@ -421,7 +429,7 @@ class acp_main
// Version check
$user->add_lang('install');
- if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.3.3', '<'))
+ if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.4', '<'))
{
$template->assign_vars(array(
'S_PHP_VERSION_OLD' => true,
@@ -431,6 +439,7 @@ class acp_main
if ($auth->acl_get('a_board'))
{
+ /* @var $version_helper \phpbb\version_helper */
$version_helper = $phpbb_container->get('version_helper');
try
{
@@ -658,7 +667,7 @@ class acp_main
}
}
- if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx))
+ if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && $phpbb_filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx))
{
// World-Writable? (000x)
$template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002));
@@ -678,7 +687,7 @@ class acp_main
// Fill dbms version if not yet filled
if (empty($config['dbms_version']))
{
- set_config('dbms_version', $db->sql_server_info(true));
+ $config->set('dbms_version', $db->sql_server_info(true));
}
$this->tpl_name = 'acp_main';
diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php
index 9d14614417..4d90b2da8b 100644
--- a/phpBB/includes/acp/acp_modules.php
+++ b/phpBB/includes/acp/acp_modules.php
@@ -19,6 +19,8 @@ if (!defined('IN_PHPBB'))
exit;
}
+use phpbb\module\exception\module_exception;
+
/**
* - Able to check for new module versions (modes changed/adjusted/added/removed)
* Icons for:
@@ -37,8 +39,10 @@ class acp_modules
function main($id, $mode)
{
- global $db, $user, $auth, $template, $module, $request;
- global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
+ global $db, $user, $template, $module, $request, $phpbb_log, $phpbb_container;
+
+ /** @var \phpbb\module\module_manager $module_manager */
+ $module_manager = $phpbb_container->get('module.manager');
// Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant)
define('MODULE_INCLUDE', true);
@@ -68,9 +72,9 @@ class acp_modules
$this->page_title = strtoupper($this->module_class);
- $this->parent_id = request_var('parent_id', 0);
- $module_id = request_var('m', 0);
- $action = request_var('action', '');
+ $this->parent_id = $request->variable('parent_id', 0);
+ $module_id = $request->variable('m', 0);
+ $action = $request->variable('action', '');
$errors = array();
switch ($action)
@@ -94,13 +98,20 @@ class acp_modules
$db->sql_freeresult($result);
}
- $errors = $this->delete_module($module_id);
-
- if (!sizeof($errors))
+ try
{
- $this->remove_cache_file();
- trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ $row = $module_manager->get_module_row($module_id, $this->module_class);
+ $module_manager->delete_module($module_id, $this->module_class);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_REMOVED', false, array($user->lang($row['module_langname'])));
}
+ catch (module_exception $e)
+ {
+ $msg = $user->lang($e->getMessage());
+ trigger_error($msg . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
+
+ $module_manager->remove_cache_file($this->module_class);
+ trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
else
{
@@ -146,8 +157,8 @@ class acp_modules
AND module_id = $module_id";
$db->sql_query($sql);
- add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']));
- $this->remove_cache_file();
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname'])));
+ $module_manager->remove_cache_file($this->module_class);
break;
@@ -176,12 +187,16 @@ class acp_modules
trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
- $move_module_name = $this->move_module_by($row, $action, 1);
+ try
+ {
+ $move_module_name = $module_manager->move_module_by($row, $this->module_class, $action, 1);
- if ($move_module_name !== false)
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname']), $move_module_name));
+ $module_manager->remove_cache_file($this->module_class);
+ }
+ catch (module_exception $e)
{
- add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name);
- $this->remove_cache_file();
+ // Do nothing
}
if ($request->is_ajax())
@@ -195,7 +210,7 @@ class acp_modules
break;
case 'quickadd':
- $quick_install = request_var('quick_install', '');
+ $quick_install = $request->variable('quick_install', '');
if (confirm_box(true))
{
@@ -207,7 +222,7 @@ class acp_modules
list($module_basename, $module_mode) = explode('::', $quick_install);
// Check if module name and mode exist...
- $fileinfo = $this->get_module_infos($module_basename);
+ $fileinfo = $module_manager->get_module_infos($this->module_class, $module_basename);
$fileinfo = $fileinfo[$module_basename];
if (isset($fileinfo['modes'][$module_mode]))
@@ -223,11 +238,20 @@ class acp_modules
'module_auth' => $fileinfo['modes'][$module_mode]['auth'],
);
- $errors = $this->update_module_data($module_data);
+ try
+ {
+ $module_manager->update_module_data($module_data);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($user->lang($module_data['module_langname'])));
+ }
+ catch (\phpbb\module\exception\module_exception $e)
+ {
+ $msg = $user->lang($e->getMessage());
+ trigger_error($msg . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
if (!sizeof($errors))
{
- $this->remove_cache_file();
+ $module_manager->remove_cache_file($this->module_class);
trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
@@ -253,7 +277,15 @@ class acp_modules
trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
- $module_row = $this->get_module_row($module_id);
+ try
+ {
+ $module_row = $module_manager->get_module_row($module_id, $this->module_class);
+ }
+ catch (\phpbb\module\exception\module_not_found_exception $e)
+ {
+ $msg = $user->lang($e->getMessage());
+ trigger_error($msg . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
// no break
@@ -266,7 +298,7 @@ class acp_modules
'module_enabled' => 0,
'module_display' => 1,
'parent_id' => 0,
- 'module_langname' => utf8_normalize_nfc(request_var('module_langname', '', true)),
+ 'module_langname' => $request->variable('module_langname', '', true),
'module_mode' => '',
'module_auth' => '',
);
@@ -274,13 +306,13 @@ class acp_modules
$module_data = array();
- $module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']);
- $module_data['module_enabled'] = request_var('module_enabled', (int) $module_row['module_enabled']);
- $module_data['module_display'] = request_var('module_display', (int) $module_row['module_display']);
- $module_data['parent_id'] = request_var('module_parent_id', (int) $module_row['parent_id']);
+ $module_data['module_basename'] = $request->variable('module_basename', (string) $module_row['module_basename']);
+ $module_data['module_enabled'] = $request->variable('module_enabled', (int) $module_row['module_enabled']);
+ $module_data['module_display'] = $request->variable('module_display', (int) $module_row['module_display']);
+ $module_data['parent_id'] = $request->variable('module_parent_id', (int) $module_row['parent_id']);
$module_data['module_class'] = $this->module_class;
- $module_data['module_langname'] = utf8_normalize_nfc(request_var('module_langname', (string) $module_row['module_langname'], true));
- $module_data['module_mode'] = request_var('module_mode', (string) $module_row['module_mode']);
+ $module_data['module_langname'] = $request->variable('module_langname', (string) $module_row['module_langname'], true);
+ $module_data['module_mode'] = $request->variable('module_mode', (string) $module_row['module_mode']);
$submit = (isset($_POST['submit'])) ? true : false;
@@ -296,7 +328,7 @@ class acp_modules
trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
- $module_type = request_var('module_type', 'category');
+ $module_type = $request->variable('module_type', 'category');
if ($module_type == 'category')
{
@@ -312,15 +344,29 @@ class acp_modules
// Adjust auth row
if ($module_data['module_basename'] && $module_data['module_mode'])
{
- $fileinfo = $this->get_module_infos($module_data['module_basename']);
+ $fileinfo = $module_manager->get_module_infos($this->module_class, $module_data['module_basename']);
$module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth'];
}
- $errors = $this->update_module_data($module_data);
+ try
+ {
+ $module_manager->update_module_data($module_data);
+ $phpbb_log->add('admin',
+ $user->data['user_id'],
+ $user->ip,
+ ($action === 'edit') ? 'LOG_MODULE_EDIT' : 'LOG_MODULE_ADD',
+ false,
+ array($user->lang($module_data['module_langname']))
+ ); }
+ catch (\phpbb\module\exception\module_exception $e)
+ {
+ $msg = $user->lang($e->getMessage());
+ trigger_error($msg . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
if (!sizeof($errors))
{
- $this->remove_cache_file();
+ $module_manager->remove_cache_file($this->module_class);
trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
@@ -330,7 +376,7 @@ class acp_modules
$is_cat = (!$module_data['module_basename']) ? true : false;
// Get module information
- $module_infos = $this->get_module_infos();
+ $module_infos = $module_manager->get_module_infos($this->module_class);
// Build name options
$s_name_options = $s_mode_options = '';
@@ -342,7 +388,7 @@ class acp_modules
}
// Name options
- $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $option . ']</option>';
+ $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $user->lang($values['title']) . ' [' . $option . ']</option>';
$template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option)));
@@ -351,14 +397,14 @@ class acp_modules
{
if ($option == $module_data['module_basename'])
{
- $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>';
+ $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $user->lang($m_values['title']) . '</option>';
}
$template->assign_block_vars('m_names.modes', array(
'OPTION' => $m_mode,
- 'VALUE' => $this->lang_name($m_values['title']),
+ 'VALUE' => $user->lang($m_values['title']),
'A_OPTION' => addslashes($m_mode),
- 'A_VALUE' => addslashes($this->lang_name($m_values['title'])))
+ 'A_VALUE' => addslashes($user->lang($m_values['title'])))
);
}
}
@@ -376,7 +422,7 @@ class acp_modules
'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'],
- 'MODULENAME' => $this->lang_name($module_data['module_langname']),
+ 'MODULENAME' => $user->lang($module_data['module_langname']),
'ACTION' => $action,
'MODULE_ID' => $module_id,
@@ -424,11 +470,11 @@ class acp_modules
{
$navigation = '<a href="' . $this->u_action . '">' . strtoupper($this->module_class) . '</a>';
- $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending');
+ $modules_nav = $module_manager->get_module_branch($this->parent_id, $this->module_class, 'parents');
foreach ($modules_nav as $row)
{
- $langname = $this->lang_name($row['module_langname']);
+ $langname = $user->lang($row['module_langname']);
if ($row['module_id'] == $this->parent_id)
{
@@ -455,7 +501,7 @@ class acp_modules
{
do
{
- $langname = $this->lang_name($row['module_langname']);
+ $langname = $user->lang($row['module_langname']);
if (!$row['module_enabled'])
{
@@ -490,7 +536,15 @@ class acp_modules
}
else if ($this->parent_id)
{
- $row = $this->get_module_row($this->parent_id);
+ try
+ {
+ $row = $module_manager->get_module_row($this->parent_id, $this->module_class);
+ }
+ catch (\phpbb\module\exception\module_not_found_exception $e)
+ {
+ $msg = $user->lang($e->getMessage());
+ trigger_error($msg . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
$url = $this->u_action . '&amp;parent_id=' . $this->parent_id . '&amp;m=' . $row['module_id'];
@@ -509,19 +563,19 @@ class acp_modules
$db->sql_freeresult($result);
// Quick adding module
- $module_infos = $this->get_module_infos();
+ $module_infos = $module_manager->get_module_infos($this->module_class);
// Build quick options
$s_install_options = '';
foreach ($module_infos as $option => $values)
{
// Name options
- $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $option . ']">';
+ $s_install_options .= '<optgroup label="' . $user->lang($values['title']) . ' [' . $option . ']">';
// Build module modes
foreach ($values['modes'] as $m_mode => $m_values)
{
- $s_install_options .= '<option value="' . $option . '::' . $m_mode . '">&nbsp; &nbsp;' . $this->lang_name($m_values['title']) . '</option>';
+ $s_install_options .= '<option value="' . $option . '::' . $m_mode . '">&nbsp; &nbsp;' . $user->lang($m_values['title']) . '</option>';
}
$s_install_options .= '</optgroup>';
@@ -539,109 +593,11 @@ class acp_modules
}
/**
- * Get row for specified module
- */
- function get_module_row($module_id)
- {
- global $db, $user;
-
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND module_id = $module_id";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
- }
-
- return $row;
- }
-
- /**
- * Get available module information from module files
- *
- * @param string $module
- * @param bool|string $module_class
- * @param bool $use_all_available Use all available instead of just all
- * enabled extensions
- * @return array
- */
- function get_module_infos($module = '', $module_class = false, $use_all_available = false)
- {
- global $phpbb_extension_manager, $phpbb_root_path, $phpEx;
-
- $module_class = ($module_class === false) ? $this->module_class : $module_class;
-
- $directory = $phpbb_root_path . 'includes/' . $module_class . '/info/';
- $fileinfo = array();
-
- $finder = $phpbb_extension_manager->get_finder($use_all_available);
-
- $modules = $finder
- ->extension_suffix('_module')
- ->extension_directory("/$module_class")
- ->core_path("includes/$module_class/info/")
- ->core_prefix($module_class . '_')
- ->get_classes(true);
-
- foreach ($modules as $cur_module)
- {
- // Skip entries we do not need if we know the module we are
- // looking for
- if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module)
- {
- continue;
- }
-
- $info_class = preg_replace('/_module$/', '_info', $cur_module);
-
- // If the class does not exist it might be following the old
- // format. phpbb_acp_info_acp_foo needs to be turned into
- // acp_foo_info and the respective file has to be included
- // manually because it does not support auto loading
- $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module);
- $old_info_class = $old_info_class_file . '_info';
-
- if (class_exists($old_info_class))
- {
- $info_class = $old_info_class;
- }
- else if (!class_exists($info_class))
- {
- $info_class = $old_info_class;
- // need to check class exists again because previous checks triggered autoloading
- if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $phpEx))
- {
- include($directory . $old_info_class_file . '.' . $phpEx);
- }
- }
-
- if (class_exists($info_class))
- {
- $info = new $info_class();
- $module_info = $info->module();
-
- $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module;
-
- $fileinfo[$main_class] = $module_info;
- }
- }
-
- ksort($fileinfo);
-
- return $fileinfo;
- }
-
- /**
* Simple version of jumpbox, just lists modules
*/
function make_module_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $ignore_noncat = false)
{
- global $db, $user, $auth, $config;
+ global $db, $user;
$sql = 'SELECT module_id, module_enabled, module_basename, parent_id, module_langname, left_id, right_id, module_auth
FROM ' . MODULES_TABLE . "
@@ -696,7 +652,7 @@ class acp_modules
$selected = (is_array($select_id)) ? ((in_array($row['module_id'], $select_id)) ? ' selected="selected"' : '') : (($row['module_id'] == $select_id) ? ' selected="selected"' : '');
- $langname = $this->lang_name($row['module_langname']);
+ $langname = $user->lang($row['module_langname']);
$module_list .= '<option value="' . $row['module_id'] . '"' . $selected . ((!$row['module_enabled']) ? ' class="disabled"' : '') . '>' . $padding . $langname . '</option>';
$iteration++;
@@ -707,401 +663,4 @@ class acp_modules
return $module_list;
}
-
- /**
- * Get module branch
- */
- function get_module_branch($module_id, $type = 'all', $order = 'descending', $include_module = true)
- {
- global $db;
-
- switch ($type)
- {
- case 'parents':
- $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id';
- break;
-
- case 'children':
- $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id';
- break;
-
- default:
- $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id';
- break;
- }
-
- $rows = array();
-
- $sql = 'SELECT m2.*
- FROM ' . MODULES_TABLE . ' m1
- LEFT JOIN ' . MODULES_TABLE . " m2 ON ($condition)
- WHERE m1.module_class = '" . $db->sql_escape($this->module_class) . "'
- AND m2.module_class = '" . $db->sql_escape($this->module_class) . "'
- AND m1.module_id = $module_id
- ORDER BY m2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC');
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- if (!$include_module && $row['module_id'] == $module_id)
- {
- continue;
- }
-
- $rows[] = $row;
- }
- $db->sql_freeresult($result);
-
- return $rows;
- }
-
- /**
- * Remove modules cache file
- */
- function remove_cache_file()
- {
- global $phpbb_container;
-
- // Sanitise for future path use, it's escaped as appropriate for queries
- $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class));
-
- $phpbb_container->get('cache.driver')->destroy('_modules_' . $p_class);
-
- // Additionally remove sql cache
- $phpbb_container->get('cache.driver')->destroy('sql', MODULES_TABLE);
- }
-
- /**
- * Return correct language name
- */
- function lang_name($module_langname)
- {
- global $user;
-
- return (!empty($user->lang[$module_langname])) ? $user->lang[$module_langname] : $module_langname;
- }
-
- /**
- * Update/Add module
- *
- * @param array &$module_data The module data
- * @param bool $run_inline if set to true errors will be returned and no logs being written
- */
- function update_module_data(&$module_data, $run_inline = false)
- {
- global $db, $user;
-
- if (!isset($module_data['module_id']))
- {
- // no module_id means we're creating a new category/module
- if ($module_data['parent_id'])
- {
- $sql = 'SELECT left_id, right_id
- FROM ' . MODULES_TABLE . "
- WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
- AND module_id = " . (int) $module_data['parent_id'];
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- if ($run_inline)
- {
- return 'PARENT_NO_EXIST';
- }
-
- trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
- }
-
- // Workaround
- $row['left_id'] = (int) $row['left_id'];
- $row['right_id'] = (int) $row['right_id'];
-
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET left_id = left_id + 2, right_id = right_id + 2
- WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
- AND left_id > {$row['right_id']}";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET right_id = right_id + 2
- WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
- AND {$row['left_id']} BETWEEN left_id AND right_id";
- $db->sql_query($sql);
-
- $module_data['left_id'] = (int) $row['right_id'];
- $module_data['right_id'] = (int) $row['right_id'] + 1;
- }
- else
- {
- $sql = 'SELECT MAX(right_id) AS right_id
- FROM ' . MODULES_TABLE . "
- WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $module_data['left_id'] = (int) $row['right_id'] + 1;
- $module_data['right_id'] = (int) $row['right_id'] + 2;
- }
-
- $sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $module_data);
- $db->sql_query($sql);
-
- $module_data['module_id'] = $db->sql_nextid();
-
- if (!$run_inline)
- {
- add_log('admin', 'LOG_MODULE_ADD', $this->lang_name($module_data['module_langname']));
- }
- }
- else
- {
- $row = $this->get_module_row($module_data['module_id']);
-
- if ($module_data['module_basename'] && !$row['module_basename'])
- {
- // we're turning a category into a module
- $branch = $this->get_module_branch($module_data['module_id'], 'children', 'descending', false);
-
- if (sizeof($branch))
- {
- return array($user->lang['NO_CATEGORY_TO_MODULE']);
- }
- }
-
- if ($row['parent_id'] != $module_data['parent_id'])
- {
- $this->move_module($module_data['module_id'], $module_data['parent_id']);
- }
-
- $update_ary = $module_data;
- unset($update_ary['module_id']);
-
- $sql = 'UPDATE ' . MODULES_TABLE . '
- SET ' . $db->sql_build_array('UPDATE', $update_ary) . "
- WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
- AND module_id = " . (int) $module_data['module_id'];
- $db->sql_query($sql);
-
- if (!$run_inline)
- {
- add_log('admin', 'LOG_MODULE_EDIT', $this->lang_name($module_data['module_langname']));
- }
- }
-
- return array();
- }
-
- /**
- * Move module around the tree
- */
- function move_module($from_module_id, $to_parent_id)
- {
- global $db;
-
- $moved_modules = $this->get_module_branch($from_module_id, 'children', 'descending');
- $from_data = $moved_modules[0];
- $diff = sizeof($moved_modules) * 2;
-
- $moved_ids = array();
- for ($i = 0, $size = sizeof($moved_modules); $i < $size; ++$i)
- {
- $moved_ids[] = $moved_modules[$i]['module_id'];
- }
-
- // Resync parents
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET right_id = right_id - $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND left_id < " . (int) $from_data['right_id'] . '
- AND right_id > ' . (int) $from_data['right_id'];
- $db->sql_query($sql);
-
- // Resync righthand side of tree
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET left_id = left_id - $diff, right_id = right_id - $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND left_id > " . (int) $from_data['right_id'];
- $db->sql_query($sql);
-
- if ($to_parent_id > 0)
- {
- $to_data = $this->get_module_row($to_parent_id);
-
- // Resync new parents
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET right_id = right_id + $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id
- AND ' . $db->sql_in_set('module_id', $moved_ids, true);
- $db->sql_query($sql);
-
- // Resync the righthand side of the tree
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET left_id = left_id + $diff, right_id = right_id + $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND left_id > " . (int) $to_data['right_id'] . '
- AND ' . $db->sql_in_set('module_id', $moved_ids, true);
- $db->sql_query($sql);
-
- // Resync moved branch
- $to_data['right_id'] += $diff;
- if ($to_data['right_id'] > $from_data['right_id'])
- {
- $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1);
- }
- else
- {
- $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1);
- }
- }
- else
- {
- $sql = 'SELECT MAX(right_id) AS right_id
- FROM ' . MODULES_TABLE . "
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND " . $db->sql_in_set('module_id', $moved_ids, true);
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1);
- }
-
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET left_id = left_id $diff, right_id = right_id $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND " . $db->sql_in_set('module_id', $moved_ids);
- $db->sql_query($sql);
- }
-
- /**
- * Remove module from tree
- */
- function delete_module($module_id)
- {
- global $db, $user;
-
- $row = $this->get_module_row($module_id);
-
- $branch = $this->get_module_branch($module_id, 'children', 'descending', false);
-
- if (sizeof($branch))
- {
- return array($user->lang['CANNOT_REMOVE_MODULE']);
- }
-
- // If not move
- $diff = 2;
- $sql = 'DELETE FROM ' . MODULES_TABLE . "
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND module_id = $module_id";
- $db->sql_query($sql);
-
- $row['right_id'] = (int) $row['right_id'];
- $row['left_id'] = (int) $row['left_id'];
-
- // Resync tree
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET right_id = right_id - $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET left_id = left_id - $diff, right_id = right_id - $diff
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND left_id > {$row['right_id']}";
- $db->sql_query($sql);
-
- add_log('admin', 'LOG_MODULE_REMOVED', $this->lang_name($row['module_langname']));
-
- return array();
-
- }
-
- /**
- * Move module position by $steps up/down
- */
- function move_module_by($module_row, $action = 'move_up', $steps = 1)
- {
- global $db;
-
- /**
- * Fetch all the siblings between the module's current spot
- * and where we want to move it to. If there are less than $steps
- * siblings between the current spot and the target then the
- * module will move as far as possible
- */
- $sql = 'SELECT module_id, left_id, right_id, module_langname
- FROM ' . MODULES_TABLE . "
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND parent_id = " . (int) $module_row['parent_id'] . '
- AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC');
- $result = $db->sql_query_limit($sql, $steps);
-
- $target = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $target = $row;
- }
- $db->sql_freeresult($result);
-
- if (!sizeof($target))
- {
- // The module is already on top or bottom
- return false;
- }
-
- /**
- * $left_id and $right_id define the scope of the nodes that are affected by the move.
- * $diff_up and $diff_down are the values to substract or add to each node's left_id
- * and right_id in order to move them up or down.
- * $move_up_left and $move_up_right define the scope of the nodes that are moving
- * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down.
- */
- if ($action == 'move_up')
- {
- $left_id = (int) $target['left_id'];
- $right_id = (int) $module_row['right_id'];
-
- $diff_up = (int) ($module_row['left_id'] - $target['left_id']);
- $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
-
- $move_up_left = (int) $module_row['left_id'];
- $move_up_right = (int) $module_row['right_id'];
- }
- else
- {
- $left_id = (int) $module_row['left_id'];
- $right_id = (int) $target['right_id'];
-
- $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
- $diff_down = (int) ($target['right_id'] - $module_row['right_id']);
-
- $move_up_left = (int) ($module_row['right_id'] + 1);
- $move_up_right = (int) $target['right_id'];
- }
-
- // Now do the dirty job
- $sql = 'UPDATE ' . MODULES_TABLE . "
- SET left_id = left_id + CASE
- WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
- ELSE {$diff_down}
- END,
- right_id = right_id + CASE
- WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
- ELSE {$diff_down}
- END
- WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
- AND left_id BETWEEN {$left_id} AND {$right_id}
- AND right_id BETWEEN {$left_id} AND {$right_id}";
- $db->sql_query($sql);
-
- $this->remove_cache_file();
-
- return $this->lang_name($target['module_langname']);
- }
}
diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php
index 0796b36fef..0bfe67830f 100644
--- a/phpBB/includes/acp/acp_permission_roles.php
+++ b/phpBB/includes/acp/acp_permission_roles.php
@@ -26,9 +26,9 @@ class acp_permission_roles
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $phpbb_container;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
- global $request;
+ global $db, $user, $template, $phpbb_container;
+ global $phpbb_root_path, $phpEx;
+ global $request, $phpbb_log;
if (!function_exists('user_get_id_name'))
{
@@ -48,8 +48,8 @@ class acp_permission_roles
$this->tpl_name = 'acp_permission_roles';
$submit = (isset($_POST['submit'])) ? true : false;
- $role_id = request_var('role_id', 0);
- $action = request_var('action', '');
+ $role_id = $request->variable('role_id', 0);
+ $action = $request->variable('action', '');
$action = (isset($_POST['add'])) ? 'add' : $action;
$form_name = 'acp_permissions';
@@ -116,7 +116,7 @@ class acp_permission_roles
$this->remove_role($role_id, $permission_type);
$role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name'];
- add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', $role_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', false, array($role_name));
trigger_error($user->lang['ROLE_DELETED'] . adm_back_link($this->u_action));
}
else
@@ -155,9 +155,9 @@ class acp_permission_roles
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
- $role_name = utf8_normalize_nfc(request_var('role_name', '', true));
- $role_description = utf8_normalize_nfc(request_var('role_description', '', true));
- $auth_settings = request_var('setting', array('' => 0));
+ $role_name = $request->variable('role_name', '', true);
+ $role_description = $request->variable('role_description', '', true);
+ $auth_settings = $request->variable('setting', array('' => 0));
if (!$role_name)
{
@@ -219,7 +219,7 @@ class acp_permission_roles
$this->auth_admin->acl_set_role($role_id, $auth_settings);
$role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name;
- add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), false, array($role_name));
trigger_error($user->lang['ROLE_' . strtoupper($action) . '_SUCCESS'] . adm_back_link($this->u_action));
@@ -232,11 +232,11 @@ class acp_permission_roles
{
case 'add':
- $options_from = request_var('options_from', 0);
+ $options_from = $request->variable('options_from', 0);
$role_row = array(
- 'role_name' => utf8_normalize_nfc(request_var('role_name', '', true)),
- 'role_description' => utf8_normalize_nfc(request_var('role_description', '', true)),
+ 'role_name' => $request->variable('role_name', '', true),
+ 'role_description' => $request->variable('role_description', '', true),
'role_type' => $permission_type,
);
@@ -306,6 +306,7 @@ class acp_permission_roles
trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
+ /* @var $phpbb_permissions \phpbb\permissions */
$phpbb_permissions = $phpbb_container->get('acl.permissions');
$template->assign_vars(array(
@@ -425,7 +426,7 @@ class acp_permission_roles
$db->sql_freeresult($result);
// Display assigned items?
- $display_item = request_var('display_item', 0);
+ $display_item = $request->variable('display_item', 0);
// Select existing roles
$sql = 'SELECT *
@@ -481,8 +482,9 @@ class acp_permission_roles
*/
function display_auth_options($auth_options)
{
- global $template, $user, $phpbb_container;
+ global $template, $phpbb_container;
+ /* @var $phpbb_permissions \phpbb\permissions */
$phpbb_permissions = $phpbb_container->get('acl.permissions');
$content_array = $categories = array();
diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php
index 660afb4e93..df3e238bcc 100644
--- a/phpBB/includes/acp/acp_permissions.php
+++ b/phpBB/includes/acp/acp_permissions.php
@@ -23,12 +23,16 @@ class acp_permissions
{
var $u_action;
var $permission_dropdown;
+
+ /**
+ * @var $phpbb_permissions \phpbb\permissions
+ */
protected $permissions;
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $phpbb_container;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $auth, $template, $phpbb_container, $request;
+ global $config, $phpbb_root_path, $phpEx;
if (!function_exists('user_get_id_name'))
{
@@ -52,9 +56,9 @@ class acp_permissions
// Trace has other vars
if ($mode == 'trace')
{
- $user_id = request_var('u', 0);
- $forum_id = request_var('f', 0);
- $permission = request_var('auth', '');
+ $user_id = $request->variable('u', 0);
+ $forum_id = $request->variable('f', 0);
+ $permission = $request->variable('auth', '');
$this->tpl_name = 'permission_trace';
@@ -83,20 +87,20 @@ class acp_permissions
}
// Set some vars
- $action = request_var('action', array('' => 0));
+ $action = $request->variable('action', array('' => 0));
$action = key($action);
$action = (isset($_POST['psubmit'])) ? 'apply_permissions' : $action;
- $all_forums = request_var('all_forums', 0);
- $subforum_id = request_var('subforum_id', 0);
- $forum_id = request_var('forum_id', array(0));
+ $all_forums = $request->variable('all_forums', 0);
+ $subforum_id = $request->variable('subforum_id', 0);
+ $forum_id = $request->variable('forum_id', array(0));
- $username = request_var('username', array(''), true);
- $usernames = request_var('usernames', '', true);
- $user_id = request_var('user_id', array(0));
+ $username = $request->variable('username', array(''), true);
+ $usernames = $request->variable('usernames', '', true);
+ $user_id = $request->variable('user_id', array(0));
- $group_id = request_var('group_id', array(0));
- $select_all_groups = request_var('select_all_groups', 0);
+ $group_id = $request->variable('group_id', array(0));
+ $select_all_groups = $request->variable('select_all_groups', 0);
$form_name = 'acp_permissions';
add_form_key($form_name);
@@ -163,8 +167,6 @@ class acp_permissions
}
// Define some common variables for every mode
- $error = array();
-
$permission_scope = (strpos($mode, '_global') !== false) ? 'global' : 'local';
// Showing introductionary page?
@@ -235,7 +237,7 @@ class acp_permissions
);
// Get permission type
- $permission_type = request_var('type', $this->permission_dropdown[0]);
+ $permission_type = $request->variable('type', $this->permission_dropdown[0]);
if (!in_array($permission_type, $this->permission_dropdown))
{
@@ -313,6 +315,7 @@ class acp_permissions
case 'apply_permissions':
if (!isset($_POST['setting']))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (!check_form_key($form_name))
@@ -326,6 +329,7 @@ class acp_permissions
case 'apply_all_permissions':
if (!isset($_POST['setting']))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (!check_form_key($form_name))
@@ -677,7 +681,7 @@ class acp_permissions
global $db, $cache, $user, $auth;
global $request;
- $psubmit = request_var('psubmit', array(0 => array(0 => 0)));
+ $psubmit = $request->variable('psubmit', array(0 => array(0 => 0)));
// User or group to be set?
$ug_type = (sizeof($user_id)) ? 'user' : 'group';
@@ -685,11 +689,10 @@ class acp_permissions
// Check the permission setting again
if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $ug_id = $forum_id = 0;
-
// We loop through the auth settings defined in our submit
list($ug_id, ) = each($psubmit);
list($forum_id, ) = each($psubmit[$ug_id]);
@@ -707,7 +710,7 @@ class acp_permissions
$assigned_role = (isset($roles[$ug_id][$forum_id])) ? (int) $roles[$ug_id][$forum_id] : 0;
// Do the admin want to set these permissions to other items too?
- $inherit = request_var('inherit', array(0 => array(0)));
+ $inherit = $request->variable('inherit', array(0 => array(0)));
$ug_id = array($ug_id);
$forum_id = array($forum_id);
@@ -772,6 +775,7 @@ class acp_permissions
// Check the permission setting again
if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -884,6 +888,7 @@ class acp_permissions
// Check the permission setting again
if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -912,7 +917,7 @@ class acp_permissions
*/
function log_action($mode, $action, $permission_type, $ug_type, $ug_id, $forum_id)
{
- global $db, $user;
+ global $db, $user, $phpbb_log, $phpbb_container;
if (!is_array($ug_id))
{
@@ -929,10 +934,14 @@ class acp_permissions
$sql .= $db->sql_in_set(($ug_type == 'group') ? 'group_id' : 'user_id', array_map('intval', $ug_id));
$result = $db->sql_query($sql);
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
$l_ug_list = '';
while ($row = $db->sql_fetchrow($result))
{
- $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '<span class="sep">' . $user->lang['G_' . $row['name']] . '</span>' : $row['name']);
+ $group_name = $group_helper->get_name($row['name']);
+ $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '<span class="sep">' . $group_name . '</span>' : $group_name);
}
$db->sql_freeresult($result);
@@ -940,7 +949,7 @@ class acp_permissions
if ($forum_id[0] == 0)
{
- add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_ug_list);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), false, array($l_ug_list));
}
else
{
@@ -957,7 +966,7 @@ class acp_permissions
}
$db->sql_freeresult($result);
- add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_forum_list, $l_ug_list);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), false, array($l_forum_list, $l_ug_list));
}
}
@@ -966,7 +975,7 @@ class acp_permissions
*/
function permission_trace($user_id, $forum_id, $permission)
{
- global $db, $template, $user, $auth;
+ global $db, $template, $user, $auth, $request, $phpbb_container;
if ($user_id != $user->data['user_id'])
{
@@ -982,6 +991,9 @@ class acp_permissions
trigger_error('NO_USERS', E_USER_ERROR);
}
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
$forum_name = false;
if ($forum_id)
@@ -994,7 +1006,7 @@ class acp_permissions
$db->sql_freeresult($result);
}
- $back = request_var('back', 0);
+ $back = $request->variable('back', 0);
$template->assign_vars(array(
'PERMISSION' => $this->permissions->get_permission_lang($permission),
@@ -1028,7 +1040,7 @@ class acp_permissions
{
$groups[$row['group_id']] = array(
'auth_setting' => ACL_NO,
- 'group_name' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']
+ 'group_name' => $group_helper->get_name($row['group_name']),
);
}
$db->sql_freeresult($result);
@@ -1185,7 +1197,7 @@ class acp_permissions
*/
function copy_forum_permissions()
{
- global $db, $auth, $cache, $template, $user;
+ global $db, $auth, $cache, $template, $user, $request;
$user->add_lang('acp/forums');
@@ -1193,8 +1205,8 @@ class acp_permissions
if ($submit)
{
- $src = request_var('src_forum_id', 0);
- $dest = request_var('dest_forum_ids', array(0));
+ $src = $request->variable('src_forum_id', 0);
+ $dest = $request->variable('dest_forum_ids', array(0));
if (confirm_box(true))
{
@@ -1236,7 +1248,10 @@ class acp_permissions
*/
function retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type)
{
- global $db, $user;
+ global $db, $phpbb_container;
+
+ /** @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');
@@ -1311,7 +1326,7 @@ class acp_permissions
$defined_group_ids = array();
while ($row = $db->sql_fetchrow($result))
{
- $s_defined_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ $s_defined_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>';
$defined_group_ids[] = $row['group_id'];
}
$db->sql_freeresult($result);
diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php
index 810a111edb..2a1afe80d4 100644
--- a/phpBB/includes/acp/acp_php_info.php
+++ b/phpBB/includes/acp/acp_php_info.php
@@ -25,8 +25,7 @@ class acp_php_info
function main($id, $mode)
{
- global $db, $user, $auth, $template;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $template;
if ($mode != 'info')
{
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index 2012d3c513..b09b496bc6 100644
--- a/phpBB/includes/acp/acp_profile.php
+++ b/phpBB/includes/acp/acp_profile.php
@@ -25,13 +25,17 @@ class acp_profile
var $edit_lang_id;
var $lang_defs;
+
+ /**
+ * @var \phpbb\di\service_collection
+ */
protected $type_collection;
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $cache;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
- global $request, $phpbb_container, $phpbb_dispatcher;
+ global $config, $db, $user, $template;
+ global $phpbb_root_path, $phpEx;
+ global $request, $phpbb_container, $phpbb_log, $phpbb_dispatcher;
if (!function_exists('generate_smilies'))
{
@@ -48,10 +52,9 @@ class acp_profile
$this->page_title = 'ACP_CUSTOM_PROFILE_FIELDS';
$field_id = $request->variable('field_id', 0);
- $action = (isset($_POST['create'])) ? 'create' : request_var('action', '');
+ $action = (isset($_POST['create'])) ? 'create' : $request->variable('action', '');
$error = array();
- $s_hidden_fields = '';
$form_key = 'acp_profile';
add_form_key($form_key);
@@ -61,6 +64,7 @@ class acp_profile
trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$this->type_collection = $phpbb_container->get('profilefields.type_collection');
@@ -122,6 +126,7 @@ class acp_profile
$db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id");
$db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id");
+ /* @var $db_tools \phpbb\db\tools\tools_interface */
$db_tools = $phpbb_container->get('dbal.tools');
$db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident);
@@ -147,7 +152,7 @@ class acp_profile
$db->sql_transaction('commit');
- add_log('admin', 'LOG_PROFILE_FIELD_REMOVED', $field_ident);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_REMOVED', false, array($field_ident));
trigger_error($user->lang['REMOVED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
else
@@ -193,7 +198,7 @@ class acp_profile
$field_ident = (string) $db->sql_fetchfield('field_ident');
$db->sql_freeresult($result);
- add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_ACTIVATE', false, array($field_ident));
if ($request->is_ajax())
{
@@ -234,7 +239,7 @@ class acp_profile
));
}
- add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_DEACTIVATE', false, array($field_ident));
trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action));
@@ -280,7 +285,7 @@ class acp_profile
case 'create':
case 'edit':
- $step = request_var('step', 1);
+ $step = $request->variable('step', 1);
$submit = (isset($_REQUEST['next']) || isset($_REQUEST['prev'])) ? true : false;
$save = (isset($_REQUEST['save'])) ? true : false;
@@ -344,7 +349,7 @@ class acp_profile
// We are adding a new field, define basic params
$lang_options = $field_row = array();
- $field_type = request_var('field_type', '');
+ $field_type = $request->variable('field_type', '');
if (!isset($this->type_collection[$field_type]))
{
@@ -353,7 +358,7 @@ class acp_profile
$profile_field = $this->type_collection[$field_type];
$field_row = array_merge($profile_field->get_default_option_values(), array(
- 'field_ident' => str_replace(' ', '_', utf8_clean_string(request_var('field_ident', '', true))),
+ 'field_ident' => str_replace(' ', '_', utf8_clean_string($request->variable('field_ident', '', true))),
'field_required' => 0,
'field_show_novalue'=> 0,
'field_hide' => 0,
@@ -366,7 +371,7 @@ class acp_profile
'field_is_contact' => 0,
'field_contact_desc'=> '',
'field_contact_url' => '',
- 'lang_name' => utf8_normalize_nfc(request_var('field_ident', '', true)),
+ 'lang_name' => $request->variable('field_ident', '', true),
'lang_explain' => '',
'lang_default_value'=> '')
);
@@ -422,7 +427,7 @@ class acp_profile
$options = $profile_field->prepare_options_form($exclude, $visibility_ary);
- $cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string(request_var('field_ident', $field_row['field_ident'], true)) : request_var('field_ident', $field_row['field_ident']);
+ $cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string($request->variable('field_ident', $field_row['field_ident'], true)) : $request->variable('field_ident', $field_row['field_ident']);
$cp->vars['lang_name'] = $request->variable('lang_name', $field_row['lang_name'], true);
$cp->vars['lang_explain'] = $request->variable('lang_explain', $field_row['lang_explain'], true);
$cp->vars['lang_default_value'] = $request->variable('lang_default_value', $field_row['lang_default_value'], true);
@@ -461,7 +466,7 @@ class acp_profile
// step 2
foreach ($exclude[2] as $key)
{
- $var = utf8_normalize_nfc(request_var($key, $field_row[$key], true));
+ $var = $request->variable($key, $field_row[$key], true);
$field_data = $cp->vars;
$var = $profile_field->get_excluded_options($key, $action, $var, $field_data, 2);
@@ -507,7 +512,7 @@ class acp_profile
foreach ($exclude[3] as $key)
{
- $cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => ''), true));
+ $cp->vars[$key] = $request->variable($key, array(0 => ''), true);
if (!$cp->vars[$key] && $action == 'edit')
{
@@ -793,7 +798,7 @@ class acp_profile
*/
function build_language_options(&$cp, $field_type, $action = 'create')
{
- global $user, $config, $db, $phpbb_container;
+ global $user, $config, $db, $request;
$default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']];
@@ -834,7 +839,7 @@ class acp_profile
$lang_options[$lang_id]['lang_iso'] = $lang_iso;
foreach ($options as $field => $field_type)
{
- $value = ($action == 'create') ? utf8_normalize_nfc(request_var('l_' . $field, array(0 => ''), true)) : $cp->vars['l_' . $field];
+ $value = ($action == 'create') ? $request->variable('l_' . $field, array(0 => ''), true) : $cp->vars['l_' . $field];
if ($field == 'lang_options')
{
$var = (!isset($cp->vars['l_lang_options'][$lang_id]) || !is_array($cp->vars['l_lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['l_lang_options'][$lang_id];
@@ -890,9 +895,9 @@ class acp_profile
*/
function save_profile_field(&$cp, $field_type, $action = 'create')
{
- global $db, $config, $user, $phpbb_container, $phpbb_dispatcher;
+ global $db, $config, $user, $phpbb_container, $phpbb_log, $request, $phpbb_dispatcher;
- $field_id = request_var('field_id', 0);
+ $field_id = $request->variable('field_id', 0);
// Collect all information, if something is going wrong, abort the operation
$profile_sql = $profile_lang = $empty_lang = $profile_lang_fields = array();
@@ -979,7 +984,7 @@ class acp_profile
if ($action == 'create')
{
$field_ident = 'pf_' . $field_ident;
-
+ /* @var $db_tools \phpbb\db\tools\tools_interface */
$db_tools = $phpbb_container->get('dbal.tools');
$db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null));
}
@@ -1178,12 +1183,12 @@ class acp_profile
if ($action == 'edit')
{
- add_log('admin', 'LOG_PROFILE_FIELD_EDIT', $cp->vars['field_ident'] . ':' . $cp->vars['lang_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_EDIT', false, array($cp->vars['field_ident'] . ':' . $cp->vars['lang_name']));
trigger_error($user->lang['CHANGED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
else
{
- add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 3) . ':' . $cp->vars['lang_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_CREATE', false, array(substr($field_ident, 3) . ':' . $cp->vars['lang_name']));
trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
}
diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php
index 98d9caabdd..d37050869a 100644
--- a/phpBB/includes/acp/acp_prune.php
+++ b/phpBB/includes/acp/acp_prune.php
@@ -25,7 +25,7 @@ class acp_prune
function main($id, $mode)
{
- global $user, $phpEx, $phpbb_admin_path, $phpbb_root_path;
+ global $user, $phpEx, $phpbb_root_path;
$user->add_lang('acp/prune');
@@ -55,11 +55,10 @@ class acp_prune
*/
function prune_forums($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $auth, $template, $phpbb_log, $request;
- $all_forums = request_var('all_forums', 0);
- $forum_id = request_var('f', array(0));
+ $all_forums = $request->variable('all_forums', 0);
+ $forum_id = $request->variable('f', array(0));
$submit = (isset($_POST['submit'])) ? true : false;
if ($all_forums)
@@ -81,14 +80,14 @@ class acp_prune
{
if (confirm_box(true))
{
- $prune_posted = request_var('prune_days', 0);
- $prune_viewed = request_var('prune_vieweddays', 0);
+ $prune_posted = $request->variable('prune_days', 0);
+ $prune_viewed = $request->variable('prune_vieweddays', 0);
$prune_all = (!$prune_posted && !$prune_viewed) ? true : false;
$prune_flags = 0;
- $prune_flags += (request_var('prune_old_polls', 0)) ? 2 : 0;
- $prune_flags += (request_var('prune_announce', 0)) ? 4 : 0;
- $prune_flags += (request_var('prune_sticky', 0)) ? 8 : 0;
+ $prune_flags += ($request->variable('prune_old_polls', 0)) ? 2 : 0;
+ $prune_flags += ($request->variable('prune_announce', 0)) ? 4 : 0;
+ $prune_flags += ($request->variable('prune_sticky', 0)) ? 8 : 0;
// Convert days to seconds for timestamp functions...
$prunedate_posted = time() - ($prune_posted * 86400);
@@ -157,7 +156,8 @@ class acp_prune
// Sync all pruned forums at once
sync('forum', 'forum_id', $prune_ids, true, true);
- add_log('admin', 'LOG_PRUNE', $log_data);
+
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PRUNE', false, array($log_data));
}
$db->sql_freeresult($result);
@@ -172,11 +172,11 @@ class acp_prune
'all_forums' => $all_forums,
'f' => $forum_id,
- 'prune_days' => request_var('prune_days', 0),
- 'prune_vieweddays' => request_var('prune_vieweddays', 0),
- 'prune_old_polls' => request_var('prune_old_polls', 0),
- 'prune_announce' => request_var('prune_announce', 0),
- 'prune_sticky' => request_var('prune_sticky', 0),
+ 'prune_days' => $request->variable('prune_days', 0),
+ 'prune_vieweddays' => $request->variable('prune_vieweddays', 0),
+ 'prune_old_polls' => $request->variable('prune_old_polls', 0),
+ 'prune_announce' => $request->variable('prune_announce', 0),
+ 'prune_sticky' => $request->variable('prune_sticky', 0),
)));
}
}
@@ -232,8 +232,11 @@ class acp_prune
*/
function prune_users($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $auth, $template, $phpbb_log, $request;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container;
+
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
$user->add_lang('memberlist');
@@ -241,8 +244,8 @@ class acp_prune
if ($prune)
{
- $action = request_var('action', 'deactivate');
- $deleteposts = request_var('deleteposts', 0);
+ $action = $request->variable('action', 'deactivate');
+ $deleteposts = $request->variable('deleteposts', 0);
if (confirm_box(true))
{
@@ -272,7 +275,7 @@ class acp_prune
}
}
- add_log('admin', $l_log, implode(', ', $usernames));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $l_log, false, array(implode(', ', $usernames)));
$msg = $user->lang['USER_' . strtoupper($action) . '_SUCCESS'];
}
else
@@ -314,8 +317,8 @@ class acp_prune
'mode' => $mode,
'prune' => 1,
- 'deleteposts' => request_var('deleteposts', 0),
- 'action' => request_var('action', ''),
+ 'deleteposts' => $request->variable('deleteposts', 0),
+ 'action' => $request->variable('action', ''),
)), 'confirm_body_prune.html');
}
}
@@ -345,7 +348,7 @@ class acp_prune
$s_group_list = '';
while ($row = $db->sql_fetchrow($result))
{
- $s_group_list .= '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>';
+ $s_group_list .= '<option value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
@@ -372,9 +375,9 @@ class acp_prune
{
global $user, $db, $request;
- $users_by_name = request_var('users', '', true);
- $users_by_id = request_var('user_ids', array(0));
- $group_id = request_var('group_id', 0);
+ $users_by_name = $request->variable('users', '', true);
+ $users_by_id = $request->variable('user_ids', array(0));
+ $group_id = $request->variable('group_id', 0);
$posts_on_queue = (trim($request->variable('posts_on_queue', '')) === '') ? false : $request->variable('posts_on_queue', 0);
if ($users_by_name)
@@ -391,15 +394,15 @@ class acp_prune
}
else
{
- $username = request_var('username', '', true);
- $email = request_var('email', '');
+ $username = $request->variable('username', '', true);
+ $email = $request->variable('email', '');
- $active_select = request_var('active_select', 'lt');
- $count_select = request_var('count_select', 'eq');
- $queue_select = request_var('queue_select', 'gt');
- $joined_before = request_var('joined_before', '');
- $joined_after = request_var('joined_after', '');
- $active = request_var('active', '');
+ $active_select = $request->variable('active_select', 'lt');
+ $count_select = $request->variable('count_select', 'eq');
+ $queue_select = $request->variable('queue_select', 'gt');
+ $joined_before = $request->variable('joined_before', '');
+ $joined_after = $request->variable('joined_after', '');
+ $active = $request->variable('active', '');
$count = ($request->variable('count', '') === '') ? false : $request->variable('count', 0);
@@ -437,7 +440,6 @@ class acp_prune
}
$key_match = array('lt' => '<', 'gt' => '>', 'eq' => '=');
- $sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit');
$where_sql = '';
$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($username))) : '';
diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php
index 5885de57ec..4d2b64d74c 100644
--- a/phpBB/includes/acp/acp_ranks.php
+++ b/phpBB/includes/acp/acp_ranks.php
@@ -25,16 +25,16 @@ class acp_ranks
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $template, $cache, $request, $phpbb_dispatcher;
+ global $config, $phpbb_root_path, $phpbb_admin_path, $phpbb_log;
$user->add_lang('acp/posting');
// Set up general vars
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$action = (isset($_POST['add'])) ? 'add' : $action;
$action = (isset($_POST['save'])) ? 'save' : $action;
- $rank_id = request_var('id', 0);
+ $rank_id = $request->variable('id', 0);
$this->tpl_name = 'acp_ranks';
$this->page_title = 'ACP_MANAGE_RANKS';
@@ -50,10 +50,10 @@ class acp_ranks
{
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
- $rank_title = utf8_normalize_nfc(request_var('title', '', true));
- $special_rank = request_var('special_rank', 0);
- $min_posts = ($special_rank) ? 0 : max(0, request_var('min_posts', 0));
- $rank_image = request_var('rank_image', '');
+ $rank_title = $request->variable('title', '', true);
+ $special_rank = $request->variable('special_rank', 0);
+ $min_posts = ($special_rank) ? 0 : max(0, $request->variable('min_posts', 0));
+ $rank_image = $request->variable('rank_image', '');
// The rank image has to be a jpg, gif or png
if ($rank_image != '' && !preg_match('#(\.gif|\.png|\.jpg|\.jpeg)$#i', $rank_image))
@@ -89,14 +89,14 @@ class acp_ranks
$sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id";
$message = $user->lang['RANK_UPDATED'];
- add_log('admin', 'LOG_RANK_UPDATED', $rank_title);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_UPDATED', false, array($rank_title));
}
else
{
$sql = 'INSERT INTO ' . RANKS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
$message = $user->lang['RANK_ADDED'];
- add_log('admin', 'LOG_RANK_ADDED', $rank_title);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_ADDED', false, array($rank_title));
}
$db->sql_query($sql);
@@ -133,7 +133,7 @@ class acp_ranks
$cache->destroy('_ranks');
- add_log('admin', 'LOG_RANK_REMOVED', $rank_title);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_REMOVED', false, array($rank_title));
if ($request->is_ajax())
{
@@ -162,7 +162,7 @@ class acp_ranks
case 'edit':
case 'add':
- $data = $ranks = $existing_imgs = array();
+ $ranks = $existing_imgs = array();
$sql = 'SELECT *
FROM ' . RANKS_TABLE . '
diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php
index bd40a88138..51c398681d 100644
--- a/phpBB/includes/acp/acp_reasons.php
+++ b/phpBB/includes/acp/acp_reasons.php
@@ -25,16 +25,15 @@ class acp_reasons
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
- global $request;
+ global $db, $user, $template;
+ global $request, $phpbb_log;
$user->add_lang(array('mcp', 'acp/posting'));
// Set up general vars
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$submit = (isset($_POST['submit'])) ? true : false;
- $reason_id = request_var('id', 0);
+ $reason_id = $request->variable('id', 0);
$this->tpl_name = 'acp_reasons';
$this->page_title = 'ACP_REASONS';
@@ -50,8 +49,8 @@ class acp_reasons
case 'edit':
$reason_row = array(
- 'reason_title' => utf8_normalize_nfc(request_var('reason_title', '', true)),
- 'reason_description' => utf8_normalize_nfc(request_var('reason_description', '', true)),
+ 'reason_title' => $request->variable('reason_title', '', true),
+ 'reason_description' => $request->variable('reason_description', '', true),
);
if ($submit)
@@ -139,7 +138,7 @@ class acp_reasons
$log = 'UPDATED';
}
- add_log('admin', 'LOG_REASON_' . $log, $reason_row['reason_title']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_' . $log, false, array($reason_row['reason_title']));
trigger_error($user->lang['REASON_' . $log] . adm_back_link($this->u_action));
}
}
@@ -232,7 +231,6 @@ class acp_reasons
break;
// Standard? What's that?
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
// Change the reports using this reason to 'other'
@@ -252,7 +250,6 @@ class acp_reasons
// Teh standard
case 'postgres':
case 'oracle':
- case 'sqlite':
case 'sqlite3':
// Change the reports using this reason to 'other'
$sql = 'UPDATE ' . REPORTS_TABLE . '
@@ -264,7 +261,7 @@ class acp_reasons
$db->sql_query('DELETE FROM ' . REPORTS_REASONS_TABLE . ' WHERE reason_id = ' . $reason_id);
- add_log('admin', 'LOG_REASON_REMOVED', $reason_row['reason_title']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_REMOVED', false, array($reason_row['reason_title']));
trigger_error($user->lang['REASON_REMOVED'] . adm_back_link($this->u_action));
}
else
diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php
index cc1e5df084..a792ee6b79 100644
--- a/phpBB/includes/acp/acp_search.php
+++ b/phpBB/includes/acp/acp_search.php
@@ -50,8 +50,8 @@ class acp_search
function settings($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $request;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $user, $template, $phpbb_log, $request;
+ global $config, $phpbb_admin_path, $phpEx;
$submit = (isset($_POST['submit'])) ? true : false;
@@ -109,8 +109,8 @@ class acp_search
unset($search);
unset($error);
- $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : array();
- $updated = request_var('updated', false);
+ $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : array();
+ $updated = $request->variable('updated', false);
foreach ($settings as $config_name => $var_type)
{
@@ -138,7 +138,7 @@ class acp_search
// only change config if anything was actually changed
if ($submit && ($config[$config_name] != $config_value))
{
- set_config($config_name, $config_value);
+ $config->set($config_name, $config_value);
$updated = true;
}
}
@@ -148,7 +148,7 @@ class acp_search
$extra_message = '';
if ($updated)
{
- add_log('admin', 'LOG_CONFIG_SEARCH');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH');
}
if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type']))
@@ -162,11 +162,11 @@ class acp_search
{
if (!method_exists($search, 'init') || !($error = $search->init()))
{
- set_config('search_type', $cfg_array['search_type']);
+ $config->set('search_type', $cfg_array['search_type']);
if (!$updated)
{
- add_log('admin', 'LOG_CONFIG_SEARCH');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH');
}
$extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=search&amp;mode=index') . '">&raquo; ' . $user->lang['GO_TO_SEARCH_INDEX'] . '</a>';
}
@@ -237,10 +237,10 @@ class acp_search
function index($id, $mode)
{
- global $db, $user, $auth, $template, $cache, $request;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $template, $phpbb_log, $request;
+ global $config, $phpbb_admin_path, $phpEx;
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$this->state = explode(',', $config['search_indexing_state']);
if (isset($_POST['cancel']))
@@ -261,7 +261,7 @@ class acp_search
switch ($action)
{
case 'progress_bar':
- $type = request_var('type', '');
+ $type = $request->variable('type', '');
$this->display_progress_bar($type);
break;
@@ -280,7 +280,7 @@ class acp_search
if (empty($this->state[0]))
{
- $this->state[0] = request_var('search_type', '');
+ $this->state[0] = $request->variable('search_type', '');
}
$this->search = null;
@@ -314,8 +314,7 @@ class acp_search
}
else
{
- $starttime = explode(' ', microtime());
- $starttime = $starttime[1] + $starttime[0];
+ $starttime = microtime(true);
$row_count = 0;
while (still_on_time() && $post_counter <= $this->max_post_id)
{
@@ -347,8 +346,7 @@ class acp_search
if ($post_counter <= $this->max_post_id)
{
- $mtime = explode(' ', microtime());
- $totaltime = $mtime[0] + $mtime[1] - $starttime;
+ $totaltime = microtime(true) - $starttime;
$rows_per_second = $row_count / $totaltime;
meta_refresh(1, append_sid($this->u_action . '&amp;action=delete&amp;skip_rows=' . $post_counter . '&amp;hash=' . generate_link_hash('acp_search')));
trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second));
@@ -360,7 +358,7 @@ class acp_search
$this->state = array('');
$this->save_state();
- add_log('admin', 'LOG_SEARCH_INDEX_REMOVED', $name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($name));
trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js());
break;
@@ -387,8 +385,7 @@ class acp_search
}
$db->sql_freeresult($result);
- $starttime = explode(' ', microtime());
- $starttime = $starttime[1] + $starttime[0];
+ $starttime = microtime(true);
$row_count = 0;
while (still_on_time() && $post_counter <= $this->max_post_id)
{
@@ -437,8 +434,7 @@ class acp_search
if ($post_counter <= $this->max_post_id)
{
- $mtime = explode(' ', microtime());
- $totaltime = $mtime[0] + $mtime[1] - $starttime;
+ $totaltime = microtime(true) - $starttime;
$rows_per_second = $row_count / $totaltime;
meta_refresh(1, append_sid($this->u_action . '&amp;action=create&amp;skip_rows=' . $post_counter . '&amp;hash=' . generate_link_hash('acp_search')));
trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second));
@@ -450,7 +446,7 @@ class acp_search
$this->state = array('');
$this->save_state();
- add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($name));
trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js());
break;
}
@@ -566,7 +562,7 @@ class acp_search
function get_search_types()
{
- global $phpbb_root_path, $phpEx, $phpbb_extension_manager;
+ global $phpbb_extension_manager;
$finder = $phpbb_extension_manager->get_finder();
@@ -592,6 +588,8 @@ class acp_search
function save_state($state = false)
{
+ global $config;
+
if ($state)
{
$this->state = $state;
@@ -599,7 +597,7 @@ class acp_search
ksort($this->state);
- set_config('search_indexing_state', implode(',', $this->state), true);
+ $config->set('search_indexing_state', implode(',', $this->state), true);
}
/**
diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_send_statistics.php
index 7c9e9cf78e..74da5996f1 100644
--- a/phpBB/includes/acp/acp_send_statistics.php
+++ b/phpBB/includes/acp/acp_send_statistics.php
@@ -41,7 +41,7 @@ class acp_send_statistics
if (!isset($config['questionnaire_unique_id']))
{
$install_id = unique_id();
- set_config('questionnaire_unique_id', $install_id);
+ $config->set('questionnaire_unique_id', $install_id);
}
else
{
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index 5181b87ecb..7878cbc8e9 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -32,6 +32,9 @@ class acp_styles
protected $styles_list_cols = 0;
protected $reserved_style_names = array('adm', 'admin', 'all');
+ /** @var \phpbb\config\config */
+ protected $config;
+
/** @var \phpbb\db\driver\driver_interface */
protected $db;
@@ -50,6 +53,9 @@ class acp_styles
/** @var \phpbb\auth\auth */
protected $auth;
+ /** @var \phpbb\textformatter\cache_interface */
+ protected $text_formatter_cache;
+
/** @var string */
protected $phpbb_root_path;
@@ -61,7 +67,7 @@ class acp_styles
public function main($id, $mode)
{
- global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_dispatcher;
+ global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_dispatcher, $phpbb_container;
$this->db = $db;
$this->user = $user;
@@ -69,6 +75,7 @@ class acp_styles
$this->request = $request;
$this->cache = $cache;
$this->auth = $auth;
+ $this->text_formatter_cache = $phpbb_container->get('text_formatter.cache');
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
@@ -194,7 +201,6 @@ class acp_styles
$messages = array();
$installed_names = array();
$installed_dirs = array();
- $last_installed = false;
foreach ($dirs as $dir)
{
if (in_array($dir, $this->reserved_style_names))
@@ -217,7 +223,6 @@ class acp_styles
$style['style_id'] = $this->install_style($style);
$style['_installed'] = true;
$found = true;
- $last_installed = $style['style_id'];
$installed_names[] = $style['style_name'];
$installed_dirs[] = $style['style_path'];
$messages[] = sprintf($this->user->lang['STYLE_INSTALLED'], htmlspecialchars($style['style_name']));
@@ -229,6 +234,12 @@ class acp_styles
}
}
+ // Invalidate the text formatter's cache for the new styles to take effect
+ if (!empty($installed_names))
+ {
+ $this->text_formatter_cache->invalidate();
+ }
+
// Show message
if (!count($messages))
{
@@ -276,6 +287,8 @@ class acp_styles
*/
protected function action_uninstall_confirmed($ids, $delete_files)
{
+ global $user, $phpbb_log;
+
$default = $this->default_style;
$uninstalled = array();
$messages = array();
@@ -335,7 +348,7 @@ class acp_styles
// Log action
if (count($uninstalled))
{
- add_log('admin', 'LOG_STYLE_DELETE', implode(', ', $uninstalled));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_DELETE', false, array(implode(', ', $uninstalled)));
}
// Clear cache
@@ -407,6 +420,8 @@ class acp_styles
*/
protected function action_details()
{
+ global $user, $phpbb_log;
+
$id = $this->request->variable('id', 0);
if (!$id)
{
@@ -538,7 +553,8 @@ class acp_styles
$this->cache->purge();
}
}
- add_log('admin', 'LOG_STYLE_EDIT_DETAILS', $style['style_name']);
+
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_EDIT_DETAILS', false, array($style['style_name']));
}
// Update default style
@@ -549,7 +565,7 @@ class acp_styles
{
trigger_error($this->user->lang['STYLE_DEFAULT_CHANGE_INACTIVE'] . adm_back_link($update_action), E_USER_WARNING);
}
- set_config('default_style', $id);
+ $this->config->set('default_style', $id);
$this->cache->purge();
}
@@ -1135,6 +1151,8 @@ class acp_styles
*/
protected function install_style($style)
{
+ global $user, $phpbb_log;
+
// Generate row
$sql_ary = array();
foreach ($style as $key => $value)
@@ -1156,7 +1174,7 @@ class acp_styles
$this->db->sql_transaction('commit');
- add_log('admin', 'LOG_STYLE_ADD', $sql_ary['style_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_STYLE_ADD', false, array($sql_ary['style_name']));
return $id;
}
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
index 529f0f2185..b88e6d3984 100644
--- a/phpBB/includes/acp/acp_update.php
+++ b/phpBB/includes/acp/acp_update.php
@@ -33,6 +33,7 @@ class acp_update
$this->tpl_name = 'acp_update';
$this->page_title = 'ACP_VERSION_CHECK';
+ /* @var $version_helper \phpbb\version_helper */
$version_helper = $phpbb_container->get('version_helper');
try
{
@@ -51,7 +52,7 @@ class acp_update
$template->assign_block_vars('updates_available', $version_data);
}
- $update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update');
+ $update_link = $phpbb_root_path . 'install/app.' . $phpEx;
$template->assign_vars(array(
'S_UP_TO_DATE' => empty($updates_available),
@@ -66,7 +67,7 @@ class acp_update
// Incomplete update?
if (phpbb_version_compare($config['version'], PHPBB_VERSION, '<'))
{
- $database_update_link = append_sid($phpbb_root_path . 'install/database_update.' . $phpEx);
+ $database_update_link = $phpbb_root_path . 'install/app.php/update';
$template->assign_vars(array(
'S_UPDATE_INCOMPLETE' => true,
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index 008cc02471..fc7f3bb56a 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -31,21 +31,21 @@ class acp_users
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $cache;
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads;
+ global $config, $db, $user, $auth, $template;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx;
global $phpbb_dispatcher, $request;
- global $phpbb_container;
+ global $phpbb_container, $phpbb_log;
$user->add_lang(array('posting', 'ucp', 'acp/users'));
$this->tpl_name = 'acp_users';
$error = array();
- $username = utf8_normalize_nfc(request_var('username', '', true));
- $user_id = request_var('u', 0);
- $action = request_var('action', '');
+ $username = $request->variable('username', '', true);
+ $user_id = $request->variable('u', 0);
+ $action = $request->variable('action', '');
// Get referer to redirect user to the appropriate page after delete action
- $redirect = request_var('redirect', '');
+ $redirect = $request->variable('redirect', '');
$redirect_tag = "redirect=$redirect";
$redirect_url = append_sid("{$phpbb_admin_path}index.$phpEx", "i=$redirect");
@@ -65,7 +65,7 @@ class acp_users
$this->page_title = 'WHOIS';
$this->tpl_name = 'simple_body';
- $user_ip = phpbb_ip_normalise(request_var('user_ip', ''));
+ $user_ip = phpbb_ip_normalise($request->variable('user_ip', ''));
$domain = gethostbyaddr($user_ip);
$ipwhois = user_ipwhois($user_ip);
@@ -180,9 +180,9 @@ class acp_users
$user->add_lang('acp/ban');
- $delete = request_var('delete', 0);
- $delete_type = request_var('delete_type', '');
- $ip = request_var('ip', 'ip');
+ $delete = $request->variable('delete', 0);
+ $delete_type = $request->variable('delete_type', '');
+ $ip = $request->variable('ip', 'ip');
/**
* Run code at beginning of ACP users overview
@@ -205,6 +205,7 @@ class acp_users
{
if (!$auth->acl_get('a_userdel'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
@@ -231,7 +232,7 @@ class acp_users
{
user_delete($delete_type, $user_id, $user_row['username']);
- add_log('admin', 'LOG_USER_DELETED', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DELETED', false, array($user_row['username']));
trigger_error($user->lang['USER_DELETED'] . adm_back_link(
(empty($redirect)) ? $this->u_action : $redirect_url
)
@@ -298,13 +299,11 @@ class acp_users
case 'banuser':
$ban[] = $user_row['username'];
$reason = 'USER_ADMIN_BAN_NAME_REASON';
- $log = 'LOG_USER_BAN_USER';
break;
case 'banemail':
$ban[] = $user_row['user_email'];
$reason = 'USER_ADMIN_BAN_EMAIL_REASON';
- $log = 'LOG_USER_BAN_EMAIL';
break;
case 'banip':
@@ -322,12 +321,11 @@ class acp_users
$db->sql_freeresult($result);
$reason = 'USER_ADMIN_BAN_IP_REASON';
- $log = 'LOG_USER_BAN_IP';
break;
}
- $ban_reason = utf8_normalize_nfc(request_var('ban_reason', $user->lang[$reason], true));
- $ban_give_reason = utf8_normalize_nfc(request_var('ban_give_reason', '', true));
+ $ban_reason = $request->variable('ban_reason', $user->lang[$reason], true);
+ $ban_give_reason = $request->variable('ban_give_reason', '', true);
// Log not used at the moment, we simply utilize the ban function.
$result = user_ban(substr($action, 3), $ban, 0, 0, 0, $ban_reason, $ban_give_reason);
@@ -411,8 +409,10 @@ class acp_users
$messenger->send(NOTIFY_EMAIL);
- add_log('admin', 'LOG_USER_REACTIVATE', $user_row['username']);
- add_log('user', $user_id, 'LOG_USER_REACTIVATE_USER');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array(
+ 'reportee_id' => $user_id
+ ));
trigger_error($user->lang['FORCE_REACTIVATION_SUCCESS'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
@@ -448,6 +448,7 @@ class acp_users
{
if ($config['require_activation'] == USER_ACTIVATION_ADMIN)
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']);
@@ -475,8 +476,10 @@ class acp_users
$message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
$log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
- add_log('admin', $log, $user_row['username']);
- add_log('user', $user_id, $log . '_USER');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($user_row['username']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, $log . '_USER', false, array(
+ 'reportee_id' => $user_id
+ ));
trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
@@ -499,8 +502,10 @@ class acp_users
WHERE user_id = $user_id";
$db->sql_query($sql);
- add_log('admin', 'LOG_USER_DEL_SIG', $user_row['username']);
- add_log('user', $user_id, 'LOG_USER_DEL_SIG_USER');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG', false, array($user_row['username']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_SIG_USER', false, array(
+ 'reportee_id' => $user_id
+ ));
trigger_error($user->lang['USER_ADMIN_SIG_REMOVED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
@@ -514,11 +519,14 @@ class acp_users
}
// Delete old avatar if present
+ /* @var $phpbb_avatar_manager \phpbb\avatar\manager */
$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
$phpbb_avatar_manager->handle_avatar_delete($db, $user, $phpbb_avatar_manager->clean_row($user_row, 'user'), USERS_TABLE, 'user_');
- add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']);
- add_log('user', $user_id, 'LOG_USER_DEL_AVATAR_USER');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR', false, array($user_row['username']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_AVATAR_USER', false, array(
+ 'reportee_id' => $user_id
+ ));
trigger_error($user->lang['USER_ADMIN_AVATAR_REMOVED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
break;
@@ -530,7 +538,7 @@ class acp_users
// Delete posts, attachments, etc.
delete_posts('poster_id', $user_id);
- add_log('admin', 'LOG_USER_DEL_POSTS', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_POSTS', false, array($user_row['username']));
trigger_error($user->lang['USER_POSTS_DELETED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
else
@@ -550,9 +558,12 @@ class acp_users
if (confirm_box(true))
{
- delete_attachments('user', $user_id);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('user', $user_id);
+ unset($attachment_manager);
- add_log('admin', 'LOG_USER_DEL_ATTACH', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_ATTACH', false, array($user_row['username']));
trigger_error($user->lang['USER_ATTACHMENTS_REMOVED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
else
@@ -598,7 +609,7 @@ class acp_users
delete_pm($user_id, $msg_ids, PRIVMSGS_OUTBOX);
- add_log('admin', 'LOG_USER_DEL_OUTBOX', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_DEL_OUTBOX', false, array($user_row['username']));
$lang = 'EMPTIED';
}
@@ -627,7 +638,7 @@ class acp_users
$user->add_lang('acp/forums');
- $new_forum_id = request_var('new_f', 0);
+ $new_forum_id = $request->variable('new_f', 0);
if (!$new_forum_id)
{
@@ -769,8 +780,11 @@ class acp_users
sync('forum', 'forum_id', $forum_id_ary, false, true);
}
- add_log('admin', 'LOG_USER_MOVE_POSTS', $user_row['username'], $forum_info['forum_name']);
- add_log('user', $user_id, 'LOG_USER_MOVE_POSTS_USER', $forum_info['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS', false, array($user_row['username'], $forum_info['forum_name']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS_USER', false, array(
+ 'reportee_id' => $user_id,
+ $forum_info['forum_name']
+ ));
trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
@@ -782,7 +796,7 @@ class acp_users
{
remove_newly_registered($user_id, $user_row);
- add_log('admin', 'LOG_USER_REMOVED_NR', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REMOVED_NR', false, array($user_row['username']));
trigger_error($user->lang['USER_LIFTED_NR'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
else
@@ -814,9 +828,9 @@ class acp_users
// Handle registration info updates
$data = array(
- 'username' => utf8_normalize_nfc(request_var('user', $user_row['username'], true)),
- 'user_founder' => request_var('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0),
- 'email' => strtolower(request_var('user_email', $user_row['user_email'])),
+ 'username' => $request->variable('user', $user_row['username'], true),
+ 'user_founder' => $request->variable('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0),
+ 'email' => strtolower($request->variable('user_email', $user_row['user_email'])),
'new_password' => $request->variable('new_password', '', true),
'password_confirm' => $request->variable('password_confirm', '', true),
);
@@ -864,6 +878,7 @@ class acp_users
}
// Instantiate passwords manager
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
// Which updates do we need to do?
@@ -936,7 +951,11 @@ class acp_users
$sql_ary['username'] = $update_username;
$sql_ary['username_clean'] = utf8_clean_string($update_username);
- add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $user_row['username'], $update_username);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array(
+ 'reportee_id' => $user_id,
+ $user_row['username'],
+ $update_username
+ ));
}
if ($update_email !== false)
@@ -946,7 +965,12 @@ class acp_users
'user_email_hash' => phpbb_email_hash($update_email),
);
- add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array(
+ 'reportee_id' => $user_id,
+ $user_row['username'],
+ $user_row['user_email'],
+ $update_email
+ ));
}
if ($update_password)
@@ -957,7 +981,11 @@ class acp_users
);
$user->reset_login_keys($user_id);
- add_log('user', $user_id, 'LOG_USER_NEW_PASSWORD', $user_row['username']);
+
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array(
+ 'reportee_id' => $user_id,
+ $user_row['username']
+ ));
}
if (sizeof($sql_ary))
@@ -976,7 +1004,7 @@ class acp_users
// Let the users permissions being updated
$auth->acl_clear_prefetch($user_id);
- add_log('admin', 'LOG_USER_USER_UPDATE', $data['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_USER_UPDATE', false, array($data['username']));
trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
@@ -1133,17 +1161,19 @@ class acp_users
$user->add_lang('mcp');
// Set up general vars
- $start = request_var('start', 0);
+ $start = $request->variable('start', 0);
$deletemark = (isset($_POST['delmarked'])) ? true : false;
$deleteall = (isset($_POST['delall'])) ? true : false;
- $marked = request_var('mark', array(0));
- $message = utf8_normalize_nfc(request_var('message', '', true));
+ $marked = $request->variable('mark', array(0));
+ $message = $request->variable('message', '', true);
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
// Sort keys
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 't');
- $sort_dir = request_var('sd', 'd');
+ $sort_days = $request->variable('st', 0);
+ $sort_key = $request->variable('sk', 't');
+ $sort_dir = $request->variable('sd', 'd');
// Delete entries if requested and able
if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs'))
@@ -1173,7 +1203,7 @@ class acp_users
$where_sql";
$db->sql_query($sql);
- add_log('admin', 'LOG_CLEAR_USER', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CLEAR_USER', false, array($user_row['username']));
}
}
@@ -1184,9 +1214,16 @@ class acp_users
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
- add_log('admin', 'LOG_USER_FEEDBACK', $user_row['username']);
- add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $user_row['username']);
- add_log('user', $user_id, 'LOG_USER_GENERAL', $message);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array($user_row['username']));
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array(
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $user_row['username']
+ ));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GENERAL', false, array(
+ 'reportee_id' => $user_id,
+ $message
+ ));
trigger_error($user->lang['USER_FEEDBACK_ADDED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
@@ -1237,17 +1274,10 @@ class acp_users
$user->add_lang('mcp');
// Set up general vars
- $start = request_var('start', 0);
$deletemark = (isset($_POST['delmarked'])) ? true : false;
$deleteall = (isset($_POST['delall'])) ? true : false;
$confirm = (isset($_POST['confirm'])) ? true : false;
- $marked = request_var('mark', array(0));
- $message = utf8_normalize_nfc(request_var('message', '', true));
-
- // Sort keys
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 't');
- $sort_dir = request_var('sd', 'd');
+ $marked = $request->variable('mark', array(0));
// Delete entries if requested and able
if ($deletemark || $deleteall || $confirm)
@@ -1255,8 +1285,8 @@ class acp_users
if (confirm_box(true))
{
$where_sql = '';
- $deletemark = request_var('delmarked', 0);
- $deleteall = request_var('delall', 0);
+ $deletemark = $request->variable('delmarked', 0);
+ $deleteall = $request->variable('delall', 0);
if ($deletemark && $marked)
{
$where_sql = ' AND ' . $db->sql_in_set('warning_id', array_values($marked));
@@ -1287,11 +1317,11 @@ class acp_users
if ($log_warnings)
{
- add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WARNINGS_DELETED', false, array($user_row['username'], $num_warnings));
}
else
{
- add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WARNINGS_DELETED_ALL', false, array($user_row['username']));
}
}
}
@@ -1383,6 +1413,7 @@ class acp_users
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$cp_data = $cp_error = array();
@@ -1397,7 +1428,7 @@ class acp_users
$user_row['iso_lang_id'] = $row['lang_id'];
$data = array(
- 'jabber' => utf8_normalize_nfc(request_var('jabber', $user_row['user_jabber'], true)),
+ 'jabber' => $request->variable('jabber', $user_row['user_jabber'], true),
'bday_day' => 0,
'bday_month' => 0,
'bday_year' => 0,
@@ -1408,9 +1439,9 @@ class acp_users
list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user_row['user_birthday']);
}
- $data['bday_day'] = request_var('bday_day', $data['bday_day']);
- $data['bday_month'] = request_var('bday_month', $data['bday_month']);
- $data['bday_year'] = request_var('bday_year', $data['bday_year']);
+ $data['bday_day'] = $request->variable('bday_day', $data['bday_day']);
+ $data['bday_month'] = $request->variable('bday_month', $data['bday_month']);
+ $data['bday_year'] = $request->variable('bday_year', $data['bday_year']);
$data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']);
/**
@@ -1511,7 +1542,6 @@ class acp_users
$selected = ($i == $data['bday_month']) ? ' selected="selected"' : '';
$s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>";
}
- $s_birthday_year_options = '';
$now = getdate();
$s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>';
@@ -1546,36 +1576,36 @@ class acp_users
}
$data = array(
- 'dateformat' => utf8_normalize_nfc(request_var('dateformat', $user_row['user_dateformat'], true)),
- 'lang' => basename(request_var('lang', $user_row['user_lang'])),
- 'tz' => request_var('tz', $user_row['user_timezone']),
- 'style' => request_var('style', $user_row['user_style']),
- 'viewemail' => request_var('viewemail', $user_row['user_allow_viewemail']),
- 'massemail' => request_var('massemail', $user_row['user_allow_massemail']),
- 'hideonline' => request_var('hideonline', !$user_row['user_allow_viewonline']),
- 'notifymethod' => request_var('notifymethod', $user_row['user_notify_type']),
- 'notifypm' => request_var('notifypm', $user_row['user_notify_pm']),
- 'allowpm' => request_var('allowpm', $user_row['user_allow_pm']),
-
- 'topic_sk' => request_var('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'),
- 'topic_sd' => request_var('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'),
- 'topic_st' => request_var('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0),
-
- 'post_sk' => request_var('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'),
- 'post_sd' => request_var('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'),
- 'post_st' => request_var('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0),
-
- 'view_images' => request_var('view_images', $this->optionget($user_row, 'viewimg')),
- 'view_flash' => request_var('view_flash', $this->optionget($user_row, 'viewflash')),
- 'view_smilies' => request_var('view_smilies', $this->optionget($user_row, 'viewsmilies')),
- 'view_sigs' => request_var('view_sigs', $this->optionget($user_row, 'viewsigs')),
- 'view_avatars' => request_var('view_avatars', $this->optionget($user_row, 'viewavatars')),
- 'view_wordcensor' => request_var('view_wordcensor', $this->optionget($user_row, 'viewcensors')),
-
- 'bbcode' => request_var('bbcode', $this->optionget($user_row, 'bbcode')),
- 'smilies' => request_var('smilies', $this->optionget($user_row, 'smilies')),
- 'sig' => request_var('sig', $this->optionget($user_row, 'attachsig')),
- 'notify' => request_var('notify', $user_row['user_notify']),
+ 'dateformat' => $request->variable('dateformat', $user_row['user_dateformat'], true),
+ 'lang' => basename($request->variable('lang', $user_row['user_lang'])),
+ 'tz' => $request->variable('tz', $user_row['user_timezone']),
+ 'style' => $request->variable('style', $user_row['user_style']),
+ 'viewemail' => $request->variable('viewemail', $user_row['user_allow_viewemail']),
+ 'massemail' => $request->variable('massemail', $user_row['user_allow_massemail']),
+ 'hideonline' => $request->variable('hideonline', !$user_row['user_allow_viewonline']),
+ 'notifymethod' => $request->variable('notifymethod', $user_row['user_notify_type']),
+ 'notifypm' => $request->variable('notifypm', $user_row['user_notify_pm']),
+ 'allowpm' => $request->variable('allowpm', $user_row['user_allow_pm']),
+
+ 'topic_sk' => $request->variable('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'),
+ 'topic_sd' => $request->variable('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'),
+ 'topic_st' => $request->variable('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0),
+
+ 'post_sk' => $request->variable('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'),
+ 'post_sd' => $request->variable('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'),
+ 'post_st' => $request->variable('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0),
+
+ 'view_images' => $request->variable('view_images', $this->optionget($user_row, 'viewimg')),
+ 'view_flash' => $request->variable('view_flash', $this->optionget($user_row, 'viewflash')),
+ 'view_smilies' => $request->variable('view_smilies', $this->optionget($user_row, 'viewsmilies')),
+ 'view_sigs' => $request->variable('view_sigs', $this->optionget($user_row, 'viewsigs')),
+ 'view_avatars' => $request->variable('view_avatars', $this->optionget($user_row, 'viewavatars')),
+ 'view_wordcensor' => $request->variable('view_wordcensor', $this->optionget($user_row, 'viewcensors')),
+
+ 'bbcode' => $request->variable('bbcode', $this->optionget($user_row, 'bbcode')),
+ 'smilies' => $request->variable('smilies', $this->optionget($user_row, 'smilies')),
+ 'sig' => $request->variable('sig', $this->optionget($user_row, 'attachsig')),
+ 'notify' => $request->variable('notify', $user_row['user_notify']),
);
/**
@@ -1945,7 +1975,7 @@ class acp_users
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
- $rank_id = request_var('user_rank', 0);
+ $rank_id = $request->variable('user_rank', 0);
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_rank = $rank_id
@@ -1979,60 +2009,70 @@ class acp_users
case 'sig':
- 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);
}
- $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $this->optionget($user_row, 'sig_bbcode') : false;
- $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $this->optionget($user_row, 'sig_smilies') : false;
- $enable_urls = ($config['allow_sig_links']) ? (bool) $this->optionget($user_row, 'sig_links') : false;
- $signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true));
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? $this->optionget($user_row, 'sig_bbcode') : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? $this->optionget($user_row, 'sig_smilies') : false;
+ $enable_urls = ($config['allow_sig_links']) ? $this->optionget($user_row, 'sig_links') : false;
- $preview = (isset($_POST['preview'])) ? true : false;
+ $decoded_message = generate_text_for_edit($user_row['user_sig'], $user_row['user_sig_bbcode_uid'], $user_row['user_sig_bbcode_bitfield']);
+ $signature = $request->variable('signature', $decoded_message['text'], true);
+ $signature_preview = '';
- if ($submit || $preview)
+ if ($submit || $request->is_set_post('preview'))
{
- if (!class_exists('messenger'))
- {
- include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
- }
-
- $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false;
- $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false;
- $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
-
- $message_parser = new parse_message($signature);
-
- // Allowing Quote BBCode
- $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig');
-
- if (sizeof($message_parser->warn_msg))
- {
- $error[] = implode('<br />', $message_parser->warn_msg);
- }
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? !$request->variable('disable_bbcode', false) : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? !$request->variable('disable_smilies', false) : false;
+ $enable_urls = ($config['allow_sig_links']) ? !$request->variable('disable_magic_url', false) : false;
if (!check_form_key($form_name))
{
- $error = 'FORM_INVALID';
+ $error[] = 'FORM_INVALID';
}
+ }
- if (!sizeof($error) && $submit)
+ $bbcode_uid = $bbcode_bitfield = $bbcode_flags = '';
+ $warn_msg = generate_text_for_storage(
+ $signature,
+ $bbcode_uid,
+ $bbcode_bitfield,
+ $bbcode_flags,
+ $enable_bbcode,
+ $enable_urls,
+ $enable_smilies,
+ $config['allow_sig_img'],
+ $config['allow_sig_flash'],
+ true,
+ $config['allow_sig_links'],
+ 'sig'
+ );
+
+ if (sizeof($warn_msg))
+ {
+ $error += $warn_msg;
+ }
+
+ if (!$submit)
+ {
+ // Parse it for displaying
+ $signature_preview = generate_text_for_display($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags);
+ }
+ else
+ {
+ if (!sizeof($error))
{
$this->optionset($user_row, 'sig_bbcode', $enable_bbcode);
$this->optionset($user_row, 'sig_smilies', $enable_smilies);
$this->optionset($user_row, 'sig_links', $enable_urls);
$sql_ary = array(
- 'user_sig' => (string) $message_parser->message,
+ 'user_sig' => $signature,
'user_options' => $user_row['user_options'],
- 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid,
- 'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield
+ 'user_sig_bbcode_uid' => $bbcode_uid,
+ 'user_sig_bbcode_bitfield' => $bbcode_bitfield,
);
$sql = 'UPDATE ' . USERS_TABLE . '
@@ -2042,33 +2082,30 @@ class acp_users
trigger_error($user->lang['USER_SIG_UPDATED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
}
-
- // Replace "error" strings with their real, localised form
- $error = array_map(array($user, 'lang'), $error);
}
- $signature_preview = '';
+ // Replace "error" strings with their real, localised form
+ $error = array_map(array($user, 'lang'), $error);
- if ($preview)
+ if ($request->is_set_post('preview'))
{
- // Now parse it for displaying
- $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false);
- unset($message_parser);
+ $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield);
}
- decode_message($signature, $user_row['user_sig_bbcode_uid']);
+ /** @var \phpbb\controller\helper $controller_helper */
+ $controller_helper = $phpbb_container->get('controller.helper');
$template->assign_vars(array(
'S_SIGNATURE' => true,
- 'SIGNATURE' => $signature,
+ 'SIGNATURE' => $decoded_message['text'],
'SIGNATURE_PREVIEW' => $signature_preview,
'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '',
'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '',
'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '',
- 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
+ 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
@@ -2089,15 +2126,16 @@ class acp_users
break;
case 'attach':
+ /* @var $pagination \phpbb\pagination */
+ $pagination = $phpbb_container->get('pagination');
- $start = request_var('start', 0);
+ $start = $request->variable('start', 0);
$deletemark = (isset($_POST['delmarked'])) ? true : false;
- $marked = request_var('mark', array(0));
- $pagination = $phpbb_container->get('pagination');
+ $marked = $request->variable('mark', array(0));
// Sort keys
- $sort_key = request_var('sk', 'a');
- $sort_dir = request_var('sd', 'd');
+ $sort_key = $request->variable('sk', 'a');
+ $sort_dir = $request->variable('sd', 'd');
if ($deletemark && sizeof($marked))
{
@@ -2132,11 +2170,14 @@ class acp_users
}
$db->sql_freeresult($result);
- delete_attachments('attach', $marked);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('attach', $marked);
+ unset($attachment_manager);
$message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED'];
- add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode($user->lang['COMMA_SEPARATOR'], $log_attachments));
+ $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 . '&amp;u=' . $user_id));
}
else
@@ -2248,7 +2289,7 @@ class acp_users
}
$user->add_lang(array('groups', 'acp/groups'));
- $group_id = request_var('g', 0);
+ $group_id = $request->variable('g', 0);
if ($group_id)
{
@@ -2265,10 +2306,6 @@ class acp_users
trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
}
- else
- {
- $founder_manage = 0;
- }
switch ($action)
{
@@ -2379,6 +2416,9 @@ class acp_users
$error = array();
}
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
$sql = 'SELECT ug.*, g.*
FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . " ug
WHERE ug.user_id = $user_id
@@ -2423,7 +2463,7 @@ class acp_users
continue;
}
- $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
@@ -2477,7 +2517,7 @@ class acp_users
$user->add_lang('acp/permissions');
add_permission_language();
- $forum_id = request_var('f', 0);
+ $forum_id = $request->variable('f', 0);
// Global Permissions
if (!$forum_id)
diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php
index 272d38bcc8..e5eeb7ab07 100644
--- a/phpBB/includes/acp/acp_words.php
+++ b/phpBB/includes/acp/acp_words.php
@@ -28,13 +28,12 @@ class acp_words
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $user, $template, $cache, $phpbb_log, $request, $phpbb_container;
$user->add_lang('acp/posting');
// Set up general vars
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
$action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['save'])) ? 'save' : $action);
$s_hidden_fields = '';
@@ -50,7 +49,7 @@ class acp_words
{
case 'edit':
- $word_id = request_var('id', 0);
+ $word_id = $request->variable('id', 0);
if (!$word_id)
{
@@ -88,9 +87,9 @@ class acp_words
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
- $word_id = request_var('id', 0);
- $word = utf8_normalize_nfc(request_var('word', '', true));
- $replacement = utf8_normalize_nfc(request_var('replacement', '', true));
+ $word_id = $request->variable('id', 0);
+ $word = $request->variable('word', '', true);
+ $replacement = $request->variable('replacement', '', true);
if ($word === '' || $replacement === '')
{
@@ -115,9 +114,11 @@ class acp_words
}
$cache->destroy('_word_censors');
+ $phpbb_container->get('text_formatter.cache')->invalidate();
$log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD';
- add_log('admin', $log_action, $word);
+
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($word));
$message = ($word_id) ? $user->lang['WORD_UPDATED'] : $user->lang['WORD_ADDED'];
trigger_error($message . adm_back_link($this->u_action));
@@ -126,7 +127,7 @@ class acp_words
case 'delete':
- $word_id = request_var('id', 0);
+ $word_id = $request->variable('id', 0);
if (!$word_id)
{
@@ -147,8 +148,9 @@ class acp_words
$db->sql_query($sql);
$cache->destroy('_word_censors');
+ $phpbb_container->get('text_formatter.cache')->invalidate();
- add_log('admin', 'LOG_WORD_DELETE', $deleted_word);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word));
trigger_error($user->lang['WORD_REMOVED'] . adm_back_link($this->u_action));
}
diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php
index 52c45499b2..b36b900396 100644
--- a/phpBB/includes/acp/auth.php
+++ b/phpBB/includes/acp/auth.php
@@ -266,9 +266,14 @@ class auth_admin extends \phpbb\auth\auth
*/
function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true)
{
- global $template, $user, $db, $phpbb_root_path, $phpEx, $phpbb_container;
+ global $template, $user, $db, $phpbb_container;
+
+ /* @var $phpbb_permissions \phpbb\permissions */
$phpbb_permissions = $phpbb_container->get('acl.permissions');
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
// Define names for template loops, might be able to be set
$tpl_pmask = 'p_mask';
$tpl_fmask = 'f_mask';
@@ -300,7 +305,7 @@ class auth_admin extends \phpbb\auth\auth
$ug_names_ary = array();
while ($row = $db->sql_fetchrow($result))
{
- $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['ug_name']] : $row['ug_name']);
+ $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : $group_helper->get_name($row['ug_name']);
}
$db->sql_freeresult($result);
@@ -408,14 +413,7 @@ class auth_admin extends \phpbb\auth\auth
{
foreach ($memberships as $row)
{
- if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL)
- {
- $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']];
- }
- else
- {
- $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name'];
- }
+ $user_groups_default[$row['user_id']][] = $group_helper->get_name($groups[$row['group_id']]['group_name']);
}
}
unset($memberships, $groups);
@@ -468,7 +466,10 @@ class auth_admin extends \phpbb\auth\auth
// Build role dropdown options
$current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
+ $role_options = array();
+
$s_role_options = '';
+ $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
@reset($roles);
while (list($role_id, $role_row) = each($roles))
@@ -478,6 +479,13 @@ class auth_admin extends \phpbb\auth\auth
$title = ($role_description) ? ' title="' . $role_description . '"' : '';
$s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
+
+ $role_options[] = array(
+ 'ID' => $role_id,
+ 'ROLE_NAME' => $role_name,
+ 'TITLE' => $role_description,
+ 'SELECTED' => $role_id == $current_role_id,
+ );
}
if ($s_role_options)
@@ -505,11 +513,14 @@ class auth_admin extends \phpbb\auth\auth
$template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
'NAME' => $ug_names_ary[$ug_id],
- 'S_ROLE_OPTIONS' => $s_role_options,
'UG_ID' => $ug_id,
+ 'S_ROLE_OPTIONS' => $s_role_options,
'S_CUSTOM' => $s_custom_permissions,
- 'FORUM_ID' => $forum_id)
- );
+ 'FORUM_ID' => $forum_id,
+ 'S_ROLE_ID' => $current_role_id,
+ ));
+
+ $template->assign_block_vars_array($tpl_pmask . '.' . $tpl_fmask . '.role_options', $role_options);
$this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace);
@@ -554,6 +565,9 @@ class auth_admin extends \phpbb\auth\auth
// Build role dropdown options
$current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
+ $role_options = array();
+
+ $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
$s_role_options = '';
@reset($roles);
@@ -564,6 +578,13 @@ class auth_admin extends \phpbb\auth\auth
$title = ($role_description) ? ' title="' . $role_description . '"' : '';
$s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
+
+ $role_options[] = array(
+ 'ID' => $role_id,
+ 'ROLE_NAME' => $role_name,
+ 'TITLE' => $role_description,
+ 'SELECTED' => $role_id == $current_role_id,
+ );
}
if ($s_role_options)
@@ -592,12 +613,14 @@ class auth_admin extends \phpbb\auth\auth
$template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'],
'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'],
- 'S_ROLE_OPTIONS' => $s_role_options,
'S_CUSTOM' => $s_custom_permissions,
'UG_ID' => $ug_id,
+ 'S_ROLE_OPTIONS' => $s_role_options,
'FORUM_ID' => $forum_id)
);
+ $template->assign_block_vars_array($tpl_pmask . '.' . $tpl_fmask . '.role_options', $role_options);
+
$this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace);
}
@@ -611,13 +634,17 @@ class auth_admin extends \phpbb\auth\auth
*/
function display_role_mask(&$hold_ary)
{
- global $db, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $template, $user, $phpbb_root_path, $phpEx;
+ global $phpbb_container;
if (!sizeof($hold_ary))
{
return;
}
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
// Get forum names
$sql = 'SELECT forum_id, forum_name
FROM ' . FORUMS_TABLE . '
@@ -673,7 +700,7 @@ class auth_admin extends \phpbb\auth\auth
{
$template->assign_block_vars('role_mask.groups', array(
'GROUP_ID' => $row['group_id'],
- 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'],
+ 'GROUP_NAME' => $group_helper->get_name($row['group_name']),
'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=group&amp;g={$row['group_id']}"))
);
}
@@ -1106,8 +1133,9 @@ class auth_admin extends \phpbb\auth\auth
*/
function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $s_view, $show_trace = false)
{
- global $template, $user, $phpbb_admin_path, $phpEx, $phpbb_container;
+ global $template, $phpbb_admin_path, $phpEx, $phpbb_container;
+ /* @var $phpbb_permissions \phpbb\permissions */
$phpbb_permissions = $phpbb_container->get('acl.permissions');
@reset($category_array);
@@ -1194,8 +1222,9 @@ class auth_admin extends \phpbb\auth\auth
*/
function build_permission_array(&$permission_row, &$content_array, &$categories, $key_sort_array)
{
- global $user, $phpbb_container;
+ global $phpbb_container;
+ /* @var $phpbb_permissions \phpbb\permissions */
$phpbb_permissions = $phpbb_container->get('acl.permissions');
foreach ($key_sort_array as $forum_id)
diff --git a/phpBB/includes/acp/info/acp_attachments.php b/phpBB/includes/acp/info/acp_attachments.php
index ff6e342f77..057f08201e 100644
--- a/phpBB/includes/acp/info/acp_attachments.php
+++ b/phpBB/includes/acp/info/acp_attachments.php
@@ -18,7 +18,6 @@ class acp_attachments_info
return array(
'filename' => 'acp_attachments',
'title' => 'ACP_ATTACHMENTS',
- 'version' => '1.0.0',
'modes' => array(
'attach' => array('title' => 'ACP_ATTACHMENT_SETTINGS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_ATTACHMENTS')),
'extensions' => array('title' => 'ACP_MANAGE_EXTENSIONS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')),
diff --git a/phpBB/includes/acp/info/acp_ban.php b/phpBB/includes/acp/info/acp_ban.php
index 4959f4da41..c88f4c2ebb 100644
--- a/phpBB/includes/acp/info/acp_ban.php
+++ b/phpBB/includes/acp/info/acp_ban.php
@@ -18,7 +18,6 @@ class acp_ban_info
return array(
'filename' => 'acp_ban',
'title' => 'ACP_BAN',
- 'version' => '1.0.0',
'modes' => array(
'email' => array('title' => 'ACP_BAN_EMAILS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')),
'ip' => array('title' => 'ACP_BAN_IPS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')),
diff --git a/phpBB/includes/acp/info/acp_bbcodes.php b/phpBB/includes/acp/info/acp_bbcodes.php
index 2bca319cc3..dfcd43a8ac 100644
--- a/phpBB/includes/acp/info/acp_bbcodes.php
+++ b/phpBB/includes/acp/info/acp_bbcodes.php
@@ -18,7 +18,6 @@ class acp_bbcodes_info
return array(
'filename' => 'acp_bbcodes',
'title' => 'ACP_BBCODES',
- 'version' => '1.0.0',
'modes' => array(
'bbcodes' => array('title' => 'ACP_BBCODES', 'auth' => 'acl_a_bbcode', 'cat' => array('ACP_MESSAGES')),
),
diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php
index 6838b4f8ba..1a3ee7b6be 100644
--- a/phpBB/includes/acp/info/acp_board.php
+++ b/phpBB/includes/acp/info/acp_board.php
@@ -18,7 +18,6 @@ class acp_board_info
return array(
'filename' => 'acp_board',
'title' => 'ACP_BOARD_MANAGEMENT',
- 'version' => '1.0.0',
'modes' => array(
'settings' => array('title' => 'ACP_BOARD_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'features' => array('title' => 'ACP_BOARD_FEATURES', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
diff --git a/phpBB/includes/acp/info/acp_bots.php b/phpBB/includes/acp/info/acp_bots.php
index 9aa24927af..26782d8c0b 100644
--- a/phpBB/includes/acp/info/acp_bots.php
+++ b/phpBB/includes/acp/info/acp_bots.php
@@ -18,7 +18,6 @@ class acp_bots_info
return array(
'filename' => 'acp_bots',
'title' => 'ACP_BOTS',
- 'version' => '1.0.0',
'modes' => array(
'bots' => array('title' => 'ACP_BOTS', 'auth' => 'acl_a_bots', 'cat' => array('ACP_GENERAL_TASKS')),
),
diff --git a/phpBB/includes/acp/info/acp_captcha.php b/phpBB/includes/acp/info/acp_captcha.php
index 99dc5ce0e5..3f7bf0351d 100644
--- a/phpBB/includes/acp/info/acp_captcha.php
+++ b/phpBB/includes/acp/info/acp_captcha.php
@@ -18,7 +18,6 @@ class acp_captcha_info
return array(
'filename' => 'acp_captcha',
'title' => 'ACP_CAPTCHA',
- 'version' => '1.0.0',
'modes' => array(
'visual' => array('title' => 'ACP_VC_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'img' => array('title' => 'ACP_VC_CAPTCHA_DISPLAY', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION'), 'display' => false)
diff --git a/phpBB/includes/acp/info/acp_database.php b/phpBB/includes/acp/info/acp_database.php
index 5cf9da24fb..815db53b67 100644
--- a/phpBB/includes/acp/info/acp_database.php
+++ b/phpBB/includes/acp/info/acp_database.php
@@ -18,7 +18,6 @@ class acp_database_info
return array(
'filename' => 'acp_database',
'title' => 'ACP_DATABASE',
- 'version' => '1.0.0',
'modes' => array(
'backup' => array('title' => 'ACP_BACKUP', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')),
'restore' => array('title' => 'ACP_RESTORE', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')),
diff --git a/phpBB/includes/acp/info/acp_disallow.php b/phpBB/includes/acp/info/acp_disallow.php
index ebd44b515c..df4765b6bb 100644
--- a/phpBB/includes/acp/info/acp_disallow.php
+++ b/phpBB/includes/acp/info/acp_disallow.php
@@ -18,7 +18,6 @@ class acp_disallow_info
return array(
'filename' => 'acp_disallow',
'title' => 'ACP_DISALLOW',
- 'version' => '1.0.0',
'modes' => array(
'usernames' => array('title' => 'ACP_DISALLOW_USERNAMES', 'auth' => 'acl_a_names', 'cat' => array('ACP_USER_SECURITY')),
),
diff --git a/phpBB/includes/acp/info/acp_email.php b/phpBB/includes/acp/info/acp_email.php
index 2f77fc617c..e85ef0923a 100644
--- a/phpBB/includes/acp/info/acp_email.php
+++ b/phpBB/includes/acp/info/acp_email.php
@@ -18,7 +18,6 @@ class acp_email_info
return array(
'filename' => 'acp_email',
'title' => 'ACP_MASS_EMAIL',
- 'version' => '1.0.0',
'modes' => array(
'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')),
),
diff --git a/phpBB/includes/acp/info/acp_extensions.php b/phpBB/includes/acp/info/acp_extensions.php
index d4cf1b0ed5..9adcd543b9 100644
--- a/phpBB/includes/acp/info/acp_extensions.php
+++ b/phpBB/includes/acp/info/acp_extensions.php
@@ -18,7 +18,6 @@ class acp_extensions_info
return array(
'filename' => 'acp_extensions',
'title' => 'ACP_EXTENSION_MANAGEMENT',
- 'version' => '1.0.0',
'modes' => array(
'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')),
),
diff --git a/phpBB/includes/acp/info/acp_forums.php b/phpBB/includes/acp/info/acp_forums.php
index 647090c8c3..8b5ce7edc2 100644
--- a/phpBB/includes/acp/info/acp_forums.php
+++ b/phpBB/includes/acp/info/acp_forums.php
@@ -18,7 +18,6 @@ class acp_forums_info
return array(
'filename' => 'acp_forums',
'title' => 'ACP_FORUM_MANAGEMENT',
- 'version' => '1.0.0',
'modes' => array(
'manage' => array('title' => 'ACP_MANAGE_FORUMS', 'auth' => 'acl_a_forum', 'cat' => array('ACP_MANAGE_FORUMS')),
),
diff --git a/phpBB/includes/acp/info/acp_groups.php b/phpBB/includes/acp/info/acp_groups.php
index 6c5ad70d97..e0aafeca0d 100644
--- a/phpBB/includes/acp/info/acp_groups.php
+++ b/phpBB/includes/acp/info/acp_groups.php
@@ -18,7 +18,6 @@ class acp_groups_info
return array(
'filename' => 'acp_groups',
'title' => 'ACP_GROUPS_MANAGEMENT',
- 'version' => '1.0.0',
'modes' => array(
'manage' => array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')),
'position' => array('title' => 'ACP_GROUPS_POSITION', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')),
diff --git a/phpBB/includes/acp/info/acp_icons.php b/phpBB/includes/acp/info/acp_icons.php
index 001d6cb402..87eadddd8d 100644
--- a/phpBB/includes/acp/info/acp_icons.php
+++ b/phpBB/includes/acp/info/acp_icons.php
@@ -18,7 +18,6 @@ class acp_icons_info
return array(
'filename' => 'acp_icons',
'title' => 'ACP_ICONS_SMILIES',
- 'version' => '1.0.0',
'modes' => array(
'icons' => array('title' => 'ACP_ICONS', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')),
'smilies' => array('title' => 'ACP_SMILIES', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')),
diff --git a/phpBB/includes/acp/info/acp_inactive.php b/phpBB/includes/acp/info/acp_inactive.php
index 442eb13c30..38cb964735 100644
--- a/phpBB/includes/acp/info/acp_inactive.php
+++ b/phpBB/includes/acp/info/acp_inactive.php
@@ -18,7 +18,6 @@ class acp_inactive_info
return array(
'filename' => 'acp_inactive',
'title' => 'ACP_INACTIVE_USERS',
- 'version' => '1.0.0',
'modes' => array(
'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')),
),
diff --git a/phpBB/includes/acp/info/acp_jabber.php b/phpBB/includes/acp/info/acp_jabber.php
index c1dfb2aca7..660299a12d 100644
--- a/phpBB/includes/acp/info/acp_jabber.php
+++ b/phpBB/includes/acp/info/acp_jabber.php
@@ -18,7 +18,6 @@ class acp_jabber_info
return array(
'filename' => 'acp_jabber',
'title' => 'ACP_JABBER_SETTINGS',
- 'version' => '1.0.0',
'modes' => array(
'settings' => array('title' => 'ACP_JABBER_SETTINGS', 'auth' => 'acl_a_jabber', 'cat' => array('ACP_CLIENT_COMMUNICATION')),
),
diff --git a/phpBB/includes/acp/info/acp_language.php b/phpBB/includes/acp/info/acp_language.php
index b9efbbbd9a..1a5a2b6ba8 100644
--- a/phpBB/includes/acp/info/acp_language.php
+++ b/phpBB/includes/acp/info/acp_language.php
@@ -18,7 +18,6 @@ class acp_language_info
return array(
'filename' => 'acp_language',
'title' => 'ACP_LANGUAGE',
- 'version' => '1.0.0',
'modes' => array(
'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')),
),
diff --git a/phpBB/includes/acp/info/acp_logs.php b/phpBB/includes/acp/info/acp_logs.php
index e9e6034cd4..efa35b2118 100644
--- a/phpBB/includes/acp/info/acp_logs.php
+++ b/phpBB/includes/acp/info/acp_logs.php
@@ -18,7 +18,6 @@ class acp_logs_info
return array(
'filename' => 'acp_logs',
'title' => 'ACP_LOGGING',
- 'version' => '1.0.0',
'modes' => array(
'admin' => array('title' => 'ACP_ADMIN_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')),
'mod' => array('title' => 'ACP_MOD_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')),
diff --git a/phpBB/includes/acp/info/acp_main.php b/phpBB/includes/acp/info/acp_main.php
index 51259e3bd9..48d35da585 100644
--- a/phpBB/includes/acp/info/acp_main.php
+++ b/phpBB/includes/acp/info/acp_main.php
@@ -18,7 +18,6 @@ class acp_main_info
return array(
'filename' => 'acp_main',
'title' => 'ACP_INDEX',
- 'version' => '1.0.0',
'modes' => array(
'main' => array('title' => 'ACP_INDEX', 'auth' => '', 'cat' => array('ACP_CAT_GENERAL')),
),
diff --git a/phpBB/includes/acp/info/acp_modules.php b/phpBB/includes/acp/info/acp_modules.php
index a47cd4ad83..073e69c6a8 100644
--- a/phpBB/includes/acp/info/acp_modules.php
+++ b/phpBB/includes/acp/info/acp_modules.php
@@ -18,7 +18,6 @@ class acp_modules_info
return array(
'filename' => 'acp_modules',
'title' => 'ACP_MODULE_MANAGEMENT',
- 'version' => '1.0.0',
'modes' => array(
'acp' => array('title' => 'ACP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')),
'ucp' => array('title' => 'UCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')),
diff --git a/phpBB/includes/acp/info/acp_permission_roles.php b/phpBB/includes/acp/info/acp_permission_roles.php
index e8aa13375d..34af693b7b 100644
--- a/phpBB/includes/acp/info/acp_permission_roles.php
+++ b/phpBB/includes/acp/info/acp_permission_roles.php
@@ -18,7 +18,6 @@ class acp_permission_roles_info
return array(
'filename' => 'acp_permission_roles',
'title' => 'ACP_PERMISSION_ROLES',
- 'version' => '1.0.0',
'modes' => array(
'admin_roles' => array('title' => 'ACP_ADMIN_ROLES', 'auth' => 'acl_a_roles && acl_a_aauth', 'cat' => array('ACP_PERMISSION_ROLES')),
'user_roles' => array('title' => 'ACP_USER_ROLES', 'auth' => 'acl_a_roles && acl_a_uauth', 'cat' => array('ACP_PERMISSION_ROLES')),
diff --git a/phpBB/includes/acp/info/acp_permissions.php b/phpBB/includes/acp/info/acp_permissions.php
index 3ec592a300..3d415f2b72 100644
--- a/phpBB/includes/acp/info/acp_permissions.php
+++ b/phpBB/includes/acp/info/acp_permissions.php
@@ -18,7 +18,6 @@ class acp_permissions_info
return array(
'filename' => 'acp_permissions',
'title' => 'ACP_PERMISSIONS',
- 'version' => '1.0.0',
'modes' => array(
'intro' => array('title' => 'ACP_PERMISSIONS', 'auth' => 'acl_a_authusers || acl_a_authgroups || acl_a_viewauth', 'cat' => array('ACP_CAT_PERMISSIONS')),
'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')),
diff --git a/phpBB/includes/acp/info/acp_php_info.php b/phpBB/includes/acp/info/acp_php_info.php
index af978e0daa..c5e60c7e66 100644
--- a/phpBB/includes/acp/info/acp_php_info.php
+++ b/phpBB/includes/acp/info/acp_php_info.php
@@ -18,7 +18,6 @@ class acp_php_info_info
return array(
'filename' => 'acp_php_info',
'title' => 'ACP_PHP_INFO',
- 'version' => '1.0.0',
'modes' => array(
'info' => array('title' => 'ACP_PHP_INFO', 'auth' => 'acl_a_phpinfo', 'cat' => array('ACP_GENERAL_TASKS')),
),
diff --git a/phpBB/includes/acp/info/acp_profile.php b/phpBB/includes/acp/info/acp_profile.php
index 307e711eee..ede34204b4 100644
--- a/phpBB/includes/acp/info/acp_profile.php
+++ b/phpBB/includes/acp/info/acp_profile.php
@@ -18,7 +18,6 @@ class acp_profile_info
return array(
'filename' => 'acp_profile',
'title' => 'ACP_CUSTOM_PROFILE_FIELDS',
- 'version' => '1.0.0',
'modes' => array(
'profile' => array('title' => 'ACP_CUSTOM_PROFILE_FIELDS', 'auth' => 'acl_a_profile', 'cat' => array('ACP_CAT_USERS')),
),
diff --git a/phpBB/includes/acp/info/acp_prune.php b/phpBB/includes/acp/info/acp_prune.php
index 58cb1ba9ab..74e5248aa9 100644
--- a/phpBB/includes/acp/info/acp_prune.php
+++ b/phpBB/includes/acp/info/acp_prune.php
@@ -18,7 +18,6 @@ class acp_prune_info
return array(
'filename' => 'acp_prune',
'title' => 'ACP_PRUNING',
- 'version' => '1.0.0',
'modes' => array(
'forums' => array('title' => 'ACP_PRUNE_FORUMS', 'auth' => 'acl_a_prune', 'cat' => array('ACP_MANAGE_FORUMS')),
'users' => array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_CAT_USERS')),
diff --git a/phpBB/includes/acp/info/acp_ranks.php b/phpBB/includes/acp/info/acp_ranks.php
index 3cc9b4a428..9bf51eba3c 100644
--- a/phpBB/includes/acp/info/acp_ranks.php
+++ b/phpBB/includes/acp/info/acp_ranks.php
@@ -18,7 +18,6 @@ class acp_ranks_info
return array(
'filename' => 'acp_ranks',
'title' => 'ACP_RANKS',
- 'version' => '1.0.0',
'modes' => array(
'ranks' => array('title' => 'ACP_MANAGE_RANKS', 'auth' => 'acl_a_ranks', 'cat' => array('ACP_CAT_USERS')),
),
diff --git a/phpBB/includes/acp/info/acp_reasons.php b/phpBB/includes/acp/info/acp_reasons.php
index c48fd1aacd..55a0495d0f 100644
--- a/phpBB/includes/acp/info/acp_reasons.php
+++ b/phpBB/includes/acp/info/acp_reasons.php
@@ -18,7 +18,6 @@ class acp_reasons_info
return array(
'filename' => 'acp_reasons',
'title' => 'ACP_REASONS',
- 'version' => '1.0.0',
'modes' => array(
'main' => array('title' => 'ACP_MANAGE_REASONS', 'auth' => 'acl_a_reasons', 'cat' => array('ACP_GENERAL_TASKS')),
),
diff --git a/phpBB/includes/acp/info/acp_search.php b/phpBB/includes/acp/info/acp_search.php
index 5d681a7174..0635dd9edd 100644
--- a/phpBB/includes/acp/info/acp_search.php
+++ b/phpBB/includes/acp/info/acp_search.php
@@ -18,7 +18,6 @@ class acp_search_info
return array(
'filename' => 'acp_search',
'title' => 'ACP_SEARCH',
- 'version' => '1.0.0',
'modes' => array(
'settings' => array('title' => 'ACP_SEARCH_SETTINGS', 'auth' => 'acl_a_search', 'cat' => array('ACP_SERVER_CONFIGURATION')),
'index' => array('title' => 'ACP_SEARCH_INDEX', 'auth' => 'acl_a_search', 'cat' => array('ACP_CAT_DATABASE')),
diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_send_statistics.php
index a4f2ddc420..a0db1a48c4 100644
--- a/phpBB/includes/acp/info/acp_send_statistics.php
+++ b/phpBB/includes/acp/info/acp_send_statistics.php
@@ -18,7 +18,6 @@ class acp_send_statistics_info
return array(
'filename' => 'acp_send_statistics',
'title' => 'ACP_SEND_STATISTICS',
- 'version' => '1.0.0',
'modes' => array(
'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')),
),
diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php
index c0ab005502..59b0a64899 100644
--- a/phpBB/includes/acp/info/acp_styles.php
+++ b/phpBB/includes/acp/info/acp_styles.php
@@ -18,7 +18,6 @@ class acp_styles_info
return array(
'filename' => 'acp_styles',
'title' => 'ACP_CAT_STYLES',
- 'version' => '2.0.0',
'modes' => array(
'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
'install' => array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
diff --git a/phpBB/includes/acp/info/acp_update.php b/phpBB/includes/acp/info/acp_update.php
index ca00f6d305..7806fb4891 100644
--- a/phpBB/includes/acp/info/acp_update.php
+++ b/phpBB/includes/acp/info/acp_update.php
@@ -18,7 +18,6 @@ class acp_update_info
return array(
'filename' => 'acp_update',
'title' => 'ACP_UPDATE',
- 'version' => '1.0.0',
'modes' => array(
'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_board', 'cat' => array('ACP_AUTOMATION')),
),
diff --git a/phpBB/includes/acp/info/acp_users.php b/phpBB/includes/acp/info/acp_users.php
index ab69523cde..cb59d24293 100644
--- a/phpBB/includes/acp/info/acp_users.php
+++ b/phpBB/includes/acp/info/acp_users.php
@@ -18,7 +18,6 @@ class acp_users_info
return array(
'filename' => 'acp_users',
'title' => 'ACP_USER_MANAGEMENT',
- 'version' => '1.0.0',
'modes' => array(
'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')),
'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
diff --git a/phpBB/includes/acp/info/acp_words.php b/phpBB/includes/acp/info/acp_words.php
index 3c8c79f25f..8a6d0d7f20 100644
--- a/phpBB/includes/acp/info/acp_words.php
+++ b/phpBB/includes/acp/info/acp_words.php
@@ -18,7 +18,6 @@ class acp_words_info
return array(
'filename' => 'acp_words',
'title' => 'ACP_WORDS',
- 'version' => '1.0.0',
'modes' => array(
'words' => array('title' => 'ACP_WORDS', 'auth' => 'acl_a_words', 'cat' => array('ACP_MESSAGES')),
),
diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php
index 86390c0901..e8492a82a3 100644
--- a/phpBB/includes/bbcode.php
+++ b/phpBB/includes/bbcode.php
@@ -110,7 +110,18 @@ class bbcode
$undid_bbcode_specialchars = true;
}
- $message = preg_replace($preg['search'], $preg['replace'], $message);
+ foreach ($preg['search'] as $key => $search)
+ {
+ if (is_callable($preg['replace'][$key]))
+ {
+ $message = preg_replace_callback($search, $preg['replace'][$key], $message);
+ }
+ else
+ {
+ $message = preg_replace($search, $preg['replace'][$key], $message);
+ }
+ }
+
$preg = array('search' => array(), 'replace' => array());
}
}
@@ -129,13 +140,32 @@ class bbcode
*/
function bbcode_cache_init()
{
- global $phpbb_root_path, $phpEx, $config, $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_path_helper;
+ global $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_container, $phpbb_filesystem;
if (empty($this->template_filename))
{
$this->template_bitfield = new bitfield($user->style['bbcode_bitfield']);
- $template = new phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new phpbb\template\context(), $phpbb_extension_manager);
+ $template = new \phpbb\template\twig\twig(
+ $phpbb_container->get('path_helper'),
+ $phpbb_container->get('config'),
+ new \phpbb\template\context(),
+ new \phpbb\template\twig\environment(
+ $phpbb_container->get('config'),
+ $phpbb_container->get('filesystem'),
+ $phpbb_container->get('path_helper'),
+ $phpbb_container->getParameter('core.cache_dir'),
+ $phpbb_container->get('ext.manager'),
+ new \phpbb\template\twig\loader(
+ $phpbb_filesystem
+ )
+ ),
+ $phpbb_container->getParameter('core.cache_dir'),
+ $phpbb_container->get('user'),
+ $phpbb_container->get('template.twig.extensions.collection'),
+ $phpbb_extension_manager
+ );
+
$template->set_style();
$template->set_filenames(array('bbcode.html' => 'bbcode.html'));
$this->template_filename = $template->get_source_file_for_handle('bbcode.html');
@@ -188,18 +218,25 @@ class bbcode
{
switch ($bbcode_id)
{
- case 0:
+ case BBCODE_ID_QUOTE:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id)
),
'preg' => array(
- '#\[quote(?:=&quot;(.*?)&quot;)?:$uid\]((?!\[quote(?:=&quot;.*?&quot;)?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')"
+ '#\[quote(?:=&quot;(.*?)&quot;)?:$uid\]((?!\[quote(?:=&quot;.*?&quot;)?:$uid\]).)?#is' => function ($match) {
+ if (!isset($match[2]))
+ {
+ $match[2] = '';
+ }
+
+ return $this->bbcode_second_pass_quote($match[1], $match[2]);
+ },
)
);
break;
- case 1:
+ case BBCODE_ID_B:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[b:$uid]' => $this->bbcode_tpl('b_open', $bbcode_id),
@@ -208,7 +245,7 @@ class bbcode
);
break;
- case 2:
+ case BBCODE_ID_I:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[i:$uid]' => $this->bbcode_tpl('i_open', $bbcode_id),
@@ -217,7 +254,7 @@ class bbcode
);
break;
- case 3:
+ case BBCODE_ID_URL:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[url:$uid\]((.*?))\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
@@ -226,7 +263,7 @@ class bbcode
);
break;
- case 4:
+ case BBCODE_ID_IMG:
if ($user->optionget('viewimg'))
{
$this->bbcode_cache[$bbcode_id] = array(
@@ -245,7 +282,7 @@ class bbcode
}
break;
- case 5:
+ case BBCODE_ID_SIZE:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s' => $this->bbcode_tpl('size', $bbcode_id),
@@ -253,7 +290,7 @@ class bbcode
);
break;
- case 6:
+ case BBCODE_ID_COLOR:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
@@ -261,7 +298,7 @@ class bbcode
);
break;
- case 7:
+ case BBCODE_ID_U:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[u:$uid]' => $this->bbcode_tpl('u_open', $bbcode_id),
@@ -270,20 +307,24 @@ class bbcode
);
break;
- case 8:
+ case BBCODE_ID_CODE:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
- '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')",
+ '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#is' => function ($match) {
+ return $this->bbcode_second_pass_code($match[1], $match[2]);
+ },
)
);
break;
- case 9:
+ case BBCODE_ID_LIST:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1",
'#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1",
- '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')",
+ '#\[list=([^\[]+):$uid\]#' => function ($match) {
+ return $this->bbcode_list($match[1]);
+ },
),
'str' => array(
'[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id),
@@ -296,7 +337,7 @@ class bbcode
);
break;
- case 10:
+ case BBCODE_ID_EMAIL:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[email:$uid\]((.*?))\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id),
@@ -305,7 +346,7 @@ class bbcode
);
break;
- case 11:
+ case BBCODE_ID_FLASH:
if ($user->optionget('viewflash'))
{
$this->bbcode_cache[$bbcode_id] = array(
@@ -324,7 +365,7 @@ class bbcode
}
break;
- case 12:
+ case BBCODE_ID_ATTACH:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[/attachment:$uid]' => $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
@@ -367,7 +408,9 @@ class bbcode
}
// Replace {L_*} lang strings
- $bbcode_tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl);
+ $bbcode_tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) {
+ return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1])));
+ }, $bbcode_tpl);
if (!empty($rowset[$bbcode_id]['second_pass_replace']))
{
@@ -491,7 +534,9 @@ class bbcode
'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2')
);
- $tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl);
+ $tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) {
+ return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1])));
+ }, $tpl);
if (!empty($replacements[$tpl_name]))
{
diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php
index 54c9287c96..0f403896a7 100644
--- a/phpBB/includes/compatibility_globals.php
+++ b/phpBB/includes/compatibility_globals.php
@@ -18,30 +18,64 @@ if (!defined('IN_PHPBB'))
exit;
}
-// set up caching
-$cache = $phpbb_container->get('cache');
+/**
+ * Sets compatibility globals in the global scope
+ *
+ * This function registers compatibility variables to the global
+ * variable scope. This is required to make it possible to include this file
+ * in a service.
+ */
+function register_compatibility_globals()
+{
+ global $phpbb_container;
+
+ global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log;
+ global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template;
+
+ // set up caching
+ /* @var $cache \phpbb\cache\service */
+ $cache = $phpbb_container->get('cache');
+
+ // Instantiate some basic classes
+ /* @var $phpbb_dispatcher \phpbb\event\dispatcher */
+ $phpbb_dispatcher = $phpbb_container->get('dispatcher');
+
+ /* @var $request \phpbb\request\request_interface */
+ $request = $phpbb_container->get('request');
+ // Inject request instance, so only this instance is used with request_var
+ request_var('', 0, false, false, $request);
-// Instantiate some basic classes
-$phpbb_dispatcher = $phpbb_container->get('dispatcher');
-$request = $phpbb_container->get('request');
-$user = $phpbb_container->get('user');
-$auth = $phpbb_container->get('auth');
-$db = $phpbb_container->get('dbal.conn');
+ /* @var $user \phpbb\user */
+ $user = $phpbb_container->get('user');
-// make sure request_var uses this request instance
-request_var('', 0, false, false, $request); // "dependency injection" for a function
+ /* @var $auth \phpbb\auth\auth */
+ $auth = $phpbb_container->get('auth');
-// Grab global variables, re-cache if necessary
-$config = $phpbb_container->get('config');
-set_config(null, null, null, $config);
-set_config_count(null, null, null, $config);
+ /* @var $db \phpbb\db\driver\driver_interface */
+ $db = $phpbb_container->get('dbal.conn');
-$phpbb_log = $phpbb_container->get('log');
-$symfony_request = $phpbb_container->get('symfony_request');
-$phpbb_filesystem = $phpbb_container->get('filesystem');
-$phpbb_path_helper = $phpbb_container->get('path_helper');
+ // Grab global variables, re-cache if necessary
+ /* @var $config phpbb\config\db */
+ $config = $phpbb_container->get('config');
+ set_config('', '', false, $config);
+ set_config_count('', 0, false, $config);
-// load extensions
-$phpbb_extension_manager = $phpbb_container->get('ext.manager');
+ /* @var $phpbb_log \phpbb\log\log_interface */
+ $phpbb_log = $phpbb_container->get('log');
-$template = $phpbb_container->get('template');
+ /* @var $symfony_request \phpbb\symfony_request */
+ $symfony_request = $phpbb_container->get('symfony_request');
+
+ /* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */
+ $phpbb_filesystem = $phpbb_container->get('filesystem');
+
+ /* @var $phpbb_path_helper \phpbb\path_helper */
+ $phpbb_path_helper = $phpbb_container->get('path_helper');
+
+ // load extensions
+ /* @var $phpbb_extension_manager \phpbb\extension\manager */
+ $phpbb_extension_manager = $phpbb_container->get('ext.manager');
+
+ /* @var $template \phpbb\template\template */
+ $template = $phpbb_container->get('template');
+}
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index 23839e3d9a..38017255b4 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.1.10');
+@define('PHPBB_VERSION', '3.2.0-RC2-dev');
// QA-related
// define('PHPBB_QA', 1);
@@ -171,17 +171,33 @@ define('CONFIRM_REPORT', 4);
// Categories - Attachments
define('ATTACHMENT_CATEGORY_NONE', 0);
define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images
-define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming
-define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming
+define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming - @deprecated 3.2
+define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming - @deprecated 3.2
define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts
define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files
-define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files
+define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - @deprecated 3.2
// BBCode UID length
define('BBCODE_UID_LEN', 8);
// Number of core BBCodes
define('NUM_CORE_BBCODES', 12);
+define('NUM_PREDEFINED_BBCODES', 22);
+
+// BBCode IDs
+define('BBCODE_ID_QUOTE', 0);
+define('BBCODE_ID_B', 1);
+define('BBCODE_ID_I', 2);
+define('BBCODE_ID_URL', 3);
+define('BBCODE_ID_IMG', 4);
+define('BBCODE_ID_SIZE', 5);
+define('BBCODE_ID_COLOR', 6);
+define('BBCODE_ID_U', 7);
+define('BBCODE_ID_CODE', 8);
+define('BBCODE_ID_LIST', 9);
+define('BBCODE_ID_EMAIL', 10);
+define('BBCODE_ID_FLASH', 11);
+define('BBCODE_ID_ATTACH', 12);
// BBCode hard limit
define('BBCODE_LIMIT', 1511);
@@ -221,6 +237,9 @@ define('CAPTCHA_MAX_CHARS', 7);
// Additional constants
define('VOTE_CONVERTED', 127);
+// BC global FTW
+global $table_prefix;
+
// Table names
define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups');
define('ACL_OPTIONS_TABLE', $table_prefix . 'acl_options');
@@ -232,7 +251,7 @@ define('BANLIST_TABLE', $table_prefix . 'banlist');
define('BBCODES_TABLE', $table_prefix . 'bbcodes');
define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks');
define('BOTS_TABLE', $table_prefix . 'bots');
-define('CONFIG_TABLE', $table_prefix . 'config');
+@define('CONFIG_TABLE', $table_prefix . 'config');
define('CONFIG_TEXT_TABLE', $table_prefix . 'config_text');
define('CONFIRM_TABLE', $table_prefix . 'confirm');
define('DISALLOW_TABLE', $table_prefix . 'disallow');
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index a152d9b620..8996c0e766 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -64,135 +64,6 @@ function set_var(&$result, $var, $type, $multibyte = false)
}
/**
-* Wrapper function of \phpbb\request\request::variable which exists for backwards compatability.
-* See {@link \phpbb\request\request_interface::variable \phpbb\request\request_interface::variable} for
-* documentation of this function's use.
-*
-* @deprecated
-* @param mixed $var_name The form variable's name from which data shall be retrieved.
-* If the value is an array this may be an array of indizes which will give
-* direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a")
-* then specifying array("var", 1) as the name will return "a".
-* If you pass an instance of {@link \phpbb\request\request_interface phpbb_request_interface}
-* as this parameter it will overwrite the current request class instance. If you do
-* not do so, it will create its own instance (but leave superglobals enabled).
-* @param mixed $default A default value that is returned if the variable was not set.
-* This function will always return a value of the same type as the default.
-* @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters
-* Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks
-* @param bool $cookie This param is mapped to \phpbb\request\request_interface::COOKIE as the last param for
-* \phpbb\request\request_interface::variable for backwards compatability reasons.
-* @param \phpbb\request\request_interface|null|false If an instance of \phpbb\request\request_interface is given the instance is stored in
-* a static variable and used for all further calls where this parameters is null. Until
-* the function is called with an instance it automatically creates a new \phpbb\request\request
-* instance on every call. By passing false this per-call instantiation can be restored
-* after having passed in a \phpbb\request\request_interface instance.
-*
-* @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the
-* the same as that of $default. If the variable is not set $default is returned.
-*/
-function request_var($var_name, $default, $multibyte = false, $cookie = false, $request = null)
-{
- // This is all just an ugly hack to add "Dependency Injection" to a function
- // the only real code is the function call which maps this function to a method.
- static $static_request = null;
-
- if ($request instanceof \phpbb\request\request_interface)
- {
- $static_request = $request;
-
- if (empty($var_name))
- {
- return;
- }
- }
- else if ($request === false)
- {
- $static_request = null;
-
- if (empty($var_name))
- {
- return;
- }
- }
-
- $tmp_request = $static_request;
-
- // no request class set, create a temporary one ourselves to keep backwards compatability
- if ($tmp_request === null)
- {
- // false param: enable super globals, so the created request class does not
- // make super globals inaccessible everywhere outside this function.
- $tmp_request = new \phpbb\request\request(new \phpbb\request\type_cast_helper(), false);
- }
-
- return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST);
-}
-
-/**
-* Sets a configuration option's value.
-*
-* Please note that this function does not update the is_dynamic value for
-* an already existing config option.
-*
-* @param string $config_name The configuration option's name
-* @param string $config_value New configuration value
-* @param bool $is_dynamic Whether this variable should be cached (false) or
-* if it changes too frequently (true) to be
-* efficiently cached.
-*
-* @return null
-*
-* @deprecated
-*/
-function set_config($config_name, $config_value, $is_dynamic = false, \phpbb\config\config $set_config = null)
-{
- static $config = null;
-
- if ($set_config !== null)
- {
- $config = $set_config;
-
- if (empty($config_name))
- {
- return;
- }
- }
-
- $config->set($config_name, $config_value, !$is_dynamic);
-}
-
-/**
-* Increments an integer config value directly in the database.
-*
-* @param string $config_name The configuration option's name
-* @param int $increment Amount to increment by
-* @param bool $is_dynamic Whether this variable should be cached (false) or
-* if it changes too frequently (true) to be
-* efficiently cached.
-*
-* @return null
-*
-* @deprecated
-*/
-function set_config_count($config_name, $increment, $is_dynamic = false, \phpbb\config\config $set_config = null)
-{
- static $config = null;
-
- if ($set_config !== null)
- {
- $config = $set_config;
-
- if (empty($config_name))
- {
- return;
- }
- }
-
- $config->increment($config_name, $increment, !$is_dynamic);
-}
-
-/**
* Generates an alphanumeric random string of given length
*
* @return string
@@ -222,25 +93,10 @@ function gen_rand_string_friendly($num_chars = 8)
/**
* Return unique id
-* @param string $extra additional entropy
*/
-function unique_id($extra = 'c')
+function unique_id()
{
- static $dss_seeded = false;
- global $config;
-
- $val = $config['rand_seed'] . microtime();
- $val = md5($val);
- $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
-
- if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10)))
- {
- set_config('rand_seed_last_update', time(), true);
- set_config('rand_seed', $config['rand_seed'], true);
- $dss_seeded = true;
- }
-
- return substr($val, 4, 16);
+ return bin2hex(random_bytes(8));
}
/**
@@ -376,8 +232,7 @@ function still_on_time($extra_time = 15)
{
static $max_execution_time, $start_time;
- $time = explode(' ', microtime());
- $current_time = $time[0] + $time[1];
+ $current_time = microtime(true);
if (empty($max_execution_time))
{
@@ -441,448 +296,6 @@ function phpbb_version_compare($version1, $version2, $operator = null)
}
}
-/**
-* Global function for chmodding directories and files for internal use
-*
-* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
-* The function determines owner and group from common.php file and sets the same to the provided file.
-* The function uses bit fields to build the permissions.
-* The function sets the appropiate execute bit on directories.
-*
-* Supported constants representing bit fields are:
-*
-* CHMOD_ALL - all permissions (7)
-* CHMOD_READ - read permission (4)
-* CHMOD_WRITE - write permission (2)
-* CHMOD_EXECUTE - execute permission (1)
-*
-* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions.
-*
-* @param string $filename The file/directory to be chmodded
-* @param int $perms Permissions to set
-*
-* @return bool true on success, otherwise false
-*/
-function phpbb_chmod($filename, $perms = CHMOD_READ)
-{
- static $_chmod_info;
-
- // Return if the file no longer exists.
- if (!file_exists($filename))
- {
- return false;
- }
-
- // Determine some common vars
- if (empty($_chmod_info))
- {
- if (!function_exists('fileowner') || !function_exists('filegroup'))
- {
- // No need to further determine owner/group - it is unknown
- $_chmod_info['process'] = false;
- }
- else
- {
- global $phpbb_root_path, $phpEx;
-
- // Determine owner/group of common.php file and the filename we want to change here
- $common_php_owner = @fileowner($phpbb_root_path . 'common.' . $phpEx);
- $common_php_group = @filegroup($phpbb_root_path . 'common.' . $phpEx);
-
- // And the owner and the groups PHP is running under.
- $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
- if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group)
- {
- $_chmod_info['process'] = false;
- }
- else
- {
- $_chmod_info = array(
- 'process' => true,
- 'common_owner' => $common_php_owner,
- 'common_group' => $common_php_group,
- 'php_uid' => $php_uid,
- 'php_gids' => $php_gids,
- );
- }
- }
- }
-
- if ($_chmod_info['process'])
- {
- $file_uid = @fileowner($filename);
- $file_gid = @filegroup($filename);
-
- // Change owner
- if (@chown($filename, $_chmod_info['common_owner']))
- {
- clearstatcache();
- $file_uid = @fileowner($filename);
- }
-
- // Change group
- if (@chgrp($filename, $_chmod_info['common_group']))
- {
- clearstatcache();
- $file_gid = @filegroup($filename);
- }
-
- // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something
- if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group'])
- {
- $_chmod_info['process'] = false;
- }
- }
-
- // Still able to process?
- if ($_chmod_info['process'])
- {
- if ($file_uid == $_chmod_info['php_uid'])
- {
- $php = 'owner';
- }
- else if (in_array($file_gid, $_chmod_info['php_gids']))
- {
- $php = 'group';
- }
- else
- {
- // Since we are setting the everyone bit anyway, no need to do expensive operations
- $_chmod_info['process'] = false;
- }
- }
-
- // We are not able to determine or change something
- if (!$_chmod_info['process'])
- {
- $php = 'other';
- }
-
- // Owner always has read/write permission
- $owner = CHMOD_READ | CHMOD_WRITE;
- if (is_dir($filename))
- {
- $owner |= CHMOD_EXECUTE;
-
- // Only add execute bit to the permission if the dir needs to be readable
- if ($perms & CHMOD_READ)
- {
- $perms |= CHMOD_EXECUTE;
- }
- }
-
- switch ($php)
- {
- case 'owner':
- $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0));
-
- clearstatcache();
-
- if (is_readable($filename) && phpbb_is_writable($filename))
- {
- break;
- }
-
- case 'group':
- $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0));
-
- clearstatcache();
-
- if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename)))
- {
- break;
- }
-
- case 'other':
- $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0));
-
- clearstatcache();
-
- if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename)))
- {
- break;
- }
-
- default:
- return false;
- break;
- }
-
- return $result;
-}
-
-/**
-* Test if a file/directory is writable
-*
-* This function calls the native is_writable() when not running under
-* Windows and it is not disabled.
-*
-* @param string $file Path to perform write test on
-* @return bool True when the path is writable, otherwise false.
-*/
-function phpbb_is_writable($file)
-{
- if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable'))
- {
- if (file_exists($file))
- {
- // Canonicalise path to absolute path
- $file = phpbb_realpath($file);
-
- if (is_dir($file))
- {
- // Test directory by creating a file inside the directory
- $result = @tempnam($file, 'i_w');
-
- if (is_string($result) && file_exists($result))
- {
- unlink($result);
-
- // Ensure the file is actually in the directory (returned realpathed)
- return (strpos($result, $file) === 0) ? true : false;
- }
- }
- else
- {
- $handle = @fopen($file, 'r+');
-
- if (is_resource($handle))
- {
- fclose($handle);
- return true;
- }
- }
- }
- else
- {
- // file does not exist test if we can write to the directory
- $dir = dirname($file);
-
- if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir))
- {
- return true;
- }
- }
-
- return false;
- }
- else
- {
- return is_writable($file);
- }
-}
-
-/**
-* Checks if a path ($path) is absolute or relative
-*
-* @param string $path Path to check absoluteness of
-* @return boolean
-*/
-function phpbb_is_absolute($path)
-{
- return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false;
-}
-
-/**
-* @author Chris Smith <chris@project-minerva.org>
-* @copyright 2006 Project Minerva Team
-* @param string $path The path which we should attempt to resolve.
-* @return mixed
-*/
-function phpbb_own_realpath($path)
-{
- global $request;
-
- // Now to perform funky shizzle
-
- // Switch to use UNIX slashes
- $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
- $path_prefix = '';
-
- // Determine what sort of path we have
- if (phpbb_is_absolute($path))
- {
- $absolute = true;
-
- if ($path[0] == '/')
- {
- // Absolute path, *NIX style
- $path_prefix = '';
- }
- else
- {
- // Absolute path, Windows style
- // Remove the drive letter and colon
- $path_prefix = $path[0] . ':';
- $path = substr($path, 2);
- }
- }
- else
- {
- // Relative Path
- // Prepend the current working directory
- if (function_exists('getcwd'))
- {
- // This is the best method, hopefully it is enabled!
- $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
- $absolute = true;
- if (preg_match('#^[a-z]:#i', $path))
- {
- $path_prefix = $path[0] . ':';
- $path = substr($path, 2);
- }
- else
- {
- $path_prefix = '';
- }
- }
- else if ($request->server('SCRIPT_FILENAME'))
- {
- // Warning: If chdir() has been used this will lie!
- // Warning: This has some problems sometime (CLI can create them easily)
- $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME'));
- $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($filename)) . '/' . $path;
- $absolute = true;
- $path_prefix = '';
- }
- else
- {
- // We have no way of getting the absolute path, just run on using relative ones.
- $absolute = false;
- $path_prefix = '.';
- }
- }
-
- // Remove any repeated slashes
- $path = preg_replace('#/{2,}#', '/', $path);
-
- // Remove the slashes from the start and end of the path
- $path = trim($path, '/');
-
- // Break the string into little bits for us to nibble on
- $bits = explode('/', $path);
-
- // Remove any . in the path, renumber array for the loop below
- $bits = array_values(array_diff($bits, array('.')));
-
- // Lets get looping, run over and resolve any .. (up directory)
- for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
- {
- // @todo Optimise
- if ($bits[$i] == '..' )
- {
- if (isset($bits[$i - 1]))
- {
- if ($bits[$i - 1] != '..')
- {
- // We found a .. and we are able to traverse upwards, lets do it!
- unset($bits[$i]);
- unset($bits[$i - 1]);
- $i -= 2;
- $max -= 2;
- $bits = array_values($bits);
- }
- }
- else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
- {
- // We have an absolute path trying to descend above the root of the filesystem
- // ... Error!
- return false;
- }
- }
- }
-
- // Prepend the path prefix
- array_unshift($bits, $path_prefix);
-
- $resolved = '';
-
- $max = sizeof($bits) - 1;
-
- // Check if we are able to resolve symlinks, Windows cannot.
- $symlink_resolve = (function_exists('readlink')) ? true : false;
-
- foreach ($bits as $i => $bit)
- {
- if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
- {
- // Path Exists
- if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
- {
- // Resolved a symlink.
- $resolved = $link . (($i == $max) ? '' : '/');
- continue;
- }
- }
- else
- {
- // Something doesn't exist here!
- // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
- // return false;
- }
- $resolved .= $bit . (($i == $max) ? '' : '/');
- }
-
- // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
- // because we must be inside that basedir, the question is where...
- // @internal The slash in is_dir() gets around an open_basedir restriction
- if (!@file_exists($resolved) || (!@is_dir($resolved . '/') && !is_file($resolved)))
- {
- return false;
- }
-
- // Put the slashes back to the native operating systems slashes
- $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
-
- // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
- if (substr($resolved, -1) == DIRECTORY_SEPARATOR)
- {
- return substr($resolved, 0, -1);
- }
-
- return $resolved; // We got here, in the end!
-}
-
-if (!function_exists('realpath'))
-{
- /**
- * A wrapper for realpath
- * @ignore
- */
- function phpbb_realpath($path)
- {
- return phpbb_own_realpath($path);
- }
-}
-else
-{
- /**
- * A wrapper for realpath
- */
- function phpbb_realpath($path)
- {
- $realpath = realpath($path);
-
- // Strangely there are provider not disabling realpath but returning strange values. :o
- // We at least try to cope with them.
- if ($realpath === $path || $realpath === false)
- {
- return phpbb_own_realpath($path);
- }
-
- // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
- if (substr($realpath, -1) == DIRECTORY_SEPARATOR)
- {
- $realpath = substr($realpath, 0, -1);
- }
-
- return $realpath;
- }
-}
-
// functions used for building option fields
/**
@@ -1192,11 +605,11 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
if ($forum_id === false || !sizeof($forum_id))
{
// Mark all forums read (index page)
-
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
// Mark all topic notifications read for this user
- $phpbb_notifications->mark_notifications_read(array(
+ $phpbb_notifications->mark_notifications(array(
'notification.type.topic',
'notification.type.quote',
'notification.type.bookmark',
@@ -1263,9 +676,10 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$forum_id = array_unique($forum_id);
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
- $phpbb_notifications->mark_notifications_read_by_parent(array(
+ $phpbb_notifications->mark_notifications_by_parent(array(
'notification.type.topic',
'notification.type.approve_topic',
), $forum_id, $user->data['user_id'], $post_time);
@@ -1282,7 +696,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
}
$db->sql_freeresult($result);
- $phpbb_notifications->mark_notifications_read_by_parent(array(
+ $phpbb_notifications->mark_notifications_by_parent(array(
'notification.type.quote',
'notification.type.bookmark',
'notification.type.post',
@@ -1385,15 +799,16 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
return;
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
// Mark post notifications read for this user in this topic
- $phpbb_notifications->mark_notifications_read(array(
+ $phpbb_notifications->mark_notifications(array(
'notification.type.topic',
'notification.type.approve_topic',
), $topic_id, $user->data['user_id'], $post_time);
- $phpbb_notifications->mark_notifications_read_by_parent(array(
+ $phpbb_notifications->mark_notifications_by_parent(array(
'notification.type.quote',
'notification.type.bookmark',
'notification.type.post',
@@ -1438,7 +853,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
$tracking['tf'][$forum_id][$topic_id36] = true;
}
- $tracking['t'][$topic_id36] = base_convert($post_time - $config['board_startdate'], 10, 36);
+ $tracking['t'][$topic_id36] = base_convert($post_time - (int) $config['board_startdate'], 10, 36);
// If the cookie grows larger than 10000 characters we will remove the smallest value
// This can result in old topics being unread - but most of the time it should be accurate...
@@ -1525,7 +940,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
*/
function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false)
{
- global $config, $user;
+ global $user;
$last_read = array();
@@ -1684,7 +1099,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
*/
function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001, $sql_limit_offset = 0)
{
- global $config, $db, $user;
+ global $config, $db, $user, $request;
global $phpbb_dispatcher;
$user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id;
@@ -1763,7 +1178,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s
if (empty($tracking_topics))
{
- $tracking_topics = request_var($config['cookie_name'] . '_track', '', false, true);
+ $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', false, \phpbb\request\request_interface::COOKIE);
$tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
}
@@ -1830,7 +1245,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s
*/
function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false)
{
- global $db, $tracking_topics, $user, $config, $auth, $request, $phpbb_container;
+ global $db, $tracking_topics, $user, $config, $request, $phpbb_container;
// Determine the users last forum mark time if not given.
if ($mark_time_forum === false)
@@ -1855,6 +1270,7 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
// Handle update of unapproved topics info.
// Only update for moderators having m_approve permission for the forum.
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
// Check the forum for any left unread topics.
@@ -1887,8 +1303,6 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
else if ($config['load_anon_lastread'] || $user->data['is_registered'])
{
// Get information from cookie
- $row = false;
-
if (!isset($tracking_topics['tf'][$forum_id]))
{
// We do not need to mark read, this happened before. Therefore setting this to true
@@ -2294,11 +1708,9 @@ function generate_board_url($without_script_path = false)
*/
function redirect($url, $return = false, $disable_cd_check = false)
{
- global $db, $cache, $config, $user, $phpbb_root_path, $phpbb_filesystem, $phpbb_path_helper, $phpEx, $phpbb_dispatcher;
-
- $failover_flag = false;
+ global $user, $phpbb_path_helper, $phpbb_dispatcher;
- if (empty($user->lang))
+ if (!$user->is_setup())
{
$user->add_lang('common');
}
@@ -2311,8 +1723,8 @@ function redirect($url, $return = false, $disable_cd_check = false)
if ($url_parts === false)
{
- // Malformed url, redirect to current page...
- $url = generate_board_url() . '/' . $user->page['page'];
+ // Malformed url
+ trigger_error('INSECURE_REDIRECT', E_USER_ERROR);
}
else if (!empty($url_parts['scheme']) && !empty($url_parts['host']))
{
@@ -2720,9 +2132,9 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
if ($check && $confirm)
{
- $user_id = request_var('confirm_uid', 0);
- $session_id = request_var('sess', '');
- $confirm_key = request_var('confirm_key', '');
+ $user_id = $request->variable('confirm_uid', 0);
+ $session_id = $request->variable('sess', '');
+ $confirm_key = $request->variable('confirm_key', '');
if ($user_id != $user->data['user_id'] || $session_id != $user->session_id || !$confirm_key || !$user->data['user_last_confirm_key'] || $confirm_key != $user->data['user_last_confirm_key'])
{
@@ -2764,7 +2176,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
);
// If activation key already exist, we better do not re-use the key (something very strange is going on...)
- if (request_var('confirm_key', ''))
+ if ($request->variable('confirm_key', ''))
{
// This should not occur, therefore we cancel the operation to safe the user
return false;
@@ -2819,13 +2231,13 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
*/
function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true)
{
- global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
- global $request, $phpbb_container, $phpbb_dispatcher;
+ global $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
+ global $request, $phpbb_container, $phpbb_dispatcher, $phpbb_log;
$err = '';
// Make sure user->setup() has been called
- if (empty($user->lang))
+ if (!$user->is_setup())
{
$user->setup();
}
@@ -2852,8 +2264,9 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
// anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions
if ($user->data['is_registered'])
{
- add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL');
}
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_ADMIN');
}
@@ -2862,14 +2275,15 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
// Get credential
if ($admin)
{
- $credential = request_var('credential', '');
+ $credential = $request->variable('credential', '');
if (strspn($credential, 'abcdef0123456789') !== strlen($credential) || strlen($credential) != 32)
{
if ($user->data['is_registered'])
{
- add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL');
}
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_ADMIN');
}
@@ -2880,7 +2294,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
$password = $request->untrimmed_variable('password', '', true);
}
- $username = request_var('username', '', true);
+ $username = $request->variable('username', '', true);
$autologin = $request->is_set_post('autologin');
$viewonline = (int) !$request->is_set_post('viewonline');
$admin = ($admin) ? 1 : 0;
@@ -2890,7 +2304,9 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
if ($admin && utf8_clean_string($username) != utf8_clean_string($user->data['username']))
{
// We log the attempt to use a different username...
- add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL');
+
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_ADMIN_USER_DIFFER');
}
@@ -2903,7 +2319,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{
if ($result['status'] == LOGIN_SUCCESS)
{
- add_log('admin', 'LOG_ADMIN_AUTH_SUCCESS');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_SUCCESS');
}
else
{
@@ -2911,7 +2327,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
// anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions
if ($user->data['is_registered'])
{
- add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL');
}
}
}
@@ -2919,7 +2335,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
// The result parameter is always an array, holding the relevant information...
if ($result['status'] == LOGIN_SUCCESS)
{
- $redirect = request_var('redirect', "{$phpbb_root_path}index.$phpEx");
+ $redirect = $request->variable('redirect', "{$phpbb_root_path}index.$phpEx");
/**
* This event allows an extension to modify the redirection when a user successfully logs in
@@ -3019,6 +2435,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
$s_hidden_fields['credential'] = $credential;
}
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$auth_provider = $provider_collection->get_provider();
@@ -3122,6 +2539,7 @@ function login_forum_box($forum_data)
}
$db->sql_freeresult($result);
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
if ($passwords_manager->check($password, $forum_data['forum_password']))
@@ -3278,52 +2696,6 @@ function parse_cfg_file($filename, $lines = false)
}
/**
-* Add log entry
-*
-* @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
-* @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise
-* @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise
-* @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise
-* @param string $log_operation Name of the operation
-* @param array $additional_data More arguments can be added, depending on the log_type
-*
-* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise.
-*
-* @deprecated Use $phpbb_log->add() instead
-*/
-function add_log()
-{
- global $phpbb_log, $user;
-
- $args = func_get_args();
- $mode = array_shift($args);
-
- // This looks kind of dirty, but add_log has some additional data before the log_operation
- $additional_data = array();
- switch ($mode)
- {
- case 'admin':
- case 'critical':
- break;
- case 'mod':
- $additional_data['forum_id'] = array_shift($args);
- $additional_data['topic_id'] = array_shift($args);
- break;
- case 'user':
- $additional_data['reportee_id'] = array_shift($args);
- break;
- }
-
- $log_operation = array_shift($args);
- $additional_data = array_merge($additional_data, $args);
-
- $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id'];
- $user_ip = (empty($user->ip)) ? '' : $user->ip;
-
- return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data);
-}
-
-/**
* Return a nicely formatted backtrace.
*
* Turns the array returned by debug_backtrace() into HTML markup.
@@ -3386,6 +2758,7 @@ function get_preg_expression($mode)
return array(
'#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
'#<!\-\- l \-\-><a (?:class="[\w-]+" )?href="(.*?)(?:(&amp;|\?)sid=[0-9a-f]{32})?">.*?</a><!\-\- l \-\->#',
+ '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="http://(.*?)">\2</a><!\-\- \1 \-\->#',
'#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->#',
'#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
'#<!\-\- .*? \-\->#s',
@@ -3452,31 +2825,19 @@ function get_preg_expression($mode)
* Depends on whether installed PHP version supports unicode properties
*
* @param string $word word template to be replaced
-* @param bool $use_unicode whether or not to take advantage of PCRE supporting unicode
*
* @return string $preg_expr regex to use with word censor
*/
-function get_censor_preg_expression($word, $use_unicode = true)
+function get_censor_preg_expression($word)
{
// Unescape the asterisk to simplify further conversions
$word = str_replace('\*', '*', preg_quote($word, '#'));
- if ($use_unicode && phpbb_pcre_utf8_support())
- {
- // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes
- $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word);
-
- // Generate the final substitution
- $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu';
- }
- else
- {
- // Replace the asterisk inside the pattern, at the start and at the end of it with regexes
- $word = preg_replace(array('#(?<=\S)\*+(?=\S)#iu', '#^\*+#', '#\*+$#'), array('(\x20*?\S*?)', '\S*?', '\S*?'), $word);
+ // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes
+ $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word);
- // Generate the final substitution
- $preg_expr = '#(?<!\S)(' . $word . ')(?!\S)#iu';
- }
+ // Generate the final substitution
+ $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu';
return $preg_expr;
}
@@ -3724,38 +3085,12 @@ function phpbb_checkdnsrr($host, $type = 'MX')
return (@gethostbyname($host_fqdn) == $host_fqdn) ? false : true;
}
- // checkdnsrr() is available on Windows since PHP 5.3,
- // but until 5.3.3 it only works for MX records
- // See: http://bugs.php.net/bug.php?id=51844
-
- // Call checkdnsrr() if
- // we're looking for an MX record or
- // we're not on Windows or
- // we're running a PHP version where #51844 has been fixed
-
- // checkdnsrr() supports AAAA since 5.0.0
- // checkdnsrr() supports TXT since 5.2.4
- if (
- ($type == 'MX' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.3', '>=')) &&
- ($type != 'AAAA' || version_compare(PHP_VERSION, '5.0.0', '>=')) &&
- ($type != 'TXT' || version_compare(PHP_VERSION, '5.2.4', '>=')) &&
- function_exists('checkdnsrr')
- )
+ if (function_exists('checkdnsrr'))
{
return checkdnsrr($host_fqdn, $type);
}
- // dns_get_record() is available since PHP 5; since PHP 5.3 also on Windows,
- // but on Windows it does not work reliable for AAAA records before PHP 5.3.1
-
- // Call dns_get_record() if
- // we're not looking for an AAAA record or
- // we're not on Windows or
- // we're running a PHP version where AAAA lookups work reliable
- if (
- ($type != 'AAAA' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.1', '>=')) &&
- function_exists('dns_get_record')
- )
+ if (function_exists('dns_get_record'))
{
// dns_get_record() expects an integer as second parameter
// We have to convert the string $type to the corresponding integer constant.
@@ -3888,7 +3223,7 @@ function phpbb_checkdnsrr($host, $type = 'MX')
function msg_handler($errno, $msg_text, $errfile, $errline)
{
global $cache, $db, $auth, $template, $config, $user, $request;
- global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
+ global $phpbb_root_path, $msg_title, $msg_long_text, $phpbb_log;
// Do not display notices if we suppress them via @
if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE)
@@ -3902,11 +3237,6 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
$msg_text = $msg_long_text;
}
- if (!defined('E_DEPRECATED'))
- {
- define('E_DEPRECATED', 8192);
- }
-
switch ($errno)
{
case E_NOTICE:
@@ -3929,7 +3259,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
// we are writing an image - the user won't see the debug, so let's place it in the log
if (defined('IMAGE_OUTPUT') || defined('IN_CRON'))
{
- add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text);
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_IMAGE_GENERATION_ERROR', false, array($errfile, $errline, $msg_text));
}
// echo '<br /><br />BACKTRACE<br />' . get_backtrace() . '<br />' . "\n";
}
@@ -3940,7 +3270,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
case E_USER_ERROR:
- if (!empty($user) && !empty($user->lang))
+ if (!empty($user) && $user->is_setup())
{
$msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text;
$msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title);
@@ -3991,7 +3321,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
{
// let's avoid loops
$db->sql_return_on_error(true);
- add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $log_text);
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_GENERAL_ERROR', false, array($msg_title, $log_text));
$db->sql_return_on_error(false);
}
@@ -4061,7 +3391,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
// We re-init the auth array to get correct results on login/logout
$auth->acl($user->data);
- if (empty($user->lang))
+ if (!$user->is_setup())
{
$user->setup();
}
@@ -4150,11 +3480,21 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
*/
function phpbb_filter_root_path($errfile)
{
+ global $phpbb_filesystem;
+
static $root_path;
if (empty($root_path))
{
- $root_path = phpbb_realpath(dirname(__FILE__) . '/../');
+ if ($phpbb_filesystem)
+ {
+ $root_path = $phpbb_filesystem->realpath(dirname(__FILE__) . '/../');
+ }
+ else
+ {
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $root_path = $filesystem->realpath(dirname(__FILE__) . '/../');
+ }
}
return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile);
@@ -4182,7 +3522,7 @@ function obtain_guest_count($item_id = 0, $item = 'forum')
// Get number of online guests
- if ($db->get_sql_layer() === 'sqlite' || $db->get_sql_layer() === 'sqlite3')
+ if ($db->get_sql_layer() === 'sqlite3')
{
$sql = 'SELECT COUNT(session_ip) as num_guests
FROM (
@@ -4216,7 +3556,7 @@ function obtain_guest_count($item_id = 0, $item = 'forum')
*/
function obtain_users_online($item_id = 0, $item = 'forum')
{
- global $db, $config, $user;
+ global $db, $config;
$reading_sql = '';
if ($item_id !== 0)
@@ -4282,7 +3622,6 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum'
{
global $config, $db, $user, $auth, $phpbb_dispatcher;
- $guests_online = $hidden_online = $l_online_users = $online_userlist = $visible_online = '';
$user_online_link = $rowset = array();
// Need caps version of $item for language-strings
$item_caps = strtoupper($item);
@@ -4462,178 +3801,6 @@ function phpbb_optionset($bit, $set, $data)
}
/**
-* Determine which plural form we should use.
-* For some languages this is not as simple as for English.
-*
-* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules
-* @param $number int|float The number we want to get the plural case for. Float numbers are floored.
-* @return int The plural-case we need to use for the number plural-rule combination
-*/
-function phpbb_get_plural_form($rule, $number)
-{
- $number = (int) $number;
-
- if ($rule > 15 || $rule < 0)
- {
- trigger_error('INVALID_PLURAL_RULE');
- }
-
- /**
- * The following plural rules are based on a list published by the Mozilla Developer Network
- * https://developer.mozilla.org/en/Localization_and_Plurals
- */
- switch ($rule)
- {
- case 0:
- /**
- * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao
- * 1 - everything: 0, 1, 2, ...
- */
- return 1;
-
- case 1:
- /**
- * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan)
- * 1 - 1
- * 2 - everything else: 0, 2, 3, ...
- */
- return ($number == 1) ? 1 : 2;
-
- case 2:
- /**
- * Families: Romanic (French, Brazilian Portuguese)
- * 1 - 0, 1
- * 2 - everything else: 2, 3, ...
- */
- return (($number == 0) || ($number == 1)) ? 1 : 2;
-
- case 3:
- /**
- * Families: Baltic (Latvian)
- * 1 - 0
- * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ...
- * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ...
- */
- return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3);
-
- case 4:
- /**
- * Families: Celtic (Scottish Gaelic)
- * 1 - is 1 or 11: 1, 11
- * 2 - is 2 or 12: 2, 12
- * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19
- * 4 - everything else: 0, 20, 21, ...
- */
- return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4));
-
- case 5:
- /**
- * Families: Romanic (Romanian)
- * 1 - 1
- * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ...
- * 3 - everything else: 20, 21, ...
- */
- return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3);
-
- case 6:
- /**
- * Families: Baltic (Lithuanian)
- * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ...
- * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ...
- * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ...
- */
- return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3);
-
- case 7:
- /**
- * Families: Slavic (Croatian, Serbian, Russian, Ukrainian)
- * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ...
- * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ...
- * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ...
- */
- return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3);
-
- case 8:
- /**
- * Families: Slavic (Slovak, Czech)
- * 1 - 1
- * 2 - 2, 3, 4
- * 3 - everything else: 0, 5, 6, 7, ...
- */
- return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3);
-
- case 9:
- /**
- * Families: Slavic (Polish)
- * 1 - 1
- * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ...
- * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ...
- */
- return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3);
-
- case 10:
- /**
- * Families: Slavic (Slovenian, Sorbian)
- * 1 - ends in 01: 1, 101, 201, ...
- * 2 - ends in 02: 2, 102, 202, ...
- * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ...
- * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ...
- */
- return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4));
-
- case 11:
- /**
- * Families: Celtic (Irish Gaeilge)
- * 1 - 1
- * 2 - 2
- * 3 - is 3-6: 3, 4, 5, 6
- * 4 - is 7-10: 7, 8, 9, 10
- * 5 - everything else: 0, 11, 12, ...
- */
- return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5)));
-
- case 12:
- /**
- * Families: Semitic (Arabic)
- * 1 - 1
- * 2 - 2
- * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ...
- * 4 - ends in 11-99: 11, ... 99, 111, 112, ...
- * 5 - everything else: 100, 101, 102, 200, 201, 202, ...
- * 6 - 0
- */
- return ($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6))));
-
- case 13:
- /**
- * Families: Semitic (Maltese)
- * 1 - 1
- * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ...
- * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ...
- * 4 - everything else: 20, 21, ...
- */
- return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4));
-
- case 14:
- /**
- * Families: Slavic (Macedonian)
- * 1 - ends in 1: 1, 11, 21, ...
- * 2 - ends in 2: 2, 12, 22, ...
- * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ...
- */
- return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3);
-
- case 15:
- /**
- * Families: Icelandic
- * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ...
- * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ...
- */
- return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2;
- }
-}
-
-/**
* Login using http authenticate.
*
* @param array $param Parameter array, see $param_defaults array.
@@ -4875,8 +4042,7 @@ function phpbb_get_group_avatar($user_row, $alt = 'GROUP_AVATAR', $ignore_config
*/
function phpbb_get_avatar($row, $alt, $ignore_config = false, $lazy = false)
{
- global $user, $config, $cache, $phpbb_root_path, $phpEx;
- global $request;
+ global $user, $config;
global $phpbb_container, $phpbb_dispatcher;
if (!$config['allow_avatar'] && !$ignore_config)
@@ -4890,6 +4056,7 @@ function phpbb_get_avatar($row, $alt, $ignore_config = false, $lazy = false)
'height' => $row['avatar_height'],
);
+ /* @var $phpbb_avatar_manager \phpbb\avatar\manager */
$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
$driver = $phpbb_avatar_manager->get_driver($row['avatar_type'], !$ignore_config);
$html = '';
@@ -5055,8 +4222,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
if ($total_online_users > $config['record_online_users'])
{
- set_config('record_online_users', $total_online_users, true);
- set_config('record_online_date', time(), true);
+ $config->set('record_online_users', $total_online_users, false);
+ $config->set('record_online_date', time(), false);
}
$l_online_record = $user->lang('RECORD_ONLINE_USERS', (int) $config['record_online_users'], $user->format_date($config['record_online_date'], false, true));
@@ -5091,8 +4258,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
}
}
- $forum_id = request_var('f', 0);
- $topic_id = request_var('t', 0);
+ $forum_id = $request->variable('f', 0);
+ $topic_id = $request->variable('t', 0);
$s_feed_news = false;
@@ -5112,6 +4279,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
// This path is sent with the base template paths in the assign_vars()
// call below. We need to correct it in case we are accessing from a
// controller because the web paths will be incorrect otherwise.
+ /* @var $phpbb_path_helper \phpbb\path_helper */
$phpbb_path_helper = $phpbb_container->get('path_helper');
$corrected_path = $phpbb_path_helper->get_web_root_path();
$web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $corrected_path;
@@ -5148,11 +4316,12 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
// Output the notifications
$notifications = false;
- if ($config['load_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE)
+ if ($config['load_notifications'] && $config['allow_board_notifications'] && $user->data['user_id'] != ANONYMOUS && $user->data['user_type'] != USER_IGNORE)
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
- $notifications = $phpbb_notifications->load_notifications(array(
+ $notifications = $phpbb_notifications->load_notifications('notification.method.board', array(
'all_unread' => true,
'limit' => 5,
));
@@ -5163,6 +4332,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
}
}
+ /** @var \phpbb\controller\helper $controller_helper */
+ $controller_helper = $phpbb_container->get('controller.helper');
$notification_mark_hash = generate_link_hash('mark_all_notifications_read');
// The following assigns all _common_ variables that may be used at any point in a template.
@@ -5187,7 +4358,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
'U_VIEW_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications'),
'U_MARK_ALL_NOTIFICATIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&amp;mode=notification_list&amp;mark=all&amp;token=' . $notification_mark_hash),
'U_NOTIFICATION_SETTINGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_notifications&amp;mode=notification_options'),
- 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'],
+ 'S_NOTIFICATIONS_DISPLAY' => $config['load_notifications'] && $config['allow_board_notifications'],
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
@@ -5216,7 +4387,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"),
'U_USER_PROFILE' => get_username_string('profile', $user->data['user_id'], $user->data['username'], $user->data['user_colour']),
'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id),
- 'U_FAQ' => append_sid("{$phpbb_root_path}faq.$phpEx"),
+ 'U_FAQ' => $controller_helper->route('phpbb_help_faq_controller'),
'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'),
'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'),
'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'),
@@ -5228,7 +4399,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
'U_PRIVACY' => 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' => generate_board_url() . "/feed.$phpEx",
+ 'U_FEED' => $controller_helper->route('phpbb_feed_index'),
'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false,
'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false,
@@ -5279,7 +4450,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/",
'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/stylesheet.css?assets_version=' . $config['assets_version'],
- 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'],
+ 'T_STYLESHEET_LANG_LINK'=> "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'],
+ 'T_FONT_AWESOME_LINK' => !empty($config['allow_cdn']) && !empty($config['load_font_awesome_url']) ? $config['load_font_awesome_url'] : "{$web_path}assets/css/font-awesome.min.css?assets_version=" . $config['assets_version'],
'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.min.js?assets_version=" . $config['assets_version'],
'S_ALLOW_CDN' => !empty($config['allow_cdn']),
@@ -5376,10 +4548,10 @@ function phpbb_generate_debug_output(\phpbb\db\driver\driver_interface $db, \php
if (isset($GLOBALS['starttime']))
{
$totaltime = microtime(true) - $GLOBALS['starttime'];
- $debug_info[] = sprintf('<abbr title="SQL time: %.3fs / PHP time: %.3fs">Time: %.3fs</abbr>', $db->get_sql_time(), ($totaltime - $db->get_sql_time()), $totaltime);
+ $debug_info[] = sprintf('<span title="SQL time: %.3fs / PHP time: %.3fs">Time: %.3fs</span>', $db->get_sql_time(), ($totaltime - $db->get_sql_time()), $totaltime);
}
- $debug_info[] = sprintf('<abbr title="Cached: %d">Queries: %d</abbr>', $db->sql_num_queries(true), $db->sql_num_queries());
+ $debug_info[] = sprintf('<span title="Cached: %d">Queries: %d</span>', $db->sql_num_queries(true), $db->sql_num_queries());
$memory_usage = memory_get_peak_usage();
if ($memory_usage)
@@ -5428,7 +4600,7 @@ function phpbb_generate_debug_output(\phpbb\db\driver\driver_interface $db, \php
*/
function page_footer($run_cron = true, $display_template = true, $exit_handler = true)
{
- global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx;
+ global $db, $config, $template, $user, $auth, $cache, $phpEx;
global $request, $phpbb_dispatcher, $phpbb_admin_path;
// A listener can set this variable to `true` when it overrides this function
@@ -5485,6 +4657,8 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler =
if ($call_cron)
{
global $phpbb_container;
+
+ /* @var $cron \phpbb\cron\manager */
$cron = $phpbb_container->get('cron.manager');
$task = $cron->find_one_ready_task();
@@ -5565,7 +4739,7 @@ function garbage_collection()
*/
function exit_handler()
{
- global $phpbb_hook, $config;
+ global $phpbb_hook;
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
{
@@ -5601,22 +4775,6 @@ function phpbb_user_session_handler()
}
/**
-* Check if PCRE has UTF-8 support
-* PHP may not be linked with the bundled PCRE lib and instead with an older version
-*
-* @return bool Returns true if PCRE (the regular expressions library) supports UTF-8 encoding
-*/
-function phpbb_pcre_utf8_support()
-{
- static $utf8_pcre_properties = null;
- if (is_null($utf8_pcre_properties))
- {
- $utf8_pcre_properties = (@preg_match('/\p{L}/u', 'a') !== false);
- }
- return $utf8_pcre_properties;
-}
-
-/**
* Casts a numeric string $input to an appropriate numeric type (i.e. integer or float)
*
* @param string $input A numeric string.
diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php
index c4afb39ff0..766669480d 100644
--- a/phpBB/includes/functions_acp.php
+++ b/phpBB/includes/functions_acp.php
@@ -24,9 +24,9 @@ if (!defined('IN_PHPBB'))
*/
function adm_page_header($page_title)
{
- global $config, $db, $user, $template;
+ global $config, $user, $template;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $SID, $_SID;
- global $phpbb_dispatcher;
+ global $phpbb_dispatcher, $phpbb_container;
if (defined('HEADER_INC'))
{
@@ -107,6 +107,8 @@ function adm_page_header($page_title)
'S_CONTENT_ENCODING' => 'UTF-8',
'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
+
+ '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.
@@ -142,8 +144,8 @@ function adm_page_header($page_title)
*/
function adm_page_footer($copyright_html = true)
{
- global $db, $config, $template, $user, $auth, $cache;
- global $starttime, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $db, $config, $template, $user, $auth;
+ global $phpbb_root_path;
global $request, $phpbb_dispatcher;
// A listener can set this variable to `true` when it overrides this function
@@ -232,7 +234,7 @@ function h_radio($name, $input_ary, $input_default = false, $id = false, $key =
/**
* Build configuration template for acp configuration pages
*/
-function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
+function build_cfg_template($tpl_type, $key, &$new_ary, $config_key, $vars)
{
global $user, $module, $phpbb_dispatcher;
@@ -240,18 +242,18 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$name = 'config[' . $config_key . ']';
// Make sure there is no notice printed out for non-existent config options (we simply set them)
- if (!isset($new[$config_key]))
+ if (!isset($new_ary[$config_key]))
{
- $new[$config_key] = '';
+ $new_ary[$config_key] = '';
}
switch ($tpl_type[0])
{
case 'password':
- if ($new[$config_key] !== '')
+ if ($new_ary[$config_key] !== '')
{
// replace passwords with asterixes
- $new[$config_key] = '********';
+ $new_ary[$config_key] = '********';
}
case 'text':
case 'url':
@@ -263,7 +265,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$size = (int) $tpl_type[1];
$maxlength = (int) $tpl_type[2];
- $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />';
+ $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new_ary[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />';
break;
case 'color':
@@ -271,7 +273,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
case 'datetime-local':
case 'month':
case 'week':
- $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '" name="' . $name . '" value="' . $new[$config_key] . '" />';
+ $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '" name="' . $name . '" value="' . $new_ary[$config_key] . '" />';
break;
case 'date':
@@ -285,7 +287,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$max = (int) $tpl_type[2];
}
- $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new[$config_key] . '" />';
+ $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new_ary[$config_key] . '" />';
break;
case 'dimension':
@@ -298,19 +300,19 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$max = (int) $tpl_type[2];
}
- $tpl = '<input id="' . $key . '" type="number"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new[$config_key . '_width'] . '" /> x <input type="number"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new[$config_key . '_height'] . '" />';
+ $tpl = '<input id="' . $key . '" type="number"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new_ary[$config_key . '_width'] . '" /> x <input type="number"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new_ary[$config_key . '_height'] . '" />';
break;
case 'textarea':
$rows = (int) $tpl_type[1];
$cols = (int) $tpl_type[2];
- $tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new[$config_key] . '</textarea>';
+ $tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new_ary[$config_key] . '</textarea>';
break;
case 'radio':
- $key_yes = ($new[$config_key]) ? ' checked="checked"' : '';
- $key_no = (!$new[$config_key]) ? ' checked="checked"' : '';
+ $key_yes = ($new_ary[$config_key]) ? ' checked="checked"' : '';
+ $key_no = (!$new_ary[$config_key]) ? ' checked="checked"' : '';
$tpl_type_cond = explode('_', $tpl_type[1]);
$type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true;
@@ -324,8 +326,6 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
case 'select':
case 'custom':
- $return = '';
-
if (isset($vars['method']))
{
$call = array($module->module, $vars['method']);
@@ -347,7 +347,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
switch ($value)
{
case '{CONFIG_VALUE}':
- $value = $new[$config_key];
+ $value = $new_ary[$config_key];
break;
case '{KEY}':
@@ -360,7 +360,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
}
else
{
- $args = array($new[$config_key], $key);
+ $args = array($new_ary[$config_key], $key);
}
$return = call_user_func_array($call, $args);
@@ -388,6 +388,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$tpl .= $vars['append'];
}
+ $new = $new_ary;
/**
* Overwrite the html code we display for the config value
*
@@ -405,6 +406,8 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
*/
$vars = array('tpl_type', 'key', 'new', 'name', 'vars', 'tpl');
extract($phpbb_dispatcher->trigger_event('core.build_config_template', compact($vars)));
+ $new_ary = $new;
+ unset($new);
return $tpl;
}
@@ -415,7 +418,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
*/
function validate_config_vars($config_vars, &$cfg_array, &$error)
{
- global $phpbb_root_path, $user, $phpbb_dispatcher;
+ global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem;
$type = 0;
$min = 1;
@@ -596,7 +599,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 (file_exists($path) && !phpbb_is_writable($path))
+ if (file_exists($path) && !$phpbb_filesystem->is_writable($path))
{
$error[] = sprintf($user->lang['DIRECTORY_NOT_WRITABLE'], $cfg_array[$config_name]);
}
@@ -652,8 +655,6 @@ function validate_range($value_ary, &$error)
foreach ($value_ary as $value)
{
$column = explode(':', $value['column_type']);
- $max = $min = 0;
- $type = 0;
if (!isset($column_types[$column[0]]))
{
continue;
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 1dc246ec33..c1a99da231 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -65,7 +65,7 @@ function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = ar
*/
function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false)
{
- global $db, $user, $auth, $phpbb_dispatcher;
+ global $db, $auth, $phpbb_dispatcher;
// This query is identical to the jumpbox one
$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id
@@ -187,7 +187,10 @@ function size_select_options($size_compare)
*/
function group_select_options($group_id, $exclude_ids = false, $manage_founder = false)
{
- global $db, $user, $config;
+ global $db, $config, $phpbb_container;
+
+ /** @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) : '';
$sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : '';
@@ -205,7 +208,7 @@ function group_select_options($group_id, $exclude_ids = false, $manage_founder =
while ($row = $db->sql_fetchrow($result))
{
$selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : '';
- $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . $group_helper->get_name($row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
@@ -342,7 +345,7 @@ function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $incl
*/
function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true)
{
- global $db;
+ global $db, $user, $phpbb_log;
// Only one forum id specified
if (!is_array($dest_forum_ids))
@@ -465,7 +468,7 @@ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perm
if ($add_log)
{
- add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_COPIED_PERMISSIONS', false, array($src_forum_name, implode(', ', $dest_forum_names)));
}
$db->sql_transaction('commit');
@@ -829,9 +832,10 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s
if ($approved_topics)
{
- set_config_count('num_topics', $approved_topics * (-1), true);
+ $config->increment('num_topics', $approved_topics * (-1), false);
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications(array(
@@ -1047,7 +1051,10 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
$search->index_remove($post_ids, $poster_ids, $forum_ids);
- delete_attachments('post', $post_ids, false);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('post', $post_ids, false);
+ unset($attachment_manager);
/**
* Perform additional actions during post(s) deletion
@@ -1114,7 +1121,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
if ($approved_posts && $post_count_sync)
{
- set_config_count('num_posts', $approved_posts * (-1), true);
+ $config->increment('num_posts', $approved_posts * (-1), false);
}
// We actually remove topics now to not be inconsistent (the delete_topics function calls this function too)
@@ -1123,6 +1130,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false);
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications($delete_notifications_types, $post_ids);
@@ -1133,329 +1141,21 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
/**
* Delete Attachments
*
+* @deprecated 3.2.0-a1 (To be removed: 3.4.0)
+*
* @param string $mode can be: post|message|topic|attach|user
* @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
* @param bool $resync set this to false if you are deleting posts or topics
*/
function delete_attachments($mode, $ids, $resync = true)
{
- global $db, $config, $phpbb_dispatcher;
-
- // 0 is as bad as an empty array
- if (empty($ids))
- {
- return false;
- }
-
- if (is_array($ids))
- {
- $ids = array_unique($ids);
- $ids = array_map('intval', $ids);
- }
- else
- {
- $ids = array((int) $ids);
- }
-
- $sql_where = '';
-
- switch ($mode)
- {
- case 'post':
- case 'message':
- $sql_id = 'post_msg_id';
- $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0);
- break;
-
- case 'topic':
- $sql_id = 'topic_id';
- break;
-
- case 'user':
- $sql_id = 'poster_id';
- break;
-
- case 'attach':
- default:
- $sql_id = 'attach_id';
- $mode = 'attach';
- break;
- }
-
- $post_ids = $message_ids = $topic_ids = $physical = array();
-
- /**
- * Perform additional actions before collecting data for attachment(s) deletion
- *
- * @event core.delete_attachments_collect_data_before
- * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
- * @var mixed ids Array or comma separated list of ids corresponding to the mode
- * @var bool resync Flag indicating if posts/messages/topics should be synchronized
- * @var string sql_id The field name to collect/delete data for depending on the mode
- * @since 3.1.7-RC1
- */
- $vars = array(
- 'mode',
- 'ids',
- 'resync',
- 'sql_id',
- );
- extract($phpbb_dispatcher->trigger_event('core.delete_attachments_collect_data_before', compact($vars)));
-
- // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
- $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
- FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set($sql_id, $ids);
-
- $sql .= $sql_where;
-
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
- if ($resync && !$row['is_orphan'])
- {
- if (!$row['in_message'])
- {
- $post_ids[] = $row['post_msg_id'];
- $topic_ids[] = $row['topic_id'];
- }
- else
- {
- $message_ids[] = $row['post_msg_id'];
- }
- }
-
- $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
- }
- $db->sql_freeresult($result);
-
- /**
- * Perform additional actions before attachment(s) deletion
- *
- * @event core.delete_attachments_before
- * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
- * @var mixed ids Array or comma separated list of ids corresponding to the mode
- * @var bool resync Flag indicating if posts/messages/topics should be synchronized
- * @var string sql_id The field name to collect/delete data for depending on the mode
- * @var array post_ids Array with post ids for deleted attachment(s)
- * @var array topic_ids Array with topic ids for deleted attachment(s)
- * @var array message_ids Array with private message ids for deleted attachment(s)
- * @var array physical Array with deleted attachment(s) physical file(s) data
- * @since 3.1.7-RC1
- */
- $vars = array(
- 'mode',
- 'ids',
- 'resync',
- 'sql_id',
- 'post_ids',
- 'topic_ids',
- 'message_ids',
- 'physical',
- );
- extract($phpbb_dispatcher->trigger_event('core.delete_attachments_before', compact($vars)));
-
- // Delete attachments
- $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set($sql_id, $ids);
-
- $sql .= $sql_where;
-
- $db->sql_query($sql);
- $num_deleted = $db->sql_affectedrows();
-
- /**
- * Perform additional actions after attachment(s) deletion from the database
- *
- * @event core.delete_attachments_from_database_after
- * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
- * @var mixed ids Array or comma separated list of ids corresponding to the mode
- * @var bool resync Flag indicating if posts/messages/topics should be synchronized
- * @var string sql_id The field name to collect/delete data for depending on the mode
- * @var array post_ids Array with post ids for deleted attachment(s)
- * @var array topic_ids Array with topic ids for deleted attachment(s)
- * @var array message_ids Array with private message ids for deleted attachment(s)
- * @var array physical Array with deleted attachment(s) physical file(s) data
- * @var int num_deleted The number of deleted attachment(s) from the database
- * @since 3.1.7-RC1
- */
- $vars = array(
- 'mode',
- 'ids',
- 'resync',
- 'sql_id',
- 'post_ids',
- 'topic_ids',
- 'message_ids',
- 'physical',
- 'num_deleted',
- );
- extract($phpbb_dispatcher->trigger_event('core.delete_attachments_from_database_after', compact($vars)));
-
- if (!$num_deleted)
- {
- return 0;
- }
-
- // Delete attachments from filesystem
- $space_removed = $files_removed = 0;
- foreach ($physical as $file_ary)
- {
- if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan'])
- {
- // Only non-orphaned files count to the file size
- $space_removed += $file_ary['filesize'];
- $files_removed++;
- }
-
- if ($file_ary['thumbnail'])
- {
- phpbb_unlink($file_ary['filename'], 'thumbnail', true);
- }
- }
-
- /**
- * Perform additional actions after attachment(s) deletion from the filesystem
- *
- * @event core.delete_attachments_from_filesystem_after
- * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
- * @var mixed ids Array or comma separated list of ids corresponding to the mode
- * @var bool resync Flag indicating if posts/messages/topics should be synchronized
- * @var string sql_id The field name to collect/delete data for depending on the mode
- * @var array post_ids Array with post ids for deleted attachment(s)
- * @var array topic_ids Array with topic ids for deleted attachment(s)
- * @var array message_ids Array with private message ids for deleted attachment(s)
- * @var array physical Array with deleted attachment(s) physical file(s) data
- * @var int num_deleted The number of deleted attachment(s) from the database
- * @var int space_removed The size of deleted files(s) from the filesystem
- * @var int files_removed The number of deleted file(s) from the filesystem
- * @since 3.1.7-RC1
- */
- $vars = array(
- 'mode',
- 'ids',
- 'resync',
- 'sql_id',
- 'post_ids',
- 'topic_ids',
- 'message_ids',
- 'physical',
- 'num_deleted',
- 'space_removed',
- 'files_removed',
- );
- extract($phpbb_dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars)));
-
- if ($space_removed || $files_removed)
- {
- set_config_count('upload_dir_size', $space_removed * (-1), true);
- set_config_count('num_files', $files_removed * (-1), true);
- }
-
- // If we do not resync, we do not need to adjust any message, post, topic or user entries
- if (!$resync)
- {
- return $num_deleted;
- }
-
- // No more use for the original ids
- unset($ids);
-
- // Now, we need to resync posts, messages, topics. We go through every one of them
- $post_ids = array_unique($post_ids);
- $message_ids = array_unique($message_ids);
- $topic_ids = array_unique($topic_ids);
-
- // Update post indicators for posts now no longer having attachments
- if (sizeof($post_ids))
- {
- // Just check which posts are still having an assigned attachment not orphaned by querying the attachments table
- $sql = 'SELECT post_msg_id
- FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
- AND in_message = 0
- AND is_orphan = 0';
- $result = $db->sql_query($sql);
-
- $remaining_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $remaining_ids[] = $row['post_msg_id'];
- }
- $db->sql_freeresult($result);
-
- // Now only unset those ids remaining
- $post_ids = array_diff($post_ids, $remaining_ids);
-
- if (sizeof($post_ids))
- {
- $sql = 'UPDATE ' . POSTS_TABLE . '
- SET post_attachment = 0
- WHERE ' . $db->sql_in_set('post_id', $post_ids);
- $db->sql_query($sql);
- }
- }
-
- // Update message table if messages are affected
- if (sizeof($message_ids))
- {
- // Just check which messages are still having an assigned attachment not orphaned by querying the attachments table
- $sql = 'SELECT post_msg_id
- FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . '
- AND in_message = 1
- AND is_orphan = 0';
- $result = $db->sql_query($sql);
-
- $remaining_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $remaining_ids[] = $row['post_msg_id'];
- }
- $db->sql_freeresult($result);
-
- // Now only unset those ids remaining
- $message_ids = array_diff($message_ids, $remaining_ids);
-
- if (sizeof($message_ids))
- {
- $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
- SET message_attachment = 0
- WHERE ' . $db->sql_in_set('msg_id', $message_ids);
- $db->sql_query($sql);
- }
- }
-
- // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
- if (sizeof($topic_ids))
- {
- // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected)
- $sql = 'SELECT topic_id
- FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
- AND is_orphan = 0';
- $result = $db->sql_query($sql);
-
- $remaining_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $remaining_ids[] = $row['topic_id'];
- }
- $db->sql_freeresult($result);
+ global $phpbb_container;
- // Now only unset those ids remaining
- $topic_ids = array_diff($topic_ids, $remaining_ids);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $num_deleted = $attachment_manager->delete($mode, $ids, $resync);
- if (sizeof($topic_ids))
- {
- $sql = 'UPDATE ' . TOPICS_TABLE . '
- SET topic_attachment = 0
- WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
- $db->sql_query($sql);
- }
- }
+ unset($attachment_manager);
return $num_deleted;
}
@@ -1573,27 +1273,19 @@ function update_posted_info(&$topic_ids)
/**
* Delete attached file
+*
+* @deprecated 3.2.0-a1 (To be removed: 3.4.0)
*/
function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)
{
- global $db, $phpbb_root_path, $config;
-
- // Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself.
- $sql = 'SELECT COUNT(attach_id) AS num_entries
- FROM ' . ATTACHMENTS_TABLE . "
- WHERE physical_filename = '" . $db->sql_escape(utf8_basename($filename)) . "'";
- $result = $db->sql_query($sql);
- $num_entries = (int) $db->sql_fetchfield('num_entries');
- $db->sql_freeresult($result);
+ global $phpbb_container;
- // Do not remove file if at least one additional entry with the same name exist.
- if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1))
- {
- return false;
- }
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $unlink = $attachment_manager->unlink($filename, $mode, $entry_removed);
+ unset($attachment_manager);
- $filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename);
- return @unlink($phpbb_root_path . $config['upload_path'] . '/' . $filename);
+ return $unlink;
}
/**
@@ -2343,7 +2035,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
AND u.user_id = p.poster_id';
$result = $db->sql_query($sql);
- $post_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$topic_id = intval($row['topic_id']);
@@ -2416,7 +2107,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
AND u.user_id = p.poster_id';
$result = $db->sql_query($sql);
- $post_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$topic_id = (int) $row['topic_id'];
@@ -2665,7 +2355,7 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync
*/
function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq)
{
- global $db;
+ global $db, $user, $phpbb_log;
$sql = 'SELECT forum_name
FROM ' . FORUMS_TABLE . "
@@ -2689,7 +2379,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr
$db->sql_query($sql);
}
- add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_AUTO_PRUNE', false, array($row['forum_name']));
}
return;
@@ -2713,7 +2403,6 @@ function phpbb_cache_moderators($db, $cache, $auth)
// Clear table
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$db->sql_query('DELETE FROM ' . MODERATOR_CACHE_TABLE);
break;
@@ -2724,7 +2413,7 @@ function phpbb_cache_moderators($db, $cache, $auth)
}
// We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting
- $hold_ary = $ug_id_ary = $sql_ary = array();
+ $sql_ary = array();
// Grab all users having moderative options...
$hold_ary = $auth->acl_user_raw_data(false, 'm_%', false);
@@ -3171,7 +2860,6 @@ function get_database_size()
}
break;
- case 'sqlite':
case 'sqlite3':
global $dbhost;
@@ -3182,7 +2870,6 @@ function get_database_size()
break;
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$sql = 'SELECT @@VERSION AS mssql_version';
@@ -3256,25 +2943,6 @@ function get_database_size()
return $database_size;
}
-/**
-* Retrieve contents from remotely stored file
-*
-* @deprecated 3.1.2 Use file_downloader instead
-*/
-function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6)
-{
- global $phpbb_container;
-
- // Get file downloader and assign $errstr and $errno
- $file_downloader = $phpbb_container->get('file_downloader');
-
- $file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout);
- $errstr = $file_downloader->get_error_string();
- $errno = $file_downloader->get_error_number();
-
- return $file_data;
-}
-
/*
* Tidy Warnings
* Remove all warnings which have now expired from the database
@@ -3318,7 +2986,7 @@ function tidy_warnings()
$db->sql_transaction('commit');
}
- set_config('warnings_last_gc', time(), true);
+ $config->set('warnings_last_gc', time(), false);
}
/**
@@ -3326,7 +2994,7 @@ function tidy_warnings()
*/
function tidy_database()
{
- global $db;
+ global $config, $db;
// Here we check permission consistency
@@ -3351,7 +3019,7 @@ function tidy_database()
WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true);
$db->sql_query($sql);
- set_config('database_last_gc', time(), true);
+ $config->set('database_last_gc', time(), false);
}
/**
@@ -3359,47 +3027,18 @@ function tidy_database()
*/
function add_permission_language()
{
- global $config, $user, $phpEx, $phpbb_extension_manager;
+ global $user, $phpEx, $phpbb_extension_manager;
// add permission language files from extensions
$finder = $phpbb_extension_manager->get_finder();
- // We grab the language files from the default, English and user's language.
- // So we can fall back to the other files like we do when using add_lang()
- $default_lang_files = $english_lang_files = $user_lang_files = array();
-
- // Search for board default language if it's not the user language
- if ($config['default_lang'] != $user->lang_name)
- {
- $default_lang_files = $finder
- ->prefix('permissions_')
- ->suffix(".$phpEx")
- ->core_path('language/' . basename($config['default_lang']) . '/')
- ->extension_directory('/language/' . basename($config['default_lang']))
- ->find();
- }
-
- // Search for english, if its not the default or user language
- if ($config['default_lang'] != 'en' && $user->lang_name != 'en')
- {
- $english_lang_files = $finder
- ->prefix('permissions_')
- ->suffix(".$phpEx")
- ->core_path('language/en/')
- ->extension_directory('/language/en')
- ->find();
- }
-
- // Find files in the user's language
- $user_lang_files = $finder
+ $lang_files = $finder
->prefix('permissions_')
->suffix(".$phpEx")
- ->core_path('language/' . $user->lang_name . '/')
- ->extension_directory('/language/' . $user->lang_name)
+ ->core_path('language/')
+ ->extension_directory('/language')
->find();
- $lang_files = array_merge($english_lang_files, $default_lang_files, $user_lang_files);
-
foreach ($lang_files as $lang_file => $ext_name)
{
if ($ext_name === '/')
diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php
index b59c7376e9..4b085a6050 100644
--- a/phpBB/includes/functions_compatibility.php
+++ b/phpBB/includes/functions_compatibility.php
@@ -60,6 +60,7 @@ function phpbb_hash($password)
{
global $phpbb_container;
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
return $passwords_manager->hash($password);
}
@@ -78,6 +79,7 @@ function phpbb_check_hash($password, $hash)
{
global $phpbb_container;
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
return $passwords_manager->check($password, $hash);
}
@@ -90,7 +92,7 @@ function phpbb_check_hash($password, $hash)
* @param string $path Path to clean
* @return string Cleaned path
*
-* @deprecated
+* @deprecated 3.1.0 (To be removed: 3.3.0)
*/
function phpbb_clean_path($path)
{
@@ -98,6 +100,7 @@ function phpbb_clean_path($path)
if (!$phpbb_path_helper && $phpbb_container)
{
+ /* @var $phpbb_path_helper \phpbb\path_helper */
$phpbb_path_helper = $phpbb_container->get('path_helper');
}
else if (!$phpbb_path_helper)
@@ -115,7 +118,7 @@ function phpbb_clean_path($path)
new phpbb\symfony_request(
$request
),
- new phpbb\filesystem(),
+ new phpbb\filesystem\filesystem(),
$request,
$phpbb_root_path,
$phpEx
@@ -133,7 +136,7 @@ function phpbb_clean_path($path)
*
* @return string Returns the options for timezone selector only
*
-* @deprecated
+* @deprecated 3.1.0 (To be removed: 3.3.0)
*/
function tz_select($default = '', $truncate = false)
{
@@ -147,7 +150,7 @@ function tz_select($default = '', $truncate = false)
* via admin_permissions. Changes of usernames and group names
* must be carried through for the moderators table.
*
-* @deprecated 3.1
+* @deprecated 3.1.0 (To be removed: 3.3.0)
* @return null
*/
function cache_moderators()
@@ -159,7 +162,7 @@ function cache_moderators()
/**
* Removes moderators and administrators from foe lists.
*
-* @deprecated 3.1
+* @deprecated 3.1.0 (To be removed: 3.3.0)
* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore
* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore
* @return null
@@ -196,3 +199,315 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank
$rank_img = $rank_data['img'];
$rank_img_src = $rank_data['img_src'];
}
+
+/**
+ * Retrieve contents from remotely stored file
+ *
+ * @deprecated 3.1.2 Use file_downloader instead
+ */
+function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6)
+{
+ global $phpbb_container;
+
+ // Get file downloader and assign $errstr and $errno
+ /* @var $file_downloader \phpbb\file_downloader */
+ $file_downloader = $phpbb_container->get('file_downloader');
+
+ $file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout);
+ $errstr = $file_downloader->get_error_string();
+ $errno = $file_downloader->get_error_number();
+
+ return $file_data;
+}
+
+/**
+ * Add log entry
+ *
+ * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
+ * @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise
+ * @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise
+ * @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise
+ * @param string $log_operation Name of the operation
+ * @param array $additional_data More arguments can be added, depending on the log_type
+ *
+ * @return int|bool Returns the log_id, if the entry was added to the database, false otherwise.
+ *
+ * @deprecated 3.1.0 (To be removed: 3.3.0)
+ */
+function add_log()
+{
+ global $phpbb_log, $user;
+
+ $args = func_get_args();
+ $mode = array_shift($args);
+
+ // This looks kind of dirty, but add_log has some additional data before the log_operation
+ $additional_data = array();
+ switch ($mode)
+ {
+ case 'admin':
+ case 'critical':
+ break;
+ case 'mod':
+ $additional_data['forum_id'] = array_shift($args);
+ $additional_data['topic_id'] = array_shift($args);
+ break;
+ case 'user':
+ $additional_data['reportee_id'] = array_shift($args);
+ break;
+ }
+
+ $log_operation = array_shift($args);
+ $additional_data = array_merge($additional_data, $args);
+
+ $user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id'];
+ $user_ip = (empty($user->ip)) ? '' : $user->ip;
+
+ return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data);
+}
+
+/**
+ * Sets a configuration option's value.
+ *
+ * Please note that this function does not update the is_dynamic value for
+ * an already existing config option.
+ *
+ * @param string $config_name The configuration option's name
+ * @param string $config_value New configuration value
+ * @param bool $is_dynamic Whether this variable should be cached (false) or
+ * if it changes too frequently (true) to be
+ * efficiently cached.
+ *
+ * @return null
+ *
+ * @deprecated 3.1.0 (To be removed: 3.3.0)
+ */
+function set_config($config_name, $config_value, $is_dynamic = false, \phpbb\config\config $set_config = null)
+{
+ static $config = null;
+
+ if ($set_config !== null)
+ {
+ $config = $set_config;
+
+ if (empty($config_name))
+ {
+ return;
+ }
+ }
+
+ $config->set($config_name, $config_value, !$is_dynamic);
+}
+
+/**
+ * Increments an integer config value directly in the database.
+ *
+ * @param string $config_name The configuration option's name
+ * @param int $increment Amount to increment by
+ * @param bool $is_dynamic Whether this variable should be cached (false) or
+ * if it changes too frequently (true) to be
+ * efficiently cached.
+ *
+ * @return null
+ *
+ * @deprecated 3.1.0 (To be removed: 3.3.0)
+ */
+function set_config_count($config_name, $increment, $is_dynamic = false, \phpbb\config\config $set_config = null)
+{
+ static $config = null;
+ if ($set_config !== null)
+ {
+ $config = $set_config;
+ if (empty($config_name))
+ {
+ return;
+ }
+ }
+ $config->increment($config_name, $increment, !$is_dynamic);
+}
+
+/**
+ * Wrapper function of \phpbb\request\request::variable which exists for backwards compatability.
+ * See {@link \phpbb\request\request_interface::variable \phpbb\request\request_interface::variable} for
+ * documentation of this function's use.
+ *
+ * @deprecated 3.1.0 (To be removed: 3.3.0)
+ * @param mixed $var_name The form variable's name from which data shall be retrieved.
+ * If the value is an array this may be an array of indizes which will give
+ * direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a")
+ * then specifying array("var", 1) as the name will return "a".
+ * If you pass an instance of {@link \phpbb\request\request_interface phpbb_request_interface}
+ * as this parameter it will overwrite the current request class instance. If you do
+ * not do so, it will create its own instance (but leave superglobals enabled).
+ * @param mixed $default A default value that is returned if the variable was not set.
+ * This function will always return a value of the same type as the default.
+ * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters
+ * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks
+ * @param bool $cookie This param is mapped to \phpbb\request\request_interface::COOKIE as the last param for
+ * \phpbb\request\request_interface::variable for backwards compatability reasons.
+ * @param \phpbb\request\request_interface|null|false If an instance of \phpbb\request\request_interface is given the instance is stored in
+ * a static variable and used for all further calls where this parameters is null. Until
+ * the function is called with an instance it automatically creates a new \phpbb\request\request
+ * instance on every call. By passing false this per-call instantiation can be restored
+ * after having passed in a \phpbb\request\request_interface instance.
+ *
+ * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the
+ * the same as that of $default. If the variable is not set $default is returned.
+ */
+function request_var($var_name, $default, $multibyte = false, $cookie = false, $request = null)
+{
+ // This is all just an ugly hack to add "Dependency Injection" to a function
+ // the only real code is the function call which maps this function to a method.
+ static $static_request = null;
+ if ($request instanceof \phpbb\request\request_interface)
+ {
+ $static_request = $request;
+ if (empty($var_name))
+ {
+ return;
+ }
+ }
+ else if ($request === false)
+ {
+ $static_request = null;
+ if (empty($var_name))
+ {
+ return;
+ }
+ }
+ $tmp_request = $static_request;
+ // no request class set, create a temporary one ourselves to keep backwards compatibility
+ if ($tmp_request === null)
+ {
+ // false param: enable super globals, so the created request class does not
+ // make super globals inaccessible everywhere outside this function.
+ $tmp_request = new \phpbb\request\request(new \phpbb\request\type_cast_helper(), false);
+ }
+ return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST);
+}
+
+/**
+ * Get tables of a database
+ *
+ * @deprecated 3.1.0 (To be removed: 3.3.0)
+ */
+function get_tables(&$db)
+{
+ $db_tools_factory = new \phpbb\db\tools\factory();
+ $db_tools = $db_tools_factory->get($db);
+
+ return $db_tools->sql_list_tables();
+}
+
+/**
+ * Global function for chmodding directories and files for internal use
+ *
+ * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
+ * The function determines owner and group from common.php file and sets the same to the provided file.
+ * The function uses bit fields to build the permissions.
+ * The function sets the appropiate execute bit on directories.
+ *
+ * Supported constants representing bit fields are:
+ *
+ * CHMOD_ALL - all permissions (7)
+ * CHMOD_READ - read permission (4)
+ * CHMOD_WRITE - write permission (2)
+ * CHMOD_EXECUTE - execute permission (1)
+ *
+ * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions.
+ *
+ * @param string $filename The file/directory to be chmodded
+ * @param int $perms Permissions to set
+ *
+ * @return bool true on success, otherwise false
+ *
+ * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::phpbb_chmod() instead
+ */
+function phpbb_chmod($filename, $perms = CHMOD_READ)
+{
+ global $phpbb_filesystem;
+
+ try
+ {
+ $phpbb_filesystem->phpbb_chmod($filename, $perms);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Test if a file/directory is writable
+ *
+ * This function calls the native is_writable() when not running under
+ * Windows and it is not disabled.
+ *
+ * @param string $file Path to perform write test on
+ * @return bool True when the path is writable, otherwise false.
+ *
+ * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_writable() instead
+ */
+function phpbb_is_writable($file)
+{
+ global $phpbb_filesystem;
+
+ return $phpbb_filesystem->is_writable($file);
+}
+
+/**
+ * Checks if a path ($path) is absolute or relative
+ *
+ * @param string $path Path to check absoluteness of
+ * @return boolean
+ *
+ * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_absolute_path() instead
+ */
+function phpbb_is_absolute($path)
+{
+ global $phpbb_filesystem;
+
+ return $phpbb_filesystem->is_absolute_path($path);
+}
+
+/**
+ * A wrapper for realpath
+ *
+ * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::realpath() instead
+ */
+function phpbb_realpath($path)
+{
+ global $phpbb_filesystem;
+
+ return $phpbb_filesystem->realpath($path);
+}
+
+/**
+ * Determine which plural form we should use.
+ * For some languages this is not as simple as for English.
+ *
+ * @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules
+ * @param $number int|float The number we want to get the plural case for. Float numbers are floored.
+ * @return int The plural-case we need to use for the number plural-rule combination
+ *
+ * @deprecated 3.2.0-dev (To be removed: 3.3.0)
+ */
+function phpbb_get_plural_form($rule, $number)
+{
+ global $phpbb_container;
+
+ /** @var \phpbb\language\language $language */
+ $language = $phpbb_container->get('language');
+ return $language->get_plural_form($number, $rule);
+}
+
+/**
+* @return bool Always true
+* @deprecated 3.2.0-dev
+*/
+function phpbb_pcre_utf8_support()
+{
+ return true;
+}
diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php
index a7ee29dd91..910708f502 100644
--- a/phpBB/includes/functions_compress.php
+++ b/phpBB/includes/functions_compress.php
@@ -56,7 +56,6 @@ class compress
// Clean up path, add closing / if not present
$src_path = ($src_path && substr($src_path, -1) != '/') ? $src_path . '/' : $src_path;
- $filelist = array();
$filelist = filelist("$phpbb_root_path$src", '', '*');
krsort($filelist);
@@ -184,7 +183,7 @@ class compress
}
/**
-* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux,
+* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux,
* Marc Delisle, http://www.phpmyadmin.net/
*
* Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com
@@ -204,11 +203,19 @@ class compress_zip extends compress
var $datasec_len = 0;
/**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
* Constructor
*/
function compress_zip($mode, $file)
{
+ global $phpbb_filesystem;
+
$this->fp = @fopen($file, $mode . 'b');
+ $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem();
if (!$this->fp)
{
@@ -286,7 +293,15 @@ class compress_zip extends compress
{
trigger_error("Could not create directory $folder");
}
- phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
}
}
}
@@ -315,7 +330,15 @@ class compress_zip extends compress
{
trigger_error("Could not create directory $folder");
}
- phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
}
}
}
@@ -539,10 +562,17 @@ class compress_tar extends compress
var $wrote = false;
/**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
* Constructor
*/
function compress_tar($mode, $file, $type = '')
{
+ global $phpbb_filesystem;
+
$type = (!$type) ? $file : $type;
$this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type);
$this->isbz = preg_match('#\.tar\.bz2$#', $type);
@@ -551,6 +581,8 @@ class compress_tar extends compress
$this->file = &$file;
$this->type = &$type;
$this->open();
+
+ $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem();
}
/**
@@ -601,7 +633,15 @@ class compress_tar extends compress
{
trigger_error("Could not create directory $folder");
}
- phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
}
}
}
@@ -628,7 +668,15 @@ class compress_tar extends compress
{
trigger_error("Could not create directory $folder");
}
- phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
}
}
@@ -637,7 +685,15 @@ class compress_tar extends compress
{
trigger_error("Couldn't create file $filename");
}
- phpbb_chmod($target_filename, CHMOD_READ);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($target_filename, CHMOD_READ);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
// Grab the file contents
fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize);
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index 8e60804d6e..e36eb8119b 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -460,41 +460,54 @@ function phpbb_clean_search_string($search_string)
/**
* Decode text whereby text is coming from the db and expected to be pre-parsed content
* We are placing this outside of the message parser because we are often in need of it...
+*
+* NOTE: special chars are kept encoded
+*
+* @param string &$message Original message, passed by reference
+* @param string $bbcode_uid BBCode UID
+* @return null
*/
function decode_message(&$message, $bbcode_uid = '')
{
- global $config, $phpbb_dispatcher;
-
- if ($bbcode_uid)
- {
- $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid");
- $replace = array("\n", '', '', '', '');
- }
- else
- {
- $match = array('<br />');
- $replace = array("\n");
- }
+ global $phpbb_container, $phpbb_dispatcher;
/**
- * Use this event to modify the message before it is decoded
- *
- * @event core.decode_message_before
- * @var string message_text The message content
- * @var string bbcode_uid The message BBCode UID
- * @since 3.1.9-RC1
- */
+ * Use this event to modify the message before it is decoded
+ *
+ * @event core.decode_message_before
+ * @var string message_text The message content
+ * @var string bbcode_uid The message BBCode UID
+ * @since 3.1.9-RC1
+ */
$message_text = $message;
$vars = array('message_text', 'bbcode_uid');
extract($phpbb_dispatcher->trigger_event('core.decode_message_before', compact($vars)));
$message = $message_text;
- $message = str_replace($match, $replace, $message);
+ if (preg_match('#^<[rt][ >]#', $message))
+ {
+ $message = htmlspecialchars($phpbb_container->get('text_formatter.utils')->unparse($message), ENT_COMPAT);
+ }
+ else
+ {
+ if ($bbcode_uid)
+ {
+ $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid");
+ $replace = array("\n", '', '', '', '');
+ }
+ else
+ {
+ $match = array('<br />');
+ $replace = array("\n");
+ }
- $match = get_preg_expression('bbcode_htm');
- $replace = array('\1', '\1', '\2', '\1', '', '');
+ $message = str_replace($match, $replace, $message);
- $message = preg_replace($match, $replace, $message);
+ $match = get_preg_expression('bbcode_htm');
+ $replace = array('\1', '\1', '\2', '\2', '\1', '', '');
+
+ $message = preg_replace($match, $replace, $message);
+ }
/**
* Use this event to modify the message after it is decoded
@@ -511,21 +524,30 @@ function decode_message(&$message, $bbcode_uid = '')
}
/**
-* Strips all bbcode from a text and returns the plain content
+* Strips all bbcode from a text in place
*/
function strip_bbcode(&$text, $uid = '')
{
- if (!$uid)
+ global $phpbb_container;
+
+ if (preg_match('#^<[rt][ >]#', $text))
{
- $uid = '[0-9a-z]{5,}';
+ $text = $phpbb_container->get('text_formatter.utils')->clean_formatting($text);
}
+ else
+ {
+ if (!$uid)
+ {
+ $uid = '[0-9a-z]{5,}';
+ }
- $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text);
+ $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text);
- $match = get_preg_expression('bbcode_htm');
- $replace = array('\1', '\1', '\2', '\1', '', '');
+ $match = get_preg_expression('bbcode_htm');
+ $replace = array('\1', '\1', '\2', '\1', '', '');
- $text = preg_replace($match, $replace, $text);
+ $text = preg_replace($match, $replace, $text);
+ }
}
/**
@@ -535,7 +557,7 @@ function strip_bbcode(&$text, $uid = '')
function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text = true)
{
static $bbcode;
- global $phpbb_dispatcher;
+ global $phpbb_dispatcher, $phpbb_container;
if ($text === '')
{
@@ -556,34 +578,56 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text
$vars = array('text', 'uid', 'bitfield', 'flags', 'censor_text');
extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_before', compact($vars)));
- if ($censor_text)
+ if (preg_match('#^<[rt][ >]#', $text))
{
- $text = censor_text($text);
- }
+ $renderer = $phpbb_container->get('text_formatter.renderer');
- // Parse bbcode if bbcode uid stored and bbcode enabled
- if ($uid && ($flags & OPTION_FLAG_BBCODE))
- {
- if (!class_exists('bbcode'))
+ // Temporarily switch off viewcensors if applicable
+ $old_censor = $renderer->get_viewcensors();
+ if ($old_censor !== $censor_text)
{
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
+ $renderer->set_viewcensors($censor_text);
}
- if (empty($bbcode))
+ $text = $renderer->render($text);
+
+ // Restore the previous value
+ if ($old_censor !== $censor_text)
{
- $bbcode = new bbcode($bitfield);
+ $renderer->set_viewcensors($old_censor);
}
- else
+ }
+ else
+ {
+ if ($censor_text)
{
- $bbcode->bbcode($bitfield);
+ $text = censor_text($text);
}
- $bbcode->bbcode_second_pass($text, $uid);
- }
+ // Parse bbcode if bbcode uid stored and bbcode enabled
+ if ($uid && ($flags & OPTION_FLAG_BBCODE))
+ {
+ if (!class_exists('bbcode'))
+ {
+ global $phpbb_root_path, $phpEx;
+ include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
+ }
+
+ if (empty($bbcode))
+ {
+ $bbcode = new bbcode($bitfield);
+ }
+ else
+ {
+ $bbcode->bbcode($bitfield);
+ }
- $text = bbcode_nl2br($text);
- $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES));
+ $bbcode->bbcode_second_pass($text, $uid);
+ }
+
+ $text = bbcode_nl2br($text);
+ $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES));
+ }
/**
* Use this event to modify the text after it is parsed
@@ -604,7 +648,7 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text
/**
* For parsing custom parsed text to be stored within the database.
* This function additionally returns the uid and bitfield that needs to be stored.
-* Expects $text to be the value directly from request_var() and in it's non-parsed form
+* Expects $text to be the value directly from $request->variable() and in it's non-parsed form
*
* @param string $text The text to be replaced with the parsed one
* @param string $uid The BBCode uid for this parse
@@ -613,10 +657,15 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text
* @param bool $allow_bbcode If BBCode is allowed (i.e. if BBCode is parsed)
* @param bool $allow_urls If urls is allowed
* @param bool $allow_smilies If smilies are allowed
+* @param bool $allow_img_bbcode
+* @param bool $allow_flash_bbcode
+* @param bool $allow_quote_bbcode
+* @param bool $allow_url_bbcode
+* @param string $mode Mode to parse text as, e.g. post or sig
*
* @return array An array of string with the errors that occurred while parsing
*/
-function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false)
+function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $mode = 'post')
{
global $phpbb_root_path, $phpEx, $phpbb_dispatcher;
@@ -631,7 +680,13 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb
* @var bool allow_bbcode Whether or not to parse BBCode
* @var bool allow_urls Whether or not to parse URLs
* @var bool allow_smilies Whether or not to parse Smilies
+ * @var bool allow_img_bbcode Whether or not to parse the [img] BBCode
+ * @var bool allow_flash_bbcode Whether or not to parse the [flash] BBCode
+ * @var bool allow_quote_bbcode Whether or not to parse the [quote] BBCode
+ * @var bool allow_url_bbcode Whether or not to parse the [url] BBCode
+ * @var string mode Mode to parse text as, e.g. post or sig
* @since 3.1.0-a1
+ * @changed 3.2.0-a1
*/
$vars = array(
'text',
@@ -641,24 +696,24 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb
'allow_bbcode',
'allow_urls',
'allow_smilies',
+ 'allow_img_bbcode',
+ 'allow_flash_bbcode',
+ 'allow_quote_bbcode',
+ 'allow_url_bbcode',
+ 'mode',
);
extract($phpbb_dispatcher->trigger_event('core.modify_text_for_storage_before', compact($vars)));
$uid = $bitfield = '';
$flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0);
- if ($text === '')
- {
- return;
- }
-
if (!class_exists('parse_message'))
{
include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
}
$message_parser = new parse_message($text);
- $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies);
+ $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode, true, $mode);
$text = $message_parser->message;
$uid = $message_parser->bbcode_uid;
@@ -693,7 +748,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb
*/
function generate_text_for_edit($text, $uid, $flags)
{
- global $phpbb_root_path, $phpEx, $phpbb_dispatcher;
+ global $phpbb_dispatcher;
/**
* Use this event to modify the text before it is decoded for editing
@@ -999,10 +1054,10 @@ function smiley_text($text, $force_option = false)
* @param mixed $forum_id The forum id the attachments are displayed in (false if in private message)
* @param string &$message The post/private message
* @param array &$attachments The attachments to parse for (inline) display. The attachments array will hold templated data after parsing.
-* @param array &$update_count The attachment counts to be updated - will be filled
+* @param array &$update_count_ary The attachment counts to be updated - will be filled
* @param bool $preview If set to true the attachments are parsed for preview. Within preview mode the comments are fetched from the given $attachments array and not fetched from the database.
*/
-function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $preview = false)
+function parse_attachments($forum_id, &$message, &$attachments, &$update_count_ary, $preview = false)
{
if (!sizeof($attachments))
{
@@ -1089,7 +1144,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
// Some basics...
$attachment['extension'] = strtolower(trim($attachment['extension']));
$filename = $phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($attachment['physical_filename']);
- $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . utf8_basename($attachment['physical_filename']);
$upload_icon = '';
@@ -1131,7 +1185,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
if (!$denied)
{
- $l_downloaded_viewed = $download_link = '';
$display_cat = $extensions[$attachment['extension']]['display_cat'];
if ($display_cat == ATTACHMENT_CATEGORY_IMAGE)
@@ -1192,7 +1245,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
'U_INLINE_LINK' => $inline_link,
);
- $update_count[] = $attachment['attach_id'];
+ $update_count_ary[] = $attachment['attach_id'];
break;
// Images, but display Thumbnail
@@ -1205,39 +1258,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
'THUMB_IMAGE' => $thumbnail_link,
);
- $update_count[] = $attachment['attach_id'];
- break;
-
- // Windows Media Streams
- case ATTACHMENT_CATEGORY_WM:
-
- // Giving the filename directly because within the wm object all variables are in local context making it impossible
- // to validate against a valid session (all params can differ)
- // $download_link = $filename;
-
- $block_array += array(
- 'U_FORUM' => generate_board_url(),
- 'ATTACH_ID' => $attachment['attach_id'],
- 'S_WM_FILE' => true,
- );
-
- // Viewed/Heared File ... update the download count
- $update_count[] = $attachment['attach_id'];
- break;
-
- // Real Media Streams
- case ATTACHMENT_CATEGORY_RM:
- case ATTACHMENT_CATEGORY_QUICKTIME:
-
- $block_array += array(
- 'S_RM_FILE' => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false,
- 'S_QUICKTIME_FILE' => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false,
- 'U_FORUM' => generate_board_url(),
- 'ATTACH_ID' => $attachment['attach_id'],
- );
-
- // Viewed/Heared File ... update the download count
- $update_count[] = $attachment['attach_id'];
+ $update_count_ary[] = $attachment['attach_id'];
break;
// Macromedia Flash Files
@@ -1252,7 +1273,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
);
// Viewed/Heared File ... update the download count
- $update_count[] = $attachment['attach_id'];
+ $update_count_ary[] = $attachment['attach_id'];
break;
default:
@@ -1275,6 +1296,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
);
}
+ $update_count = $update_count_ary;
/**
* Use this event to modify the attachment template data.
*
@@ -1302,6 +1324,8 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
'update_count',
);
extract($phpbb_dispatcher->trigger_event('core.parse_attachments_modify_template_data', compact($vars)));
+ $update_count_ary = $update_count;
+ unset($update_count);
$template->assign_block_vars('_file', $block_array);
@@ -1387,8 +1411,6 @@ function extension_allowed($forum_id, $extension, &$extensions)
*/
function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = false, $append = '')
{
- $chars = array();
-
$strip_reply = false;
$stripped = false;
if ($allow_reply && strpos($string, 'Re: ') === 0)
diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php
index da4820134d..176e3dd6de 100644
--- a/phpBB/includes/functions_convert.php
+++ b/phpBB/includes/functions_convert.php
@@ -423,7 +423,7 @@ function remote_avatar_dims()
function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false)
{
- global $config, $convert, $phpbb_root_path, $user;
+ global $config, $convert, $user;
$relative_path = empty($convert->convertor['source_path_absolute']);
@@ -492,7 +492,7 @@ function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false
function import_attachment_files($category_name = '')
{
- global $config, $convert, $phpbb_root_path, $db, $user;
+ global $config, $convert, $db, $user;
$sql = 'SELECT config_value AS upload_path
FROM ' . CONFIG_TABLE . "
@@ -590,7 +590,7 @@ function import_attachment($source, $use_target = false)
return '';
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $config, $user;
// check for trailing slash
if (rtrim($convert->convertor['upload_path'], '/') === '')
@@ -632,7 +632,7 @@ function import_rank($source, $use_target = false)
return '';
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $user;
if (!isset($convert->convertor['ranks_path']))
{
@@ -650,7 +650,7 @@ function import_smiley($source, $use_target = false)
return '';
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $user;
// check for trailing slash
if (rtrim($convert->convertor['smilies_path'], '/') === '')
@@ -671,7 +671,7 @@ function import_avatar($source, $use_target = false, $user_id = false)
return;
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $config, $user;
// check for trailing slash
if (rtrim($convert->convertor['avatar_path'], '/') === '')
@@ -684,7 +684,7 @@ function import_avatar($source, $use_target = false, $user_id = false)
$use_target = $config['avatar_salt'] . '_' . $user_id . '.' . substr(strrchr($source, '.'), 1);
}
- $result = _import_check('avatar_path', $source, $use_target);
+ _import_check('avatar_path', $source, $use_target);
return ((!empty($user_id)) ? $user_id : $use_target) . '.' . substr(strrchr($source, '.'), 1);
}
@@ -750,7 +750,7 @@ function get_smiley_dim($source, $axis)
return $smiley_cache[$source][$axis];
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $user;
$orig_source = $source;
@@ -858,14 +858,12 @@ function get_upload_avatar_dim($source, $axis)
return $cachedims[$axis];
}
- $orig_source = $source;
-
if (substr($source, 0, 7) == 'upload:')
{
$source = substr($source, 7);
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $user;
if (!isset($convert->convertor['avatar_path']))
{
@@ -907,7 +905,7 @@ function get_gallery_avatar_dim($source, $axis)
return $avatar_cache[$source][$axis];
}
- global $convert, $phpbb_root_path, $config, $user;
+ global $convert, $user;
$orig_source = $source;
@@ -1122,7 +1120,7 @@ function words_unique(&$words)
*/
function add_user_group($group_id, $user_id, $group_leader = false)
{
- global $convert, $phpbb_root_path, $config, $user, $db;
+ global $db;
$sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'group_id' => $group_id,
@@ -1142,7 +1140,7 @@ function add_user_group($group_id, $user_id, $group_leader = false)
*/
function user_group_auth($group, $select_query, $use_src_db)
{
- global $convert, $phpbb_root_path, $config, $user, $db, $src_db, $same_db;
+ global $convert, $user, $db, $src_db, $same_db;
if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots')))
{
@@ -1198,7 +1196,7 @@ function get_config()
return $convert_config;
}
- global $src_db, $same_db, $phpbb_root_path, $config;
+ global $src_db, $same_db;
global $convert;
if ($convert->config_schema['table_format'] != 'file')
@@ -1277,7 +1275,7 @@ function get_config()
*/
function restore_config($schema)
{
- global $db, $config;
+ global $config;
$convert_config = get_config();
@@ -1312,7 +1310,7 @@ function restore_config($schema)
$config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false);
}
- set_config($config_name, $config_value);
+ $config->set($config_name, $config_value);
}
}
}
@@ -1322,7 +1320,7 @@ function restore_config($schema)
*/
function update_folder_pm_count()
{
- global $db, $convert, $user;
+ global $db;
$sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages
FROM ' . PRIVMSGS_TO_TABLE . '
@@ -1381,7 +1379,7 @@ function extract_variables_from_file($_filename)
function get_path($src_path, $src_url, $test_file)
{
- global $config, $phpbb_root_path, $phpEx;
+ global $phpbb_root_path, $phpEx;
$board_config = get_config();
@@ -1492,7 +1490,7 @@ function compare_table($tables, $tablename, &$prefixes)
*/
function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
{
- global $db, $convert, $user, $config;
+ global $db;
static $acl_option_ids, $group_ids;
if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id))
@@ -1654,8 +1652,6 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
$sql = 'VALUES ' . implode(', ', preg_replace('#^(.*?)$#', '(\1)', $sql_subary));
break;
- case 'mssql':
- case 'sqlite':
case 'sqlite3':
case 'mssqlnative':
$sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary));
@@ -1968,9 +1964,9 @@ function update_dynamic_config()
if ($row)
{
- set_config('newest_user_id', $row['user_id'], true);
- set_config('newest_username', $row['username'], true);
- set_config('newest_user_colour', $row['user_colour'], true);
+ $config->set('newest_user_id', $row['user_id'], false);
+ $config->set('newest_username', $row['username'], false);
+ $config->set('newest_user_colour', $row['user_colour'], false);
}
// Also do not reset record online user/date. There will be old data or the fresh data from the schema.
@@ -1984,7 +1980,7 @@ function update_dynamic_config()
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('num_posts', (int) $row['stat'], true);
+ $config->set('num_posts', (int) $row['stat'], false);
$sql = 'SELECT COUNT(topic_id) AS stat
FROM ' . TOPICS_TABLE . '
@@ -1993,7 +1989,7 @@ function update_dynamic_config()
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('num_topics', (int) $row['stat'], true);
+ $config->set('num_topics', (int) $row['stat'], false);
$sql = 'SELECT COUNT(user_id) AS stat
FROM ' . USERS_TABLE . '
@@ -2002,20 +1998,20 @@ function update_dynamic_config()
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('num_users', (int) $row['stat'], true);
+ $config->set('num_users', (int) $row['stat'], false);
$sql = 'SELECT COUNT(attach_id) as stat
FROM ' . ATTACHMENTS_TABLE . '
WHERE is_orphan = 0';
$result = $db->sql_query($sql);
- set_config('num_files', (int) $db->sql_fetchfield('stat'), true);
+ $config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
$sql = 'SELECT SUM(filesize) as stat
FROM ' . ATTACHMENTS_TABLE . '
WHERE is_orphan = 0';
$result = $db->sql_query($sql);
- set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true);
+ $config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false);
$db->sql_freeresult($result);
/**
@@ -2039,11 +2035,10 @@ function update_dynamic_config()
*/
function update_topics_posted()
{
- global $db, $config;
+ global $db;
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
break;
@@ -2180,7 +2175,7 @@ function fix_empty_primary_groups()
*/
function remove_invalid_users()
{
- global $convert, $db, $phpEx, $phpbb_root_path;
+ global $db, $phpEx, $phpbb_root_path;
// username_clean is UNIQUE
$sql = 'SELECT user_id
@@ -2316,7 +2311,10 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals
function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
{
- global $convert, $phpbb_root_path, $config, $user, $db;
+ global $convert, $phpbb_root_path, $user, $phpbb_filesystem;
+
+ /** @var \phpbb\filesystem\filesystem_interface $filesystem */
+ $filesystem = $phpbb_filesystem;
if (substr($trg, -1) == '/')
{
@@ -2349,7 +2347,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour
}
}
- if (!phpbb_is_writable($path))
+ if (!$filesystem->is_writable($path))
{
@chmod($path, 0777);
}
@@ -2370,7 +2368,10 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour
function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
{
- global $convert, $phpbb_root_path, $config, $user, $db;
+ global $convert, $phpbb_root_path, $config, $user, $phpbb_filesystem;
+
+ /** @var \phpbb\filesystem\filesystem_interface $filesystem */
+ $filesystem = $phpbb_filesystem;
$dirlist = $filelist = $bad_dirs = array();
$src = path($src, $source_relative_path);
@@ -2384,7 +2385,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_
@chmod($trg_path, 0777);
}
- if (!phpbb_is_writable($trg_path))
+ if (!$filesystem->is_writable($trg_path))
{
$bad_dirs[] = path($config['script_path']) . $trg;
}
@@ -2451,7 +2452,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_
@chmod($trg_path . $dir, 0777);
}
- if (!phpbb_is_writable($trg_path . $dir))
+ if (!$filesystem->is_writable($trg_path . $dir))
{
$bad_dirs[] = $trg . $dir;
$bad_dirs[] = $trg_path . $dir;
@@ -2479,7 +2480,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_
function relative_base($path, $is_relative = true, $line = false, $file = false)
{
- global $convert, $phpbb_root_path, $config, $user, $db;
+ global $convert, $user;
if (!$is_relative)
{
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index 4881dde6f5..4726676e2d 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -30,10 +30,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_rows = $subforums = $forum_ids = $forum_ids_moderator = $forum_moderators = $active_forum_ary = array();
$parent_id = $visible_forums = 0;
- $sql_from = '';
// Mark forums read?
- $mark_read = request_var('mark', '');
+ $mark_read = $request->variable('mark', '');
if ($mark_read == 'all')
{
@@ -61,9 +60,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$redirect = build_url(array('mark', 'hash', 'mark_time'));
meta_refresh(3, $redirect);
- if (check_link_hash(request_var('hash', ''), 'global'))
+ if (check_link_hash($request->variable('hash', ''), 'global'))
{
- markread('all', false, false, request_var('mark_time', 0));
+ markread('all', false, false, $request->variable('mark_time', 0));
if ($request->is_ajax())
{
@@ -153,6 +152,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_tracking_info = $valid_categories = array();
$branch_root_id = $root_data['forum_id'];
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
while ($row = $db->sql_fetchrow($result))
@@ -341,10 +341,10 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
if ($mark_read == 'forums')
{
$redirect = build_url(array('mark', 'hash', 'mark_time'));
- $token = request_var('hash', '');
+ $token = $request->variable('hash', '');
if (check_link_hash($token, 'global'))
{
- markread('topics', $forum_ids, false, request_var('mark_time', 0));
+ markread('topics', $forum_ids, false, $request->variable('mark_time', 0));
$message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
meta_refresh(3, $redirect);
@@ -437,15 +437,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
*
* @event core.display_forums_modify_category_template_vars
* @var array cat_row Template data of the 'category'
- * @var bool catless The flag indicating whether the 'category' has a parent category
* @var bool last_catless The flag indicating whether the last forum had a parent category
* @var array root_data Array with the root forum data
* @var array row The data of the 'category'
* @since 3.1.0-RC4
+ * @change 3.1.7-RC1 Removed undefined catless variable
*/
$vars = array(
'cat_row',
- 'catless',
'last_catless',
'root_data',
'row',
@@ -732,7 +731,7 @@ function generate_forum_rules(&$forum_data)
return;
}
- global $template, $phpbb_root_path, $phpEx;
+ global $template;
if ($forum_data['forum_rules'])
{
@@ -750,20 +749,20 @@ function generate_forum_rules(&$forum_data)
* Create forum navigation links for given forum, create parent
* list if currently null, assign basic forum info to template
*/
-function generate_forum_nav(&$forum_data)
+function generate_forum_nav(&$forum_data_ary)
{
- global $db, $user, $template, $auth, $config;
+ global $template, $auth, $config;
global $phpEx, $phpbb_root_path, $phpbb_dispatcher;
- if (!$auth->acl_get('f_list', $forum_data['forum_id']))
+ if (!$auth->acl_get('f_list', $forum_data_ary['forum_id']))
{
return;
}
- $navlinks = $navlinks_parents = $forum_template_data = array();
+ $navlinks_parents = $forum_template_data = array();
// Get forum parents
- $forum_parents = get_forum_parents($forum_data);
+ $forum_parents = get_forum_parents($forum_data_ary);
$microdata_attr = 'data-forum-id';
@@ -793,23 +792,24 @@ function generate_forum_nav(&$forum_data)
}
$navlinks = array(
- 'S_IS_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false,
- 'S_IS_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false,
- 'S_IS_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false,
- 'FORUM_NAME' => $forum_data['forum_name'],
- 'FORUM_ID' => $forum_data['forum_id'],
- 'MICRODATA' => $microdata_attr . '="' . $forum_data['forum_id'] . '"',
- 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data['forum_id']),
+ 'S_IS_CAT' => ($forum_data_ary['forum_type'] == FORUM_CAT) ? true : false,
+ 'S_IS_LINK' => ($forum_data_ary['forum_type'] == FORUM_LINK) ? true : false,
+ 'S_IS_POST' => ($forum_data_ary['forum_type'] == FORUM_POST) ? true : false,
+ 'FORUM_NAME' => $forum_data_ary['forum_name'],
+ 'FORUM_ID' => $forum_data_ary['forum_id'],
+ 'MICRODATA' => $microdata_attr . '="' . $forum_data_ary['forum_id'] . '"',
+ 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data_ary['forum_id']),
);
$forum_template_data = array(
- 'FORUM_ID' => $forum_data['forum_id'],
- 'FORUM_NAME' => $forum_data['forum_name'],
- 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']),
+ 'FORUM_ID' => $forum_data_ary['forum_id'],
+ 'FORUM_NAME' => $forum_data_ary['forum_name'],
+ 'FORUM_DESC' => generate_text_for_display($forum_data_ary['forum_desc'], $forum_data_ary['forum_desc_uid'], $forum_data_ary['forum_desc_bitfield'], $forum_data_ary['forum_desc_options']),
- 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data['forum_options'])) ? true : false,
+ 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data_ary['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data_ary['forum_options'])) ? true : false,
);
+ $forum_data = $forum_data_ary;
/**
* Event to modify the navlinks text
*
@@ -829,6 +829,8 @@ function generate_forum_nav(&$forum_data)
'navlinks',
);
extract($phpbb_dispatcher->trigger_event('core.generate_forum_nav', compact($vars)));
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
$template->assign_block_vars_array('navlinks', $navlinks_parents);
$template->assign_block_vars('navlinks', $navlinks);
@@ -884,7 +886,8 @@ function get_forum_parents(&$forum_data)
*/
function get_moderators(&$forum_moderators, $forum_id = false)
{
- global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth;
+ global $db, $phpbb_root_path, $phpEx, $user, $auth;
+ global $phpbb_container;
$forum_id_ary = array();
@@ -920,6 +923,9 @@ function get_moderators(&$forum_moderators, $forum_id = false)
'WHERE' => 'm.display_on_index = 1',
);
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
// We query every forum here because for caching we should not have any parameter.
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query($sql, 3600);
@@ -939,7 +945,7 @@ function get_moderators(&$forum_moderators, $forum_id = false)
}
else
{
- $group_name = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']);
+ $group_name = $group_helper->get_name($row['group_name']);
if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile'))
{
@@ -996,8 +1002,6 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold
{
global $user, $config;
- $folder = $folder_new = '';
-
if ($topic_row['topic_status'] == ITEM_MOVED)
{
$topic_type = $user->lang['VIEW_TOPIC_MOVED'];
@@ -1072,7 +1076,7 @@ function display_custom_bbcodes()
global $db, $template, $user, $phpbb_dispatcher;
// Start counting from 22 for the bbcode ids (every bbcode takes two ids - opening/closing)
- $num_predefined_bbcodes = 22;
+ $num_predefined_bbcodes = NUM_PREDEFINED_BBCODES;
$sql_ary = array(
'SELECT' => 'b.bbcode_id, b.bbcode_tag, b.bbcode_helpline',
@@ -1143,46 +1147,27 @@ function display_custom_bbcodes()
/**
* Display reasons
+*
+* @deprecated 3.2.0-dev
*/
function display_reasons($reason_id = 0)
{
- global $db, $user, $template;
+ global $phpbb_container;
- $sql = 'SELECT *
- FROM ' . REPORTS_REASONS_TABLE . '
- ORDER BY reason_order ASC';
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- // If the reason is defined within the language file, we will use the localized version, else just use the database entry...
- if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]))
- {
- $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])];
- $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])];
- }
-
- $template->assign_block_vars('reason', array(
- 'ID' => $row['reason_id'],
- 'TITLE' => $row['reason_title'],
- 'DESCRIPTION' => $row['reason_description'],
- 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false)
- );
- }
- $db->sql_freeresult($result);
+ $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id);
}
/**
* Display user activity (action forum/topic)
*/
-function display_user_activity(&$userdata)
+function display_user_activity(&$userdata_ary)
{
global $auth, $template, $db, $user;
global $phpbb_root_path, $phpEx;
global $phpbb_container, $phpbb_dispatcher;
// Do not display user activity for users having more than 5000 posts...
- if ($userdata['user_posts'] > 5000)
+ if ($userdata_ary['user_posts'] > 5000)
{
return;
}
@@ -1203,12 +1188,13 @@ function display_user_activity(&$userdata)
$active_f_row = $active_t_row = array();
if (!empty($forum_ary))
{
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
// Obtain active forum
$sql = 'SELECT forum_id, COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . '
- WHERE poster_id = ' . $userdata['user_id'] . '
+ WHERE poster_id = ' . $userdata_ary['user_id'] . '
AND post_postcount = 1
AND ' . $phpbb_content_visibility->get_forums_visibility_sql('post', $forum_ary) . '
GROUP BY forum_id
@@ -1230,7 +1216,7 @@ function display_user_activity(&$userdata)
// Obtain active topic
$sql = 'SELECT topic_id, COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . '
- WHERE poster_id = ' . $userdata['user_id'] . '
+ WHERE poster_id = ' . $userdata_ary['user_id'] . '
AND post_postcount = 1
AND ' . $phpbb_content_visibility->get_forums_visibility_sql('post', $forum_ary) . '
GROUP BY topic_id
@@ -1250,6 +1236,7 @@ function display_user_activity(&$userdata)
}
}
+ $userdata = $userdata_ary;
/**
* Alter list of forums and topics to display as active
*
@@ -1261,9 +1248,11 @@ function display_user_activity(&$userdata)
*/
$vars = array('userdata', 'active_f_row', 'active_t_row');
extract($phpbb_dispatcher->trigger_event('core.display_user_activity_modify_actives', compact($vars)));
+ $userdata_ary = $userdata;
+ unset($userdata);
- $userdata['active_t_row'] = $active_t_row;
- $userdata['active_f_row'] = $active_f_row;
+ $userdata_ary['active_t_row'] = $active_t_row;
+ $userdata_ary['active_f_row'] = $active_f_row;
$active_f_name = $active_f_id = $active_f_count = $active_f_pct = '';
if (!empty($active_f_row['num_posts']))
@@ -1271,7 +1260,7 @@ function display_user_activity(&$userdata)
$active_f_name = $active_f_row['forum_name'];
$active_f_id = $active_f_row['forum_id'];
$active_f_count = $active_f_row['num_posts'];
- $active_f_pct = ($userdata['user_posts']) ? ($active_f_count / $userdata['user_posts']) * 100 : 0;
+ $active_f_pct = ($userdata_ary['user_posts']) ? ($active_f_count / $userdata_ary['user_posts']) * 100 : 0;
}
$active_t_name = $active_t_id = $active_t_count = $active_t_pct = '';
@@ -1280,10 +1269,10 @@ function display_user_activity(&$userdata)
$active_t_name = $active_t_row['topic_title'];
$active_t_id = $active_t_row['topic_id'];
$active_t_count = $active_t_row['num_posts'];
- $active_t_pct = ($userdata['user_posts']) ? ($active_t_count / $userdata['user_posts']) * 100 : 0;
+ $active_t_pct = ($userdata_ary['user_posts']) ? ($active_t_count / $userdata_ary['user_posts']) * 100 : 0;
}
- $l_active_pct = ($userdata['user_id'] != ANONYMOUS && $userdata['user_id'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE'];
+ $l_active_pct = ($userdata_ary['user_id'] != ANONYMOUS && $userdata_ary['user_id'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE'];
$template->assign_vars(array(
'ACTIVE_FORUM' => $active_f_name,
@@ -1303,7 +1292,7 @@ function display_user_activity(&$userdata)
*/
function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $notify_status = 'unset', $start = 0, $item_title = '')
{
- global $template, $db, $user, $phpEx, $start, $phpbb_root_path;
+ global $db, $user, $phpEx, $start, $phpbb_root_path;
global $request;
$table_sql = ($mode == 'forum') ? FORUMS_WATCH_TABLE : TOPICS_WATCH_TABLE;
@@ -1334,8 +1323,8 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
{
if (isset($_GET['unwatch']))
{
- $uid = request_var('uid', 0);
- $token = request_var('hash', '');
+ $uid = $request->variable('uid', 0);
+ $token = $request->variable('hash', '');
if ($token && check_link_hash($token, "{$mode}_$match_id") || confirm_box(true))
{
@@ -1408,8 +1397,8 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
{
if (isset($_GET['watch']))
{
- $uid = request_var('uid', 0);
- $token = request_var('hash', '');
+ $uid = $request->variable('uid', 0);
+ $token = $request->variable('hash', '');
if ($token && check_link_hash($token, "{$mode}_$match_id") || confirm_box(true))
{
diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php
index c571de579e..d61ce3d098 100644
--- a/phpBB/includes/functions_download.php
+++ b/phpBB/includes/functions_download.php
@@ -124,7 +124,7 @@ function wrap_img_in_html($src, $title)
*/
function send_file_to_browser($attachment, $upload_dir, $category)
{
- global $user, $db, $config, $phpbb_root_path;
+ global $user, $db, $phpbb_root_path, $request;
$filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename'];
@@ -186,7 +186,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)
header('X-Content-Type-Options: nosniff');
}
- if ($category == ATTACHMENT_CATEGORY_FLASH && request_var('view', 0) === 1)
+ if ($category == ATTACHMENT_CATEGORY_FLASH && $request->variable('view', 0) === 1)
{
// We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline
header('Content-Disposition: inline');
@@ -254,11 +254,21 @@ function send_file_to_browser($attachment, $upload_dir, $category)
send_status_line(206, 'Partial Content');
header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
header('Content-Length: ' . $range['bytes_requested']);
- }
- while (!feof($fp))
+ // First read chunks
+ while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192)
+ {
+ echo fread($fp, 8192);
+ }
+ // Then, read the remainder
+ echo fread($fp, $range['bytes_requested'] % 8192);
+ }
+ else
{
- echo fread($fp, 8192);
+ while (!feof($fp))
+ {
+ echo fread($fp, 8192);
+ }
}
fclose($fp);
}
@@ -529,6 +539,9 @@ function phpbb_find_range_request()
*/
function phpbb_parse_range_request($request_array, $filesize)
{
+ $first_byte_pos = -1;
+ $last_byte_pos = -1;
+
// Go through all ranges
foreach ($request_array as $range_string)
{
@@ -540,62 +553,61 @@ function phpbb_parse_range_request($request_array, $filesize)
continue;
}
+ // Substitute defaults
if ($range[0] === '')
{
- // Return last $range[1] bytes.
-
- if (!$range[1])
- {
- continue;
- }
+ $range[0] = 0;
+ }
- if ($range[1] >= $filesize)
- {
- return false;
- }
+ if ($range[1] === '')
+ {
+ $range[1] = $filesize - 1;
+ }
- $first_byte_pos = $filesize - (int) $range[1];
- $last_byte_pos = $filesize - 1;
+ if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
+ {
+ // We only support contiguous ranges, no multipart stuff :(
+ return false;
}
- else
+
+ if ($range[1] && $range[1] < $range[0])
{
- // Return bytes from $range[0] to $range[1]
+ // The requested range contains 0 bytes.
+ continue;
+ }
+ // Return bytes from $range[0] to $range[1]
+ if ($first_byte_pos < 0)
+ {
$first_byte_pos = (int) $range[0];
- $last_byte_pos = (int) $range[1];
-
- if ($last_byte_pos && $last_byte_pos < $first_byte_pos)
- {
- // The requested range contains 0 bytes.
- continue;
- }
+ }
- if ($first_byte_pos >= $filesize)
- {
- // Requested range not satisfiable
- return false;
- }
+ $last_byte_pos = (int) $range[1];
- // Adjust last-byte-pos if it is absent or greater than the content.
- if ($range[1] === '' || $last_byte_pos >= $filesize)
- {
- $last_byte_pos = $filesize - 1;
- }
+ if ($first_byte_pos >= $filesize)
+ {
+ // Requested range not satisfiable
+ return false;
}
- // We currently do not support range requests that end before the end of the file
- if ($last_byte_pos != $filesize - 1)
+ // Adjust last-byte-pos if it is absent or greater than the content.
+ if ($range[1] === '' || $last_byte_pos >= $filesize)
{
- continue;
+ $last_byte_pos = $filesize - 1;
}
+ }
- return array(
- 'byte_pos_start' => $first_byte_pos,
- 'byte_pos_end' => $last_byte_pos,
- 'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
- 'bytes_total' => $filesize,
- );
+ if ($first_byte_pos < 0 || $last_byte_pos < 0)
+ {
+ return false;
}
+
+ return array(
+ 'byte_pos_start' => $first_byte_pos,
+ 'byte_pos_end' => $last_byte_pos,
+ 'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
+ 'bytes_total' => $filesize,
+ );
}
/**
diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php
deleted file mode 100644
index 28cc603bdb..0000000000
--- a/phpBB/includes/functions_install.php
+++ /dev/null
@@ -1,545 +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.
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Returns an array of available DBMS with some data, if a DBMS is specified it will only
-* return data for that DBMS and will load its extension if necessary.
-*/
-function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
-{
- global $lang;
- $available_dbms = array(
- // Note: php 5.5 alpha 2 deprecated mysql.
- // Keep mysqli before mysql in this list.
- 'mysqli' => array(
- 'LABEL' => 'MySQL with MySQLi Extension',
- 'SCHEMA' => 'mysql_41',
- 'MODULE' => 'mysqli',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\mysqli',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mysql' => array(
- 'LABEL' => 'MySQL',
- 'SCHEMA' => 'mysql',
- 'MODULE' => 'mysql',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\mysql',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mssql' => array(
- 'LABEL' => 'MS SQL Server 2000+',
- 'SCHEMA' => 'mssql',
- 'MODULE' => 'mssql',
- 'DELIM' => 'GO',
- 'DRIVER' => 'phpbb\db\driver\mssql',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mssql_odbc'=> array(
- 'LABEL' => 'MS SQL Server [ ODBC ]',
- 'SCHEMA' => 'mssql',
- 'MODULE' => 'odbc',
- 'DELIM' => 'GO',
- 'DRIVER' => 'phpbb\db\driver\mssql_odbc',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mssqlnative' => array(
- 'LABEL' => 'MS SQL Server 2005+ [ Native ]',
- 'SCHEMA' => 'mssql',
- 'MODULE' => 'sqlsrv',
- 'DELIM' => 'GO',
- 'DRIVER' => 'phpbb\db\driver\mssqlnative',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- 'oracle' => array(
- 'LABEL' => 'Oracle',
- 'SCHEMA' => 'oracle',
- 'MODULE' => 'oci8',
- 'DELIM' => '/',
- 'DRIVER' => 'phpbb\db\driver\oracle',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- 'postgres' => array(
- 'LABEL' => 'PostgreSQL 8.3+',
- 'SCHEMA' => 'postgres',
- 'MODULE' => 'pgsql',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\postgres',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'sqlite' => array(
- 'LABEL' => 'SQLite',
- 'SCHEMA' => 'sqlite',
- 'MODULE' => 'sqlite',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\sqlite',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- 'sqlite3' => array(
- 'LABEL' => 'SQLite3',
- 'SCHEMA' => 'sqlite',
- 'MODULE' => 'sqlite3',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\sqlite3',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- );
-
- if ($dbms)
- {
- if (isset($available_dbms[$dbms]))
- {
- $available_dbms = array($dbms => $available_dbms[$dbms]);
- }
- else
- {
- return array();
- }
- }
-
- // now perform some checks whether they are really available
- foreach ($available_dbms as $db_name => $db_ary)
- {
- if ($only_20x_options && !$db_ary['2.0.x'])
- {
- if ($return_unavailable)
- {
- $available_dbms[$db_name]['AVAILABLE'] = false;
- }
- else
- {
- unset($available_dbms[$db_name]);
- }
- continue;
- }
-
- $dll = $db_ary['MODULE'];
-
- if (!@extension_loaded($dll))
- {
- if ($return_unavailable)
- {
- $available_dbms[$db_name]['AVAILABLE'] = false;
- }
- else
- {
- unset($available_dbms[$db_name]);
- }
- continue;
- }
- $any_db_support = true;
- }
-
- if ($return_unavailable)
- {
- $available_dbms['ANY_DB_SUPPORT'] = $any_db_support;
- }
- return $available_dbms;
-}
-
-/**
-* Generate the drop down of available database options
-*/
-function dbms_select($default = '', $only_20x_options = false)
-{
- global $lang;
-
- $available_dbms = get_available_dbms(false, false, $only_20x_options);
- $dbms_options = '';
- foreach ($available_dbms as $dbms_name => $details)
- {
- $selected = ($dbms_name == $default) ? ' selected="selected"' : '';
- $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>';
- }
- return $dbms_options;
-}
-
-/**
-* Get tables of a database
-*
-* @deprecated
-*/
-function get_tables(&$db)
-{
- $db_tools = new \phpbb\db\tools($db);
-
- return $db_tools->sql_list_tables();
-}
-
-/**
-* Used to test whether we are able to connect to the database the user has specified
-* and identify any problems (eg there are already tables with the names we want to use
-* @param array $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()}
-* necessary extensions should be loaded already
-*/
-function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true)
-{
- global $phpbb_root_path, $phpEx, $config, $lang;
-
- $dbms = $dbms_details['DRIVER'];
-
- // Instantiate it and set return on error true
- $db = new $dbms();
- $db->sql_return_on_error(true);
-
- // Check that we actually have a database name before going any further.....
- if ($dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite' && $dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite3' && $dbms_details['DRIVER'] != 'phpbb\db\driver\oracle' && $dbname === '')
- {
- $error[] = $lang['INST_ERR_DB_NO_NAME'];
- return false;
- }
-
- // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
- if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0)
- {
- $error[] = $lang['INST_ERR_DB_FORUM_PATH'];
- return false;
- }
-
- // Check the prefix length to ensure that index names are not too long and does not contain invalid characters
- switch ($dbms_details['DRIVER'])
- {
- case 'phpbb\db\driver\mysql':
- case 'phpbb\db\driver\mysqli':
- if (strspn($table_prefix, '-./\\') !== 0)
- {
- $error[] = $lang['INST_ERR_PREFIX_INVALID'];
- return false;
- }
-
- // no break;
-
- case 'phpbb\db\driver\postgres':
- $prefix_length = 36;
- break;
-
- case 'phpbb\db\driver\mssql':
- case 'phpbb\db\driver\mssql_odbc':
- case 'phpbb\db\driver\mssqlnative':
- $prefix_length = 90;
- break;
-
- case 'phpbb\db\driver\sqlite':
- case 'phpbb\db\driver\sqlite3':
- $prefix_length = 200;
- break;
-
- case 'phpbb\db\driver\oracle':
- $prefix_length = 6;
- break;
- }
-
- if (strlen($table_prefix) > $prefix_length)
- {
- $error[] = sprintf($lang['INST_ERR_PREFIX_TOO_LONG'], $prefix_length);
- return false;
- }
-
- // Try and connect ...
- if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true)))
- {
- $db_error = $db->sql_error();
- $error[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? utf8_convert_message($db_error['message']) : $lang['INST_ERR_DB_NO_ERROR']);
- }
- else
- {
- // Likely matches for an existing phpBB installation
- if (!$prefix_may_exist)
- {
- $temp_prefix = strtolower($table_prefix);
- $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users');
-
- $tables = get_tables($db);
- $tables = array_map('strtolower', $tables);
- $table_intersect = array_intersect($tables, $table_ary);
-
- if (sizeof($table_intersect))
- {
- $error[] = $lang['INST_ERR_PREFIX'];
- }
- }
-
- // Make sure that the user has selected a sensible DBAL for the DBMS actually installed
- switch ($dbms_details['DRIVER'])
- {
- case 'phpbb\db\driver\mysqli':
- if (version_compare(mysqli_get_server_info($db->get_db_connect_id()), '4.1.3', '<'))
- {
- $error[] = $lang['INST_ERR_DB_NO_MYSQLI'];
- }
- break;
-
- case 'phpbb\db\driver\sqlite':
- if (version_compare(sqlite_libversion(), '2.8.2', '<'))
- {
- $error[] = $lang['INST_ERR_DB_NO_SQLITE'];
- }
- break;
-
- case 'phpbb\db\driver\sqlite3':
- $version = \SQLite3::version();
- if (version_compare($version['versionString'], '3.6.15', '<'))
- {
- $error[] = $lang['INST_ERR_DB_NO_SQLITE3'];
- }
- break;
-
- case 'phpbb\db\driver\oracle':
- if ($unicode_check)
- {
- $sql = "SELECT *
- FROM NLS_DATABASE_PARAMETERS
- WHERE PARAMETER = 'NLS_RDBMS_VERSION'
- OR PARAMETER = 'NLS_CHARACTERSET'";
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $stats[$row['parameter']] = $row['value'];
- }
- $db->sql_freeresult($result);
-
- if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
- {
- $error[] = $lang['INST_ERR_DB_NO_ORACLE'];
- }
- }
- break;
-
- case 'phpbb\db\driver\postgres':
- if ($unicode_check)
- {
- $sql = "SHOW server_encoding;";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
- {
- $error[] = $lang['INST_ERR_DB_NO_POSTGRES'];
- }
- }
- break;
- }
-
- }
-
- if ($error_connect && (!isset($error) || !sizeof($error)))
- {
- return true;
- }
- return false;
-}
-
-/**
-* Removes "/* style" as well as "# style" comments from $input.
-*
-* @param string $input Input string
-*
-* @return string Input string with comments removed
-*/
-function phpbb_remove_comments($input)
-{
- // Remove /* */ comments (http://ostermiller.org/findcomment.html)
- $input = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $input);
-
- // Remove # style comments
- $input = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $input));
-
- return $input;
-}
-
-/**
-* split_sql_file will split an uploaded sql file into single sql statements.
-* Note: expects trim() to have already been run on $sql.
-*/
-function split_sql_file($sql, $delimiter)
-{
- $sql = str_replace("\r" , '', $sql);
- $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
-
- $data = array_map('trim', $data);
-
- // The empty case
- $end_data = end($data);
-
- if (empty($end_data))
- {
- unset($data[key($data)]);
- }
-
- return $data;
-}
-
-/**
-* For replacing {L_*} strings with preg_replace_callback
-*/
-function adjust_language_keys_callback($matches)
-{
- if (!empty($matches[1]))
- {
- global $lang, $db;
-
- return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]);
- }
-}
-
-/**
-* Creates the output to be stored in a phpBB config.php file
-*
-* @param array $data Array containing the database connection information
-* @param string $dbms The name of the DBAL class to use
-* @param bool $debug If the debug constants should be enabled by default or not
-* @param bool $debug_container If the container should be compiled on
-* every page load or not
-* @param bool $debug_test If the DEBUG_TEST constant should be added
-* NOTE: Only for use within the testing framework
-*
-* @return string The output to write to the file
-*/
-function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_container = false, $debug_test = false)
-{
- $config_data = "<?php\n";
- $config_data .= "// phpBB 3.1.x auto-generated configuration file\n// Do not change anything in this file!\n";
-
- $config_data_array = array(
- 'dbms' => $dbms,
- 'dbhost' => $data['dbhost'],
- 'dbport' => $data['dbport'],
- 'dbname' => $data['dbname'],
- 'dbuser' => $data['dbuser'],
- 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']),
- 'table_prefix' => $data['table_prefix'],
-
- 'phpbb_adm_relative_path' => 'adm/',
-
- 'acm_type' => 'phpbb\cache\driver\file',
- );
-
- foreach ($config_data_array as $key => $value)
- {
- $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n";
- }
-
- $config_data .= "\n@define('PHPBB_INSTALLED', true);\n";
- $config_data .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n";
-
- if ($debug)
- {
- $config_data .= "@define('DEBUG', true);\n";
- }
- else
- {
- $config_data .= "// @define('DEBUG', true);\n";
- }
-
- if ($debug_container)
- {
- $config_data .= "@define('DEBUG_CONTAINER', true);\n";
- }
- else
- {
- $config_data .= "// @define('DEBUG_CONTAINER', true);\n";
- }
-
- if ($debug_test)
- {
- $config_data .= "@define('DEBUG_TEST', true);\n";
- }
-
- return $config_data;
-}
-
-/**
-* Check whether a file should be ignored on update
-*
-* We ignore new files in some circumstances:
-* 1. The file is a language file, but the language is not installed
-* 2. The file is a style file, but the style is not installed
-* 3. The file is a style language file, but the language is not installed
-*
-* @param string $phpbb_root_path phpBB root path
-* @param string $file File including path from phpbb root
-* @return bool Should we ignore the new file or add it to the board?
-*/
-function phpbb_ignore_new_file_on_update($phpbb_root_path, $file)
-{
- $ignore_new_file = false;
-
- // We ignore new files in some circumstances:
- // 1. The file is a language file, but the language is not installed
- if (!$ignore_new_file && strpos($file, 'language/') === 0)
- {
- list($language_dir, $language_iso) = explode('/', $file);
- $ignore_new_file = !file_exists($phpbb_root_path . $language_dir . '/' . $language_iso);
- }
-
- // 2. The file is a style file, but the style is not installed
- if (!$ignore_new_file && strpos($file, 'styles/') === 0)
- {
- list($styles_dir, $style_name) = explode('/', $file);
- $ignore_new_file = !file_exists($phpbb_root_path . $styles_dir . '/' . $style_name);
- }
-
- // 3. The file is a style language file, but the language is not installed
- if (!$ignore_new_file && strpos($file, 'styles/') === 0)
- {
- $dirs = explode('/', $file);
- if (sizeof($dirs) >= 5)
- {
- list($styles_dir, $style_name, $template_component, $language_iso) = explode('/', $file);
- if ($template_component == 'theme' && $language_iso !== 'images')
- {
- $ignore_new_file = !file_exists($phpbb_root_path . 'language/' . $language_iso);
- }
- }
- }
-
- return $ignore_new_file;
-}
-
-/**
-* Check whether phpBB is installed.
-*
-* @param string $phpbb_root_path Path to the phpBB board root.
-* @param string $php_ext PHP file extension.
-*
-* @return bool Returns true if phpBB is installed.
-*/
-function phpbb_check_installation_exists($phpbb_root_path, $php_ext)
-{
- // Try opening config file
- if (file_exists($phpbb_root_path . 'config.' . $php_ext))
- {
- include($phpbb_root_path . 'config.' . $php_ext);
- }
-
- return defined('PHPBB_INSTALLED');
-}
diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php
index bd2e9e93ac..a38888a861 100644
--- a/phpBB/includes/functions_jabber.php
+++ b/phpBB/includes/functions_jabber.php
@@ -87,8 +87,7 @@ class jabber
*/
static public function can_use_ssl()
{
- // Will not work with PHP >= 5.2.1 or < 5.2.3RC2 until timeout problem with ssl hasn't been fixed (http://bugs.php.net/41236)
- return ((version_compare(PHP_VERSION, '5.2.1', '<') || version_compare(PHP_VERSION, '5.2.3RC2', '>=')) && @extension_loaded('openssl')) ? true : false;
+ return @extension_loaded('openssl');
}
/**
diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php
index 1e08864bdc..dfe3fefbd0 100644
--- a/phpBB/includes/functions_mcp.php
+++ b/phpBB/includes/functions_mcp.php
@@ -301,6 +301,7 @@ function phpbb_get_forum_data($forum_id, $acl_list = 'f_list', $read_tracking =
WHERE " . $db->sql_in_set('f.forum_id', $forum_id);
$result = $db->sql_query($sql);
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
while ($row = $db->sql_fetchrow($result))
@@ -366,12 +367,12 @@ function phpbb_get_pm_data($pm_ids)
* $mode reports and reports_closed: the $where parameters uses aliases p for posts table and r for report table
* $mode unapproved_posts: the $where parameters uses aliases p for posts table and t for topic table
*/
-function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, &$sort_order_sql, &$total, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE')
+function phpbb_mcp_sorting($mode, &$sort_days_val, &$sort_key_val, &$sort_dir_val, &$sort_by_sql_ary, &$sort_order_sql, &$total_val, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE')
{
- global $db, $user, $auth, $template, $phpbb_dispatcher;
+ global $db, $user, $auth, $template, $request, $phpbb_dispatcher;
- $sort_days = request_var('st', 0);
- $min_time = ($sort_days) ? time() - ($sort_days * 86400) : 0;
+ $sort_days_val = $request->variable('st', 0);
+ $min_time = ($sort_days_val) ? time() - ($sort_days_val * 86400) : 0;
switch ($mode)
{
@@ -511,8 +512,8 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
break;
}
- $sort_key = request_var('sk', $default_key);
- $sort_dir = request_var('sd', $default_dir);
+ $sort_key_val = $request->variable('sk', $default_key);
+ $sort_dir_val = $request->variable('sd', $default_dir);
$sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
switch ($type)
@@ -521,41 +522,46 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
$limit_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'tt' => $user->lang['TOPIC_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'), 'tt' => 't.topic_time', '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' => 't.topic_title', 'v' => 't.topic_views');
+ $sort_by_sql_ary = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'tt' => 't.topic_time', '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' => 't.topic_title', 'v' => 't.topic_views');
$limit_time_sql = ($min_time) ? "AND t.topic_last_post_time >= $min_time" : '';
break;
case 'posts':
$limit_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 't' => array('p.post_time', 'p.post_id'), 's' => 'p.post_subject');
+ $sort_by_sql_ary = array('a' => 'u.username_clean', 't' => array('p.post_time', 'p.post_id'), 's' => 'p.post_subject');
$limit_time_sql = ($min_time) ? "AND p.post_time >= $min_time" : '';
break;
case 'reports':
$limit_days = array(0 => $user->lang['ALL_REPORTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => array('p.post_time', 'p.post_id'), 't' => 'r.report_time', 's' => 'p.post_subject');
+ $sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => array('p.post_time', 'p.post_id'), 't' => 'r.report_time', 's' => 'p.post_subject');
break;
case 'pm_reports':
$limit_days = array(0 => $user->lang['ALL_REPORTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => 'p.message_time', 't' => 'r.report_time', 's' => 'p.message_subject');
+ $sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => 'p.message_time', 't' => 'r.report_time', 's' => 'p.message_subject');
break;
case 'logs':
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']);
- $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation');
+ $sort_by_sql_ary = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation');
$limit_time_sql = ($min_time) ? "AND l.log_time >= $min_time" : '';
break;
}
// Default total to -1 to allow editing by the event
- $total = -1;
+ $total_val = -1;
+ $sort_by_sql = $sort_by_sql_ary;
+ $sort_days = $sort_days_val;
+ $sort_dir = $sort_dir_val;
+ $sort_key = $sort_key_val;
+ $total = $total_val;
/**
* This event allows you to control the SQL query used to get the total number
* of reports the user can access.
@@ -602,25 +608,35 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
'where_sql',
);
extract($phpbb_dispatcher->trigger_event('core.mcp_sorting_query_before', compact($vars)));
-
- if (!isset($sort_by_sql[$sort_key]))
+ $sort_by_sql_ary = $sort_by_sql;
+ $sort_days_val = $sort_days;
+ $sort_key_val = $sort_key;
+ $sort_dir_val = $sort_dir;
+ $total_val = $total;
+ unset($sort_by_sql);
+ unset($sort_days);
+ unset($sort_key);
+ unset($sort_dir);
+ unset($total);
+
+ if (!isset($sort_by_sql_ary[$sort_key_val]))
{
- $sort_key = $default_key;
+ $sort_key_val = $default_key;
}
- $direction = ($sort_dir == 'd') ? 'DESC' : 'ASC';
+ $direction = ($sort_dir_val == 'd') ? 'DESC' : 'ASC';
- if (is_array($sort_by_sql[$sort_key]))
+ if (is_array($sort_by_sql_ary[$sort_key_val]))
{
- $sort_order_sql = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction;
+ $sort_order_sql = implode(' ' . $direction . ', ', $sort_by_sql_ary[$sort_key_val]) . ' ' . $direction;
}
else
{
- $sort_order_sql = $sort_by_sql[$sort_key] . ' ' . $direction;
+ $sort_order_sql = $sort_by_sql_ary[$sort_key_val] . ' ' . $direction;
}
$s_limit_days = $s_sort_key = $s_sort_dir = $sort_url = '';
- gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $sort_url);
+ gen_sort_selects($limit_days, $sort_by_text, $sort_days_val, $sort_key_val, $sort_dir_val, $s_limit_days, $s_sort_key, $s_sort_dir, $sort_url);
$template->assign_vars(array(
'S_SELECT_SORT_DIR' => $s_sort_dir,
@@ -628,15 +644,15 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
'S_SELECT_SORT_DAYS' => $s_limit_days)
);
- if (($sort_days && $mode != 'viewlogs') || in_array($mode, array('reports', 'unapproved_topics', 'unapproved_posts', 'deleted_topics', 'deleted_posts')) || $where_sql != 'WHERE')
+ if (($sort_days_val && $mode != 'viewlogs') || in_array($mode, array('reports', 'unapproved_topics', 'unapproved_posts', 'deleted_topics', 'deleted_posts')) || $where_sql != 'WHERE')
{
$result = $db->sql_query($sql);
- $total = (int) $db->sql_fetchfield('total');
+ $total_val = (int) $db->sql_fetchfield('total');
$db->sql_freeresult($result);
}
- else if ($total < -1)
+ else if ($total_val < -1)
{
- $total = -1;
+ $total_val = -1;
}
}
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index 9b3ca14101..0056cbca35 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -33,8 +33,6 @@ class messenger
/** @var \phpbb\template\template */
protected $template;
- var $eol = "\n";
-
/**
* Constructor
*/
@@ -44,10 +42,6 @@ class messenger
$this->use_queue = (!$config['email_package_size']) ? false : $use_queue;
$this->subject = '';
-
- // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac)
- $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL;
- $this->eol = (!$this->eol) ? "\n" : $this->eol;
}
/**
@@ -212,7 +206,7 @@ class messenger
*/
function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '')
{
- global $config, $phpbb_root_path, $phpEx, $user, $phpbb_extension_manager;
+ global $config, $phpbb_root_path, $user;
$template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix;
@@ -379,7 +373,7 @@ class messenger
*/
function error($type, $msg)
{
- global $user, $phpEx, $phpbb_root_path, $config, $request;
+ global $user, $config, $request, $phpbb_log;
// Session doesn't exist, create it
if (!isset($user->session_id) || $user->session_id === '')
@@ -389,7 +383,6 @@ class messenger
$calling_page = htmlspecialchars_decode($request->server('PHP_SELF'));
- $message = '';
switch ($type)
{
case 'EMAIL':
@@ -402,7 +395,7 @@ class messenger
}
$message .= '<br /><em>' . htmlspecialchars($calling_page) . '</em><br /><br />' . $msg . '<br />';
- add_log('critical', 'LOG_ERROR_' . $type, $message);
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_' . $type, false, array($message));
}
/**
@@ -483,7 +476,7 @@ class messenger
*/
function msg_email()
{
- global $config, $user;
+ global $config;
if (empty($config['email_enable']))
{
@@ -521,7 +514,7 @@ class messenger
$this->from = $board_contact;
}
- $encode_eol = ($config['smtp_delivery']) ? "\r\n" : $this->eol;
+ $encode_eol = ($config['smtp_delivery']) ? "\r\n" : PHP_EOL;
// Build to, cc and bcc strings
$to = $cc = $bcc = '';
@@ -553,7 +546,7 @@ class messenger
}
else
{
- $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg);
+ $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, PHP_EOL, $err_msg);
}
if (!$result)
@@ -581,7 +574,7 @@ class messenger
*/
function msg_jabber()
{
- global $config, $db, $user, $phpbb_root_path, $phpEx;
+ global $config, $user, $phpbb_root_path, $phpEx;
if (empty($config['jab_enable']) || empty($config['jab_host']) || empty($config['jab_username']) || empty($config['jab_password']))
{
@@ -653,14 +646,35 @@ class messenger
*/
protected function setup_template()
{
- global $config, $phpbb_path_helper, $user, $phpbb_extension_manager;
+ global $phpbb_container;
if ($this->template instanceof \phpbb\template\template)
{
return;
}
- $this->template = new \phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new \phpbb\template\context(), $phpbb_extension_manager);
+ $template_environment = new \phpbb\template\twig\environment(
+ $phpbb_container->get('config'),
+ $phpbb_container->get('filesystem'),
+ $phpbb_container->get('path_helper'),
+ $phpbb_container->getParameter('core.template.cache_path'),
+ $phpbb_container->get('ext.manager'),
+ new \phpbb\template\twig\loader(
+ $phpbb_container->get('filesystem')
+ )
+ );
+ $template_environment->setLexer($phpbb_container->get('template.twig.lexer'));
+
+ $this->template = new \phpbb\template\twig\twig(
+ $phpbb_container->get('path_helper'),
+ $phpbb_container->get('config'),
+ new \phpbb\template\context(),
+ $template_environment,
+ $phpbb_container->getParameter('core.template.cache_path'),
+ $phpbb_container->get('user'),
+ $phpbb_container->get('template.twig.extensions.collection'),
+ $phpbb_container->get('ext.manager')
+ );
}
/**
@@ -686,18 +700,20 @@ class queue
var $eol = "\n";
/**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
* constructor
*/
function queue()
{
- global $phpEx, $phpbb_root_path;
+ global $phpEx, $phpbb_root_path, $phpbb_filesystem, $phpbb_container;
$this->data = array();
- $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx";
-
- // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac)
- $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL;
- $this->eol = (!$this->eol) ? "\n" : $this->eol;
+ $this->cache_file = $phpbb_container->getParameter('core.cache_dir') . "queue.$phpEx";
+ $this->filesystem = $phpbb_filesystem;
}
/**
@@ -724,7 +740,7 @@ class queue
*/
function process()
{
- global $db, $config, $phpEx, $phpbb_root_path, $user;
+ global $config, $phpEx, $phpbb_root_path, $user;
$lock = new \phpbb\lock\flock($this->cache_file);
$lock->acquire();
@@ -735,14 +751,14 @@ class queue
{
if (!$have_cache_file)
{
- set_config('last_queue_run', time(), true);
+ $config->set('last_queue_run', time(), false);
}
$lock->release();
return;
}
- set_config('last_queue_run', time(), true);
+ $config->set('last_queue_run', time(), false);
include($this->cache_file);
@@ -830,7 +846,7 @@ class queue
}
else
{
- $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg);
+ $result = phpbb_mail($to, $subject, $msg, $headers, PHP_EOL, $err_msg);
}
if (!$result)
@@ -888,7 +904,14 @@ class queue
@opcache_invalidate($this->cache_file);
}
- phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
+ try
+ {
+ $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
}
}
@@ -935,7 +958,14 @@ class queue
@opcache_invalidate($this->cache_file);
}
- phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
+ try
+ {
+ $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
$this->data = array();
}
@@ -1263,8 +1293,6 @@ class smtp_class
{
global $user;
- $err_msg = '';
-
// Here we try to determine the *real* hostname (reverse DNS entry preferrably)
$local_host = $user->host;
@@ -1299,7 +1327,7 @@ class smtp_class
$this->server_send("QUIT");
fclose($this->socket);
- $result = $this->pop_before_smtp($hostname, $username, $password);
+ $this->pop_before_smtp($hostname, $username, $password);
$username = $password = $default_auth_method = '';
// We need to close the previous session, else the server is not
diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php
index 90d59cfd1e..7a1991d69a 100644
--- a/phpBB/includes/functions_module.php
+++ b/phpBB/includes/functions_module.php
@@ -82,8 +82,8 @@ class p_master
*/
function list_modules($p_class)
{
- global $auth, $db, $user, $cache;
- global $config, $phpbb_root_path, $phpEx, $phpbb_dispatcher;
+ global $db, $user, $cache;
+ global $phpbb_dispatcher;
// Sanitise for future path use, it's escaped as appropriate for queries
$this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class));
@@ -480,13 +480,15 @@ class p_master
*/
function set_active($id = false, $mode = false)
{
+ global $request;
+
$icat = false;
$this->active_module = false;
- if (request_var('icat', ''))
+ if ($request->variable('icat', ''))
{
$icat = $id;
- $id = request_var('icat', '');
+ $id = $request->variable('icat', '');
}
// Restore the backslashes in class names
@@ -553,10 +555,10 @@ class p_master
*/
function load_active($mode = false, $module_url = false, $execute_module = true)
{
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user, $template;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user, $template, $request;
$module_path = $this->include_path . $this->p_class;
- $icat = request_var('icat', '');
+ $icat = $request->variable('icat', '');
if ($this->active_module === false)
{
@@ -727,8 +729,6 @@ class p_master
*/
function get_parents($parent_id, $left_id, $right_id, &$all_parents)
{
- global $db;
-
$parents = array();
if ($parent_id > 0)
@@ -820,7 +820,7 @@ class p_master
// Make sure the module_url has a question mark set, effectively determining the delimiter to use
$delim = (strpos($module_url, '?') === false) ? '?' : '&amp;';
- $current_padding = $current_depth = 0;
+ $current_depth = 0;
$linear_offset = 'l_block1';
$tabular_offset = 't_block2';
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index 4a4d2de0fe..3a2004396c 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -24,12 +24,13 @@ if (!defined('IN_PHPBB'))
*/
function generate_smilies($mode, $forum_id)
{
- global $db, $user, $config, $template, $phpbb_dispatcher;
+ global $db, $user, $config, $template, $phpbb_dispatcher, $request;
global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper;
- $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&amp;f=' . $forum_id);
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
- $start = request_var('start', 0);
+ $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&amp;f=' . $forum_id);
+ $start = $request->variable('start', 0);
if ($mode == 'window')
{
@@ -310,10 +311,10 @@ function posting_gen_topic_icons($mode, $icon_id)
{
$template->assign_block_vars('topic_icon', array(
'ICON_ID' => $id,
- 'ICON_NAME' => $data['img'],
'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'],
'ICON_WIDTH' => $data['width'],
'ICON_HEIGHT' => $data['height'],
+ 'ICON_ALT' => $data['alt'],
'S_CHECKED' => ($id == $icon_id) ? true : false,
'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '')
@@ -332,23 +333,20 @@ function posting_gen_topic_icons($mode, $icon_id)
*/
function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
{
- global $auth, $user, $template, $topic_type;
+ global $auth, $user, $template;
$toggle = false;
$topic_types = array(
- 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'),
- 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'),
- 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL')
+ 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'),
+ 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'),
+ 'announce_global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL')
);
$topic_type_array = array();
foreach ($topic_types as $auth_key => $topic_value)
{
- // We do not have a special post global announcement permission
- $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key;
-
if ($auth->acl_get('f_' . $auth_key, $forum_id))
{
$toggle = true;
@@ -378,8 +376,8 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
$template->assign_vars(array(
'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)),
- 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_get('f_announce', $forum_id)))
- );
+ 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_gets('f_announce', 'f_announce_global', $forum_id)),
+ ));
}
return $toggle;
@@ -393,183 +391,27 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
* Upload Attachment - filedata is generated here
* Uses upload class
*
+* @deprecated 3.2.0-a1 (To be removed: 3.4.0)
+*
* @param string $form_name The form name of the file upload input
* @param int $forum_id The id of the forum
* @param bool $local Whether the file is local or not
* @param string $local_storage The path to the local file
* @param bool $is_message Whether it is a PM or not
-* @param \filespec $local_filedata A filespec object created for the local file
-* @param \phpbb\mimetype\guesser $mimetype_guesser The mimetype guesser object if used
-* @param \phpbb\plupload\plupload $plupload The plupload object if one is being used
+* @param array $local_filedata A filespec object created for the local file
*
-* @return object filespec
+* @return array File data array
*/
-function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
+function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false)
{
- global $auth, $user, $config, $db, $cache;
- global $phpbb_root_path, $phpEx, $phpbb_dispatcher;
-
- $filedata = array(
- 'error' => array()
- );
-
- include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
- $upload = new fileupload();
-
- if ($config['check_attachment_content'] && isset($config['mime_triggers']))
- {
- $upload->set_disallowed_content(explode('|', $config['mime_triggers']));
- }
- else if (!$config['check_attachment_content'])
- {
- $upload->set_disallowed_content(array());
- }
-
- $filedata['post_attach'] = $local || $upload->is_valid($form_name);
-
- if (!$filedata['post_attach'])
- {
- $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND'];
- return $filedata;
- }
-
- $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id));
- $upload->set_allowed_extensions(array_keys($extensions['_allowed_']));
-
- $file = ($local) ? $upload->local_upload($local_storage, $local_filedata, $mimetype_guesser) : $upload->form_upload($form_name, $mimetype_guesser, $plupload);
-
- if ($file->init_error)
- {
- $filedata['post_attach'] = false;
- return $filedata;
- }
+ global $phpbb_container;
- // Whether the uploaded file is in the image category
- $is_image = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false;
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $file = $attachment_manager->upload($form_name, $forum_id, $local, $local_storage, $is_message, $local_filedata);
+ unset($attachment_manager);
- if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id))
- {
- // Check Image Size, if it is an image
- if ($is_image)
- {
- $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']);
- }
-
- // Admins and mods are allowed to exceed the allowed filesize
- if (!empty($extensions[$file->get('extension')]['max_filesize']))
- {
- $allowed_filesize = $extensions[$file->get('extension')]['max_filesize'];
- }
- else
- {
- $allowed_filesize = ($is_message) ? $config['max_filesize_pm'] : $config['max_filesize'];
- }
-
- $file->upload->set_max_filesize($allowed_filesize);
- }
-
- $file->clean_filename('unique', $user->data['user_id'] . '_');
-
- // Are we uploading an image *and* this image being within the image category?
- // Only then perform additional image checks.
- $file->move_file($config['upload_path'], false, !$is_image);
-
- // Do we have to create a thumbnail?
- $filedata['thumbnail'] = ($is_image && $config['img_create_thumbnail']) ? 1 : 0;
-
- if (sizeof($file->error))
- {
- $file->remove();
- $filedata['error'] = array_merge($filedata['error'], $file->error);
- $filedata['post_attach'] = false;
-
- return $filedata;
- }
-
- // Make sure the image category only holds valid images...
- if ($is_image && !$file->is_image())
- {
- $file->remove();
-
- if ($plupload && $plupload->is_active())
- {
- $plupload->emit_error(104, 'ATTACHED_IMAGE_NOT_IMAGE');
- }
-
- // If this error occurs a user tried to exploit an IE Bug by renaming extensions
- // Since the image category is displaying content inline we need to catch this.
- trigger_error($user->lang['ATTACHED_IMAGE_NOT_IMAGE']);
- }
-
- $filedata['filesize'] = $file->get('filesize');
- $filedata['mimetype'] = $file->get('mimetype');
- $filedata['extension'] = $file->get('extension');
- $filedata['physical_filename'] = $file->get('realname');
- $filedata['real_filename'] = $file->get('uploadname');
- $filedata['filetime'] = time();
-
- /**
- * Event to modify uploaded file before submit to the post
- *
- * @event core.modify_uploaded_file
- * @var array filedata Array containing uploaded file data
- * @var bool is_image Flag indicating if the file is an image
- * @since 3.1.0-RC3
- */
- $vars = array(
- 'filedata',
- 'is_image',
- );
- extract($phpbb_dispatcher->trigger_event('core.modify_uploaded_file', compact($vars)));
-
- // Check our complete quota
- if ($config['attachment_quota'])
- {
- if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota'])
- {
- $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
- $filedata['post_attach'] = false;
-
- $file->remove();
-
- return $filedata;
- }
- }
-
- // Check free disk space
- if ($free_space = @disk_free_space($phpbb_root_path . $config['upload_path']))
- {
- if ($free_space <= $file->get('filesize'))
- {
- if ($auth->acl_get('a_'))
- {
- $filedata['error'][] = $user->lang['ATTACH_DISK_FULL'];
- }
- else
- {
- $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
- }
- $filedata['post_attach'] = false;
-
- $file->remove();
-
- return $filedata;
- }
- }
-
- // Create Thumbnail
- if ($filedata['thumbnail'])
- {
- $source = $file->get('destination_file');
- $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname');
-
- if (!create_thumbnail($source, $destination, $file->get('mimetype')))
- {
- $filedata['thumbnail'] = 0;
- }
- }
-
- return $filedata;
+ return $file;
}
/**
@@ -668,7 +510,7 @@ function get_supported_image_types($type = false)
*/
function create_thumbnail($source, $destination, $mimetype)
{
- global $config;
+ global $config, $phpbb_filesystem;
$min_filesize = (int) $config['img_min_thumb_filesize'];
$img_filesize = (file_exists($source)) ? @filesize($source) : false;
@@ -820,7 +662,14 @@ function create_thumbnail($source, $destination, $mimetype)
return false;
}
- phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE);
+ try
+ {
+ $phpbb_filesystem->phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
return true;
}
@@ -984,7 +833,7 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms
foreach ($draft_rows as $draft)
{
$link_topic = $link_forum = $link_pm = false;
- $insert_url = $view_url = $title = '';
+ $view_url = $title = '';
if (isset($topic_rows[$draft['topic_id']])
&& (
@@ -1037,9 +886,10 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms
*/
function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true)
{
- global $user, $auth, $db, $template, $cache;
+ global $user, $auth, $db, $template;
global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
$sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC';
@@ -1113,11 +963,9 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
$db->sql_freeresult($result);
// Grab extensions
- $extensions = $attachments = array();
+ $attachments = array();
if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
{
- $extensions = $cache->obtain_attach_extensions($forum_id);
-
// Get attachments...
$sql = 'SELECT *
FROM ' . ATTACHMENTS_TABLE . '
@@ -1242,6 +1090,8 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
'MESSAGE' => $message,
'DECODED_MESSAGE' => $decoded_message,
'POST_ID' => $row['post_id'],
+ 'POST_TIME' => $row['post_time'],
+ 'USER_ID' => $row['user_id'],
'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=post_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '',
@@ -1306,7 +1156,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
*/
function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '')
{
- global $db, $user, $auth, $phpbb_container;
+ global $db, $user, $phpbb_container;
global $config, $phpEx, $phpbb_root_path;
// Specify our post mode
@@ -1353,6 +1203,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $
$db->sql_freeresult($result);
}
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
// (Soft) delete the post
@@ -1394,7 +1245,6 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $
if ($is_soft)
{
- $topic_row = array();
$phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason);
}
else
@@ -1564,10 +1414,12 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $
* Submit Post
* @todo Split up and create lightweight, simple API for this.
*/
-function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
+function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data_ary, $update_message = true, $update_search_index = true)
{
- global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;
+ global $db, $auth, $user, $config, $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request;
+ $poll = $poll_ary;
+ $data = $data_ary;
/**
* Modify the data for post submitting
*
@@ -1593,6 +1445,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'update_search_index',
);
extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
+ $poll_ary = $poll;
+ $data_ary = $data;
+ unset($poll);
+ unset($data);
// We do not handle erasing posts here
if ($mode == 'delete')
@@ -1600,9 +1456,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
return false;
}
- if (!empty($data['post_time']))
+ if (!empty($data_ary['post_time']))
{
- $current_time = $data['post_time'];
+ $current_time = $data_ary['post_time'];
}
else
{
@@ -1621,31 +1477,31 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
else if ($mode == 'edit')
{
- $post_mode = ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit'));
+ $post_mode = ($data_ary['topic_posts_approved'] + $data_ary['topic_posts_unapproved'] + $data_ary['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data_ary['topic_first_post_id'] == $data_ary['post_id']) ? 'edit_first_post' : (($data_ary['topic_last_post_id'] == $data_ary['post_id']) ? 'edit_last_post' : 'edit'));
}
// First of all make sure the subject and topic title are having the correct length.
// To achieve this without cutting off between special chars we convert to an array and then count the elements.
$subject = truncate_string($subject, 120);
- $data['topic_title'] = truncate_string($data['topic_title'], 120);
+ $data_ary['topic_title'] = truncate_string($data_ary['topic_title'], 120);
// Collect some basic information about which tables and which rows to update/insert
$sql_data = $topic_row = array();
- $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id'];
+ $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id'];
// Retrieve some additional information if not present
- if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false))
+ if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false))
{
$sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
WHERE t.topic_id = p.topic_id
- AND p.post_id = ' . $data['post_id'];
+ AND p.post_id = ' . $data_ary['post_id'];
$result = $db->sql_query($sql);
$topic_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- $data['topic_visibility'] = $topic_row['topic_visibility'];
- $data['post_visibility'] = $topic_row['post_visibility'];
+ $data_ary['topic_visibility'] = $topic_row['topic_visibility'];
+ $data_ary['post_visibility'] = $topic_row['post_visibility'];
}
// This variable indicates if the user is able to post or put into the queue
@@ -1653,7 +1509,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Check the permissions for post approval.
// Moderators must go through post approval like ordinary users.
- if (!$auth->acl_get('f_noapprove', $data['forum_id']))
+ if (!$auth->acl_get('f_noapprove', $data_ary['forum_id']))
{
// Post not approved, but in queue
$post_visibility = ITEM_UNAPPROVED;
@@ -1667,19 +1523,19 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
break;
}
}
- else if (isset($data['post_visibility']) && $data['post_visibility'] !== false)
+ else if (isset($data_ary['post_visibility']) && $data_ary['post_visibility'] !== false)
{
- $post_visibility = $data['post_visibility'];
+ $post_visibility = $data_ary['post_visibility'];
}
// MODs/Extensions are able to force any visibility on posts
- if (isset($data['force_approved_state']))
+ if (isset($data_ary['force_approved_state']))
{
- $post_visibility = (in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data['force_approved_state'] : $post_visibility;
+ $post_visibility = (in_array((int) $data_ary['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_approved_state'] : $post_visibility;
}
- if (isset($data['force_visibility']))
+ if (isset($data_ary['force_visibility']))
{
- $post_visibility = (in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data['force_visibility'] : $post_visibility;
+ $post_visibility = (in_array((int) $data_ary['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_visibility'] : $post_visibility;
}
// Start the transaction here
@@ -1691,25 +1547,25 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
case 'post':
case 'reply':
$sql_data[POSTS_TABLE]['sql'] = array(
- 'forum_id' => $data['forum_id'],
+ 'forum_id' => $data_ary['forum_id'],
'poster_id' => (int) $user->data['user_id'],
- 'icon_id' => $data['icon_id'],
+ 'icon_id' => $data_ary['icon_id'],
'poster_ip' => $user->ip,
'post_time' => $current_time,
'post_visibility' => $post_visibility,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
'post_username' => (!$user->data['is_registered']) ? $username : '',
'post_subject' => $subject,
- 'post_text' => $data['message'],
- 'post_checksum' => $data['message_md5'],
- 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid'],
- 'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0,
- 'post_edit_locked' => $data['post_edit_locked']
+ 'post_text' => $data_ary['message'],
+ 'post_checksum' => $data_ary['message_md5'],
+ 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid'],
+ 'post_postcount' => ($auth->acl_get('f_postcount', $data_ary['forum_id'])) ? 1 : 0,
+ 'post_edit_locked' => $data_ary['post_edit_locked']
);
break;
@@ -1726,19 +1582,19 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// If normal edit display edit info
// Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
- if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
+ if ($data_ary['post_edit_reason'] || (!$auth->acl_get('m_edit', $data_ary['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
{
- $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
+ $data_ary['post_edit_reason'] = truncate_string($data_ary['post_edit_reason'], 255, 255, false);
$sql_data[POSTS_TABLE]['sql'] = array(
'post_edit_time' => $current_time,
- 'post_edit_reason' => $data['post_edit_reason'],
- 'post_edit_user' => (int) $data['post_edit_user'],
+ 'post_edit_reason' => $data_ary['post_edit_reason'],
+ 'post_edit_user' => (int) $data_ary['post_edit_user'],
);
$sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
}
- else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id']))
+ else if (!$data_ary['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data_ary['forum_id']))
{
$sql_data[POSTS_TABLE]['sql'] = array(
'post_edit_reason' => '',
@@ -1749,8 +1605,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
if ($user->data['user_id'] != $poster_id)
{
- $log_subject = ($subject) ? $subject : $data['topic_title'];
- add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST'], $data['post_edit_reason']);
+ $log_subject = ($subject) ? $subject : $data_ary['topic_title'];
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array(
+ 'forum_id' => $data_ary['forum_id'],
+ 'topic_id' => $data_ary['topic_id'],
+ 'post_id' => $data_ary['post_id'],
+ $log_subject,
+ (!empty($username)) ? $username : $user->lang['GUEST'],
+ $data_ary['post_edit_reason']
+ ));
}
if (!isset($sql_data[POSTS_TABLE]['sql']))
@@ -1759,32 +1622,31 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
- 'forum_id' => $data['forum_id'],
- 'poster_id' => $data['poster_id'],
- 'icon_id' => $data['icon_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'poster_id' => $data_ary['poster_id'],
+ 'icon_id' => $data_ary['icon_id'],
// We will change the visibility later
//'post_visibility' => $post_visibility,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
- 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '',
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
+ 'post_username' => ($username && $data_ary['poster_id'] == ANONYMOUS) ? $username : '',
'post_subject' => $subject,
- 'post_checksum' => $data['message_md5'],
- 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid'],
- 'post_edit_locked' => $data['post_edit_locked'])
+ 'post_checksum' => $data_ary['message_md5'],
+ 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid'],
+ 'post_edit_locked' => $data_ary['post_edit_locked'])
);
if ($update_message)
{
- $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
+ $sql_data[POSTS_TABLE]['sql']['post_text'] = $data_ary['message'];
}
break;
}
- $topic_row = array();
// And the topic ladies and gentlemen
switch ($post_mode)
@@ -1794,8 +1656,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'topic_poster' => (int) $user->data['user_id'],
'topic_time' => $current_time,
'topic_last_view_time' => $current_time,
- 'forum_id' => $data['forum_id'],
- 'icon_id' => $data['icon_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'icon_id' => $data_ary['icon_id'],
'topic_posts_approved' => ($post_visibility == ITEM_APPROVED) ? 1 : 0,
'topic_posts_softdeleted' => ($post_visibility == ITEM_DELETED) ? 1 : 0,
'topic_posts_unapproved' => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0,
@@ -1805,15 +1667,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
'topic_first_poster_colour' => $user->data['user_colour'],
'topic_type' => $topic_type,
- 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
- 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
- 'topic_status' => (isset($data['topic_status'])) ? $data['topic_status'] : ITEM_UNLOCKED,
+ 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0,
+ 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'topic_status' => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED,
);
- if (isset($poll['poll_options']) && !empty($poll['poll_options']))
+ if (isset($poll_ary['poll_options']) && !empty($poll_ary['poll_options']))
{
- $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time;
- $poll_length = $poll['poll_length'] * 86400;
+ $poll_start = ($poll_ary['poll_start']) ? $poll_ary['poll_start'] : $current_time;
+ $poll_length = $poll_ary['poll_length'] * 86400;
if ($poll_length < 0)
{
$poll_start = $poll_start + $poll_length;
@@ -1825,15 +1687,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array(
- 'poll_title' => $poll['poll_title'],
+ 'poll_title' => $poll_ary['poll_title'],
'poll_start' => $poll_start,
- 'poll_max_options' => $poll['poll_max_options'],
+ 'poll_max_options' => $poll_ary['poll_max_options'],
'poll_length' => $poll_length,
- 'poll_vote_change' => $poll['poll_vote_change'])
+ 'poll_vote_change' => $poll_ary['poll_vote_change'])
);
}
- $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
+ $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
if ($post_visibility == ITEM_APPROVED)
{
@@ -1859,9 +1721,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
(($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') .
(($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') .
(($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') .
- ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : '');
+ ((!empty($data_ary['attachment_data']) || (isset($data_ary['topic_attachment']) && $data_ary['topic_attachment'])) ? ', topic_attachment = 1' : '');
- $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
+ $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
if ($post_visibility == ITEM_APPROVED)
{
@@ -1879,10 +1741,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
case 'edit_topic':
case 'edit_first_post':
- if (isset($poll['poll_options']))
+ if (isset($poll_ary['poll_options']))
{
- $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time;
- $poll_length = $poll['poll_length'] * 86400;
+ $poll_start = ($poll_ary['poll_start'] || empty($poll_ary['poll_options'])) ? $poll_ary['poll_start'] : $current_time;
+ $poll_length = $poll_ary['poll_length'] * 86400;
if ($poll_length < 0)
{
$poll_start = $poll_start + $poll_length;
@@ -1895,25 +1757,27 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$sql_data[TOPICS_TABLE]['sql'] = array(
- 'forum_id' => $data['forum_id'],
- 'icon_id' => $data['icon_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'icon_id' => $data_ary['icon_id'],
'topic_title' => $subject,
'topic_first_poster_name' => $username,
'topic_type' => $topic_type,
- 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
- 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '',
- 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0,
- 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1,
- 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0,
- 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0,
+ 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0,
+ 'poll_title' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '',
+ 'poll_start' => (isset($poll_ary['poll_options'])) ? $poll_start : 0,
+ 'poll_max_options' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1,
+ 'poll_length' => (isset($poll_ary['poll_options'])) ? $poll_length : 0,
+ 'poll_vote_change' => (isset($poll_ary['poll_vote_change'])) ? $poll_ary['poll_vote_change'] : 0,
'topic_last_view_time' => $current_time,
- 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0),
+ 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : (isset($data_ary['topic_attachment']) ? $data_ary['topic_attachment'] : 0),
);
break;
}
+ $poll = $poll_ary;
+ $data = $data_ary;
/**
* Modify sql query data for post submitting
*
@@ -1937,6 +1801,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'username',
);
extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars)));
+ $poll_ary = $poll;
+ $data_ary = $data;
+ unset($poll);
+ unset($data);
// Submit new topic
if ($post_mode == 'post')
@@ -1945,10 +1813,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
$db->sql_query($sql);
- $data['topic_id'] = $db->sql_nextid();
+ $data_ary['topic_id'] = $db->sql_nextid();
$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
- 'topic_id' => $data['topic_id'])
+ 'topic_id' => $data_ary['topic_id'])
);
unset($sql_data[TOPICS_TABLE]['sql']);
}
@@ -1959,18 +1827,18 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($post_mode == 'reply')
{
$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
- 'topic_id' => $data['topic_id'],
+ 'topic_id' => $data_ary['topic_id'],
));
}
$sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
$db->sql_query($sql);
- $data['post_id'] = $db->sql_nextid();
+ $data_ary['post_id'] = $db->sql_nextid();
if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED)
{
$sql_data[TOPICS_TABLE]['sql'] = array(
- 'topic_last_post_id' => $data['post_id'],
+ 'topic_last_post_id' => $data_ary['post_id'],
'topic_last_post_time' => $current_time,
'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'],
'topic_last_poster_name' => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'],
@@ -1981,7 +1849,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($post_mode == 'post')
{
- $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id'];
+ $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data_ary['post_id'];
}
// Update total post count and forum information
@@ -1989,11 +1857,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
if ($post_mode == 'post')
{
- set_config_count('num_topics', 1, true);
+ $config->increment('num_topics', 1, false);
}
- set_config_count('num_posts', 1, true);
+ $config->increment('num_posts', 1, false);
- $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
+ $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data_ary['post_id'];
$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
@@ -2009,7 +1877,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
$sql = 'UPDATE ' . TOPICS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
- WHERE topic_id = ' . $data['topic_id'];
+ WHERE topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
unset($sql_data[TOPICS_TABLE]['sql']);
@@ -2020,14 +1888,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
$sql = 'UPDATE ' . POSTS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
- WHERE post_id = ' . $data['post_id'];
+ WHERE post_id = ' . $data_ary['post_id'];
$db->sql_query($sql);
unset($sql_data[POSTS_TABLE]['sql']);
}
// Update Poll Tables
- if (isset($poll['poll_options']))
+ if (isset($poll_ary['poll_options']))
{
$cur_poll_options = array();
@@ -2035,7 +1903,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
$sql = 'SELECT *
FROM ' . POLL_OPTIONS_TABLE . '
- WHERE topic_id = ' . $data['topic_id'] . '
+ WHERE topic_id = ' . $data_ary['topic_id'] . '
ORDER BY poll_option_id';
$result = $db->sql_query($sql);
@@ -2049,25 +1917,25 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$sql_insert_ary = array();
- for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++)
+ for ($i = 0, $size = sizeof($poll_ary['poll_options']); $i < $size; $i++)
{
- if (strlen(trim($poll['poll_options'][$i])))
+ if (strlen(trim($poll_ary['poll_options'][$i])))
{
if (empty($cur_poll_options[$i]))
{
// 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),
- 'topic_id' => (int) $data['topic_id'],
- 'poll_option_text' => (string) $poll['poll_options'][$i]
+ 'topic_id' => (int) $data_ary['topic_id'],
+ 'poll_option_text' => (string) $poll_ary['poll_options'][$i]
);
}
- else if ($poll['poll_options'][$i] != $cur_poll_options[$i])
+ else if ($poll_ary['poll_options'][$i] != $cur_poll_options[$i])
{
$sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
- SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'
+ SET poll_option_text = '" . $db->sql_escape($poll_ary['poll_options'][$i]) . "'
WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
- AND topic_id = ' . $data['topic_id'];
+ AND topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
}
@@ -2075,29 +1943,29 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
- if (sizeof($poll['poll_options']) < sizeof($cur_poll_options))
+ if (sizeof($poll_ary['poll_options']) < sizeof($cur_poll_options))
{
$sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
- WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
- AND topic_id = ' . $data['topic_id'];
+ WHERE poll_option_id > ' . sizeof($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['poll_options']) != sizeof($cur_poll_options))
+ if ($mode == 'edit' && sizeof($poll_ary['poll_options']) != sizeof($cur_poll_options))
{
- $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
- $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
+ $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']);
}
}
// Submit Attachments
- if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
+ if (!empty($data_ary['attachment_data']) && $data_ary['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
{
$space_taken = $files_added = 0;
$orphan_rows = array();
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
$orphan_rows[(int) $attach_row['attach_id']] = array();
}
@@ -2119,7 +1987,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_freeresult($result);
}
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
{
@@ -2147,8 +2015,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$files_added++;
$attach_sql = array(
- 'post_msg_id' => $data['post_id'],
- 'topic_id' => $data['topic_id'],
+ 'post_msg_id' => $data_ary['post_id'],
+ 'topic_id' => $data_ary['topic_id'],
'is_orphan' => 0,
'poster_id' => $poster_id,
'attach_comment' => $attach_row['attach_comment'],
@@ -2164,37 +2032,38 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($space_taken && $files_added)
{
- set_config_count('upload_dir_size', $space_taken, true);
- set_config_count('num_files', $files_added, true);
+ $config->increment('upload_dir_size', $space_taken, false);
+ $config->increment('num_files', $files_added, false);
}
}
$first_post_has_topic_info = ($post_mode == 'edit_first_post' &&
- (($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1) ||
- ($post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1) ||
- ($post_visibility == ITEM_REAPPROVE && $data['topic_posts_unapproved'] == 1) ||
- ($post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1)));
+ (($post_visibility == ITEM_DELETED && $data_ary['topic_posts_softdeleted'] == 1) ||
+ ($post_visibility == ITEM_UNAPPROVED && $data_ary['topic_posts_unapproved'] == 1) ||
+ ($post_visibility == ITEM_REAPPROVE && $data_ary['topic_posts_unapproved'] == 1) ||
+ ($post_visibility == ITEM_APPROVED && $data_ary['topic_posts_approved'] == 1)));
// Fix the post's and topic's visibility and first/last post information, when the post is edited
- if (($post_mode != 'post' && $post_mode != 'reply') && $data['post_visibility'] != $post_visibility)
+ if (($post_mode != 'post' && $post_mode != 'reply') && $data_ary['post_visibility'] != $post_visibility)
{
// If the post was not approved, it could also be the starter,
// so we sync the starter after approving/restoring, to ensure that the stats are correct
// Same applies for the last post
- $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED);
- $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED);
+ $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
+ $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
- $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
+ $phpbb_content_visibility->set_post_visibility($post_visibility, $data_ary['post_id'], $data_ary['topic_id'], $data_ary['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
}
else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info)
{
- if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility)
+ if ($post_visibility == ITEM_APPROVED || $data_ary['topic_visibility'] == $post_visibility)
{
// only the subject can be changed from edit
$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
// Maybe not only the subject, but also changing anonymous usernames. ;)
- if ($data['poster_id'] == ANONYMOUS)
+ if ($data_ary['poster_id'] == ANONYMOUS)
{
$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
}
@@ -2205,13 +2074,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// it just means that we might have to
$sql = 'SELECT forum_last_post_id, forum_last_post_subject
FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . (int) $data['forum_id'];
+ WHERE forum_id = ' . (int) $data_ary['forum_id'];
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// this post is the latest post in the forum, better update
- if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS))
+ if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS))
{
// the post's subject changed
if ($row['forum_last_post_subject'] !== $subject)
@@ -2220,7 +2089,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Update the user name if poster is anonymous... just in case a moderator changed it
- if ($data['poster_id'] == ANONYMOUS)
+ if ($data_ary['poster_id'] == ANONYMOUS)
{
$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
}
@@ -2231,9 +2100,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Update forum stats
$where_sql = array(
- POSTS_TABLE => 'post_id = ' . $data['post_id'],
- TOPICS_TABLE => 'topic_id = ' . $data['topic_id'],
- FORUMS_TABLE => 'forum_id = ' . $data['forum_id'],
+ POSTS_TABLE => 'post_id = ' . $data_ary['post_id'],
+ TOPICS_TABLE => 'topic_id = ' . $data_ary['topic_id'],
+ FORUMS_TABLE => 'forum_id = ' . $data_ary['forum_id'],
USERS_TABLE => 'user_id = ' . $poster_id
);
@@ -2250,7 +2119,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($topic_type == POST_GLOBAL)
{
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
- WHERE topic_moved_id = ' . $data['topic_id'];
+ WHERE topic_moved_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
@@ -2258,7 +2127,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_transaction('commit');
// Delete draft if post was loaded...
- $draft_id = request_var('draft_loaded', 0);
+ $draft_id = $request->variable('draft_loaded', 0);
if ($draft_id)
{
$sql = 'DELETE FROM ' . DRAFTS_TABLE . "
@@ -2268,7 +2137,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Index message contents
- if ($update_search_index && $data['enable_indexing'])
+ if ($update_search_index && $data_ary['enable_indexing'])
{
// Select the search method and do some additional checks to ensure it can actually be utilised
$search_type = $config['search_type'];
@@ -2286,23 +2155,23 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
trigger_error($error);
}
- $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']);
+ $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']);
}
// Topic Notification, do not change if moderator is changing other users posts...
if ($user->data['user_id'] == $poster_id)
{
- if (!$data['notify_set'] && $data['notify'])
+ if (!$data_ary['notify_set'] && $data_ary['notify'])
{
$sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
- VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
+ VALUES (' . $user->data['user_id'] . ', ' . $data_ary['topic_id'] . ')';
$db->sql_query($sql);
}
- else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify'])
+ else if (($config['email_enable'] || $config['jab_enable']) && $data_ary['notify_set'] && !$data_ary['notify'])
{
$sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
WHERE user_id = ' . $user->data['user_id'] . '
- AND topic_id = ' . $data['topic_id'];
+ AND topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
}
@@ -2310,12 +2179,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
{
// Mark this topic as posted to
- markread('post', $data['forum_id'], $data['topic_id']);
+ markread('post', $data_ary['forum_id'], $data_ary['topic_id']);
}
// Mark this topic as read
// We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
- markread('topic', $data['forum_id'], $data['topic_id'], time());
+ markread('topic', $data_ary['forum_id'], $data_ary['topic_id'], time());
//
if ($config['load_db_lastread'] && $user->data['is_registered'])
@@ -2323,7 +2192,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$sql = 'SELECT mark_time
FROM ' . FORUMS_TRACK_TABLE . '
WHERE user_id = ' . $user->data['user_id'] . '
- AND forum_id = ' . $data['forum_id'];
+ AND forum_id = ' . $data_ary['forum_id'];
$result = $db->sql_query($sql);
$f_mark_time = (int) $db->sql_fetchfield('mark_time');
$db->sql_freeresult($result);
@@ -2338,12 +2207,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Update forum info
$sql = 'SELECT forum_last_post_time
FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . $data['forum_id'];
+ WHERE forum_id = ' . $data_ary['forum_id'];
$result = $db->sql_query($sql);
$forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
$db->sql_freeresult($result);
- update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
+ update_forum_tracking_info($data_ary['forum_id'], $forum_last_post_time, $f_mark_time, false);
}
// If a username was supplied or the poster is a guest, we will use the supplied username.
@@ -2352,15 +2221,16 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username'];
// Send Notifications
- $notification_data = array_merge($data, array(
- 'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject,
+ $notification_data = array_merge($data_ary, array(
+ 'topic_title' => (isset($data_ary['topic_title'])) ? $data_ary['topic_title'] : $subject,
'post_username' => $username,
'poster_id' => $poster_id,
- 'post_text' => $data['message'],
+ 'post_text' => $data_ary['message'],
'post_time' => $current_time,
'post_subject' => $subject,
));
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
if ($post_visibility == ITEM_APPROVED)
@@ -2465,25 +2335,27 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$params = $add_anchor = '';
if ($post_visibility == ITEM_APPROVED ||
- ($auth->acl_get('m_softdelete', $data['forum_id']) && $post_visibility == ITEM_DELETED) ||
- ($auth->acl_get('m_approve', $data['forum_id']) && in_array($post_visibility, array(ITEM_UNAPPROVED, ITEM_REAPPROVE))))
+ ($auth->acl_get('m_softdelete', $data_ary['forum_id']) && $post_visibility == ITEM_DELETED) ||
+ ($auth->acl_get('m_approve', $data_ary['forum_id']) && in_array($post_visibility, array(ITEM_UNAPPROVED, ITEM_REAPPROVE))))
{
- $params .= '&amp;t=' . $data['topic_id'];
+ $params .= '&amp;t=' . $data_ary['topic_id'];
if ($mode != 'post')
{
- $params .= '&amp;p=' . $data['post_id'];
- $add_anchor = '#p' . $data['post_id'];
+ $params .= '&amp;p=' . $data_ary['post_id'];
+ $add_anchor = '#p' . $data_ary['post_id'];
}
}
else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
{
- $params .= '&amp;t=' . $data['topic_id'];
+ $params .= '&amp;t=' . $data_ary['topic_id'];
}
$url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx";
- $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
+ $url = append_sid($url, 'f=' . $data_ary['forum_id'] . $params) . $add_anchor;
+ $poll = $poll_ary;
+ $data = $data_ary;
/**
* This event is used for performing actions directly after a post or topic
* has been submitted. When a new topic is posted, the topic ID is
@@ -2521,6 +2393,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'url',
);
extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
+ $data_ary = $data;
+ $poll_ary = $poll;
+ unset($data);
+ unset($poll);
return $url;
}
@@ -2541,7 +2417,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
*/
function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
{
- global $config, $db, $user, $phpEx, $phpbb_root_path;
+ global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log;
if ($bump_time === false)
{
@@ -2620,7 +2496,11 @@ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false);
}
- add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array(
+ 'forum_id' => $forum_id,
+ 'topic_id' => $topic_id,
+ $post_data['topic_title']
+ ));
$url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}";
@@ -2658,7 +2538,7 @@ function phpbb_upload_popup($forum_style = 0)
function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '')
{
global $user, $auth, $config, $request;
- global $phpbb_root_path, $phpEx;
+ global $phpbb_root_path, $phpEx, $phpbb_log;
$perm_check = ($is_soft) ? 'softdelete' : 'delete';
@@ -2693,14 +2573,27 @@ function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $
if ($next_post_id === false)
{
- add_log('mod', $forum_id, $topic_id, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), $post_data['topic_title'], $post_username, $delete_reason);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), false, array(
+ 'forum_id' => $forum_id,
+ 'topic_id' => $topic_id,
+ $post_data['topic_title'],
+ $post_username,
+ $delete_reason
+ ));
$meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id");
$message = $user->lang['POST_DELETED'];
}
else
{
- add_log('mod', $forum_id, $topic_id, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), $post_data['post_subject'], $post_username, $delete_reason);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), false, array(
+ 'forum_id' => $forum_id,
+ 'topic_id' => $topic_id,
+ 'post_id' => $post_id,
+ $post_data['post_subject'],
+ $post_username,
+ $delete_reason
+ ));
$meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;p=$next_post_id") . "#p$next_post_id";
$message = $user->lang['POST_DELETED'];
diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index 1639eb1a4c..69c3dad9e6 100644
--- a/phpBB/includes/functions_privmsgs.php
+++ b/phpBB/includes/functions_privmsgs.php
@@ -226,7 +226,7 @@ function get_folder($user_id, $folder_id = false)
*/
function clean_sentbox($num_sentbox_messages)
{
- global $db, $user, $config;
+ global $db, $user;
// Check Message Limit
if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit'])
@@ -255,8 +255,6 @@ function clean_sentbox($num_sentbox_messages)
*/
function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
{
- global $user, $config;
-
if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
{
return false;
@@ -335,7 +333,7 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
break;
case ACTION_DELETE_MESSAGE:
- global $db, $auth;
+ global $db;
// Check for admins/mods - users are not allowed to remove those messages...
// We do the check here to make sure the data we use is consistent
@@ -546,7 +544,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
}
// We place actions into arrays, to save queries.
- $sql = $unread_ids = $delete_ids = $important_ids = array();
+ $unread_ids = $delete_ids = $important_ids = array();
foreach ($action_ary as $msg_id => $msg_ary)
{
@@ -803,6 +801,7 @@ function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_fol
if (!$row)
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -881,9 +880,10 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id)
global $db, $user, $phpbb_container;
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
- $phpbb_notifications->mark_notifications_read('notification.type.pm', $msg_id, $user_id);
+ $phpbb_notifications->mark_notifications('notification.type.pm', $msg_id, $user_id);
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
SET pm_unread = 0
@@ -937,11 +937,10 @@ function mark_folder_read($user_id, $folder_id)
*/
function handle_mark_actions($user_id, $mark_action)
{
- global $db, $user, $phpbb_root_path, $phpEx;
+ global $db, $user, $phpbb_root_path, $phpEx, $request;
- $msg_ids = request_var('marked_msg_id', array(0));
- $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX);
- $confirm = (isset($_POST['confirm'])) ? true : false;
+ $msg_ids = $request->variable('marked_msg_id', array(0));
+ $cur_folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX);
if (!sizeof($msg_ids))
{
@@ -967,6 +966,7 @@ function handle_mark_actions($user_id, $mark_action)
if (!$auth->acl_get('u_pm_delete'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_DELETE_MESSAGE');
}
@@ -1006,7 +1006,7 @@ function handle_mark_actions($user_id, $mark_action)
*/
function delete_pm($user_id, $msg_ids, $folder_id)
{
- global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
+ global $db, $user, $phpbb_container, $phpbb_dispatcher;
$user_id = (int) $user_id;
$folder_id = (int) $folder_id;
@@ -1130,6 +1130,7 @@ function delete_pm($user_id, $msg_ids, $folder_id)
$user->data['user_unread_privmsg'] -= $num_unread;
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications('notification.type.pm', array_keys($delete_rows));
@@ -1151,12 +1152,10 @@ function delete_pm($user_id, $msg_ids, $folder_id)
if (sizeof($delete_ids))
{
// Check if there are any attachments we need to remove
- if (!function_exists('delete_attachments'))
- {
- include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
- }
-
- delete_attachments('message', $delete_ids, false);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('message', $delete_ids, false);
+ unset($attachment_manager);
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
@@ -1177,8 +1176,6 @@ function delete_pm($user_id, $msg_ids, $folder_id)
*/
function phpbb_delete_user_pms($user_id)
{
- global $db, $user, $phpbb_root_path, $phpEx;
-
$user_id = (int) $user_id;
if (!$user_id)
@@ -1198,7 +1195,7 @@ function phpbb_delete_user_pms($user_id)
*/
function phpbb_delete_users_pms($user_ids)
{
- global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
+ global $db, $phpbb_container;
$user_id_sql = $db->sql_in_set('user_id', $user_ids);
$author_id_sql = $db->sql_in_set('author_id', $user_ids);
@@ -1243,6 +1240,7 @@ function phpbb_delete_users_pms($user_ids)
$db->sql_transaction('begin');
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
if (!empty($undelivered_msg))
@@ -1360,12 +1358,10 @@ function phpbb_delete_users_pms($user_ids)
if (!empty($delete_ids))
{
// Check if there are any attachments we need to remove
- if (!function_exists('delete_attachments'))
- {
- include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
- }
-
- delete_attachments('message', $delete_ids, false);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('message', $delete_ids, false);
+ unset($attachment_manager);
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
@@ -1397,8 +1393,6 @@ function phpbb_delete_users_pms($user_ids)
*/
function rebuild_header($check_ary)
{
- global $db;
-
$address = array();
foreach ($check_ary as $check_type => $address_field)
@@ -1433,7 +1427,10 @@ function rebuild_header($check_ary)
*/
function write_pm_addresses($check_ary, $author_id, $plaintext = false)
{
- global $db, $user, $template, $phpbb_root_path, $phpEx;
+ global $db, $user, $template, $phpbb_root_path, $phpEx, $phpbb_container;
+
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
$addresses = array();
@@ -1494,7 +1491,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false)
{
if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
{
- $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $address[] = $group_helper->get_name($row['group_name']);
}
}
$db->sql_freeresult($result);
@@ -1514,7 +1511,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false)
{
if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
{
- $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $row['group_name'] = $group_helper->get_name($row['group_name']);
$address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
}
}
@@ -1575,7 +1572,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false)
*/
function get_folder_status($folder_id, $folder)
{
- global $db, $user, $config;
+ global $user;
if (isset($folder[$folder_id]))
{
@@ -1606,9 +1603,9 @@ function get_folder_status($folder_id, $folder)
/**
* Submit PM
*/
-function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
+function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true)
{
- global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;
+ global $db, $auth, $config, $user, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $request;
// We do not handle erasing pms here
if ($mode == 'delete')
@@ -1618,6 +1615,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$current_time = time();
+ $data = $data_ary;
/**
* Get all parts of the PM that are to be submited to the DB.
*
@@ -1629,6 +1627,8 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
*/
$vars = array('mode', 'subject', 'data');
extract($phpbb_dispatcher->trigger_event('core.submit_pm_before', compact($vars)));
+ $data_ary = $data;
+ unset($data);
// Collect some basic information about which tables and which rows to update/insert
$sql_data = array();
@@ -1644,9 +1644,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$_types = array('u', 'g');
foreach ($_types as $ug_type)
{
- if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
+ if (isset($data_ary['address_list'][$ug_type]) && sizeof($data_ary['address_list'][$ug_type]))
{
- foreach ($data['address_list'][$ug_type] as $id => $field)
+ foreach ($data_ary['address_list'][$ug_type] as $id => $field)
{
$id = (int) $id;
@@ -1666,7 +1666,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
}
}
- if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
+ if (isset($data_ary['address_list']['g']) && sizeof($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
@@ -1674,7 +1674,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$sql = 'SELECT u.user_type, ug.group_id, ug.user_id
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
- WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
+ WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data_ary['address_list']['g'])) . '
AND ug.user_pending = 0
AND u.user_id = ug.user_id
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' .
@@ -1683,7 +1683,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
while ($row = $db->sql_fetchrow($result))
{
- $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
+ $field = ($data_ary['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
$recipients[$row['user_id']] = $field;
}
$db->sql_freeresult($result);
@@ -1706,13 +1706,13 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{
case 'reply':
case 'quote':
- $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id'];
+ $root_level = ($data_ary['reply_from_root_level']) ? $data_ary['reply_from_root_level'] : $data_ary['reply_from_msg_id'];
// Set message_replied switch for this user
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
SET pm_replied = 1
- WHERE user_id = ' . $data['from_user_id'] . '
- AND msg_id = ' . $data['reply_from_msg_id'];
+ WHERE user_id = ' . $data_ary['from_user_id'] . '
+ AND msg_id = ' . $data_ary['reply_from_msg_id'];
// no break
@@ -1721,19 +1721,19 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
case 'quotepost':
$sql_data = array(
'root_level' => $root_level,
- 'author_id' => $data['from_user_id'],
- 'icon_id' => $data['icon_id'],
- 'author_ip' => $data['from_user_ip'],
+ 'author_id' => $data_ary['from_user_id'],
+ 'icon_id' => $data_ary['icon_id'],
+ 'author_ip' => $data_ary['from_user_ip'],
'message_time' => $current_time,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
'message_subject' => $subject,
- 'message_text' => $data['message'],
- 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid'],
+ 'message_text' => $data_ary['message'],
+ 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid'],
'to_address' => implode(':', $to),
'bcc_address' => implode(':', $bcc),
'message_reported' => 0,
@@ -1742,35 +1742,33 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
case 'edit':
$sql_data = array(
- 'icon_id' => $data['icon_id'],
+ 'icon_id' => $data_ary['icon_id'],
'message_edit_time' => $current_time,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
'message_subject' => $subject,
- 'message_text' => $data['message'],
- 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid']
+ 'message_text' => $data_ary['message'],
+ 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid']
);
break;
}
if (sizeof($sql_data))
{
- $query = '';
-
if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
{
$db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
- $data['msg_id'] = $db->sql_nextid();
+ $data_ary['msg_id'] = $db->sql_nextid();
}
else if ($mode == 'edit')
{
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
- WHERE msg_id = ' . $data['msg_id'];
+ WHERE msg_id = ' . $data_ary['msg_id'];
$db->sql_query($sql);
}
}
@@ -1787,9 +1785,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
foreach ($recipients as $user_id => $type)
{
$sql_ary[] = array(
- 'msg_id' => (int) $data['msg_id'],
+ 'msg_id' => (int) $data_ary['msg_id'],
'user_id' => (int) $user_id,
- 'author_id' => (int) $data['from_user_id'],
+ 'author_id' => (int) $data_ary['from_user_id'],
'folder_id' => PRIVMSGS_NO_BOX,
'pm_new' => 1,
'pm_unread' => 1,
@@ -1808,9 +1806,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
if ($put_in_outbox)
{
$db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'msg_id' => (int) $data['msg_id'],
- 'user_id' => (int) $data['from_user_id'],
- 'author_id' => (int) $data['from_user_id'],
+ 'msg_id' => (int) $data_ary['msg_id'],
+ 'user_id' => (int) $data_ary['from_user_id'],
+ 'author_id' => (int) $data_ary['from_user_id'],
'folder_id' => PRIVMSGS_OUTBOX,
'pm_new' => 0,
'pm_unread' => 0,
@@ -1824,17 +1822,17 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_lastpost_time = $current_time
- WHERE user_id = " . $data['from_user_id'];
+ WHERE user_id = " . $data_ary['from_user_id'];
$db->sql_query($sql);
}
// Submit Attachments
- if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
+ if (!empty($data_ary['attachment_data']) && $data_ary['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
{
$space_taken = $files_added = 0;
$orphan_rows = array();
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
$orphan_rows[(int) $attach_row['attach_id']] = array();
}
@@ -1857,7 +1855,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$db->sql_freeresult($result);
}
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
{
@@ -1885,10 +1883,10 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$files_added++;
$attach_sql = array(
- 'post_msg_id' => $data['msg_id'],
+ 'post_msg_id' => $data_ary['msg_id'],
'topic_id' => 0,
'is_orphan' => 0,
- 'poster_id' => $data['from_user_id'],
+ 'poster_id' => $data_ary['from_user_id'],
'attach_comment' => $attach_row['attach_comment'],
);
@@ -1902,29 +1900,30 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
if ($space_taken && $files_added)
{
- set_config_count('upload_dir_size', $space_taken, true);
- set_config_count('num_files', $files_added, true);
+ $config->increment('upload_dir_size', $space_taken, false);
+ $config->increment('num_files', $files_added, false);
}
}
// Delete draft if post was loaded...
- $draft_id = request_var('draft_loaded', 0);
+ $draft_id = $request->variable('draft_loaded', 0);
if ($draft_id)
{
$sql = 'DELETE FROM ' . DRAFTS_TABLE . "
WHERE draft_id = $draft_id
- AND user_id = " . $data['from_user_id'];
+ AND user_id = " . $data_ary['from_user_id'];
$db->sql_query($sql);
}
$db->sql_transaction('commit');
// Send Notifications
- $pm_data = array_merge($data, array(
+ $pm_data = array_merge($data_ary, array(
'message_subject' => $subject,
'recipients' => $recipients,
));
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
if ($mode == 'edit')
@@ -1936,6 +1935,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$phpbb_notifications->add_notifications('notification.type.pm', $pm_data);
}
+ $data = $data_ary;
/**
* Get PM message ID after submission to DB
*
@@ -1948,8 +1948,10 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
*/
$vars = array('mode', 'subject', 'data', 'pm_data');
extract($phpbb_dispatcher->trigger_event('core.submit_pm_after', compact($vars)));
+ $data_ary = $data;
+ unset($data);
- return $data['msg_id'];
+ return $data_ary['msg_id'];
}
/**
@@ -1957,7 +1959,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
*/
function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)
{
- global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth;
+ global $db, $user, $template, $phpbb_root_path, $phpEx, $auth;
// Select all receipts and the author from the pm we currently view, to only display their pm-history
$sql = 'SELECT author_id, user_id
@@ -2096,6 +2098,8 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode
'S_IN_POST_MODE' => $in_post_mode,
'MSG_ID' => $row['msg_id'],
+ 'MESSAGE_TIME' => $row['message_time'],
+ 'USER_ID' => $row['user_id'],
'U_VIEW_MESSAGE' => "$url&amp;f=$folder_id&amp;p=" . $row['msg_id'],
'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $row['msg_id'] : '')
@@ -2123,17 +2127,42 @@ function set_user_message_limit()
{
global $user, $db, $config;
- // Get maximum about from user memberships - if it is 0, there is no limit set and we use the maximum value within the config.
- $sql = 'SELECT MAX(g.group_message_limit) as max_message_limit
+ // Get maximum about from user memberships
+ $message_limit = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'message_limit');
+
+ // If it is 0, there is no limit set and we use the maximum value within the config.
+ $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit;
+}
+
+/**
+ * Get the maximum PM setting for the groups of the user
+ *
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param int $user_id
+ * @param string $setting Only 'max_recipients' and 'message_limit' are supported
+ * @return int The maximum setting for all groups of the user, unless one group has '0'
+ * @throws \InvalidArgumentException If selected group setting is not supported
+ */
+function phpbb_get_max_setting_from_group(\phpbb\db\driver\driver_interface $db, $user_id, $setting)
+{
+ if ($setting !== 'max_recipients' && $setting !== 'message_limit')
+ {
+ throw new InvalidArgumentException('Setting "' . $setting . '" is not supported');
+ }
+
+ // Get maximum number of allowed recipients
+ $sql = 'SELECT MIN(g.group_' . $setting . ') as min_setting, MAX(g.group_' . $setting . ') as max_setting
FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
- WHERE ug.user_id = ' . $user->data['user_id'] . '
+ WHERE ug.user_id = ' . (int) $user_id . '
AND ug.user_pending = 0
AND ug.group_id = g.group_id';
$result = $db->sql_query($sql);
- $message_limit = (int) $db->sql_fetchfield('max_message_limit');
+ $row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+ $max_setting = (int) $row['max_setting'];
+ $min_setting = (int) $row['min_setting'];
- $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit;
+ return ($min_setting > 0) ? $max_setting : 0;
}
/**
@@ -2147,7 +2176,10 @@ function set_user_message_limit()
*/
function get_recipient_strings($pm_by_id)
{
- global $db, $phpbb_root_path, $phpEx, $user;
+ global $db, $phpbb_root_path, $phpEx, $user, $phpbb_container;
+
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
$address_list = $recipient_list = $address = array();
@@ -2193,7 +2225,7 @@ function get_recipient_strings($pm_by_id)
{
if ($ug_type == 'g')
{
- $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name'];
+ $row['name'] = $group_helper->get_name($row['name']);
}
$recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php
index 42fdee364c..0fc8a7eea5 100644
--- a/phpBB/includes/functions_transfer.php
+++ b/phpBB/includes/functions_transfer.php
@@ -406,9 +406,6 @@ class ftp extends transfer
*/
function _put($from_file, $to_file)
{
- // get the file extension
- $file_extension = strtolower(substr(strrchr($to_file, '.'), 1));
-
// We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
$mode = FTP_BINARY;
diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php
deleted file mode 100644
index 1aac0e803c..0000000000
--- a/phpBB/includes/functions_upload.php
+++ /dev/null
@@ -1,1118 +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.
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Responsible for holding all file relevant information, as well as doing file-specific operations.
-* The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
-*/
-class filespec
-{
- var $filename = '';
- var $realname = '';
- var $uploadname = '';
- var $mimetype = '';
- var $extension = '';
- var $filesize = 0;
- var $width = 0;
- var $height = 0;
- var $image_info = array();
-
- var $destination_file = '';
- var $destination_path = '';
-
- var $file_moved = false;
- var $init_error = false;
- var $local = false;
-
- var $error = array();
-
- var $upload = '';
-
- /**
- * The plupload object
- * @var \phpbb\plupload\plupload
- */
- protected $plupload;
-
- /**
- * phpBB Mimetype guesser
- * @var \phpbb\mimetype\guesser
- */
- protected $mimetype_guesser;
-
- /**
- * File Class
- * @access private
- */
- function filespec($upload_ary, $upload_namespace, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
- {
- if (!isset($upload_ary))
- {
- $this->init_error = true;
- return;
- }
-
- $this->filename = $upload_ary['tmp_name'];
- $this->filesize = $upload_ary['size'];
- $name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name'];
- $name = trim(utf8_basename($name));
- $this->realname = $this->uploadname = $name;
- $this->mimetype = $upload_ary['type'];
-
- // Opera adds the name to the mime type
- $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype;
-
- if (!$this->mimetype)
- {
- $this->mimetype = 'application/octet-stream';
- }
-
- $this->extension = strtolower(self::get_extension($this->realname));
-
- // Try to get real filesize from temporary folder (not always working) ;)
- $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize;
-
- $this->width = $this->height = 0;
- $this->file_moved = false;
-
- $this->local = (isset($upload_ary['local_mode'])) ? true : false;
- $this->upload = $upload_namespace;
- $this->plupload = $plupload;
- $this->mimetype_guesser = $mimetype_guesser;
- }
-
- /**
- * Cleans destination filename
- *
- * @param real|unique|unique_ext $mode real creates a realname, filtering some characters, lowering every character. Unique creates an unique filename
- * @param string $prefix Prefix applied to filename
- * @param string $user_id The user_id is only needed for when cleaning a user's avatar
- * @access public
- */
- function clean_filename($mode = 'unique', $prefix = '', $user_id = '')
- {
- if ($this->init_error)
- {
- return;
- }
-
- switch ($mode)
- {
- case 'real':
- // Remove every extension from filename (to not let the mime bug being exposed)
- if (strpos($this->realname, '.') !== false)
- {
- $this->realname = substr($this->realname, 0, strpos($this->realname, '.'));
- }
-
- // Replace any chars which may cause us problems with _
- $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
-
- $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname)));
- $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname);
-
- $this->realname = $prefix . $this->realname . '.' . $this->extension;
- break;
-
- case 'unique':
- $this->realname = $prefix . md5(unique_id());
- break;
-
- case 'avatar':
- $this->extension = strtolower($this->extension);
- $this->realname = $prefix . $user_id . '.' . $this->extension;
-
- break;
-
- case 'unique_ext':
- default:
- $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension;
- break;
- }
- }
-
- /**
- * Get property from file object
- */
- function get($property)
- {
- if ($this->init_error || !isset($this->$property))
- {
- return false;
- }
-
- return $this->$property;
- }
-
- /**
- * Check if file is an image (mimetype)
- *
- * @return true if it is an image, false if not
- */
- function is_image()
- {
- return (strpos($this->mimetype, 'image/') === 0);
- }
-
- /**
- * Check if the file got correctly uploaded
- *
- * @return true if it is a valid upload, false if not
- */
- function is_uploaded()
- {
- $is_plupload = $this->plupload && $this->plupload->is_active();
-
- if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename))
- {
- return false;
- }
-
- if (($this->local || $is_plupload) && !file_exists($this->filename))
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Remove file
- */
- function remove()
- {
- if ($this->file_moved)
- {
- @unlink($this->destination_file);
- }
- }
-
- /**
- * Get file extension
- *
- * @param string Filename that needs to be checked
- * @return string Extension of the supplied filename
- */
- static public function get_extension($filename)
- {
- $filename = utf8_basename($filename);
-
- if (strpos($filename, '.') === false)
- {
- return '';
- }
-
- $filename = explode('.', $filename);
- return array_pop($filename);
- }
-
- /**
- * Get mimetype
- *
- * @param string $filename Filename that needs to be checked
- * @return string Mimetype of supplied filename
- */
- function get_mimetype($filename)
- {
- if ($this->mimetype_guesser !== null)
- {
- $mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname);
-
- if ($mimetype !== 'application/octet-stream')
- {
- $this->mimetype = $mimetype;
- }
- }
-
- return $this->mimetype;
- }
-
- /**
- * Get filesize
- */
- function get_filesize($filename)
- {
- return @filesize($filename);
- }
-
-
- /**
- * Check the first 256 bytes for forbidden content
- */
- function check_content($disallowed_content)
- {
- if (empty($disallowed_content))
- {
- return true;
- }
-
- $fp = @fopen($this->filename, 'rb');
-
- if ($fp !== false)
- {
- $ie_mime_relevant = fread($fp, 256);
- fclose($fp);
- foreach ($disallowed_content as $forbidden)
- {
- if (stripos($ie_mime_relevant, '<' . $forbidden) !== false)
- {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Move file to destination folder
- * The phpbb_root_path variable will be applied to the destination path
- *
- * @param string $destination Destination path, for example $config['avatar_path']
- * @param bool $overwrite If set to true, an already existing file will be overwritten
- * @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped
- * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here reflects the mode defined by {@link phpbb_chmod()}
- *
- * @access public
- */
- function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false)
- {
- global $user, $phpbb_root_path;
-
- if (sizeof($this->error))
- {
- return false;
- }
-
- $chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod;
-
- // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
- $this->destination_path = $phpbb_root_path . $destination;
-
- // Check if the destination path exist...
- if (!file_exists($this->destination_path))
- {
- @unlink($this->filename);
- return false;
- }
-
- $upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy';
- $upload_mode = ($this->local) ? 'local' : $upload_mode;
- $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
-
- // Check if the file already exist, else there is something wrong...
- if (file_exists($this->destination_file) && !$overwrite)
- {
- @unlink($this->filename);
- $this->error[] = $user->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
- $this->file_moved = false;
- return false;
- }
- else
- {
- if (file_exists($this->destination_file))
- {
- @unlink($this->destination_file);
- }
-
- switch ($upload_mode)
- {
- case 'copy':
-
- if (!@copy($this->filename, $this->destination_file))
- {
- if (!@move_uploaded_file($this->filename, $this->destination_file))
- {
- $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
- }
- }
-
- break;
-
- case 'move':
-
- if (!@move_uploaded_file($this->filename, $this->destination_file))
- {
- if (!@copy($this->filename, $this->destination_file))
- {
- $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
- }
- }
-
- break;
-
- case 'local':
-
- if (!@copy($this->filename, $this->destination_file))
- {
- $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
- }
-
- break;
- }
-
- // Remove temporary filename
- @unlink($this->filename);
-
- if (sizeof($this->error))
- {
- return false;
- }
-
- phpbb_chmod($this->destination_file, $chmod);
- }
-
- // Try to get real filesize from destination folder
- $this->filesize = (@filesize($this->destination_file)) ? @filesize($this->destination_file) : $this->filesize;
-
- // Get mimetype of supplied file
- $this->mimetype = $this->get_mimetype($this->destination_file);
-
- if ($this->is_image() && !$skip_image_check)
- {
- $this->width = $this->height = 0;
-
- if (($this->image_info = @getimagesize($this->destination_file)) !== false)
- {
- $this->width = $this->image_info[0];
- $this->height = $this->image_info[1];
-
- if (!empty($this->image_info['mime']))
- {
- $this->mimetype = $this->image_info['mime'];
- }
-
- // Check image type
- $types = fileupload::image_types();
-
- if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
- {
- if (!isset($types[$this->image_info[2]]))
- {
- $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype);
- }
- else
- {
- $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension);
- }
- }
-
- // Make sure the dimensions match a valid image
- if (empty($this->width) || empty($this->height))
- {
- $this->error[] = $user->lang['ATTACHED_IMAGE_NOT_IMAGE'];
- }
- }
- else
- {
- $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
- }
- }
-
- $this->file_moved = true;
- $this->additional_checks();
- unset($this->upload);
-
- return true;
- }
-
- /**
- * Performing additional checks
- */
- function additional_checks()
- {
- global $user;
-
- if (!$this->file_moved)
- {
- return false;
- }
-
- // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
- if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
- {
- $max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
-
- $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
-
- return false;
- }
-
- if (!$this->upload->valid_dimensions($this))
- {
- $this->error[] = $user->lang($this->upload->error_prefix . 'WRONG_SIZE',
- $user->lang('PIXELS', (int) $this->upload->min_width),
- $user->lang('PIXELS', (int) $this->upload->min_height),
- $user->lang('PIXELS', (int) $this->upload->max_width),
- $user->lang('PIXELS', (int) $this->upload->max_height),
- $user->lang('PIXELS', (int) $this->width),
- $user->lang('PIXELS', (int) $this->height));
-
- return false;
- }
-
- return true;
- }
-}
-
-/**
-* Class for assigning error messages before a real filespec class can be assigned
-*/
-class fileerror extends filespec
-{
- function fileerror($error_msg)
- {
- $this->error[] = $error_msg;
- }
-}
-
-/**
-* File upload class
-* Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads
-*/
-class fileupload
-{
- var $allowed_extensions = array();
- var $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title');
- var $max_filesize = 0;
- var $min_width = 0;
- var $min_height = 0;
- var $max_width = 0;
- var $max_height = 0;
- var $error_prefix = '';
-
- /** @var int Timeout for remote upload */
- var $upload_timeout = 6;
-
- /**
- * Init file upload class.
- *
- * @param string $error_prefix Used error messages will get prefixed by this string
- * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png')
- * @param int $max_filesize Maximum filesize
- * @param int $min_width Minimum image width (only checked for images)
- * @param int $min_height Minimum image height (only checked for images)
- * @param int $max_width Maximum image width (only checked for images)
- * @param int $max_height Maximum image height (only checked for images)
- * @param bool|array $disallowed_content If enabled, the first 256 bytes of the file must not
- * contain any of its values. Defaults to false.
- *
- */
- function fileupload($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false)
- {
- $this->set_allowed_extensions($allowed_extensions);
- $this->set_max_filesize($max_filesize);
- $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height);
- $this->set_error_prefix($error_prefix);
- $this->set_disallowed_content($disallowed_content);
- }
-
- /**
- * Reset vars
- */
- function reset_vars()
- {
- $this->max_filesize = 0;
- $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0;
- $this->error_prefix = '';
- $this->allowed_extensions = array();
- $this->disallowed_content = array();
- }
-
- /**
- * Set allowed extensions
- */
- function set_allowed_extensions($allowed_extensions)
- {
- if ($allowed_extensions !== false && is_array($allowed_extensions))
- {
- $this->allowed_extensions = $allowed_extensions;
- }
- }
-
- /**
- * Set allowed dimensions
- */
- function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height)
- {
- $this->min_width = (int) $min_width;
- $this->min_height = (int) $min_height;
- $this->max_width = (int) $max_width;
- $this->max_height = (int) $max_height;
- }
-
- /**
- * Set maximum allowed filesize
- */
- function set_max_filesize($max_filesize)
- {
- if ($max_filesize !== false && (int) $max_filesize)
- {
- $this->max_filesize = (int) $max_filesize;
- }
- }
-
- /**
- * Set disallowed strings
- */
- function set_disallowed_content($disallowed_content)
- {
- if ($disallowed_content !== false && is_array($disallowed_content))
- {
- $this->disallowed_content = array_diff($disallowed_content, array(''));
- }
- }
-
- /**
- * Set error prefix
- */
- function set_error_prefix($error_prefix)
- {
- $this->error_prefix = $error_prefix;
- }
-
- /**
- * Form upload method
- * Upload file from users harddisk
- *
- * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified)
- * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
- * @param \phpbb\plupload\plupload $plupload The plupload object
- *
- * @return object $file Object "filespec" is returned, all further operations can be done with this object
- * @access public
- */
- function form_upload($form_name, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
- {
- global $user, $request;
-
- $upload = $request->file($form_name);
- unset($upload['local_mode']);
-
- if ($plupload)
- {
- $result = $plupload->handle_upload($form_name);
- if (is_array($result))
- {
- $upload = array_merge($upload, $result);
- }
- }
-
- $file = new filespec($upload, $this, $mimetype_guesser, $plupload);
-
- if ($file->init_error)
- {
- $file->error[] = '';
- return $file;
- }
-
- // Error array filled?
- if (isset($upload['error']))
- {
- $error = $this->assign_internal_error($upload['error']);
-
- if ($error !== false)
- {
- $file->error[] = $error;
- return $file;
- }
- }
-
- // Check if empty file got uploaded (not catched by is_uploaded_file)
- if (isset($upload['size']) && $upload['size'] == 0)
- {
- $file->error[] = $user->lang[$this->error_prefix . 'EMPTY_FILEUPLOAD'];
- return $file;
- }
-
- // PHP Upload filesize exceeded
- if ($file->get('filename') == 'none')
- {
- $max_filesize = @ini_get('upload_max_filesize');
- $unit = 'MB';
-
- if (!empty($max_filesize))
- {
- $unit = strtolower(substr($max_filesize, -1, 1));
- $max_filesize = (int) $max_filesize;
-
- $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
- }
-
- $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
- return $file;
- }
-
- // Not correctly uploaded
- if (!$file->is_uploaded())
- {
- $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
- return $file;
- }
-
- $this->common_checks($file);
-
- return $file;
- }
-
- /**
- * Move file from another location to phpBB
- */
- function local_upload($source_file, $filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null)
- {
- global $user, $request;
-
- $upload = array();
-
- $upload['local_mode'] = true;
- $upload['tmp_name'] = $source_file;
-
- if ($filedata === false)
- {
- $upload['name'] = utf8_basename($source_file);
- $upload['size'] = 0;
- }
- else
- {
- $upload['name'] = $filedata['realname'];
- $upload['size'] = $filedata['size'];
- $upload['type'] = $filedata['type'];
- }
-
- $file = new filespec($upload, $this, $mimetype_guesser);
-
- if ($file->init_error)
- {
- $file->error[] = '';
- return $file;
- }
-
- if (isset($upload['error']))
- {
- $error = $this->assign_internal_error($upload['error']);
-
- if ($error !== false)
- {
- $file->error[] = $error;
- return $file;
- }
- }
-
- // PHP Upload filesize exceeded
- if ($file->get('filename') == 'none')
- {
- $max_filesize = @ini_get('upload_max_filesize');
- $unit = 'MB';
-
- if (!empty($max_filesize))
- {
- $unit = strtolower(substr($max_filesize, -1, 1));
- $max_filesize = (int) $max_filesize;
-
- $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
- }
-
- $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
- return $file;
- }
-
- // Not correctly uploaded
- if (!$file->is_uploaded())
- {
- $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
- return $file;
- }
-
- $this->common_checks($file);
- $request->overwrite('local', $upload, \phpbb\request\request_interface::FILES);
-
- return $file;
- }
-
- /**
- * Remote upload method
- * Uploads file from given url
- *
- * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif
- * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
- * @return object $file Object "filespec" is returned, all further operations can be done with this object
- * @access public
- */
- function remote_upload($upload_url, \phpbb\mimetype\guesser $mimetype_guesser = null)
- {
- global $user, $phpbb_root_path;
-
- $upload_ary = array();
- $upload_ary['local_mode'] = true;
-
- if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match))
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
- return $file;
- }
-
- if (empty($match[2]))
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
- return $file;
- }
-
- $url = parse_url($upload_url);
-
- $default_port = 80;
- $hostname = $url['host'];
-
- if ($url['scheme'] == 'https')
- {
- $default_port = 443;
- $hostname = 'tls://' . $url['host'];
- }
-
- $host = $url['host'];
- $path = $url['path'];
- $port = (!empty($url['port'])) ? (int) $url['port'] : $default_port;
-
- $upload_ary['type'] = 'application/octet-stream';
-
- $url['path'] = explode('.', $url['path']);
- $ext = array_pop($url['path']);
-
- $url['path'] = implode('', $url['path']);
- $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
- $filename = $url['path'];
- $filesize = 0;
-
- $remote_max_filesize = $this->max_filesize;
- if (!$remote_max_filesize)
- {
- $max_filesize = @ini_get('upload_max_filesize');
-
- if (!empty($max_filesize))
- {
- $unit = strtolower(substr($max_filesize, -1, 1));
- $remote_max_filesize = (int) $max_filesize;
-
- switch ($unit)
- {
- case 'g':
- $remote_max_filesize *= 1024;
- // no break
- case 'm':
- $remote_max_filesize *= 1024;
- // no break
- case 'k':
- $remote_max_filesize *= 1024;
- // no break
- }
- }
- }
-
- $errno = 0;
- $errstr = '';
-
- if (!($fsock = @fsockopen($hostname, $port, $errno, $errstr)))
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
- return $file;
- }
-
- // Make sure $path not beginning with /
- if (strpos($path, '/') === 0)
- {
- $path = substr($path, 1);
- }
-
- fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n");
- fputs($fsock, "HOST: " . $host . "\r\n");
- fputs($fsock, "Connection: close\r\n\r\n");
-
- // Set a proper timeout for the socket
- socket_set_timeout($fsock, $this->upload_timeout);
-
- $get_info = false;
- $data = '';
- $length = false;
- $timer_stop = time() + $this->upload_timeout;
-
- while ((!$length || $filesize < $length) && !@feof($fsock))
- {
- if ($get_info)
- {
- if ($length)
- {
- // Don't attempt to read past end of file if server indicated length
- $block = @fread($fsock, min($length - $filesize, 1024));
- }
- else
- {
- $block = @fread($fsock, 1024);
- }
-
- $filesize += strlen($block);
-
- if ($remote_max_filesize && $filesize > $remote_max_filesize)
- {
- $max_filesize = get_formatted_filesize($remote_max_filesize, false);
-
- $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
- return $file;
- }
-
- $data .= $block;
- }
- else
- {
- $line = @fgets($fsock, 1024);
-
- if ($line == "\r\n")
- {
- $get_info = true;
- }
- else
- {
- if (stripos($line, 'content-type: ') !== false)
- {
- $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line)));
- }
- else if ($this->max_filesize && stripos($line, 'content-length: ') !== false)
- {
- $length = (int) str_replace('content-length: ', '', strtolower($line));
-
- if ($remote_max_filesize && $length && $length > $remote_max_filesize)
- {
- $max_filesize = get_formatted_filesize($remote_max_filesize, false);
-
- $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
- return $file;
- }
- }
- else if (stripos($line, '404 not found') !== false)
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'URL_NOT_FOUND']);
- return $file;
- }
- }
- }
-
- $stream_meta_data = stream_get_meta_data($fsock);
-
- // Cancel upload if we exceed timeout
- if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'REMOTE_UPLOAD_TIMEOUT']);
- return $file;
- }
- }
- @fclose($fsock);
-
- if (empty($data))
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'EMPTY_REMOTE_DATA']);
- return $file;
- }
-
- $tmp_path = (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') ? sys_get_temp_dir() : $phpbb_root_path . 'cache';
- $filename = tempnam($tmp_path, unique_id() . '-');
-
- if (!($fp = @fopen($filename, 'wb')))
- {
- $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
- return $file;
- }
-
- $upload_ary['size'] = fwrite($fp, $data);
- fclose($fp);
- unset($data);
-
- $upload_ary['tmp_name'] = $filename;
-
- $file = new filespec($upload_ary, $this, $mimetype_guesser);
- $this->common_checks($file);
-
- return $file;
- }
-
- /**
- * Assign internal error
- * @access private
- */
- function assign_internal_error($errorcode)
- {
- global $user;
-
- switch ($errorcode)
- {
- case 1:
- $max_filesize = @ini_get('upload_max_filesize');
- $unit = 'MB';
-
- if (!empty($max_filesize))
- {
- $unit = strtolower(substr($max_filesize, -1, 1));
- $max_filesize = (int) $max_filesize;
-
- $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
- }
-
- $error = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
- break;
-
- case 2:
- $max_filesize = get_formatted_filesize($this->max_filesize, false);
-
- $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
- break;
-
- case 3:
- $error = $user->lang[$this->error_prefix . 'PARTIAL_UPLOAD'];
- break;
-
- case 4:
- $error = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
- break;
-
- case 6:
- $error = 'Temporary folder could not be found. Please check your PHP installation.';
- break;
-
- default:
- $error = false;
- break;
- }
-
- return $error;
- }
-
- /**
- * Perform common checks
- */
- function common_checks(&$file)
- {
- global $user;
-
- // 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))
- {
- $max_filesize = get_formatted_filesize($this->max_filesize, false);
-
- $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
- }
-
- // check Filename
- if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname')))
- {
- $file->error[] = sprintf($user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname'));
- }
-
- // Invalid Extension
- if (!$this->valid_extension($file))
- {
- $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension'));
- }
-
- // MIME Sniffing
- if (!$this->valid_content($file))
- {
- $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_CONTENT']);
- }
- }
-
- /**
- * Check for allowed extension
- */
- function valid_extension(&$file)
- {
- return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false;
- }
-
- /**
- * Check for allowed dimension
- */
- function valid_dimensions(&$file)
- {
- if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height)
- {
- return true;
- }
-
- if (($file->get('width') > $this->max_width && $this->max_width) ||
- ($file->get('height') > $this->max_height && $this->max_height) ||
- ($file->get('width') < $this->min_width && $this->min_width) ||
- ($file->get('height') < $this->min_height && $this->min_height))
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Check if form upload is valid
- */
- function is_valid($form_name)
- {
- global $request;
- $upload = $request->file($form_name);
-
- return (!empty($upload) && $upload['name'] !== 'none');
- }
-
-
- /**
- * Check for bad content (IE mime-sniffing)
- */
- function valid_content(&$file)
- {
- return ($file->check_content($this->disallowed_content));
- }
-
- /**
- * Get image type/extension mapping
- *
- * @return array Array containing the image types and their extensions
- */
- static public function image_types()
- {
- $result = array(
- IMAGETYPE_GIF => array('gif'),
- IMAGETYPE_JPEG => array('jpg', 'jpeg'),
- IMAGETYPE_PNG => array('png'),
- IMAGETYPE_SWF => array('swf'),
- IMAGETYPE_PSD => array('psd'),
- IMAGETYPE_BMP => array('bmp'),
- IMAGETYPE_TIFF_II => array('tif', 'tiff'),
- IMAGETYPE_TIFF_MM => array('tif', 'tiff'),
- IMAGETYPE_JPC => array('jpg', 'jpeg'),
- IMAGETYPE_JP2 => array('jpg', 'jpeg'),
- IMAGETYPE_JPX => array('jpg', 'jpeg'),
- IMAGETYPE_JB2 => array('jpg', 'jpeg'),
- IMAGETYPE_IFF => array('iff'),
- IMAGETYPE_WBMP => array('wbmp'),
- IMAGETYPE_XBM => array('xbm'),
- );
-
- if (defined('IMAGETYPE_SWC'))
- {
- $result[IMAGETYPE_SWC] = array('swc');
- }
-
- return $result;
- }
-}
diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php
deleted file mode 100644
index b965046aad..0000000000
--- a/phpBB/includes/functions_url_matcher.php
+++ /dev/null
@@ -1,112 +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.
-*
-*/
-
-use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
-use Symfony\Component\Routing\Matcher\UrlMatcher;
-use Symfony\Component\Routing\RequestContext;
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Create a new UrlMatcher class and dump it into the cache file
-*
-* @param \phpbb\extension\manager $manager Extension manager
-* @param RequestContext $context Symfony RequestContext object
-* @param string $root_path Root path
-* @param string $php_ext PHP file extension
-* @return null
-*/
-function phpbb_get_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path, $php_ext)
-{
- if (defined('DEBUG'))
- {
- return phpbb_create_url_matcher($manager, $context, $root_path);
- }
-
- if (!phpbb_url_matcher_dumped($root_path, $php_ext))
- {
- phpbb_create_dumped_url_matcher($manager, $root_path, $php_ext);
- }
-
- return phpbb_load_url_matcher($context, $root_path, $php_ext);
-}
-
-/**
-* Create a new UrlMatcher class and dump it into the cache file
-*
-* @param \phpbb\extension\manager $manager Extension manager
-* @param string $root_path Root path
-* @param string $php_ext PHP file extension
-* @return null
-*/
-function phpbb_create_dumped_url_matcher(\phpbb\extension\manager $manager, $root_path, $php_ext)
-{
- $provider = new \phpbb\controller\provider();
- $provider->find_routing_files($manager->get_finder());
- $routes = $provider->find($root_path)->get_routes();
- $dumper = new PhpMatcherDumper($routes);
- $cached_url_matcher_dump = $dumper->dump(array(
- 'class' => 'phpbb_url_matcher',
- ));
-
- file_put_contents($root_path . 'cache/url_matcher.' . $php_ext, $cached_url_matcher_dump);
-}
-
-/**
-* Create a non-cached UrlMatcher
-*
-* @param \phpbb\extension\manager $manager Extension manager
-* @param RequestContext $context Symfony RequestContext object
-* @return UrlMatcher
-*/
-function phpbb_create_url_matcher(\phpbb\extension\manager $manager, RequestContext $context, $root_path)
-{
- $provider = new \phpbb\controller\provider();
- $provider->find_routing_files($manager->get_finder());
- $routes = $provider->find($root_path)->get_routes();
- return new UrlMatcher($routes, $context);
-}
-
-/**
-* Load the cached phpbb_url_matcher class
-*
-* @param RequestContext $context Symfony RequestContext object
-* @param string $root_path Root path
-* @param string $php_ext PHP file extension
-* @return phpbb_url_matcher
-*/
-function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext)
-{
- require($root_path . 'cache/url_matcher.' . $php_ext);
- return new phpbb_url_matcher($context);
-}
-
-/**
-* Determine whether we have our dumped URL matcher
-*
-* The class is automatically dumped to the cache directory
-*
-* @param string $root_path Root path
-* @param string $php_ext PHP file extension
-* @return bool True if it exists, false if not
-*/
-function phpbb_url_matcher_dumped($root_path, $php_ext)
-{
- return file_exists($root_path . 'cache/url_matcher.' . $php_ext);
-}
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index b82abe0c5e..f29f974ccf 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -89,7 +89,7 @@ function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false)
*/
function update_last_username()
{
- global $db;
+ global $config, $db;
// Get latest username
$sql = 'SELECT user_id, username, user_colour
@@ -102,9 +102,9 @@ function update_last_username()
if ($row)
{
- set_config('newest_user_id', $row['user_id'], true);
- set_config('newest_username', $row['username'], true);
- set_config('newest_user_colour', $row['user_colour'], true);
+ $config->set('newest_user_id', $row['user_id'], false);
+ $config->set('newest_username', $row['username'], false);
+ $config->set('newest_user_colour', $row['user_colour'], false);
}
}
@@ -148,7 +148,7 @@ function user_update_name($old_name, $new_name)
if ($config['newest_username'] == $old_name)
{
- set_config('newest_username', $new_name, true);
+ $config->set('newest_username', $new_name, false);
}
/**
@@ -176,7 +176,7 @@ function user_update_name($old_name, $new_name)
*/
function user_add($user_row, $cp_data = false, $notifications_data = null)
{
- global $db, $user, $auth, $config, $phpbb_root_path, $phpEx;
+ global $db, $config;
global $phpbb_dispatcher, $phpbb_container;
if (empty($user_row['username']) || !isset($user_row['group_id']) || !isset($user_row['user_email']) || !isset($user_row['user_type']))
@@ -291,6 +291,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null)
{
$cp_data['user_id'] = (int) $user_id;
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' .
$db->sql_build_array('INSERT', $cp->build_insert_sql_array($cp_data));
@@ -323,7 +324,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null)
{
global $phpbb_log;
- // Because these actions only fill the log unneccessarily we skip the add_log() entry.
+ // Because these actions only fill the log unnecessarily, we disable it
$phpbb_log->disable('admin');
// Add user to "newly registered users" group and set to default group if admin specified so.
@@ -344,9 +345,9 @@ function user_add($user_row, $cp_data = false, $notifications_data = null)
// set the newest user and adjust the user count if the user is a normal user and no activation mail is sent
if ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_FOUNDER)
{
- set_config('newest_user_id', $user_id, true);
- set_config('newest_username', $user_row['username'], true);
- set_config_count('num_users', 1, true);
+ $config->set('newest_user_id', $user_id, false);
+ $config->set('newest_username', $user_row['username'], false);
+ $config->increment('num_users', 1, false);
$sql = 'SELECT group_colour
FROM ' . GROUPS_TABLE . '
@@ -355,7 +356,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null)
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- set_config('newest_user_colour', $row['group_colour'], true);
+ $config->set('newest_user_colour', $row['group_colour'], false);
}
// Use default notifications settings if notifications_data is not set
@@ -376,6 +377,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null)
// Subscribe user to notifications if necessary
if (!empty($notifications_data))
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
foreach ($notifications_data as $subscription)
{
@@ -616,7 +618,7 @@ function user_delete($mode, $user_ids, $retain_username = true)
if ($num_users_delta != 0)
{
- set_config_count('num_users', $num_users_delta, true);
+ $config->increment('num_users', $num_users_delta, false);
}
// Now do the invariant tasks
@@ -849,12 +851,12 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
if ($deactivated)
{
- set_config_count('num_users', $deactivated * (-1), true);
+ $config->increment('num_users', $deactivated * (-1), false);
}
if ($activated)
{
- set_config_count('num_users', $activated, true);
+ $config->increment('num_users', $activated, false);
}
// Update latest username
@@ -874,7 +876,7 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
*/
function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '')
{
- global $db, $user, $auth, $cache;
+ global $db, $user, $cache, $phpbb_log;
// Delete stale bans
$sql = 'DELETE FROM ' . BANLIST_TABLE . '
@@ -1023,7 +1025,6 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
if ($ip_2_counter == 0 && $ip_2_end == 254)
{
$ip_2_counter = 256;
- $ip_2_fragment = 256;
$banlist_ary[] = "$ip_1_counter.*";
}
@@ -1036,7 +1037,6 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
if ($ip_3_counter == 0 && $ip_3_end == 254)
{
$ip_3_counter = 256;
- $ip_3_fragment = 256;
$banlist_ary[] = "$ip_1_counter.$ip_2_counter.*";
}
@@ -1049,7 +1049,6 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
if ($ip_4_counter == 0 && $ip_4_end == 254)
{
$ip_4_counter = 256;
- $ip_4_fragment = 256;
$banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*";
}
@@ -1265,13 +1264,22 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
$log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_';
// Add to admin log, moderator log and user notes
- add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
- add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array($ban_reason, $ban_list_log));
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array(
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $ban_reason,
+ $ban_list_log
+ ));
if ($mode == 'user')
{
foreach ($banlist_ary as $user_id)
{
- add_log('user', $user_id, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array(
+ 'reportee_id' => $user_id,
+ $ban_reason,
+ $ban_list_log
+ ));
}
}
@@ -1291,7 +1299,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
*/
function user_unban($mode, $ban)
{
- global $db, $user, $auth, $cache;
+ global $db, $user, $cache, $phpbb_log;
// Delete stale bans
$sql = 'DELETE FROM ' . BANLIST_TABLE . '
@@ -1349,13 +1357,20 @@ function user_unban($mode, $ban)
$db->sql_query($sql);
// Add to moderator log, admin log and user notes
- add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
- add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array($l_unban_list));
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array(
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $l_unban_list
+ ));
if ($mode == 'user')
{
foreach ($user_ids_ary as $user_id)
{
- add_log('user', $user_id, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_UNBAN_' . strtoupper($mode), false, array(
+ 'reportee_id' => $user_id,
+ $l_unban_list
+ ));
}
}
}
@@ -1674,89 +1689,37 @@ function validate_username($username, $allowed_username = false)
return 'INVALID_CHARS';
}
- $mbstring = $pcre = false;
-
- // generic UTF-8 character types supported?
- if (phpbb_pcre_utf8_support())
- {
- $pcre = true;
- }
- else if (function_exists('mb_ereg_match'))
- {
- mb_regex_encoding('UTF-8');
- $mbstring = true;
- }
-
switch ($config['allow_name_chars'])
{
case 'USERNAME_CHARS_ANY':
- $pcre = true;
$regex = '.+';
break;
case 'USERNAME_ALPHA_ONLY':
- $pcre = true;
$regex = '[A-Za-z0-9]+';
break;
case 'USERNAME_ALPHA_SPACERS':
- $pcre = true;
$regex = '[A-Za-z0-9-[\]_+ ]+';
break;
case 'USERNAME_LETTER_NUM':
- if ($pcre)
- {
- $regex = '[\p{Lu}\p{Ll}\p{N}]+';
- }
- else if ($mbstring)
- {
- $regex = '[[:upper:][:lower:][:digit:]]+';
- }
- else
- {
- $pcre = true;
- $regex = '[a-zA-Z0-9]+';
- }
+ $regex = '[\p{Lu}\p{Ll}\p{N}]+';
break;
case 'USERNAME_LETTER_NUM_SPACERS':
- if ($pcre)
- {
- $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+';
- }
- else if ($mbstring)
- {
- $regex = '[-\]_+ \[[:upper:][:lower:][:digit:]]+';
- }
- else
- {
- $pcre = true;
- $regex = '[-\]_+ [a-zA-Z0-9]+';
- }
+ $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+';
break;
case 'USERNAME_ASCII':
default:
- $pcre = true;
$regex = '[\x01-\x7F]+';
break;
}
- if ($pcre)
- {
- if (!preg_match('#^' . $regex . '$#u', $username))
- {
- return 'INVALID_CHARS';
- }
- }
- else if ($mbstring)
+ if (!preg_match('#^' . $regex . '$#u', $username))
{
- mb_ereg_search_init($username, '^' . $regex . '$');
- if (!mb_ereg_search())
- {
- return 'INVALID_CHARS';
- }
+ return 'INVALID_CHARS';
}
$sql = 'SELECT username
@@ -1811,35 +1774,10 @@ function validate_password($password)
return false;
}
- $pcre = $mbstring = false;
-
- // generic UTF-8 character types supported?
- if (phpbb_pcre_utf8_support())
- {
- $upp = '\p{Lu}';
- $low = '\p{Ll}';
- $num = '\p{N}';
- $sym = '[^\p{Lu}\p{Ll}\p{N}]';
- $pcre = true;
- }
- else if (function_exists('mb_ereg_match'))
- {
- mb_regex_encoding('UTF-8');
- $upp = '[[:upper:]]';
- $low = '[[:lower:]]';
- $num = '[[:digit:]]';
- $sym = '[^[:upper:][:lower:][:digit:]]';
- $mbstring = true;
- }
- else
- {
- $upp = '[A-Z]';
- $low = '[a-z]';
- $num = '[0-9]';
- $sym = '[^A-Za-z0-9]';
- $pcre = true;
- }
-
+ $upp = '\p{Lu}';
+ $low = '\p{Ll}';
+ $num = '\p{N}';
+ $sym = '[^\p{Lu}\p{Ll}\p{N}]';
$chars = array();
switch ($config['pass_complex'])
@@ -1862,24 +1800,11 @@ function validate_password($password)
$chars[] = $upp;
}
- if ($pcre)
+ foreach ($chars as $char)
{
- foreach ($chars as $char)
+ if (!preg_match('#' . $char . '#u', $password))
{
- if (!preg_match('#' . $char . '#u', $password))
- {
- return 'INVALID_CHARS';
- }
- }
- }
- else if ($mbstring)
- {
- foreach ($chars as $char)
- {
- if (mb_ereg($char, $password) === false)
- {
- return 'INVALID_CHARS';
- }
+ return 'INVALID_CHARS';
}
}
@@ -2223,7 +2148,7 @@ function phpbb_style_is_active($style_id)
*/
function avatar_delete($mode, $row, $clean_db = false)
{
- global $phpbb_root_path, $config, $db, $user;
+ global $phpbb_root_path, $config;
// Check if the users avatar is actually *not* a group avatar
if ($mode == 'user')
@@ -2295,7 +2220,10 @@ function phpbb_avatar_explanation_string()
*/
function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow_desc_bbcode = false, $allow_desc_urls = false, $allow_desc_smilies = false)
{
- global $phpbb_root_path, $config, $db, $user, $file_upload, $phpbb_container;
+ global $db, $user, $phpbb_container, $phpbb_log;
+
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
$error = array();
@@ -2327,8 +2255,12 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
$current_legend = \phpbb\groupposition\legend::GROUP_DISABLED;
$current_teampage = \phpbb\groupposition\teampage::GROUP_DISABLED;
+ /* @var $legend \phpbb\groupposition\legend */
$legend = $phpbb_container->get('groupposition.legend');
+
+ /* @var $teampage \phpbb\groupposition\teampage */
$teampage = $phpbb_container->get('groupposition.teampage');
+
if ($group_id)
{
try
@@ -2400,8 +2332,6 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
// Setting the log message before we set the group id (if group gets added)
$log = ($group_id) ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED';
- $query = '';
-
if ($group_id)
{
$sql = 'SELECT user_id
@@ -2544,8 +2474,8 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
group_set_user_default($group_id, $user_ary, $sql_ary);
}
- $name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name;
- add_log('admin', $log, $name);
+ $name = $group_helper->get_name($name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($name));
group_update_listings($group_id);
}
@@ -2583,7 +2513,7 @@ function group_correct_avatar($group_id, $old_entry)
*/
function avatar_remove_db($avatar_name)
{
- global $config, $db;
+ global $db;
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_avatar = '',
@@ -2598,7 +2528,7 @@ function avatar_remove_db($avatar_name)
*/
function group_delete($group_id, $group_name = false)
{
- global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container;
+ global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container, $phpbb_log;
if (!$group_name)
{
@@ -2642,6 +2572,7 @@ function group_delete($group_id, $group_name = false)
// Delete group from legend and teampage
try
{
+ /* @var $legend \phpbb\groupposition\legend */
$legend = $phpbb_container->get('groupposition.legend');
$legend->delete_group($group_id);
unset($legend);
@@ -2655,6 +2586,7 @@ function group_delete($group_id, $group_name = false)
try
{
+ /* @var $teampage \phpbb\groupposition\teampage */
$teampage = $phpbb_container->get('groupposition.teampage');
$teampage->delete_group($group_id);
unset($teampage);
@@ -2695,7 +2627,7 @@ function group_delete($group_id, $group_name = false)
phpbb_cache_moderators($db, $cache, $auth);
- add_log('admin', 'LOG_GROUP_DELETE', $group_name);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_GROUP_DELETE', false, array($group_name));
// Return false - no error
return false;
@@ -2708,7 +2640,7 @@ function group_delete($group_id, $group_name = false)
*/
function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false)
{
- global $db, $auth, $phpbb_container, $phpbb_dispatcher;
+ global $db, $auth, $user, $phpbb_container, $phpbb_log, $phpbb_dispatcher;
// We need both username and user_id info
$result = user_get_id_name($user_id_ary, $username_ary);
@@ -2812,12 +2744,13 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
$log = ($leader) ? 'LOG_MODS_ADDED' : (($pending) ? 'LOG_USERS_PENDING' : 'LOG_USERS_ADDED');
- add_log('admin', $log, $group_name, implode(', ', $username_ary));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary)));
group_update_listings($group_id);
if ($pending)
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
foreach ($add_id_ary as $user_id)
@@ -2843,7 +2776,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
*/
function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $log_action = true)
{
- global $db, $auth, $config, $phpbb_dispatcher, $phpbb_container;
+ global $db, $auth, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_log;
if ($config['coppa_enable'])
{
@@ -2987,12 +2920,13 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
if ($group_name)
{
- add_log('admin', $log, $group_name, implode(', ', $username_ary));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary)));
}
}
group_update_listings($group_id);
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications('notification.type.group_request', $user_id_ary, $group_id);
@@ -3086,7 +3020,7 @@ function remove_default_rank($group_id, $user_ids)
*/
function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false)
{
- global $db, $auth, $phpbb_root_path, $phpEx, $config, $phpbb_container, $phpbb_dispatcher;
+ global $db, $auth, $user, $phpbb_container, $phpbb_log, $phpbb_dispatcher;
// We need both username and user_id info
$result = user_get_id_name($user_id_ary, $username_ary);
@@ -3157,6 +3091,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
AND " . $db->sql_in_set('user_id', $user_id_ary);
$db->sql_query($sql);
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->add_notifications('notification.type.group_request_approved', array(
@@ -3242,7 +3177,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
// Clear permissions cache of relevant users
$auth->acl_clear_prefetch($user_id_ary);
- add_log('admin', $log, $group_name, implode(', ', $username_ary));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary)));
group_update_listings($group_id);
@@ -3254,7 +3189,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
*/
function group_validate_groupname($group_id, $group_name)
{
- global $config, $db;
+ global $db;
$group_name = utf8_clean_string($group_name);
@@ -3302,7 +3237,7 @@ function group_validate_groupname($group_id, $group_name)
*/
function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false)
{
- global $phpbb_container, $db, $phpbb_dispatcher;
+ global $config, $phpbb_container, $db, $phpbb_dispatcher;
if (empty($user_id_ary))
{
@@ -3372,8 +3307,8 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
if (isset($sql_ary[$avatar_option]))
{
$avatar_sql_ary[$avatar_option] = $sql_ary[$avatar_option];
- }
}
+ }
$sql = 'UPDATE ' . USERS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $avatar_sql_ary) . "
@@ -3414,11 +3349,9 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary);
$db->sql_query($sql);
- global $config;
-
if (in_array($config['newest_user_id'], $user_id_ary))
{
- set_config('newest_user_colour', $sql_ary['user_colour'], true);
+ $config->set('newest_user_colour', $sql_ary['user_colour'], false);
}
}
@@ -3453,7 +3386,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
*/
function get_group_name($group_id)
{
- global $db, $user;
+ global $db, $phpbb_container;
$sql = 'SELECT group_name, group_type
FROM ' . GROUPS_TABLE . '
@@ -3462,12 +3395,15 @@ function get_group_name($group_id)
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang)))
+ if (!$row)
{
return '';
}
- return ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
+
+ return $group_helper->get_name($row['group_name']);
}
/**
diff --git a/phpBB/includes/mcp/info/mcp_ban.php b/phpBB/includes/mcp/info/mcp_ban.php
index 4aedbc8558..b4fd32792a 100644
--- a/phpBB/includes/mcp/info/mcp_ban.php
+++ b/phpBB/includes/mcp/info/mcp_ban.php
@@ -18,7 +18,6 @@ class mcp_ban_info
return array(
'filename' => 'mcp_ban',
'title' => 'MCP_BAN',
- 'version' => '1.0.0',
'modes' => array(
'user' => array('title' => 'MCP_BAN_USERNAMES', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')),
'ip' => array('title' => 'MCP_BAN_IPS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')),
diff --git a/phpBB/includes/mcp/info/mcp_logs.php b/phpBB/includes/mcp/info/mcp_logs.php
index c6482c1255..7a0205fce9 100644
--- a/phpBB/includes/mcp/info/mcp_logs.php
+++ b/phpBB/includes/mcp/info/mcp_logs.php
@@ -18,7 +18,6 @@ class mcp_logs_info
return array(
'filename' => 'mcp_logs',
'title' => 'MCP_LOGS',
- 'version' => '1.0.0',
'modes' => array(
'front' => array('title' => 'MCP_LOGS_FRONT', 'auth' => 'acl_m_ || aclf_m_', 'cat' => array('MCP_LOGS')),
'forum_logs' => array('title' => 'MCP_LOGS_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')),
diff --git a/phpBB/includes/mcp/info/mcp_main.php b/phpBB/includes/mcp/info/mcp_main.php
index 81ccdbd1cd..c0f0363255 100644
--- a/phpBB/includes/mcp/info/mcp_main.php
+++ b/phpBB/includes/mcp/info/mcp_main.php
@@ -18,7 +18,6 @@ class mcp_main_info
return array(
'filename' => 'mcp_main',
'title' => 'MCP_MAIN',
- 'version' => '1.0.0',
'modes' => array(
'front' => array('title' => 'MCP_MAIN_FRONT', 'auth' => '', 'cat' => array('MCP_MAIN')),
'forum_view' => array('title' => 'MCP_MAIN_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')),
diff --git a/phpBB/includes/mcp/info/mcp_notes.php b/phpBB/includes/mcp/info/mcp_notes.php
index 4b8c255fe2..de4a41dd80 100644
--- a/phpBB/includes/mcp/info/mcp_notes.php
+++ b/phpBB/includes/mcp/info/mcp_notes.php
@@ -18,7 +18,6 @@ class mcp_notes_info
return array(
'filename' => 'mcp_notes',
'title' => 'MCP_NOTES',
- 'version' => '1.0.0',
'modes' => array(
'front' => array('title' => 'MCP_NOTES_FRONT', 'auth' => '', 'cat' => array('MCP_NOTES')),
'user_notes' => array('title' => 'MCP_NOTES_USER', 'auth' => '', 'cat' => array('MCP_NOTES')),
diff --git a/phpBB/includes/mcp/info/mcp_pm_reports.php b/phpBB/includes/mcp/info/mcp_pm_reports.php
index c80f3b86a3..2a57c0c49a 100644
--- a/phpBB/includes/mcp/info/mcp_pm_reports.php
+++ b/phpBB/includes/mcp/info/mcp_pm_reports.php
@@ -18,7 +18,6 @@ class mcp_pm_reports_info
return array(
'filename' => 'mcp_pm_reports',
'title' => 'MCP_PM_REPORTS',
- 'version' => '1.0.0',
'modes' => array(
'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')),
'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')),
diff --git a/phpBB/includes/mcp/info/mcp_queue.php b/phpBB/includes/mcp/info/mcp_queue.php
index 556c3902b0..d5605aa50e 100644
--- a/phpBB/includes/mcp/info/mcp_queue.php
+++ b/phpBB/includes/mcp/info/mcp_queue.php
@@ -18,7 +18,6 @@ class mcp_queue_info
return array(
'filename' => 'mcp_queue',
'title' => 'MCP_QUEUE',
- 'version' => '1.0.0',
'modes' => array(
'unapproved_topics' => array('title' => 'MCP_QUEUE_UNAPPROVED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')),
'unapproved_posts' => array('title' => 'MCP_QUEUE_UNAPPROVED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')),
diff --git a/phpBB/includes/mcp/info/mcp_reports.php b/phpBB/includes/mcp/info/mcp_reports.php
index 31fee19d79..76e62efe9c 100644
--- a/phpBB/includes/mcp/info/mcp_reports.php
+++ b/phpBB/includes/mcp/info/mcp_reports.php
@@ -18,7 +18,6 @@ class mcp_reports_info
return array(
'filename' => 'mcp_reports',
'title' => 'MCP_REPORTS',
- 'version' => '1.0.0',
'modes' => array(
'reports' => array('title' => 'MCP_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')),
'reports_closed' => array('title' => 'MCP_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')),
diff --git a/phpBB/includes/mcp/info/mcp_warn.php b/phpBB/includes/mcp/info/mcp_warn.php
index d85499f280..b4f83e77c6 100644
--- a/phpBB/includes/mcp/info/mcp_warn.php
+++ b/phpBB/includes/mcp/info/mcp_warn.php
@@ -18,7 +18,6 @@ class mcp_warn_info
return array(
'filename' => 'mcp_warn',
'title' => 'MCP_WARN',
- 'version' => '1.0.0',
'modes' => array(
'front' => array('title' => 'MCP_WARN_FRONT', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')),
'list' => array('title' => 'MCP_WARN_LIST', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')),
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index e4c0640ec7..c8e1e46209 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -36,11 +36,11 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
$merge_select = ($action == 'merge_select' || $action == 'merge_topic' || $action == 'merge_topics') ? true : false;
$forum_id = $forum_info['forum_id'];
- $start = request_var('start', 0);
- $topic_id_list = request_var('topic_id_list', array(0));
- $post_id_list = request_var('post_id_list', array(0));
- $source_topic_ids = array(request_var('t', 0));
- $to_topic_id = request_var('to_topic_id', 0);
+ $start = $request->variable('start', 0);
+ $topic_id_list = $request->variable('topic_id_list', array(0));
+ $post_id_list = $request->variable('post_id_list', array(0));
+ $source_topic_ids = array($request->variable('t', 0));
+ $to_topic_id = $request->variable('to_topic_id', 0);
$url_extra = '';
$url_extra .= ($forum_id) ? "&amp;f=$forum_id" : '';
@@ -54,7 +54,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
switch ($action)
{
case 'resync':
- $topic_ids = request_var('topic_id_list', array(0));
+ $topic_ids = $request->variable('topic_id_list', array(0));
mcp_resync_topics($topic_ids);
break;
@@ -92,6 +92,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
);
extract($phpbb_dispatcher->trigger_event('core.mcp_forum_view_before', compact($vars)));
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
$selected_ids = '';
@@ -145,9 +146,10 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
'S_CAN_SYNC' => $auth->acl_get('m_', $forum_id),
'S_CAN_APPROVE' => $auth->acl_get('m_approve', $forum_id),
'S_MERGE_SELECT' => ($merge_select) ? true : false,
- 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', $forum_id),
+ 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', 'f_announce_global', $forum_id),
'S_CAN_MAKE_STICKY' => $auth->acl_get('f_sticky', $forum_id),
'S_CAN_MAKE_ANNOUNCE' => $auth->acl_get('f_announce', $forum_id),
+ 'S_CAN_MAKE_ANNOUNCE_GLOBAL' => $auth->acl_get('f_announce_global', $forum_id),
'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
'U_VIEW_FORUM_LOGS' => ($auth->acl_gets('a_', 'm_', $forum_id) && $module->loaded('logs')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&amp;mode=forum_logs&amp;f=' . $forum_id) : '',
@@ -172,6 +174,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
$read_tracking_join = $read_tracking_select = '';
}
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
$sql = 'SELECT t.topic_id
@@ -200,9 +203,9 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
$topic_list = $topic_tracking_info = array();
- while ($row = $db->sql_fetchrow($result))
+ while ($row_ary = $db->sql_fetchrow($result))
{
- $topic_list[] = $row['topic_id'];
+ $topic_list[] = $row_ary['topic_id'];
}
$db->sql_freeresult($result);
@@ -211,9 +214,9 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
WHERE " . $db->sql_in_set('t.topic_id', $topic_list, false, true);
$result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
+ while ($row_ary = $db->sql_fetchrow($result))
{
- $topic_rows[$row['topic_id']] = $row;
+ $topic_rows[$row_ary['topic_id']] = $row_ary;
}
$db->sql_freeresult($result);
@@ -238,109 +241,110 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
foreach ($topic_list as $topic_id)
{
- $topic_title = '';
+ $row_ary = &$topic_rows[$topic_id];
- $row = &$topic_rows[$topic_id];
+ $replies = $phpbb_content_visibility->get_count('topic_posts', $row_ary, $forum_id) - 1;
- $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
-
- if ($row['topic_status'] == ITEM_MOVED)
+ if ($row_ary['topic_status'] == ITEM_MOVED)
{
$unread_topic = false;
}
else
{
- $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
+ $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row_ary['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
}
// Get folder img, topic status/type related information
$folder_img = $folder_alt = $topic_type = '';
- topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
+ topic_status($row_ary, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
- $topic_title = censor_text($row['topic_title']);
+ $topic_title = censor_text($row_ary['topic_title']);
- $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false;
- $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false;
- $topic_deleted = $row['topic_visibility'] == ITEM_DELETED;
- $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&amp;i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&amp;t=' . $row['topic_id'] : '';
+ $topic_unapproved = (($row_ary['topic_visibility'] == ITEM_UNAPPROVED || $row_ary['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row_ary['forum_id'])) ? true : false;
+ $posts_unapproved = ($row_ary['topic_visibility'] == ITEM_APPROVED && $row_ary['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row_ary['forum_id'])) ? true : false;
+ $topic_deleted = $row_ary['topic_visibility'] == ITEM_DELETED;
+ $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&amp;i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&amp;t=' . $row_ary['topic_id'] : '';
$u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? $url . '&amp;i=queue&amp;mode=deleted_topics&amp;t=' . $topic_id : $u_mcp_queue;
$topic_row = array(
- 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
+ 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row_ary['forum_id']) && $row_ary['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
'TOPIC_IMG_STYLE' => $folder_img,
'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt),
- 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
- 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
- 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
+ 'TOPIC_ICON_IMG' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['img'] : '',
+ 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['width'] : '',
+ 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['height'] : '',
'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '',
'DELETED_IMG' => ($topic_deleted) ? $user->img('icon_topic_deleted', 'TOPIC_DELETED') : '',
- 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
- 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
- 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
- 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
+ 'TOPIC_AUTHOR' => get_username_string('username', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']),
+ 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']),
+ 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']),
+ 'U_TOPIC_AUTHOR' => get_username_string('profile', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']),
- 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
- 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
- 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
- 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
+ 'LAST_POST_AUTHOR' => get_username_string('username', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
+ 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
+ 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
+ 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
'TOPIC_TYPE' => $topic_type,
'TOPIC_TITLE' => $topic_title,
- 'REPLIES' => $phpbb_content_visibility->get_count('topic_posts', $row, $row['forum_id']) - 1,
- 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
- 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
- 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'],
- 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
+ 'REPLIES' => $phpbb_content_visibility->get_count('topic_posts', $row_ary, $row_ary['forum_id']) - 1,
+ 'LAST_POST_TIME' => $user->format_date($row_ary['topic_last_post_time']),
+ 'FIRST_POST_TIME' => $user->format_date($row_ary['topic_time']),
+ 'LAST_POST_SUBJECT' => $row_ary['topic_last_post_subject'],
+ 'LAST_VIEW_TIME' => $user->format_date($row_ary['topic_last_view_time']),
- 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false,
+ 'S_TOPIC_REPORTED' => (!empty($row_ary['topic_reported']) && empty($row_ary['topic_moved_id']) && $auth->acl_get('m_report', $row_ary['forum_id'])) ? true : false,
'S_TOPIC_UNAPPROVED' => $topic_unapproved,
'S_POSTS_UNAPPROVED' => $posts_unapproved,
'S_TOPIC_DELETED' => $topic_deleted,
'S_UNREAD_TOPIC' => $unread_topic,
);
- if ($row['topic_status'] == ITEM_MOVED)
+ if ($row_ary['topic_status'] == ITEM_MOVED)
{
$topic_row = array_merge($topic_row, array(
- 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_moved_id']}"),
- 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;topic_id_list[]={$row['topic_id']}&amp;mode=forum_view&amp;action=delete_topic") : '',
+ 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row_ary['topic_moved_id']}"),
+ 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;topic_id_list[]={$row_ary['topic_id']}&amp;mode=forum_view&amp;action=delete_topic") : '',
'S_MOVED_TOPIC' => true,
- 'TOPIC_ID' => $row['topic_moved_id'],
+ 'TOPIC_ID' => $row_ary['topic_moved_id'],
));
}
else
{
if ($action == 'merge_topic' || $action == 'merge_topics')
{
- $u_select_topic = $url . "&amp;i=$id&amp;mode=forum_view&amp;action=$action&amp;to_topic_id=" . $row['topic_id'] . $selected_ids;
+ $u_select_topic = $url . "&amp;i=$id&amp;mode=forum_view&amp;action=$action&amp;to_topic_id=" . $row_ary['topic_id'] . $selected_ids;
}
else
{
- $u_select_topic = $url . "&amp;i=$id&amp;mode=topic_view&amp;action=merge&amp;to_topic_id=" . $row['topic_id'] . $selected_ids;
+ $u_select_topic = $url . "&amp;i=$id&amp;mode=topic_view&amp;action=merge&amp;to_topic_id=" . $row_ary['topic_id'] . $selected_ids;
}
$topic_row = array_merge($topic_row, array(
- 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;t={$row['topic_id']}&amp;mode=topic_view"),
+ 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;t={$row_ary['topic_id']}&amp;mode=topic_view"),
- 'S_SELECT_TOPIC' => ($merge_select && !in_array($row['topic_id'], $source_topic_ids)) ? true : false,
+ 'S_SELECT_TOPIC' => ($merge_select && !in_array($row_ary['topic_id'], $source_topic_ids)) ? true : false,
'U_SELECT_TOPIC' => $u_select_topic,
'U_MCP_QUEUE' => $u_mcp_queue,
- 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=topic_view&amp;t=' . $row['topic_id'] . '&amp;action=reports') : '',
- 'TOPIC_ID' => $row['topic_id'],
- 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row['topic_id'], $topic_id_list)) ? true : false,
+ 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=topic_view&amp;t=' . $row_ary['topic_id'] . '&amp;action=reports') : '',
+ 'TOPIC_ID' => $row_ary['topic_id'],
+ 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row_ary['topic_id'], $topic_id_list)) ? true : false,
));
}
+ $row = $row_ary;
/**
* Modify the topic data before it is assigned to the template in MCP
*
* @event core.mcp_view_forum_modify_topicrow
- * @var array row Array with topic data
+ * @var array row Array with topic data
* @var array topic_row Template array with topic data
* @since 3.1.0-a1
*/
$vars = array('row', 'topic_row');
extract($phpbb_dispatcher->trigger_event('core.mcp_view_forum_modify_topicrow', compact($vars)));
+ $row_ary = $row;
+ unset($row);
$template->assign_block_vars('topicrow', $topic_row);
}
@@ -352,7 +356,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
*/
function mcp_resync_topics($topic_ids)
{
- global $auth, $db, $template, $phpEx, $user, $phpbb_root_path;
+ global $db, $user, $phpbb_log, $request;
if (!sizeof($topic_ids))
{
@@ -377,13 +381,17 @@ function mcp_resync_topics($topic_ids)
// Log this action
while ($row = $db->sql_fetchrow($result))
{
- add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_TOPIC_RESYNC', $row['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_RESYNC', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $row['topic_id'],
+ $row['topic_title']
+ ));
}
$db->sql_freeresult($result);
$msg = (sizeof($topic_ids) == 1) ? $user->lang['TOPIC_RESYNC_SUCCESS'] : $user->lang['TOPICS_RESYNC_SUCCESS'];
- $redirect = request_var('redirect', $user->data['session_page']);
+ $redirect = $request->variable('redirect', $user->data['session_page']);
meta_refresh(3, $redirect);
trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'));
@@ -396,7 +404,7 @@ function mcp_resync_topics($topic_ids)
*/
function merge_topics($forum_id, $topic_ids, $to_topic_id)
{
- global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $phpbb_dispatcher;
+ global $db, $template, $user, $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher;
if (!sizeof($topic_ids))
{
@@ -429,8 +437,8 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
$to_topic_data = $all_topic_data[$to_topic_id];
- $post_id_list = request_var('post_id_list', array(0));
- $start = request_var('start', 0);
+ $post_id_list = $request->variable('post_id_list', array(0));
+ $start = $request->variable('start', 0);
if (!sizeof($post_id_list) && sizeof($topic_ids))
{
@@ -458,7 +466,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
return;
}
- $redirect = request_var('redirect', build_url(array('quickmod')));
+ $redirect = $request->variable('redirect', build_url(array('quickmod')));
$s_hidden_fields = build_hidden_fields(array(
'i' => 'main',
@@ -471,14 +479,19 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
'redirect' => $redirect,
'topic_id_list' => $topic_ids)
);
- $success_msg = $return_link = '';
+ $return_link = '';
if (confirm_box(true))
{
$to_forum_id = $to_topic_data['forum_id'];
move_posts($post_id_list, $to_topic_id, false);
- add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $to_topic_data['topic_title']);
+
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MERGE', false, array(
+ 'forum_id' => $to_forum_id,
+ 'topic_id' => $to_topic_id,
+ $to_topic_data['topic_title']
+ ));
// Update topic views count
$sql = 'UPDATE ' . TOPICS_TABLE . '
@@ -508,7 +521,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
// Link to the new topic
$return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
- $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
+ $redirect = $request->variable('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
$redirect = reapply_sid($redirect);
/**
diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php
index 5d8aa18c16..aeb716c1f9 100644
--- a/phpBB/includes/mcp/mcp_front.php
+++ b/phpBB/includes/mcp/mcp_front.php
@@ -24,9 +24,9 @@ if (!defined('IN_PHPBB'))
*/
function mcp_front_view($id, $mode, $action)
{
- global $phpEx, $phpbb_root_path, $config;
+ global $phpEx, $phpbb_root_path;
global $template, $db, $user, $auth, $module;
- global $phpbb_dispatcher;
+ global $phpbb_dispatcher, $request;
// Latest 5 unapproved
if ($module->loaded('queue'))
@@ -35,7 +35,7 @@ function mcp_front_view($id, $mode, $action)
$post_list = array();
$forum_names = array();
- $forum_id = request_var('f', 0);
+ $forum_id = $request->variable('f', 0);
$template->assign_var('S_SHOW_UNAPPROVED', (!empty($forum_list)) ? true : false);
diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php
index 9c76f0df90..c34c915a40 100644
--- a/phpBB/includes/mcp/mcp_logs.php
+++ b/phpBB/includes/mcp/mcp_logs.php
@@ -35,12 +35,12 @@ class mcp_logs
function main($id, $mode)
{
- global $auth, $db, $user, $template;
- global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_log;
+ global $auth, $db, $user, $template, $request;
+ global $config, $phpbb_container, $phpbb_log;
$user->add_lang('acp/common');
- $action = request_var('action', array('' => ''));
+ $action = $request->variable('action', array('' => ''));
if (is_array($action))
{
@@ -48,23 +48,24 @@ class mcp_logs
}
else
{
- $action = request_var('action', '');
+ $action = $request->variable('action', '');
}
// Set up general vars
- $start = request_var('start', 0);
+ $start = $request->variable('start', 0);
$deletemark = ($action == 'del_marked') ? true : false;
$deleteall = ($action == 'del_all') ? true : false;
- $marked = request_var('mark', array(0));
+ $marked = $request->variable('mark', array(0));
// Sort keys
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 't');
- $sort_dir = request_var('sd', 'd');
+ $sort_days = $request->variable('st', 0);
+ $sort_key = $request->variable('sk', 't');
+ $sort_dir = $request->variable('sd', 'd');
$this->tpl_name = 'mcp_logs';
$this->page_title = 'MCP_LOGS';
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
$forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_')));
@@ -78,10 +79,11 @@ class mcp_logs
break;
case 'forum_logs':
- $forum_id = request_var('f', 0);
+ $forum_id = $request->variable('f', 0);
if (!in_array($forum_id, $forum_list))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -89,7 +91,7 @@ class mcp_logs
break;
case 'topic_logs':
- $topic_id = request_var('t', 0);
+ $topic_id = $request->variable('t', 0);
$sql = 'SELECT forum_id
FROM ' . TOPICS_TABLE . '
@@ -100,6 +102,7 @@ class mcp_logs
if (!in_array($forum_id, $forum_list))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -123,7 +126,7 @@ class mcp_logs
}
else if ($deleteall)
{
- $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords = $request->variable('keywords', '', true);
$conditions = array(
'forum_id' => array('IN' => $forum_list),
@@ -157,7 +160,7 @@ class mcp_logs
'sd' => $sort_dir,
'i' => $id,
'mode' => $mode,
- 'action' => request_var('action', array('' => ''))))
+ 'action' => $request->variable('action', array('' => ''))))
);
}
}
@@ -174,7 +177,7 @@ class mcp_logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
- $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords = $request->variable('keywords', '', true);
$keywords_param = !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
// Grab log data
@@ -204,7 +207,7 @@ class mcp_logs
{
$data = array();
- $checks = array('viewtopic', 'viewforum');
+ $checks = array('viewpost', 'viewtopic', 'viewforum');
foreach ($checks as $check)
{
if (isset($row[$check]) && $row[$check])
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index b2441aed1b..0270166ad0 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -35,8 +35,8 @@ class mcp_main
function main($id, $mode)
{
- global $auth, $db, $user, $template, $action;
- global $config, $phpbb_root_path, $phpEx, $request;
+ global $auth, $user, $action;
+ global $phpbb_root_path, $phpEx, $request;
global $phpbb_dispatcher;
$quickmod = ($mode == 'quickmod') ? true : false;
@@ -45,7 +45,7 @@ class mcp_main
{
case 'lock':
case 'unlock':
- $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
+ $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
if (!sizeof($topic_ids))
{
@@ -58,7 +58,7 @@ class mcp_main
case 'lock_post':
case 'unlock_post':
- $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0));
+ $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0));
if (!sizeof($post_ids))
{
@@ -73,7 +73,7 @@ class mcp_main
case 'make_global':
case 'make_normal':
- $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
+ $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
if (!sizeof($topic_ids))
{
@@ -86,7 +86,7 @@ class mcp_main
case 'move':
$user->add_lang('viewtopic');
- $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
+ $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
if (!sizeof($topic_ids))
{
@@ -99,7 +99,7 @@ class mcp_main
case 'fork':
$user->add_lang('viewtopic');
- $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
+ $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
if (!sizeof($topic_ids))
{
@@ -189,7 +189,7 @@ class mcp_main
$user->add_lang('viewforum');
- $forum_id = request_var('f', 0);
+ $forum_id = $request->variable('f', 0);
$forum_info = phpbb_get_forum_data($forum_id, 'm_', true);
@@ -262,7 +262,7 @@ class mcp_main
*/
function lock_unlock($action, $ids)
{
- global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_dispatcher;
+ global $user, $db, $request, $phpbb_log, $phpbb_dispatcher;
if ($action == 'lock' || $action == 'unlock')
{
@@ -298,7 +298,7 @@ function lock_unlock($action, $ids)
}
unset($orig_ids);
- $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
+ $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
$redirect = reapply_sid($redirect);
$s_hidden_fields = build_hidden_fields(array(
@@ -306,7 +306,6 @@ function lock_unlock($action, $ids)
'action' => $action,
'redirect' => $redirect)
);
- $success_msg = '';
if (confirm_box(true))
{
@@ -319,7 +318,12 @@ function lock_unlock($action, $ids)
foreach ($data as $id => $row)
{
- add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($action), false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $row['topic_id'],
+ 'post_id' => isset($row['post_id']) ? $row['post_id'] : 0,
+ $row['topic_title']
+ ));
}
/**
@@ -362,7 +366,7 @@ function lock_unlock($action, $ids)
*/
function change_topic_type($action, $topic_ids)
{
- global $auth, $user, $db, $phpEx, $phpbb_root_path, $request;
+ global $user, $db, $request, $phpbb_log;
switch ($action)
{
@@ -374,7 +378,7 @@ function change_topic_type($action, $topic_ids)
case 'make_global':
$new_topic_type = POST_GLOBAL;
- $check_acl = 'f_announce';
+ $check_acl = 'f_announce_global';
$l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS';
break;
@@ -398,7 +402,7 @@ function change_topic_type($action, $topic_ids)
return;
}
- $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
+ $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
$redirect = reapply_sid($redirect);
$s_hidden_fields = array(
@@ -407,7 +411,6 @@ function change_topic_type($action, $topic_ids)
'action' => $action,
'redirect' => $redirect,
);
- $success_msg = '';
if (confirm_box(true))
{
@@ -437,7 +440,11 @@ function change_topic_type($action, $topic_ids)
foreach ($data as $topic_id => $row)
{
- add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_TYPE_CHANGED', false, array(
+ 'forum_id' => $forum_id,
+ 'topic_id' => $topic_id,
+ $row['topic_title']
+ ));
}
}
@@ -474,8 +481,8 @@ function mcp_move_topic($topic_ids)
return;
}
- $to_forum_id = request_var('to_forum_id', 0);
- $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
+ $to_forum_id = $request->variable('to_forum_id', 0);
+ $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
$additional_msg = $success_msg = '';
$s_hidden_fields = build_hidden_fields(array(
@@ -695,7 +702,7 @@ function mcp_move_topic($topic_ids)
confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
}
- $redirect = request_var('redirect', "index.$phpEx");
+ $redirect = $request->variable('redirect', "index.$phpEx");
$redirect = reapply_sid($redirect);
if (!$success_msg)
@@ -720,7 +727,7 @@ function mcp_move_topic($topic_ids)
*/
function mcp_restore_topic($topic_ids)
{
- global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;
+ global $user, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log;
if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve')))
{
@@ -744,13 +751,19 @@ function mcp_restore_topic($topic_ids)
$data = phpbb_get_topic_data($topic_ids);
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
foreach ($data as $topic_id => $row)
{
$return = $phpbb_content_visibility->set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), '');
if (!empty($return))
{
- add_log('mod', $row['forum_id'], $topic_id, 'LOG_RESTORE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_RESTORE_TOPIC', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $topic_id,
+ $row['topic_title'],
+ $row['topic_first_poster_name']
+ ));
}
}
}
@@ -793,7 +806,7 @@ function mcp_restore_topic($topic_ids)
*/
function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic')
{
- global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;
+ global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log;
$check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array($check_permission)))
@@ -822,30 +835,47 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = ''
{
if ($row['topic_moved_id'])
{
- add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_SHADOW_TOPIC', $row['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_SHADOW_TOPIC', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $topic_id,
+ $row['topic_title']
+ ));
}
else
{
// Only soft delete non-shadow topics
if ($is_soft)
{
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
$return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason);
if (!empty($return))
{
- add_log('mod', $row['forum_id'], $topic_id, 'LOG_SOFTDELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_TOPIC', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $topic_id,
+ $row['topic_title'],
+ $row['topic_first_poster_name'],
+ $soft_delete_reason
+ ));
}
}
else
{
- add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_TOPIC', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $topic_id,
+ $row['topic_title'],
+ $row['topic_first_poster_name'],
+ $soft_delete_reason
+ ));
}
}
}
if (!$is_soft)
{
- $return = delete_topics('topic_id', $topic_ids);
+ delete_topics('topic_id', $topic_ids);
}
}
else
@@ -933,7 +963,7 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = ''
*/
function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post')
{
- global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;
+ global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log;
$check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission)))
@@ -983,6 +1013,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',
$approve_log[] = array(
'forum_id' => $post_data['forum_id'],
'topic_id' => $post_data['topic_id'],
+ 'post_id' => $post_id,
'post_subject' => $post_data['post_subject'],
'poster_id' => $post_data['poster_id'],
'post_username' => $post_data['post_username'],
@@ -990,6 +1021,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',
);
}
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
foreach ($topic_info as $topic_id => $topic_data)
{
@@ -1004,7 +1036,14 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',
foreach ($approve_log as $row)
{
$post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
- add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_SOFTDELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_POST', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $row['topic_id'],
+ 'post_id' => $row['post_id'],
+ $row['post_subject'],
+ $post_username,
+ $soft_delete_reason
+ ));
}
$topic_id = $request->variable('t', 0);
@@ -1047,7 +1086,14 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',
foreach ($post_data as $id => $row)
{
$post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
- add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_POST', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $row['topic_id'],
+ 'post_id' => $row['post_id'],
+ $row['post_subject'],
+ $post_username,
+ $soft_delete_reason
+ ));
}
// Now delete the posts, topics and forums are automatically resync'ed
@@ -1162,16 +1208,16 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '',
function mcp_fork_topic($topic_ids)
{
global $auth, $user, $db, $template, $config;
- global $phpEx, $phpbb_root_path, $phpbb_dispatcher;
+ global $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher;
if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_')))
{
return;
}
- $to_forum_id = request_var('to_forum_id', 0);
- $forum_id = request_var('f', 0);
- $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
+ $to_forum_id = $request->variable('to_forum_id', 0);
+ $forum_id = $request->variable('f', 0);
+ $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
$additional_msg = $success_msg = '';
$counter = array();
@@ -1301,8 +1347,6 @@ function mcp_fork_topic($topic_ids)
if ($topic_row['poll_start'])
{
- $poll_rows = array();
-
$sql = 'SELECT *
FROM ' . POLL_OPTIONS_TABLE . "
WHERE topic_id = $topic_id";
@@ -1515,12 +1559,16 @@ function mcp_fork_topic($topic_ids)
sync('topic', 'topic_id', $new_topic_id_list);
sync('forum', 'forum_id', $to_forum_id);
- set_config_count('num_topics', sizeof($new_topic_id_list), true);
- set_config_count('num_posts', $total_posts, true);
+ $config->increment('num_topics', sizeof($new_topic_id_list), false);
+ $config->increment('num_posts', $total_posts, false);
foreach ($new_topic_id_list as $topic_id => $new_topic_id)
{
- add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_FORK', false, array(
+ 'forum_id' => $to_forum_id,
+ 'topic_id' => $new_topic_id,
+ $topic_row['forum_name']
+ ));
}
$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS';
@@ -1536,7 +1584,7 @@ function mcp_fork_topic($topic_ids)
confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
}
- $redirect = request_var('redirect', "index.$phpEx");
+ $redirect = $request->variable('redirect', "index.$phpEx");
$redirect = reapply_sid($redirect);
if (!$success_msg)
diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php
index 465ee63a98..67f59bd618 100644
--- a/phpBB/includes/mcp/mcp_notes.php
+++ b/phpBB/includes/mcp/mcp_notes.php
@@ -35,10 +35,10 @@ class mcp_notes
function main($id, $mode)
{
- global $auth, $db, $user, $template;
- global $config, $phpbb_root_path, $phpEx;
+ global $user, $template, $request;
+ global $phpbb_root_path, $phpEx;
- $action = request_var('action', array('' => ''));
+ $action = $request->variable('action', array('' => ''));
if (is_array($action))
{
@@ -74,15 +74,17 @@ class mcp_notes
*/
function mcp_notes_user_view($action)
{
- global $phpEx, $phpbb_root_path, $config;
+ global $config, $phpbb_log, $request;
global $template, $db, $user, $auth, $phpbb_container;
- $user_id = request_var('u', 0);
- $username = request_var('username', '', true);
- $start = request_var('start', 0);
- $st = request_var('st', 0);
- $sk = request_var('sk', 'b');
- $sd = request_var('sd', 'd');
+ $user_id = $request->variable('u', 0);
+ $username = $request->variable('username', '', true);
+ $start = $request->variable('start', 0);
+ $st = $request->variable('st', 0);
+ $sk = $request->variable('sk', 'b');
+ $sd = $request->variable('sd', 'd');
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
add_form_key('mcp_notes');
@@ -114,8 +116,8 @@ class mcp_notes
$deletemark = ($action == 'del_marked') ? true : false;
$deleteall = ($action == 'del_all') ? true : false;
- $marked = request_var('marknote', array(0));
- $usernote = utf8_normalize_nfc(request_var('usernote', '', true));
+ $marked = $request->variable('marknote', array(0));
+ $usernote = $request->variable('usernote', '', true);
// Handle any actions
if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs'))
@@ -142,7 +144,7 @@ class mcp_notes
$where_sql";
$db->sql_query($sql);
- add_log('admin', 'LOG_CLEAR_USER', $userrow['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CLEAR_USER', false, array($userrow['username']));
$msg = ($deletemark) ? 'MARKED_NOTES_DELETED' : 'ALL_NOTES_DELETED';
}
@@ -160,10 +162,17 @@ class mcp_notes
{
if (check_form_key('mcp_notes'))
{
- add_log('admin', 'LOG_USER_FEEDBACK', $userrow['username']);
- add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $userrow['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array($userrow['username']));
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_FEEDBACK', false, array(
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $userrow['username']
+ ));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GENERAL', false, array(
+ 'reportee_id' => $user_id,
+ $usernote
+ ));
- add_log('user', $user_id, 'LOG_USER_GENERAL', $usernote);
$msg = $user->lang['USER_FEEDBACK_ADDED'];
}
else
@@ -192,7 +201,7 @@ class mcp_notes
$sql_where = ($st) ? (time() - ($st * 86400)) : 0;
$sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC');
- $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords = $request->variable('keywords', '', true);
$keywords_param = !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
$log_data = array();
diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php
index d76bedba98..67a1a959e4 100644
--- a/phpBB/includes/mcp/mcp_pm_reports.php
+++ b/phpBB/includes/mcp/mcp_pm_reports.php
@@ -35,14 +35,15 @@ class mcp_pm_reports
function main($id, $mode)
{
- global $auth, $db, $user, $template, $cache;
+ global $auth, $db, $user, $template, $request;
global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
- $start = request_var('start', 0);
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
+ $start = $request->variable('start', 0);
$this->page_title = 'MCP_PM_REPORTS';
@@ -52,7 +53,7 @@ class mcp_pm_reports
case 'delete':
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $report_id_list = request_var('report_id_list', array(0));
+ $report_id_list = $request->variable('report_id_list', array(0));
if (!sizeof($report_id_list))
{
@@ -75,7 +76,7 @@ class mcp_pm_reports
$user->add_lang(array('posting', 'viewforum', 'viewtopic', 'ucp'));
- $report_id = request_var('r', 0);
+ $report_id = $request->variable('r', 0);
$sql = 'SELECT r.pm_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour
FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u
@@ -93,9 +94,10 @@ class mcp_pm_reports
trigger_error('NO_REPORT');
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
- $phpbb_notifications->mark_notifications_read_by_parent('notification.type.report_pm', $report_id, $user->data['user_id']);
+ $phpbb_notifications->mark_notifications_by_parent('report_pm', $report_id, $user->data['user_id']);
$pm_id = $report['pm_id'];
$report_id = $report['report_id'];
@@ -199,7 +201,7 @@ class mcp_pm_reports
'POST_SUBJECT' => ($pm_info['message_subject']) ? $pm_info['message_subject'] : $user->lang['NO_SUBJECT'],
'POST_DATE' => $user->format_date($pm_info['message_time']),
'POST_IP' => $pm_info['author_ip'],
- 'POST_IPADDR' => ($auth->acl_getf_global('m_info') && request_var('lookup', '')) ? @gethostbyaddr($pm_info['author_ip']) : '',
+ 'POST_IPADDR' => ($auth->acl_getf_global('m_info') && $request->variable('lookup', '')) ? @gethostbyaddr($pm_info['author_ip']) : '',
'POST_ID' => $pm_info['msg_id'],
'U_LOOKUP_IP' => ($auth->acl_getf_global('m_info')) ? $this->u_action . '&amp;r=' . $report_id . '&amp;pm=' . $pm_id . '&amp;lookup=' . $pm_info['author_ip'] . '#ip' : '',
diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php
index 2dcfcd608b..7fa6ef4fff 100644
--- a/phpBB/includes/mcp/mcp_post.php
+++ b/phpBB/includes/mcp/mcp_post.php
@@ -24,14 +24,14 @@ if (!defined('IN_PHPBB'))
*/
function mcp_post_details($id, $mode, $action)
{
- global $phpEx, $phpbb_root_path, $config;
- global $template, $db, $user, $auth, $cache;
+ global $phpEx, $phpbb_root_path, $config, $request;
+ global $template, $db, $user, $auth;
global $phpbb_dispatcher;
$user->add_lang('posting');
- $post_id = request_var('p', 0);
- $start = request_var('start', 0);
+ $post_id = $request->variable('p', 0);
+ $start = $request->variable('start', 0);
// Get post data
$post_info = phpbb_get_post_data(array($post_id), false, true);
@@ -52,7 +52,7 @@ function mcp_post_details($id, $mode, $action)
if ($auth->acl_get('m_info', $post_info['forum_id']))
{
- $ip = request_var('ip', '');
+ $ip = $request->variable('ip', '');
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
$template->assign_vars(array(
@@ -73,12 +73,12 @@ function mcp_post_details($id, $mode, $action)
if ($action == 'chgposter')
{
- $username = request_var('username', '', true);
+ $username = $request->variable('username', '', true);
$sql_where = "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
}
else
{
- $new_user_id = request_var('u', 0);
+ $new_user_id = $request->variable('u', 0);
$sql_where = 'user_id = ' . $new_user_id;
}
@@ -128,7 +128,6 @@ function mcp_post_details($id, $mode, $action)
$users_ary = $usernames_ary = array();
$attachments = $extensions = array();
$post_id = $post_info['post_id'];
- $topic_tracking_info = array();
// Get topic tracking info
if ($config['load_db_lastread'])
@@ -150,8 +149,6 @@ function mcp_post_details($id, $mode, $action)
if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id']))
{
- $extensions = $cache->obtain_attach_extensions($post_info['forum_id']);
-
$sql = 'SELECT *
FROM ' . ATTACHMENTS_TABLE . '
WHERE post_msg_id = ' . $post_id . '
@@ -260,7 +257,7 @@ function mcp_post_details($id, $mode, $action)
'POST_SUBJECT' => $post_info['post_subject'],
'POST_DATE' => $user->format_date($post_info['post_time']),
'POST_IP' => $post_info['poster_ip'],
- 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($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'],
'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? "$url&amp;i=$id&amp;mode=$mode&amp;lookup={$post_info['poster_ip']}#ip" : '',
@@ -355,7 +352,7 @@ function mcp_post_details($id, $mode, $action)
// Get IP
if ($auth->acl_get('m_info', $post_info['forum_id']))
{
- $rdns_ip_num = request_var('rdns', '');
+ $rdns_ip_num = $request->variable('rdns', '');
if ($rdns_ip_num != 'all')
{
@@ -461,7 +458,7 @@ function mcp_post_details($id, $mode, $action)
*/
function change_poster(&$post_info, $userdata)
{
- global $auth, $db, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher;
+ global $auth, $db, $config, $phpbb_root_path, $phpEx, $user, $phpbb_log, $phpbb_dispatcher;
if (empty($userdata) || $userdata['user_id'] == $post_info['user_id'])
{
@@ -572,5 +569,12 @@ function change_poster(&$post_info, $userdata)
$post_info = $post_info[$post_id];
// Now add log entry
- add_log('mod', $post_info['forum_id'], $post_info['topic_id'], 'LOG_MCP_CHANGE_POSTER', $post_info['topic_title'], $from_username, $to_username);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MCP_CHANGE_POSTER', false, array(
+ 'forum_id' => $post_info['forum_id'],
+ 'topic_id' => $post_info['topic_id'],
+ 'post_id' => $post_info['post_id'],
+ $post_info['topic_title'],
+ $from_username,
+ $to_username
+ ));
}
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index 3567e545f0..9060cc1098 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -35,14 +35,14 @@ class mcp_queue
public function main($id, $mode)
{
- global $auth, $db, $user, $template, $cache, $request;
+ global $auth, $db, $user, $template, $request;
global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container;
global $phpbb_dispatcher;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
- $forum_id = request_var('f', 0);
- $start = request_var('start', 0);
+ $forum_id = $request->variable('f', 0);
+ $start = $request->variable('start', 0);
$this->page_title = 'MCP_QUEUE';
@@ -104,7 +104,7 @@ class mcp_queue
if (!empty($topic_id_list) && $mode == 'deleted_topics')
{
- if (!function_exists('mcp_delete_topics'))
+ if (!function_exists('mcp_delete_topic'))
{
global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx);
@@ -154,9 +154,10 @@ class mcp_queue
$user->add_lang(array('posting', 'viewtopic'));
- $post_id = request_var('p', 0);
- $topic_id = request_var('t', 0);
+ $post_id = $request->variable('p', 0);
+ $topic_id = $request->variable('t', 0);
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
if ($topic_id)
@@ -166,7 +167,7 @@ class mcp_queue
{
$post_id = (int) $topic_info[$topic_id]['topic_first_post_id'];
- $phpbb_notifications->mark_notifications_read('notification.type.topic_in_queue', $topic_id, $user->data['user_id']);
+ $phpbb_notifications->mark_notifications('topic_in_queue', $topic_id, $user->data['user_id']);
}
else
{
@@ -174,7 +175,7 @@ class mcp_queue
}
}
- $phpbb_notifications->mark_notifications_read('notification.type.post_in_queue', $post_id, $user->data['user_id']);
+ $phpbb_notifications->mark_notifications('post_in_queue', $post_id, $user->data['user_id']);
$post_info = phpbb_get_post_data(array($post_id), 'm_approve', true);
@@ -194,7 +195,7 @@ class mcp_queue
));
}
- $extensions = $attachments = $topic_tracking_info = array();
+ $attachments = $topic_tracking_info = array();
// Get topic tracking info
if ($config['load_db_lastread'])
@@ -216,8 +217,6 @@ class mcp_queue
if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id']))
{
- $extensions = $cache->obtain_attach_extensions($post_info['forum_id']);
-
$sql = 'SELECT *
FROM ' . ATTACHMENTS_TABLE . '
WHERE post_msg_id = ' . $post_id . '
@@ -320,7 +319,7 @@ class mcp_queue
'POST_SUBJECT' => $post_info['post_subject'],
'POST_DATE' => $user->format_date($post_info['post_time']),
'POST_IP' => $post_info['poster_ip'],
- 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($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'],
'S_FIRST_POST' => ($post_info['topic_first_post_id'] == $post_id),
@@ -342,6 +341,8 @@ class mcp_queue
$topic_id = $request->variable('t', 0);
$forum_info = array();
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
if ($topic_id)
@@ -399,7 +400,6 @@ class mcp_queue
trigger_error('NOT_MODERATOR');
}
- $forum_info = $forum_info[$forum_id];
$forum_list = $forum_id;
}
@@ -414,7 +414,6 @@ class mcp_queue
$sort_by_sql = $sort_order_sql = array();
phpbb_mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id);
- $forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total;
$limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : '';
$forum_names = array();
@@ -618,17 +617,18 @@ class mcp_queue
*/
static public function approve_posts($action, $post_id_list, $id, $mode)
{
- global $db, $template, $user, $config, $request, $phpbb_container, $phpbb_dispatcher;
- global $phpEx, $phpbb_root_path;
+ global $template, $user, $request, $phpbb_container, $phpbb_dispatcher;
+ global $phpEx, $phpbb_root_path, $phpbb_log;
if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
$redirect = $request->variable('redirect', build_url(array('quickmod')));
$redirect = reapply_sid($redirect);
- $success_msg = $post_url = '';
+ $post_url = '';
$approve_log = array();
$num_topics = 0;
@@ -677,10 +677,12 @@ class mcp_queue
$approve_log[] = array(
'forum_id' => $post_data['forum_id'],
'topic_id' => $post_data['topic_id'],
+ 'post_id' => $post_id,
'post_subject' => $post_data['post_subject'],
);
}
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
foreach ($topic_info as $topic_id => $topic_data)
{
@@ -689,12 +691,18 @@ class mcp_queue
foreach ($approve_log as $log_data)
{
- add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_POST_' . strtoupper($action) . 'D', $log_data['post_subject']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_' . strtoupper($action) . 'D', false, array(
+ 'forum_id' => $log_data['forum_id'],
+ 'topic_id' => $log_data['topic_id'],
+ 'post_id' => $log_data['post_id'],
+ $log_data['post_subject']
+ ));
}
// Only send out the mails, when the posts are being approved
if ($action == 'approve')
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
// Handle notifications
@@ -731,7 +739,7 @@ class mcp_queue
$phpbb_notifications->add_notifications(array('notification.type.quote'), $post_data);
$phpbb_notifications->delete_notifications('notification.type.post_in_queue', $post_id);
- $phpbb_notifications->mark_notifications_read(array(
+ $phpbb_notifications->mark_notifications(array(
'notification.type.quote',
'notification.type.bookmark',
'notification.type.post',
@@ -865,11 +873,12 @@ class mcp_queue
*/
static public function approve_topics($action, $topic_id_list, $id, $mode)
{
- global $db, $template, $user, $config;
+ global $db, $template, $user, $phpbb_log;
global $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_dispatcher;
if (!phpbb_check_ids($topic_id_list, TOPICS_TABLE, 'topic_id', array('m_approve')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -892,6 +901,7 @@ class mcp_queue
{
$notify_poster = ($action == 'approve' && isset($_REQUEST['notify_poster'])) ? true : false;
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
$first_post_ids = array();
@@ -916,7 +926,11 @@ class mcp_queue
foreach ($approve_log as $log_data)
{
- add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_TOPIC_' . strtoupper($action) . 'D', $log_data['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_' . strtoupper($action) . 'D', false, array(
+ 'forum_id' => $log_data['forum_id'],
+ 'topic_id' => $log_data['topic_id'],
+ $log_data['topic_title']
+ ));
}
// Only send out the mails, when the posts are being approved
@@ -935,6 +949,7 @@ class mcp_queue
$db->sql_freeresult($result);
// Handle notifications
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
foreach ($topic_info as $topic_id => $topic_data)
@@ -961,8 +976,8 @@ class mcp_queue
), $topic_data);
}
- $phpbb_notifications->mark_notifications_read('notification.type.quote', $topic_data['post_id'], $user->data['user_id']);
- $phpbb_notifications->mark_notifications_read('notification.type.topic', $topic_id, $user->data['user_id']);
+ $phpbb_notifications->mark_notifications('quote', $topic_data['post_id'], $user->data['user_id']);
+ $phpbb_notifications->mark_notifications('topic', $topic_id, $user->data['user_id']);
if ($notify_poster)
{
@@ -1056,11 +1071,12 @@ class mcp_queue
*/
static public function disapprove_posts($post_id_list, $id, $mode)
{
- global $db, $template, $user, $config, $phpbb_container, $phpbb_dispatcher;
- global $phpEx, $phpbb_root_path, $request;
+ global $db, $template, $user, $phpbb_container, $phpbb_dispatcher;
+ global $phpEx, $phpbb_root_path, $request, $phpbb_log;
if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -1068,7 +1084,7 @@ class mcp_queue
$redirect = reapply_sid($redirect);
$reason = $request->variable('reason', '', true);
$reason_id = $request->variable('reason_id', 0);
- $success_msg = $additional_msg = '';
+ $additional_msg = '';
$s_hidden_fields = build_hidden_fields(array(
'i' => $id,
@@ -1126,7 +1142,7 @@ class mcp_queue
if (confirm_box(true))
{
- $disapprove_log = $disapprove_log_topics = $disapprove_log_posts = array();
+ $disapprove_log_topics = $disapprove_log_posts = array();
$topic_posts_unapproved = $post_disapprove_list = $topic_information = array();
// Build a list of posts to be disapproved and get the related topics real replies count
@@ -1217,16 +1233,28 @@ class mcp_queue
if ($is_disapproving)
{
$l_log_message = ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED';
- add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $disapprove_reason, $log_data['post_username']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $l_log_message, false, array(
+ 'forum_id' => $log_data['forum_id'],
+ 'topic_id' => $log_data['topic_id'],
+ $log_data['post_subject'],
+ $disapprove_reason,
+ $log_data['post_username']
+ ));
}
else
{
$l_log_message = ($log_data['type'] == 'topic') ? 'LOG_DELETE_TOPIC' : 'LOG_DELETE_POST';
- add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $log_data['post_username']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, $l_log_message, false, array(
+ 'forum_id' => $log_data['forum_id'],
+ 'topic_id' => $log_data['topic_id'],
+ $log_data['post_subject'],
+ $log_data['post_username']
+ ));
}
}
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$lang_reasons = array();
@@ -1388,11 +1416,6 @@ class mcp_queue
}
else
{
- if (!function_exists('display_reasons'))
- {
- include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
- }
-
$show_notify = false;
foreach ($post_info as $post_data)
@@ -1412,7 +1435,7 @@ class mcp_queue
$confirm_template = 'mcp_approve.html';
if ($is_disapproving)
{
- display_reasons($reason_id);
+ $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id);
}
else
{
diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php
index 6bb606a990..1462acf110 100644
--- a/phpBB/includes/mcp/mcp_reports.php
+++ b/phpBB/includes/mcp/mcp_reports.php
@@ -35,13 +35,13 @@ class mcp_reports
function main($id, $mode)
{
- global $auth, $db, $user, $template, $cache;
+ global $auth, $db, $user, $template, $request;
global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container, $phpbb_dispatcher;
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
- $forum_id = request_var('f', 0);
- $start = request_var('start', 0);
+ $forum_id = $request->variable('f', 0);
+ $start = $request->variable('start', 0);
$this->page_title = 'MCP_REPORTS';
@@ -51,7 +51,7 @@ class mcp_reports
case 'delete':
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $report_id_list = request_var('report_id_list', array(0));
+ $report_id_list = $request->variable('report_id_list', array(0));
if (!sizeof($report_id_list))
{
@@ -69,10 +69,11 @@ class mcp_reports
$user->add_lang(array('posting', 'viewforum', 'viewtopic'));
- $post_id = request_var('p', 0);
+ $post_id = $request->variable('p', 0);
// closed reports are accessed by report id
- $report_id = request_var('r', 0);
+ $report_id = $request->variable('r', 0);
+
$sql_ary = array(
'SELECT' => 'r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour',
@@ -138,9 +139,10 @@ class mcp_reports
trigger_error('NO_REPORT');
}
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
- $phpbb_notifications->mark_notifications_read('notification.type.report_post', $post_id, $user->data['user_id']);
+ $phpbb_notifications->mark_notifications('report_post', $post_id, $user->data['user_id']);
if (!$report_id && $report['report_closed'])
{
@@ -180,7 +182,7 @@ class mcp_reports
));
}
- $topic_tracking_info = $extensions = $attachments = array();
+ $attachments = array();
// Get topic tracking info
if ($config['load_db_lastread'])
{
@@ -287,7 +289,7 @@ class mcp_reports
'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'],
'POST_DATE' => $user->format_date($post_info['post_time']),
'POST_IP' => $post_info['poster_ip'],
- 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($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'],
'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? $this->u_action . '&amp;r=' . $report_id . '&amp;p=' . $post_id . '&amp;f=' . $forum_id . '&amp;lookup=' . $post_info['poster_ip'] . '#ip' : '',
@@ -299,7 +301,7 @@ class mcp_reports
case 'reports':
case 'reports_closed':
- $topic_id = request_var('t', 0);
+ $topic_id = $request->variable('t', 0);
$forum_info = array();
$forum_list_reports = get_forum_list('m_report', false, true);
@@ -349,8 +351,6 @@ class mcp_reports
trigger_error('NOT_MODERATOR');
}
- $global_id = $forum_list[0];
-
$sql = 'SELECT SUM(forum_topics_approved) as sum_forum_topics
FROM ' . FORUMS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $forum_list);
@@ -367,13 +367,13 @@ class mcp_reports
trigger_error('NOT_MODERATOR');
}
- $forum_info = $forum_info[$forum_id];
$forum_list = array($forum_id);
}
+ /* @var $pagination \phpbb\pagination */
+ $pagination = $phpbb_container->get('pagination');
$forum_list[] = 0;
$forum_data = array();
- $pagination = $phpbb_container->get('pagination');
$forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>';
foreach ($forum_list_reports as $row)
@@ -388,7 +388,6 @@ class mcp_reports
$sort_by_sql = $sort_order_sql = array();
phpbb_mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id);
- $forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total;
$limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : '';
if ($mode == 'reports')
@@ -457,7 +456,6 @@ class mcp_reports
ORDER BY ' . $sort_order_sql;
$result = $db->sql_query($sql);
- $report_data = $rowset = array();
while ($row = $db->sql_fetchrow($result))
{
$template->assign_block_vars('postrow', array(
@@ -519,7 +517,7 @@ class mcp_reports
*/
function close_report($report_id_list, $mode, $action, $pm = false)
{
- global $db, $template, $user, $config, $auth;
+ global $db, $user, $auth, $phpbb_log, $request;
global $phpEx, $phpbb_root_path, $phpbb_container;
$pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 ';
@@ -544,6 +542,7 @@ function close_report($report_id_list, $mode, $action, $pm = false)
{
if (!$auth->acl_getf_global('m_report'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
}
@@ -551,25 +550,26 @@ function close_report($report_id_list, $mode, $action, $pm = false)
{
if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
}
if ($action == 'delete' && strpos($user->data['session_page'], 'mode=report_details') !== false)
{
- $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&amp;mode=reports');
+ $redirect = $request->variable('redirect', build_url(array('mode', 'r', 'quickmod')) . '&amp;mode=reports');
}
else if ($action == 'delete' && strpos($user->data['session_page'], 'mode=pm_report_details') !== false)
{
- $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&amp;mode=pm_reports');
+ $redirect = $request->variable('redirect', build_url(array('mode', 'r', 'quickmod')) . '&amp;mode=pm_reports');
}
- else if ($action == 'close' && !request_var('r', 0))
+ else if ($action == 'close' && !$request->variable('r', 0))
{
- $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&amp;mode=' . $module);
+ $redirect = $request->variable('redirect', build_url(array('mode', 'p', 'quickmod')) . '&amp;mode=' . $module);
}
else
{
- $redirect = request_var('redirect', build_url(array('quickmod')));
+ $redirect = $request->variable('redirect', build_url(array('quickmod')));
}
$success_msg = '';
$forum_ids = array();
@@ -694,18 +694,28 @@ function close_report($report_id_list, $mode, $action, $pm = false)
}
unset($close_report_posts, $close_report_topics);
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
foreach ($reports as $report)
{
if ($pm)
{
- add_log('mod', 0, 0, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', $post_info[$report['pm_id']]['message_subject']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', false, array(
+ 'forum_id' => 0,
+ 'topic_id' => 0,
+ $post_info[$report['pm_id']]['message_subject']
+ ));
$phpbb_notifications->delete_notifications('notification.type.report_pm', $report['pm_id']);
}
else
{
- add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_REPORT_' . strtoupper($action) . 'D', false, array(
+ 'forum_id' => $post_info[$report['post_id']]['forum_id'],
+ 'topic_id' => $post_info[$report['post_id']]['topic_id'],
+ 'post_id' => $report['post_id'],
+ $post_info[$report['post_id']]['post_subject']
+ ));
$phpbb_notifications->delete_notifications('notification.type.report_post', $report['post_id']);
}
}
@@ -758,7 +768,7 @@ function close_report($report_id_list, $mode, $action, $pm = false)
confirm_box(false, $user->lang[strtoupper($action) . "_{$pm_prefix}REPORT" . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields);
}
- $redirect = request_var('redirect', "index.$phpEx");
+ $redirect = $request->variable('redirect', "index.$phpEx");
$redirect = reapply_sid($redirect);
if (!$success_msg)
diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php
index 2217f8fdeb..ba86484040 100644
--- a/phpBB/includes/mcp/mcp_topic.php
+++ b/phpBB/includes/mcp/mcp_topic.php
@@ -24,15 +24,16 @@ if (!defined('IN_PHPBB'))
*/
function mcp_topic_view($id, $mode, $action)
{
- global $phpEx, $phpbb_root_path, $config;
- global $template, $db, $user, $auth, $cache, $phpbb_container, $phpbb_dispatcher;
+ global $phpEx, $phpbb_root_path, $config, $request;
+ global $template, $db, $user, $auth, $phpbb_container, $phpbb_dispatcher;
$url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . phpbb_extra_url());
- $user->add_lang('viewtopic');
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
+ $user->add_lang('viewtopic');
- $topic_id = request_var('t', 0);
+ $topic_id = $request->variable('t', 0);
$topic_info = phpbb_get_topic_data(array($topic_id), false, true);
if (!sizeof($topic_info))
@@ -43,16 +44,16 @@ function mcp_topic_view($id, $mode, $action)
$topic_info = $topic_info[$topic_id];
// Set up some vars
- $icon_id = request_var('icon', 0);
- $subject = utf8_normalize_nfc(request_var('subject', '', true));
- $start = request_var('start', 0);
- $sort_days_old = request_var('st_old', 0);
- $forum_id = request_var('f', 0);
- $to_topic_id = request_var('to_topic_id', 0);
- $to_forum_id = request_var('to_forum_id', 0);
+ $icon_id = $request->variable('icon', 0);
+ $subject = $request->variable('subject', '', true);
+ $start = $request->variable('start', 0);
+ $sort_days_old = $request->variable('st_old', 0);
+ $forum_id = $request->variable('f', 0);
+ $to_topic_id = $request->variable('to_topic_id', 0);
+ $to_forum_id = $request->variable('to_forum_id', 0);
$sort = isset($_POST['sort']) ? true : false;
- $submitted_id_list = request_var('post_ids', array(0));
- $checked_ids = $post_id_list = request_var('post_id_list', array(0));
+ $submitted_id_list = $request->variable('post_ids', array(0));
+ $checked_ids = $post_id_list = $request->variable('post_id_list', array(0));
// Resync Topic?
if ($action == 'resync')
@@ -116,15 +117,16 @@ function mcp_topic_view($id, $mode, $action)
$sort_by_sql = $sort_order_sql = array();
phpbb_mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $topic_info['forum_id'], $topic_id, $where_sql);
- $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
+ $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
if ($total == -1)
{
$total = $phpbb_content_visibility->get_count('topic_posts', $topic_info, $topic_info['forum_id']);
}
- $posts_per_page = max(0, request_var('posts_per_page', intval($config['posts_per_page'])));
+ $posts_per_page = max(0, $request->variable('posts_per_page', intval($config['posts_per_page'])));
if ($posts_per_page == 0)
{
$posts_per_page = $total;
@@ -154,8 +156,6 @@ function mcp_topic_view($id, $mode, $action)
}
$db->sql_freeresult($result);
- $topic_tracking_info = array();
-
// Get topic tracking info
if ($config['load_db_lastread'])
{
@@ -171,11 +171,9 @@ function mcp_topic_view($id, $mode, $action)
$has_unapproved_posts = $has_deleted_posts = false;
// Grab extensions
- $extensions = $attachments = array();
+ $attachments = array();
if ($topic_info['topic_attachment'] && sizeof($post_id_list))
{
- $extensions = $cache->obtain_attach_extensions($topic_info['forum_id']);
-
// Get attachments...
if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $topic_info['forum_id']))
{
@@ -269,8 +267,6 @@ function mcp_topic_view($id, $mode, $action)
'U_MCP_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $topic_info['forum_id'] . '&amp;p=' . $row['post_id']) : '',
);
- $current_row_number = $i;
-
/**
* Event to modify the template data block for topic reviews in the MCP
*
@@ -406,11 +402,11 @@ function mcp_topic_view($id, $mode, $action)
*/
function split_topic($action, $topic_id, $to_forum_id, $subject)
{
- global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config;
+ global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log, $request;
- $post_id_list = request_var('post_id_list', array(0));
- $forum_id = request_var('forum_id', 0);
- $start = request_var('start', 0);
+ $post_id_list = $request->variable('post_id_list', array(0));
+ $forum_id = $request->variable('forum_id', 0);
+ $start = $request->variable('start', 0);
if (!sizeof($post_id_list))
{
@@ -464,7 +460,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
return;
}
- $redirect = request_var('redirect', build_url(array('quickmod')));
+ $redirect = $request->variable('redirect', build_url(array('quickmod')));
$s_hidden_fields = build_hidden_fields(array(
'i' => 'main',
@@ -477,9 +473,8 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
'redirect' => $redirect,
'subject' => $subject,
'to_forum_id' => $to_forum_id,
- 'icon' => request_var('icon', 0))
+ 'icon' => $request->variable('icon', 0))
);
- $success_msg = $return_link = '';
if (confirm_box(true))
{
@@ -540,7 +535,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
trigger_error('NO_POST_SELECTED');
}
- $icon_id = request_var('icon', 0);
+ $icon_id = $request->variable('icon', 0);
$sql_ary = array(
'forum_id' => $to_forum_id,
@@ -558,8 +553,16 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
$topic_info = phpbb_get_topic_data(array($topic_id));
$topic_info = $topic_info[$topic_id];
- add_log('mod', $to_forum_id, $to_topic_id, 'LOG_SPLIT_DESTINATION', $subject);
- add_log('mod', $forum_id, $topic_id, 'LOG_SPLIT_SOURCE', $topic_info['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SPLIT_DESTINATION', false, array(
+ 'forum_id' => $to_forum_id,
+ 'topic_id' => $to_topic_id,
+ $subject
+ ));
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SPLIT_SOURCE', false, array(
+ 'forum_id' => $forum_id,
+ 'topic_id' => $topic_id,
+ $topic_info['topic_title']
+ ));
// Change topic title of first post
$sql = 'UPDATE ' . POSTS_TABLE . "
@@ -613,11 +616,11 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
$success_msg = 'TOPIC_SPLIT_SUCCESS';
// Update forum statistics
- set_config_count('num_topics', 1, true);
+ $config->increment('num_topics', 1, false);
// Link back to both topics
$return_link = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&amp;t=' . $post_info['topic_id']) . '">', '</a>') . '<br /><br />' . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
- $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
+ $redirect = $request->variable('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
$redirect = reapply_sid($redirect);
meta_refresh(3, $redirect);
@@ -634,7 +637,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
*/
function merge_posts($topic_id, $to_topic_id)
{
- global $db, $template, $user, $phpEx, $phpbb_root_path, $auth;
+ global $db, $template, $user, $phpEx, $phpbb_root_path, $phpbb_log, $request;
if (!$to_topic_id)
{
@@ -660,8 +663,8 @@ function merge_posts($topic_id, $to_topic_id)
$topic_data = $topic_data[$to_topic_id];
- $post_id_list = request_var('post_id_list', array(0));
- $start = request_var('start', 0);
+ $post_id_list = $request->variable('post_id_list', array(0));
+ $start = $request->variable('start', 0);
if (!sizeof($post_id_list))
{
@@ -674,7 +677,7 @@ function merge_posts($topic_id, $to_topic_id)
return;
}
- $redirect = request_var('redirect', build_url(array('quickmod')));
+ $redirect = $request->variable('redirect', build_url(array('quickmod')));
$s_hidden_fields = build_hidden_fields(array(
'i' => 'main',
@@ -686,14 +689,19 @@ function merge_posts($topic_id, $to_topic_id)
'redirect' => $redirect,
't' => $topic_id)
);
- $success_msg = $return_link = '';
+ $return_link = '';
if (confirm_box(true))
{
$to_forum_id = $topic_data['forum_id'];
move_posts($post_id_list, $to_topic_id, false);
- add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']);
+
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MERGE', false, array(
+ 'forum_id' => $to_forum_id,
+ 'topic_id' => $to_topic_id,
+ $topic_data['topic_title']
+ ));
// Message and return links
$success_msg = 'POSTS_MERGED_SUCCESS';
@@ -732,7 +740,7 @@ function merge_posts($topic_id, $to_topic_id)
// Link to the new topic
$return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
- $redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
+ $redirect = $request->variable('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
$redirect = reapply_sid($redirect);
meta_refresh(3, $redirect);
diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php
index 33c898ffc2..0e80372f43 100644
--- a/phpBB/includes/mcp/mcp_warn.php
+++ b/phpBB/includes/mcp/mcp_warn.php
@@ -35,10 +35,9 @@ class mcp_warn
function main($id, $mode)
{
- global $auth, $db, $user, $template;
- global $config, $phpbb_root_path, $phpEx;
+ global $request;
- $action = request_var('action', array('' => ''));
+ $action = $request->variable('action', array('' => ''));
if (is_array($action))
{
@@ -78,8 +77,8 @@ class mcp_warn
*/
function mcp_warn_front_view()
{
- global $phpEx, $phpbb_root_path, $config;
- global $template, $db, $user, $auth;
+ global $phpEx, $phpbb_root_path;
+ global $template, $db, $user;
$template->assign_vars(array(
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=mcp&amp;field=username&amp;select_single=true'),
@@ -132,15 +131,16 @@ class mcp_warn
function mcp_warn_list_view($action)
{
global $phpEx, $phpbb_root_path, $config, $phpbb_container;
- global $template, $db, $user, $auth;
+ global $template, $user, $auth, $request;
- $user->add_lang('memberlist');
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
+ $user->add_lang('memberlist');
- $start = request_var('start', 0);
- $st = request_var('st', 0);
- $sk = request_var('sk', 'b');
- $sd = request_var('sd', 'd');
+ $start = $request->variable('start', 0);
+ $st = $request->variable('st', 0);
+ $sk = $request->variable('sk', 'b');
+ $sd = $request->variable('sd', 'd');
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_WARNINGS']);
@@ -189,13 +189,13 @@ class mcp_warn
*/
function mcp_warn_post_view($action)
{
- global $phpEx, $phpbb_root_path, $config;
- global $template, $db, $user, $auth, $phpbb_dispatcher;
+ global $phpEx, $phpbb_root_path, $config, $request;
+ global $template, $db, $user, $phpbb_dispatcher;
- $post_id = request_var('p', 0);
- $forum_id = request_var('f', 0);
+ $post_id = $request->variable('p', 0);
+ $forum_id = $request->variable('f', 0);
$notify = (isset($_REQUEST['notify_user'])) ? true : false;
- $warning = utf8_normalize_nfc(request_var('warning', '', true));
+ $warning = $request->variable('warning', '', true);
$sql = 'SELECT u.*, p.*
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
@@ -369,13 +369,13 @@ class mcp_warn
*/
function mcp_warn_user_view($action)
{
- global $phpEx, $phpbb_root_path, $config, $module;
- global $template, $db, $user, $auth, $phpbb_dispatcher;
+ global $phpEx, $phpbb_root_path, $config, $request;
+ global $template, $db, $user, $phpbb_dispatcher;
- $user_id = request_var('u', 0);
- $username = request_var('username', '', true);
+ $user_id = $request->variable('u', 0);
+ $username = $request->variable('username', '', true);
$notify = (isset($_REQUEST['notify_user'])) ? true : false;
- $warning = utf8_normalize_nfc(request_var('warning', '', true));
+ $warning = $request->variable('warning', '', true);
$sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
@@ -522,8 +522,8 @@ class mcp_warn
*/
function add_warning($user_row, $warning, $send_pm = true, $post_id = 0)
{
- global $phpEx, $phpbb_root_path, $config;
- global $template, $db, $user, $auth;
+ global $phpEx, $phpbb_root_path, $config, $phpbb_log;
+ global $db, $user;
if ($send_pm)
{
@@ -572,8 +572,11 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0)
submit_pm('post', $warn_pm_subject, $pm_data, false);
}
- add_log('admin', 'LOG_USER_WARNING', $user_row['username']);
- $log_id = add_log('user', $user_row['user_id'], 'LOG_USER_WARNING_BODY', $warning);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING', false, array($user_row['username']));
+ $log_id = $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING_BODY', false, array(
+ 'reportee_id' => $user_row['user_id'],
+ $warning
+ ));
$sql_ary = array(
'user_id' => $user_row['user_id'],
@@ -598,5 +601,10 @@ function add_warning($user_row, $warning, $send_pm = true, $post_id = 0)
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_USER_WARNING', $user_row['username']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_USER_WARNING', false, array(
+ 'forum_id' => $row['forum_id'],
+ 'topic_id' => $row['topic_id'],
+ 'post_id' => $post_id,
+ $user_row['username']
+ ));
}
diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php
index 16b65fb83e..c68ff87cd7 100644
--- a/phpBB/includes/message_parser.php
+++ b/phpBB/includes/message_parser.php
@@ -83,7 +83,14 @@ class bbcode_firstpass extends bbcode
// it should not demand recompilation
if (preg_match($regexp, $this->message))
{
- $this->message = preg_replace($regexp, $replacement, $this->message);
+ if (is_callable($replacement))
+ {
+ $this->message = preg_replace_callback($regexp, $replacement, $this->message);
+ }
+ else
+ {
+ $this->message = preg_replace($regexp, $replacement, $this->message);
+ }
$bitfield->set($bbcode_data['bbcode_id']);
}
}
@@ -123,6 +130,8 @@ class bbcode_firstpass extends bbcode
static $rowset;
+ $bbcode_class = $this;
+
// This array holds all bbcode data. BBCodes will be processed in this
// order, so it is important to keep [code] in first position and
// [quote] in second position.
@@ -132,19 +141,71 @@ class bbcode_firstpass extends bbcode
// To perform custom validation in extension, use $this->validate_bbcode_by_extension()
// method which accepts variable number of parameters
$this->bbcodes = array(
- 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uise' => "\$this->bbcode_code('\$1', '\$2')")),
- 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:=&quot;(.*?)&quot;)?\](.+)\[/quote\]#uise' => "\$this->bbcode_quote('\$0')")),
- 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uise' => "\$this->bbcode_attachment('\$1', '\$2')")),
- 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->bbcode_strong('\$1')")),
- 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uise' => "\$this->bbcode_italic('\$1')")),
- 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiUe' => "\$this->validate_url('\$2', ('\$3') ? '\$3' : '\$4')")),
- 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiUe' => "\$this->bbcode_img('\$1')")),
- 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uise' => "\$this->bbcode_size('\$1', '\$2')")),
- 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uise' => "\$this->bbcode_color('\$1', '\$2')")),
- 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uise' => "\$this->bbcode_underline('\$1')")),
- 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uise' => "\$this->bbcode_parse_list('\$0')")),
- 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uise' => "\$this->validate_email('\$1', '\$2')")),
- 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#uie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')"))
+ 'code' => array('bbcode_id' => BBCODE_ID_CODE, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_code($match[1], $match[2]);
+ }
+ )),
+ 'quote' => array('bbcode_id' => BBCODE_ID_QUOTE, 'regexp' => array('#\[quote(?:=&quot;(.*?)&quot;)?\](.+)\[/quote\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_quote($match[0]);
+ }
+ )),
+ 'attachment' => array('bbcode_id' => BBCODE_ID_ATTACH, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_attachment($match[1], $match[2]);
+ }
+ )),
+ 'b' => array('bbcode_id' => BBCODE_ID_B, 'regexp' => array('#\[b\](.*?)\[/b\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_strong($match[1]);
+ }
+ )),
+ 'i' => array('bbcode_id' => BBCODE_ID_I, 'regexp' => array('#\[i\](.*?)\[/i\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_italic($match[1]);
+ }
+ )),
+ 'url' => array('bbcode_id' => BBCODE_ID_URL, 'regexp' => array('#\[url(=(.*))?\](?(1)((?s).*(?-s))|(.*))\[/url\]#uiU' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->validate_url($match[2], ($match[3]) ? $match[3] : $match[4]);
+ }
+ )),
+ 'img' => array('bbcode_id' => BBCODE_ID_IMG, 'regexp' => array('#\[img\](.*)\[/img\]#uiU' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_img($match[1]);
+ }
+ )),
+ 'size' => array('bbcode_id' => BBCODE_ID_SIZE, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_size($match[1], $match[2]);
+ }
+ )),
+ 'color' => array('bbcode_id' => BBCODE_ID_COLOR, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_color($match[1], $match[2]);
+ }
+ )),
+ 'u' => array('bbcode_id' => BBCODE_ID_U, 'regexp' => array('#\[u\](.*?)\[/u\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_underline($match[1]);
+ }
+ )),
+ 'list' => array('bbcode_id' => BBCODE_ID_LIST, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_parse_list($match[0]);
+ }
+ )),
+ 'email' => array('bbcode_id' => BBCODE_ID_EMAIL, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uis' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->validate_email($match[1], $match[2]);
+ }
+ )),
+ 'flash' => array('bbcode_id' => BBCODE_ID_FLASH, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ui' => function ($match) use($bbcode_class)
+ {
+ return $bbcode_class->bbcode_flash($match[1], $match[2], $match[3]);
+ }
+ ))
);
// Zero the parsed items array
@@ -342,22 +403,23 @@ class bbcode_firstpass extends bbcode
if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width'])
{
- $stats = @getimagesize(htmlspecialchars_decode($in));
+ $imagesize = new \FastImageSize\FastImageSize();
+ $size_info = $imagesize->getImageSize(htmlspecialchars_decode($in));
- if ($stats === false)
+ if ($size_info === false)
{
$error = true;
$this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
}
else
{
- if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1])
+ if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $size_info['height'])
{
$error = true;
$this->warn_msg[] = $user->lang('MAX_IMG_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']);
}
- if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0])
+ if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $size_info['width'])
{
$error = true;
$this->warn_msg[] = $user->lang('MAX_IMG_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']);
@@ -736,8 +798,6 @@ class bbcode_firstpass extends bbcode
*/
function bbcode_quote($in)
{
- global $config, $user;
-
$in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in)));
if (!$in)
@@ -746,7 +806,9 @@ class bbcode_firstpass extends bbcode
}
// To let the parser not catch tokens within quote_username quotes we encode them before we start this...
- $in = preg_replace('#quote=&quot;(.*?)&quot;\]#ie', "'quote=&quot;' . str_replace(array('[', ']', '\\\"'), array('&#91;', '&#93;', '\"'), '\$1') . '&quot;]'", $in);
+ $in = preg_replace_callback('#quote=&quot;(.*?)&quot;\]#i', function ($match) {
+ return 'quote=&quot;' . str_replace(array('[', ']', '\\\"'), array('&#91;', '&#93;', '\"'), $match[1]) . '&quot;]';
+ }, $in);
$tok = ']';
$out = '[';
@@ -945,8 +1007,6 @@ class bbcode_firstpass extends bbcode
*/
function validate_url($var1, $var2)
{
- global $config;
-
$var1 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var1)));
$var2 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var2)));
@@ -1077,12 +1137,6 @@ class parse_message extends bbcode_firstpass
protected $plupload;
/**
- * The mimetype guesser object used for attachment mimetypes
- * @var \phpbb\mimetype\guesser
- */
- protected $mimetype_guesser;
-
- /**
* Init - give message here or manually
*/
function parse_message($message = '')
@@ -1097,7 +1151,7 @@ class parse_message extends bbcode_firstpass
*/
function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post')
{
- global $config, $db, $user, $phpbb_dispatcher;
+ global $config, $user, $phpbb_dispatcher, $phpbb_container;
$this->mode = $mode;
@@ -1126,12 +1180,6 @@ class parse_message extends bbcode_firstpass
$this->decode_message();
}
- // Do some general 'cleanup' first before processing message,
- // e.g. remove excessive newlines(?), smilies(?)
- $match = array('#(script|about|applet|activex|chrome):#i');
- $replace = array("\\1&#058;");
- $this->message = preg_replace($match, $replace, trim($this->message));
-
// Store message length...
$message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message));
@@ -1204,56 +1252,29 @@ class parse_message extends bbcode_firstpass
return (!$update_this_message) ? $return_message : $this->warn_msg;
}
- // Prepare BBcode (just prepares some tags for better parsing)
- if ($allow_bbcode && strpos($this->message, '[') !== false)
- {
- $this->bbcode_init();
- $disallow = array('img', 'flash', 'quote', 'url');
- foreach ($disallow as $bool)
- {
- if (!${'allow_' . $bool . '_bbcode'})
- {
- $this->bbcodes[$bool]['disabled'] = true;
- }
- }
-
- $this->prepare_bbcodes();
- }
-
- // Parse smilies
- if ($allow_smilies)
- {
- $this->smilies($config['max_' . $mode . '_smilies']);
- }
-
- $num_urls = 0;
-
- // Parse BBCode
- if ($allow_bbcode && strpos($this->message, '[') !== false)
- {
- $this->parse_bbcode();
- $num_urls += $this->parsed_items['url'];
- }
+ // Get the parser
+ $parser = $phpbb_container->get('text_formatter.parser');
- // Parse URL's
- if ($allow_magic_url)
- {
- $this->magic_url(generate_board_url());
+ // Set the parser's options
+ ($allow_bbcode) ? $parser->enable_bbcodes() : $parser->disable_bbcodes();
+ ($allow_magic_url) ? $parser->enable_magic_url() : $parser->disable_magic_url();
+ ($allow_smilies) ? $parser->enable_smilies() : $parser->disable_smilies();
+ ($allow_img_bbcode) ? $parser->enable_bbcode('img') : $parser->disable_bbcode('img');
+ ($allow_flash_bbcode) ? $parser->enable_bbcode('flash') : $parser->disable_bbcode('flash');
+ ($allow_quote_bbcode) ? $parser->enable_bbcode('quote') : $parser->disable_bbcode('quote');
+ ($allow_url_bbcode) ? $parser->enable_bbcode('url') : $parser->disable_bbcode('url');
- if ($config['max_' . $mode . '_urls'])
- {
- $num_urls += preg_match_all('#\<!-- ([lmwe]) --\>.*?\<!-- \1 --\>#', $this->message, $matches);
- }
- }
+ // Set some config values
+ $parser->set_vars(array(
+ 'max_font_size' => $config['max_' . $this->mode . '_font_size'],
+ 'max_img_height' => $config['max_' . $this->mode . '_img_height'],
+ 'max_img_width' => $config['max_' . $this->mode . '_img_width'],
+ 'max_smilies' => $config['max_' . $this->mode . '_smilies'],
+ 'max_urls' => $config['max_' . $this->mode . '_urls']
+ ));
- // Check for out-of-bounds characters that are currently
- // not supported by utf8_bin in MySQL
- if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $this->message, $matches))
- {
- $character_list = implode('<br />', $matches[0]);
- $this->warn_msg[] = $user->lang('UNSUPPORTED_CHARACTERS_MESSAGE', $character_list);
- return $update_this_message ? $this->warn_msg : $return_message;
- }
+ // Parse this message
+ $this->message = $parser->parse(htmlspecialchars_decode($this->message, ENT_QUOTES));
// Remove quotes that are nested too deep
if ($config['max_quote_depth'] > 0)
@@ -1269,10 +1290,27 @@ class parse_message extends bbcode_firstpass
return (!$update_this_message) ? $return_message : $this->warn_msg;
}
- // Check number of links
- if ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls'])
+ // Remove quotes that are nested too deep
+ if ($config['max_quote_depth'] > 0)
+ {
+ $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode(
+ $this->message,
+ 'quote',
+ $config['max_quote_depth']
+ );
+ }
+
+ // Check for errors
+ $errors = $parser->get_errors();
+ if ($errors)
{
- $this->warn_msg[] = sprintf($user->lang['TOO_MANY_URLS'], $config['max_' . $mode . '_urls']);
+ foreach ($errors as $i => $args)
+ {
+ // Translate each error with $user->lang()
+ $errors[$i] = call_user_func_array(array($user, 'lang'), $args);
+ }
+ $this->warn_msg = array_merge($this->warn_msg, $errors);
+
return (!$update_this_message) ? $return_message : $this->warn_msg;
}
@@ -1292,7 +1330,7 @@ class parse_message extends bbcode_firstpass
*/
function format_display($allow_bbcode, $allow_magic_url, $allow_smilies, $update_this_message = true)
{
- global $phpbb_dispatcher;
+ global $phpbb_container, $phpbb_dispatcher;
// If false, then the parsed message get returned but internal message not processed.
if (!$update_this_message)
@@ -1324,26 +1362,25 @@ class parse_message extends bbcode_firstpass
$this->bbcode_uid = $uid;
unset($text, $uid);
- if ($this->message_status == 'plain')
+ // NOTE: message_status is unreliable for detecting unparsed text because some callers
+ // change $this->message without resetting $this->message_status to 'plain' so we
+ // inspect the message instead
+ //if ($this->message_status == 'plain')
+ if (!preg_match('/^<[rt][ >]/', $this->message))
{
// Force updating message - of course.
$this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true);
}
- // Replace naughty words such as farty pants
- $this->message = censor_text($this->message);
-
- // Parse BBcode
- if ($allow_bbcode)
+ // There's a bug when previewing a topic with no poll, because the empty title of the poll
+ // gets parsed but $this->message still ends up empty. This fixes it, until a proper fix is
+ // devised
+ if ($this->message === '')
{
- $this->bbcode_cache_init();
-
- // We are giving those parameters to be able to use the bbcode class on its own
- $this->bbcode_second_pass($this->message, $this->bbcode_uid);
+ $this->message = $phpbb_container->get('text_formatter.parser')->parse($this->message);
}
- $this->message = bbcode_nl2br($this->message);
- $this->message = smiley_text($this->message, !$allow_smilies);
+ $this->message = $phpbb_container->get('text_formatter.renderer')->render($this->message);
$text = $this->message;
$uid = $this->bbcode_uid;
@@ -1433,7 +1470,6 @@ class parse_message extends bbcode_firstpass
// For now setting the ttl to 10 minutes
switch ($db->get_sql_layer())
{
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$sql = 'SELECT *
@@ -1494,11 +1530,12 @@ class parse_message extends bbcode_firstpass
function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
{
global $config, $auth, $user, $phpbb_root_path, $phpEx, $db, $request;
+ global $phpbb_container;
$error = array();
$num_attachments = sizeof($this->attachment_data);
- $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true));
+ $this->filename_data['filecomment'] = $request->variable('filecomment', '', true);
$upload = $request->file($form_name);
$upload_file = (!empty($upload) && $upload['name'] !== 'none' && trim($upload['name']));
@@ -1506,7 +1543,7 @@ class parse_message extends bbcode_firstpass
$delete_file = (isset($_POST['delete_file'])) ? true : false;
// First of all adjust comments if changed
- $actual_comment_list = utf8_normalize_nfc(request_var('comment_list', array(''), true));
+ $actual_comment_list = $request->variable('comment_list', array(''), true);
foreach ($actual_comment_list as $comment_key => $comment)
{
@@ -1529,7 +1566,9 @@ class parse_message extends bbcode_firstpass
{
if ($num_attachments < $cfg['max_attachments'] || $auth->acl_get('a_') || $auth->acl_get('m_', $forum_id))
{
- $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $filedata = $attachment_manager->upload($form_name, $forum_id, false, '', $is_message);
$error = $filedata['error'];
if ($filedata['post_attach'] && !sizeof($error))
@@ -1559,7 +1598,9 @@ class parse_message extends bbcode_firstpass
);
$this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
- $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
+ $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) {
+ return '[attachment='.($match[1] + 1).']' . $match[2] . '[/attachment]';
+ }, $this->message);
$this->filename_data['filecomment'] = '';
@@ -1592,11 +1633,14 @@ class parse_message extends bbcode_firstpass
{
include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
- $index = array_keys(request_var('delete_file', array(0 => 0)));
+ $index = array_keys($request->variable('delete_file', array(0 => 0)));
$index = (!empty($index)) ? $index[0] : false;
if ($index !== false && !empty($this->attachment_data[$index]))
{
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+
// delete selected attachment
if ($this->attachment_data[$index]['is_orphan'])
{
@@ -1611,11 +1655,11 @@ class parse_message extends bbcode_firstpass
if ($row)
{
- phpbb_unlink($row['physical_filename'], 'file');
+ $attachment_manager->unlink($row['physical_filename'], 'file');
if ($row['thumbnail'])
{
- phpbb_unlink($row['physical_filename'], 'thumbnail');
+ $attachment_manager->unlink($row['physical_filename'], 'thumbnail');
}
$db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']);
@@ -1623,11 +1667,13 @@ class parse_message extends bbcode_firstpass
}
else
{
- delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
+ $attachment_manager->delete('attach', $this->attachment_data[$index]['attach_id']);
}
unset($this->attachment_data[$index]);
- $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message);
+ $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) use($index) {
+ return ($match[1] == $index) ? '' : (($match[1] > $index) ? '[attachment=' . ($match[1] - 1) . ']' . $match[2] . '[/attachment]' : $match[0]);
+ }, $this->message);
// Reindex Array
$this->attachment_data = array_values($this->attachment_data);
@@ -1641,7 +1687,9 @@ class parse_message extends bbcode_firstpass
{
if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_', $forum_id))
{
- $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message, false, $this->mimetype_guesser, $this->plupload);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $filedata = $attachment_manager->upload($form_name, $forum_id, false, '', $is_message);
$error = array_merge($error, $filedata['error']);
if (!sizeof($error))
@@ -1671,7 +1719,9 @@ class parse_message extends bbcode_firstpass
);
$this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
- $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
+ $this->message = preg_replace_callback('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#', function ($match) {
+ return '[attachment=' . ($match[1] + 1) . ']' . $match[2] . '[/attachment]';
+ }, $this->message);
$this->filename_data['filecomment'] = '';
if (isset($this->plupload) && $this->plupload->is_active())
@@ -1715,10 +1765,10 @@ class parse_message extends bbcode_firstpass
*/
function get_submitted_attachment_data($check_user_id = false)
{
- global $user, $db, $phpbb_root_path, $phpEx, $config;
+ global $user, $db;
global $request;
- $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true));
+ $this->filename_data['filecomment'] = $request->variable('filecomment', '', true);
$attachment_data = $request->variable('attachment_data', array(0 => array('' => '')), true, \phpbb\request\request_interface::POST);
$this->attachment_data = array();
@@ -1803,28 +1853,26 @@ class parse_message extends bbcode_firstpass
*/
function parse_poll(&$poll)
{
- global $auth, $user, $config;
+ global $user, $config;
$poll_max_options = $poll['poll_max_options'];
- // Parse Poll Option text ;)
+ // Parse Poll Option text
$tmp_message = $this->message;
- $this->message = $poll['poll_option_text'];
- $bbcode_bitfield = $this->bbcode_bitfield;
- $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll');
+ $poll['poll_options'] = preg_split('/\s*?\n\s*/', trim($poll['poll_option_text']));
+ $poll['poll_options_size'] = sizeof($poll['poll_options']);
- $bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield));
- $this->message = $tmp_message;
+ foreach ($poll['poll_options'] as &$poll_option)
+ {
+ $this->message = $poll_option;
+ $poll_option = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll');
+ }
+ unset($poll_option);
+ $poll['poll_option_text'] = implode("\n", $poll['poll_options']);
// Parse Poll Title
- $tmp_message = $this->message;
$this->message = $poll['poll_title'];
- $this->bbcode_bitfield = $bbcode_bitfield;
-
- $poll['poll_options'] = preg_split('/\s*?\n\s*/', trim($poll['poll_option_text']));
- $poll['poll_options_size'] = sizeof($poll['poll_options']);
-
if (!$poll['poll_title'] && $poll['poll_options_size'])
{
$this->warn_msg[] = $user->lang['NO_POLL_TITLE'];
@@ -1842,10 +1890,6 @@ class parse_message extends bbcode_firstpass
}
}
- $this->bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield));
- $this->message = $tmp_message;
- unset($tmp_message);
-
if (sizeof($poll['poll_options']) == 1)
{
$this->warn_msg[] = $user->lang['TOO_FEW_POLL_OPTIONS'];
@@ -1860,6 +1904,8 @@ class parse_message extends bbcode_firstpass
}
$poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > $config['max_poll_options']) ? $config['max_poll_options'] : $poll['poll_max_options']);
+
+ $this->message = $tmp_message;
}
/**
@@ -1870,6 +1916,19 @@ class parse_message extends bbcode_firstpass
*/
public function remove_nested_quotes($max_depth)
{
+ global $phpbb_container;
+
+ if (preg_match('#^<[rt][ >]#', $this->message))
+ {
+ $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode(
+ $this->message,
+ 'quote',
+ $max_depth
+ );
+
+ return;
+ }
+
// Capture all [quote] and [/quote] tags
preg_match_all('(\\[/?quote(?:=&quot;(.*?)&quot;)?:' . $this->bbcode_uid . '\\])', $this->message, $matches, PREG_OFFSET_CAPTURE);
@@ -1919,18 +1978,6 @@ class parse_message extends bbcode_firstpass
}
/**
- * Setter function for passing the mimetype_guesser object
- *
- * @param \phpbb\mimetype\guesser $mimetype_guesser The mimetype_guesser object
- *
- * @return null
- */
- public function set_mimetype_guesser(\phpbb\mimetype\guesser $mimetype_guesser)
- {
- $this->mimetype_guesser = $mimetype_guesser;
- }
-
- /**
* Function to perform custom bbcode validation by extensions
* can be used in bbcode_init() to assign regexp replacement
* Example: 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->validate_bbcode_by_extension('\$1')")
diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php
index 63ea432863..6350f4bc5a 100644
--- a/phpBB/includes/questionnaire/questionnaire.php
+++ b/phpBB/includes/questionnaire/questionnaire.php
@@ -190,7 +190,6 @@ class phpbb_questionnaire_system_data_provider
// - 192.168.0.0/16
if ($ip_address_ary[0] == '10' ||
($ip_address_ary[0] == '172' && intval($ip_address_ary[1]) > 15 && intval($ip_address_ary[1]) < 32) ||
- ($ip_address_ary[0] == '192' && $ip_address_ary[1] == '168') ||
($ip_address_ary[0] == '192' && $ip_address_ary[1] == '168'))
{
return true;
@@ -230,7 +229,7 @@ class phpbb_questionnaire_phpbb_data_provider
if (empty($config['questionnaire_unique_id']))
{
$this->unique_id = unique_id();
- set_config('questionnaire_unique_id', $this->unique_id);
+ $config->set('questionnaire_unique_id', $this->unique_id);
}
else
{
@@ -257,7 +256,7 @@ class phpbb_questionnaire_phpbb_data_provider
*/
function get_data()
{
- global $phpbb_root_path, $phpEx, $phpbb_config_php_file;
+ global $phpbb_config_php_file;
extract($phpbb_config_php_file->get_all());
unset($dbhost, $dbport, $dbname, $dbuser, $dbpasswd); // Just a precaution
diff --git a/phpBB/includes/sphinxapi.php b/phpBB/includes/sphinxapi.php
index 6c3b66710c..5e1f131ac2 100644
--- a/phpBB/includes/sphinxapi.php
+++ b/phpBB/includes/sphinxapi.php
@@ -1659,7 +1659,6 @@ class SphinxClient
return false;
}
- $res = substr ( $response, 4 ); // just ignore length, error handling, etc
$p = 0;
list ( $rows, $cols ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8;
diff --git a/phpBB/includes/startup.php b/phpBB/includes/startup.php
index 7353b90d99..5900016c39 100644
--- a/phpBB/includes/startup.php
+++ b/phpBB/includes/startup.php
@@ -19,10 +19,6 @@ if (!defined('IN_PHPBB'))
}
// Report all errors, except notices and deprecation messages
-if (!defined('E_DEPRECATED'))
-{
- define('E_DEPRECATED', 8192);
-}
$level = E_ALL & ~E_NOTICE & ~E_DEPRECATED;
error_reporting($level);
@@ -109,33 +105,21 @@ else
define('STRIP', (get_magic_quotes_gpc()) ? true : false);
}
-// Prevent date/time functions from throwing E_WARNING on PHP 5.3 by setting a default timezone
-if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get'))
-{
- // For PHP 5.1.0 the date/time functions have been rewritten
- // and setting a timezone is required prior to calling any date/time function.
-
- // Since PHP 5.2.0 calls to date/time functions without having a timezone set
- // result in E_STRICT errors being thrown.
- // Note: We already exclude E_STRICT errors
- // (to be exact: they are not included in E_ALL in PHP 5.2)
-
- // In PHP 5.3.0 the error level has been raised to E_WARNING which causes problems
- // because we show E_WARNING errors and do not set a default timezone.
- // This is because we have our own timezone handling and work in UTC only anyway.
+// In PHP 5.3.0 the error level has been raised to E_WARNING which causes problems
+// because we show E_WARNING errors and do not set a default timezone.
+// This is because we have our own timezone handling and work in UTC only anyway.
- // So what we basically want to do is set our timezone to UTC,
- // but we don't know what other scripts (such as bridges) are involved,
- // so we check whether a timezone is already set by calling date_default_timezone_get().
+// So what we basically want to do is set our timezone to UTC,
+// but we don't know what other scripts (such as bridges) are involved,
+// so we check whether a timezone is already set by calling date_default_timezone_get().
- // Unfortunately, date_default_timezone_get() itself might throw E_WARNING
- // if no timezone has been set, so we have to keep it quiet with @.
+// Unfortunately, date_default_timezone_get() itself might throw E_WARNING
+// if no timezone has been set, so we have to keep it quiet with @.
- // date_default_timezone_get() tries to guess the correct timezone first
- // and then falls back to UTC when everything fails.
- // We just set the timezone to whatever date_default_timezone_get() returns.
- date_default_timezone_set(@date_default_timezone_get());
-}
+// date_default_timezone_get() tries to guess the correct timezone first
+// and then falls back to UTC when everything fails.
+// We just set the timezone to whatever date_default_timezone_get() returns.
+date_default_timezone_set(@date_default_timezone_get());
// Autoloading of dependencies.
// Three options are supported:
@@ -172,5 +156,4 @@ else
require($phpbb_root_path . 'vendor/autoload.php');
}
-$starttime = explode(' ', microtime());
-$starttime = $starttime[1] + $starttime[0];
+$starttime = microtime(true);
diff --git a/phpBB/includes/ucp/info/ucp_attachments.php b/phpBB/includes/ucp/info/ucp_attachments.php
index 2e20106f5c..96e7956db9 100644
--- a/phpBB/includes/ucp/info/ucp_attachments.php
+++ b/phpBB/includes/ucp/info/ucp_attachments.php
@@ -18,7 +18,6 @@ class ucp_attachments_info
return array(
'filename' => 'ucp_attachments',
'title' => 'UCP_ATTACHMENTS',
- 'version' => '1.0.0',
'modes' => array(
'attachments' => array('title' => 'UCP_MAIN_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_MAIN')),
),
diff --git a/phpBB/includes/ucp/info/ucp_auth_link.php b/phpBB/includes/ucp/info/ucp_auth_link.php
index 9ec4cb7b3a..57c9269c5e 100644
--- a/phpBB/includes/ucp/info/ucp_auth_link.php
+++ b/phpBB/includes/ucp/info/ucp_auth_link.php
@@ -18,7 +18,6 @@ class ucp_auth_link_info
return array(
'filename' => 'ucp_auth_link',
'title' => 'UCP_AUTH_LINK',
- 'version' => '1.0.0',
'modes' => array(
'auth_link' => array('title' => 'UCP_AUTH_LINK_MANAGE', 'auth' => 'authmethod_oauth', 'cat' => array('UCP_PROFILE')),
),
diff --git a/phpBB/includes/ucp/info/ucp_groups.php b/phpBB/includes/ucp/info/ucp_groups.php
index 6da2a4fe38..42eb285075 100644
--- a/phpBB/includes/ucp/info/ucp_groups.php
+++ b/phpBB/includes/ucp/info/ucp_groups.php
@@ -18,7 +18,6 @@ class ucp_groups_info
return array(
'filename' => 'ucp_groups',
'title' => 'UCP_USERGROUPS',
- 'version' => '1.0.0',
'modes' => array(
'membership' => array('title' => 'UCP_USERGROUPS_MEMBER', 'auth' => '', 'cat' => array('UCP_USERGROUPS')),
'manage' => array('title' => 'UCP_USERGROUPS_MANAGE', 'auth' => '', 'cat' => array('UCP_USERGROUPS')),
diff --git a/phpBB/includes/ucp/info/ucp_main.php b/phpBB/includes/ucp/info/ucp_main.php
index de8e7d5602..e967b8445f 100644
--- a/phpBB/includes/ucp/info/ucp_main.php
+++ b/phpBB/includes/ucp/info/ucp_main.php
@@ -18,7 +18,6 @@ class ucp_main_info
return array(
'filename' => 'ucp_main',
'title' => 'UCP_MAIN',
- 'version' => '1.0.0',
'modes' => array(
'front' => array('title' => 'UCP_MAIN_FRONT', 'auth' => '', 'cat' => array('UCP_MAIN')),
'subscribed' => array('title' => 'UCP_MAIN_SUBSCRIBED', 'auth' => '', 'cat' => array('UCP_MAIN')),
diff --git a/phpBB/includes/ucp/info/ucp_notifications.php b/phpBB/includes/ucp/info/ucp_notifications.php
index 0cc011d96e..94e0467ccb 100644
--- a/phpBB/includes/ucp/info/ucp_notifications.php
+++ b/phpBB/includes/ucp/info/ucp_notifications.php
@@ -18,10 +18,9 @@ class ucp_notifications_info
return array(
'filename' => 'ucp_notifications',
'title' => 'UCP_NOTIFICATION_OPTIONS',
- 'version' => '1.0.0',
'modes' => array(
'notification_options' => array('title' => 'UCP_NOTIFICATION_OPTIONS', 'auth' => '', 'cat' => array('UCP_PREFS')),
- 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => '', 'cat' => array('UCP_MAIN')),
+ 'notification_list' => array('title' => 'UCP_NOTIFICATION_LIST', 'auth' => 'cfg_allow_board_notifications', 'cat' => array('UCP_MAIN')),
),
);
}
diff --git a/phpBB/includes/ucp/info/ucp_pm.php b/phpBB/includes/ucp/info/ucp_pm.php
index 6aa1669cb6..26bd670fc5 100644
--- a/phpBB/includes/ucp/info/ucp_pm.php
+++ b/phpBB/includes/ucp/info/ucp_pm.php
@@ -18,7 +18,6 @@ class ucp_pm_info
return array(
'filename' => 'ucp_pm',
'title' => 'UCP_PM',
- 'version' => '1.0.0',
'modes' => array(
'view' => array('title' => 'UCP_PM_VIEW', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')),
'compose' => array('title' => 'UCP_PM_COMPOSE', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')),
diff --git a/phpBB/includes/ucp/info/ucp_prefs.php b/phpBB/includes/ucp/info/ucp_prefs.php
index 5c2d29ac73..4793aa2649 100644
--- a/phpBB/includes/ucp/info/ucp_prefs.php
+++ b/phpBB/includes/ucp/info/ucp_prefs.php
@@ -18,7 +18,6 @@ class ucp_prefs_info
return array(
'filename' => 'ucp_prefs',
'title' => 'UCP_PREFS',
- 'version' => '1.0.0',
'modes' => array(
'personal' => array('title' => 'UCP_PREFS_PERSONAL', 'auth' => '', 'cat' => array('UCP_PREFS')),
'post' => array('title' => 'UCP_PREFS_POST', 'auth' => '', 'cat' => array('UCP_PREFS')),
diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php
index 919de99a96..fc2792224d 100644
--- a/phpBB/includes/ucp/info/ucp_profile.php
+++ b/phpBB/includes/ucp/info/ucp_profile.php
@@ -18,7 +18,6 @@ class ucp_profile_info
return array(
'filename' => 'ucp_profile',
'title' => 'UCP_PROFILE',
- 'version' => '1.0.0',
'modes' => array(
'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => 'acl_u_chgprofileinfo', 'cat' => array('UCP_PROFILE')),
'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => 'acl_u_sig', 'cat' => array('UCP_PROFILE')),
diff --git a/phpBB/includes/ucp/info/ucp_zebra.php b/phpBB/includes/ucp/info/ucp_zebra.php
index 99d4a4f4c0..69274c2866 100644
--- a/phpBB/includes/ucp/info/ucp_zebra.php
+++ b/phpBB/includes/ucp/info/ucp_zebra.php
@@ -18,7 +18,6 @@ class ucp_zebra_info
return array(
'filename' => 'ucp_zebra',
'title' => 'UCP_ZEBRA',
- 'version' => '1.0.0',
'modes' => array(
'friends' => array('title' => 'UCP_ZEBRA_FRIENDS', 'auth' => '', 'cat' => array('UCP_ZEBRA')),
'foes' => array('title' => 'UCP_ZEBRA_FOES', 'auth' => '', 'cat' => array('UCP_ZEBRA')),
diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php
index 1f5ce93277..1e54c18dc1 100644
--- a/phpBB/includes/ucp/ucp_activate.php
+++ b/phpBB/includes/ucp/ucp_activate.php
@@ -29,11 +29,11 @@ class ucp_activate
function main($id, $mode)
{
- global $config, $phpbb_root_path, $phpEx;
- global $db, $user, $auth, $template, $phpbb_container, $phpbb_dispatcher;
+ global $config, $phpbb_root_path, $phpEx, $request;
+ global $db, $user, $auth, $phpbb_container, $phpbb_log, $phpbb_dispatcher;
- $user_id = request_var('u', 0);
- $key = request_var('k', '');
+ $user_id = $request->variable('u', 0);
+ $key = $request->variable('k', '');
$sql = 'SELECT user_id, username, user_type, user_email, user_newpasswd, user_lang, user_notify_type, user_actkey, user_inactive_reason
FROM ' . USERS_TABLE . "
@@ -67,6 +67,7 @@ class ucp_activate
{
login_box('', $user->lang['NO_AUTH_OPERATION']);
}
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_OPERATION');
}
@@ -86,7 +87,10 @@ class ucp_activate
WHERE user_id = ' . $user_row['user_id'];
$db->sql_query($sql);
- add_log('user', $user_row['user_id'], 'LOG_USER_NEW_PASSWORD', $user_row['username']);
+ $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']
+ ));
}
if (!$update_password)
@@ -101,15 +105,19 @@ class ucp_activate
$db->sql_query($sql);
// Create the correct logs
- add_log('user', $user_row['user_id'], 'LOG_USER_ACTIVE_USER');
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array(
+ 'reportee_id' => $user_row['user_id']
+ ));
+
if ($auth->acl_get('a_user'))
{
- add_log('admin', 'LOG_USER_ACTIVE', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($user_row['username']));
}
}
if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password)
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']);
diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php
index 42724209aa..66c3109b3d 100644
--- a/phpBB/includes/ucp/ucp_attachments.php
+++ b/phpBB/includes/ucp/ucp_attachments.php
@@ -29,15 +29,14 @@ class ucp_attachments
function main($id, $mode)
{
- global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container;
+ global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request;
- $start = request_var('start', 0);
- $sort_key = request_var('sk', 'a');
- $sort_dir = request_var('sd', 'a');
+ $start = $request->variable('start', 0);
+ $sort_key = $request->variable('sk', 'a');
+ $sort_dir = $request->variable('sd', 'a');
$delete = (isset($_POST['delete'])) ? true : false;
- $confirm = (isset($_POST['confirm'])) ? true : false;
- $delete_ids = array_keys(request_var('attachment', array(0)));
+ $delete_ids = array_keys($request->variable('attachment', array(0)));
if ($delete && sizeof($delete_ids))
{
@@ -70,12 +69,10 @@ class ucp_attachments
if (confirm_box(true))
{
- if (!function_exists('delete_attachments'))
- {
- include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
- }
-
- delete_attachments('attach', $delete_ids);
+ /** @var \phpbb\attachment\manager $attachment_manager */
+ $attachment_manager = $phpbb_container->get('attachment.manager');
+ $attachment_manager->delete('attach', $delete_ids);
+ 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>');
@@ -123,6 +120,7 @@ class ucp_attachments
$db->sql_freeresult($result);
// Ensure start is a valid value
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
$start = $pagination->validate_start($start, $config['topics_per_page'], $num_attachments);
diff --git a/phpBB/includes/ucp/ucp_auth_link.php b/phpBB/includes/ucp/ucp_auth_link.php
index 748f0fdec2..08aacdef3a 100644
--- a/phpBB/includes/ucp/ucp_auth_link.php
+++ b/phpBB/includes/ucp/ucp_auth_link.php
@@ -38,6 +38,7 @@ class ucp_auth_link
$error = array();
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$auth_provider = $provider_collection->get_provider();
diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php
index 7392f8dea8..cdf4de65fd 100644
--- a/phpBB/includes/ucp/ucp_confirm.php
+++ b/phpBB/includes/ucp/ucp_confirm.php
@@ -36,10 +36,10 @@ class ucp_confirm
function main($id, $mode)
{
- global $db, $user, $phpbb_root_path, $config, $phpEx, $phpbb_container;
+ global $config, $phpbb_container, $request;
$captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);
- $captcha->init(request_var('type', 0));
+ $captcha->init($request->variable('type', 0));
$captcha->execute();
garbage_collection();
diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php
index 86a8226d5b..352b7d1ec3 100644
--- a/phpBB/includes/ucp/ucp_groups.php
+++ b/phpBB/includes/ucp/ucp_groups.php
@@ -30,16 +30,17 @@ class ucp_groups
{
global $config, $phpbb_root_path, $phpEx, $phpbb_admin_path;
global $db, $user, $auth, $cache, $template;
- global $request, $phpbb_container;
+ global $request, $phpbb_container, $phpbb_log;
$user->add_lang('groups');
$return_page = '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '">', '</a>');
- $mark_ary = request_var('mark', array(0));
+ $mark_ary = $request->variable('mark', array(0));
$submit = $request->variable('submit', false, false, \phpbb\request\request_interface::POST);
- $delete = $request->variable('delete', false, false, \phpbb\request\request_interface::POST);
- $error = $data = array();
+
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
switch ($mode)
{
@@ -49,8 +50,8 @@ class ucp_groups
if ($submit || isset($_POST['change_default']))
{
- $action = (isset($_POST['change_default'])) ? 'change_default' : request_var('action', '');
- $group_id = ($action == 'change_default') ? request_var('default', 0) : request_var('selected', 0);
+ $action = (isset($_POST['change_default'])) ? 'change_default' : $request->variable('action', '');
+ $group_id = ($action == 'change_default') ? $request->variable('default', 0) : $request->variable('selected', 0);
if (!$group_id)
{
@@ -65,7 +66,7 @@ class ucp_groups
$group_row = array();
while ($row = $db->sql_fetchrow($result))
{
- $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $row['group_name'] = $group_helper->get_name($row['group_name']);
$group_row[$row['group_id']] = $row;
}
$db->sql_freeresult($result);
@@ -86,6 +87,7 @@ class ucp_groups
if (!$auth->acl_get('u_chggrp'))
{
+ send_status_line(403, 'Forbidden');
trigger_error($user->lang['NOT_AUTHORISED'] . $return_page);
}
@@ -99,7 +101,10 @@ class ucp_groups
{
group_user_attributes('default', $group_id, $user->data['user_id']);
- add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_CHANGE', sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name']));
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_CHANGE', false, array(
+ 'reportee_id' => $user->data['user_id'],
+ sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name'])
+ ));
meta_refresh(3, $this->u_action);
trigger_error($user->lang['CHANGED_DEFAULT_GROUP'] . $return_page);
@@ -146,7 +151,10 @@ class ucp_groups
{
group_user_del($group_id, $user->data['user_id']);
- add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_RESIGN', $group_row[$group_id]['group_name']);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_RESIGN', false, array(
+ 'reportee_id' => $user->data['user_id'],
+ $group_row[$group_id]['group_name']
+ ));
meta_refresh(3, $this->u_action);
trigger_error($user->lang[($row['user_pending']) ? 'GROUP_RESIGNED_PENDING' : 'GROUP_RESIGNED_MEMBERSHIP'] . $return_page);
@@ -202,7 +210,10 @@ class ucp_groups
group_user_add($group_id, $user->data['user_id'], false, false, false, 0, 1);
}
- add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), false, array(
+ 'reportee_id' => $user->data['user_id'],
+ $group_row[$group_id]['group_name']
+ ));
meta_refresh(3, $this->u_action);
trigger_error($user->lang[($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOINED' : 'GROUP_JOINED_PENDING'] . $return_page);
@@ -237,7 +248,10 @@ class ucp_groups
{
group_user_attributes('demote', $group_id, $user->data['user_id']);
- add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_DEMOTE', $group_row[$group_id]['group_name']);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_GROUP_DEMOTE', false, array(
+ 'reportee_id' => $user->data['user_id'],
+ $group_row[$group_id]['group_name']
+ ));
meta_refresh(3, $this->u_action);
trigger_error($user->lang['USER_GROUP_DEMOTED'] . $return_page);
@@ -295,7 +309,7 @@ class ucp_groups
$template->assign_block_vars($block, array(
'GROUP_ID' => $row['group_id'],
- 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'],
+ 'GROUP_NAME' => $group_helper->get_name($row['group_name']),
'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'],
'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true,
'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status],
@@ -349,7 +363,7 @@ class ucp_groups
$template->assign_block_vars('nonmember', array(
'GROUP_ID' => $row['group_id'],
- 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'],
+ 'GROUP_NAME' => $group_helper->get_name($row['group_name']),
'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'],
'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true,
'GROUP_CLOSED' => ($row['group_type'] <> GROUP_CLOSED || $auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? false : true,
@@ -379,8 +393,8 @@ class ucp_groups
case 'manage':
$this->page_title = 'UCP_USERGROUPS_MANAGE';
- $action = (isset($_POST['addusers'])) ? 'addusers' : request_var('action', '');
- $group_id = request_var('g', 0);
+ $action = (isset($_POST['addusers'])) ? 'addusers' : $request->variable('action', '');
+ $group_id = $request->variable('g', 0);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
@@ -414,7 +428,7 @@ class ucp_groups
$avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true);
$template->assign_vars(array(
- 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name,
+ 'GROUP_NAME' => $group_helper->get_name($group_name),
'GROUP_INTERNAL_NAME' => $group_name,
'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '',
'GROUP_DESC_DISP' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']),
@@ -447,11 +461,8 @@ class ucp_groups
trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page);
}
- $file_uploads = (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on') ? true : false;
$user->add_lang(array('acp/groups', 'acp/common'));
- $data = $submit_ary = array();
-
$update = (isset($_POST['update'])) ? true : false;
$error = array();
@@ -499,20 +510,20 @@ class ucp_groups
// Did we submit?
if ($update)
{
- $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
- $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true));
- $group_type = request_var('group_type', GROUP_FREE);
+ $group_name = $request->variable('group_name', '', true);
+ $group_desc = $request->variable('group_desc', '', true);
+ $group_type = $request->variable('group_type', GROUP_FREE);
- $allow_desc_bbcode = request_var('desc_parse_bbcode', false);
- $allow_desc_urls = request_var('desc_parse_urls', false);
- $allow_desc_smilies = request_var('desc_parse_smilies', false);
+ $allow_desc_bbcode = $request->variable('desc_parse_bbcode', false);
+ $allow_desc_urls = $request->variable('desc_parse_urls', false);
+ $allow_desc_smilies = $request->variable('desc_parse_smilies', false);
$submit_ary = array(
- 'colour' => request_var('group_colour', ''),
- 'rank' => request_var('group_rank', 0),
+ 'colour' => $request->variable('group_colour', ''),
+ 'rank' => $request->variable('group_rank', 0),
'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0,
- 'message_limit' => request_var('group_message_limit', 0),
- 'max_recipients'=> request_var('group_max_recipients', 0),
+ 'message_limit' => $request->variable('group_message_limit', 0),
+ 'max_recipients'=> $request->variable('group_max_recipients', 0),
'legend' => $group_row['group_legend'],
'teampage' => $group_row['group_teampage'],
);
@@ -521,7 +532,6 @@ class ucp_groups
{
// Handle avatar
$driver_name = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', ''));
- $config_name = preg_replace('#^avatar\.driver.#', '', $driver_name);
if (in_array($driver_name, $avatar_drivers) && !$request->is_set_post('avatar_delete'))
{
@@ -610,7 +620,6 @@ class ucp_groups
}
else if (!$group_id)
{
- $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
$group_desc_data = array(
'text' => '',
'allow_bbcode' => true,
@@ -747,7 +756,7 @@ class ucp_groups
}
$user->add_lang(array('acp/groups', 'acp/common'));
- $start = request_var('start', 0);
+ $start = $request->variable('start', 0);
// Grab the leaders - always, on every page...
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
@@ -836,6 +845,7 @@ class ucp_groups
$s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>';
}
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
$base_url = $this->u_action . "&amp;action=$action&amp;g=$group_id";
$start = $pagination->validate_start($start, $config['topics_per_page'], $total_members);
@@ -897,7 +907,7 @@ class ucp_groups
trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page);
}
- $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_row['group_name'] = $group_helper->get_name($group_row['group_name']);
if (confirm_box(true))
{
@@ -976,7 +986,7 @@ class ucp_groups
trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page);
}
- $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_row['group_name'] = $group_helper->get_name($group_row['group_name']);
if (confirm_box(true))
{
@@ -1014,7 +1024,7 @@ class ucp_groups
$user->add_lang(array('acp/groups', 'acp/common'));
- $names = utf8_normalize_nfc(request_var('usernames', '', true));
+ $names = $request->variable('usernames', '', true);
if (!$group_id)
{
@@ -1038,9 +1048,9 @@ class ucp_groups
}
$name_ary = array_unique(explode("\n", $names));
- $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
+ $group_name = $group_helper->get_name($group_row['group_name']);
- $default = request_var('default', 0);
+ $default = $request->variable('default', 0);
if (confirm_box(true))
{
@@ -1084,7 +1094,7 @@ class ucp_groups
while ($value = $db->sql_fetchrow($result))
{
$template->assign_block_vars('leader', array(
- 'GROUP_NAME' => ($value['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $value['group_name']] : $value['group_name'],
+ 'GROUP_NAME' => $group_helper->get_name($value['group_name']),
'GROUP_DESC' => generate_text_for_display($value['group_desc'], $value['group_desc_uid'], $value['group_desc_bitfield'], $value['group_desc_options']),
'GROUP_TYPE' => $value['group_type'],
'GROUP_ID' => $value['group_id'],
diff --git a/phpBB/includes/ucp/ucp_login_link.php b/phpBB/includes/ucp/ucp_login_link.php
index bfe4804286..f4d47e30bb 100644
--- a/phpBB/includes/ucp/ucp_login_link.php
+++ b/phpBB/includes/ucp/ucp_login_link.php
@@ -57,6 +57,7 @@ class ucp_login_link
}
// Use the auth_provider requested even if different from configured
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$auth_provider = $provider_collection->get_provider($request->variable('auth_provider', ''));
@@ -98,7 +99,7 @@ class ucp_login_link
else
{
// Finish login
- $result = $user->session_create($login_result['user_row']['user_id'], false, false, true);
+ $user->session_create($login_result['user_row']['user_id'], false, false, true);
// Perform a redirect as the account has been linked
$this->perform_redirect();
@@ -181,7 +182,7 @@ class ucp_login_link
*/
protected function process_login_result($result)
{
- global $config, $request, $template, $user, $phpbb_container;
+ global $config, $template, $user, $phpbb_container;
$login_error = null;
diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php
index 8584a9a0fd..77ac1dfb54 100644
--- a/phpBB/includes/ucp/ucp_main.php
+++ b/phpBB/includes/ucp/ucp_main.php
@@ -227,9 +227,8 @@ class ucp_main
{
if (check_form_key('ucp_front_subscribed'))
{
- $forums = array_keys(request_var('f', array(0 => 0)));
- $topics = array_keys(request_var('t', array(0 => 0)));
- $msg = '';
+ $forums = array_keys($request->variable('f', array(0 => 0)));
+ $topics = array_keys($request->variable('t', array(0 => 0)));
if (sizeof($forums) || sizeof($topics))
{
@@ -451,7 +450,7 @@ class ucp_main
if (isset($_POST['unbookmark']))
{
$s_hidden_fields = array('unbookmark' => 1);
- $topics = (isset($_POST['t'])) ? array_keys(request_var('t', array(0 => 0))) : array();
+ $topics = (isset($_POST['t'])) ? array_keys($request->variable('t', array(0 => 0))) : array();
$url = $this->u_action;
if (!sizeof($topics))
@@ -507,7 +506,7 @@ class ucp_main
{
if (check_form_key('ucp_draft'))
{
- $drafts = array_keys(request_var('d', array(0 => 0)));
+ $drafts = array_keys($request->variable('d', array(0 => 0)));
if (sizeof($drafts))
{
@@ -530,8 +529,8 @@ class ucp_main
if ($submit && $edit)
{
- $draft_subject = utf8_normalize_nfc(request_var('subject', '', true));
- $draft_message = utf8_normalize_nfc(request_var('message', '', true));
+ $draft_subject = $request->variable('subject', '', true);
+ $draft_message = $request->variable('message', '', true);
if (check_form_key('ucp_draft'))
{
if ($draft_message && $draft_subject)
@@ -695,9 +694,10 @@ class ucp_main
{
global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container, $request, $phpbb_dispatcher;
- $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE;
- $start = request_var('start', 0);
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
+ $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE;
+ $start = $request->variable('start', 0);
// Grab icons
$icons = $cache->obtain_icons();
@@ -852,6 +852,7 @@ class ucp_main
}
}
+ /* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
foreach ($topic_list as $topic_id)
diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php
index 66dc651447..51bd77bd4c 100644
--- a/phpBB/includes/ucp/ucp_notifications.php
+++ b/phpBB/includes/ucp/ucp_notifications.php
@@ -34,7 +34,10 @@ class ucp_notifications
$form_time = $request->variable('form_time', 0);
$form_time = ($form_time <= 0 || $form_time > time()) ? time() : $form_time;
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
switch ($mode)
@@ -67,15 +70,6 @@ class ucp_notifications
$phpbb_notifications->delete_subscription($type, 0, $method_data['id']);
}
}
-
- if ($request->is_set_post(str_replace('.', '_', $type) . '_notification') && !isset($subscriptions[$type]))
- {
- $phpbb_notifications->add_subscription($type);
- }
- else if (!$request->is_set_post(str_replace('.', '_', $type) . '_notification') && isset($subscriptions[$type]))
- {
- $phpbb_notifications->delete_subscription($type);
- }
}
}
@@ -97,7 +91,7 @@ class ucp_notifications
// Mark all items read
if ($request->variable('mark', '') == 'all' && check_link_hash($request->variable('token', ''), 'mark_all_notifications_read'))
{
- $phpbb_notifications->mark_notifications_read(false, false, $user->data['user_id'], $form_time);
+ $phpbb_notifications->mark_notifications(false, false, $user->data['user_id'], $form_time);
meta_refresh(3, $this->u_action);
$message = $user->lang['NOTIFICATIONS_MARK_ALL_READ_SUCCESS'];
@@ -128,11 +122,11 @@ class ucp_notifications
if (!empty($mark_read))
{
- $phpbb_notifications->mark_notifications_read_by_id($mark_read, $form_time);
+ $phpbb_notifications->mark_notifications_by_id('notification.method.board', $mark_read, $form_time);
}
}
- $notifications = $phpbb_notifications->load_notifications(array(
+ $notifications = $phpbb_notifications->load_notifications('notification.method.board', array(
'start' => $start,
'limit' => $config['topics_per_page'],
'count_total' => true,
@@ -193,8 +187,6 @@ class ucp_notifications
'NAME' => $user->lang($data['lang']),
'EXPLAIN' => (isset($user->lang[$data['lang'] . '_EXPLAIN'])) ? $user->lang($data['lang'] . '_EXPLAIN') : '',
-
- 'SUBSCRIBED' => (isset($subscriptions[$type])) ? true : false,
));
foreach ($notification_methods as $method => $method_data)
diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php
index f026cd3eb3..d145d66f59 100644
--- a/phpBB/includes/ucp/ucp_pm.php
+++ b/phpBB/includes/ucp/ucp_pm.php
@@ -62,7 +62,7 @@ class ucp_pm
$template->assign_var('S_PRIVMSGS', true);
// Folder directly specified?
- $folder_specified = request_var('folder', '');
+ $folder_specified = $request->variable('folder', '');
if (!in_array($folder_specified, array('inbox', 'outbox', 'sentbox')))
{
@@ -75,7 +75,7 @@ class ucp_pm
if (!$folder_specified)
{
- $mode = (!$mode) ? request_var('mode', 'view') : $mode;
+ $mode = (!$mode) ? $request->variable('mode', 'view') : $mode;
}
else
{
@@ -88,7 +88,7 @@ class ucp_pm
{
// Compose message
case 'compose':
- $action = request_var('action', 'post');
+ $action = $request->variable('action', 'post');
$user_folders = get_folder($user->data['user_id']);
@@ -151,12 +151,12 @@ class ucp_pm
}
else
{
- $folder_id = request_var('f', PRIVMSGS_NO_BOX);
- $action = request_var('action', 'view_folder');
+ $folder_id = $request->variable('f', PRIVMSGS_NO_BOX);
+ $action = $request->variable('action', 'view_folder');
}
- $msg_id = request_var('p', 0);
- $view = request_var('view', '');
+ $msg_id = $request->variable('p', 0);
+ $view = $request->variable('view', '');
// View message if specified
if ($msg_id)
@@ -166,6 +166,7 @@ class ucp_pm
if (!$auth->acl_get('u_readpm'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_READ_MESSAGE');
}
@@ -178,8 +179,8 @@ class ucp_pm
// First Handle Mark actions and moving messages
$submit_mark = (isset($_POST['submit_mark'])) ? true : false;
$move_pm = (isset($_POST['move_pm'])) ? true : false;
- $mark_option = request_var('mark_option', '');
- $dest_folder = request_var('dest_folder', PRIVMSGS_NO_BOX);
+ $mark_option = $request->variable('mark_option', '');
+ $dest_folder = $request->variable('dest_folder', PRIVMSGS_NO_BOX);
// Is moving PM triggered through mark options?
if (!in_array($mark_option, array('mark_important', 'delete_marked')) && $submit_mark)
@@ -192,8 +193,8 @@ class ucp_pm
// Move PM
if ($move_pm)
{
- $move_msg_ids = (isset($_POST['marked_msg_id'])) ? request_var('marked_msg_id', array(0)) : array();
- $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX);
+ $move_msg_ids = (isset($_POST['marked_msg_id'])) ? $request->variable('marked_msg_id', array(0)) : array();
+ $cur_folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX);
if (move_pm($user->data['user_id'], $user->data['message_limit'], $move_msg_ids, $dest_folder, $cur_folder_id))
{
@@ -201,7 +202,7 @@ class ucp_pm
if ($action == 'view_message')
{
$msg_id = 0;
- $folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX);
+ $folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX);
$action = 'view_folder';
}
}
@@ -215,7 +216,7 @@ class ucp_pm
// If new messages arrived, place them into the appropriate folder
$num_not_moved = $num_removed = 0;
- $release = request_var('release', 0);
+ $release = $request->variable('release', 0);
if ($user->data['user_new_privmsg'] && ($action == 'view_folder' || $action == 'view_message'))
{
diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php
index d365e8b489..b61a9fab9f 100644
--- a/phpBB/includes/ucp/ucp_pm_compose.php
+++ b/phpBB/includes/ucp/ucp_pm_compose.php
@@ -44,14 +44,14 @@ function compose_pm($id, $mode, $action, $user_folders = array())
add_form_key('ucp_pm_compose');
// Grab only parameters needed here
- $to_user_id = request_var('u', 0);
- $to_group_id = request_var('g', 0);
- $msg_id = request_var('p', 0);
- $draft_id = request_var('d', 0);
- $lastclick = request_var('lastclick', 0);
+ $to_user_id = $request->variable('u', 0);
+ $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_var('reply_to_all', 0);
+ $reply_to_all = $request->variable('reply_to_all', 0);
$address_list = $request->variable('address_list', array('' => array(0 => '')));
@@ -76,6 +76,9 @@ function compose_pm($id, $mode, $action, $user_folders = array())
$error = array();
$current_time = time();
+ /** @var \phpbb\group\helper $group_helper */
+ $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))
{
@@ -145,7 +148,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'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
}
@@ -168,6 +171,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
case 'post':
if (!$auth->acl_get('u_sendpm'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_SEND_MESSAGE');
}
break;
@@ -183,6 +187,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
if (!$auth->acl_get('u_sendpm'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_SEND_MESSAGE');
}
@@ -223,6 +228,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
case 'delete':
if (!$auth->acl_get('u_pm_delete'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_DELETE_MESSAGE');
}
@@ -248,11 +254,13 @@ function compose_pm($id, $mode, $action, $user_folders = array())
if ($action == 'forward' && (!$config['forward_pm'] || !$auth->acl_get('u_pm_forward')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_FORWARD_MESSAGE');
}
if ($action == 'edit' && !$auth->acl_get('u_pm_edit'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_EDIT_MESSAGE');
}
@@ -263,8 +271,6 @@ function compose_pm($id, $mode, $action, $user_folders = array())
*
* @event core.ucp_pm_compose_compose_pm_basic_info_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 msg_id topic_id in the page request
* @var int to_user_id The id of whom the message is to
* @var int to_group_id The id of the group whom the message is to
@@ -273,14 +279,11 @@ function compose_pm($id, $mode, $action, $user_folders = array())
* @var string action One of: post, reply, quote, forward, quotepost, edit, delete, smilies
* @var bool delete Whether the user is deleting the PM
* @var int reply_to_all Value of reply_to_all request variable.
- * @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.1.0-RC5
+ * @change 3.2.0-a1 Removed undefined variables
*/
$vars = array(
'sql',
- 'forum_list',
- 'visibility_const',
'msg_id',
'to_user_id',
'to_group_id',
@@ -289,8 +292,6 @@ function compose_pm($id, $mode, $action, $user_folders = array())
'action',
'delete',
'reply_to_all',
- 'limit_time_sql',
- 'sort_order_sql',
);
extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_compose_pm_basic_info_query_before', compact($vars)));
@@ -325,6 +326,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
{
if (($post['forum_id'] && !$auth->acl_get('f_read', $post['forum_id'])) || (!$post['forum_id'] && !$auth->acl_getf_global('f_read')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -335,8 +337,6 @@ function compose_pm($id, $mode, $action, $user_folders = array())
* @var string sql The original SQL used in the query
* @var array post Associative array with the data of the quoted post
* @var array msg_id The post_id that was searched to get the message for quoting
- * @var int visibility_const Visibility of the quoted post (one of the possible ITEM_* constant values)
- * @var int topic_id Topic ID of the quoted post
* @var int to_user_id Users the message is sent to
* @var int to_group_id Groups the message is sent to
* @var bool submit Whether the user is sending the PM or not
@@ -345,13 +345,12 @@ function compose_pm($id, $mode, $action, $user_folders = array())
* @var bool delete If deleting message
* @var int reply_to_all Value of reply_to_all request variable.
* @since 3.1.0-RC5
+ * @change 3.2.0-a1 Removed undefined variables
*/
$vars = array(
'sql',
'post',
'msg_id',
- 'visibility_const',
- 'topic_id',
'to_user_id',
'to_group_id',
'submit',
@@ -463,6 +462,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group')))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_GROUP_MESSAGE');
}
@@ -484,8 +484,9 @@ function compose_pm($id, $mode, $action, $user_folders = array())
$icon_id = 0;
}
- $message_parser = new parse_message();
+ /* @var $plupload \phpbb\plupload\plupload */
$plupload = $phpbb_container->get('plupload');
+ $message_parser = new parse_message();
$message_parser->set_plupload($plupload);
$message_parser->message = ($action == 'reply') ? '' : $message_text;
@@ -498,7 +499,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
if ($action == 'delete')
{
// Folder id has been determined by the SQL Statement
- // $folder_id = request_var('f', PRIVMSGS_NO_BOX);
+ // $folder_id = $request->variable('f', PRIVMSGS_NO_BOX);
// Do we need to confirm ?
if (confirm_box(true))
@@ -529,15 +530,9 @@ function compose_pm($id, $mode, $action, $user_folders = array())
}
// Get maximum number of allowed recipients
- $sql = 'SELECT MAX(g.group_max_recipients) as max_recipients
- FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
- WHERE ug.user_id = ' . $user->data['user_id'] . '
- AND ug.user_pending = 0
- AND ug.group_id = g.group_id';
- $result = $db->sql_query($sql);
- $max_recipients = (int) $db->sql_fetchfield('max_recipients');
- $db->sql_freeresult($result);
+ $max_recipients = phpbb_get_max_setting_from_group($db, $user->data['user_id'], 'max_recipients');
+ // If it is 0, there is no limit set and we use the maximum value within the config.
$max_recipients = (!$max_recipients) ? $config['pm_max_recipients'] : $max_recipients;
// If this is a quote/reply "to all"... we may increase the max_recpients to the number of original recipients
@@ -610,7 +605,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
$enable_urls = true;
}
- $enable_magic_url = $drafts = false;
+ $drafts = false;
// User own some drafts?
if ($auth->acl_get('u_savedrafts') && $action != 'delete')
@@ -645,9 +640,9 @@ function compose_pm($id, $mode, $action, $user_folders = array())
// Save Draft
if ($save && $auth->acl_get('u_savedrafts'))
{
- $subject = utf8_normalize_nfc(request_var('subject', '', true));
+ $subject = $request->variable('subject', '', true);
$subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject;
- $message = utf8_normalize_nfc(request_var('message', '', true));
+ $message = $request->variable('message', '', true);
if ($subject && $message)
{
@@ -741,10 +736,10 @@ function compose_pm($id, $mode, $action, $user_folders = array())
{
$error[] = $user->lang['FORM_INVALID'];
}
- $subject = utf8_normalize_nfc(request_var('subject', '', true));
- $message_parser->message = utf8_normalize_nfc(request_var('message', '', true));
+ $subject = $request->variable('subject', '', true);
+ $message_parser->message = $request->variable('message', '', true);
- $icon_id = request_var('icon', 0);
+ $icon_id = $request->variable('icon', 0);
$enable_bbcode = (!$bbcode_status || isset($_POST['disable_bbcode'])) ? false : true;
$enable_smilies = (!$smilies_status || isset($_POST['disable_smilies'])) ? false : true;
@@ -779,16 +774,6 @@ function compose_pm($id, $mode, $action, $user_folders = array())
);
extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_parse_before', compact($vars)));
- if ($submit)
- {
- $status_switch = (($enable_bbcode+1) << 8) + (($enable_smilies+1) << 4) + (($enable_urls+1) << 2) + (($enable_sig+1) << 1);
- $status_switch = ($status_switch != $check_value);
- }
- else
- {
- $status_switch = 1;
- }
-
// Parse Attachments - before checksum is calculated
$message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true);
@@ -960,7 +945,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
{
if ($action == 'quotepost')
{
- $post_id = request_var('p', 0);
+ $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";
@@ -974,7 +959,20 @@ function compose_pm($id, $mode, $action, $user_folders = array())
{
$message_link = '';
}
- $message_parser->message = $message_link . '[quote=&quot;' . $quote_username . '&quot;]' . censor_text(trim($message_parser->message)) . "[/quote]\n";
+ $quote_attributes = array(
+ 'author' => $quote_username,
+ 'time' => $post['message_time'],
+ 'user_id' => $post['author_id'],
+ );
+ if ($action === 'quotepost')
+ {
+ $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";
}
if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh)
@@ -1002,7 +1000,11 @@ function compose_pm($id, $mode, $action, $user_folders = array())
$forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text);
$forward_text[] = sprintf($user->lang['FWD_TO'], implode($user->lang['COMMA_SEPARATOR'], $fwd_to_field['to']));
- $message_parser->message = implode("\n", $forward_text) . "\n\n[quote=&quot;{$quote_username}&quot;]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]";
+ $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote(
+ censor_text($message_parser->message),
+ array('author' => $quote_username)
+ );
+ $message_parser->message = implode("\n", $forward_text) . "\n\n" . $quote_text;
$message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject);
}
@@ -1075,7 +1077,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
{
if ($type == 'g')
{
- $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name'];
+ $row['name'] = $group_helper->get_name($row['name']);
}
${$type}[$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
@@ -1085,7 +1087,6 @@ function compose_pm($id, $mode, $action, $user_folders = array())
}
// Now Build the address list
- $plain_address_field = '';
foreach ($address_list as $type => $adr_ary)
{
foreach ($adr_ary as $id => $field)
@@ -1173,6 +1174,9 @@ function compose_pm($id, $mode, $action, $user_folders = array())
$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"';
+ /** @var \phpbb\controller\helper $controller_helper */
+ $controller_helper = $phpbb_container->get('controller.helper');
+
// Start assigning vars for main posting page ...
$template->assign_vars(array(
'L_POST_A' => $page_title,
@@ -1181,7 +1185,7 @@ function compose_pm($id, $mode, $action, $user_folders = array())
'SUBJECT' => (isset($message_subject)) ? $message_subject : '',
'MESSAGE' => $message_text,
- 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
+ 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
@@ -1277,13 +1281,13 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove
}
// Add Selected Groups
- $group_list = request_var('group_list', array(0));
+ $group_list = $request->variable('group_list', array(0));
// Build usernames to add
- $usernames = request_var('username', '', true);
+ $usernames = $request->variable('username', '', true);
$usernames = (empty($usernames)) ? array() : array($usernames);
- $username_list = request_var('username_list', '', true);
+ $username_list = $request->variable('username_list', '', true);
if ($username_list)
{
$usernames = array_merge($usernames, explode("\n", $username_list));
@@ -1300,7 +1304,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove
$submit = false;
// Preview is only true if there was also a message entered
- if (request_var('message', ''))
+ if ($request->variable('message', ''))
{
$preview = true;
}
@@ -1432,7 +1436,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove
}
/**
-* Build the hidden field for the recipients. Needed, as the variable is not read via request_var.
+* Build the hidden field for the recipients. Needed, as the variable is not read via $request->variable().
*/
function build_address_field($address_list)
{
diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php
index d1fc9d2c62..2458c4118d 100644
--- a/phpBB/includes/ucp/ucp_pm_options.php
+++ b/phpBB/includes/ucp/ucp_pm_options.php
@@ -24,7 +24,7 @@ if (!defined('IN_PHPBB'))
*/
function message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions)
{
- global $phpbb_root_path, $phpEx, $user, $template, $auth, $config, $db;
+ global $phpbb_root_path, $phpEx, $user, $template, $config, $db, $request;
$redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&amp;mode=options");
@@ -37,7 +37,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
trigger_error('FORM_INVALID');
}
- $full_action = request_var('full_action', 0);
+ $full_action = $request->variable('full_action', 0);
$set_folder_id = 0;
switch ($full_action)
@@ -47,7 +47,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
break;
case 2:
- $set_folder_id = request_var('full_move_to', PRIVMSGS_INBOX);
+ $set_folder_id = $request->variable('full_move_to', PRIVMSGS_INBOX);
break;
case 3:
@@ -79,8 +79,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
{
if (check_form_key('ucp_pm_options'))
{
- $folder_name = utf8_normalize_nfc(request_var('foldername', '', true));
- $msg = '';
+ $folder_name = $request->variable('foldername', '', true);
if ($folder_name)
{
@@ -135,8 +134,8 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
{
if (check_form_key('ucp_pm_options'))
{
- $new_folder_name = utf8_normalize_nfc(request_var('new_folder_name', '', true));
- $rename_folder_id= request_var('rename_folder_id', 0);
+ $new_folder_name = $request->variable('new_folder_name', '', true);
+ $rename_folder_id= $request->variable('rename_folder_id', 0);
if (!$new_folder_name)
{
@@ -178,11 +177,11 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
// Remove Folder
if (isset($_POST['remove_folder']))
{
- $remove_folder_id = request_var('remove_folder_id', 0);
+ $remove_folder_id = $request->variable('remove_folder_id', 0);
// Default to "move all messages to inbox"
- $remove_action = request_var('remove_action', 1);
- $move_to = request_var('move_to', PRIVMSGS_INBOX);
+ $remove_action = $request->variable('remove_action', 1);
+ $move_to = $request->variable('move_to', PRIVMSGS_INBOX);
// Move to same folder?
if ($remove_action == 1 && $remove_folder_id == $move_to)
@@ -291,13 +290,13 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
{
if (check_form_key('ucp_pm_options'))
{
- $check_option = request_var('check_option', 0);
- $rule_option = request_var('rule_option', 0);
- $cond_option = request_var('cond_option', '');
- $action_option = explode('|', request_var('action_option', ''));
- $rule_string = ($cond_option != 'none') ? utf8_normalize_nfc(request_var('rule_string', '', true)) : '';
- $rule_user_id = ($cond_option != 'none') ? request_var('rule_user_id', 0) : 0;
- $rule_group_id = ($cond_option != 'none') ? request_var('rule_group_id', 0) : 0;
+ $check_option = $request->variable('check_option', 0);
+ $rule_option = $request->variable('rule_option', 0);
+ $cond_option = $request->variable('cond_option', '');
+ $action_option = explode('|', $request->variable('action_option', ''));
+ $rule_string = ($cond_option != 'none') ? $request->variable('rule_string', '', true) : '';
+ $rule_user_id = ($cond_option != 'none') ? $request->variable('rule_user_id', 0) : 0;
+ $rule_group_id = ($cond_option != 'none') ? $request->variable('rule_group_id', 0) : 0;
$action = (int) $action_option[0];
$folder_id = (int) $action_option[1];
@@ -371,7 +370,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
// Remove Rule
if (isset($_POST['delete_rule']) && !isset($_POST['cancel']))
{
- $delete_id = array_keys(request_var('delete_rule', array(0 => 0)));
+ $delete_id = array_keys($request->variable('delete_rule', array(0 => 0)));
$delete_id = (!empty($delete_id[0])) ? $delete_id[0] : 0;
if (!$delete_id)
@@ -507,18 +506,20 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
$rule_lang = $action_lang = $check_lang = array();
// Build all three language arrays
- preg_replace('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#e', "\${strtolower('\\2') . '_lang'}[constant('\\1')] = \$user->lang['PM_\\2']['\\3']", array_keys(get_defined_constants()));
+ preg_replace_callback('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#', function ($match) use(&$rule_lang, &$action_lang, &$check_lang, $user) {
+ ${strtolower($match[2]) . '_lang'}[constant($match[1])] = $user->lang['PM_' . $match[2]][$match[3]];
+ }, array_keys(get_defined_constants()));
/*
Rule Ordering:
-> CHECK_* -> RULE_* [IN $global_privmsgs_rules:CHECK_*] -> [IF $rule_conditions[RULE_*] [|text|bool|user|group|own_group]] -> ACTION_*
*/
- $check_option = request_var('check_option', 0);
- $rule_option = request_var('rule_option', 0);
- $cond_option = request_var('cond_option', '');
- $action_option = request_var('action_option', '');
- $back = (isset($_REQUEST['back'])) ? request_var('back', array('' => 0)) : array();
+ $check_option = $request->variable('check_option', 0);
+ $rule_option = $request->variable('rule_option', 0);
+ $cond_option = $request->variable('cond_option', '');
+ $action_option = $request->variable('action_option', '');
+ $back = (isset($_REQUEST['back'])) ? $request->variable('back', array('' => 0)) : array();
if (sizeof($back))
{
@@ -609,7 +610,7 @@ function define_check_option($hardcoded, $check_option, $check_lang)
*/
function define_action_option($hardcoded, $action_option, $action_lang, $folder)
{
- global $db, $template, $user;
+ global $template;
$l_action = $s_action_options = '';
if ($hardcoded)
@@ -698,7 +699,10 @@ function define_rule_option($hardcoded, $rule_option, $rule_lang, $check_ary)
*/
function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule_conditions)
{
- global $db, $template, $auth, $user;
+ global $db, $template, $auth, $user, $request, $phpbb_container;
+
+ /** @var \phpbb\group\helper $group_helper */
+ $group_helper = $phpbb_container->get('group_helper');
$template->assign_vars(array(
'S_COND_DEFINED' => true,
@@ -717,12 +721,11 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
// Define Condition
$condition = $global_rule_conditions[$rule_option];
- $current_value = '';
switch ($condition)
{
case 'text':
- $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true));
+ $rule_string = $request->variable('rule_string', '', true);
$template->assign_vars(array(
'S_TEXT_CONDITION' => true,
@@ -735,8 +738,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
break;
case 'user':
- $rule_user_id = request_var('rule_user_id', 0);
- $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true));
+ $rule_user_id = $request->variable('rule_user_id', 0);
+ $rule_string = $request->variable('rule_string', '', true);
if ($rule_string && !$rule_user_id)
{
@@ -778,8 +781,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
break;
case 'group':
- $rule_group_id = request_var('rule_group_id', 0);
- $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true));
+ $rule_group_id = $request->variable('rule_group_id', 0);
+ $rule_string = $request->variable('rule_string', '', true);
$sql = 'SELECT g.group_id, g.group_name, g.group_type
FROM ' . GROUPS_TABLE . ' g ';
@@ -810,13 +813,13 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
{
if ($rule_group_id && ($row['group_id'] == $rule_group_id))
{
- $rule_string = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']);
+ $rule_string = $group_helper->get_name($row['group_name']);
}
$s_class = ($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '';
$s_selected = ($row['group_id'] == $rule_group_id) ? ' selected="selected"' : '';
- $s_group_options .= '<option value="' . $row['group_id'] . '"' . $s_class . $s_selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ $s_group_options .= '<option value="' . $row['group_id'] . '"' . $s_class . $s_selected . '>' . $group_helper->get_name($row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php
index 19acd9ecb9..af2126c83d 100644
--- a/phpBB/includes/ucp/ucp_pm_viewfolder.php
+++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php
@@ -25,7 +25,7 @@ if (!defined('IN_PHPBB'))
*/
function view_folder($id, $mode, $folder_id, $folder)
{
- global $user, $template, $auth, $db, $cache;
+ global $user, $template, $auth, $db, $cache, $request;
global $phpbb_root_path, $config, $phpEx;
$submit_export = (isset($_POST['submit_export'])) ? true : false;
@@ -41,9 +41,6 @@ function view_folder($id, $mode, $folder_id, $folder)
$color_rows = array('marked', 'replied');
- // only show the friend/foe color rows if the module is enabled
- $zebra_enabled = false;
-
$_module = new p_master();
$_module->list_modules('ucp');
$_module->set_active('zebra');
@@ -196,9 +193,9 @@ function view_folder($id, $mode, $folder_id, $folder)
}
else
{
- $export_type = request_var('export_option', '');
- $enclosure = request_var('enclosure', '');
- $delimiter = request_var('delimiter', '');
+ $export_type = $request->variable('export_option', '');
+ $enclosure = $request->variable('enclosure', '');
+ $delimiter = $request->variable('delimiter', '');
if ($export_type == 'CSV' && ($delimiter === '' || $enclosure === ''))
{
@@ -397,15 +394,16 @@ function view_folder($id, $mode, $folder_id, $folder)
*/
function get_pm_from($folder_id, $folder, $user_id)
{
- global $user, $db, $template, $config, $auth, $phpbb_container, $phpbb_root_path, $phpEx;
+ global $user, $db, $template, $config, $auth, $phpbb_container, $phpbb_root_path, $phpEx, $request;
- $start = request_var('start', 0);
+ $start = $request->variable('start', 0);
// Additional vars later, pm ordering is mostly different from post ordering. :/
- $sort_days = request_var('st', 0);
- $sort_key = request_var('sk', 't');
- $sort_dir = request_var('sd', 'd');
+ $sort_days = $request->variable('st', 0);
+ $sort_key = $request->variable('sk', 't');
+ $sort_dir = $request->variable('sd', 'd');
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
// PM ordering options
diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php
index d7b9b32dbf..48d14a133c 100644
--- a/phpBB/includes/ucp/ucp_pm_viewmessage.php
+++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php
@@ -24,7 +24,7 @@ if (!defined('IN_PHPBB'))
*/
function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
{
- global $user, $template, $auth, $db, $cache, $phpbb_container;
+ global $user, $template, $auth, $db, $phpbb_container;
global $phpbb_root_path, $request, $phpEx, $config, $phpbb_dispatcher;
$user->add_lang(array('viewtopic', 'memberlist'));
@@ -32,7 +32,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
$msg_id = (int) $msg_id;
$folder_id = (int) $folder_id;
$author_id = (int) $message_row['author_id'];
- $view = request_var('view', '');
+ $view = $request->variable('view', '');
// Not able to view message, it was deleted by the sender
if ($message_row['pm_deleted'])
@@ -41,6 +41,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
$message = $user->lang['NO_AUTH_READ_REMOVED_MESSAGE'];
$message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>');
+ send_status_line(403, 'Forbidden');
trigger_error($message);
}
@@ -50,12 +51,10 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
trigger_error('NO_AUTH_READ_HOLD_MESSAGE');
}
- // Grab icons
- $icons = $cache->obtain_icons();
-
// Load the custom profile fields
if ($config['load_cpf_pm'])
{
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$profile_fields = $cp->grab_profile_fields_data($author_id);
@@ -231,7 +230,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&amp;mode=compose&amp;action=delete&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
'U_EMAIL' => $user_info['email'],
- 'U_REPORT' => ($config['allow_pm_report']) ? append_sid("{$phpbb_root_path}report.$phpEx", "pm=" . $message_row['msg_id']) : '',
+ 'U_REPORT' => ($config['allow_pm_report']) ? $phpbb_container->get('controller.helper')->route('phpbb_report_pm_controller', array('id' => $message_row['msg_id'])) : '',
'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&amp;mode=compose&amp;action=edit&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
@@ -356,7 +355,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
*/
function get_user_information($user_id, $user_row)
{
- global $db, $auth, $user, $cache;
+ global $db, $auth, $user;
global $phpbb_root_path, $phpEx, $config;
if (!$user_id)
diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php
index e63e9b4c08..c2aa910ed0 100644
--- a/phpBB/includes/ucp/ucp_prefs.php
+++ b/phpBB/includes/ucp/ucp_prefs.php
@@ -29,7 +29,7 @@ class ucp_prefs
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
+ global $config, $db, $user, $auth, $template, $phpbb_dispatcher, $request;
$submit = (isset($_POST['submit'])) ? true : false;
$error = $data = array();
@@ -40,16 +40,16 @@ class ucp_prefs
case 'personal':
add_form_key('ucp_prefs_personal');
$data = array(
- 'notifymethod' => request_var('notifymethod', $user->data['user_notify_type']),
- 'dateformat' => request_var('dateformat', $user->data['user_dateformat'], true),
- 'lang' => basename(request_var('lang', $user->data['user_lang'])),
- 'user_style' => request_var('user_style', (int) $user->data['user_style']),
- 'tz' => request_var('tz', $user->data['user_timezone']),
-
- 'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']),
- 'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']),
- 'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']),
- 'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']),
+ 'notifymethod' => $request->variable('notifymethod', $user->data['user_notify_type']),
+ 'dateformat' => $request->variable('dateformat', $user->data['user_dateformat'], true),
+ 'lang' => basename($request->variable('lang', $user->data['user_lang'])),
+ 'user_style' => $request->variable('user_style', (int) $user->data['user_style']),
+ 'tz' => $request->variable('tz', $user->data['user_timezone']),
+
+ 'viewemail' => $request->variable('viewemail', (bool) $user->data['user_allow_viewemail']),
+ 'massemail' => $request->variable('massemail', (bool) $user->data['user_allow_massemail']),
+ 'hideonline' => $request->variable('hideonline', (bool) !$user->data['user_allow_viewonline']),
+ 'allowpm' => $request->variable('allowpm', (bool) $user->data['user_allow_pm']),
);
if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml')))
@@ -221,20 +221,20 @@ class ucp_prefs
add_form_key('ucp_prefs_view');
$data = array(
- 'topic_sk' => request_var('topic_sk', (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't'),
- 'topic_sd' => request_var('topic_sd', (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd'),
- 'topic_st' => request_var('topic_st', (!empty($user->data['user_topic_show_days'])) ? (int) $user->data['user_topic_show_days'] : 0),
-
- 'post_sk' => request_var('post_sk', (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't'),
- 'post_sd' => request_var('post_sd', (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a'),
- 'post_st' => request_var('post_st', (!empty($user->data['user_post_show_days'])) ? (int) $user->data['user_post_show_days'] : 0),
-
- 'images' => request_var('images', (bool) $user->optionget('viewimg')),
- 'flash' => request_var('flash', (bool) $user->optionget('viewflash')),
- 'smilies' => request_var('smilies', (bool) $user->optionget('viewsmilies')),
- 'sigs' => request_var('sigs', (bool) $user->optionget('viewsigs')),
- 'avatars' => request_var('avatars', (bool) $user->optionget('viewavatars')),
- 'wordcensor' => request_var('wordcensor', (bool) $user->optionget('viewcensors')),
+ 'topic_sk' => $request->variable('topic_sk', (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't'),
+ 'topic_sd' => $request->variable('topic_sd', (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd'),
+ 'topic_st' => $request->variable('topic_st', (!empty($user->data['user_topic_show_days'])) ? (int) $user->data['user_topic_show_days'] : 0),
+
+ 'post_sk' => $request->variable('post_sk', (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't'),
+ 'post_sd' => $request->variable('post_sd', (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a'),
+ 'post_st' => $request->variable('post_st', (!empty($user->data['user_post_show_days'])) ? (int) $user->data['user_post_show_days'] : 0),
+
+ 'images' => $request->variable('images', (bool) $user->optionget('viewimg')),
+ 'flash' => $request->variable('flash', (bool) $user->optionget('viewflash')),
+ 'smilies' => $request->variable('smilies', (bool) $user->optionget('viewsmilies')),
+ 'sigs' => $request->variable('sigs', (bool) $user->optionget('viewsigs')),
+ 'avatars' => $request->variable('avatars', (bool) $user->optionget('viewavatars')),
+ 'wordcensor' => $request->variable('wordcensor', (bool) $user->optionget('viewcensors')),
);
/**
@@ -436,10 +436,10 @@ class ucp_prefs
case 'post':
$data = array(
- 'bbcode' => request_var('bbcode', $user->optionget('bbcode')),
- 'smilies' => request_var('smilies', $user->optionget('smilies')),
- 'sig' => request_var('sig', $user->optionget('attachsig')),
- 'notify' => request_var('notify', (bool) $user->data['user_notify']),
+ 'bbcode' => $request->variable('bbcode', $user->optionget('bbcode')),
+ 'smilies' => $request->variable('smilies', $user->optionget('smilies')),
+ 'sig' => $request->variable('sig', $user->optionget('attachsig')),
+ 'notify' => $request->variable('notify', (bool) $user->data['user_notify']),
);
add_form_key('ucp_prefs_post');
diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php
index 0be1930f1a..a86c4f2672 100644
--- a/phpBB/includes/ucp/ucp_profile.php
+++ b/phpBB/includes/ucp/ucp_profile.php
@@ -31,14 +31,12 @@ class ucp_profile
function main($id, $mode)
{
- global $cache, $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx;
- global $request, $phpbb_container, $phpbb_dispatcher;
+ global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx;
+ global $request, $phpbb_container, $phpbb_log, $phpbb_dispatcher;
$user->add_lang('posting');
- $preview = $request->variable('preview', false, false, \phpbb\request\request_interface::POST);
$submit = $request->variable('submit', false, false, \phpbb\request\request_interface::POST);
- $delete = $request->variable('delete', false, false, \phpbb\request\request_interface::POST);
$error = $data = array();
$s_hidden_fields = '';
@@ -47,8 +45,8 @@ class ucp_profile
case 'reg_details':
$data = array(
- 'username' => utf8_normalize_nfc(request_var('username', $user->data['username'], true)),
- 'email' => strtolower(request_var('email', $user->data['user_email'])),
+ 'username' => $request->variable('username', $user->data['username'], true),
+ 'email' => strtolower($request->variable('email', $user->data['user_email'])),
'new_password' => $request->variable('new_password', '', true),
'cur_password' => $request->variable('cur_password', '', true),
'password_confirm' => $request->variable('password_confirm', '', true),
@@ -96,6 +94,7 @@ class ucp_profile
}
// Instantiate passwords manager
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
// Only check the new password against the previous password if there have been no errors
@@ -139,18 +138,30 @@ class ucp_profile
if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username'])
{
- add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_NAME', false, array(
+ 'reportee_id' => $user->data['user_id'],
+ $user->data['username'],
+ $data['username']
+ ));
}
if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !$passwords_manager->check($data['new_password'], $user->data['user_password']))
{
$user->reset_login_keys();
- add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']);
+ $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array(
+ 'reportee_id' => $user->data['user_id'],
+ $user->data['username']
+ ));
}
if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'])
{
- add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $data['username'], $user->data['user_email'], $data['email']);
+ $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'],
+ $data['email']
+ ));
}
$message = 'PROFILE_UPDATED';
@@ -268,15 +279,17 @@ class ucp_profile
// Do not display profile information panel if not authed to do so
if (!$auth->acl_get('u_chgprofileinfo'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_PROFILEINFO');
}
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$cp_data = $cp_error = array();
$data = array(
- 'jabber' => utf8_normalize_nfc(request_var('jabber', $user->data['user_jabber'], true)),
+ 'jabber' => $request->variable('jabber', $user->data['user_jabber'], true),
);
if ($config['allow_birthdays'])
@@ -288,9 +301,9 @@ class ucp_profile
list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user->data['user_birthday']);
}
- $data['bday_day'] = request_var('bday_day', $data['bday_day']);
- $data['bday_month'] = request_var('bday_month', $data['bday_month']);
- $data['bday_year'] = request_var('bday_year', $data['bday_year']);
+ $data['bday_day'] = $request->variable('bday_day', $data['bday_day']);
+ $data['bday_month'] = $request->variable('bday_month', $data['bday_month']);
+ $data['bday_year'] = $request->variable('bday_year', $data['bday_year']);
$data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']);
}
@@ -417,7 +430,6 @@ class ucp_profile
$selected = ($i == $data['bday_month']) ? ' selected="selected"' : '';
$s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>";
}
- $s_birthday_year_options = '';
$now = getdate();
$s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>';
@@ -453,128 +465,142 @@ class ucp_profile
if (!$auth->acl_get('u_sig'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_SIGNATURE');
}
include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
- $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $user->optionget('sig_bbcode') : false;
- $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $user->optionget('sig_smilies') : false;
- $enable_urls = ($config['allow_sig_links']) ? (bool) $user->optionget('sig_links') : false;
+ $preview = $request->is_set_post('preview');
- $signature = utf8_normalize_nfc(request_var('signature', (string) $user->data['user_sig'], true));
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? $user->optionget('sig_bbcode') : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? $user->optionget('sig_smilies') : false;
+ $enable_urls = ($config['allow_sig_links']) ? $user->optionget('sig_links') : false;
- add_form_key('ucp_sig');
+ $decoded_message = generate_text_for_edit($user->data['user_sig'], $user->data['user_sig_bbcode_uid'], $user->data['user_sig_bbcode_bitfield']);
+ $signature = $request->variable('signature', $decoded_message['text'], true);
+ $signature_preview = '';
if ($submit || $preview)
{
- include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? !$request->variable('disable_bbcode', false) : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? !$request->variable('disable_smilies', false) : false;
+ $enable_urls = ($config['allow_sig_links']) ? !$request->variable('disable_magic_url', false) : false;
+
+ if (!check_form_key('ucp_sig'))
+ {
+ $error[] = 'FORM_INVALID';
+ }
+ }
+
+ /**
+ * Modify user signature on editing profile in UCP
+ *
+ * @event core.ucp_profile_modify_signature
+ * @var bool enable_bbcode Whether or not bbcode is enabled
+ * @var bool enable_smilies Whether or not smilies are enabled
+ * @var bool enable_urls Whether or not urls are enabled
+ * @var string signature Users signature text
+ * @var array error Any error strings
+ * @var bool submit Whether or not the form has been sumitted
+ * @var bool preview Whether or not the signature is being previewed
+ * @since 3.1.10-RC1
+ * @change 3.2.0-RC2 Removed message parser
+ */
+ $vars = array(
+ 'enable_bbcode',
+ 'enable_smilies',
+ 'enable_urls',
+ 'signature',
+ 'error',
+ 'submit',
+ 'preview',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.ucp_profile_modify_signature', compact($vars)));
+
+ $bbcode_uid = $bbcode_bitfield = $bbcode_flags = '';
+ $warn_msg = generate_text_for_storage(
+ $signature,
+ $bbcode_uid,
+ $bbcode_bitfield,
+ $bbcode_flags,
+ $enable_bbcode,
+ $enable_urls,
+ $enable_smilies,
+ $config['allow_sig_img'],
+ $config['allow_sig_flash'],
+ true,
+ $config['allow_sig_links'],
+ 'sig'
+ );
- $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false;
- $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false;
- $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
+ if (sizeof($warn_msg))
+ {
+ $error += $warn_msg;
+ }
+ if (!$submit)
+ {
+ // Parse it for displaying
+ $signature_preview = generate_text_for_display($signature, $bbcode_uid, $bbcode_bitfield, $bbcode_flags);
+ }
+ else
+ {
if (!sizeof($error))
{
- $message_parser = new parse_message($signature);
+ $user->optionset('sig_bbcode', $enable_bbcode);
+ $user->optionset('sig_smilies', $enable_smilies);
+ $user->optionset('sig_links', $enable_urls);
+
+ $sql_ary = array(
+ 'user_sig' => $signature,
+ 'user_options' => $user->data['user_options'],
+ 'user_sig_bbcode_uid' => $bbcode_uid,
+ 'user_sig_bbcode_bitfield' => $bbcode_bitfield
+ );
/**
- * Modify user signature on editing profile in UCP
+ * Modify user registration data before submitting it to the database
*
- * @event core.ucp_profile_modify_signature
- * @var bool enable_bbcode Whether or not bbcode is enabled
- * @var bool enable_smilies Whether or not smilies are enabled
- * @var bool enable_urls Whether or not urls are enabled
- * @var string signature Users signature text
- * @var object message_parser The message parser object
- * @var array error Any error strings
- * @var bool submit Whether or not the form has been sumitted
- * @var bool preview Whether or not the signature is being previewed
+ * @event core.ucp_profile_modify_signature_sql_ary
+ * @var array sql_ary Array with user signature data to submit to the database
* @since 3.1.10-RC1
*/
- $vars = array(
- 'enable_bbcode',
- 'enable_smilies',
- 'enable_urls',
- 'signature',
- 'message_parser',
- 'error',
- 'submit',
- 'preview',
- );
- extract($phpbb_dispatcher->trigger_event('core.ucp_profile_modify_signature', compact($vars)));
-
- // Allowing Quote BBCode
- $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig');
-
- if (sizeof($message_parser->warn_msg))
- {
- $error[] = implode('<br />', $message_parser->warn_msg);
- }
-
- if (!check_form_key('ucp_sig'))
- {
- $error[] = 'FORM_INVALID';
- }
-
- if (!sizeof($error) && $submit)
- {
- $user->optionset('sig_bbcode', $enable_bbcode);
- $user->optionset('sig_smilies', $enable_smilies);
- $user->optionset('sig_links', $enable_urls);
-
- $sql_ary = array(
- 'user_sig' => (string) $message_parser->message,
- 'user_options' => $user->data['user_options'],
- 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid,
- 'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield
- );
-
- /**
- * Modify user registration data before submitting it to the database
- *
- * @event core.ucp_profile_modify_signature_sql_ary
- * @var array sql_ary Array with user signature data to submit to the database
- * @since 3.1.10-RC1
- */
- $vars = array('sql_ary');
- extract($phpbb_dispatcher->trigger_event('core.ucp_profile_modify_signature_sql_ary', compact($vars)));
+ $vars = array('sql_ary');
+ extract($phpbb_dispatcher->trigger_event('core.ucp_profile_modify_signature_sql_ary', compact($vars)));
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
- WHERE user_id = ' . $user->data['user_id'];
- $db->sql_query($sql);
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
+ WHERE user_id = ' . $user->data['user_id'];
+ $db->sql_query($sql);
- $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>');
- trigger_error($message);
- }
+ $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>');
+ trigger_error($message);
}
-
- // Replace "error" strings with their real, localised form
- $error = array_map(array($user, 'lang'), $error);
}
- $signature_preview = '';
- if ($preview)
+ // Replace "error" strings with their real, localised form
+ $error = array_map(array($user, 'lang'), $error);
+
+ if ($request->is_set_post('preview'))
{
- // Now parse it for displaying
- $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false);
- unset($message_parser);
+ $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_flags);
}
- decode_message($signature, $user->data['user_sig_bbcode_uid']);
+ /** @var \phpbb\controller\helper $controller_helper */
+ $controller_helper = $phpbb_container->get('controller.helper');
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'SIGNATURE' => $signature,
+ 'SIGNATURE' => $decoded_message['text'],
'SIGNATURE_PREVIEW' => $signature_preview,
'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '',
'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '',
'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '',
- 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
+ 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
@@ -590,6 +616,8 @@ class ucp_profile
'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false)
);
+ add_form_key('ucp_sig');
+
// Build custom bbcodes array
display_custom_bbcodes();
@@ -606,6 +634,7 @@ class ucp_profile
if ($config['allow_avatar'] && $auth->acl_get('u_chgavatar'))
{
+ /* @var $phpbb_avatar_manager \phpbb\avatar\manager */
$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
$avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers();
@@ -731,7 +760,7 @@ class ucp_profile
if ($submit)
{
- $keys = request_var('keys', array(''));
+ $keys = $request->variable('keys', array(''));
if (!check_form_key('ucp_autologin_keys'))
{
diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php
index 3426af95d0..1b62790700 100644
--- a/phpBB/includes/ucp/ucp_register.php
+++ b/phpBB/includes/ucp/ucp_register.php
@@ -29,7 +29,7 @@ class ucp_register
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx;
+ global $config, $db, $user, $template, $phpbb_root_path, $phpEx;
global $request, $phpbb_container, $phpbb_dispatcher;
//
@@ -42,8 +42,8 @@ class ucp_register
$coppa = $request->is_set('coppa') ? (int) $request->variable('coppa', false) : false;
$agreed = $request->variable('agreed', false);
$submit = $request->is_set_post('submit');
- $change_lang = request_var('change_lang', '');
- $user_lang = request_var('lang', $user->lang_name);
+ $change_lang = $request->variable('change_lang', '');
+ $user_lang = $request->variable('lang', $user->lang_name);
if ($agreed)
{
@@ -77,6 +77,7 @@ class ucp_register
}
}
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$error = $cp_data = $cp_error = array();
@@ -88,6 +89,7 @@ class ucp_register
if (!empty($login_link_data))
{
// Confirm that we have all necessary data
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$auth_provider = $provider_collection->get_provider($request->variable('auth_provider', ''));
@@ -113,10 +115,10 @@ class ucp_register
{
// We do not include the password
$s_hidden_fields = array_merge($s_hidden_fields, array(
- 'username' => utf8_normalize_nfc(request_var('username', '', true)),
- 'email' => strtolower(request_var('email', '')),
+ 'username' => $request->variable('username', '', true),
+ 'email' => strtolower($request->variable('email', '')),
'lang' => $user->lang_name,
- 'tz' => request_var('tz', $config['board_timezone']),
+ 'tz' => $request->variable('tz', $config['board_timezone']),
));
}
@@ -200,12 +202,12 @@ class ucp_register
$timezone = $config['board_timezone'];
$data = array(
- 'username' => utf8_normalize_nfc(request_var('username', '', true)),
+ 'username' => $request->variable('username', '', true),
'new_password' => $request->variable('new_password', '', true),
'password_confirm' => $request->variable('password_confirm', '', true),
- 'email' => strtolower(request_var('email', '')),
- 'lang' => basename(request_var('lang', $user->lang_name)),
- 'tz' => request_var('tz', $timezone),
+ 'email' => strtolower($request->variable('email', '')),
+ 'lang' => basename($request->variable('lang', $user->lang_name)),
+ 'tz' => $request->variable('tz', $timezone),
);
/**
* Add UCP register data before they are assigned to the template or submitted
@@ -334,6 +336,7 @@ class ucp_register
}
// Instantiate passwords manager
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
$user_row = array(
@@ -439,6 +442,7 @@ class ucp_register
if ($config['require_activation'] == USER_ACTIVATION_ADMIN)
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
$phpbb_notifications->add_notifications('notification.type.admin_activate_user', array(
'user_id' => $user_id,
@@ -480,7 +484,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);
- $confirm_image = '';
// Visual Confirmation - Show images
if ($config['enable_confirm'])
@@ -503,7 +506,9 @@ class ucp_register
break;
}
- $timezone_selects = phpbb_timezone_select($template, $user, $data['tz'], true);
+ // Assign template vars for timezone select
+ phpbb_timezone_select($template, $user, $data['tz'], true);
+
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
'USERNAME' => $data['username'],
diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php
index 415bf0e84d..a44f077693 100644
--- a/phpBB/includes/ucp/ucp_remind.php
+++ b/phpBB/includes/ucp/ucp_remind.php
@@ -29,16 +29,16 @@ class ucp_remind
function main($id, $mode)
{
- global $config, $phpbb_root_path, $phpEx;
- global $db, $user, $auth, $template, $phpbb_container;
+ global $config, $phpbb_root_path, $phpEx, $request;
+ global $db, $user, $template, $phpbb_container;
if (!$config['allow_password_reset'])
{
trigger_error($user->lang('UCP_PASSWORD_RESET_DISABLED', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'));
}
- $username = request_var('username', '', true);
- $email = strtolower(request_var('email', ''));
+ $username = $request->variable('username', '', true);
+ $email = strtolower($request->variable('email', ''));
$submit = (isset($_POST['submit'])) ? true : false;
if ($submit)
@@ -79,6 +79,7 @@ class ucp_remind
if (!$auth2->acl_get('u_chgpasswd'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_AUTH_PASSWORD_REMINDER');
}
@@ -92,6 +93,7 @@ class ucp_remind
$user_actkey = gen_rand_string(mt_rand(6, 10));
// Instantiate passwords manager
+ /* @var $manager \phpbb\passwords\manager */
$passwords_manager = $phpbb_container->get('passwords.manager');
$sql = 'UPDATE ' . USERS_TABLE . "
diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php
index 9fe8850000..44c54100cd 100644
--- a/phpBB/includes/ucp/ucp_resend.php
+++ b/phpBB/includes/ucp/ucp_resend.php
@@ -30,10 +30,10 @@ class ucp_resend
function main($id, $mode)
{
global $config, $phpbb_root_path, $phpEx;
- global $db, $user, $auth, $template;
+ global $db, $user, $auth, $template, $request;
- $username = request_var('username', '', true);
- $email = strtolower(request_var('email', ''));
+ $username = $request->variable('username', '', true);
+ $email = strtolower($request->variable('email', ''));
$submit = (isset($_POST['submit'])) ? true : false;
add_form_key('ucp_resend');
diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php
index dbf8cf31c1..fa6a03f87c 100644
--- a/phpBB/includes/ucp/ucp_zebra.php
+++ b/phpBB/includes/ucp/ucp_zebra.php
@@ -25,7 +25,7 @@ class ucp_zebra
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher;
+ global $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher;
$submit = (isset($_POST['submit']) || isset($_GET['add']) || isset($_GET['remove'])) ? true : false;
$s_hidden_fields = '';
@@ -44,7 +44,7 @@ class ucp_zebra
foreach ($var_ary as $var => $default)
{
- $data[$var] = request_var($var, $default, true);
+ $data[$var] = $request->variable($var, $default, true);
}
if (!empty($data['add']) || sizeof($data['usernames']))
diff --git a/phpBB/includes/utf/data/utf_canonical_comp.php b/phpBB/includes/utf/data/utf_canonical_comp.php
deleted file mode 100644
index 2de3149ee8..0000000000
--- a/phpBB/includes/utf/data/utf_canonical_comp.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$GLOBALS['utf_canonical_comp']=array('AÌ€'=>'À','AÌ'=>'Ã','AÌ‚'=>'Â','Ã'=>'Ã','Ä'=>'Ä','AÌŠ'=>'Ã…','Ç'=>'Ç','EÌ€'=>'È','EÌ'=>'É','EÌ‚'=>'Ê','Ë'=>'Ë','IÌ€'=>'ÃŒ','IÌ'=>'Ã','IÌ‚'=>'ÃŽ','Ï'=>'Ã','Ñ'=>'Ñ','OÌ€'=>'Ã’','OÌ'=>'Ó','OÌ‚'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','UÌ€'=>'Ù','UÌ'=>'Ú','UÌ‚'=>'Û','Ü'=>'Ãœ','YÌ'=>'Ã','aÌ€'=>'à','aÌ'=>'á','aÌ‚'=>'â','ã'=>'ã','ä'=>'ä','aÌŠ'=>'Ã¥','ç'=>'ç','eÌ€'=>'è','eÌ'=>'é','eÌ‚'=>'ê','ë'=>'ë','iÌ€'=>'ì','iÌ'=>'í','iÌ‚'=>'î','ï'=>'ï','ñ'=>'ñ','oÌ€'=>'ò','oÌ'=>'ó','oÌ‚'=>'ô','õ'=>'õ','ö'=>'ö','uÌ€'=>'ù','uÌ'=>'ú','uÌ‚'=>'û','ü'=>'ü','yÌ'=>'ý','ÿ'=>'ÿ','AÌ„'=>'Ä€','aÌ„'=>'Ä','Ă'=>'Ä‚','ă'=>'ă','Ą'=>'Ä„','ą'=>'Ä…','CÌ'=>'Ć','cÌ'=>'ć','CÌ‚'=>'Ĉ','cÌ‚'=>'ĉ','Ċ'=>'ÄŠ','ċ'=>'Ä‹','CÌŒ'=>'ÄŒ','cÌŒ'=>'Ä','DÌŒ'=>'ÄŽ','dÌŒ'=>'Ä','EÌ„'=>'Ä’','eÌ„'=>'Ä“','Ĕ'=>'Ä”','ĕ'=>'Ä•','Ė'=>'Ä–','ė'=>'Ä—','Ę'=>'Ę','ę'=>'Ä™','EÌŒ'=>'Äš','eÌŒ'=>'Ä›','GÌ‚'=>'Äœ','gÌ‚'=>'Ä','Ğ'=>'Äž','ğ'=>'ÄŸ','Ġ'=>'Ä ','ġ'=>'Ä¡','Ģ'=>'Ä¢','ģ'=>'Ä£','HÌ‚'=>'Ĥ','hÌ‚'=>'Ä¥','Ĩ'=>'Ĩ','ĩ'=>'Ä©','IÌ„'=>'Ī','iÌ„'=>'Ä«','Ĭ'=>'Ĭ','ĭ'=>'Ä­','Į'=>'Ä®','į'=>'į','İ'=>'Ä°','JÌ‚'=>'Ä´','jÌ‚'=>'ĵ','Ķ'=>'Ķ','ķ'=>'Ä·','LÌ'=>'Ĺ','lÌ'=>'ĺ','Ļ'=>'Ä»','ļ'=>'ļ','LÌŒ'=>'Ľ','lÌŒ'=>'ľ','NÌ'=>'Ń','nÌ'=>'Å„','Ņ'=>'Å…','ņ'=>'ņ','NÌŒ'=>'Ň','nÌŒ'=>'ň','OÌ„'=>'ÅŒ','oÌ„'=>'Å','Ŏ'=>'ÅŽ','ŏ'=>'Å','OÌ‹'=>'Å','oÌ‹'=>'Å‘','RÌ'=>'Å”','rÌ'=>'Å•','Ŗ'=>'Å–','ŗ'=>'Å—','RÌŒ'=>'Ř','rÌŒ'=>'Å™','SÌ'=>'Åš','sÌ'=>'Å›','SÌ‚'=>'Åœ','sÌ‚'=>'Å','Ş'=>'Åž','ş'=>'ÅŸ','SÌŒ'=>'Å ','sÌŒ'=>'Å¡','Ţ'=>'Å¢','ţ'=>'Å£','TÌŒ'=>'Ť','tÌŒ'=>'Å¥','Ũ'=>'Ũ','ũ'=>'Å©','UÌ„'=>'Ū','uÌ„'=>'Å«','Ŭ'=>'Ŭ','ŭ'=>'Å­','UÌŠ'=>'Å®','uÌŠ'=>'ů','UÌ‹'=>'Å°','uÌ‹'=>'ű','Ų'=>'Ų','ų'=>'ų','WÌ‚'=>'Å´','wÌ‚'=>'ŵ','YÌ‚'=>'Ŷ','yÌ‚'=>'Å·','Ÿ'=>'Ÿ','ZÌ'=>'Ź','zÌ'=>'ź','Ż'=>'Å»','ż'=>'ż','ZÌŒ'=>'Ž','zÌŒ'=>'ž','OÌ›'=>'Æ ','oÌ›'=>'Æ¡','UÌ›'=>'Ư','uÌ›'=>'Æ°','AÌŒ'=>'Ç','aÌŒ'=>'ÇŽ','IÌŒ'=>'Ç','iÌŒ'=>'Ç','OÌŒ'=>'Ç‘','oÌŒ'=>'Ç’','UÌŒ'=>'Ç“','uÌŒ'=>'Ç”','Ǖ'=>'Ç•','ǖ'=>'Ç–','ÃœÌ'=>'Ç—','üÌ'=>'ǘ','Ǚ'=>'Ç™','ǚ'=>'Çš','Ǜ'=>'Ç›','ǜ'=>'Çœ','Ǟ'=>'Çž','ǟ'=>'ÇŸ','Ǡ'=>'Ç ','ǡ'=>'Ç¡','Ǣ'=>'Ç¢','ǣ'=>'Ç£','GÌŒ'=>'Ǧ','gÌŒ'=>'ǧ','KÌŒ'=>'Ǩ','kÌŒ'=>'Ç©','Ǫ'=>'Ǫ','ǫ'=>'Ç«','Ǭ'=>'Ǭ','Ç«Ì„'=>'Ç­','Æ·ÌŒ'=>'Ç®','Ê’ÌŒ'=>'ǯ','jÌŒ'=>'Ç°','GÌ'=>'Ç´','gÌ'=>'ǵ','NÌ€'=>'Ǹ','nÌ€'=>'ǹ','Ã…Ì'=>'Ǻ','Ã¥Ì'=>'Ç»','ÆÌ'=>'Ǽ','æÌ'=>'ǽ','ØÌ'=>'Ǿ','øÌ'=>'Ç¿','AÌ'=>'È€','aÌ'=>'È','AÌ‘'=>'È‚','aÌ‘'=>'ȃ','EÌ'=>'È„','eÌ'=>'È…','EÌ‘'=>'Ȇ','eÌ‘'=>'ȇ','IÌ'=>'Ȉ','iÌ'=>'ȉ','IÌ‘'=>'ÈŠ','iÌ‘'=>'È‹','OÌ'=>'ÈŒ','oÌ'=>'È','OÌ‘'=>'ÈŽ','oÌ‘'=>'È','RÌ'=>'È','rÌ'=>'È‘','RÌ‘'=>'È’','rÌ‘'=>'È“','UÌ'=>'È”','uÌ'=>'È•','UÌ‘'=>'È–','uÌ‘'=>'È—','Ș'=>'Ș','ș'=>'È™','Ț'=>'Èš','ț'=>'È›','HÌŒ'=>'Èž','hÌŒ'=>'ÈŸ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'È©','Ȫ'=>'Ȫ','ȫ'=>'È«','Ȭ'=>'Ȭ','ȭ'=>'È­','Ȯ'=>'È®','ȯ'=>'ȯ','Ȱ'=>'È°','ȱ'=>'ȱ','YÌ„'=>'Ȳ','yÌ„'=>'ȳ','̈Ì'=>'Í„','¨Ì'=>'Î…','ΑÌ'=>'Ά','ΕÌ'=>'Έ','ΗÌ'=>'Ή','ΙÌ'=>'Ί','ΟÌ'=>'ÎŒ','Î¥Ì'=>'ÎŽ','ΩÌ'=>'Î','ÏŠÌ'=>'Î','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','αÌ'=>'ά','εÌ'=>'έ','ηÌ'=>'ή','ιÌ'=>'ί','Ï‹Ì'=>'ΰ','ϊ'=>'ÏŠ','ϋ'=>'Ï‹','οÌ'=>'ÏŒ','Ï…Ì'=>'Ï','ωÌ'=>'ÏŽ','Ï’Ì'=>'Ï“','ϔ'=>'Ï”','Ѐ'=>'Ѐ','Ё'=>'Ð','ГÌ'=>'Ѓ','Ї'=>'Ї','КÌ'=>'ÐŒ','Ѝ'=>'Ð','Ў'=>'ÐŽ','Й'=>'Й','й'=>'й','ѐ'=>'Ñ','ё'=>'Ñ‘','гÌ'=>'Ñ“','ї'=>'Ñ—','кÌ'=>'Ñœ','ѝ'=>'Ñ','ў'=>'Ñž','Ñ´Ì'=>'Ѷ','ѵÌ'=>'Ñ·','Ӂ'=>'Ó','ӂ'=>'Ó‚','Ð̆'=>'Ó','ӑ'=>'Ó‘','Ð̈'=>'Ó’','ӓ'=>'Ó“','Ӗ'=>'Ó–','ӗ'=>'Ó—','Ӛ'=>'Óš','ӛ'=>'Ó›','Ӝ'=>'Óœ','ӝ'=>'Ó','Ӟ'=>'Óž','ӟ'=>'ÓŸ','Ӣ'=>'Ó¢','ӣ'=>'Ó£','Ӥ'=>'Ó¤','ӥ'=>'Ó¥','Ӧ'=>'Ó¦','ӧ'=>'Ó§','Ӫ'=>'Óª','ӫ'=>'Ó«','Ӭ'=>'Ó¬','Ñ̈'=>'Ó­','Ӯ'=>'Ó®','ӯ'=>'Ó¯','Ӱ'=>'Ó°','ӱ'=>'Ó±','Ӳ'=>'Ó²','ӳ'=>'Ó³','Ӵ'=>'Ó´','ӵ'=>'Óµ','Ӹ'=>'Ó¸','ӹ'=>'Ó¹','آ'=>'Ø¢','أ'=>'Ø£','ÙˆÙ”'=>'ؤ','إ'=>'Ø¥','ÙŠÙ”'=>'ئ','Û•Ù”'=>'Û€','ÛÙ”'=>'Û‚','Û’Ù”'=>'Û“','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','ো'=>'ো','ৌ'=>'ৌ','ୈ'=>'à­ˆ','ୋ'=>'à­‹','ୌ'=>'à­Œ','ஔ'=>'à®”','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','ೀ'=>'à³€','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','ේ'=>'à·š','à·™à·'=>'à·œ','ෝ'=>'à·','ෞ'=>'à·ž','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ཱྀ'=>'à¾','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','á¬á¬µ'=>'ᬎ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','ᭀ'=>'á­€','ᭁ'=>'á­','ᭃ'=>'á­ƒ','AÌ¥'=>'Ḁ','aÌ¥'=>'á¸','Ḃ'=>'Ḃ','ḃ'=>'ḃ','BÌ£'=>'Ḅ','bÌ£'=>'ḅ','Ḇ'=>'Ḇ','ḇ'=>'ḇ','ÇÌ'=>'Ḉ','çÌ'=>'ḉ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','DÌ£'=>'Ḍ','dÌ£'=>'á¸','Ḏ'=>'Ḏ','ḏ'=>'á¸','Ḑ'=>'á¸','ḑ'=>'ḑ','DÌ­'=>'Ḓ','dÌ­'=>'ḓ','Ä’Ì€'=>'Ḕ','Ä“Ì€'=>'ḕ','Ä’Ì'=>'Ḗ','Ä“Ì'=>'ḗ','EÌ­'=>'Ḙ','eÌ­'=>'ḙ','EÌ°'=>'Ḛ','eÌ°'=>'ḛ','Ḝ'=>'Ḝ','ḝ'=>'á¸','Ḟ'=>'Ḟ','ḟ'=>'ḟ','GÌ„'=>'Ḡ','gÌ„'=>'ḡ','Ḣ'=>'Ḣ','ḣ'=>'ḣ','HÌ£'=>'Ḥ','hÌ£'=>'ḥ','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','HÌ®'=>'Ḫ','hÌ®'=>'ḫ','IÌ°'=>'Ḭ','iÌ°'=>'ḭ','ÃÌ'=>'Ḯ','ïÌ'=>'ḯ','KÌ'=>'Ḱ','kÌ'=>'ḱ','KÌ£'=>'Ḳ','kÌ£'=>'ḳ','Ḵ'=>'Ḵ','ḵ'=>'ḵ','LÌ£'=>'Ḷ','lÌ£'=>'ḷ','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','LÌ­'=>'Ḽ','lÌ­'=>'ḽ','MÌ'=>'Ḿ','mÌ'=>'ḿ','Ṁ'=>'á¹€','ṁ'=>'á¹','MÌ£'=>'Ṃ','mÌ£'=>'ṃ','Ṅ'=>'Ṅ','ṅ'=>'á¹…','NÌ£'=>'Ṇ','nÌ£'=>'ṇ','Ṉ'=>'Ṉ','ṉ'=>'ṉ','NÌ­'=>'Ṋ','nÌ­'=>'ṋ','ÕÌ'=>'Ṍ','õÌ'=>'á¹','Ṏ'=>'Ṏ','ṏ'=>'á¹','Ṑ'=>'á¹','ÅÌ€'=>'ṑ','ÅŒÌ'=>'á¹’','ÅÌ'=>'ṓ','PÌ'=>'á¹”','pÌ'=>'ṕ','Ṗ'=>'á¹–','ṗ'=>'á¹—','Ṙ'=>'Ṙ','ṙ'=>'á¹™','RÌ£'=>'Ṛ','rÌ£'=>'á¹›','Ṝ'=>'Ṝ','ṝ'=>'á¹','Ṟ'=>'Ṟ','ṟ'=>'ṟ','Ṡ'=>'á¹ ','ṡ'=>'ṡ','SÌ£'=>'á¹¢','sÌ£'=>'á¹£','Ṥ'=>'Ṥ','ṥ'=>'á¹¥','Ṧ'=>'Ṧ','ṧ'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','TÌ£'=>'Ṭ','tÌ£'=>'á¹­','Ṯ'=>'á¹®','ṯ'=>'ṯ','TÌ­'=>'á¹°','tÌ­'=>'á¹±','Ṳ'=>'á¹²','ṳ'=>'á¹³','UÌ°'=>'á¹´','uÌ°'=>'á¹µ','UÌ­'=>'Ṷ','uÌ­'=>'á¹·','ŨÌ'=>'Ṹ','Å©Ì'=>'á¹¹','Ṻ'=>'Ṻ','ṻ'=>'á¹»','Ṽ'=>'á¹¼','ṽ'=>'á¹½','VÌ£'=>'á¹¾','vÌ£'=>'ṿ','WÌ€'=>'Ẁ','wÌ€'=>'áº','WÌ'=>'Ẃ','wÌ'=>'ẃ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','WÌ£'=>'Ẉ','wÌ£'=>'ẉ','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','ẍ'=>'áº','Ẏ'=>'Ẏ','ẏ'=>'áº','ZÌ‚'=>'áº','zÌ‚'=>'ẑ','ZÌ£'=>'Ẓ','zÌ£'=>'ẓ','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','wÌŠ'=>'ẘ','yÌŠ'=>'ẙ','ẛ'=>'ẛ','AÌ£'=>'Ạ','aÌ£'=>'ạ','Ả'=>'Ả','ả'=>'ả','ÂÌ'=>'Ấ','âÌ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ä‚Ì'=>'Ắ','ăÌ'=>'ắ','Ä‚Ì€'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','EÌ£'=>'Ẹ','eÌ£'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','ÊÌ'=>'Ế','êÌ'=>'ế','Ề'=>'Ề','ề'=>'á»','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'á»…','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','IÌ£'=>'Ị','iÌ£'=>'ị','OÌ£'=>'Ọ','oÌ£'=>'á»','Ỏ'=>'Ỏ','ỏ'=>'á»','ÔÌ'=>'á»','ôÌ'=>'ố','Ồ'=>'á»’','ồ'=>'ồ','Ổ'=>'á»”','ổ'=>'ổ','Ỗ'=>'á»–','ỗ'=>'á»—','Ộ'=>'Ộ','á»Ì‚'=>'á»™','Æ Ì'=>'Ớ','Æ¡Ì'=>'á»›','Ờ'=>'Ờ','Æ¡Ì€'=>'á»','Ở'=>'Ở','ở'=>'ở','Ỡ'=>'á» ','ỡ'=>'ỡ','Ợ'=>'Ợ','Æ¡Ì£'=>'ợ','UÌ£'=>'Ụ','uÌ£'=>'ụ','Ủ'=>'Ủ','ủ'=>'ủ','ƯÌ'=>'Ứ','Æ°Ì'=>'ứ','Ừ'=>'Ừ','Æ°Ì€'=>'ừ','Ử'=>'Ử','ử'=>'á»­','Ữ'=>'á»®','ữ'=>'ữ','Ự'=>'á»°','Æ°Ì£'=>'á»±','YÌ€'=>'Ỳ','yÌ€'=>'ỳ','YÌ£'=>'á»´','yÌ£'=>'ỵ','Ỷ'=>'Ỷ','ỷ'=>'á»·','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'á¼€','ἁ'=>'á¼','ἂ'=>'ἂ','á¼Ì€'=>'ἃ','á¼€Ì'=>'ἄ','á¼Ì'=>'á¼…','ἆ'=>'ἆ','á¼Í‚'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','ἈÌ'=>'Ἄ','ἉÌ'=>'á¼','Ἆ'=>'Ἆ','Ἇ'=>'á¼','ἐ'=>'á¼','ἑ'=>'ἑ','á¼Ì€'=>'á¼’','ἓ'=>'ἓ','á¼Ì'=>'á¼”','ἑÌ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'á¼™','Ἒ'=>'Ἒ','Ἓ'=>'á¼›','ἘÌ'=>'Ἔ','á¼™Ì'=>'á¼','ἠ'=>'á¼ ','ἡ'=>'ἡ','ἢ'=>'á¼¢','ἣ'=>'á¼£','á¼ Ì'=>'ἤ','ἡÌ'=>'á¼¥','á¼ Í‚'=>'ἦ','ἧ'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','ἨÌ'=>'Ἤ','ἩÌ'=>'á¼­','Ἦ'=>'á¼®','Ἧ'=>'Ἧ','ἰ'=>'á¼°','ἱ'=>'á¼±','á¼°Ì€'=>'á¼²','ἳ'=>'á¼³','á¼°Ì'=>'á¼´','á¼±Ì'=>'á¼µ','á¼°Í‚'=>'ἶ','ἷ'=>'á¼·','Ἰ'=>'Ἰ','Ἱ'=>'á¼¹','Ἲ'=>'Ἲ','Ἳ'=>'á¼»','ἸÌ'=>'á¼¼','á¼¹Ì'=>'á¼½','Ἶ'=>'á¼¾','Ἷ'=>'Ἷ','ὀ'=>'á½€','ὁ'=>'á½','ὂ'=>'ὂ','á½Ì€'=>'ὃ','á½€Ì'=>'ὄ','á½Ì'=>'á½…','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','ὈÌ'=>'Ὄ','ὉÌ'=>'á½','Ï…Ì“'=>'á½','Ï…Ì”'=>'ὑ','á½Ì€'=>'á½’','ὓ'=>'ὓ','á½Ì'=>'á½”','ὑÌ'=>'ὕ','á½Í‚'=>'á½–','ὗ'=>'á½—','Ὑ'=>'á½™','Ὓ'=>'á½›','á½™Ì'=>'á½','Ὗ'=>'Ὗ','ὠ'=>'á½ ','ὡ'=>'ὡ','ὢ'=>'á½¢','ὣ'=>'á½£','á½ Ì'=>'ὤ','ὡÌ'=>'á½¥','á½ Í‚'=>'ὦ','ὧ'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','ὨÌ'=>'Ὤ','ὩÌ'=>'á½­','Ὦ'=>'á½®','Ὧ'=>'Ὧ','ὰ'=>'á½°','ὲ'=>'á½²','ὴ'=>'á½´','ὶ'=>'ὶ','ὸ'=>'ὸ','Ï…Ì€'=>'ὺ','ὼ'=>'á½¼','ᾀ'=>'á¾€','á¼Í…'=>'á¾','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','á¼…Í…'=>'á¾…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','á¼Í…'=>'á¾','ᾎ'=>'ᾎ','á¼Í…'=>'á¾','á¼ Í…'=>'á¾','ᾑ'=>'ᾑ','ᾒ'=>'á¾’','ᾓ'=>'ᾓ','ᾔ'=>'á¾”','ᾕ'=>'ᾕ','ᾖ'=>'á¾–','ᾗ'=>'á¾—','ᾘ'=>'ᾘ','ᾙ'=>'á¾™','ᾚ'=>'ᾚ','ᾛ'=>'á¾›','ᾜ'=>'ᾜ','á¼­Í…'=>'á¾','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á½ Í…'=>'á¾ ','ᾡ'=>'ᾡ','ᾢ'=>'á¾¢','ᾣ'=>'á¾£','ᾤ'=>'ᾤ','ᾥ'=>'á¾¥','ᾦ'=>'ᾦ','ᾧ'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','á½­Í…'=>'á¾­','ᾮ'=>'á¾®','ᾯ'=>'ᾯ','ᾰ'=>'á¾°','ᾱ'=>'á¾±','á½°Í…'=>'á¾²','ᾳ'=>'á¾³','ᾴ'=>'á¾´','ᾶ'=>'ᾶ','ᾷ'=>'á¾·','Ᾰ'=>'Ᾰ','Ᾱ'=>'á¾¹','Ὰ'=>'Ὰ','ᾼ'=>'á¾¼','῁'=>'á¿','á½´Í…'=>'á¿‚','ῃ'=>'ῃ','ῄ'=>'á¿„','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Ὴ'=>'á¿Š','ῌ'=>'á¿Œ','῍'=>'á¿','᾿Ì'=>'á¿Ž','῏'=>'á¿','ῐ'=>'á¿','ῑ'=>'á¿‘','ÏŠÌ€'=>'á¿’','ῖ'=>'á¿–','ÏŠÍ‚'=>'á¿—','Ῐ'=>'Ῐ','Ῑ'=>'á¿™','Ὶ'=>'á¿š','῝'=>'á¿','῾Ì'=>'á¿ž','῟'=>'á¿Ÿ','ῠ'=>'á¿ ','Ï…Ì„'=>'á¿¡','Ï‹Ì€'=>'á¿¢','ÏÌ“'=>'ῤ','ÏÌ”'=>'á¿¥','Ï…Í‚'=>'ῦ','Ï‹Í‚'=>'ῧ','Ῠ'=>'Ῠ','Ῡ'=>'á¿©','Ὺ'=>'Ὺ','Ῥ'=>'Ῥ','῭'=>'á¿­','ῲ'=>'ῲ','ῳ'=>'ῳ','ÏŽÍ…'=>'á¿´','ῶ'=>'ῶ','ῷ'=>'á¿·','Ὸ'=>'Ὸ','Ὼ'=>'Ὼ','ῼ'=>'ῼ','â†Ì¸'=>'↚','↛'=>'↛','↮'=>'↮','â‡Ì¸'=>'â‡','⇎'=>'⇎','⇏'=>'â‡','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','≁'=>'â‰','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰Ì¸'=>'≭','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','⊁'=>'âŠ','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','⋠'=>'â‹ ','⋡'=>'â‹¡','⋢'=>'â‹¢','⋣'=>'â‹£','⋪'=>'⋪','⋫'=>'â‹«','⋬'=>'⋬','⋭'=>'â‹­','ã‹ã‚™'=>'ãŒ','ãã‚™'=>'ãŽ','ãã‚™'=>'ã','ã‘ã‚™'=>'ã’','ã“ã‚™'=>'ã”','ã•ã‚™'=>'ã–','ã—ã‚™'=>'ã˜','ã™ã‚™'=>'ãš','ã›ã‚™'=>'ãœ','ãã‚™'=>'ãž','ãŸã‚™'=>'ã ','ã¡ã‚™'=>'ã¢','ã¤ã‚™'=>'ã¥','ã¦ã‚™'=>'ã§','ã¨ã‚™'=>'ã©','ã¯ã‚™'=>'ã°','ã¯ã‚š'=>'ã±','ã²ã‚™'=>'ã³','ã²ã‚š'=>'ã´','ãµã‚™'=>'ã¶','ãµã‚š'=>'ã·','ã¸ã‚™'=>'ã¹','ã¸ã‚š'=>'ãº','ã»ã‚™'=>'ã¼','ã»ã‚š'=>'ã½','ã†ã‚™'=>'ã‚”','ã‚ã‚™'=>'ã‚ž','ã‚«ã‚™'=>'ガ','ã‚­ã‚™'=>'ã‚®','グ'=>'ã‚°','ゲ'=>'ゲ','ゴ'=>'ã‚´','ザ'=>'ザ','ã‚·ã‚™'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ã‚¿ã‚™'=>'ダ','ãƒã‚™'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒã‚™'=>'ãƒ','ãƒã‚š'=>'パ','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ポ'=>'ãƒ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ');
diff --git a/phpBB/includes/utf/data/utf_canonical_decomp.php b/phpBB/includes/utf/data/utf_canonical_decomp.php
deleted file mode 100644
index 9fb90803e2..0000000000
--- a/phpBB/includes/utf/data/utf_canonical_decomp.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$GLOBALS['utf_canonical_decomp']=array('À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ãœ'=>'Ü','Ã'=>'YÌ','à'=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','í'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä­'=>'ĭ','Ä®'=>'Į','į'=>'į','Ä°'=>'İ','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å­'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Å°'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','Æ°'=>'uÌ›','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç­'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','Ç°'=>'jÌŒ','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È­'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','È°'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ',';'=>';','Î…'=>'¨Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','έ'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï“'=>'Ï’Ì','Ï”'=>'ϔ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ӭ','Ó­'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','ো'=>'ো','ৌ'=>'ৌ','ড়'=>'ড়','à§'=>'ঢ়','য়'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','à©š'=>'ਗ਼','à©›'=>'ਜ਼','à©ž'=>'ਫ਼','à­ˆ'=>'ୈ','à­‹'=>'ୋ','à­Œ'=>'ୌ','à­œ'=>'ଡ଼','à­'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ླྀ'=>'ླྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á­€'=>'ᭀ','á­'=>'ᭁ','á­ƒ'=>'ᭃ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ­','ḓ'=>'dÌ­','Ḕ'=>'EÌ„Ì€','ḕ'=>'eÌ„Ì€','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ­','ḙ'=>'eÌ­','Ḛ'=>'EÌ°','ḛ'=>'eÌ°','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'IÌ°','ḭ'=>'iÌ°','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ­','ḽ'=>'lÌ­','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ­','ṋ'=>'nÌ­','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'OÌ„Ì€','ṑ'=>'oÌ„Ì€','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','ṧ'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹­'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ­','á¹±'=>'tÌ­','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'UÌ°','á¹µ'=>'uÌ°','Ṷ'=>'UÌ­','á¹·'=>'uÌ­','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẛ'=>'ẛ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'AÌ‚Ì€','ầ'=>'aÌ‚Ì€','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'EÌ‚Ì€','á»'=>'eÌ‚Ì€','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'OÌ‚Ì€','ồ'=>'oÌ‚Ì€','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','ủ'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»­'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','Ỷ'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','ἧ'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼­'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','ἶ'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'Ï…Ì“Ì€','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'Ï…Ì“Í‚','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','ὧ'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½­'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','ὶ'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','ᾧ'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾­'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','ᾶ'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾¾'=>'ι','á¿'=>'῁','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','á¿Š'=>'Ὴ','á¿‹'=>'ΗÌ','á¿Œ'=>'ῌ','á¿'=>'῍','á¿Ž'=>'᾿Ì','á¿'=>'῏','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','á¿š'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>'῝','á¿ž'=>'῾Ì','á¿Ÿ'=>'῟','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','ῧ'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿­'=>'῭','á¿®'=>'¨Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','ῶ'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>'´',' '=>' ','â€'=>' ','Ω'=>'Ω','K'=>'K','â„«'=>'AÌŠ','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','≭'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹­'=>'⋭','〈'=>'〈','〉'=>'〉','â«œ'=>'â«Ì¸','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ã‚ž'=>'ã‚ã‚™','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚­ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ザ'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'駱','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'蘭','鸞'=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','來'=>'來','冷'=>'冷','勞'=>'å‹ž','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'盧','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é­¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'綠','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'綾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','怒'=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'å¡ž','省'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'掠','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'糧','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–­','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ­·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'秊','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','裂'=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','玲'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'零','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','燎'=>'燎','ï§'=>'療','蓼'=>'蓼','遼'=>'é¼','龍'=>'é¾','暈'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','流'=>'æµ','溜'=>'溜','琉'=>'ç‰','ï§'=>'ç•™','硫'=>'ç¡«','ï§'=>'ç´','ï§'=>'é¡ž','六'=>'å…­','戮'=>'戮','陸'=>'陸','倫'=>'倫','崙'=>'å´™','淪'=>'æ·ª','輪'=>'輪','律'=>'律','慄'=>'æ…„','栗'=>'æ —','率'=>'率','隆'=>'隆','ï§'=>'利','吏'=>'å','履'=>'å±¥','易'=>'易','李'=>'æŽ','梨'=>'梨','泥'=>'æ³¥','理'=>'ç†','痢'=>'ç—¢','罹'=>'ç½¹','裏'=>'è£','裡'=>'裡','里'=>'里','離'=>'離','匿'=>'匿','溺'=>'溺','吝'=>'å','燐'=>'ç‡','璘'=>'ç’˜','藺'=>'è—º','隣'=>'隣','鱗'=>'é±—','麟'=>'麟','林'=>'æž—','淋'=>'æ·‹','臨'=>'臨','立'=>'ç«‹','笠'=>'笠','粒'=>'ç²’','狀'=>'ç‹€','炙'=>'ç‚™','識'=>'è­˜','什'=>'什','茶'=>'茶','刺'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'è¡Œ','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'å¡š','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','蘒'=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','鶴'=>'鶴','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','ï©Š'=>'ç¢','ï©‹'=>'碑','ï©Œ'=>'社','ï©'=>'祉','ï©Ž'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','ï©š'=>'ç½²','ï©›'=>'者','ï©œ'=>'臭','ï©'=>'艹','ï©ž'=>'艹','ï©Ÿ'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'辶','逸'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','勇'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'å¡š','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾­','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ­¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'瞧','爵'=>'爵','犯'=>'犯','猪'=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','節'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«­','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','ï«Š'=>'響','ï«‹'=>'é ‹','ï«Œ'=>'é »','ï«'=>'鬒','ï«Ž'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ï¬'=>'×™Ö´','ײַ'=>'ײַ','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','שּׂ'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï­€'=>'× Ö¼','ï­'=>'סּ','ï­ƒ'=>'×£Ö¼','ï­„'=>'פּ','ï­†'=>'צּ','ï­‡'=>'קּ','ï­ˆ'=>'רּ','ï­‰'=>'שּ','ï­Š'=>'תּ','ï­‹'=>'וֹ','ï­Œ'=>'בֿ','ï­'=>'×›Ö¿','ï­Ž'=>'פֿ','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'ã“Ÿ','刻'=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','卑'=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð ­£','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'哶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','寃'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','憤'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚­','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã­‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'𣑭','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','櫛'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ­”','㱎'=>'㱎','歲'=>'æ­²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'汧','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'涅','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'㶖','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚­','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','㺸'=>'㺸','瑇'=>'瑇','瑜'=>'ç‘œ','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'ç“Š','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'ç¡Ž','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'秫','䄯'=>'䄯','穀'=>'ç©€','穊'=>'ç©Š','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'䊠','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','䌁'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'莭','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','𦼬'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'虧','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'𧙧','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'𧢮','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'誠','ð¯§'=>'è«­','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð  „','跋'=>'è·‹','趼'=>'趼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'𨗭','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','𨯺'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'嶲','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'䩶','韠'=>'韠','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'駂','駾'=>'駾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³­','ð¯¨'=>'鵧','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀');
diff --git a/phpBB/includes/utf/data/utf_compatibility_decomp.php b/phpBB/includes/utf/data/utf_compatibility_decomp.php
deleted file mode 100644
index c62948e81a..0000000000
--- a/phpBB/includes/utf/data/utf_compatibility_decomp.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$GLOBALS['utf_compatibility_decomp']=array(' '=>' ','¨'=>' ̈','ª'=>'a','¯'=>' Ì„','²'=>'2','³'=>'3','´'=>' Ì','µ'=>'μ','¸'=>' ̧','¹'=>'1','º'=>'o','¼'=>'1â„4','½'=>'1â„2','¾'=>'3â„4','À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ãœ'=>'Ü','Ã'=>'YÌ','à'=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','í'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä­'=>'ĭ','Ä®'=>'Į','į'=>'į','Ä°'=>'İ','IJ'=>'IJ','ij'=>'ij','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ä¿'=>'L·','Å€'=>'l·','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ʼn'=>'ʼn','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å­'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Å°'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Å¿'=>'s','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','Æ°'=>'uÌ›','Ç„'=>'DZÌŒ','Ç…'=>'DzÌŒ','dž'=>'dzÌŒ','LJ'=>'LJ','Lj'=>'Lj','lj'=>'lj','ÇŠ'=>'NJ','Ç‹'=>'Nj','ÇŒ'=>'nj','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç­'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','Ç°'=>'jÌŒ','DZ'=>'DZ','Dz'=>'Dz','dz'=>'dz','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È­'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','È°'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','Ê°'=>'h','ʱ'=>'ɦ','ʲ'=>'j','ʳ'=>'r','Ê´'=>'ɹ','ʵ'=>'É»','ʶ'=>'Ê','Ê·'=>'w','ʸ'=>'y','˘'=>' ̆','Ë™'=>' ̇','Ëš'=>' ÌŠ','Ë›'=>' ̨','Ëœ'=>' ̃','Ë'=>' Ì‹','Ë '=>'É£','Ë¡'=>'l','Ë¢'=>'s','Ë£'=>'x','ˤ'=>'Ê•','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ','ͺ'=>' Í…',';'=>';','΄'=>' Ì','Î…'=>' ̈Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','έ'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï'=>'β','Ï‘'=>'θ','Ï’'=>'Î¥','Ï“'=>'Î¥Ì','Ï”'=>'Ϋ','Ï•'=>'φ','Ï–'=>'Ï€','Ï°'=>'κ','ϱ'=>'Ï','ϲ'=>'Ï‚','Ï´'=>'Θ','ϵ'=>'ε','Ϲ'=>'Σ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ӭ','Ó­'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ö‡'=>'Õ¥Ö‚','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Ùµ'=>'اٴ','Ù¶'=>'وٴ','Ù·'=>'Û‡Ù´','Ù¸'=>'يٴ','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','ো'=>'ো','ৌ'=>'ৌ','ড়'=>'ড়','à§'=>'ঢ়','য়'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','à©š'=>'ਗ਼','à©›'=>'ਜ਼','à©ž'=>'ਫ਼','à­ˆ'=>'ୈ','à­‹'=>'ୋ','à­Œ'=>'ୌ','à­œ'=>'ଡ଼','à­'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','ำ'=>'à¹à¸²','ຳ'=>'à»àº²','ໜ'=>'ຫນ','à»'=>'ຫມ','༌'=>'་','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ཷ'=>'ྲཱྀ','ླྀ'=>'ླྀ','ཹ'=>'ླཱྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ჼ'=>'ნ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á­€'=>'ᭀ','á­'=>'ᭁ','á­ƒ'=>'ᭃ','á´¬'=>'A','á´­'=>'Æ','á´®'=>'B','á´°'=>'D','á´±'=>'E','á´²'=>'ÆŽ','á´³'=>'G','á´´'=>'H','á´µ'=>'I','á´¶'=>'J','á´·'=>'K','á´¸'=>'L','á´¹'=>'M','á´º'=>'N','á´¼'=>'O','á´½'=>'È¢','á´¾'=>'P','á´¿'=>'R','áµ€'=>'T','áµ'=>'U','ᵂ'=>'W','ᵃ'=>'a','ᵄ'=>'É','áµ…'=>'É‘','ᵆ'=>'á´‚','ᵇ'=>'b','ᵈ'=>'d','ᵉ'=>'e','ᵊ'=>'É™','ᵋ'=>'É›','ᵌ'=>'Éœ','áµ'=>'g','áµ'=>'k','áµ'=>'m','ᵑ'=>'Å‹','áµ’'=>'o','ᵓ'=>'É”','áµ”'=>'á´–','ᵕ'=>'á´—','áµ–'=>'p','áµ—'=>'t','ᵘ'=>'u','áµ™'=>'á´','ᵚ'=>'ɯ','áµ›'=>'v','ᵜ'=>'á´¥','áµ'=>'β','ᵞ'=>'γ','ᵟ'=>'δ','áµ '=>'φ','ᵡ'=>'χ','áµ¢'=>'i','áµ£'=>'r','ᵤ'=>'u','áµ¥'=>'v','ᵦ'=>'β','ᵧ'=>'γ','ᵨ'=>'Ï','ᵩ'=>'φ','ᵪ'=>'χ','ᵸ'=>'н','ᶛ'=>'É’','ᶜ'=>'c','á¶'=>'É•','ᶞ'=>'ð','ᶟ'=>'Éœ','ᶠ'=>'f','ᶡ'=>'ÉŸ','ᶢ'=>'É¡','ᶣ'=>'É¥','ᶤ'=>'ɨ','ᶥ'=>'É©','ᶦ'=>'ɪ','ᶧ'=>'áµ»','ᶨ'=>'Ê','ᶩ'=>'É­','ᶪ'=>'ᶅ','ᶫ'=>'ÊŸ','ᶬ'=>'ɱ','ᶭ'=>'É°','ᶮ'=>'ɲ','ᶯ'=>'ɳ','ᶰ'=>'É´','ᶱ'=>'ɵ','ᶲ'=>'ɸ','ᶳ'=>'Ê‚','ᶴ'=>'ʃ','ᶵ'=>'Æ«','ᶶ'=>'ʉ','ᶷ'=>'ÊŠ','ᶸ'=>'á´œ','ᶹ'=>'Ê‹','ᶺ'=>'ÊŒ','ᶻ'=>'z','ᶼ'=>'Ê','ᶽ'=>'Ê‘','ᶾ'=>'Ê’','ᶿ'=>'θ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ­','ḓ'=>'dÌ­','Ḕ'=>'EÌ„Ì€','ḕ'=>'eÌ„Ì€','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ­','ḙ'=>'eÌ­','Ḛ'=>'EÌ°','ḛ'=>'eÌ°','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'IÌ°','ḭ'=>'iÌ°','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ­','ḽ'=>'lÌ­','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ­','ṋ'=>'nÌ­','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'OÌ„Ì€','ṑ'=>'oÌ„Ì€','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','ṧ'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹­'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ­','á¹±'=>'tÌ­','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'UÌ°','á¹µ'=>'uÌ°','Ṷ'=>'UÌ­','á¹·'=>'uÌ­','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẚ'=>'aʾ','ẛ'=>'ṡ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'AÌ‚Ì€','ầ'=>'aÌ‚Ì€','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'EÌ‚Ì€','á»'=>'eÌ‚Ì€','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'OÌ‚Ì€','ồ'=>'oÌ‚Ì€','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','ủ'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»­'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','Ỷ'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','ἧ'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼­'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','ἶ'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'Ï…Ì“Ì€','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'Ï…Ì“Í‚','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','ὧ'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½­'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','ὶ'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','ᾧ'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾­'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','ᾶ'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾½'=>' Ì“','á¾¾'=>'ι','᾿'=>' Ì“','á¿€'=>' Í‚','á¿'=>' ̈͂','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','á¿Š'=>'Ὴ','á¿‹'=>'ΗÌ','á¿Œ'=>'ῌ','á¿'=>' Ì“Ì€','á¿Ž'=>' Ì“Ì','á¿'=>' Ì“Í‚','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','á¿š'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>' ̔̀','á¿ž'=>' Ì”Ì','á¿Ÿ'=>' ̔͂','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','ῧ'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿­'=>' ̈̀','á¿®'=>' ̈Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','ῶ'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>' Ì','῾'=>' Ì”',' '=>' ','â€'=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','‑'=>'â€','‗'=>' ̳','․'=>'.','‥'=>'..','…'=>'...',' '=>' ','″'=>'′′','‴'=>'′′′','‶'=>'‵‵','‷'=>'‵‵‵','‼'=>'!!','‾'=>' Ì…','â‡'=>'??','âˆ'=>'?!','â‰'=>'!?','â—'=>'′′′′','âŸ'=>' ','â°'=>'0','â±'=>'i','â´'=>'4','âµ'=>'5','â¶'=>'6','â·'=>'7','â¸'=>'8','â¹'=>'9','âº'=>'+','â»'=>'−','â¼'=>'=','â½'=>'(','â¾'=>')','â¿'=>'n','â‚€'=>'0','â‚'=>'1','â‚‚'=>'2','₃'=>'3','â‚„'=>'4','â‚…'=>'5','₆'=>'6','₇'=>'7','₈'=>'8','₉'=>'9','â‚Š'=>'+','â‚‹'=>'−','â‚Œ'=>'=','â‚'=>'(','â‚Ž'=>')','â‚'=>'a','â‚‘'=>'e','â‚’'=>'o','â‚“'=>'x','â‚”'=>'É™','₨'=>'Rs','â„€'=>'a/c','â„'=>'a/s','â„‚'=>'C','℃'=>'°C','â„…'=>'c/o','℆'=>'c/u','ℇ'=>'Æ','℉'=>'°F','â„Š'=>'g','â„‹'=>'H','â„Œ'=>'H','â„'=>'H','â„Ž'=>'h','â„'=>'ħ','â„'=>'I','â„‘'=>'I','â„’'=>'L','â„“'=>'l','â„•'=>'N','â„–'=>'No','â„™'=>'P','â„š'=>'Q','â„›'=>'R','â„œ'=>'R','â„'=>'R','â„ '=>'SM','â„¡'=>'TEL','â„¢'=>'TM','ℤ'=>'Z','Ω'=>'Ω','ℨ'=>'Z','K'=>'K','â„«'=>'AÌŠ','ℬ'=>'B','â„­'=>'C','ℯ'=>'e','â„°'=>'E','ℱ'=>'F','ℳ'=>'M','â„´'=>'o','ℵ'=>'×','ℶ'=>'ב','â„·'=>'×’','ℸ'=>'ד','ℹ'=>'i','â„»'=>'FAX','ℼ'=>'Ï€','ℽ'=>'γ','ℾ'=>'Γ','â„¿'=>'Π','â…€'=>'∑','â……'=>'D','â…†'=>'d','â…‡'=>'e','â…ˆ'=>'i','â…‰'=>'j','â…“'=>'1â„3','â…”'=>'2â„3','â…•'=>'1â„5','â…–'=>'2â„5','â…—'=>'3â„5','â…˜'=>'4â„5','â…™'=>'1â„6','â…š'=>'5â„6','â…›'=>'1â„8','â…œ'=>'3â„8','â…'=>'5â„8','â…ž'=>'7â„8','â…Ÿ'=>'1â„','â… '=>'I','â…¡'=>'II','â…¢'=>'III','â…£'=>'IV','â…¤'=>'V','â…¥'=>'VI','â…¦'=>'VII','â…§'=>'VIII','â…¨'=>'IX','â…©'=>'X','â…ª'=>'XI','â…«'=>'XII','â…¬'=>'L','â…­'=>'C','â…®'=>'D','â…¯'=>'M','â…°'=>'i','â…±'=>'ii','â…²'=>'iii','â…³'=>'iv','â…´'=>'v','â…µ'=>'vi','â…¶'=>'vii','â…·'=>'viii','â…¸'=>'ix','â…¹'=>'x','â…º'=>'xi','â…»'=>'xii','â…¼'=>'l','â…½'=>'c','â…¾'=>'d','â…¿'=>'m','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','∬'=>'∫∫','∭'=>'∫∫∫','∯'=>'∮∮','∰'=>'∮∮∮','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','≭'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹­'=>'⋭','〈'=>'〈','〉'=>'〉','â‘ '=>'1','â‘¡'=>'2','â‘¢'=>'3','â‘£'=>'4','⑤'=>'5','â‘¥'=>'6','⑦'=>'7','⑧'=>'8','⑨'=>'9','â‘©'=>'10','⑪'=>'11','â‘«'=>'12','⑬'=>'13','â‘­'=>'14','â‘®'=>'15','⑯'=>'16','â‘°'=>'17','⑱'=>'18','⑲'=>'19','⑳'=>'20','â‘´'=>'(1)','⑵'=>'(2)','⑶'=>'(3)','â‘·'=>'(4)','⑸'=>'(5)','⑹'=>'(6)','⑺'=>'(7)','â‘»'=>'(8)','⑼'=>'(9)','⑽'=>'(10)','⑾'=>'(11)','â‘¿'=>'(12)','â’€'=>'(13)','â’'=>'(14)','â’‚'=>'(15)','â’ƒ'=>'(16)','â’„'=>'(17)','â’…'=>'(18)','â’†'=>'(19)','â’‡'=>'(20)','â’ˆ'=>'1.','â’‰'=>'2.','â’Š'=>'3.','â’‹'=>'4.','â’Œ'=>'5.','â’'=>'6.','â’Ž'=>'7.','â’'=>'8.','â’'=>'9.','â’‘'=>'10.','â’’'=>'11.','â’“'=>'12.','â’”'=>'13.','â’•'=>'14.','â’–'=>'15.','â’—'=>'16.','â’˜'=>'17.','â’™'=>'18.','â’š'=>'19.','â’›'=>'20.','â’œ'=>'(a)','â’'=>'(b)','â’ž'=>'(c)','â’Ÿ'=>'(d)','â’ '=>'(e)','â’¡'=>'(f)','â’¢'=>'(g)','â’£'=>'(h)','â’¤'=>'(i)','â’¥'=>'(j)','â’¦'=>'(k)','â’§'=>'(l)','â’¨'=>'(m)','â’©'=>'(n)','â’ª'=>'(o)','â’«'=>'(p)','â’¬'=>'(q)','â’­'=>'(r)','â’®'=>'(s)','â’¯'=>'(t)','â’°'=>'(u)','â’±'=>'(v)','â’²'=>'(w)','â’³'=>'(x)','â’´'=>'(y)','â’µ'=>'(z)','â’¶'=>'A','â’·'=>'B','â’¸'=>'C','â’¹'=>'D','â’º'=>'E','â’»'=>'F','â’¼'=>'G','â’½'=>'H','â’¾'=>'I','â’¿'=>'J','â“€'=>'K','â“'=>'L','â“‚'=>'M','Ⓝ'=>'N','â“„'=>'O','â“…'=>'P','Ⓠ'=>'Q','Ⓡ'=>'R','Ⓢ'=>'S','Ⓣ'=>'T','â“Š'=>'U','â“‹'=>'V','â“Œ'=>'W','â“'=>'X','â“Ž'=>'Y','â“'=>'Z','â“'=>'a','â“‘'=>'b','â“’'=>'c','â““'=>'d','â“”'=>'e','â“•'=>'f','â“–'=>'g','â“—'=>'h','ⓘ'=>'i','â“™'=>'j','â“š'=>'k','â“›'=>'l','â“œ'=>'m','â“'=>'n','â“ž'=>'o','â“Ÿ'=>'p','â“ '=>'q','â“¡'=>'r','â“¢'=>'s','â“£'=>'t','ⓤ'=>'u','â“¥'=>'v','ⓦ'=>'w','ⓧ'=>'x','ⓨ'=>'y','â“©'=>'z','⓪'=>'0','⨌'=>'∫∫∫∫','â©´'=>'::=','⩵'=>'==','⩶'=>'===','â«œ'=>'â«Ì¸','ⵯ'=>'ⵡ','⺟'=>'æ¯','⻳'=>'龟','â¼€'=>'一','â¼'=>'丨','⼂'=>'丶','⼃'=>'丿','⼄'=>'ä¹™','â¼…'=>'亅','⼆'=>'二','⼇'=>'亠','⼈'=>'人','⼉'=>'å„¿','⼊'=>'å…¥','⼋'=>'å…«','⼌'=>'冂','â¼'=>'冖','⼎'=>'冫','â¼'=>'几','â¼'=>'凵','⼑'=>'刀','â¼’'=>'力','⼓'=>'勹','â¼”'=>'匕','⼕'=>'匚','â¼–'=>'匸','â¼—'=>'å','⼘'=>'åœ','â¼™'=>'å©','⼚'=>'厂','â¼›'=>'厶','⼜'=>'åˆ','â¼'=>'å£','⼞'=>'å›—','⼟'=>'土','â¼ '=>'士','⼡'=>'夂','â¼¢'=>'夊','â¼£'=>'夕','⼤'=>'大','â¼¥'=>'女','⼦'=>'å­','⼧'=>'宀','⼨'=>'寸','⼩'=>'å°','⼪'=>'å°¢','⼫'=>'å°¸','⼬'=>'å±®','â¼­'=>'å±±','â¼®'=>'å·›','⼯'=>'å·¥','â¼°'=>'å·±','â¼±'=>'å·¾','â¼²'=>'å¹²','â¼³'=>'幺','â¼´'=>'广','â¼µ'=>'å»´','⼶'=>'廾','â¼·'=>'弋','⼸'=>'弓','â¼¹'=>'å½','⼺'=>'彡','â¼»'=>'å½³','â¼¼'=>'心','â¼½'=>'戈','â¼¾'=>'戶','⼿'=>'手','â½€'=>'支','â½'=>'æ”´','⽂'=>'æ–‡','⽃'=>'æ–—','⽄'=>'æ–¤','â½…'=>'æ–¹','⽆'=>'æ— ','⽇'=>'æ—¥','⽈'=>'æ›°','⽉'=>'月','⽊'=>'木','⽋'=>'欠','⽌'=>'æ­¢','â½'=>'æ­¹','⽎'=>'殳','â½'=>'毋','â½'=>'比','⽑'=>'毛','â½’'=>'æ°','⽓'=>'æ°”','â½”'=>'æ°´','⽕'=>'ç«','â½–'=>'爪','â½—'=>'父','⽘'=>'爻','â½™'=>'爿','⽚'=>'片','â½›'=>'牙','⽜'=>'牛','â½'=>'犬','⽞'=>'玄','⽟'=>'玉','â½ '=>'ç“œ','⽡'=>'瓦','â½¢'=>'甘','â½£'=>'生','⽤'=>'用','â½¥'=>'ç”°','⽦'=>'ç–‹','⽧'=>'ç–’','⽨'=>'癶','⽩'=>'白','⽪'=>'çš®','⽫'=>'çš¿','⽬'=>'ç›®','â½­'=>'矛','â½®'=>'矢','⽯'=>'石','â½°'=>'示','â½±'=>'禸','â½²'=>'禾','â½³'=>'ç©´','â½´'=>'ç«‹','â½µ'=>'竹','⽶'=>'ç±³','â½·'=>'糸','⽸'=>'缶','â½¹'=>'网','⽺'=>'羊','â½»'=>'ç¾½','â½¼'=>'è€','â½½'=>'而','â½¾'=>'耒','⽿'=>'耳','â¾€'=>'è¿','â¾'=>'肉','⾂'=>'臣','⾃'=>'自','⾄'=>'至','â¾…'=>'臼','⾆'=>'舌','⾇'=>'舛','⾈'=>'舟','⾉'=>'艮','⾊'=>'色','⾋'=>'艸','⾌'=>'è™','â¾'=>'虫','⾎'=>'è¡€','â¾'=>'è¡Œ','â¾'=>'è¡£','⾑'=>'襾','â¾’'=>'見','⾓'=>'角','â¾”'=>'言','⾕'=>'è°·','â¾–'=>'豆','â¾—'=>'豕','⾘'=>'豸','â¾™'=>'è²','⾚'=>'赤','â¾›'=>'èµ°','⾜'=>'足','â¾'=>'身','⾞'=>'車','⾟'=>'è¾›','â¾ '=>'è¾°','⾡'=>'è¾µ','â¾¢'=>'é‚‘','â¾£'=>'é…‰','⾤'=>'釆','â¾¥'=>'里','⾦'=>'金','⾧'=>'é•·','⾨'=>'é–€','⾩'=>'阜','⾪'=>'隶','⾫'=>'éš¹','⾬'=>'雨','â¾­'=>'é‘','â¾®'=>'éž','⾯'=>'é¢','â¾°'=>'é©','â¾±'=>'韋','â¾²'=>'韭','â¾³'=>'音','â¾´'=>'é ','â¾µ'=>'風','⾶'=>'飛','â¾·'=>'食','⾸'=>'首','â¾¹'=>'香','⾺'=>'馬','â¾»'=>'骨','â¾¼'=>'高','â¾½'=>'é«Ÿ','â¾¾'=>'鬥','⾿'=>'鬯','â¿€'=>'鬲','â¿'=>'鬼','â¿‚'=>'é­š','⿃'=>'é³¥','â¿„'=>'é¹µ','â¿…'=>'鹿','⿆'=>'麥','⿇'=>'麻','⿈'=>'黃','⿉'=>'é»','â¿Š'=>'黑','â¿‹'=>'黹','â¿Œ'=>'黽','â¿'=>'鼎','â¿Ž'=>'鼓','â¿'=>'é¼ ','â¿'=>'é¼»','â¿‘'=>'齊','â¿’'=>'é½’','â¿“'=>'é¾','â¿”'=>'龜','â¿•'=>'é¾ ',' '=>' ','〶'=>'〒','〸'=>'å','〹'=>'å„','〺'=>'å…','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ã‚›'=>' ã‚™','ã‚œ'=>' ã‚š','ã‚ž'=>'ã‚ã‚™','ã‚Ÿ'=>'より','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚­ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ザ'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','ヿ'=>'コト','ㄱ'=>'á„€','ㄲ'=>'á„','ㄳ'=>'ᆪ','ã„´'=>'á„‚','ㄵ'=>'ᆬ','ㄶ'=>'ᆭ','ã„·'=>'ᄃ','ㄸ'=>'á„„','ㄹ'=>'á„…','ㄺ'=>'ᆰ','ã„»'=>'ᆱ','ㄼ'=>'ᆲ','ㄽ'=>'ᆳ','ㄾ'=>'ᆴ','ã„¿'=>'ᆵ','ã…€'=>'á„š','ã…'=>'ᄆ','ã…‚'=>'ᄇ','ã…ƒ'=>'ᄈ','ã…„'=>'á„¡','ã……'=>'ᄉ','ã…†'=>'á„Š','ã…‡'=>'á„‹','ã…ˆ'=>'á„Œ','ã…‰'=>'á„','ã…Š'=>'á„Ž','ã…‹'=>'á„','ã…Œ'=>'á„','ã…'=>'á„‘','ã…Ž'=>'á„’','ã…'=>'á…¡','ã…'=>'á…¢','ã…‘'=>'á…£','ã…’'=>'á…¤','ã…“'=>'á…¥','ã…”'=>'á…¦','ã…•'=>'á…§','ã…–'=>'á…¨','ã…—'=>'á…©','ã…˜'=>'á…ª','ã…™'=>'á…«','ã…š'=>'á…¬','ã…›'=>'á…­','ã…œ'=>'á…®','ã…'=>'á…¯','ã…ž'=>'á…°','ã…Ÿ'=>'á…±','ã… '=>'á…²','ã…¡'=>'á…³','ã…¢'=>'á…´','ã…£'=>'á…µ','ã…¤'=>'á… ','ã…¥'=>'á„”','ã…¦'=>'á„•','ã…§'=>'ᇇ','ã…¨'=>'ᇈ','ã…©'=>'ᇌ','ã…ª'=>'ᇎ','ã…«'=>'ᇓ','ã…¬'=>'ᇗ','ã…­'=>'ᇙ','ã…®'=>'á„œ','ã…¯'=>'á‡','ã…°'=>'ᇟ','ã…±'=>'á„','ã…²'=>'á„ž','ã…³'=>'á„ ','ã…´'=>'á„¢','ã…µ'=>'á„£','ã…¶'=>'ᄧ','ã…·'=>'á„©','ã…¸'=>'á„«','ã…¹'=>'ᄬ','ã…º'=>'á„­','ã…»'=>'á„®','ã…¼'=>'ᄯ','ã…½'=>'ᄲ','ã…¾'=>'ᄶ','ã…¿'=>'á…€','ㆀ'=>'á…‡','ã†'=>'á…Œ','ㆂ'=>'ᇱ','ㆃ'=>'ᇲ','ㆄ'=>'á…—','ㆅ'=>'á…˜','ㆆ'=>'á…™','ㆇ'=>'ᆄ','ㆈ'=>'ᆅ','ㆉ'=>'ᆈ','ㆊ'=>'ᆑ','ㆋ'=>'ᆒ','ㆌ'=>'ᆔ','ã†'=>'ᆞ','ㆎ'=>'ᆡ','㆒'=>'一','㆓'=>'二','㆔'=>'三','㆕'=>'å››','㆖'=>'上','㆗'=>'中','㆘'=>'下','㆙'=>'甲','㆚'=>'ä¹™','㆛'=>'丙','㆜'=>'ä¸','ã†'=>'天','㆞'=>'地','㆟'=>'人','㈀'=>'(á„€)','ãˆ'=>'(á„‚)','㈂'=>'(ᄃ)','㈃'=>'(á„…)','㈄'=>'(ᄆ)','㈅'=>'(ᄇ)','㈆'=>'(ᄉ)','㈇'=>'(á„‹)','㈈'=>'(á„Œ)','㈉'=>'(á„Ž)','㈊'=>'(á„)','㈋'=>'(á„)','㈌'=>'(á„‘)','ãˆ'=>'(á„’)','㈎'=>'(가)','ãˆ'=>'(á„‚á…¡)','ãˆ'=>'(다)','㈑'=>'(á„…á…¡)','㈒'=>'(마)','㈓'=>'(바)','㈔'=>'(사)','㈕'=>'(á„‹á…¡)','㈖'=>'(자)','㈗'=>'(á„Žá…¡)','㈘'=>'(á„á…¡)','㈙'=>'(á„á…¡)','㈚'=>'(á„‘á…¡)','㈛'=>'(á„’á…¡)','㈜'=>'(주)','ãˆ'=>'(오전)','㈞'=>'(á„‹á…©á„’á…®)','㈠'=>'(一)','㈡'=>'(二)','㈢'=>'(三)','㈣'=>'(å››)','㈤'=>'(五)','㈥'=>'(å…­)','㈦'=>'(七)','㈧'=>'(å…«)','㈨'=>'(ä¹)','㈩'=>'(å)','㈪'=>'(月)','㈫'=>'(ç«)','㈬'=>'(æ°´)','㈭'=>'(木)','㈮'=>'(金)','㈯'=>'(土)','㈰'=>'(æ—¥)','㈱'=>'(æ ª)','㈲'=>'(有)','㈳'=>'(社)','㈴'=>'(å)','㈵'=>'(特)','㈶'=>'(財)','㈷'=>'(ç¥)','㈸'=>'(労)','㈹'=>'(代)','㈺'=>'(呼)','㈻'=>'(å­¦)','㈼'=>'(監)','㈽'=>'(ä¼)','㈾'=>'(資)','㈿'=>'(å”)','㉀'=>'(祭)','ã‰'=>'(休)','㉂'=>'(自)','㉃'=>'(至)','ã‰'=>'PTE','㉑'=>'21','㉒'=>'22','㉓'=>'23','㉔'=>'24','㉕'=>'25','㉖'=>'26','㉗'=>'27','㉘'=>'28','㉙'=>'29','㉚'=>'30','㉛'=>'31','㉜'=>'32','ã‰'=>'33','㉞'=>'34','㉟'=>'35','㉠'=>'á„€','㉡'=>'á„‚','㉢'=>'ᄃ','㉣'=>'á„…','㉤'=>'ᄆ','㉥'=>'ᄇ','㉦'=>'ᄉ','㉧'=>'á„‹','㉨'=>'á„Œ','㉩'=>'á„Ž','㉪'=>'á„','㉫'=>'á„','㉬'=>'á„‘','㉭'=>'á„’','㉮'=>'가','㉯'=>'á„‚á…¡','㉰'=>'다','㉱'=>'á„…á…¡','㉲'=>'마','㉳'=>'바','㉴'=>'사','㉵'=>'á„‹á…¡','㉶'=>'자','㉷'=>'á„Žá…¡','㉸'=>'á„á…¡','㉹'=>'á„á…¡','㉺'=>'á„‘á…¡','㉻'=>'á„’á…¡','㉼'=>'참고','㉽'=>'주의','㉾'=>'á„‹á…®','㊀'=>'一','ãŠ'=>'二','㊂'=>'三','㊃'=>'å››','㊄'=>'五','㊅'=>'å…­','㊆'=>'七','㊇'=>'å…«','㊈'=>'ä¹','㊉'=>'å','㊊'=>'月','㊋'=>'ç«','㊌'=>'æ°´','ãŠ'=>'木','㊎'=>'金','ãŠ'=>'土','ãŠ'=>'æ—¥','㊑'=>'æ ª','㊒'=>'有','㊓'=>'社','㊔'=>'å','㊕'=>'特','㊖'=>'財','㊗'=>'ç¥','㊘'=>'労','㊙'=>'秘','㊚'=>'ç”·','㊛'=>'女','㊜'=>'é©','ãŠ'=>'優','㊞'=>'å°','㊟'=>'注','㊠'=>'é …','㊡'=>'休','㊢'=>'写','㊣'=>'æ­£','㊤'=>'上','㊥'=>'中','㊦'=>'下','㊧'=>'å·¦','㊨'=>'å³','㊩'=>'医','㊪'=>'å®—','㊫'=>'å­¦','㊬'=>'監','㊭'=>'ä¼','㊮'=>'資','㊯'=>'å”','㊰'=>'夜','㊱'=>'36','㊲'=>'37','㊳'=>'38','㊴'=>'39','㊵'=>'40','㊶'=>'41','㊷'=>'42','㊸'=>'43','㊹'=>'44','㊺'=>'45','㊻'=>'46','㊼'=>'47','㊽'=>'48','㊾'=>'49','㊿'=>'50','ã‹€'=>'1月','ã‹'=>'2月','ã‹‚'=>'3月','㋃'=>'4月','ã‹„'=>'5月','ã‹…'=>'6月','㋆'=>'7月','㋇'=>'8月','㋈'=>'9月','㋉'=>'10月','ã‹Š'=>'11月','ã‹‹'=>'12月','ã‹Œ'=>'Hg','ã‹'=>'erg','ã‹Ž'=>'eV','ã‹'=>'LTD','ã‹'=>'ã‚¢','ã‹‘'=>'イ','ã‹’'=>'ウ','ã‹“'=>'エ','ã‹”'=>'オ','ã‹•'=>'ã‚«','ã‹–'=>'ã‚­','ã‹—'=>'ク','㋘'=>'ケ','ã‹™'=>'コ','ã‹š'=>'サ','ã‹›'=>'ã‚·','ã‹œ'=>'ス','ã‹'=>'ã‚»','ã‹ž'=>'ソ','ã‹Ÿ'=>'ã‚¿','ã‹ '=>'ãƒ','ã‹¡'=>'ツ','ã‹¢'=>'テ','ã‹£'=>'ト','㋤'=>'ナ','ã‹¥'=>'ニ','㋦'=>'ヌ','㋧'=>'ãƒ','㋨'=>'ノ','ã‹©'=>'ãƒ','㋪'=>'ヒ','ã‹«'=>'フ','㋬'=>'ヘ','ã‹­'=>'ホ','ã‹®'=>'マ','㋯'=>'ミ','ã‹°'=>'ム','㋱'=>'メ','㋲'=>'モ','㋳'=>'ヤ','ã‹´'=>'ユ','㋵'=>'ヨ','㋶'=>'ラ','ã‹·'=>'リ','㋸'=>'ル','㋹'=>'レ','㋺'=>'ロ','ã‹»'=>'ワ','㋼'=>'ヰ','㋽'=>'ヱ','㋾'=>'ヲ','㌀'=>'ã‚¢ãƒã‚šãƒ¼ãƒˆ','ãŒ'=>'アルファ','㌂'=>'アンペア','㌃'=>'アール','㌄'=>'イニング','㌅'=>'インãƒ','㌆'=>'ウォン','㌇'=>'エスクード','㌈'=>'エーカー','㌉'=>'オンス','㌊'=>'オーム','㌋'=>'カイリ','㌌'=>'カラット','ãŒ'=>'カロリー','㌎'=>'ガロン','ãŒ'=>'ガンマ','ãŒ'=>'ギガ','㌑'=>'ギニー','㌒'=>'キュリー','㌓'=>'ギルダー','㌔'=>'キロ','㌕'=>'キログラム','㌖'=>'キロメートル','㌗'=>'キロワット','㌘'=>'グラム','㌙'=>'グラムトン','㌚'=>'クルゼイロ','㌛'=>'クローãƒ','㌜'=>'ケース','ãŒ'=>'コルナ','㌞'=>'コーポ','㌟'=>'サイクル','㌠'=>'サンãƒãƒ¼ãƒ ','㌡'=>'シリング','㌢'=>'センãƒ','㌣'=>'セント','㌤'=>'ダース','㌥'=>'デシ','㌦'=>'ドル','㌧'=>'トン','㌨'=>'ナノ','㌩'=>'ノット','㌪'=>'ãƒã‚¤ãƒ„','㌫'=>'ãƒã‚šãƒ¼ã‚»ãƒ³ãƒˆ','㌬'=>'ãƒã‚šãƒ¼ãƒ„','㌭'=>'ãƒã‚™ãƒ¼ãƒ¬ãƒ«','㌮'=>'ピアストル','㌯'=>'ピクル','㌰'=>'ピコ','㌱'=>'ビル','㌲'=>'ファラッド','㌳'=>'フィート','㌴'=>'ブッシェル','㌵'=>'フラン','㌶'=>'ヘクタール','㌷'=>'ペソ','㌸'=>'ペニヒ','㌹'=>'ヘルツ','㌺'=>'ペンス','㌻'=>'ページ','㌼'=>'ベータ','㌽'=>'ポイント','㌾'=>'ボルト','㌿'=>'ホン','ã€'=>'ポンド','ã'=>'ホール','ã‚'=>'ホーン','ãƒ'=>'マイクロ','ã„'=>'マイル','ã…'=>'マッãƒ','ã†'=>'マルク','ã‡'=>'マンション','ãˆ'=>'ミクロン','ã‰'=>'ミリ','ãŠ'=>'ミリãƒã‚™ãƒ¼ãƒ«','ã‹'=>'メガ','ãŒ'=>'メガトン','ã'=>'メートル','ãŽ'=>'ヤード','ã'=>'ヤール','ã'=>'ユアン','ã‘'=>'リットル','ã’'=>'リラ','ã“'=>'ルピー','ã”'=>'ルーブル','ã•'=>'レム','ã–'=>'レントゲン','ã—'=>'ワット','ã˜'=>'0点','ã™'=>'1点','ãš'=>'2点','ã›'=>'3点','ãœ'=>'4点','ã'=>'5点','ãž'=>'6点','ãŸ'=>'7点','ã '=>'8点','ã¡'=>'9点','ã¢'=>'10点','ã£'=>'11点','ã¤'=>'12点','ã¥'=>'13点','ã¦'=>'14点','ã§'=>'15点','ã¨'=>'16点','ã©'=>'17点','ãª'=>'18点','ã«'=>'19点','ã¬'=>'20点','ã­'=>'21点','ã®'=>'22点','ã¯'=>'23点','ã°'=>'24点','ã±'=>'hPa','ã²'=>'da','ã³'=>'AU','ã´'=>'bar','ãµ'=>'oV','ã¶'=>'pc','ã·'=>'dm','ã¸'=>'dm2','ã¹'=>'dm3','ãº'=>'IU','ã»'=>'å¹³æˆ','ã¼'=>'昭和','ã½'=>'大正','ã¾'=>'明治','ã¿'=>'æ ªå¼ä¼šç¤¾','㎀'=>'pA','ãŽ'=>'nA','㎂'=>'μA','㎃'=>'mA','㎄'=>'kA','㎅'=>'KB','㎆'=>'MB','㎇'=>'GB','㎈'=>'cal','㎉'=>'kcal','㎊'=>'pF','㎋'=>'nF','㎌'=>'μF','ãŽ'=>'μg','㎎'=>'mg','ãŽ'=>'kg','ãŽ'=>'Hz','㎑'=>'kHz','㎒'=>'MHz','㎓'=>'GHz','㎔'=>'THz','㎕'=>'μl','㎖'=>'ml','㎗'=>'dl','㎘'=>'kl','㎙'=>'fm','㎚'=>'nm','㎛'=>'μm','㎜'=>'mm','ãŽ'=>'cm','㎞'=>'km','㎟'=>'mm2','㎠'=>'cm2','㎡'=>'m2','㎢'=>'km2','㎣'=>'mm3','㎤'=>'cm3','㎥'=>'m3','㎦'=>'km3','㎧'=>'m∕s','㎨'=>'m∕s2','㎩'=>'Pa','㎪'=>'kPa','㎫'=>'MPa','㎬'=>'GPa','㎭'=>'rad','㎮'=>'rad∕s','㎯'=>'rad∕s2','㎰'=>'ps','㎱'=>'ns','㎲'=>'μs','㎳'=>'ms','㎴'=>'pV','㎵'=>'nV','㎶'=>'μV','㎷'=>'mV','㎸'=>'kV','㎹'=>'MV','㎺'=>'pW','㎻'=>'nW','㎼'=>'μW','㎽'=>'mW','㎾'=>'kW','㎿'=>'MW','ã€'=>'kΩ','ã'=>'MΩ','ã‚'=>'a.m.','ãƒ'=>'Bq','ã„'=>'cc','ã…'=>'cd','ã†'=>'C∕kg','ã‡'=>'Co.','ãˆ'=>'dB','ã‰'=>'Gy','ãŠ'=>'ha','ã‹'=>'HP','ãŒ'=>'in','ã'=>'KK','ãŽ'=>'KM','ã'=>'kt','ã'=>'lm','ã‘'=>'ln','ã’'=>'log','ã“'=>'lx','ã”'=>'mb','ã•'=>'mil','ã–'=>'mol','ã—'=>'PH','ã˜'=>'p.m.','ã™'=>'PPM','ãš'=>'PR','ã›'=>'sr','ãœ'=>'Sv','ã'=>'Wb','ãž'=>'V∕m','ãŸ'=>'A∕m','ã '=>'1æ—¥','ã¡'=>'2æ—¥','ã¢'=>'3æ—¥','ã£'=>'4æ—¥','ã¤'=>'5æ—¥','ã¥'=>'6æ—¥','ã¦'=>'7æ—¥','ã§'=>'8æ—¥','ã¨'=>'9æ—¥','ã©'=>'10æ—¥','ãª'=>'11æ—¥','ã«'=>'12æ—¥','ã¬'=>'13æ—¥','ã­'=>'14æ—¥','ã®'=>'15æ—¥','ã¯'=>'16æ—¥','ã°'=>'17æ—¥','ã±'=>'18æ—¥','ã²'=>'19æ—¥','ã³'=>'20æ—¥','ã´'=>'21æ—¥','ãµ'=>'22æ—¥','ã¶'=>'23æ—¥','ã·'=>'24æ—¥','ã¸'=>'25æ—¥','ã¹'=>'26æ—¥','ãº'=>'27æ—¥','ã»'=>'28æ—¥','ã¼'=>'29æ—¥','ã½'=>'30æ—¥','ã¾'=>'31æ—¥','ã¿'=>'gal','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'駱','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'蘭','鸞'=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','來'=>'來','冷'=>'冷','勞'=>'å‹ž','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'盧','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é­¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'綠','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'綾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','怒'=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'å¡ž','省'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'掠','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'糧','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–­','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ­·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'秊','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','裂'=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','玲'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'零','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','燎'=>'燎','ï§'=>'療','蓼'=>'蓼','遼'=>'é¼','龍'=>'é¾','暈'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','流'=>'æµ','溜'=>'溜','琉'=>'ç‰','ï§'=>'ç•™','硫'=>'ç¡«','ï§'=>'ç´','ï§'=>'é¡ž','六'=>'å…­','戮'=>'戮','陸'=>'陸','倫'=>'倫','崙'=>'å´™','淪'=>'æ·ª','輪'=>'輪','律'=>'律','慄'=>'æ…„','栗'=>'æ —','率'=>'率','隆'=>'隆','ï§'=>'利','吏'=>'å','履'=>'å±¥','易'=>'易','李'=>'æŽ','梨'=>'梨','泥'=>'æ³¥','理'=>'ç†','痢'=>'ç—¢','罹'=>'ç½¹','裏'=>'è£','裡'=>'裡','里'=>'里','離'=>'離','匿'=>'匿','溺'=>'溺','吝'=>'å','燐'=>'ç‡','璘'=>'ç’˜','藺'=>'è—º','隣'=>'隣','鱗'=>'é±—','麟'=>'麟','林'=>'æž—','淋'=>'æ·‹','臨'=>'臨','立'=>'ç«‹','笠'=>'笠','粒'=>'ç²’','狀'=>'ç‹€','炙'=>'ç‚™','識'=>'è­˜','什'=>'什','茶'=>'茶','刺'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'è¡Œ','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'å¡š','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','蘒'=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','鶴'=>'鶴','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','ï©Š'=>'ç¢','ï©‹'=>'碑','ï©Œ'=>'社','ï©'=>'祉','ï©Ž'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','ï©š'=>'ç½²','ï©›'=>'者','ï©œ'=>'臭','ï©'=>'艹','ï©ž'=>'艹','ï©Ÿ'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'辶','逸'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','勇'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'å¡š','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾­','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ­¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'瞧','爵'=>'爵','犯'=>'犯','猪'=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','節'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«­','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','ï«Š'=>'響','ï«‹'=>'é ‹','ï«Œ'=>'é »','ï«'=>'鬒','ï«Ž'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ff'=>'ff','ï¬'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'Õ´Õ¶','ﬔ'=>'Õ´Õ¥','ﬕ'=>'Õ´Õ«','ﬖ'=>'Õ¾Õ¶','ﬗ'=>'Õ´Õ­','ï¬'=>'×™Ö´','ײַ'=>'ײַ','ﬠ'=>'×¢','ﬡ'=>'×','ﬢ'=>'ד','ﬣ'=>'×”','ﬤ'=>'×›','ﬥ'=>'ל','ﬦ'=>'×','ﬧ'=>'ר','ﬨ'=>'ת','﬩'=>'+','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','שּׂ'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï­€'=>'× Ö¼','ï­'=>'סּ','ï­ƒ'=>'×£Ö¼','ï­„'=>'פּ','ï­†'=>'צּ','ï­‡'=>'קּ','ï­ˆ'=>'רּ','ï­‰'=>'שּ','ï­Š'=>'תּ','ï­‹'=>'וֹ','ï­Œ'=>'בֿ','ï­'=>'×›Ö¿','ï­Ž'=>'פֿ','ï­'=>'×ל','ï­'=>'Ù±','ï­‘'=>'Ù±','ï­’'=>'Ù»','ï­“'=>'Ù»','ï­”'=>'Ù»','ï­•'=>'Ù»','ï­–'=>'Ù¾','ï­—'=>'Ù¾','ï­˜'=>'Ù¾','ï­™'=>'Ù¾','ï­š'=>'Ú€','ï­›'=>'Ú€','ï­œ'=>'Ú€','ï­'=>'Ú€','ï­ž'=>'Ùº','ï­Ÿ'=>'Ùº','ï­ '=>'Ùº','ï­¡'=>'Ùº','ï­¢'=>'Ù¿','ï­£'=>'Ù¿','ï­¤'=>'Ù¿','ï­¥'=>'Ù¿','ï­¦'=>'Ù¹','ï­§'=>'Ù¹','ï­¨'=>'Ù¹','ï­©'=>'Ù¹','ï­ª'=>'Ú¤','ï­«'=>'Ú¤','ï­¬'=>'Ú¤','ï­­'=>'Ú¤','ï­®'=>'Ú¦','ï­¯'=>'Ú¦','ï­°'=>'Ú¦','ï­±'=>'Ú¦','ï­²'=>'Ú„','ï­³'=>'Ú„','ï­´'=>'Ú„','ï­µ'=>'Ú„','ï­¶'=>'Úƒ','ï­·'=>'Úƒ','ï­¸'=>'Úƒ','ï­¹'=>'Úƒ','ï­º'=>'Ú†','ï­»'=>'Ú†','ï­¼'=>'Ú†','ï­½'=>'Ú†','ï­¾'=>'Ú‡','ï­¿'=>'Ú‡','ﮀ'=>'Ú‡','ï®'=>'Ú‡','ﮂ'=>'Ú','ﮃ'=>'Ú','ﮄ'=>'ÚŒ','ï®…'=>'ÚŒ','ﮆ'=>'ÚŽ','ﮇ'=>'ÚŽ','ﮈ'=>'Úˆ','ﮉ'=>'Úˆ','ﮊ'=>'Ú˜','ﮋ'=>'Ú˜','ﮌ'=>'Ú‘','ï®'=>'Ú‘','ﮎ'=>'Ú©','ï®'=>'Ú©','ï®'=>'Ú©','ﮑ'=>'Ú©','ï®’'=>'Ú¯','ﮓ'=>'Ú¯','ï®”'=>'Ú¯','ﮕ'=>'Ú¯','ï®–'=>'Ú³','ï®—'=>'Ú³','ﮘ'=>'Ú³','ï®™'=>'Ú³','ﮚ'=>'Ú±','ï®›'=>'Ú±','ﮜ'=>'Ú±','ï®'=>'Ú±','ﮞ'=>'Úº','ﮟ'=>'Úº','ï® '=>'Ú»','ﮡ'=>'Ú»','ﮢ'=>'Ú»','ﮣ'=>'Ú»','ﮤ'=>'Û•Ù”','ﮥ'=>'Û•Ù”','ﮦ'=>'Û','ﮧ'=>'Û','ﮨ'=>'Û','ﮩ'=>'Û','ﮪ'=>'Ú¾','ﮫ'=>'Ú¾','ﮬ'=>'Ú¾','ï®­'=>'Ú¾','ï®®'=>'Û’','ﮯ'=>'Û’','ï®°'=>'Û’Ù”','ï®±'=>'Û’Ù”','ﯓ'=>'Ú­','ﯔ'=>'Ú­','ﯕ'=>'Ú­','ﯖ'=>'Ú­','ﯗ'=>'Û‡','ﯘ'=>'Û‡','ﯙ'=>'Û†','ﯚ'=>'Û†','ﯛ'=>'Ûˆ','ﯜ'=>'Ûˆ','ï¯'=>'Û‡Ù´','ﯞ'=>'Û‹','ﯟ'=>'Û‹','ﯠ'=>'Û…','ﯡ'=>'Û…','ﯢ'=>'Û‰','ﯣ'=>'Û‰','ﯤ'=>'Û','ﯥ'=>'Û','ﯦ'=>'Û','ﯧ'=>'Û','ﯨ'=>'Ù‰','ﯩ'=>'Ù‰','ﯪ'=>'ئا','ﯫ'=>'ئا','ﯬ'=>'ÙŠÙ”Û•','ﯭ'=>'ÙŠÙ”Û•','ﯮ'=>'ÙŠÙ”Ùˆ','ﯯ'=>'ÙŠÙ”Ùˆ','ﯰ'=>'ÙŠÙ”Û‡','ﯱ'=>'ÙŠÙ”Û‡','ﯲ'=>'ÙŠÙ”Û†','ﯳ'=>'ÙŠÙ”Û†','ﯴ'=>'ÙŠÙ”Ûˆ','ﯵ'=>'ÙŠÙ”Ûˆ','ﯶ'=>'ÙŠÙ”Û','ﯷ'=>'ÙŠÙ”Û','ﯸ'=>'ÙŠÙ”Û','ﯹ'=>'ÙŠÙ”Ù‰','ﯺ'=>'ÙŠÙ”Ù‰','ﯻ'=>'ÙŠÙ”Ù‰','ﯼ'=>'ÛŒ','ﯽ'=>'ÛŒ','ﯾ'=>'ÛŒ','ﯿ'=>'ÛŒ','ï°€'=>'ئج','ï°'=>'ئح','ï°‚'=>'ÙŠÙ”Ù…','ï°ƒ'=>'ÙŠÙ”Ù‰','ï°„'=>'ÙŠÙ”ÙŠ','ï°…'=>'بج','ï°†'=>'بح','ï°‡'=>'بخ','ï°ˆ'=>'بم','ï°‰'=>'بى','ï°Š'=>'بي','ï°‹'=>'تج','ï°Œ'=>'تح','ï°'=>'تخ','ï°Ž'=>'تم','ï°'=>'تى','ï°'=>'تي','ï°‘'=>'ثج','ï°’'=>'ثم','ï°“'=>'ثى','ï°”'=>'ثي','ï°•'=>'جح','ï°–'=>'جم','ï°—'=>'حج','ï°˜'=>'حم','ï°™'=>'خج','ï°š'=>'خح','ï°›'=>'خم','ï°œ'=>'سج','ï°'=>'سح','ï°ž'=>'سخ','ï°Ÿ'=>'سم','ï° '=>'صح','ï°¡'=>'صم','ï°¢'=>'ضج','ï°£'=>'ضح','ï°¤'=>'ضخ','ï°¥'=>'ضم','ï°¦'=>'طح','ï°§'=>'طم','ï°¨'=>'ظم','ï°©'=>'عج','ï°ª'=>'عم','ï°«'=>'غج','ï°¬'=>'غم','ï°­'=>'Ùج','ï°®'=>'ÙØ­','ï°¯'=>'ÙØ®','ï°°'=>'ÙÙ…','ï°±'=>'ÙÙ‰','ï°²'=>'ÙÙŠ','ï°³'=>'قح','ï°´'=>'قم','ï°µ'=>'قى','ï°¶'=>'قي','ï°·'=>'كا','ï°¸'=>'كج','ï°¹'=>'كح','ï°º'=>'كخ','ï°»'=>'كل','ï°¼'=>'كم','ï°½'=>'كى','ï°¾'=>'كي','ï°¿'=>'لج','ï±€'=>'لح','ï±'=>'لخ','ﱂ'=>'لم','ﱃ'=>'لى','ﱄ'=>'لي','ï±…'=>'مج','ﱆ'=>'مح','ﱇ'=>'مخ','ﱈ'=>'مم','ﱉ'=>'مى','ﱊ'=>'مي','ﱋ'=>'نج','ﱌ'=>'نح','ï±'=>'نخ','ﱎ'=>'نم','ï±'=>'نى','ï±'=>'ني','ﱑ'=>'هج','ï±’'=>'هم','ﱓ'=>'هى','ï±”'=>'هي','ﱕ'=>'يج','ï±–'=>'يح','ï±—'=>'يخ','ﱘ'=>'يم','ï±™'=>'يى','ﱚ'=>'يي','ï±›'=>'ذٰ','ﱜ'=>'رٰ','ï±'=>'ىٰ','ﱞ'=>' ٌّ','ﱟ'=>' ÙÙ‘','ï± '=>' ÙŽÙ‘','ﱡ'=>' ÙÙ‘','ï±¢'=>' ÙÙ‘','ï±£'=>' ّٰ','ﱤ'=>'ئر','ï±¥'=>'ئز','ﱦ'=>'ÙŠÙ”Ù…','ﱧ'=>'ÙŠÙ”Ù†','ﱨ'=>'ÙŠÙ”Ù‰','ﱩ'=>'ÙŠÙ”ÙŠ','ﱪ'=>'بر','ﱫ'=>'بز','ﱬ'=>'بم','ï±­'=>'بن','ï±®'=>'بى','ﱯ'=>'بي','ï±°'=>'تر','ï±±'=>'تز','ï±²'=>'تم','ï±³'=>'تن','ï±´'=>'تى','ï±µ'=>'تي','ﱶ'=>'ثر','ï±·'=>'ثز','ﱸ'=>'ثم','ï±¹'=>'ثن','ﱺ'=>'ثى','ï±»'=>'ثي','ï±¼'=>'ÙÙ‰','ï±½'=>'ÙÙŠ','ï±¾'=>'قى','ﱿ'=>'قي','ï²€'=>'كا','ï²'=>'كل','ﲂ'=>'كم','ﲃ'=>'كى','ﲄ'=>'كي','ï²…'=>'لم','ﲆ'=>'لى','ﲇ'=>'لي','ﲈ'=>'ما','ﲉ'=>'مم','ﲊ'=>'نر','ﲋ'=>'نز','ﲌ'=>'نم','ï²'=>'نن','ﲎ'=>'نى','ï²'=>'ني','ï²'=>'ىٰ','ﲑ'=>'ير','ï²’'=>'يز','ﲓ'=>'يم','ï²”'=>'ين','ﲕ'=>'يى','ï²–'=>'يي','ï²—'=>'ئج','ﲘ'=>'ئح','ï²™'=>'ئخ','ﲚ'=>'ÙŠÙ”Ù…','ï²›'=>'ÙŠÙ”Ù‡','ﲜ'=>'بج','ï²'=>'بح','ﲞ'=>'بخ','ﲟ'=>'بم','ï² '=>'به','ﲡ'=>'تج','ï²¢'=>'تح','ï²£'=>'تخ','ﲤ'=>'تم','ï²¥'=>'ته','ﲦ'=>'ثم','ﲧ'=>'جح','ﲨ'=>'جم','ﲩ'=>'حج','ﲪ'=>'حم','ﲫ'=>'خج','ﲬ'=>'خم','ï²­'=>'سج','ï²®'=>'سح','ﲯ'=>'سخ','ï²°'=>'سم','ï²±'=>'صح','ï²²'=>'صخ','ï²³'=>'صم','ï²´'=>'ضج','ï²µ'=>'ضح','ﲶ'=>'ضخ','ï²·'=>'ضم','ﲸ'=>'طح','ï²¹'=>'ظم','ﲺ'=>'عج','ï²»'=>'عم','ï²¼'=>'غج','ï²½'=>'غم','ï²¾'=>'Ùج','ﲿ'=>'ÙØ­','ï³€'=>'ÙØ®','ï³'=>'ÙÙ…','ﳂ'=>'قح','ﳃ'=>'قم','ﳄ'=>'كج','ï³…'=>'كح','ﳆ'=>'كخ','ﳇ'=>'كل','ﳈ'=>'كم','ﳉ'=>'لج','ﳊ'=>'لح','ﳋ'=>'لخ','ﳌ'=>'لم','ï³'=>'له','ﳎ'=>'مج','ï³'=>'مح','ï³'=>'مخ','ﳑ'=>'مم','ï³’'=>'نج','ﳓ'=>'نح','ï³”'=>'نخ','ﳕ'=>'نم','ï³–'=>'نه','ï³—'=>'هج','ﳘ'=>'هم','ï³™'=>'هٰ','ﳚ'=>'يج','ï³›'=>'يح','ﳜ'=>'يخ','ï³'=>'يم','ﳞ'=>'يه','ﳟ'=>'ÙŠÙ”Ù…','ï³ '=>'ÙŠÙ”Ù‡','ﳡ'=>'بم','ï³¢'=>'به','ï³£'=>'تم','ﳤ'=>'ته','ï³¥'=>'ثم','ﳦ'=>'ثه','ﳧ'=>'سم','ﳨ'=>'سه','ﳩ'=>'شم','ﳪ'=>'شه','ﳫ'=>'كل','ﳬ'=>'كم','ï³­'=>'لم','ï³®'=>'نم','ﳯ'=>'نه','ï³°'=>'يم','ï³±'=>'يه','ï³²'=>'Ù€ÙŽÙ‘','ï³³'=>'Ù€ÙÙ‘','ï³´'=>'Ù€ÙÙ‘','ï³µ'=>'طى','ﳶ'=>'طي','ï³·'=>'عى','ﳸ'=>'عي','ï³¹'=>'غى','ﳺ'=>'غي','ï³»'=>'سى','ï³¼'=>'سي','ï³½'=>'شى','ï³¾'=>'شي','ﳿ'=>'حى','ï´€'=>'حي','ï´'=>'جى','ï´‚'=>'جي','ï´ƒ'=>'خى','ï´„'=>'خي','ï´…'=>'صى','ï´†'=>'صي','ï´‡'=>'ضى','ï´ˆ'=>'ضي','ï´‰'=>'شج','ï´Š'=>'شح','ï´‹'=>'شخ','ï´Œ'=>'شم','ï´'=>'شر','ï´Ž'=>'سر','ï´'=>'صر','ï´'=>'ضر','ï´‘'=>'طى','ï´’'=>'طي','ï´“'=>'عى','ï´”'=>'عي','ï´•'=>'غى','ï´–'=>'غي','ï´—'=>'سى','ï´˜'=>'سي','ï´™'=>'شى','ï´š'=>'شي','ï´›'=>'حى','ï´œ'=>'حي','ï´'=>'جى','ï´ž'=>'جي','ï´Ÿ'=>'خى','ï´ '=>'خي','ï´¡'=>'صى','ï´¢'=>'صي','ï´£'=>'ضى','ï´¤'=>'ضي','ï´¥'=>'شج','ï´¦'=>'شح','ï´§'=>'شخ','ï´¨'=>'شم','ï´©'=>'شر','ï´ª'=>'سر','ï´«'=>'صر','ï´¬'=>'ضر','ï´­'=>'شج','ï´®'=>'شح','ï´¯'=>'شخ','ï´°'=>'شم','ï´±'=>'سه','ï´²'=>'شه','ï´³'=>'طم','ï´´'=>'سج','ï´µ'=>'سح','ï´¶'=>'سخ','ï´·'=>'شج','ï´¸'=>'شح','ï´¹'=>'شخ','ï´º'=>'طم','ï´»'=>'ظم','ï´¼'=>'اً','ï´½'=>'اً','ïµ'=>'تجم','ﵑ'=>'تحج','ïµ’'=>'تحج','ﵓ'=>'تحم','ïµ”'=>'تخم','ﵕ'=>'تمج','ïµ–'=>'تمح','ïµ—'=>'تمخ','ﵘ'=>'جمح','ïµ™'=>'جمح','ﵚ'=>'حمي','ïµ›'=>'حمى','ﵜ'=>'سحج','ïµ'=>'سجح','ﵞ'=>'سجى','ﵟ'=>'سمح','ïµ '=>'سمح','ﵡ'=>'سمج','ïµ¢'=>'سمم','ïµ£'=>'سمم','ﵤ'=>'صحح','ïµ¥'=>'صحح','ﵦ'=>'صمم','ﵧ'=>'شحم','ﵨ'=>'شحم','ﵩ'=>'شجي','ﵪ'=>'شمخ','ﵫ'=>'شمخ','ﵬ'=>'شمم','ïµ­'=>'شمم','ïµ®'=>'ضحى','ﵯ'=>'ضخم','ïµ°'=>'ضخم','ïµ±'=>'طمح','ïµ²'=>'طمح','ïµ³'=>'طمم','ïµ´'=>'طمي','ïµµ'=>'عجم','ﵶ'=>'عمم','ïµ·'=>'عمم','ﵸ'=>'عمى','ïµ¹'=>'غمم','ﵺ'=>'غمي','ïµ»'=>'غمى','ïµ¼'=>'Ùخم','ïµ½'=>'Ùخم','ïµ¾'=>'قمح','ﵿ'=>'قمم','ﶀ'=>'لحم','ï¶'=>'لحي','ﶂ'=>'لحى','ﶃ'=>'لجج','ﶄ'=>'لجج','ﶅ'=>'لخم','ﶆ'=>'لخم','ﶇ'=>'لمح','ﶈ'=>'لمح','ﶉ'=>'محج','ﶊ'=>'محم','ﶋ'=>'محي','ﶌ'=>'مجح','ï¶'=>'مجم','ﶎ'=>'مخج','ï¶'=>'مخم','ﶒ'=>'مجخ','ﶓ'=>'همج','ﶔ'=>'همم','ﶕ'=>'نحم','ﶖ'=>'نحى','ﶗ'=>'نجم','ﶘ'=>'نجم','ﶙ'=>'نجى','ﶚ'=>'نمي','ﶛ'=>'نمى','ﶜ'=>'يمم','ï¶'=>'يمم','ﶞ'=>'بخي','ﶟ'=>'تجي','ﶠ'=>'تجى','ﶡ'=>'تخي','ﶢ'=>'تخى','ﶣ'=>'تمي','ﶤ'=>'تمى','ﶥ'=>'جمي','ﶦ'=>'جحى','ﶧ'=>'جمى','ﶨ'=>'سخى','ﶩ'=>'صحي','ﶪ'=>'شحي','ﶫ'=>'ضحي','ﶬ'=>'لجي','ﶭ'=>'لمي','ﶮ'=>'يحي','ﶯ'=>'يجي','ﶰ'=>'يمي','ﶱ'=>'ممي','ﶲ'=>'قمي','ﶳ'=>'نحي','ﶴ'=>'قمح','ﶵ'=>'لحم','ﶶ'=>'عمي','ﶷ'=>'كمي','ﶸ'=>'نجح','ﶹ'=>'مخي','ﶺ'=>'لجم','ﶻ'=>'كمم','ﶼ'=>'لجم','ﶽ'=>'نجح','ﶾ'=>'جحي','ﶿ'=>'حجي','ï·€'=>'مجي','ï·'=>'Ùمي','ï·‚'=>'بحي','ï·ƒ'=>'كمم','ï·„'=>'عجم','ï·…'=>'صمم','ï·†'=>'سخي','ï·‡'=>'نجي','ï·°'=>'صلے','ï·±'=>'قلے','ï·²'=>'الله','ï·³'=>'اكبر','ï·´'=>'محمد','ï·µ'=>'صلعم','ï·¶'=>'رسول','ï··'=>'عليه','ï·¸'=>'وسلم','ï·¹'=>'صلى','ï·º'=>'صلى الله عليه وسلم','ï·»'=>'جل جلاله','ï·¼'=>'ریال','ï¸'=>',','︑'=>'ã€','︒'=>'。','︓'=>':','︔'=>';','︕'=>'!','︖'=>'?','︗'=>'〖','︘'=>'〗','︙'=>'...','︰'=>'..','︱'=>'—','︲'=>'–','︳'=>'_','︴'=>'_','︵'=>'(','︶'=>')','︷'=>'{','︸'=>'}','︹'=>'〔','︺'=>'〕','︻'=>'ã€','︼'=>'】','︽'=>'《','︾'=>'》','︿'=>'〈','ï¹€'=>'〉','ï¹'=>'「','﹂'=>'ã€','﹃'=>'『','﹄'=>'ã€','﹇'=>'[','﹈'=>']','﹉'=>' Ì…','﹊'=>' Ì…','﹋'=>' Ì…','﹌'=>' Ì…','ï¹'=>'_','﹎'=>'_','ï¹'=>'_','ï¹'=>',','﹑'=>'ã€','ï¹’'=>'.','ï¹”'=>';','﹕'=>':','ï¹–'=>'?','ï¹—'=>'!','﹘'=>'—','ï¹™'=>'(','﹚'=>')','ï¹›'=>'{','﹜'=>'}','ï¹'=>'〔','﹞'=>'〕','﹟'=>'#','ï¹ '=>'&','﹡'=>'*','ï¹¢'=>'+','ï¹£'=>'-','﹤'=>'<','ï¹¥'=>'>','﹦'=>'=','﹨'=>'\\','﹩'=>'$','﹪'=>'%','﹫'=>'@','ï¹°'=>' Ù‹','ï¹±'=>'ـً','ï¹²'=>' ÙŒ','ï¹´'=>' Ù','ﹶ'=>' ÙŽ','ï¹·'=>'Ù€ÙŽ','ﹸ'=>' Ù','ï¹¹'=>'Ù€Ù','ﹺ'=>' Ù','ï¹»'=>'Ù€Ù','ï¹¼'=>' Ù‘','ï¹½'=>'ـّ','ï¹¾'=>' Ù’','ﹿ'=>'ـْ','ﺀ'=>'Ø¡','ïº'=>'آ','ﺂ'=>'آ','ﺃ'=>'أ','ﺄ'=>'أ','ﺅ'=>'ÙˆÙ”','ﺆ'=>'ÙˆÙ”','ﺇ'=>'إ','ﺈ'=>'إ','ﺉ'=>'ÙŠÙ”','ﺊ'=>'ÙŠÙ”','ﺋ'=>'ÙŠÙ”','ﺌ'=>'ÙŠÙ”','ïº'=>'ا','ﺎ'=>'ا','ïº'=>'ب','ïº'=>'ب','ﺑ'=>'ب','ﺒ'=>'ب','ﺓ'=>'Ø©','ﺔ'=>'Ø©','ﺕ'=>'ت','ﺖ'=>'ت','ﺗ'=>'ت','ﺘ'=>'ت','ﺙ'=>'Ø«','ﺚ'=>'Ø«','ﺛ'=>'Ø«','ﺜ'=>'Ø«','ïº'=>'ج','ﺞ'=>'ج','ﺟ'=>'ج','ﺠ'=>'ج','ﺡ'=>'Ø­','ﺢ'=>'Ø­','ﺣ'=>'Ø­','ﺤ'=>'Ø­','ﺥ'=>'Ø®','ﺦ'=>'Ø®','ﺧ'=>'Ø®','ﺨ'=>'Ø®','ﺩ'=>'د','ﺪ'=>'د','ﺫ'=>'Ø°','ﺬ'=>'Ø°','ﺭ'=>'ر','ﺮ'=>'ر','ﺯ'=>'ز','ﺰ'=>'ز','ﺱ'=>'س','ﺲ'=>'س','ﺳ'=>'س','ﺴ'=>'س','ﺵ'=>'Ø´','ﺶ'=>'Ø´','ﺷ'=>'Ø´','ﺸ'=>'Ø´','ﺹ'=>'ص','ﺺ'=>'ص','ﺻ'=>'ص','ﺼ'=>'ص','ﺽ'=>'ض','ﺾ'=>'ض','ﺿ'=>'ض','ﻀ'=>'ض','ï»'=>'Ø·','ﻂ'=>'Ø·','ﻃ'=>'Ø·','ﻄ'=>'Ø·','ï»…'=>'ظ','ﻆ'=>'ظ','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻉ'=>'ع','ﻊ'=>'ع','ﻋ'=>'ع','ﻌ'=>'ع','ï»'=>'غ','ﻎ'=>'غ','ï»'=>'غ','ï»'=>'غ','ﻑ'=>'Ù','ï»’'=>'Ù','ﻓ'=>'Ù','ï»”'=>'Ù','ﻕ'=>'Ù‚','ï»–'=>'Ù‚','ï»—'=>'Ù‚','ﻘ'=>'Ù‚','ï»™'=>'Ùƒ','ﻚ'=>'Ùƒ','ï»›'=>'Ùƒ','ﻜ'=>'Ùƒ','ï»'=>'Ù„','ﻞ'=>'Ù„','ﻟ'=>'Ù„','ï» '=>'Ù„','ﻡ'=>'Ù…','ﻢ'=>'Ù…','ﻣ'=>'Ù…','ﻤ'=>'Ù…','ﻥ'=>'Ù†','ﻦ'=>'Ù†','ﻧ'=>'Ù†','ﻨ'=>'Ù†','ﻩ'=>'Ù‡','ﻪ'=>'Ù‡','ﻫ'=>'Ù‡','ﻬ'=>'Ù‡','ï»­'=>'Ùˆ','ï»®'=>'Ùˆ','ﻯ'=>'Ù‰','ï»°'=>'Ù‰','ï»±'=>'ÙŠ','ﻲ'=>'ÙŠ','ﻳ'=>'ÙŠ','ï»´'=>'ÙŠ','ﻵ'=>'لآ','ﻶ'=>'لآ','ï»·'=>'لأ','ﻸ'=>'لأ','ﻹ'=>'لإ','ﻺ'=>'لإ','ï»»'=>'لا','ﻼ'=>'لا','ï¼'=>'!','"'=>'"','#'=>'#','$'=>'$','ï¼…'=>'%','&'=>'&','''=>'\'','('=>'(',')'=>')','*'=>'*','+'=>'+',','=>',','ï¼'=>'-','.'=>'.','ï¼'=>'/','ï¼'=>'0','1'=>'1','ï¼’'=>'2','3'=>'3','ï¼”'=>'4','5'=>'5','ï¼–'=>'6','ï¼—'=>'7','8'=>'8','ï¼™'=>'9',':'=>':','ï¼›'=>';','<'=>'<','ï¼'=>'=','>'=>'>','?'=>'?','ï¼ '=>'@','A'=>'A','ï¼¢'=>'B','ï¼£'=>'C','D'=>'D','ï¼¥'=>'E','F'=>'F','G'=>'G','H'=>'H','I'=>'I','J'=>'J','K'=>'K','L'=>'L','ï¼­'=>'M','ï¼®'=>'N','O'=>'O','ï¼°'=>'P','ï¼±'=>'Q','ï¼²'=>'R','ï¼³'=>'S','ï¼´'=>'T','ï¼µ'=>'U','V'=>'V','ï¼·'=>'W','X'=>'X','ï¼¹'=>'Y','Z'=>'Z','ï¼»'=>'[','ï¼¼'=>'\\','ï¼½'=>']','ï¼¾'=>'^','_'=>'_','ï½€'=>'`','ï½'=>'a','b'=>'b','c'=>'c','d'=>'d','ï½…'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j','k'=>'k','l'=>'l','ï½'=>'m','n'=>'n','ï½'=>'o','ï½'=>'p','q'=>'q','ï½’'=>'r','s'=>'s','ï½”'=>'t','u'=>'u','ï½–'=>'v','ï½—'=>'w','x'=>'x','ï½™'=>'y','z'=>'z','ï½›'=>'{','|'=>'|','ï½'=>'}','~'=>'~','⦅'=>'⦅','ï½ '=>'⦆','。'=>'。','ï½¢'=>'「','ï½£'=>'ã€','、'=>'ã€','ï½¥'=>'・','ヲ'=>'ヲ','ァ'=>'ã‚¡','ィ'=>'ã‚£','ゥ'=>'ã‚¥','ェ'=>'ェ','ォ'=>'ã‚©','ャ'=>'ャ','ï½­'=>'ュ','ï½®'=>'ョ','ッ'=>'ッ','ï½°'=>'ー','ï½±'=>'ã‚¢','ï½²'=>'イ','ï½³'=>'ウ','ï½´'=>'エ','ï½µ'=>'オ','カ'=>'ã‚«','ï½·'=>'ã‚­','ク'=>'ク','ï½¹'=>'ケ','コ'=>'コ','ï½»'=>'サ','ï½¼'=>'ã‚·','ï½½'=>'ス','ï½¾'=>'ã‚»','ソ'=>'ソ','ï¾€'=>'ã‚¿','ï¾'=>'ãƒ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ï¾…'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ãƒ','ノ'=>'ノ','ハ'=>'ãƒ','ヒ'=>'ヒ','フ'=>'フ','ï¾'=>'ヘ','ホ'=>'ホ','ï¾'=>'マ','ï¾'=>'ミ','ム'=>'ム','ï¾’'=>'メ','モ'=>'モ','ï¾”'=>'ヤ','ユ'=>'ユ','ï¾–'=>'ヨ','ï¾—'=>'ラ','リ'=>'リ','ï¾™'=>'ル','レ'=>'レ','ï¾›'=>'ロ','ワ'=>'ワ','ï¾'=>'ン','゙'=>'ã‚™','゚'=>'ã‚š','ï¾ '=>'á… ','ᄀ'=>'á„€','ï¾¢'=>'á„','ï¾£'=>'ᆪ','ᄂ'=>'á„‚','ï¾¥'=>'ᆬ','ᆭ'=>'ᆭ','ᄃ'=>'ᄃ','ᄄ'=>'á„„','ᄅ'=>'á„…','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ï¾­'=>'ᆳ','ï¾®'=>'ᆴ','ᆵ'=>'ᆵ','ï¾°'=>'á„š','ï¾±'=>'ᄆ','ï¾²'=>'ᄇ','ï¾³'=>'ᄈ','ï¾´'=>'á„¡','ï¾µ'=>'ᄉ','ᄊ'=>'á„Š','ï¾·'=>'á„‹','ᄌ'=>'á„Œ','ï¾¹'=>'á„','ᄎ'=>'á„Ž','ï¾»'=>'á„','ï¾¼'=>'á„','ï¾½'=>'á„‘','ï¾¾'=>'á„’','ï¿‚'=>'á…¡','ᅢ'=>'á…¢','ï¿„'=>'á…£','ï¿…'=>'á…¤','ᅥ'=>'á…¥','ᅦ'=>'á…¦','ï¿Š'=>'á…§','ï¿‹'=>'á…¨','ï¿Œ'=>'á…©','ï¿'=>'á…ª','ï¿Ž'=>'á…«','ï¿'=>'á…¬','ï¿’'=>'á…­','ï¿“'=>'á…®','ï¿”'=>'á…¯','ï¿•'=>'á…°','ï¿–'=>'á…±','ï¿—'=>'á…²','ï¿š'=>'á…³','ï¿›'=>'á…´','ï¿œ'=>'á…µ','ï¿ '=>'¢','ï¿¡'=>'£','ï¿¢'=>'¬','ï¿£'=>' Ì„','¦'=>'¦','ï¿¥'=>'Â¥','₩'=>'â‚©','│'=>'│','ï¿©'=>'â†','↑'=>'↑','ï¿«'=>'→','↓'=>'↓','ï¿­'=>'â– ','ï¿®'=>'â—‹','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','ð€'=>'A','ð'=>'B','ð‚'=>'C','ðƒ'=>'D','ð„'=>'E','ð…'=>'F','ð†'=>'G','ð‡'=>'H','ðˆ'=>'I','ð‰'=>'J','ðŠ'=>'K','ð‹'=>'L','ðŒ'=>'M','ð'=>'N','ðŽ'=>'O','ð'=>'P','ð'=>'Q','ð‘'=>'R','ð’'=>'S','ð“'=>'T','ð”'=>'U','ð•'=>'V','ð–'=>'W','ð—'=>'X','ð˜'=>'Y','ð™'=>'Z','ðš'=>'a','ð›'=>'b','ðœ'=>'c','ð'=>'d','ðž'=>'e','ðŸ'=>'f','ð '=>'g','ð¡'=>'h','ð¢'=>'i','ð£'=>'j','ð¤'=>'k','ð¥'=>'l','ð¦'=>'m','ð§'=>'n','ð¨'=>'o','ð©'=>'p','ðª'=>'q','ð«'=>'r','ð¬'=>'s','ð­'=>'t','ð®'=>'u','ð¯'=>'v','ð°'=>'w','ð±'=>'x','ð²'=>'y','ð³'=>'z','ð´'=>'A','ðµ'=>'B','ð¶'=>'C','ð·'=>'D','ð¸'=>'E','ð¹'=>'F','ðº'=>'G','ð»'=>'H','ð¼'=>'I','ð½'=>'J','ð¾'=>'K','ð¿'=>'L','ð‘€'=>'M','ð‘'=>'N','ð‘‚'=>'O','ð‘ƒ'=>'P','ð‘„'=>'Q','ð‘…'=>'R','ð‘†'=>'S','ð‘‡'=>'T','ð‘ˆ'=>'U','ð‘‰'=>'V','ð‘Š'=>'W','ð‘‹'=>'X','ð‘Œ'=>'Y','ð‘'=>'Z','ð‘Ž'=>'a','ð‘'=>'b','ð‘'=>'c','ð‘‘'=>'d','ð‘’'=>'e','ð‘“'=>'f','ð‘”'=>'g','ð‘–'=>'i','ð‘—'=>'j','ð‘˜'=>'k','ð‘™'=>'l','ð‘š'=>'m','ð‘›'=>'n','ð‘œ'=>'o','ð‘'=>'p','ð‘ž'=>'q','ð‘Ÿ'=>'r','ð‘ '=>'s','ð‘¡'=>'t','ð‘¢'=>'u','ð‘£'=>'v','ð‘¤'=>'w','ð‘¥'=>'x','ð‘¦'=>'y','ð‘§'=>'z','ð‘¨'=>'A','ð‘©'=>'B','ð‘ª'=>'C','ð‘«'=>'D','ð‘¬'=>'E','ð‘­'=>'F','ð‘®'=>'G','ð‘¯'=>'H','ð‘°'=>'I','ð‘±'=>'J','ð‘²'=>'K','ð‘³'=>'L','ð‘´'=>'M','ð‘µ'=>'N','ð‘¶'=>'O','ð‘·'=>'P','ð‘¸'=>'Q','ð‘¹'=>'R','ð‘º'=>'S','ð‘»'=>'T','ð‘¼'=>'U','ð‘½'=>'V','ð‘¾'=>'W','ð‘¿'=>'X','ð’€'=>'Y','ð’'=>'Z','ð’‚'=>'a','ð’ƒ'=>'b','ð’„'=>'c','ð’…'=>'d','ð’†'=>'e','ð’‡'=>'f','ð’ˆ'=>'g','ð’‰'=>'h','ð’Š'=>'i','ð’‹'=>'j','ð’Œ'=>'k','ð’'=>'l','ð’Ž'=>'m','ð’'=>'n','ð’'=>'o','ð’‘'=>'p','ð’’'=>'q','ð’“'=>'r','ð’”'=>'s','ð’•'=>'t','ð’–'=>'u','ð’—'=>'v','ð’˜'=>'w','ð’™'=>'x','ð’š'=>'y','ð’›'=>'z','ð’œ'=>'A','ð’ž'=>'C','ð’Ÿ'=>'D','ð’¢'=>'G','ð’¥'=>'J','ð’¦'=>'K','ð’©'=>'N','ð’ª'=>'O','ð’«'=>'P','ð’¬'=>'Q','ð’®'=>'S','ð’¯'=>'T','ð’°'=>'U','ð’±'=>'V','ð’²'=>'W','ð’³'=>'X','ð’´'=>'Y','ð’µ'=>'Z','ð’¶'=>'a','ð’·'=>'b','ð’¸'=>'c','ð’¹'=>'d','ð’»'=>'f','ð’½'=>'h','ð’¾'=>'i','ð’¿'=>'j','ð“€'=>'k','ð“'=>'l','ð“‚'=>'m','ð“ƒ'=>'n','ð“…'=>'p','ð“†'=>'q','ð“‡'=>'r','ð“ˆ'=>'s','ð“‰'=>'t','ð“Š'=>'u','ð“‹'=>'v','ð“Œ'=>'w','ð“'=>'x','ð“Ž'=>'y','ð“'=>'z','ð“'=>'A','ð“‘'=>'B','ð“’'=>'C','ð““'=>'D','ð“”'=>'E','ð“•'=>'F','ð“–'=>'G','ð“—'=>'H','ð“˜'=>'I','ð“™'=>'J','ð“š'=>'K','ð“›'=>'L','ð“œ'=>'M','ð“'=>'N','ð“ž'=>'O','ð“Ÿ'=>'P','ð“ '=>'Q','ð“¡'=>'R','ð“¢'=>'S','ð“£'=>'T','ð“¤'=>'U','ð“¥'=>'V','ð“¦'=>'W','ð“§'=>'X','ð“¨'=>'Y','ð“©'=>'Z','ð“ª'=>'a','ð“«'=>'b','ð“¬'=>'c','ð“­'=>'d','ð“®'=>'e','ð“¯'=>'f','ð“°'=>'g','ð“±'=>'h','ð“²'=>'i','ð“³'=>'j','ð“´'=>'k','ð“µ'=>'l','ð“¶'=>'m','ð“·'=>'n','ð“¸'=>'o','ð“¹'=>'p','ð“º'=>'q','ð“»'=>'r','ð“¼'=>'s','ð“½'=>'t','ð“¾'=>'u','ð“¿'=>'v','ð”€'=>'w','ð”'=>'x','ð”‚'=>'y','ð”ƒ'=>'z','ð”„'=>'A','ð”…'=>'B','ð”‡'=>'D','ð”ˆ'=>'E','ð”‰'=>'F','ð”Š'=>'G','ð”'=>'J','ð”Ž'=>'K','ð”'=>'L','ð”'=>'M','ð”‘'=>'N','ð”’'=>'O','ð”“'=>'P','ð””'=>'Q','ð”–'=>'S','ð”—'=>'T','ð”˜'=>'U','ð”™'=>'V','ð”š'=>'W','ð”›'=>'X','ð”œ'=>'Y','ð”ž'=>'a','ð”Ÿ'=>'b','ð” '=>'c','ð”¡'=>'d','ð”¢'=>'e','ð”£'=>'f','ð”¤'=>'g','ð”¥'=>'h','ð”¦'=>'i','ð”§'=>'j','ð”¨'=>'k','ð”©'=>'l','ð”ª'=>'m','ð”«'=>'n','ð”¬'=>'o','ð”­'=>'p','ð”®'=>'q','ð”¯'=>'r','ð”°'=>'s','ð”±'=>'t','ð”²'=>'u','ð”³'=>'v','ð”´'=>'w','ð”µ'=>'x','ð”¶'=>'y','ð”·'=>'z','ð”¸'=>'A','ð”¹'=>'B','ð”»'=>'D','ð”¼'=>'E','ð”½'=>'F','ð”¾'=>'G','ð•€'=>'I','ð•'=>'J','ð•‚'=>'K','ð•ƒ'=>'L','ð•„'=>'M','ð•†'=>'O','ð•Š'=>'S','ð•‹'=>'T','ð•Œ'=>'U','ð•'=>'V','ð•Ž'=>'W','ð•'=>'X','ð•'=>'Y','ð•’'=>'a','ð•“'=>'b','ð•”'=>'c','ð••'=>'d','ð•–'=>'e','ð•—'=>'f','ð•˜'=>'g','ð•™'=>'h','ð•š'=>'i','ð•›'=>'j','ð•œ'=>'k','ð•'=>'l','ð•ž'=>'m','ð•Ÿ'=>'n','ð• '=>'o','ð•¡'=>'p','ð•¢'=>'q','ð•£'=>'r','ð•¤'=>'s','ð•¥'=>'t','ð•¦'=>'u','ð•§'=>'v','ð•¨'=>'w','ð•©'=>'x','ð•ª'=>'y','ð•«'=>'z','ð•¬'=>'A','ð•­'=>'B','ð•®'=>'C','ð•¯'=>'D','ð•°'=>'E','ð•±'=>'F','ð•²'=>'G','ð•³'=>'H','ð•´'=>'I','ð•µ'=>'J','ð•¶'=>'K','ð•·'=>'L','ð•¸'=>'M','ð•¹'=>'N','ð•º'=>'O','ð•»'=>'P','ð•¼'=>'Q','ð•½'=>'R','ð•¾'=>'S','ð•¿'=>'T','ð–€'=>'U','ð–'=>'V','ð–‚'=>'W','ð–ƒ'=>'X','ð–„'=>'Y','ð–…'=>'Z','ð–†'=>'a','ð–‡'=>'b','ð–ˆ'=>'c','ð–‰'=>'d','ð–Š'=>'e','ð–‹'=>'f','ð–Œ'=>'g','ð–'=>'h','ð–Ž'=>'i','ð–'=>'j','ð–'=>'k','ð–‘'=>'l','ð–’'=>'m','ð–“'=>'n','ð–”'=>'o','ð–•'=>'p','ð––'=>'q','ð–—'=>'r','ð–˜'=>'s','ð–™'=>'t','ð–š'=>'u','ð–›'=>'v','ð–œ'=>'w','ð–'=>'x','ð–ž'=>'y','ð–Ÿ'=>'z','ð– '=>'A','ð–¡'=>'B','ð–¢'=>'C','ð–£'=>'D','ð–¤'=>'E','ð–¥'=>'F','ð–¦'=>'G','ð–§'=>'H','ð–¨'=>'I','ð–©'=>'J','ð–ª'=>'K','ð–«'=>'L','ð–¬'=>'M','ð–­'=>'N','ð–®'=>'O','ð–¯'=>'P','ð–°'=>'Q','ð–±'=>'R','ð–²'=>'S','ð–³'=>'T','ð–´'=>'U','ð–µ'=>'V','ð–¶'=>'W','ð–·'=>'X','ð–¸'=>'Y','ð–¹'=>'Z','ð–º'=>'a','ð–»'=>'b','ð–¼'=>'c','ð–½'=>'d','ð–¾'=>'e','ð–¿'=>'f','ð—€'=>'g','ð—'=>'h','ð—‚'=>'i','ð—ƒ'=>'j','ð—„'=>'k','ð—…'=>'l','ð—†'=>'m','ð—‡'=>'n','ð—ˆ'=>'o','ð—‰'=>'p','ð—Š'=>'q','ð—‹'=>'r','ð—Œ'=>'s','ð—'=>'t','ð—Ž'=>'u','ð—'=>'v','ð—'=>'w','ð—‘'=>'x','ð—’'=>'y','ð—“'=>'z','ð—”'=>'A','ð—•'=>'B','ð—–'=>'C','ð——'=>'D','ð—˜'=>'E','ð—™'=>'F','ð—š'=>'G','ð—›'=>'H','ð—œ'=>'I','ð—'=>'J','ð—ž'=>'K','ð—Ÿ'=>'L','ð— '=>'M','ð—¡'=>'N','ð—¢'=>'O','ð—£'=>'P','ð—¤'=>'Q','ð—¥'=>'R','ð—¦'=>'S','ð—§'=>'T','ð—¨'=>'U','ð—©'=>'V','ð—ª'=>'W','ð—«'=>'X','ð—¬'=>'Y','ð—­'=>'Z','ð—®'=>'a','ð—¯'=>'b','ð—°'=>'c','ð—±'=>'d','ð—²'=>'e','ð—³'=>'f','ð—´'=>'g','ð—µ'=>'h','ð—¶'=>'i','ð—·'=>'j','ð—¸'=>'k','ð—¹'=>'l','ð—º'=>'m','ð—»'=>'n','ð—¼'=>'o','ð—½'=>'p','ð—¾'=>'q','ð—¿'=>'r','ð˜€'=>'s','ð˜'=>'t','ð˜‚'=>'u','ð˜ƒ'=>'v','ð˜„'=>'w','ð˜…'=>'x','ð˜†'=>'y','ð˜‡'=>'z','ð˜ˆ'=>'A','ð˜‰'=>'B','ð˜Š'=>'C','ð˜‹'=>'D','ð˜Œ'=>'E','ð˜'=>'F','ð˜Ž'=>'G','ð˜'=>'H','ð˜'=>'I','ð˜‘'=>'J','ð˜’'=>'K','ð˜“'=>'L','ð˜”'=>'M','ð˜•'=>'N','ð˜–'=>'O','ð˜—'=>'P','ð˜˜'=>'Q','ð˜™'=>'R','ð˜š'=>'S','ð˜›'=>'T','ð˜œ'=>'U','ð˜'=>'V','ð˜ž'=>'W','ð˜Ÿ'=>'X','ð˜ '=>'Y','ð˜¡'=>'Z','ð˜¢'=>'a','ð˜£'=>'b','ð˜¤'=>'c','ð˜¥'=>'d','ð˜¦'=>'e','ð˜§'=>'f','ð˜¨'=>'g','ð˜©'=>'h','ð˜ª'=>'i','ð˜«'=>'j','ð˜¬'=>'k','ð˜­'=>'l','ð˜®'=>'m','ð˜¯'=>'n','ð˜°'=>'o','ð˜±'=>'p','ð˜²'=>'q','ð˜³'=>'r','ð˜´'=>'s','ð˜µ'=>'t','ð˜¶'=>'u','ð˜·'=>'v','ð˜¸'=>'w','ð˜¹'=>'x','ð˜º'=>'y','ð˜»'=>'z','ð˜¼'=>'A','ð˜½'=>'B','ð˜¾'=>'C','ð˜¿'=>'D','ð™€'=>'E','ð™'=>'F','ð™‚'=>'G','ð™ƒ'=>'H','ð™„'=>'I','ð™…'=>'J','ð™†'=>'K','ð™‡'=>'L','ð™ˆ'=>'M','ð™‰'=>'N','ð™Š'=>'O','ð™‹'=>'P','ð™Œ'=>'Q','ð™'=>'R','ð™Ž'=>'S','ð™'=>'T','ð™'=>'U','ð™‘'=>'V','ð™’'=>'W','ð™“'=>'X','ð™”'=>'Y','ð™•'=>'Z','ð™–'=>'a','ð™—'=>'b','ð™˜'=>'c','ð™™'=>'d','ð™š'=>'e','ð™›'=>'f','ð™œ'=>'g','ð™'=>'h','ð™ž'=>'i','ð™Ÿ'=>'j','ð™ '=>'k','ð™¡'=>'l','ð™¢'=>'m','ð™£'=>'n','ð™¤'=>'o','ð™¥'=>'p','ð™¦'=>'q','ð™§'=>'r','ð™¨'=>'s','ð™©'=>'t','ð™ª'=>'u','ð™«'=>'v','ð™¬'=>'w','ð™­'=>'x','ð™®'=>'y','ð™¯'=>'z','ð™°'=>'A','ð™±'=>'B','ð™²'=>'C','ð™³'=>'D','ð™´'=>'E','ð™µ'=>'F','ð™¶'=>'G','ð™·'=>'H','ð™¸'=>'I','ð™¹'=>'J','ð™º'=>'K','ð™»'=>'L','ð™¼'=>'M','ð™½'=>'N','ð™¾'=>'O','ð™¿'=>'P','ðš€'=>'Q','ðš'=>'R','ðš‚'=>'S','ðšƒ'=>'T','ðš„'=>'U','ðš…'=>'V','ðš†'=>'W','ðš‡'=>'X','ðšˆ'=>'Y','ðš‰'=>'Z','ðšŠ'=>'a','ðš‹'=>'b','ðšŒ'=>'c','ðš'=>'d','ðšŽ'=>'e','ðš'=>'f','ðš'=>'g','ðš‘'=>'h','ðš’'=>'i','ðš“'=>'j','ðš”'=>'k','ðš•'=>'l','ðš–'=>'m','ðš—'=>'n','ðš˜'=>'o','ðš™'=>'p','ðšš'=>'q','ðš›'=>'r','ðšœ'=>'s','ðš'=>'t','ðšž'=>'u','ðšŸ'=>'v','ðš '=>'w','ðš¡'=>'x','ðš¢'=>'y','ðš£'=>'z','ðš¤'=>'ı','ðš¥'=>'È·','ðš¨'=>'Α','ðš©'=>'Î’','ðšª'=>'Γ','ðš«'=>'Δ','ðš¬'=>'Ε','ðš­'=>'Ζ','ðš®'=>'Η','ðš¯'=>'Θ','ðš°'=>'Ι','ðš±'=>'Κ','ðš²'=>'Λ','ðš³'=>'Îœ','ðš´'=>'Î','ðšµ'=>'Ξ','ðš¶'=>'Ο','ðš·'=>'Π','ðš¸'=>'Ρ','ðš¹'=>'Θ','ðšº'=>'Σ','ðš»'=>'Τ','ðš¼'=>'Î¥','ðš½'=>'Φ','ðš¾'=>'Χ','ðš¿'=>'Ψ','ð›€'=>'Ω','ð›'=>'∇','ð›‚'=>'α','ð›ƒ'=>'β','ð›„'=>'γ','ð›…'=>'δ','ð›†'=>'ε','ð›‡'=>'ζ','ð›ˆ'=>'η','ð›‰'=>'θ','ð›Š'=>'ι','ð›‹'=>'κ','ð›Œ'=>'λ','ð›'=>'μ','ð›Ž'=>'ν','ð›'=>'ξ','ð›'=>'ο','ð›‘'=>'Ï€','ð›’'=>'Ï','ð›“'=>'Ï‚','ð›”'=>'σ','ð›•'=>'Ï„','ð›–'=>'Ï…','ð›—'=>'φ','ð›˜'=>'χ','ð›™'=>'ψ','ð›š'=>'ω','ð››'=>'∂','ð›œ'=>'ε','ð›'=>'θ','ð›ž'=>'κ','ð›Ÿ'=>'φ','ð› '=>'Ï','ð›¡'=>'Ï€','ð›¢'=>'Α','ð›£'=>'Î’','ð›¤'=>'Γ','ð›¥'=>'Δ','ð›¦'=>'Ε','ð›§'=>'Ζ','ð›¨'=>'Η','ð›©'=>'Θ','ð›ª'=>'Ι','ð›«'=>'Κ','ð›¬'=>'Λ','ð›­'=>'Îœ','ð›®'=>'Î','ð›¯'=>'Ξ','ð›°'=>'Ο','ð›±'=>'Π','ð›²'=>'Ρ','ð›³'=>'Θ','ð›´'=>'Σ','ð›µ'=>'Τ','ð›¶'=>'Î¥','ð›·'=>'Φ','ð›¸'=>'Χ','ð›¹'=>'Ψ','ð›º'=>'Ω','ð›»'=>'∇','ð›¼'=>'α','ð›½'=>'β','ð›¾'=>'γ','ð›¿'=>'δ','ðœ€'=>'ε','ðœ'=>'ζ','ðœ‚'=>'η','ðœƒ'=>'θ','ðœ„'=>'ι','ðœ…'=>'κ','ðœ†'=>'λ','ðœ‡'=>'μ','ðœˆ'=>'ν','ðœ‰'=>'ξ','ðœŠ'=>'ο','ðœ‹'=>'Ï€','ðœŒ'=>'Ï','ðœ'=>'Ï‚','ðœŽ'=>'σ','ðœ'=>'Ï„','ðœ'=>'Ï…','ðœ‘'=>'φ','ðœ’'=>'χ','ðœ“'=>'ψ','ðœ”'=>'ω','ðœ•'=>'∂','ðœ–'=>'ε','ðœ—'=>'θ','ðœ˜'=>'κ','ðœ™'=>'φ','ðœš'=>'Ï','ðœ›'=>'Ï€','ðœœ'=>'Α','ðœ'=>'Î’','ðœž'=>'Γ','ðœŸ'=>'Δ','ðœ '=>'Ε','ðœ¡'=>'Ζ','ðœ¢'=>'Η','ðœ£'=>'Θ','ðœ¤'=>'Ι','ðœ¥'=>'Κ','ðœ¦'=>'Λ','ðœ§'=>'Îœ','ðœ¨'=>'Î','ðœ©'=>'Ξ','ðœª'=>'Ο','ðœ«'=>'Π','ðœ¬'=>'Ρ','ðœ­'=>'Θ','ðœ®'=>'Σ','ðœ¯'=>'Τ','ðœ°'=>'Î¥','ðœ±'=>'Φ','ðœ²'=>'Χ','ðœ³'=>'Ψ','ðœ´'=>'Ω','ðœµ'=>'∇','ðœ¶'=>'α','ðœ·'=>'β','ðœ¸'=>'γ','ðœ¹'=>'δ','ðœº'=>'ε','ðœ»'=>'ζ','ðœ¼'=>'η','ðœ½'=>'θ','ðœ¾'=>'ι','ðœ¿'=>'κ','ð€'=>'λ','ð'=>'μ','ð‚'=>'ν','ðƒ'=>'ξ','ð„'=>'ο','ð…'=>'Ï€','ð†'=>'Ï','ð‡'=>'Ï‚','ðˆ'=>'σ','ð‰'=>'Ï„','ðŠ'=>'Ï…','ð‹'=>'φ','ðŒ'=>'χ','ð'=>'ψ','ðŽ'=>'ω','ð'=>'∂','ð'=>'ε','ð‘'=>'θ','ð’'=>'κ','ð“'=>'φ','ð”'=>'Ï','ð•'=>'Ï€','ð–'=>'Α','ð—'=>'Î’','ð˜'=>'Γ','ð™'=>'Δ','ðš'=>'Ε','ð›'=>'Ζ','ðœ'=>'Η','ð'=>'Θ','ðž'=>'Ι','ðŸ'=>'Κ','ð '=>'Λ','ð¡'=>'Îœ','ð¢'=>'Î','ð£'=>'Ξ','ð¤'=>'Ο','ð¥'=>'Π','ð¦'=>'Ρ','ð§'=>'Θ','ð¨'=>'Σ','ð©'=>'Τ','ðª'=>'Î¥','ð«'=>'Φ','ð¬'=>'Χ','ð­'=>'Ψ','ð®'=>'Ω','ð¯'=>'∇','ð°'=>'α','ð±'=>'β','ð²'=>'γ','ð³'=>'δ','ð´'=>'ε','ðµ'=>'ζ','ð¶'=>'η','ð·'=>'θ','ð¸'=>'ι','ð¹'=>'κ','ðº'=>'λ','ð»'=>'μ','ð¼'=>'ν','ð½'=>'ξ','ð¾'=>'ο','ð¿'=>'Ï€','ðž€'=>'Ï','ðž'=>'Ï‚','ðž‚'=>'σ','ðžƒ'=>'Ï„','ðž„'=>'Ï…','ðž…'=>'φ','ðž†'=>'χ','ðž‡'=>'ψ','ðžˆ'=>'ω','ðž‰'=>'∂','ðžŠ'=>'ε','ðž‹'=>'θ','ðžŒ'=>'κ','ðž'=>'φ','ðžŽ'=>'Ï','ðž'=>'Ï€','ðž'=>'Α','ðž‘'=>'Î’','ðž’'=>'Γ','ðž“'=>'Δ','ðž”'=>'Ε','ðž•'=>'Ζ','ðž–'=>'Η','ðž—'=>'Θ','ðž˜'=>'Ι','ðž™'=>'Κ','ðžš'=>'Λ','ðž›'=>'Îœ','ðžœ'=>'Î','ðž'=>'Ξ','ðžž'=>'Ο','ðžŸ'=>'Π','ðž '=>'Ρ','ðž¡'=>'Θ','ðž¢'=>'Σ','ðž£'=>'Τ','ðž¤'=>'Î¥','ðž¥'=>'Φ','ðž¦'=>'Χ','ðž§'=>'Ψ','ðž¨'=>'Ω','ðž©'=>'∇','ðžª'=>'α','ðž«'=>'β','ðž¬'=>'γ','ðž­'=>'δ','ðž®'=>'ε','ðž¯'=>'ζ','ðž°'=>'η','ðž±'=>'θ','ðž²'=>'ι','ðž³'=>'κ','ðž´'=>'λ','ðžµ'=>'μ','ðž¶'=>'ν','ðž·'=>'ξ','ðž¸'=>'ο','ðž¹'=>'Ï€','ðžº'=>'Ï','ðž»'=>'Ï‚','ðž¼'=>'σ','ðž½'=>'Ï„','ðž¾'=>'Ï…','ðž¿'=>'φ','ðŸ€'=>'χ','ðŸ'=>'ψ','ðŸ‚'=>'ω','ðŸƒ'=>'∂','ðŸ„'=>'ε','ðŸ…'=>'θ','ðŸ†'=>'κ','ðŸ‡'=>'φ','ðŸˆ'=>'Ï','ðŸ‰'=>'Ï€','ðŸŠ'=>'Ïœ','ðŸ‹'=>'Ï','ðŸŽ'=>'0','ðŸ'=>'1','ðŸ'=>'2','ðŸ‘'=>'3','ðŸ’'=>'4','ðŸ“'=>'5','ðŸ”'=>'6','ðŸ•'=>'7','ðŸ–'=>'8','ðŸ—'=>'9','ðŸ˜'=>'0','ðŸ™'=>'1','ðŸš'=>'2','ðŸ›'=>'3','ðŸœ'=>'4','ðŸ'=>'5','ðŸž'=>'6','ðŸŸ'=>'7','ðŸ '=>'8','ðŸ¡'=>'9','ðŸ¢'=>'0','ðŸ£'=>'1','ðŸ¤'=>'2','ðŸ¥'=>'3','ðŸ¦'=>'4','ðŸ§'=>'5','ðŸ¨'=>'6','ðŸ©'=>'7','ðŸª'=>'8','ðŸ«'=>'9','ðŸ¬'=>'0','ðŸ­'=>'1','ðŸ®'=>'2','ðŸ¯'=>'3','ðŸ°'=>'4','ðŸ±'=>'5','ðŸ²'=>'6','ðŸ³'=>'7','ðŸ´'=>'8','ðŸµ'=>'9','ðŸ¶'=>'0','ðŸ·'=>'1','ðŸ¸'=>'2','ðŸ¹'=>'3','ðŸº'=>'4','ðŸ»'=>'5','ðŸ¼'=>'6','ðŸ½'=>'7','ðŸ¾'=>'8','ðŸ¿'=>'9','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'ã“Ÿ','刻'=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','卑'=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð ­£','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'哶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','寃'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','憤'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚­','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã­‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'𣑭','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','櫛'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ­”','㱎'=>'㱎','歲'=>'æ­²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'汧','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'涅','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'㶖','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚­','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','㺸'=>'㺸','瑇'=>'瑇','瑜'=>'ç‘œ','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'ç“Š','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'ç¡Ž','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'秫','䄯'=>'䄯','穀'=>'ç©€','穊'=>'ç©Š','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'䊠','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','䌁'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'莭','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','𦼬'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'虧','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'𧙧','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'𧢮','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'誠','ð¯§'=>'è«­','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð  „','跋'=>'è·‹','趼'=>'趼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'𨗭','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','𨯺'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'嶲','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'䩶','韠'=>'韠','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'駂','駾'=>'駾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³­','ð¯¨'=>'鵧','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀');
diff --git a/phpBB/includes/utf/data/utf_nfc_qc.php b/phpBB/includes/utf/data/utf_nfc_qc.php
deleted file mode 100644
index ff56357ea6..0000000000
--- a/phpBB/includes/utf/data/utf_nfc_qc.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$GLOBALS['utf_nfc_qc']=array('Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,';'=>1,'·'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'ড়'=>1,'à§'=>1,'য়'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'à©š'=>1,'à©›'=>1,'à©ž'=>1,'à­œ'=>1,'à­'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ླྀ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾¾'=>1,'Έ'=>1,'á¿‹'=>1,'á¿“'=>1,'á¿›'=>1,'á¿£'=>1,'á¿«'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,' '=>1,'â€'=>1,'Ω'=>1,'K'=>1,'â„«'=>1,'〈'=>1,'〉'=>1,'â«œ'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'鸞'=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'來'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'怒'=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'省'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'裂'=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'玲'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'燎'=>1,'ï§'=>1,'蓼'=>1,'遼'=>1,'龍'=>1,'暈'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'流'=>1,'溜'=>1,'琉'=>1,'ï§'=>1,'硫'=>1,'ï§'=>1,'ï§'=>1,'六'=>1,'戮'=>1,'陸'=>1,'倫'=>1,'崙'=>1,'淪'=>1,'輪'=>1,'律'=>1,'慄'=>1,'栗'=>1,'率'=>1,'隆'=>1,'ï§'=>1,'吏'=>1,'履'=>1,'易'=>1,'李'=>1,'梨'=>1,'泥'=>1,'理'=>1,'痢'=>1,'罹'=>1,'裏'=>1,'裡'=>1,'里'=>1,'離'=>1,'匿'=>1,'溺'=>1,'吝'=>1,'燐'=>1,'璘'=>1,'藺'=>1,'隣'=>1,'鱗'=>1,'麟'=>1,'林'=>1,'淋'=>1,'臨'=>1,'立'=>1,'笠'=>1,'粒'=>1,'狀'=>1,'炙'=>1,'識'=>1,'什'=>1,'茶'=>1,'刺'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'蘒'=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'鶴'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'ï©Š'=>1,'ï©‹'=>1,'ï©Œ'=>1,'ï©'=>1,'ï©Ž'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'ï©š'=>1,'ï©›'=>1,'ï©œ'=>1,'ï©'=>1,'ï©ž'=>1,'ï©Ÿ'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'逸'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'勇'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'猪'=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'節'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'ï«Š'=>1,'ï«‹'=>1,'ï«Œ'=>1,'ï«'=>1,'ï«Ž'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ï¬'=>1,'ײַ'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'שּׂ'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï­€'=>1,'ï­'=>1,'ï­ƒ'=>1,'ï­„'=>1,'ï­†'=>1,'ï­‡'=>1,'ï­ˆ'=>1,'ï­‰'=>1,'ï­Š'=>1,'ï­‹'=>1,'ï­Œ'=>1,'ï­'=>1,'ï­Ž'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'刻'=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'卑'=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'寃'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'憤'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'櫛'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'㺸'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'䌁'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'𦼬'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'𨯺'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>0,'Ì'=>0,'Ì‚'=>0,'̃'=>0,'Ì„'=>0,'̆'=>0,'̇'=>0,'̈'=>0,'̉'=>0,'ÌŠ'=>0,'Ì‹'=>0,'ÌŒ'=>0,'Ì'=>0,'Ì‘'=>0,'Ì“'=>0,'Ì”'=>0,'Ì›'=>0,'Ì£'=>0,'̤'=>0,'Ì¥'=>0,'̦'=>0,'̧'=>0,'̨'=>0,'Ì­'=>0,'Ì®'=>0,'Ì°'=>0,'̱'=>0,'̸'=>0,'Í‚'=>0,'Í…'=>0,'Ù“'=>0,'Ù”'=>0,'Ù•'=>0,'़'=>0,'া'=>0,'ৗ'=>0,'ା'=>0,'à­–'=>0,'à­—'=>0,'ா'=>0,'ௗ'=>0,'à±–'=>0,'ೂ'=>0,'ೕ'=>0,'à³–'=>0,'à´¾'=>0,'ൗ'=>0,'à·Š'=>0,'à·'=>0,'à·Ÿ'=>0,'ီ'=>0,'á…¡'=>0,'á…¢'=>0,'á…£'=>0,'á…¤'=>0,'á…¥'=>0,'á…¦'=>0,'á…§'=>0,'á…¨'=>0,'á…©'=>0,'á…ª'=>0,'á…«'=>0,'á…¬'=>0,'á…­'=>0,'á…®'=>0,'á…¯'=>0,'á…°'=>0,'á…±'=>0,'á…²'=>0,'á…³'=>0,'á…´'=>0,'á…µ'=>0,'ᆨ'=>0,'ᆩ'=>0,'ᆪ'=>0,'ᆫ'=>0,'ᆬ'=>0,'ᆭ'=>0,'ᆮ'=>0,'ᆯ'=>0,'ᆰ'=>0,'ᆱ'=>0,'ᆲ'=>0,'ᆳ'=>0,'ᆴ'=>0,'ᆵ'=>0,'ᆶ'=>0,'ᆷ'=>0,'ᆸ'=>0,'ᆹ'=>0,'ᆺ'=>0,'ᆻ'=>0,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'ã‚š'=>0);
diff --git a/phpBB/includes/utf/data/utf_nfkc_qc.php b/phpBB/includes/utf/data/utf_nfkc_qc.php
deleted file mode 100644
index 181a07b351..0000000000
--- a/phpBB/includes/utf/data/utf_nfkc_qc.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$GLOBALS['utf_nfkc_qc']=array(' '=>1,'¨'=>1,'ª'=>1,'¯'=>1,'²'=>1,'³'=>1,'´'=>1,'µ'=>1,'¸'=>1,'¹'=>1,'º'=>1,'¼'=>1,'½'=>1,'¾'=>1,'IJ'=>1,'ij'=>1,'Ä¿'=>1,'Å€'=>1,'ʼn'=>1,'Å¿'=>1,'Ç„'=>1,'Ç…'=>1,'dž'=>1,'LJ'=>1,'Lj'=>1,'lj'=>1,'ÇŠ'=>1,'Ç‹'=>1,'ÇŒ'=>1,'DZ'=>1,'Dz'=>1,'dz'=>1,'Ê°'=>1,'ʱ'=>1,'ʲ'=>1,'ʳ'=>1,'Ê´'=>1,'ʵ'=>1,'ʶ'=>1,'Ê·'=>1,'ʸ'=>1,'˘'=>1,'Ë™'=>1,'Ëš'=>1,'Ë›'=>1,'Ëœ'=>1,'Ë'=>1,'Ë '=>1,'Ë¡'=>1,'Ë¢'=>1,'Ë£'=>1,'ˤ'=>1,'Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,'ͺ'=>1,';'=>1,'΄'=>1,'Î…'=>1,'·'=>1,'Ï'=>1,'Ï‘'=>1,'Ï’'=>1,'Ï“'=>1,'Ï”'=>1,'Ï•'=>1,'Ï–'=>1,'Ï°'=>1,'ϱ'=>1,'ϲ'=>1,'Ï´'=>1,'ϵ'=>1,'Ϲ'=>1,'Ö‡'=>1,'Ùµ'=>1,'Ù¶'=>1,'Ù·'=>1,'Ù¸'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'ড়'=>1,'à§'=>1,'য়'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'à©š'=>1,'à©›'=>1,'à©ž'=>1,'à­œ'=>1,'à­'=>1,'ำ'=>1,'ຳ'=>1,'ໜ'=>1,'à»'=>1,'༌'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ཷ'=>1,'ླྀ'=>1,'ཹ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'ჼ'=>1,'á´¬'=>1,'á´­'=>1,'á´®'=>1,'á´°'=>1,'á´±'=>1,'á´²'=>1,'á´³'=>1,'á´´'=>1,'á´µ'=>1,'á´¶'=>1,'á´·'=>1,'á´¸'=>1,'á´¹'=>1,'á´º'=>1,'á´¼'=>1,'á´½'=>1,'á´¾'=>1,'á´¿'=>1,'áµ€'=>1,'áµ'=>1,'ᵂ'=>1,'ᵃ'=>1,'ᵄ'=>1,'áµ…'=>1,'ᵆ'=>1,'ᵇ'=>1,'ᵈ'=>1,'ᵉ'=>1,'ᵊ'=>1,'ᵋ'=>1,'ᵌ'=>1,'áµ'=>1,'áµ'=>1,'áµ'=>1,'ᵑ'=>1,'áµ’'=>1,'ᵓ'=>1,'áµ”'=>1,'ᵕ'=>1,'áµ–'=>1,'áµ—'=>1,'ᵘ'=>1,'áµ™'=>1,'ᵚ'=>1,'áµ›'=>1,'ᵜ'=>1,'áµ'=>1,'ᵞ'=>1,'ᵟ'=>1,'áµ '=>1,'ᵡ'=>1,'áµ¢'=>1,'áµ£'=>1,'ᵤ'=>1,'áµ¥'=>1,'ᵦ'=>1,'ᵧ'=>1,'ᵨ'=>1,'ᵩ'=>1,'ᵪ'=>1,'ᵸ'=>1,'ᶛ'=>1,'ᶜ'=>1,'á¶'=>1,'ᶞ'=>1,'ᶟ'=>1,'ᶠ'=>1,'ᶡ'=>1,'ᶢ'=>1,'ᶣ'=>1,'ᶤ'=>1,'ᶥ'=>1,'ᶦ'=>1,'ᶧ'=>1,'ᶨ'=>1,'ᶩ'=>1,'ᶪ'=>1,'ᶫ'=>1,'ᶬ'=>1,'ᶭ'=>1,'ᶮ'=>1,'ᶯ'=>1,'ᶰ'=>1,'ᶱ'=>1,'ᶲ'=>1,'ᶳ'=>1,'ᶴ'=>1,'ᶵ'=>1,'ᶶ'=>1,'ᶷ'=>1,'ᶸ'=>1,'ᶹ'=>1,'ᶺ'=>1,'ᶻ'=>1,'ᶼ'=>1,'ᶽ'=>1,'ᶾ'=>1,'ᶿ'=>1,'ẚ'=>1,'ẛ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾½'=>1,'á¾¾'=>1,'᾿'=>1,'á¿€'=>1,'á¿'=>1,'Έ'=>1,'á¿‹'=>1,'á¿'=>1,'á¿Ž'=>1,'á¿'=>1,'á¿“'=>1,'á¿›'=>1,'á¿'=>1,'á¿ž'=>1,'á¿Ÿ'=>1,'á¿£'=>1,'á¿«'=>1,'á¿­'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,'῾'=>1,' '=>1,'â€'=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,'‑'=>1,'‗'=>1,'․'=>1,'‥'=>1,'…'=>1,' '=>1,'″'=>1,'‴'=>1,'‶'=>1,'‷'=>1,'‼'=>1,'‾'=>1,'â‡'=>1,'âˆ'=>1,'â‰'=>1,'â—'=>1,'âŸ'=>1,'â°'=>1,'â±'=>1,'â´'=>1,'âµ'=>1,'â¶'=>1,'â·'=>1,'â¸'=>1,'â¹'=>1,'âº'=>1,'â»'=>1,'â¼'=>1,'â½'=>1,'â¾'=>1,'â¿'=>1,'â‚€'=>1,'â‚'=>1,'â‚‚'=>1,'₃'=>1,'â‚„'=>1,'â‚…'=>1,'₆'=>1,'₇'=>1,'₈'=>1,'₉'=>1,'â‚Š'=>1,'â‚‹'=>1,'â‚Œ'=>1,'â‚'=>1,'â‚Ž'=>1,'â‚'=>1,'â‚‘'=>1,'â‚’'=>1,'â‚“'=>1,'â‚”'=>1,'₨'=>1,'â„€'=>1,'â„'=>1,'â„‚'=>1,'℃'=>1,'â„…'=>1,'℆'=>1,'ℇ'=>1,'℉'=>1,'â„Š'=>1,'â„‹'=>1,'â„Œ'=>1,'â„'=>1,'â„Ž'=>1,'â„'=>1,'â„'=>1,'â„‘'=>1,'â„’'=>1,'â„“'=>1,'â„•'=>1,'â„–'=>1,'â„™'=>1,'â„š'=>1,'â„›'=>1,'â„œ'=>1,'â„'=>1,'â„ '=>1,'â„¡'=>1,'â„¢'=>1,'ℤ'=>1,'Ω'=>1,'ℨ'=>1,'K'=>1,'â„«'=>1,'ℬ'=>1,'â„­'=>1,'ℯ'=>1,'â„°'=>1,'ℱ'=>1,'ℳ'=>1,'â„´'=>1,'ℵ'=>1,'ℶ'=>1,'â„·'=>1,'ℸ'=>1,'ℹ'=>1,'â„»'=>1,'ℼ'=>1,'ℽ'=>1,'ℾ'=>1,'â„¿'=>1,'â…€'=>1,'â……'=>1,'â…†'=>1,'â…‡'=>1,'â…ˆ'=>1,'â…‰'=>1,'â…“'=>1,'â…”'=>1,'â…•'=>1,'â…–'=>1,'â…—'=>1,'â…˜'=>1,'â…™'=>1,'â…š'=>1,'â…›'=>1,'â…œ'=>1,'â…'=>1,'â…ž'=>1,'â…Ÿ'=>1,'â… '=>1,'â…¡'=>1,'â…¢'=>1,'â…£'=>1,'â…¤'=>1,'â…¥'=>1,'â…¦'=>1,'â…§'=>1,'â…¨'=>1,'â…©'=>1,'â…ª'=>1,'â…«'=>1,'â…¬'=>1,'â…­'=>1,'â…®'=>1,'â…¯'=>1,'â…°'=>1,'â…±'=>1,'â…²'=>1,'â…³'=>1,'â…´'=>1,'â…µ'=>1,'â…¶'=>1,'â…·'=>1,'â…¸'=>1,'â…¹'=>1,'â…º'=>1,'â…»'=>1,'â…¼'=>1,'â…½'=>1,'â…¾'=>1,'â…¿'=>1,'∬'=>1,'∭'=>1,'∯'=>1,'∰'=>1,'〈'=>1,'〉'=>1,'â‘ '=>1,'â‘¡'=>1,'â‘¢'=>1,'â‘£'=>1,'⑤'=>1,'â‘¥'=>1,'⑦'=>1,'⑧'=>1,'⑨'=>1,'â‘©'=>1,'⑪'=>1,'â‘«'=>1,'⑬'=>1,'â‘­'=>1,'â‘®'=>1,'⑯'=>1,'â‘°'=>1,'⑱'=>1,'⑲'=>1,'⑳'=>1,'â‘´'=>1,'⑵'=>1,'⑶'=>1,'â‘·'=>1,'⑸'=>1,'⑹'=>1,'⑺'=>1,'â‘»'=>1,'⑼'=>1,'⑽'=>1,'⑾'=>1,'â‘¿'=>1,'â’€'=>1,'â’'=>1,'â’‚'=>1,'â’ƒ'=>1,'â’„'=>1,'â’…'=>1,'â’†'=>1,'â’‡'=>1,'â’ˆ'=>1,'â’‰'=>1,'â’Š'=>1,'â’‹'=>1,'â’Œ'=>1,'â’'=>1,'â’Ž'=>1,'â’'=>1,'â’'=>1,'â’‘'=>1,'â’’'=>1,'â’“'=>1,'â’”'=>1,'â’•'=>1,'â’–'=>1,'â’—'=>1,'â’˜'=>1,'â’™'=>1,'â’š'=>1,'â’›'=>1,'â’œ'=>1,'â’'=>1,'â’ž'=>1,'â’Ÿ'=>1,'â’ '=>1,'â’¡'=>1,'â’¢'=>1,'â’£'=>1,'â’¤'=>1,'â’¥'=>1,'â’¦'=>1,'â’§'=>1,'â’¨'=>1,'â’©'=>1,'â’ª'=>1,'â’«'=>1,'â’¬'=>1,'â’­'=>1,'â’®'=>1,'â’¯'=>1,'â’°'=>1,'â’±'=>1,'â’²'=>1,'â’³'=>1,'â’´'=>1,'â’µ'=>1,'â’¶'=>1,'â’·'=>1,'â’¸'=>1,'â’¹'=>1,'â’º'=>1,'â’»'=>1,'â’¼'=>1,'â’½'=>1,'â’¾'=>1,'â’¿'=>1,'â“€'=>1,'â“'=>1,'â“‚'=>1,'Ⓝ'=>1,'â“„'=>1,'â“…'=>1,'Ⓠ'=>1,'Ⓡ'=>1,'Ⓢ'=>1,'Ⓣ'=>1,'â“Š'=>1,'â“‹'=>1,'â“Œ'=>1,'â“'=>1,'â“Ž'=>1,'â“'=>1,'â“'=>1,'â“‘'=>1,'â“’'=>1,'â““'=>1,'â“”'=>1,'â“•'=>1,'â“–'=>1,'â“—'=>1,'ⓘ'=>1,'â“™'=>1,'â“š'=>1,'â“›'=>1,'â“œ'=>1,'â“'=>1,'â“ž'=>1,'â“Ÿ'=>1,'â“ '=>1,'â“¡'=>1,'â“¢'=>1,'â“£'=>1,'ⓤ'=>1,'â“¥'=>1,'ⓦ'=>1,'ⓧ'=>1,'ⓨ'=>1,'â“©'=>1,'⓪'=>1,'⨌'=>1,'â©´'=>1,'⩵'=>1,'⩶'=>1,'â«œ'=>1,'ⵯ'=>1,'⺟'=>1,'⻳'=>1,'â¼€'=>1,'â¼'=>1,'⼂'=>1,'⼃'=>1,'⼄'=>1,'â¼…'=>1,'⼆'=>1,'⼇'=>1,'⼈'=>1,'⼉'=>1,'⼊'=>1,'⼋'=>1,'⼌'=>1,'â¼'=>1,'⼎'=>1,'â¼'=>1,'â¼'=>1,'⼑'=>1,'â¼’'=>1,'⼓'=>1,'â¼”'=>1,'⼕'=>1,'â¼–'=>1,'â¼—'=>1,'⼘'=>1,'â¼™'=>1,'⼚'=>1,'â¼›'=>1,'⼜'=>1,'â¼'=>1,'⼞'=>1,'⼟'=>1,'â¼ '=>1,'⼡'=>1,'â¼¢'=>1,'â¼£'=>1,'⼤'=>1,'â¼¥'=>1,'⼦'=>1,'⼧'=>1,'⼨'=>1,'⼩'=>1,'⼪'=>1,'⼫'=>1,'⼬'=>1,'â¼­'=>1,'â¼®'=>1,'⼯'=>1,'â¼°'=>1,'â¼±'=>1,'â¼²'=>1,'â¼³'=>1,'â¼´'=>1,'â¼µ'=>1,'⼶'=>1,'â¼·'=>1,'⼸'=>1,'â¼¹'=>1,'⼺'=>1,'â¼»'=>1,'â¼¼'=>1,'â¼½'=>1,'â¼¾'=>1,'⼿'=>1,'â½€'=>1,'â½'=>1,'⽂'=>1,'⽃'=>1,'⽄'=>1,'â½…'=>1,'⽆'=>1,'⽇'=>1,'⽈'=>1,'⽉'=>1,'⽊'=>1,'⽋'=>1,'⽌'=>1,'â½'=>1,'⽎'=>1,'â½'=>1,'â½'=>1,'⽑'=>1,'â½’'=>1,'⽓'=>1,'â½”'=>1,'⽕'=>1,'â½–'=>1,'â½—'=>1,'⽘'=>1,'â½™'=>1,'⽚'=>1,'â½›'=>1,'⽜'=>1,'â½'=>1,'⽞'=>1,'⽟'=>1,'â½ '=>1,'⽡'=>1,'â½¢'=>1,'â½£'=>1,'⽤'=>1,'â½¥'=>1,'⽦'=>1,'⽧'=>1,'⽨'=>1,'⽩'=>1,'⽪'=>1,'⽫'=>1,'⽬'=>1,'â½­'=>1,'â½®'=>1,'⽯'=>1,'â½°'=>1,'â½±'=>1,'â½²'=>1,'â½³'=>1,'â½´'=>1,'â½µ'=>1,'⽶'=>1,'â½·'=>1,'⽸'=>1,'â½¹'=>1,'⽺'=>1,'â½»'=>1,'â½¼'=>1,'â½½'=>1,'â½¾'=>1,'⽿'=>1,'â¾€'=>1,'â¾'=>1,'⾂'=>1,'⾃'=>1,'⾄'=>1,'â¾…'=>1,'⾆'=>1,'⾇'=>1,'⾈'=>1,'⾉'=>1,'⾊'=>1,'⾋'=>1,'⾌'=>1,'â¾'=>1,'⾎'=>1,'â¾'=>1,'â¾'=>1,'⾑'=>1,'â¾’'=>1,'⾓'=>1,'â¾”'=>1,'⾕'=>1,'â¾–'=>1,'â¾—'=>1,'⾘'=>1,'â¾™'=>1,'⾚'=>1,'â¾›'=>1,'⾜'=>1,'â¾'=>1,'⾞'=>1,'⾟'=>1,'â¾ '=>1,'⾡'=>1,'â¾¢'=>1,'â¾£'=>1,'⾤'=>1,'â¾¥'=>1,'⾦'=>1,'⾧'=>1,'⾨'=>1,'⾩'=>1,'⾪'=>1,'⾫'=>1,'⾬'=>1,'â¾­'=>1,'â¾®'=>1,'⾯'=>1,'â¾°'=>1,'â¾±'=>1,'â¾²'=>1,'â¾³'=>1,'â¾´'=>1,'â¾µ'=>1,'⾶'=>1,'â¾·'=>1,'⾸'=>1,'â¾¹'=>1,'⾺'=>1,'â¾»'=>1,'â¾¼'=>1,'â¾½'=>1,'â¾¾'=>1,'⾿'=>1,'â¿€'=>1,'â¿'=>1,'â¿‚'=>1,'⿃'=>1,'â¿„'=>1,'â¿…'=>1,'⿆'=>1,'⿇'=>1,'⿈'=>1,'⿉'=>1,'â¿Š'=>1,'â¿‹'=>1,'â¿Œ'=>1,'â¿'=>1,'â¿Ž'=>1,'â¿'=>1,'â¿'=>1,'â¿‘'=>1,'â¿’'=>1,'â¿“'=>1,'â¿”'=>1,'â¿•'=>1,' '=>1,'〶'=>1,'〸'=>1,'〹'=>1,'〺'=>1,'ã‚›'=>1,'ã‚œ'=>1,'ã‚Ÿ'=>1,'ヿ'=>1,'ㄱ'=>1,'ㄲ'=>1,'ㄳ'=>1,'ã„´'=>1,'ㄵ'=>1,'ㄶ'=>1,'ã„·'=>1,'ㄸ'=>1,'ㄹ'=>1,'ㄺ'=>1,'ã„»'=>1,'ㄼ'=>1,'ㄽ'=>1,'ㄾ'=>1,'ã„¿'=>1,'ã…€'=>1,'ã…'=>1,'ã…‚'=>1,'ã…ƒ'=>1,'ã…„'=>1,'ã……'=>1,'ã…†'=>1,'ã…‡'=>1,'ã…ˆ'=>1,'ã…‰'=>1,'ã…Š'=>1,'ã…‹'=>1,'ã…Œ'=>1,'ã…'=>1,'ã…Ž'=>1,'ã…'=>1,'ã…'=>1,'ã…‘'=>1,'ã…’'=>1,'ã…“'=>1,'ã…”'=>1,'ã…•'=>1,'ã…–'=>1,'ã…—'=>1,'ã…˜'=>1,'ã…™'=>1,'ã…š'=>1,'ã…›'=>1,'ã…œ'=>1,'ã…'=>1,'ã…ž'=>1,'ã…Ÿ'=>1,'ã… '=>1,'ã…¡'=>1,'ã…¢'=>1,'ã…£'=>1,'ã…¤'=>1,'ã…¥'=>1,'ã…¦'=>1,'ã…§'=>1,'ã…¨'=>1,'ã…©'=>1,'ã…ª'=>1,'ã…«'=>1,'ã…¬'=>1,'ã…­'=>1,'ã…®'=>1,'ã…¯'=>1,'ã…°'=>1,'ã…±'=>1,'ã…²'=>1,'ã…³'=>1,'ã…´'=>1,'ã…µ'=>1,'ã…¶'=>1,'ã…·'=>1,'ã…¸'=>1,'ã…¹'=>1,'ã…º'=>1,'ã…»'=>1,'ã…¼'=>1,'ã…½'=>1,'ã…¾'=>1,'ã…¿'=>1,'ㆀ'=>1,'ã†'=>1,'ㆂ'=>1,'ㆃ'=>1,'ㆄ'=>1,'ㆅ'=>1,'ㆆ'=>1,'ㆇ'=>1,'ㆈ'=>1,'ㆉ'=>1,'ㆊ'=>1,'ㆋ'=>1,'ㆌ'=>1,'ã†'=>1,'ㆎ'=>1,'㆒'=>1,'㆓'=>1,'㆔'=>1,'㆕'=>1,'㆖'=>1,'㆗'=>1,'㆘'=>1,'㆙'=>1,'㆚'=>1,'㆛'=>1,'㆜'=>1,'ã†'=>1,'㆞'=>1,'㆟'=>1,'㈀'=>1,'ãˆ'=>1,'㈂'=>1,'㈃'=>1,'㈄'=>1,'㈅'=>1,'㈆'=>1,'㈇'=>1,'㈈'=>1,'㈉'=>1,'㈊'=>1,'㈋'=>1,'㈌'=>1,'ãˆ'=>1,'㈎'=>1,'ãˆ'=>1,'ãˆ'=>1,'㈑'=>1,'㈒'=>1,'㈓'=>1,'㈔'=>1,'㈕'=>1,'㈖'=>1,'㈗'=>1,'㈘'=>1,'㈙'=>1,'㈚'=>1,'㈛'=>1,'㈜'=>1,'ãˆ'=>1,'㈞'=>1,'㈠'=>1,'㈡'=>1,'㈢'=>1,'㈣'=>1,'㈤'=>1,'㈥'=>1,'㈦'=>1,'㈧'=>1,'㈨'=>1,'㈩'=>1,'㈪'=>1,'㈫'=>1,'㈬'=>1,'㈭'=>1,'㈮'=>1,'㈯'=>1,'㈰'=>1,'㈱'=>1,'㈲'=>1,'㈳'=>1,'㈴'=>1,'㈵'=>1,'㈶'=>1,'㈷'=>1,'㈸'=>1,'㈹'=>1,'㈺'=>1,'㈻'=>1,'㈼'=>1,'㈽'=>1,'㈾'=>1,'㈿'=>1,'㉀'=>1,'ã‰'=>1,'㉂'=>1,'㉃'=>1,'ã‰'=>1,'㉑'=>1,'㉒'=>1,'㉓'=>1,'㉔'=>1,'㉕'=>1,'㉖'=>1,'㉗'=>1,'㉘'=>1,'㉙'=>1,'㉚'=>1,'㉛'=>1,'㉜'=>1,'ã‰'=>1,'㉞'=>1,'㉟'=>1,'㉠'=>1,'㉡'=>1,'㉢'=>1,'㉣'=>1,'㉤'=>1,'㉥'=>1,'㉦'=>1,'㉧'=>1,'㉨'=>1,'㉩'=>1,'㉪'=>1,'㉫'=>1,'㉬'=>1,'㉭'=>1,'㉮'=>1,'㉯'=>1,'㉰'=>1,'㉱'=>1,'㉲'=>1,'㉳'=>1,'㉴'=>1,'㉵'=>1,'㉶'=>1,'㉷'=>1,'㉸'=>1,'㉹'=>1,'㉺'=>1,'㉻'=>1,'㉼'=>1,'㉽'=>1,'㉾'=>1,'㊀'=>1,'ãŠ'=>1,'㊂'=>1,'㊃'=>1,'㊄'=>1,'㊅'=>1,'㊆'=>1,'㊇'=>1,'㊈'=>1,'㊉'=>1,'㊊'=>1,'㊋'=>1,'㊌'=>1,'ãŠ'=>1,'㊎'=>1,'ãŠ'=>1,'ãŠ'=>1,'㊑'=>1,'㊒'=>1,'㊓'=>1,'㊔'=>1,'㊕'=>1,'㊖'=>1,'㊗'=>1,'㊘'=>1,'㊙'=>1,'㊚'=>1,'㊛'=>1,'㊜'=>1,'ãŠ'=>1,'㊞'=>1,'㊟'=>1,'㊠'=>1,'㊡'=>1,'㊢'=>1,'㊣'=>1,'㊤'=>1,'㊥'=>1,'㊦'=>1,'㊧'=>1,'㊨'=>1,'㊩'=>1,'㊪'=>1,'㊫'=>1,'㊬'=>1,'㊭'=>1,'㊮'=>1,'㊯'=>1,'㊰'=>1,'㊱'=>1,'㊲'=>1,'㊳'=>1,'㊴'=>1,'㊵'=>1,'㊶'=>1,'㊷'=>1,'㊸'=>1,'㊹'=>1,'㊺'=>1,'㊻'=>1,'㊼'=>1,'㊽'=>1,'㊾'=>1,'㊿'=>1,'ã‹€'=>1,'ã‹'=>1,'ã‹‚'=>1,'㋃'=>1,'ã‹„'=>1,'ã‹…'=>1,'㋆'=>1,'㋇'=>1,'㋈'=>1,'㋉'=>1,'ã‹Š'=>1,'ã‹‹'=>1,'ã‹Œ'=>1,'ã‹'=>1,'ã‹Ž'=>1,'ã‹'=>1,'ã‹'=>1,'ã‹‘'=>1,'ã‹’'=>1,'ã‹“'=>1,'ã‹”'=>1,'ã‹•'=>1,'ã‹–'=>1,'ã‹—'=>1,'㋘'=>1,'ã‹™'=>1,'ã‹š'=>1,'ã‹›'=>1,'ã‹œ'=>1,'ã‹'=>1,'ã‹ž'=>1,'ã‹Ÿ'=>1,'ã‹ '=>1,'ã‹¡'=>1,'ã‹¢'=>1,'ã‹£'=>1,'㋤'=>1,'ã‹¥'=>1,'㋦'=>1,'㋧'=>1,'㋨'=>1,'ã‹©'=>1,'㋪'=>1,'ã‹«'=>1,'㋬'=>1,'ã‹­'=>1,'ã‹®'=>1,'㋯'=>1,'ã‹°'=>1,'㋱'=>1,'㋲'=>1,'㋳'=>1,'ã‹´'=>1,'㋵'=>1,'㋶'=>1,'ã‹·'=>1,'㋸'=>1,'㋹'=>1,'㋺'=>1,'ã‹»'=>1,'㋼'=>1,'㋽'=>1,'㋾'=>1,'㌀'=>1,'ãŒ'=>1,'㌂'=>1,'㌃'=>1,'㌄'=>1,'㌅'=>1,'㌆'=>1,'㌇'=>1,'㌈'=>1,'㌉'=>1,'㌊'=>1,'㌋'=>1,'㌌'=>1,'ãŒ'=>1,'㌎'=>1,'ãŒ'=>1,'ãŒ'=>1,'㌑'=>1,'㌒'=>1,'㌓'=>1,'㌔'=>1,'㌕'=>1,'㌖'=>1,'㌗'=>1,'㌘'=>1,'㌙'=>1,'㌚'=>1,'㌛'=>1,'㌜'=>1,'ãŒ'=>1,'㌞'=>1,'㌟'=>1,'㌠'=>1,'㌡'=>1,'㌢'=>1,'㌣'=>1,'㌤'=>1,'㌥'=>1,'㌦'=>1,'㌧'=>1,'㌨'=>1,'㌩'=>1,'㌪'=>1,'㌫'=>1,'㌬'=>1,'㌭'=>1,'㌮'=>1,'㌯'=>1,'㌰'=>1,'㌱'=>1,'㌲'=>1,'㌳'=>1,'㌴'=>1,'㌵'=>1,'㌶'=>1,'㌷'=>1,'㌸'=>1,'㌹'=>1,'㌺'=>1,'㌻'=>1,'㌼'=>1,'㌽'=>1,'㌾'=>1,'㌿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã­'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'㎀'=>1,'ãŽ'=>1,'㎂'=>1,'㎃'=>1,'㎄'=>1,'㎅'=>1,'㎆'=>1,'㎇'=>1,'㎈'=>1,'㎉'=>1,'㎊'=>1,'㎋'=>1,'㎌'=>1,'ãŽ'=>1,'㎎'=>1,'ãŽ'=>1,'ãŽ'=>1,'㎑'=>1,'㎒'=>1,'㎓'=>1,'㎔'=>1,'㎕'=>1,'㎖'=>1,'㎗'=>1,'㎘'=>1,'㎙'=>1,'㎚'=>1,'㎛'=>1,'㎜'=>1,'ãŽ'=>1,'㎞'=>1,'㎟'=>1,'㎠'=>1,'㎡'=>1,'㎢'=>1,'㎣'=>1,'㎤'=>1,'㎥'=>1,'㎦'=>1,'㎧'=>1,'㎨'=>1,'㎩'=>1,'㎪'=>1,'㎫'=>1,'㎬'=>1,'㎭'=>1,'㎮'=>1,'㎯'=>1,'㎰'=>1,'㎱'=>1,'㎲'=>1,'㎳'=>1,'㎴'=>1,'㎵'=>1,'㎶'=>1,'㎷'=>1,'㎸'=>1,'㎹'=>1,'㎺'=>1,'㎻'=>1,'㎼'=>1,'㎽'=>1,'㎾'=>1,'㎿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã­'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'鸞'=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'來'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'怒'=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'省'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'裂'=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'玲'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'燎'=>1,'ï§'=>1,'蓼'=>1,'遼'=>1,'龍'=>1,'暈'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'流'=>1,'溜'=>1,'琉'=>1,'ï§'=>1,'硫'=>1,'ï§'=>1,'ï§'=>1,'六'=>1,'戮'=>1,'陸'=>1,'倫'=>1,'崙'=>1,'淪'=>1,'輪'=>1,'律'=>1,'慄'=>1,'栗'=>1,'率'=>1,'隆'=>1,'ï§'=>1,'吏'=>1,'履'=>1,'易'=>1,'李'=>1,'梨'=>1,'泥'=>1,'理'=>1,'痢'=>1,'罹'=>1,'裏'=>1,'裡'=>1,'里'=>1,'離'=>1,'匿'=>1,'溺'=>1,'吝'=>1,'燐'=>1,'璘'=>1,'藺'=>1,'隣'=>1,'鱗'=>1,'麟'=>1,'林'=>1,'淋'=>1,'臨'=>1,'立'=>1,'笠'=>1,'粒'=>1,'狀'=>1,'炙'=>1,'識'=>1,'什'=>1,'茶'=>1,'刺'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'蘒'=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'鶴'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'ï©Š'=>1,'ï©‹'=>1,'ï©Œ'=>1,'ï©'=>1,'ï©Ž'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'ï©š'=>1,'ï©›'=>1,'ï©œ'=>1,'ï©'=>1,'ï©ž'=>1,'ï©Ÿ'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'逸'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'勇'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'猪'=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'節'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'ï«Š'=>1,'ï«‹'=>1,'ï«Œ'=>1,'ï«'=>1,'ï«Ž'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ff'=>1,'ï¬'=>1,'fl'=>1,'ffi'=>1,'ffl'=>1,'ſt'=>1,'st'=>1,'ﬓ'=>1,'ﬔ'=>1,'ﬕ'=>1,'ﬖ'=>1,'ﬗ'=>1,'ï¬'=>1,'ײַ'=>1,'ﬠ'=>1,'ﬡ'=>1,'ﬢ'=>1,'ﬣ'=>1,'ﬤ'=>1,'ﬥ'=>1,'ﬦ'=>1,'ﬧ'=>1,'ﬨ'=>1,'﬩'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'שּׂ'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï­€'=>1,'ï­'=>1,'ï­ƒ'=>1,'ï­„'=>1,'ï­†'=>1,'ï­‡'=>1,'ï­ˆ'=>1,'ï­‰'=>1,'ï­Š'=>1,'ï­‹'=>1,'ï­Œ'=>1,'ï­'=>1,'ï­Ž'=>1,'ï­'=>1,'ï­'=>1,'ï­‘'=>1,'ï­’'=>1,'ï­“'=>1,'ï­”'=>1,'ï­•'=>1,'ï­–'=>1,'ï­—'=>1,'ï­˜'=>1,'ï­™'=>1,'ï­š'=>1,'ï­›'=>1,'ï­œ'=>1,'ï­'=>1,'ï­ž'=>1,'ï­Ÿ'=>1,'ï­ '=>1,'ï­¡'=>1,'ï­¢'=>1,'ï­£'=>1,'ï­¤'=>1,'ï­¥'=>1,'ï­¦'=>1,'ï­§'=>1,'ï­¨'=>1,'ï­©'=>1,'ï­ª'=>1,'ï­«'=>1,'ï­¬'=>1,'ï­­'=>1,'ï­®'=>1,'ï­¯'=>1,'ï­°'=>1,'ï­±'=>1,'ï­²'=>1,'ï­³'=>1,'ï­´'=>1,'ï­µ'=>1,'ï­¶'=>1,'ï­·'=>1,'ï­¸'=>1,'ï­¹'=>1,'ï­º'=>1,'ï­»'=>1,'ï­¼'=>1,'ï­½'=>1,'ï­¾'=>1,'ï­¿'=>1,'ﮀ'=>1,'ï®'=>1,'ﮂ'=>1,'ﮃ'=>1,'ﮄ'=>1,'ï®…'=>1,'ﮆ'=>1,'ﮇ'=>1,'ﮈ'=>1,'ﮉ'=>1,'ﮊ'=>1,'ﮋ'=>1,'ﮌ'=>1,'ï®'=>1,'ﮎ'=>1,'ï®'=>1,'ï®'=>1,'ﮑ'=>1,'ï®’'=>1,'ﮓ'=>1,'ï®”'=>1,'ﮕ'=>1,'ï®–'=>1,'ï®—'=>1,'ﮘ'=>1,'ï®™'=>1,'ﮚ'=>1,'ï®›'=>1,'ﮜ'=>1,'ï®'=>1,'ﮞ'=>1,'ﮟ'=>1,'ï® '=>1,'ﮡ'=>1,'ﮢ'=>1,'ﮣ'=>1,'ﮤ'=>1,'ﮥ'=>1,'ﮦ'=>1,'ﮧ'=>1,'ﮨ'=>1,'ﮩ'=>1,'ﮪ'=>1,'ﮫ'=>1,'ﮬ'=>1,'ï®­'=>1,'ï®®'=>1,'ﮯ'=>1,'ï®°'=>1,'ï®±'=>1,'ﯓ'=>1,'ﯔ'=>1,'ﯕ'=>1,'ﯖ'=>1,'ﯗ'=>1,'ﯘ'=>1,'ﯙ'=>1,'ﯚ'=>1,'ﯛ'=>1,'ﯜ'=>1,'ï¯'=>1,'ﯞ'=>1,'ﯟ'=>1,'ﯠ'=>1,'ﯡ'=>1,'ﯢ'=>1,'ﯣ'=>1,'ﯤ'=>1,'ﯥ'=>1,'ﯦ'=>1,'ﯧ'=>1,'ﯨ'=>1,'ﯩ'=>1,'ﯪ'=>1,'ﯫ'=>1,'ﯬ'=>1,'ﯭ'=>1,'ﯮ'=>1,'ﯯ'=>1,'ﯰ'=>1,'ﯱ'=>1,'ﯲ'=>1,'ﯳ'=>1,'ﯴ'=>1,'ﯵ'=>1,'ﯶ'=>1,'ﯷ'=>1,'ﯸ'=>1,'ﯹ'=>1,'ﯺ'=>1,'ﯻ'=>1,'ﯼ'=>1,'ﯽ'=>1,'ﯾ'=>1,'ﯿ'=>1,'ï°€'=>1,'ï°'=>1,'ï°‚'=>1,'ï°ƒ'=>1,'ï°„'=>1,'ï°…'=>1,'ï°†'=>1,'ï°‡'=>1,'ï°ˆ'=>1,'ï°‰'=>1,'ï°Š'=>1,'ï°‹'=>1,'ï°Œ'=>1,'ï°'=>1,'ï°Ž'=>1,'ï°'=>1,'ï°'=>1,'ï°‘'=>1,'ï°’'=>1,'ï°“'=>1,'ï°”'=>1,'ï°•'=>1,'ï°–'=>1,'ï°—'=>1,'ï°˜'=>1,'ï°™'=>1,'ï°š'=>1,'ï°›'=>1,'ï°œ'=>1,'ï°'=>1,'ï°ž'=>1,'ï°Ÿ'=>1,'ï° '=>1,'ï°¡'=>1,'ï°¢'=>1,'ï°£'=>1,'ï°¤'=>1,'ï°¥'=>1,'ï°¦'=>1,'ï°§'=>1,'ï°¨'=>1,'ï°©'=>1,'ï°ª'=>1,'ï°«'=>1,'ï°¬'=>1,'ï°­'=>1,'ï°®'=>1,'ï°¯'=>1,'ï°°'=>1,'ï°±'=>1,'ï°²'=>1,'ï°³'=>1,'ï°´'=>1,'ï°µ'=>1,'ï°¶'=>1,'ï°·'=>1,'ï°¸'=>1,'ï°¹'=>1,'ï°º'=>1,'ï°»'=>1,'ï°¼'=>1,'ï°½'=>1,'ï°¾'=>1,'ï°¿'=>1,'ï±€'=>1,'ï±'=>1,'ﱂ'=>1,'ﱃ'=>1,'ﱄ'=>1,'ï±…'=>1,'ﱆ'=>1,'ﱇ'=>1,'ﱈ'=>1,'ﱉ'=>1,'ﱊ'=>1,'ﱋ'=>1,'ﱌ'=>1,'ï±'=>1,'ﱎ'=>1,'ï±'=>1,'ï±'=>1,'ﱑ'=>1,'ï±’'=>1,'ﱓ'=>1,'ï±”'=>1,'ﱕ'=>1,'ï±–'=>1,'ï±—'=>1,'ﱘ'=>1,'ï±™'=>1,'ﱚ'=>1,'ï±›'=>1,'ﱜ'=>1,'ï±'=>1,'ﱞ'=>1,'ﱟ'=>1,'ï± '=>1,'ﱡ'=>1,'ï±¢'=>1,'ï±£'=>1,'ﱤ'=>1,'ï±¥'=>1,'ﱦ'=>1,'ﱧ'=>1,'ﱨ'=>1,'ﱩ'=>1,'ﱪ'=>1,'ﱫ'=>1,'ﱬ'=>1,'ï±­'=>1,'ï±®'=>1,'ﱯ'=>1,'ï±°'=>1,'ï±±'=>1,'ï±²'=>1,'ï±³'=>1,'ï±´'=>1,'ï±µ'=>1,'ﱶ'=>1,'ï±·'=>1,'ﱸ'=>1,'ï±¹'=>1,'ﱺ'=>1,'ï±»'=>1,'ï±¼'=>1,'ï±½'=>1,'ï±¾'=>1,'ﱿ'=>1,'ï²€'=>1,'ï²'=>1,'ﲂ'=>1,'ﲃ'=>1,'ﲄ'=>1,'ï²…'=>1,'ﲆ'=>1,'ﲇ'=>1,'ﲈ'=>1,'ﲉ'=>1,'ﲊ'=>1,'ﲋ'=>1,'ﲌ'=>1,'ï²'=>1,'ﲎ'=>1,'ï²'=>1,'ï²'=>1,'ﲑ'=>1,'ï²’'=>1,'ﲓ'=>1,'ï²”'=>1,'ﲕ'=>1,'ï²–'=>1,'ï²—'=>1,'ﲘ'=>1,'ï²™'=>1,'ﲚ'=>1,'ï²›'=>1,'ﲜ'=>1,'ï²'=>1,'ﲞ'=>1,'ﲟ'=>1,'ï² '=>1,'ﲡ'=>1,'ï²¢'=>1,'ï²£'=>1,'ﲤ'=>1,'ï²¥'=>1,'ﲦ'=>1,'ﲧ'=>1,'ﲨ'=>1,'ﲩ'=>1,'ﲪ'=>1,'ﲫ'=>1,'ﲬ'=>1,'ï²­'=>1,'ï²®'=>1,'ﲯ'=>1,'ï²°'=>1,'ï²±'=>1,'ï²²'=>1,'ï²³'=>1,'ï²´'=>1,'ï²µ'=>1,'ﲶ'=>1,'ï²·'=>1,'ﲸ'=>1,'ï²¹'=>1,'ﲺ'=>1,'ï²»'=>1,'ï²¼'=>1,'ï²½'=>1,'ï²¾'=>1,'ﲿ'=>1,'ï³€'=>1,'ï³'=>1,'ﳂ'=>1,'ﳃ'=>1,'ﳄ'=>1,'ï³…'=>1,'ﳆ'=>1,'ﳇ'=>1,'ﳈ'=>1,'ﳉ'=>1,'ﳊ'=>1,'ﳋ'=>1,'ﳌ'=>1,'ï³'=>1,'ﳎ'=>1,'ï³'=>1,'ï³'=>1,'ﳑ'=>1,'ï³’'=>1,'ﳓ'=>1,'ï³”'=>1,'ﳕ'=>1,'ï³–'=>1,'ï³—'=>1,'ﳘ'=>1,'ï³™'=>1,'ﳚ'=>1,'ï³›'=>1,'ﳜ'=>1,'ï³'=>1,'ﳞ'=>1,'ﳟ'=>1,'ï³ '=>1,'ﳡ'=>1,'ï³¢'=>1,'ï³£'=>1,'ﳤ'=>1,'ï³¥'=>1,'ﳦ'=>1,'ﳧ'=>1,'ﳨ'=>1,'ﳩ'=>1,'ﳪ'=>1,'ﳫ'=>1,'ﳬ'=>1,'ï³­'=>1,'ï³®'=>1,'ﳯ'=>1,'ï³°'=>1,'ï³±'=>1,'ï³²'=>1,'ï³³'=>1,'ï³´'=>1,'ï³µ'=>1,'ﳶ'=>1,'ï³·'=>1,'ﳸ'=>1,'ï³¹'=>1,'ﳺ'=>1,'ï³»'=>1,'ï³¼'=>1,'ï³½'=>1,'ï³¾'=>1,'ﳿ'=>1,'ï´€'=>1,'ï´'=>1,'ï´‚'=>1,'ï´ƒ'=>1,'ï´„'=>1,'ï´…'=>1,'ï´†'=>1,'ï´‡'=>1,'ï´ˆ'=>1,'ï´‰'=>1,'ï´Š'=>1,'ï´‹'=>1,'ï´Œ'=>1,'ï´'=>1,'ï´Ž'=>1,'ï´'=>1,'ï´'=>1,'ï´‘'=>1,'ï´’'=>1,'ï´“'=>1,'ï´”'=>1,'ï´•'=>1,'ï´–'=>1,'ï´—'=>1,'ï´˜'=>1,'ï´™'=>1,'ï´š'=>1,'ï´›'=>1,'ï´œ'=>1,'ï´'=>1,'ï´ž'=>1,'ï´Ÿ'=>1,'ï´ '=>1,'ï´¡'=>1,'ï´¢'=>1,'ï´£'=>1,'ï´¤'=>1,'ï´¥'=>1,'ï´¦'=>1,'ï´§'=>1,'ï´¨'=>1,'ï´©'=>1,'ï´ª'=>1,'ï´«'=>1,'ï´¬'=>1,'ï´­'=>1,'ï´®'=>1,'ï´¯'=>1,'ï´°'=>1,'ï´±'=>1,'ï´²'=>1,'ï´³'=>1,'ï´´'=>1,'ï´µ'=>1,'ï´¶'=>1,'ï´·'=>1,'ï´¸'=>1,'ï´¹'=>1,'ï´º'=>1,'ï´»'=>1,'ï´¼'=>1,'ï´½'=>1,'ïµ'=>1,'ﵑ'=>1,'ïµ’'=>1,'ﵓ'=>1,'ïµ”'=>1,'ﵕ'=>1,'ïµ–'=>1,'ïµ—'=>1,'ﵘ'=>1,'ïµ™'=>1,'ﵚ'=>1,'ïµ›'=>1,'ﵜ'=>1,'ïµ'=>1,'ﵞ'=>1,'ﵟ'=>1,'ïµ '=>1,'ﵡ'=>1,'ïµ¢'=>1,'ïµ£'=>1,'ﵤ'=>1,'ïµ¥'=>1,'ﵦ'=>1,'ﵧ'=>1,'ﵨ'=>1,'ﵩ'=>1,'ﵪ'=>1,'ﵫ'=>1,'ﵬ'=>1,'ïµ­'=>1,'ïµ®'=>1,'ﵯ'=>1,'ïµ°'=>1,'ïµ±'=>1,'ïµ²'=>1,'ïµ³'=>1,'ïµ´'=>1,'ïµµ'=>1,'ﵶ'=>1,'ïµ·'=>1,'ﵸ'=>1,'ïµ¹'=>1,'ﵺ'=>1,'ïµ»'=>1,'ïµ¼'=>1,'ïµ½'=>1,'ïµ¾'=>1,'ﵿ'=>1,'ﶀ'=>1,'ï¶'=>1,'ﶂ'=>1,'ﶃ'=>1,'ﶄ'=>1,'ﶅ'=>1,'ﶆ'=>1,'ﶇ'=>1,'ﶈ'=>1,'ﶉ'=>1,'ﶊ'=>1,'ﶋ'=>1,'ﶌ'=>1,'ï¶'=>1,'ﶎ'=>1,'ï¶'=>1,'ﶒ'=>1,'ﶓ'=>1,'ﶔ'=>1,'ﶕ'=>1,'ﶖ'=>1,'ﶗ'=>1,'ﶘ'=>1,'ﶙ'=>1,'ﶚ'=>1,'ﶛ'=>1,'ﶜ'=>1,'ï¶'=>1,'ﶞ'=>1,'ﶟ'=>1,'ﶠ'=>1,'ﶡ'=>1,'ﶢ'=>1,'ﶣ'=>1,'ﶤ'=>1,'ﶥ'=>1,'ﶦ'=>1,'ﶧ'=>1,'ﶨ'=>1,'ﶩ'=>1,'ﶪ'=>1,'ﶫ'=>1,'ﶬ'=>1,'ﶭ'=>1,'ﶮ'=>1,'ﶯ'=>1,'ﶰ'=>1,'ﶱ'=>1,'ﶲ'=>1,'ﶳ'=>1,'ﶴ'=>1,'ﶵ'=>1,'ﶶ'=>1,'ﶷ'=>1,'ﶸ'=>1,'ﶹ'=>1,'ﶺ'=>1,'ﶻ'=>1,'ﶼ'=>1,'ﶽ'=>1,'ﶾ'=>1,'ﶿ'=>1,'ï·€'=>1,'ï·'=>1,'ï·‚'=>1,'ï·ƒ'=>1,'ï·„'=>1,'ï·…'=>1,'ï·†'=>1,'ï·‡'=>1,'ï·°'=>1,'ï·±'=>1,'ï·²'=>1,'ï·³'=>1,'ï·´'=>1,'ï·µ'=>1,'ï·¶'=>1,'ï··'=>1,'ï·¸'=>1,'ï·¹'=>1,'ï·º'=>1,'ï·»'=>1,'ï·¼'=>1,'ï¸'=>1,'︑'=>1,'︒'=>1,'︓'=>1,'︔'=>1,'︕'=>1,'︖'=>1,'︗'=>1,'︘'=>1,'︙'=>1,'︰'=>1,'︱'=>1,'︲'=>1,'︳'=>1,'︴'=>1,'︵'=>1,'︶'=>1,'︷'=>1,'︸'=>1,'︹'=>1,'︺'=>1,'︻'=>1,'︼'=>1,'︽'=>1,'︾'=>1,'︿'=>1,'ï¹€'=>1,'ï¹'=>1,'﹂'=>1,'﹃'=>1,'﹄'=>1,'﹇'=>1,'﹈'=>1,'﹉'=>1,'﹊'=>1,'﹋'=>1,'﹌'=>1,'ï¹'=>1,'﹎'=>1,'ï¹'=>1,'ï¹'=>1,'﹑'=>1,'ï¹’'=>1,'ï¹”'=>1,'﹕'=>1,'ï¹–'=>1,'ï¹—'=>1,'﹘'=>1,'ï¹™'=>1,'﹚'=>1,'ï¹›'=>1,'﹜'=>1,'ï¹'=>1,'﹞'=>1,'﹟'=>1,'ï¹ '=>1,'﹡'=>1,'ï¹¢'=>1,'ï¹£'=>1,'﹤'=>1,'ï¹¥'=>1,'﹦'=>1,'﹨'=>1,'﹩'=>1,'﹪'=>1,'﹫'=>1,'ï¹°'=>1,'ï¹±'=>1,'ï¹²'=>1,'ï¹´'=>1,'ﹶ'=>1,'ï¹·'=>1,'ﹸ'=>1,'ï¹¹'=>1,'ﹺ'=>1,'ï¹»'=>1,'ï¹¼'=>1,'ï¹½'=>1,'ï¹¾'=>1,'ﹿ'=>1,'ﺀ'=>1,'ïº'=>1,'ﺂ'=>1,'ﺃ'=>1,'ﺄ'=>1,'ﺅ'=>1,'ﺆ'=>1,'ﺇ'=>1,'ﺈ'=>1,'ﺉ'=>1,'ﺊ'=>1,'ﺋ'=>1,'ﺌ'=>1,'ïº'=>1,'ﺎ'=>1,'ïº'=>1,'ïº'=>1,'ﺑ'=>1,'ﺒ'=>1,'ﺓ'=>1,'ﺔ'=>1,'ﺕ'=>1,'ﺖ'=>1,'ﺗ'=>1,'ﺘ'=>1,'ﺙ'=>1,'ﺚ'=>1,'ﺛ'=>1,'ﺜ'=>1,'ïº'=>1,'ﺞ'=>1,'ﺟ'=>1,'ﺠ'=>1,'ﺡ'=>1,'ﺢ'=>1,'ﺣ'=>1,'ﺤ'=>1,'ﺥ'=>1,'ﺦ'=>1,'ﺧ'=>1,'ﺨ'=>1,'ﺩ'=>1,'ﺪ'=>1,'ﺫ'=>1,'ﺬ'=>1,'ﺭ'=>1,'ﺮ'=>1,'ﺯ'=>1,'ﺰ'=>1,'ﺱ'=>1,'ﺲ'=>1,'ﺳ'=>1,'ﺴ'=>1,'ﺵ'=>1,'ﺶ'=>1,'ﺷ'=>1,'ﺸ'=>1,'ﺹ'=>1,'ﺺ'=>1,'ﺻ'=>1,'ﺼ'=>1,'ﺽ'=>1,'ﺾ'=>1,'ﺿ'=>1,'ﻀ'=>1,'ï»'=>1,'ﻂ'=>1,'ﻃ'=>1,'ﻄ'=>1,'ï»…'=>1,'ﻆ'=>1,'ﻇ'=>1,'ﻈ'=>1,'ﻉ'=>1,'ﻊ'=>1,'ﻋ'=>1,'ﻌ'=>1,'ï»'=>1,'ﻎ'=>1,'ï»'=>1,'ï»'=>1,'ﻑ'=>1,'ï»’'=>1,'ﻓ'=>1,'ï»”'=>1,'ﻕ'=>1,'ï»–'=>1,'ï»—'=>1,'ﻘ'=>1,'ï»™'=>1,'ﻚ'=>1,'ï»›'=>1,'ﻜ'=>1,'ï»'=>1,'ﻞ'=>1,'ﻟ'=>1,'ï» '=>1,'ﻡ'=>1,'ﻢ'=>1,'ﻣ'=>1,'ﻤ'=>1,'ﻥ'=>1,'ﻦ'=>1,'ﻧ'=>1,'ﻨ'=>1,'ﻩ'=>1,'ﻪ'=>1,'ﻫ'=>1,'ﻬ'=>1,'ï»­'=>1,'ï»®'=>1,'ﻯ'=>1,'ï»°'=>1,'ï»±'=>1,'ﻲ'=>1,'ﻳ'=>1,'ï»´'=>1,'ﻵ'=>1,'ﻶ'=>1,'ï»·'=>1,'ﻸ'=>1,'ﻹ'=>1,'ﻺ'=>1,'ï»»'=>1,'ﻼ'=>1,'ï¼'=>1,'"'=>1,'#'=>1,'$'=>1,'ï¼…'=>1,'&'=>1,'''=>1,'('=>1,')'=>1,'*'=>1,'+'=>1,','=>1,'ï¼'=>1,'.'=>1,'ï¼'=>1,'ï¼'=>1,'1'=>1,'ï¼’'=>1,'3'=>1,'ï¼”'=>1,'5'=>1,'ï¼–'=>1,'ï¼—'=>1,'8'=>1,'ï¼™'=>1,':'=>1,'ï¼›'=>1,'<'=>1,'ï¼'=>1,'>'=>1,'?'=>1,'ï¼ '=>1,'A'=>1,'ï¼¢'=>1,'ï¼£'=>1,'D'=>1,'ï¼¥'=>1,'F'=>1,'G'=>1,'H'=>1,'I'=>1,'J'=>1,'K'=>1,'L'=>1,'ï¼­'=>1,'ï¼®'=>1,'O'=>1,'ï¼°'=>1,'ï¼±'=>1,'ï¼²'=>1,'ï¼³'=>1,'ï¼´'=>1,'ï¼µ'=>1,'V'=>1,'ï¼·'=>1,'X'=>1,'ï¼¹'=>1,'Z'=>1,'ï¼»'=>1,'ï¼¼'=>1,'ï¼½'=>1,'ï¼¾'=>1,'_'=>1,'ï½€'=>1,'ï½'=>1,'b'=>1,'c'=>1,'d'=>1,'ï½…'=>1,'f'=>1,'g'=>1,'h'=>1,'i'=>1,'j'=>1,'k'=>1,'l'=>1,'ï½'=>1,'n'=>1,'ï½'=>1,'ï½'=>1,'q'=>1,'ï½’'=>1,'s'=>1,'ï½”'=>1,'u'=>1,'ï½–'=>1,'ï½—'=>1,'x'=>1,'ï½™'=>1,'z'=>1,'ï½›'=>1,'|'=>1,'ï½'=>1,'~'=>1,'⦅'=>1,'ï½ '=>1,'。'=>1,'ï½¢'=>1,'ï½£'=>1,'、'=>1,'ï½¥'=>1,'ヲ'=>1,'ァ'=>1,'ィ'=>1,'ゥ'=>1,'ェ'=>1,'ォ'=>1,'ャ'=>1,'ï½­'=>1,'ï½®'=>1,'ッ'=>1,'ï½°'=>1,'ï½±'=>1,'ï½²'=>1,'ï½³'=>1,'ï½´'=>1,'ï½µ'=>1,'カ'=>1,'ï½·'=>1,'ク'=>1,'ï½¹'=>1,'コ'=>1,'ï½»'=>1,'ï½¼'=>1,'ï½½'=>1,'ï½¾'=>1,'ソ'=>1,'ï¾€'=>1,'ï¾'=>1,'ツ'=>1,'テ'=>1,'ト'=>1,'ï¾…'=>1,'ニ'=>1,'ヌ'=>1,'ネ'=>1,'ノ'=>1,'ハ'=>1,'ヒ'=>1,'フ'=>1,'ï¾'=>1,'ホ'=>1,'ï¾'=>1,'ï¾'=>1,'ム'=>1,'ï¾’'=>1,'モ'=>1,'ï¾”'=>1,'ユ'=>1,'ï¾–'=>1,'ï¾—'=>1,'リ'=>1,'ï¾™'=>1,'レ'=>1,'ï¾›'=>1,'ワ'=>1,'ï¾'=>1,'゙'=>1,'゚'=>1,'ï¾ '=>1,'ᄀ'=>1,'ï¾¢'=>1,'ï¾£'=>1,'ᄂ'=>1,'ï¾¥'=>1,'ᆭ'=>1,'ᄃ'=>1,'ᄄ'=>1,'ᄅ'=>1,'ᆰ'=>1,'ᆱ'=>1,'ᆲ'=>1,'ï¾­'=>1,'ï¾®'=>1,'ᆵ'=>1,'ï¾°'=>1,'ï¾±'=>1,'ï¾²'=>1,'ï¾³'=>1,'ï¾´'=>1,'ï¾µ'=>1,'ᄊ'=>1,'ï¾·'=>1,'ᄌ'=>1,'ï¾¹'=>1,'ᄎ'=>1,'ï¾»'=>1,'ï¾¼'=>1,'ï¾½'=>1,'ï¾¾'=>1,'ï¿‚'=>1,'ᅢ'=>1,'ï¿„'=>1,'ï¿…'=>1,'ᅥ'=>1,'ᅦ'=>1,'ï¿Š'=>1,'ï¿‹'=>1,'ï¿Œ'=>1,'ï¿'=>1,'ï¿Ž'=>1,'ï¿'=>1,'ï¿’'=>1,'ï¿“'=>1,'ï¿”'=>1,'ï¿•'=>1,'ï¿–'=>1,'ï¿—'=>1,'ï¿š'=>1,'ï¿›'=>1,'ï¿œ'=>1,'ï¿ '=>1,'ï¿¡'=>1,'ï¿¢'=>1,'ï¿£'=>1,'¦'=>1,'ï¿¥'=>1,'₩'=>1,'│'=>1,'ï¿©'=>1,'↑'=>1,'ï¿«'=>1,'↓'=>1,'ï¿­'=>1,'ï¿®'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð­'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ð‘€'=>1,'ð‘'=>1,'ð‘‚'=>1,'ð‘ƒ'=>1,'ð‘„'=>1,'ð‘…'=>1,'ð‘†'=>1,'ð‘‡'=>1,'ð‘ˆ'=>1,'ð‘‰'=>1,'ð‘Š'=>1,'ð‘‹'=>1,'ð‘Œ'=>1,'ð‘'=>1,'ð‘Ž'=>1,'ð‘'=>1,'ð‘'=>1,'ð‘‘'=>1,'ð‘’'=>1,'ð‘“'=>1,'ð‘”'=>1,'ð‘–'=>1,'ð‘—'=>1,'ð‘˜'=>1,'ð‘™'=>1,'ð‘š'=>1,'ð‘›'=>1,'ð‘œ'=>1,'ð‘'=>1,'ð‘ž'=>1,'ð‘Ÿ'=>1,'ð‘ '=>1,'ð‘¡'=>1,'ð‘¢'=>1,'ð‘£'=>1,'ð‘¤'=>1,'ð‘¥'=>1,'ð‘¦'=>1,'ð‘§'=>1,'ð‘¨'=>1,'ð‘©'=>1,'ð‘ª'=>1,'ð‘«'=>1,'ð‘¬'=>1,'ð‘­'=>1,'ð‘®'=>1,'ð‘¯'=>1,'ð‘°'=>1,'ð‘±'=>1,'ð‘²'=>1,'ð‘³'=>1,'ð‘´'=>1,'ð‘µ'=>1,'ð‘¶'=>1,'ð‘·'=>1,'ð‘¸'=>1,'ð‘¹'=>1,'ð‘º'=>1,'ð‘»'=>1,'ð‘¼'=>1,'ð‘½'=>1,'ð‘¾'=>1,'ð‘¿'=>1,'ð’€'=>1,'ð’'=>1,'ð’‚'=>1,'ð’ƒ'=>1,'ð’„'=>1,'ð’…'=>1,'ð’†'=>1,'ð’‡'=>1,'ð’ˆ'=>1,'ð’‰'=>1,'ð’Š'=>1,'ð’‹'=>1,'ð’Œ'=>1,'ð’'=>1,'ð’Ž'=>1,'ð’'=>1,'ð’'=>1,'ð’‘'=>1,'ð’’'=>1,'ð’“'=>1,'ð’”'=>1,'ð’•'=>1,'ð’–'=>1,'ð’—'=>1,'ð’˜'=>1,'ð’™'=>1,'ð’š'=>1,'ð’›'=>1,'ð’œ'=>1,'ð’ž'=>1,'ð’Ÿ'=>1,'ð’¢'=>1,'ð’¥'=>1,'ð’¦'=>1,'ð’©'=>1,'ð’ª'=>1,'ð’«'=>1,'ð’¬'=>1,'ð’®'=>1,'ð’¯'=>1,'ð’°'=>1,'ð’±'=>1,'ð’²'=>1,'ð’³'=>1,'ð’´'=>1,'ð’µ'=>1,'ð’¶'=>1,'ð’·'=>1,'ð’¸'=>1,'ð’¹'=>1,'ð’»'=>1,'ð’½'=>1,'ð’¾'=>1,'ð’¿'=>1,'ð“€'=>1,'ð“'=>1,'ð“‚'=>1,'ð“ƒ'=>1,'ð“…'=>1,'ð“†'=>1,'ð“‡'=>1,'ð“ˆ'=>1,'ð“‰'=>1,'ð“Š'=>1,'ð“‹'=>1,'ð“Œ'=>1,'ð“'=>1,'ð“Ž'=>1,'ð“'=>1,'ð“'=>1,'ð“‘'=>1,'ð“’'=>1,'ð““'=>1,'ð“”'=>1,'ð“•'=>1,'ð“–'=>1,'ð“—'=>1,'ð“˜'=>1,'ð“™'=>1,'ð“š'=>1,'ð“›'=>1,'ð“œ'=>1,'ð“'=>1,'ð“ž'=>1,'ð“Ÿ'=>1,'ð“ '=>1,'ð“¡'=>1,'ð“¢'=>1,'ð“£'=>1,'ð“¤'=>1,'ð“¥'=>1,'ð“¦'=>1,'ð“§'=>1,'ð“¨'=>1,'ð“©'=>1,'ð“ª'=>1,'ð“«'=>1,'ð“¬'=>1,'ð“­'=>1,'ð“®'=>1,'ð“¯'=>1,'ð“°'=>1,'ð“±'=>1,'ð“²'=>1,'ð“³'=>1,'ð“´'=>1,'ð“µ'=>1,'ð“¶'=>1,'ð“·'=>1,'ð“¸'=>1,'ð“¹'=>1,'ð“º'=>1,'ð“»'=>1,'ð“¼'=>1,'ð“½'=>1,'ð“¾'=>1,'ð“¿'=>1,'ð”€'=>1,'ð”'=>1,'ð”‚'=>1,'ð”ƒ'=>1,'ð”„'=>1,'ð”…'=>1,'ð”‡'=>1,'ð”ˆ'=>1,'ð”‰'=>1,'ð”Š'=>1,'ð”'=>1,'ð”Ž'=>1,'ð”'=>1,'ð”'=>1,'ð”‘'=>1,'ð”’'=>1,'ð”“'=>1,'ð””'=>1,'ð”–'=>1,'ð”—'=>1,'ð”˜'=>1,'ð”™'=>1,'ð”š'=>1,'ð”›'=>1,'ð”œ'=>1,'ð”ž'=>1,'ð”Ÿ'=>1,'ð” '=>1,'ð”¡'=>1,'ð”¢'=>1,'ð”£'=>1,'ð”¤'=>1,'ð”¥'=>1,'ð”¦'=>1,'ð”§'=>1,'ð”¨'=>1,'ð”©'=>1,'ð”ª'=>1,'ð”«'=>1,'ð”¬'=>1,'ð”­'=>1,'ð”®'=>1,'ð”¯'=>1,'ð”°'=>1,'ð”±'=>1,'ð”²'=>1,'ð”³'=>1,'ð”´'=>1,'ð”µ'=>1,'ð”¶'=>1,'ð”·'=>1,'ð”¸'=>1,'ð”¹'=>1,'ð”»'=>1,'ð”¼'=>1,'ð”½'=>1,'ð”¾'=>1,'ð•€'=>1,'ð•'=>1,'ð•‚'=>1,'ð•ƒ'=>1,'ð•„'=>1,'ð•†'=>1,'ð•Š'=>1,'ð•‹'=>1,'ð•Œ'=>1,'ð•'=>1,'ð•Ž'=>1,'ð•'=>1,'ð•'=>1,'ð•’'=>1,'ð•“'=>1,'ð•”'=>1,'ð••'=>1,'ð•–'=>1,'ð•—'=>1,'ð•˜'=>1,'ð•™'=>1,'ð•š'=>1,'ð•›'=>1,'ð•œ'=>1,'ð•'=>1,'ð•ž'=>1,'ð•Ÿ'=>1,'ð• '=>1,'ð•¡'=>1,'ð•¢'=>1,'ð•£'=>1,'ð•¤'=>1,'ð•¥'=>1,'ð•¦'=>1,'ð•§'=>1,'ð•¨'=>1,'ð•©'=>1,'ð•ª'=>1,'ð•«'=>1,'ð•¬'=>1,'ð•­'=>1,'ð•®'=>1,'ð•¯'=>1,'ð•°'=>1,'ð•±'=>1,'ð•²'=>1,'ð•³'=>1,'ð•´'=>1,'ð•µ'=>1,'ð•¶'=>1,'ð•·'=>1,'ð•¸'=>1,'ð•¹'=>1,'ð•º'=>1,'ð•»'=>1,'ð•¼'=>1,'ð•½'=>1,'ð•¾'=>1,'ð•¿'=>1,'ð–€'=>1,'ð–'=>1,'ð–‚'=>1,'ð–ƒ'=>1,'ð–„'=>1,'ð–…'=>1,'ð–†'=>1,'ð–‡'=>1,'ð–ˆ'=>1,'ð–‰'=>1,'ð–Š'=>1,'ð–‹'=>1,'ð–Œ'=>1,'ð–'=>1,'ð–Ž'=>1,'ð–'=>1,'ð–'=>1,'ð–‘'=>1,'ð–’'=>1,'ð–“'=>1,'ð–”'=>1,'ð–•'=>1,'ð––'=>1,'ð–—'=>1,'ð–˜'=>1,'ð–™'=>1,'ð–š'=>1,'ð–›'=>1,'ð–œ'=>1,'ð–'=>1,'ð–ž'=>1,'ð–Ÿ'=>1,'ð– '=>1,'ð–¡'=>1,'ð–¢'=>1,'ð–£'=>1,'ð–¤'=>1,'ð–¥'=>1,'ð–¦'=>1,'ð–§'=>1,'ð–¨'=>1,'ð–©'=>1,'ð–ª'=>1,'ð–«'=>1,'ð–¬'=>1,'ð–­'=>1,'ð–®'=>1,'ð–¯'=>1,'ð–°'=>1,'ð–±'=>1,'ð–²'=>1,'ð–³'=>1,'ð–´'=>1,'ð–µ'=>1,'ð–¶'=>1,'ð–·'=>1,'ð–¸'=>1,'ð–¹'=>1,'ð–º'=>1,'ð–»'=>1,'ð–¼'=>1,'ð–½'=>1,'ð–¾'=>1,'ð–¿'=>1,'ð—€'=>1,'ð—'=>1,'ð—‚'=>1,'ð—ƒ'=>1,'ð—„'=>1,'ð—…'=>1,'ð—†'=>1,'ð—‡'=>1,'ð—ˆ'=>1,'ð—‰'=>1,'ð—Š'=>1,'ð—‹'=>1,'ð—Œ'=>1,'ð—'=>1,'ð—Ž'=>1,'ð—'=>1,'ð—'=>1,'ð—‘'=>1,'ð—’'=>1,'ð—“'=>1,'ð—”'=>1,'ð—•'=>1,'ð—–'=>1,'ð——'=>1,'ð—˜'=>1,'ð—™'=>1,'ð—š'=>1,'ð—›'=>1,'ð—œ'=>1,'ð—'=>1,'ð—ž'=>1,'ð—Ÿ'=>1,'ð— '=>1,'ð—¡'=>1,'ð—¢'=>1,'ð—£'=>1,'ð—¤'=>1,'ð—¥'=>1,'ð—¦'=>1,'ð—§'=>1,'ð—¨'=>1,'ð—©'=>1,'ð—ª'=>1,'ð—«'=>1,'ð—¬'=>1,'ð—­'=>1,'ð—®'=>1,'ð—¯'=>1,'ð—°'=>1,'ð—±'=>1,'ð—²'=>1,'ð—³'=>1,'ð—´'=>1,'ð—µ'=>1,'ð—¶'=>1,'ð—·'=>1,'ð—¸'=>1,'ð—¹'=>1,'ð—º'=>1,'ð—»'=>1,'ð—¼'=>1,'ð—½'=>1,'ð—¾'=>1,'ð—¿'=>1,'ð˜€'=>1,'ð˜'=>1,'ð˜‚'=>1,'ð˜ƒ'=>1,'ð˜„'=>1,'ð˜…'=>1,'ð˜†'=>1,'ð˜‡'=>1,'ð˜ˆ'=>1,'ð˜‰'=>1,'ð˜Š'=>1,'ð˜‹'=>1,'ð˜Œ'=>1,'ð˜'=>1,'ð˜Ž'=>1,'ð˜'=>1,'ð˜'=>1,'ð˜‘'=>1,'ð˜’'=>1,'ð˜“'=>1,'ð˜”'=>1,'ð˜•'=>1,'ð˜–'=>1,'ð˜—'=>1,'ð˜˜'=>1,'ð˜™'=>1,'ð˜š'=>1,'ð˜›'=>1,'ð˜œ'=>1,'ð˜'=>1,'ð˜ž'=>1,'ð˜Ÿ'=>1,'ð˜ '=>1,'ð˜¡'=>1,'ð˜¢'=>1,'ð˜£'=>1,'ð˜¤'=>1,'ð˜¥'=>1,'ð˜¦'=>1,'ð˜§'=>1,'ð˜¨'=>1,'ð˜©'=>1,'ð˜ª'=>1,'ð˜«'=>1,'ð˜¬'=>1,'ð˜­'=>1,'ð˜®'=>1,'ð˜¯'=>1,'ð˜°'=>1,'ð˜±'=>1,'ð˜²'=>1,'ð˜³'=>1,'ð˜´'=>1,'ð˜µ'=>1,'ð˜¶'=>1,'ð˜·'=>1,'ð˜¸'=>1,'ð˜¹'=>1,'ð˜º'=>1,'ð˜»'=>1,'ð˜¼'=>1,'ð˜½'=>1,'ð˜¾'=>1,'ð˜¿'=>1,'ð™€'=>1,'ð™'=>1,'ð™‚'=>1,'ð™ƒ'=>1,'ð™„'=>1,'ð™…'=>1,'ð™†'=>1,'ð™‡'=>1,'ð™ˆ'=>1,'ð™‰'=>1,'ð™Š'=>1,'ð™‹'=>1,'ð™Œ'=>1,'ð™'=>1,'ð™Ž'=>1,'ð™'=>1,'ð™'=>1,'ð™‘'=>1,'ð™’'=>1,'ð™“'=>1,'ð™”'=>1,'ð™•'=>1,'ð™–'=>1,'ð™—'=>1,'ð™˜'=>1,'ð™™'=>1,'ð™š'=>1,'ð™›'=>1,'ð™œ'=>1,'ð™'=>1,'ð™ž'=>1,'ð™Ÿ'=>1,'ð™ '=>1,'ð™¡'=>1,'ð™¢'=>1,'ð™£'=>1,'ð™¤'=>1,'ð™¥'=>1,'ð™¦'=>1,'ð™§'=>1,'ð™¨'=>1,'ð™©'=>1,'ð™ª'=>1,'ð™«'=>1,'ð™¬'=>1,'ð™­'=>1,'ð™®'=>1,'ð™¯'=>1,'ð™°'=>1,'ð™±'=>1,'ð™²'=>1,'ð™³'=>1,'ð™´'=>1,'ð™µ'=>1,'ð™¶'=>1,'ð™·'=>1,'ð™¸'=>1,'ð™¹'=>1,'ð™º'=>1,'ð™»'=>1,'ð™¼'=>1,'ð™½'=>1,'ð™¾'=>1,'ð™¿'=>1,'ðš€'=>1,'ðš'=>1,'ðš‚'=>1,'ðšƒ'=>1,'ðš„'=>1,'ðš…'=>1,'ðš†'=>1,'ðš‡'=>1,'ðšˆ'=>1,'ðš‰'=>1,'ðšŠ'=>1,'ðš‹'=>1,'ðšŒ'=>1,'ðš'=>1,'ðšŽ'=>1,'ðš'=>1,'ðš'=>1,'ðš‘'=>1,'ðš’'=>1,'ðš“'=>1,'ðš”'=>1,'ðš•'=>1,'ðš–'=>1,'ðš—'=>1,'ðš˜'=>1,'ðš™'=>1,'ðšš'=>1,'ðš›'=>1,'ðšœ'=>1,'ðš'=>1,'ðšž'=>1,'ðšŸ'=>1,'ðš '=>1,'ðš¡'=>1,'ðš¢'=>1,'ðš£'=>1,'ðš¤'=>1,'ðš¥'=>1,'ðš¨'=>1,'ðš©'=>1,'ðšª'=>1,'ðš«'=>1,'ðš¬'=>1,'ðš­'=>1,'ðš®'=>1,'ðš¯'=>1,'ðš°'=>1,'ðš±'=>1,'ðš²'=>1,'ðš³'=>1,'ðš´'=>1,'ðšµ'=>1,'ðš¶'=>1,'ðš·'=>1,'ðš¸'=>1,'ðš¹'=>1,'ðšº'=>1,'ðš»'=>1,'ðš¼'=>1,'ðš½'=>1,'ðš¾'=>1,'ðš¿'=>1,'ð›€'=>1,'ð›'=>1,'ð›‚'=>1,'ð›ƒ'=>1,'ð›„'=>1,'ð›…'=>1,'ð›†'=>1,'ð›‡'=>1,'ð›ˆ'=>1,'ð›‰'=>1,'ð›Š'=>1,'ð›‹'=>1,'ð›Œ'=>1,'ð›'=>1,'ð›Ž'=>1,'ð›'=>1,'ð›'=>1,'ð›‘'=>1,'ð›’'=>1,'ð›“'=>1,'ð›”'=>1,'ð›•'=>1,'ð›–'=>1,'ð›—'=>1,'ð›˜'=>1,'ð›™'=>1,'ð›š'=>1,'ð››'=>1,'ð›œ'=>1,'ð›'=>1,'ð›ž'=>1,'ð›Ÿ'=>1,'ð› '=>1,'ð›¡'=>1,'ð›¢'=>1,'ð›£'=>1,'ð›¤'=>1,'ð›¥'=>1,'ð›¦'=>1,'ð›§'=>1,'ð›¨'=>1,'ð›©'=>1,'ð›ª'=>1,'ð›«'=>1,'ð›¬'=>1,'ð›­'=>1,'ð›®'=>1,'ð›¯'=>1,'ð›°'=>1,'ð›±'=>1,'ð›²'=>1,'ð›³'=>1,'ð›´'=>1,'ð›µ'=>1,'ð›¶'=>1,'ð›·'=>1,'ð›¸'=>1,'ð›¹'=>1,'ð›º'=>1,'ð›»'=>1,'ð›¼'=>1,'ð›½'=>1,'ð›¾'=>1,'ð›¿'=>1,'ðœ€'=>1,'ðœ'=>1,'ðœ‚'=>1,'ðœƒ'=>1,'ðœ„'=>1,'ðœ…'=>1,'ðœ†'=>1,'ðœ‡'=>1,'ðœˆ'=>1,'ðœ‰'=>1,'ðœŠ'=>1,'ðœ‹'=>1,'ðœŒ'=>1,'ðœ'=>1,'ðœŽ'=>1,'ðœ'=>1,'ðœ'=>1,'ðœ‘'=>1,'ðœ’'=>1,'ðœ“'=>1,'ðœ”'=>1,'ðœ•'=>1,'ðœ–'=>1,'ðœ—'=>1,'ðœ˜'=>1,'ðœ™'=>1,'ðœš'=>1,'ðœ›'=>1,'ðœœ'=>1,'ðœ'=>1,'ðœž'=>1,'ðœŸ'=>1,'ðœ '=>1,'ðœ¡'=>1,'ðœ¢'=>1,'ðœ£'=>1,'ðœ¤'=>1,'ðœ¥'=>1,'ðœ¦'=>1,'ðœ§'=>1,'ðœ¨'=>1,'ðœ©'=>1,'ðœª'=>1,'ðœ«'=>1,'ðœ¬'=>1,'ðœ­'=>1,'ðœ®'=>1,'ðœ¯'=>1,'ðœ°'=>1,'ðœ±'=>1,'ðœ²'=>1,'ðœ³'=>1,'ðœ´'=>1,'ðœµ'=>1,'ðœ¶'=>1,'ðœ·'=>1,'ðœ¸'=>1,'ðœ¹'=>1,'ðœº'=>1,'ðœ»'=>1,'ðœ¼'=>1,'ðœ½'=>1,'ðœ¾'=>1,'ðœ¿'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð­'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ðž€'=>1,'ðž'=>1,'ðž‚'=>1,'ðžƒ'=>1,'ðž„'=>1,'ðž…'=>1,'ðž†'=>1,'ðž‡'=>1,'ðžˆ'=>1,'ðž‰'=>1,'ðžŠ'=>1,'ðž‹'=>1,'ðžŒ'=>1,'ðž'=>1,'ðžŽ'=>1,'ðž'=>1,'ðž'=>1,'ðž‘'=>1,'ðž’'=>1,'ðž“'=>1,'ðž”'=>1,'ðž•'=>1,'ðž–'=>1,'ðž—'=>1,'ðž˜'=>1,'ðž™'=>1,'ðžš'=>1,'ðž›'=>1,'ðžœ'=>1,'ðž'=>1,'ðžž'=>1,'ðžŸ'=>1,'ðž '=>1,'ðž¡'=>1,'ðž¢'=>1,'ðž£'=>1,'ðž¤'=>1,'ðž¥'=>1,'ðž¦'=>1,'ðž§'=>1,'ðž¨'=>1,'ðž©'=>1,'ðžª'=>1,'ðž«'=>1,'ðž¬'=>1,'ðž­'=>1,'ðž®'=>1,'ðž¯'=>1,'ðž°'=>1,'ðž±'=>1,'ðž²'=>1,'ðž³'=>1,'ðž´'=>1,'ðžµ'=>1,'ðž¶'=>1,'ðž·'=>1,'ðž¸'=>1,'ðž¹'=>1,'ðžº'=>1,'ðž»'=>1,'ðž¼'=>1,'ðž½'=>1,'ðž¾'=>1,'ðž¿'=>1,'ðŸ€'=>1,'ðŸ'=>1,'ðŸ‚'=>1,'ðŸƒ'=>1,'ðŸ„'=>1,'ðŸ…'=>1,'ðŸ†'=>1,'ðŸ‡'=>1,'ðŸˆ'=>1,'ðŸ‰'=>1,'ðŸŠ'=>1,'ðŸ‹'=>1,'ðŸŽ'=>1,'ðŸ'=>1,'ðŸ'=>1,'ðŸ‘'=>1,'ðŸ’'=>1,'ðŸ“'=>1,'ðŸ”'=>1,'ðŸ•'=>1,'ðŸ–'=>1,'ðŸ—'=>1,'ðŸ˜'=>1,'ðŸ™'=>1,'ðŸš'=>1,'ðŸ›'=>1,'ðŸœ'=>1,'ðŸ'=>1,'ðŸž'=>1,'ðŸŸ'=>1,'ðŸ '=>1,'ðŸ¡'=>1,'ðŸ¢'=>1,'ðŸ£'=>1,'ðŸ¤'=>1,'ðŸ¥'=>1,'ðŸ¦'=>1,'ðŸ§'=>1,'ðŸ¨'=>1,'ðŸ©'=>1,'ðŸª'=>1,'ðŸ«'=>1,'ðŸ¬'=>1,'ðŸ­'=>1,'ðŸ®'=>1,'ðŸ¯'=>1,'ðŸ°'=>1,'ðŸ±'=>1,'ðŸ²'=>1,'ðŸ³'=>1,'ðŸ´'=>1,'ðŸµ'=>1,'ðŸ¶'=>1,'ðŸ·'=>1,'ðŸ¸'=>1,'ðŸ¹'=>1,'ðŸº'=>1,'ðŸ»'=>1,'ðŸ¼'=>1,'ðŸ½'=>1,'ðŸ¾'=>1,'ðŸ¿'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'刻'=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'卑'=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'寃'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'憤'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'櫛'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'㺸'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'䌁'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'𦼬'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'𨯺'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>0,'Ì'=>0,'Ì‚'=>0,'̃'=>0,'Ì„'=>0,'̆'=>0,'̇'=>0,'̈'=>0,'̉'=>0,'ÌŠ'=>0,'Ì‹'=>0,'ÌŒ'=>0,'Ì'=>0,'Ì‘'=>0,'Ì“'=>0,'Ì”'=>0,'Ì›'=>0,'Ì£'=>0,'̤'=>0,'Ì¥'=>0,'̦'=>0,'̧'=>0,'̨'=>0,'Ì­'=>0,'Ì®'=>0,'Ì°'=>0,'̱'=>0,'̸'=>0,'Í‚'=>0,'Í…'=>0,'Ù“'=>0,'Ù”'=>0,'Ù•'=>0,'़'=>0,'া'=>0,'ৗ'=>0,'ା'=>0,'à­–'=>0,'à­—'=>0,'ா'=>0,'ௗ'=>0,'à±–'=>0,'ೂ'=>0,'ೕ'=>0,'à³–'=>0,'à´¾'=>0,'ൗ'=>0,'à·Š'=>0,'à·'=>0,'à·Ÿ'=>0,'ီ'=>0,'á…¡'=>0,'á…¢'=>0,'á…£'=>0,'á…¤'=>0,'á…¥'=>0,'á…¦'=>0,'á…§'=>0,'á…¨'=>0,'á…©'=>0,'á…ª'=>0,'á…«'=>0,'á…¬'=>0,'á…­'=>0,'á…®'=>0,'á…¯'=>0,'á…°'=>0,'á…±'=>0,'á…²'=>0,'á…³'=>0,'á…´'=>0,'á…µ'=>0,'ᆨ'=>0,'ᆩ'=>0,'ᆪ'=>0,'ᆫ'=>0,'ᆬ'=>0,'ᆭ'=>0,'ᆮ'=>0,'ᆯ'=>0,'ᆰ'=>0,'ᆱ'=>0,'ᆲ'=>0,'ᆳ'=>0,'ᆴ'=>0,'ᆵ'=>0,'ᆶ'=>0,'ᆷ'=>0,'ᆸ'=>0,'ᆹ'=>0,'ᆺ'=>0,'ᆻ'=>0,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'ã‚š'=>0);
diff --git a/phpBB/includes/utf/data/utf_normalizer_common.php b/phpBB/includes/utf/data/utf_normalizer_common.php
deleted file mode 100644
index 2eb7feac69..0000000000
--- a/phpBB/includes/utf/data/utf_normalizer_common.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-$GLOBALS['utf_jamo_index']=array('á„€'=>44032,'á„'=>44620,'á„‚'=>45208,'ᄃ'=>45796,'á„„'=>46384,'á„…'=>46972,'ᄆ'=>47560,'ᄇ'=>48148,'ᄈ'=>48736,'ᄉ'=>49324,'á„Š'=>49912,'á„‹'=>50500,'á„Œ'=>51088,'á„'=>51676,'á„Ž'=>52264,'á„'=>52852,'á„'=>53440,'á„‘'=>54028,'á„’'=>54616,'á…¡'=>0,'á…¢'=>28,'á…£'=>56,'á…¤'=>84,'á…¥'=>112,'á…¦'=>140,'á…§'=>168,'á…¨'=>196,'á…©'=>224,'á…ª'=>252,'á…«'=>280,'á…¬'=>308,'á…­'=>336,'á…®'=>364,'á…¯'=>392,'á…°'=>420,'á…±'=>448,'á…²'=>476,'á…³'=>504,'á…´'=>532,'á…µ'=>560,'ᆧ'=>0,'ᆨ'=>1,'ᆩ'=>2,'ᆪ'=>3,'ᆫ'=>4,'ᆬ'=>5,'ᆭ'=>6,'ᆮ'=>7,'ᆯ'=>8,'ᆰ'=>9,'ᆱ'=>10,'ᆲ'=>11,'ᆳ'=>12,'ᆴ'=>13,'ᆵ'=>14,'ᆶ'=>15,'ᆷ'=>16,'ᆸ'=>17,'ᆹ'=>18,'ᆺ'=>19,'ᆻ'=>20,'ᆼ'=>21,'ᆽ'=>22,'ᆾ'=>23,'ᆿ'=>24,'ᇀ'=>25,'á‡'=>26,'ᇂ'=>27);
-$GLOBALS['utf_jamo_type']=array('á„€'=>0,'á„'=>0,'á„‚'=>0,'ᄃ'=>0,'á„„'=>0,'á„…'=>0,'ᄆ'=>0,'ᄇ'=>0,'ᄈ'=>0,'ᄉ'=>0,'á„Š'=>0,'á„‹'=>0,'á„Œ'=>0,'á„'=>0,'á„Ž'=>0,'á„'=>0,'á„'=>0,'á„‘'=>0,'á„’'=>0,'á…¡'=>1,'á…¢'=>1,'á…£'=>1,'á…¤'=>1,'á…¥'=>1,'á…¦'=>1,'á…§'=>1,'á…¨'=>1,'á…©'=>1,'á…ª'=>1,'á…«'=>1,'á…¬'=>1,'á…­'=>1,'á…®'=>1,'á…¯'=>1,'á…°'=>1,'á…±'=>1,'á…²'=>1,'á…³'=>1,'á…´'=>1,'á…µ'=>1,'ᆧ'=>2,'ᆨ'=>2,'ᆩ'=>2,'ᆪ'=>2,'ᆫ'=>2,'ᆬ'=>2,'ᆭ'=>2,'ᆮ'=>2,'ᆯ'=>2,'ᆰ'=>2,'ᆱ'=>2,'ᆲ'=>2,'ᆳ'=>2,'ᆴ'=>2,'ᆵ'=>2,'ᆶ'=>2,'ᆷ'=>2,'ᆸ'=>2,'ᆹ'=>2,'ᆺ'=>2,'ᆻ'=>2,'ᆼ'=>2,'ᆽ'=>2,'ᆾ'=>2,'ᆿ'=>2,'ᇀ'=>2,'á‡'=>2,'ᇂ'=>2);
-$GLOBALS['utf_combining_class']=array('Ì€'=>230,'Ì'=>230,'Ì‚'=>230,'̃'=>230,'Ì„'=>230,'Ì…'=>230,'̆'=>230,'̇'=>230,'̈'=>230,'̉'=>230,'ÌŠ'=>230,'Ì‹'=>230,'ÌŒ'=>230,'Ì'=>230,'ÌŽ'=>230,'Ì'=>230,'Ì'=>230,'Ì‘'=>230,'Ì’'=>230,'Ì“'=>230,'Ì”'=>230,'Ì•'=>232,'Ì–'=>220,'Ì—'=>220,'̘'=>220,'Ì™'=>220,'Ìš'=>232,'Ì›'=>216,'Ìœ'=>220,'Ì'=>220,'Ìž'=>220,'ÌŸ'=>220,'Ì '=>220,'Ì¡'=>202,'Ì¢'=>202,'Ì£'=>220,'̤'=>220,'Ì¥'=>220,'̦'=>220,'̧'=>202,'̨'=>202,'Ì©'=>220,'̪'=>220,'Ì«'=>220,'̬'=>220,'Ì­'=>220,'Ì®'=>220,'̯'=>220,'Ì°'=>220,'̱'=>220,'̲'=>220,'̳'=>220,'Ì´'=>1,'̵'=>1,'̶'=>1,'Ì·'=>1,'̸'=>1,'̹'=>220,'̺'=>220,'Ì»'=>220,'̼'=>220,'̽'=>230,'̾'=>230,'Ì¿'=>230,'Í€'=>230,'Í'=>230,'Í‚'=>230,'̓'=>230,'Í„'=>230,'Í…'=>240,'͆'=>230,'͇'=>220,'͈'=>220,'͉'=>220,'ÍŠ'=>230,'Í‹'=>230,'ÍŒ'=>230,'Í'=>220,'ÍŽ'=>220,'Í'=>230,'Í‘'=>230,'Í’'=>230,'Í“'=>220,'Í”'=>220,'Í•'=>220,'Í–'=>220,'Í—'=>230,'͘'=>232,'Í™'=>220,'Íš'=>220,'Í›'=>230,'Íœ'=>233,'Í'=>234,'Íž'=>234,'ÍŸ'=>233,'Í '=>234,'Í¡'=>234,'Í¢'=>233,'Í£'=>230,'ͤ'=>230,'Í¥'=>230,'ͦ'=>230,'ͧ'=>230,'ͨ'=>230,'Í©'=>230,'ͪ'=>230,'Í«'=>230,'ͬ'=>230,'Í­'=>230,'Í®'=>230,'ͯ'=>230,'Òƒ'=>230,'Ò„'=>230,'Ò…'=>230,'Ò†'=>230,'Ö‘'=>220,'Ö’'=>230,'Ö“'=>230,'Ö”'=>230,'Ö•'=>230,'Ö–'=>220,'Ö—'=>230,'Ö˜'=>230,'Ö™'=>230,'Öš'=>222,'Ö›'=>220,'Öœ'=>230,'Ö'=>230,'Öž'=>230,'ÖŸ'=>230,'Ö '=>230,'Ö¡'=>230,'Ö¢'=>220,'Ö£'=>220,'Ö¤'=>220,'Ö¥'=>220,'Ö¦'=>220,'Ö§'=>220,'Ö¨'=>230,'Ö©'=>230,'Öª'=>220,'Ö«'=>230,'Ö¬'=>230,'Ö­'=>222,'Ö®'=>228,'Ö¯'=>230,'Ö°'=>10,'Ö±'=>11,'Ö²'=>12,'Ö³'=>13,'Ö´'=>14,'Öµ'=>15,'Ö¶'=>16,'Ö·'=>17,'Ö¸'=>18,'Ö¹'=>19,'Öº'=>19,'Ö»'=>20,'Ö¼'=>21,'Ö½'=>22,'Ö¿'=>23,'×'=>24,'ׂ'=>25,'ׄ'=>230,'×…'=>220,'ׇ'=>18,'Ø'=>230,'Ø‘'=>230,'Ø’'=>230,'Ø“'=>230,'Ø”'=>230,'Ø•'=>230,'Ù‹'=>27,'ÙŒ'=>28,'Ù'=>29,'ÙŽ'=>30,'Ù'=>31,'Ù'=>32,'Ù‘'=>33,'Ù’'=>34,'Ù“'=>230,'Ù”'=>230,'Ù•'=>220,'Ù–'=>220,'Ù—'=>230,'Ù˜'=>230,'Ù™'=>230,'Ùš'=>230,'Ù›'=>230,'Ùœ'=>220,'Ù'=>230,'Ùž'=>230,'Ù°'=>35,'Û–'=>230,'Û—'=>230,'Û˜'=>230,'Û™'=>230,'Ûš'=>230,'Û›'=>230,'Ûœ'=>230,'ÛŸ'=>230,'Û '=>230,'Û¡'=>230,'Û¢'=>230,'Û£'=>220,'Û¤'=>230,'Û§'=>230,'Û¨'=>230,'Ûª'=>220,'Û«'=>230,'Û¬'=>230,'Û­'=>220,'Ü‘'=>36,'Ü°'=>230,'ܱ'=>220,'ܲ'=>230,'ܳ'=>230,'Ü´'=>220,'ܵ'=>230,'ܶ'=>230,'Ü·'=>220,'ܸ'=>220,'ܹ'=>220,'ܺ'=>230,'Ü»'=>220,'ܼ'=>220,'ܽ'=>230,'ܾ'=>220,'Ü¿'=>230,'Ý€'=>230,'Ý'=>230,'Ý‚'=>220,'݃'=>230,'Ý„'=>220,'Ý…'=>230,'݆'=>220,'݇'=>230,'݈'=>220,'݉'=>230,'ÝŠ'=>230,'ß«'=>230,'߬'=>230,'ß­'=>230,'ß®'=>230,'߯'=>230,'ß°'=>230,'ß±'=>230,'ß²'=>220,'ß³'=>230,'़'=>7,'à¥'=>9,'॑'=>230,'॒'=>220,'॓'=>230,'॔'=>230,'়'=>7,'à§'=>9,'਼'=>7,'à©'=>9,'઼'=>7,'à«'=>9,'଼'=>7,'à­'=>9,'à¯'=>9,'à±'=>9,'ౕ'=>84,'à±–'=>91,'಼'=>7,'à³'=>9,'àµ'=>9,'à·Š'=>9,'ุ'=>103,'ู'=>103,'ฺ'=>9,'่'=>107,'้'=>107,'๊'=>107,'๋'=>107,'ຸ'=>118,'ູ'=>118,'່'=>122,'້'=>122,'໊'=>122,'໋'=>122,'༘'=>220,'༙'=>220,'༵'=>220,'༷'=>220,'༹'=>216,'ཱ'=>129,'ི'=>130,'ུ'=>132,'ེ'=>130,'ཻ'=>130,'ོ'=>130,'ཽ'=>130,'ྀ'=>130,'ྂ'=>230,'ྃ'=>230,'྄'=>9,'྆'=>230,'྇'=>230,'࿆'=>220,'့'=>7,'္'=>9,'áŸ'=>230,'᜔'=>9,'᜴'=>9,'្'=>9,'áŸ'=>230,'ᢩ'=>228,'᤹'=>222,'᤺'=>230,'᤻'=>220,'ᨗ'=>230,'ᨘ'=>220,'᬴'=>7,'á­„'=>9,'á­«'=>230,'á­¬'=>220,'á­­'=>230,'á­®'=>230,'á­¯'=>230,'á­°'=>230,'á­±'=>230,'á­²'=>230,'á­³'=>230,'á·€'=>230,'á·'=>230,'á·‚'=>220,'á·ƒ'=>230,'á·„'=>230,'á·…'=>230,'á·†'=>230,'á·‡'=>230,'á·ˆ'=>230,'á·‰'=>230,'á·Š'=>220,'á·¾'=>230,'á·¿'=>220,'âƒ'=>230,'⃑'=>230,'⃒'=>1,'⃓'=>1,'⃔'=>230,'⃕'=>230,'⃖'=>230,'⃗'=>230,'⃘'=>1,'⃙'=>1,'⃚'=>1,'⃛'=>230,'⃜'=>230,'⃡'=>230,'⃥'=>1,'⃦'=>1,'⃧'=>230,'⃨'=>220,'⃩'=>230,'⃪'=>1,'⃫'=>1,'⃬'=>220,'⃭'=>220,'⃮'=>220,'⃯'=>220,'〪'=>218,'〫'=>228,'〬'=>232,'〭'=>222,'〮'=>224,'〯'=>224,'ã‚™'=>8,'ã‚š'=>8,'ê †'=>9,'ﬞ'=>26,'︠'=>230,'︡'=>230,'︢'=>230,'︣'=>230,'ð¨'=>220,'ð¨'=>230,'ð¨¸'=>230,'ð¨¹'=>1,'ð¨º'=>220,'ð¨¿'=>9,'ð…¥'=>216,'ð…¦'=>216,'ð…§'=>1,'ð…¨'=>1,'ð…©'=>1,'ð…­'=>226,'ð…®'=>216,'ð…¯'=>216,'ð…°'=>216,'ð…±'=>216,'ð…²'=>216,'ð…»'=>220,'ð…¼'=>220,'ð…½'=>220,'ð…¾'=>220,'ð…¿'=>220,'ð†€'=>220,'ð†'=>220,'ð†‚'=>220,'ð†…'=>230,'ð††'=>230,'ð†‡'=>230,'ð†ˆ'=>230,'ð†‰'=>230,'ð†Š'=>220,'ð†‹'=>220,'ð†ª'=>230,'ð†«'=>230,'ð†¬'=>230,'ð†­'=>230,'ð‰‚'=>230,'ð‰ƒ'=>230,'ð‰„'=>230);
diff --git a/phpBB/includes/utf/utf_normalizer.php b/phpBB/includes/utf/utf_normalizer.php
deleted file mode 100644
index bbb23a6617..0000000000
--- a/phpBB/includes/utf/utf_normalizer.php
+++ /dev/null
@@ -1,1509 +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.
-*
-*/
-
-/**
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Some Unicode characters encoded in UTF-8
-*
-* Preserved for compatibility
-*/
-define('UTF8_REPLACEMENT', "\xEF\xBF\xBD");
-define('UTF8_MAX', "\xF4\x8F\xBF\xBF");
-define('UTF8_FFFE', "\xEF\xBF\xBE");
-define('UTF8_FFFF', "\xEF\xBF\xBF");
-define('UTF8_SURROGATE_FIRST', "\xED\xA0\x80");
-define('UTF8_SURROGATE_LAST', "\xED\xBF\xBF");
-define('UTF8_HANGUL_FIRST', "\xEA\xB0\x80");
-define('UTF8_HANGUL_LAST', "\xED\x9E\xA3");
-
-define('UTF8_CJK_FIRST', "\xE4\xB8\x80");
-define('UTF8_CJK_LAST', "\xE9\xBE\xBB");
-define('UTF8_CJK_B_FIRST', "\xF0\xA0\x80\x80");
-define('UTF8_CJK_B_LAST', "\xF0\xAA\x9B\x96");
-
-// Unset global variables
-unset($GLOBALS['utf_jamo_index'], $GLOBALS['utf_jamo_type'], $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_combining_class'], $GLOBALS['utf_canonical_comp'], $GLOBALS['utf_canonical_decomp'], $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']);
-
-// NFC_QC and NFKC_QC values
-define('UNICODE_QC_MAYBE', 0);
-define('UNICODE_QC_NO', 1);
-
-// Contains all the ASCII characters appearing in UTF-8, sorted by frequency
-define('UTF8_ASCII_RANGE', "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F");
-
-// Contains all the tail bytes that can appear in the composition of a UTF-8 char
-define('UTF8_TRAILING_BYTES', "\xA9\xA0\xA8\x80\xAA\x99\xA7\xBB\xAB\x89\x94\x82\xB4\xA2\xAE\x83\xB0\xB9\xB8\x93\xAF\xBC\xB3\x81\xA4\xB2\x9C\xA1\xB5\xBE\xBD\xBA\x98\xAD\xB1\x84\x95\xA6\xB6\x88\x8D\x90\xB7\xBF\x92\x85\xA5\x97\x8C\x86\xA3\x8E\x9F\x8F\x87\x91\x9D\xAC\x9E\x8B\x96\x9B\x8A\x9A");
-
-// Constants used by the Hangul [de]composition algorithms
-define('UNICODE_HANGUL_SBASE', 0xAC00);
-define('UNICODE_HANGUL_LBASE', 0x1100);
-define('UNICODE_HANGUL_VBASE', 0x1161);
-define('UNICODE_HANGUL_TBASE', 0x11A7);
-define('UNICODE_HANGUL_SCOUNT', 11172);
-define('UNICODE_HANGUL_LCOUNT', 19);
-define('UNICODE_HANGUL_VCOUNT', 21);
-define('UNICODE_HANGUL_TCOUNT', 28);
-define('UNICODE_HANGUL_NCOUNT', 588);
-define('UNICODE_JAMO_L', 0);
-define('UNICODE_JAMO_V', 1);
-define('UNICODE_JAMO_T', 2);
-
-/**
-* Unicode normalization routines
-*/
-class utf_normalizer
-{
- /**
- * Validate, cleanup and normalize a string
- *
- * The ultimate convenience function! Clean up invalid UTF-8 sequences,
- * and convert to Normal Form C, canonical composition.
- *
- * @param string &$str The dirty string
- * @return string The same string, all shiny and cleaned-up
- */
- static function cleanup(&$str)
- {
- // The string below is the list of all autorized characters, sorted by frequency in latin text
- $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D");
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings with no special chars return immediately
- return;
- }
-
- // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together
- if (!isset($GLOBALS['utf_nfc_qc']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx);
- }
-
- if (!isset($GLOBALS['utf_canonical_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx);
- }
-
- // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t
- // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char
- $str = strtr(
- $str,
- "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
- );
-
- $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']);
- }
-
- /**
- * Validate and normalize a UTF string to NFC
- *
- * @param string &$str Unchecked UTF string
- * @return string The string, validated and in normal form
- */
- static function nfc(&$str)
- {
- $pos = strspn($str, UTF8_ASCII_RANGE);
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings return immediately
- return;
- }
-
- if (!isset($GLOBALS['utf_nfc_qc']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx);
- }
-
- if (!isset($GLOBALS['utf_canonical_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx);
- }
-
- $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']);
- }
-
- /**
- * Validate and normalize a UTF string to NFKC
- *
- * @param string &$str Unchecked UTF string
- * @return string The string, validated and in normal form
- */
- static function nfkc(&$str)
- {
- $pos = strspn($str, UTF8_ASCII_RANGE);
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings return immediately
- return;
- }
-
- if (!isset($GLOBALS['utf_nfkc_qc']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx);
- }
-
- if (!isset($GLOBALS['utf_compatibility_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx);
- }
-
- $str = utf_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']);
- }
-
- /**
- * Validate and normalize a UTF string to NFD
- *
- * @param string &$str Unchecked UTF string
- * @return string The string, validated and in normal form
- */
- static function nfd(&$str)
- {
- $pos = strspn($str, UTF8_ASCII_RANGE);
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings return immediately
- return;
- }
-
- if (!isset($GLOBALS['utf_canonical_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx);
- }
-
- $str = utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_canonical_decomp']);
- }
-
- /**
- * Validate and normalize a UTF string to NFKD
- *
- * @param string &$str Unchecked UTF string
- * @return string The string, validated and in normal form
- */
- static function nfkd(&$str)
- {
- $pos = strspn($str, UTF8_ASCII_RANGE);
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings return immediately
- return;
- }
-
- if (!isset($GLOBALS['utf_compatibility_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx);
- }
-
- $str = utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_compatibility_decomp']);
- }
-
-
- /**
- * Recompose a UTF string
- *
- * @param string $str Unchecked UTF string
- * @param integer $pos Position of the first UTF char (in bytes)
- * @param integer $len Length of the string (in bytes)
- * @param array &$qc Quick-check array, passed by reference but never modified
- * @param array &$decomp_map Decomposition mapping, passed by reference but never modified
- * @return string The string, validated and recomposed
- *
- * @access private
- */
- static function recompose($str, $pos, $len, &$qc, &$decomp_map)
- {
- global $utf_combining_class, $utf_canonical_comp, $utf_jamo_type, $utf_jamo_index;
-
- // Load some commonly-used tables
- if (!isset($utf_jamo_index, $utf_jamo_type, $utf_combining_class))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx);
- }
-
- // Load the canonical composition table
- if (!isset($utf_canonical_comp))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx);
- }
-
- // Buffer the last ASCII char before the UTF-8 stuff if applicable
- $tmp = '';
- $i = $tmp_pos = $last_cc = 0;
-
- $buffer = ($pos) ? array(++$i => $str[$pos - 1]) : array();
-
- // UTF char length array
- // This array is used to determine the length of a UTF character.
- // Be $c the result of ($str[$pos] & "\xF0") --where $str is the string we're operating on and $pos
- // the position of the cursor--, if $utf_len_mask[$c] does not exist, the byte is an ASCII char.
- // Otherwise, if $utf_len_mask[$c] is greater than 0, we have a the leading byte of a multibyte character
- // whose length is $utf_len_mask[$c] and if it is equal to 0, the byte is a trailing byte.
- $utf_len_mask = array(
- // Leading bytes masks
- "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4,
- // Trailing bytes masks
- "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0
- );
-
- $extra_check = array(
- "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1,
- "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1,
- "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1
- );
-
- $utf_validation_mask = array(
- 2 => "\xE0\xC0",
- 3 => "\xF0\xC0\xC0",
- 4 => "\xF8\xC0\xC0\xC0"
- );
-
- $utf_validation_check = array(
- 2 => "\xC0\x80",
- 3 => "\xE0\x80\x80",
- 4 => "\xF0\x80\x80\x80"
- );
-
- // Main loop
- do
- {
- // STEP 0: Capture the current char and buffer it
- $c = $str[$pos];
- $c_mask = $c & "\xF0";
-
- if (isset($utf_len_mask[$c_mask]))
- {
- // Byte at $pos is either a leading byte or a missplaced trailing byte
- if ($utf_len = $utf_len_mask[$c_mask])
- {
- // Capture the char
- $buffer[++$i & 7] = $utf_char = substr($str, $pos, $utf_len);
-
- // Let's find out if a thorough check is needed
- if (isset($qc[$utf_char]))
- {
- // If the UTF char is in the qc array then it may not be in normal form. We do nothing here, the actual processing is below this "if" block
- }
- else if (isset($utf_combining_class[$utf_char]))
- {
- if ($utf_combining_class[$utf_char] < $last_cc)
- {
- // A combining character that is NOT canonically ordered
- }
- else
- {
- // A combining character that IS canonically ordered, skip to the next char
- $last_cc = $utf_combining_class[$utf_char];
-
- $pos += $utf_len;
- continue;
- }
- }
- else
- {
- // At this point, $utf_char holds a UTF char that we know is not a NF[K]C_QC and is not a combining character.
- // It can be a singleton, a canonical composite, a replacement char or an even an ill-formed bunch of bytes. Let's find out
- $last_cc = 0;
-
- // Check that we have the correct number of trailing bytes
- if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len])
- {
- // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char
- // has been encoded in a five- or six- byte sequence
- if ($utf_char[0] >= "\xF8")
- {
- if ($utf_char[0] < "\xFC")
- {
- $trailing_bytes = 4;
- }
- else if ($utf_char[0] > "\xFD")
- {
- $trailing_bytes = 0;
- }
- else
- {
- $trailing_bytes = 5;
- }
- }
- else
- {
- $trailing_bytes = $utf_len - 1;
- }
-
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += strspn($str, UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes);
- $tmp_pos = $pos;
-
- continue;
- }
-
- if (isset($extra_check[$c]))
- {
- switch ($c)
- {
- // Note: 0xED is quite common in Korean
- case "\xED":
- if ($utf_char >= "\xED\xA0\x80")
- {
- // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF)
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += $utf_len;
- $tmp_pos = $pos;
- continue 2;
- }
- break;
-
- // Note: 0xEF is quite common in Japanese
- case "\xEF":
- if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF")
- {
- // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF)
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += $utf_len;
- $tmp_pos = $pos;
- continue 2;
- }
- break;
-
- case "\xC0":
- case "\xC1":
- if ($utf_char <= "\xC1\xBF")
- {
- // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += $utf_len;
- $tmp_pos = $pos;
- continue 2;
- }
- break;
-
- case "\xE0":
- if ($utf_char <= "\xE0\x9F\xBF")
- {
- // Unicode char U+0000..U+07FF encoded in 3 bytes
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += $utf_len;
- $tmp_pos = $pos;
- continue 2;
- }
- break;
-
- case "\xF0":
- if ($utf_char <= "\xF0\x8F\xBF\xBF")
- {
- // Unicode char U+0000..U+FFFF encoded in 4 bytes
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += $utf_len;
- $tmp_pos = $pos;
- continue 2;
- }
- break;
-
- default:
- // Five- and six- byte sequences do not need being checked for here anymore
- if ($utf_char > UTF8_MAX)
- {
- // Out of the Unicode range
- if ($utf_char[0] < "\xF8")
- {
- $trailing_bytes = 3;
- }
- else if ($utf_char[0] < "\xFC")
- {
- $trailing_bytes = 4;
- }
- else if ($utf_char[0] > "\xFD")
- {
- $trailing_bytes = 0;
- }
- else
- {
- $trailing_bytes = 5;
- }
-
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
- $pos += strspn($str, UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes);
- $tmp_pos = $pos;
- continue 2;
- }
- break;
- }
- }
-
- // The char is a valid starter, move the cursor and go on
- $pos += $utf_len;
- continue;
- }
- }
- else
- {
- // A trailing byte came out of nowhere, we will advance the cursor and treat the this byte and all following trailing bytes as if
- // each of them was a Unicode replacement char
- $spn = strspn($str, UTF8_TRAILING_BYTES, $pos);
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn);
-
- $pos += $spn;
- $tmp_pos = $pos;
- continue;
- }
-
- // STEP 1: Decompose current char
-
- // We have found a character that is either:
- // - in the NFC_QC/NFKC_QC list
- // - a non-starter char that is not canonically ordered
- //
- // We are going to capture the shortest UTF sequence that satisfies these two conditions:
- //
- // 1 - If the sequence does not start at the begginning of the string, it must begin with a starter,
- // and that starter must not have the NF[K]C_QC property equal to "MAYBE"
- //
- // 2 - If the sequence does not end at the end of the string, it must end with a non-starter and be
- // immediately followed by a starter that is not on the QC list
- //
- $utf_seq = array();
- $last_cc = 0;
- $lpos = $pos;
- $pos += $utf_len;
-
- if (isset($decomp_map[$utf_char]))
- {
- $_pos = 0;
- $_len = strlen($decomp_map[$utf_char]);
-
- do
- {
- $_utf_len =& $utf_len_mask[$decomp_map[$utf_char][$_pos] & "\xF0"];
-
- if (isset($_utf_len))
- {
- $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len);
- $_pos += $_utf_len;
- }
- else
- {
- $utf_seq[] = $decomp_map[$utf_char][$_pos];
- ++$_pos;
- }
- }
- while ($_pos < $_len);
- }
- else
- {
- // The char is not decomposable
- $utf_seq = array($utf_char);
- }
-
- // STEP 2: Capture the starter
-
- // Check out the combining class of the first character of the UTF sequence
- $k = 0;
- if (isset($utf_combining_class[$utf_seq[0]]) || $qc[$utf_char] == UNICODE_QC_MAYBE)
- {
- // Not a starter, inspect previous characters
- // The last 8 characters are kept in a buffer so that we don't have to capture them everytime.
- // This is enough for all real-life strings but even if it wasn't, we can capture characters in backward mode,
- // although it is slower than this method.
- //
- // In the following loop, $j starts at the previous buffered character ($i - 1, because current character is
- // at offset $i) and process them in backward mode until we find a starter.
- //
- // $k is the index on each UTF character inside of our UTF sequence. At this time, $utf_seq contains one or more
- // characters numbered 0 to n. $k starts at 0 and for each char we prepend we pre-decrement it and for numbering
- $starter_found = 0;
- $j_min = max(1, $i - 7);
-
- for ($j = $i - 1; $j >= $j_min && $lpos > $tmp_pos; --$j)
- {
- $utf_char = $buffer[$j & 7];
- $lpos -= strlen($utf_char);
-
- if (isset($decomp_map[$utf_char]))
- {
- // The char is a composite, decompose for storage
- $decomp_seq = array();
- $_pos = 0;
- $_len = strlen($decomp_map[$utf_char]);
-
- do
- {
- $c = $decomp_map[$utf_char][$_pos];
- $_utf_len =& $utf_len_mask[$c & "\xF0"];
-
- if (isset($_utf_len))
- {
- $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len);
- $_pos += $_utf_len;
- }
- else
- {
- $decomp_seq[] = $c;
- ++$_pos;
- }
- }
- while ($_pos < $_len);
-
- // Prepend the UTF sequence with our decomposed sequence
- if (isset($decomp_seq[1]))
- {
- // The char expanded into several chars
- $decomp_cnt = sizeof($decomp_seq);
-
- foreach ($decomp_seq as $decomp_i => $decomp_char)
- {
- $utf_seq[$k + $decomp_i - $decomp_cnt] = $decomp_char;
- }
- $k -= $decomp_cnt;
- }
- else
- {
- // Decomposed to a single char, easier to prepend
- $utf_seq[--$k] = $decomp_seq[0];
- }
- }
- else
- {
- $utf_seq[--$k] = $utf_char;
- }
-
- if (!isset($utf_combining_class[$utf_seq[$k]]))
- {
- // We have found our starter
- $starter_found = 1;
- break;
- }
- }
-
- if (!$starter_found && $lpos > $tmp_pos)
- {
- // The starter was not found in the buffer, let's rewind some more
- do
- {
- // $utf_len_mask contains the masks of both leading bytes and trailing bytes. If $utf_en > 0 then it's a leading byte, otherwise it's a trailing byte.
- $c = $str[--$lpos];
- $c_mask = $c & "\xF0";
-
- if (isset($utf_len_mask[$c_mask]))
- {
- // UTF byte
- if ($utf_len = $utf_len_mask[$c_mask])
- {
- // UTF *leading* byte
- $utf_char = substr($str, $lpos, $utf_len);
-
- if (isset($decomp_map[$utf_char]))
- {
- // Decompose the character
- $decomp_seq = array();
- $_pos = 0;
- $_len = strlen($decomp_map[$utf_char]);
-
- do
- {
- $c = $decomp_map[$utf_char][$_pos];
- $_utf_len =& $utf_len_mask[$c & "\xF0"];
-
- if (isset($_utf_len))
- {
- $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len);
- $_pos += $_utf_len;
- }
- else
- {
- $decomp_seq[] = $c;
- ++$_pos;
- }
- }
- while ($_pos < $_len);
-
- // Prepend the UTF sequence with our decomposed sequence
- if (isset($decomp_seq[1]))
- {
- // The char expanded into several chars
- $decomp_cnt = sizeof($decomp_seq);
- foreach ($decomp_seq as $decomp_i => $utf_char)
- {
- $utf_seq[$k + $decomp_i - $decomp_cnt] = $utf_char;
- }
- $k -= $decomp_cnt;
- }
- else
- {
- // Decomposed to a single char, easier to prepend
- $utf_seq[--$k] = $decomp_seq[0];
- }
- }
- else
- {
- $utf_seq[--$k] = $utf_char;
- }
- }
- }
- else
- {
- // ASCII char
- $utf_seq[--$k] = $c;
- }
- }
- while ($lpos > $tmp_pos);
- }
- }
-
- // STEP 3: Capture following combining modifiers
-
- while ($pos < $len)
- {
- $c_mask = $str[$pos] & "\xF0";
-
- if (isset($utf_len_mask[$c_mask]))
- {
- if ($utf_len = $utf_len_mask[$c_mask])
- {
- $utf_char = substr($str, $pos, $utf_len);
- }
- else
- {
- // A trailing byte came out of nowhere
- // Trailing bytes are replaced with Unicode replacement chars, we will just ignore it for now, break out of the loop
- // as if it was a starter (replacement chars ARE starters) and let the next loop replace it
- break;
- }
-
- if (isset($utf_combining_class[$utf_char]) || isset($qc[$utf_char]))
- {
- // Combining character, add it to the sequence and move the cursor
- if (isset($decomp_map[$utf_char]))
- {
- // Decompose the character
- $_pos = 0;
- $_len = strlen($decomp_map[$utf_char]);
-
- do
- {
- $c = $decomp_map[$utf_char][$_pos];
- $_utf_len =& $utf_len_mask[$c & "\xF0"];
-
- if (isset($_utf_len))
- {
- $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len);
- $_pos += $_utf_len;
- }
- else
- {
- $utf_seq[] = $c;
- ++$_pos;
- }
- }
- while ($_pos < $_len);
- }
- else
- {
- $utf_seq[] = $utf_char;
- }
-
- $pos += $utf_len;
- }
- else
- {
- // Combining class 0 and no QC, break out of the loop
- // Note: we do not know if that character is valid. If it's not, the next iteration will replace it
- break;
- }
- }
- else
- {
- // ASCII chars are starters
- break;
- }
- }
-
- // STEP 4: Sort and combine
-
- // Here we sort...
- $k_max = $k + sizeof($utf_seq);
-
- if (!$k && $k_max == 1)
- {
- // There is only one char in the UTF sequence, add it then jump to the next iteration of main loop
- // Note: the two commented lines below can be enabled under PHP5 for a very small performance gain in most cases
-// if (substr_compare($str, $utf_seq[0], $lpos, $pos - $lpos))
-// {
- $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $utf_seq[0];
- $tmp_pos = $pos;
-// }
-
- continue;
- }
-
- // ...there we combine
- if (isset($utf_combining_class[$utf_seq[$k]]))
- {
- $starter = $nf_seq = '';
- }
- else
- {
- $starter = $utf_seq[$k++];
- $nf_seq = '';
- }
- $utf_sort = array();
-
- // We add an empty char at the end of the UTF char sequence. It will act as a starter and trigger the sort/combine routine
- // at the end of the string without altering it
- $utf_seq[] = '';
-
- do
- {
- $utf_char = $utf_seq[$k++];
-
- if (isset($utf_combining_class[$utf_char]))
- {
- $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char;
- }
- else
- {
- if (empty($utf_sort))
- {
- // No combining characters... check for a composite of the two starters
- if (isset($utf_canonical_comp[$starter . $utf_char]))
- {
- // Good ol' composite character
- $starter = $utf_canonical_comp[$starter . $utf_char];
- }
- else if (isset($utf_jamo_type[$utf_char]))
- {
- // Current char is a composable jamo
- if (isset($utf_jamo_type[$starter]) && $utf_jamo_type[$starter] == UNICODE_JAMO_L && $utf_jamo_type[$utf_char] == UNICODE_JAMO_V)
- {
- // We have a L jamo followed by a V jamo, we are going to prefetch the next char to see if it's a T jamo
- if (isset($utf_jamo_type[$utf_seq[$k]]) && $utf_jamo_type[$utf_seq[$k]] == UNICODE_JAMO_T)
- {
- // L+V+T jamos, combine to a LVT Hangul syllable ($k is incremented)
- $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char] + $utf_jamo_index[$utf_seq[$k]];
- ++$k;
- }
- else
- {
- // L+V jamos, combine to a LV Hangul syllable
- $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char];
- }
-
- $starter = chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
- }
- else
- {
- // Non-composable jamo, just add it to the sequence
- $nf_seq .= $starter;
- $starter = $utf_char;
- }
- }
- else
- {
- // No composite, just add the first starter to the sequence then continue with the other one
- $nf_seq .= $starter;
- $starter = $utf_char;
- }
- }
- else
- {
- ksort($utf_sort);
-
- // For each class of combining characters
- foreach ($utf_sort as $cc => $utf_chars)
- {
- $j = 0;
-
- do
- {
- // Look for a composite
- if (isset($utf_canonical_comp[$starter . $utf_chars[$j]]))
- {
- // Found a composite, replace the starter
- $starter = $utf_canonical_comp[$starter . $utf_chars[$j]];
- unset($utf_sort[$cc][$j]);
- }
- else
- {
- // No composite, all following characters in that class are blocked
- break;
- }
- }
- while (isset($utf_sort[$cc][++$j]));
- }
-
- // Add the starter to the normalized sequence, followed by non-starters in canonical order
- $nf_seq .= $starter;
-
- foreach ($utf_sort as $utf_chars)
- {
- if (!empty($utf_chars))
- {
- $nf_seq .= implode('', $utf_chars);
- }
- }
-
- // Reset the array and go on
- $utf_sort = array();
- $starter = $utf_char;
- }
- }
- }
- while ($k <= $k_max);
-
- $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $nf_seq;
- $tmp_pos = $pos;
- }
- else
- {
- // Only a ASCII char can make the program get here
- //
- // First we skip the current byte with ++$pos, then we quickly skip following ASCII chars with strspn().
- //
- // The first two "if"'s here can be removed, with the consequences of being faster on latin text (lots of ASCII) and slower on
- // multi-byte text (where the only ASCII chars are spaces and punctuation)
- if (++$pos != $len)
- {
- if ($str[$pos] < "\x80")
- {
- $pos += strspn($str, UTF8_ASCII_RANGE, ++$pos);
- $buffer[++$i & 7] = $str[$pos - 1];
- }
- else
- {
- $buffer[++$i & 7] = $c;
- }
- }
- }
- }
- while ($pos < $len);
-
- // Now is time to return the string
- if ($tmp_pos)
- {
- // If the $tmp_pos cursor is not at the beggining of the string then at least one character was not in normal form. Replace $str with the fixed version
- if ($tmp_pos == $len)
- {
- // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str
- return $tmp;
- }
- else
- {
- // The rightmost chunk of $str has not been appended to $tmp yet
- return $tmp . substr($str, $tmp_pos);
- }
- }
-
- // The string was already in normal form
- return $str;
- }
-
- /**
- * Decompose a UTF string
- *
- * @param string $str UTF string
- * @param integer $pos Position of the first UTF char (in bytes)
- * @param integer $len Length of the string (in bytes)
- * @param array &$decomp_map Decomposition mapping, passed by reference but never modified
- * @return string The string, decomposed and sorted canonically
- *
- * @access private
- */
- static function decompose($str, $pos, $len, &$decomp_map)
- {
- global $utf_combining_class;
-
- // Load some commonly-used tables
- if (!isset($utf_combining_class))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx);
- }
-
- // UTF char length array
- $utf_len_mask = array(
- // Leading bytes masks
- "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4,
- // Trailing bytes masks
- "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0
- );
-
- // Some extra checks are triggered on the first byte of a UTF sequence
- $extra_check = array(
- "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1,
- "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1,
- "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1
- );
-
- // These masks are used to check if a UTF sequence is well formed. Here are the only 3 lengths we acknowledge:
- // - 2-byte: 110? ???? 10?? ????
- // - 3-byte: 1110 ???? 10?? ???? 10?? ????
- // - 4-byte: 1111 0??? 10?? ???? 10?? ???? 10?? ????
- // Note that 5- and 6- byte sequences are automatically discarded
- $utf_validation_mask = array(
- 2 => "\xE0\xC0",
- 3 => "\xF0\xC0\xC0",
- 4 => "\xF8\xC0\xC0\xC0"
- );
-
- $utf_validation_check = array(
- 2 => "\xC0\x80",
- 3 => "\xE0\x80\x80",
- 4 => "\xF0\x80\x80\x80"
- );
-
- $tmp = '';
- $starter_pos = $pos;
- $tmp_pos = $last_cc = $sort = $dump = 0;
- $utf_sort = array();
-
- // Main loop
- do
- {
- // STEP 0: Capture the current char
-
- $cur_mask = $str[$pos] & "\xF0";
- if (isset($utf_len_mask[$cur_mask]))
- {
- if ($utf_len = $utf_len_mask[$cur_mask])
- {
- // Multibyte char
- $utf_char = substr($str, $pos, $utf_len);
- $pos += $utf_len;
- }
- else
- {
- // A trailing byte came out of nowhere, we will treat it and all following trailing bytes as if each of them was a Unicode
- // replacement char and we will advance the cursor
- $spn = strspn($str, UTF8_TRAILING_BYTES, $pos);
-
- if ($dump)
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- // Dump combiners
- if (!empty($utf_sort))
- {
- if ($sort)
- {
- ksort($utf_sort);
- }
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- }
-
- $tmp .= str_repeat(UTF8_REPLACEMENT, $spn);
- $dump = $sort = 0;
- }
- else
- {
- $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn);
- }
-
- $pos += $spn;
- $tmp_pos = $starter_pos = $pos;
-
- $utf_sort = array();
- $last_cc = 0;
-
- continue;
- }
-
- // STEP 1: Decide what to do with current char
-
- // Now, in that order:
- // - check if that character is decomposable
- // - check if that character is a non-starter
- // - check if that character requires extra checks to be performed
- if (isset($decomp_map[$utf_char]))
- {
- // Decompose the char
- $_pos = 0;
- $_len = strlen($decomp_map[$utf_char]);
-
- do
- {
- $c = $decomp_map[$utf_char][$_pos];
- $_utf_len =& $utf_len_mask[$c & "\xF0"];
-
- if (isset($_utf_len))
- {
- $_utf_char = substr($decomp_map[$utf_char], $_pos, $_utf_len);
- $_pos += $_utf_len;
-
- if (isset($utf_combining_class[$_utf_char]))
- {
- // The character decomposed to a non-starter, buffer it for sorting
- $utf_sort[$utf_combining_class[$_utf_char]][] = $_utf_char;
-
- if ($utf_combining_class[$_utf_char] < $last_cc)
- {
- // Not canonically ordered, will require sorting
- $sort = $dump = 1;
- }
- else
- {
- $dump = 1;
- $last_cc = $utf_combining_class[$_utf_char];
- }
- }
- else
- {
- // This character decomposition contains a starter, dump the buffer and continue
- if ($dump)
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- // Dump combiners
- if (!empty($utf_sort))
- {
- if ($sort)
- {
- ksort($utf_sort);
- }
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- }
-
- $tmp .= $_utf_char;
- $dump = $sort = 0;
- }
- else
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos) . $_utf_char;
- }
-
- $tmp_pos = $starter_pos = $pos;
- $utf_sort = array();
- $last_cc = 0;
- }
- }
- else
- {
- // This character decomposition contains an ASCII char, which is a starter. Dump the buffer and continue
- ++$_pos;
-
- if ($dump)
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- // Dump combiners
- if (!empty($utf_sort))
- {
- if ($sort)
- {
- ksort($utf_sort);
- }
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- }
-
- $tmp .= $c;
- $dump = $sort = 0;
- }
- else
- {
- $tmp .= substr($str, $tmp_pos, $pos - $utf_len - $tmp_pos) . $c;
- }
-
- $tmp_pos = $starter_pos = $pos;
- $utf_sort = array();
- $last_cc = 0;
- }
- }
- while ($_pos < $_len);
- }
- else if (isset($utf_combining_class[$utf_char]))
- {
- // Combining character
- if ($utf_combining_class[$utf_char] < $last_cc)
- {
- // Not in canonical order
- $sort = $dump = 1;
- }
- else
- {
- $last_cc = $utf_combining_class[$utf_char];
- }
-
- $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char;
- }
- else
- {
- // Non-decomposable starter, check out if it's a Hangul syllable
- if ($utf_char < UTF8_HANGUL_FIRST || $utf_char > UTF8_HANGUL_LAST)
- {
- // Nope, regular UTF char, check that we have the correct number of trailing bytes
- if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len])
- {
- // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char
- // has been encoded in a five- or six- byte sequence.
- // Move the cursor back to its original position then advance it to the position it should really be at
- $pos -= $utf_len;
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- // Add a replacement char then another replacement char for every trailing byte.
- //
- // @todo I'm not entirely sure that's how we're supposed to mark invalidated byte sequences, check this
- $spn = strspn($str, UTF8_TRAILING_BYTES, ++$pos);
- $tmp .= str_repeat(UTF8_REPLACEMENT, $spn + 1);
-
- $dump = $sort = 0;
-
- $pos += $spn;
- $tmp_pos = $pos;
- continue;
- }
-
- if (isset($extra_check[$utf_char[0]]))
- {
- switch ($utf_char[0])
- {
- // Note: 0xED is quite common in Korean
- case "\xED":
- if ($utf_char >= "\xED\xA0\x80")
- {
- // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF)
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- $tmp .= UTF8_REPLACEMENT;
- $dump = $sort = 0;
-
- $tmp_pos = $starter_pos = $pos;
- continue 2;
- }
- break;
-
- // Note: 0xEF is quite common in Japanese
- case "\xEF":
- if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF")
- {
- // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF)
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- $tmp .= UTF8_REPLACEMENT;
- $dump = $sort = 0;
-
- $tmp_pos = $starter_pos = $pos;
- continue 2;
- }
- break;
-
- case "\xC0":
- case "\xC1":
- if ($utf_char <= "\xC1\xBF")
- {
- // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- $tmp .= UTF8_REPLACEMENT;
- $dump = $sort = 0;
-
- $tmp_pos = $starter_pos = $pos;
- continue 2;
- }
- break;
-
- case "\xE0":
- if ($utf_char <= "\xE0\x9F\xBF")
- {
- // Unicode char U+0000..U+07FF encoded in 3 bytes
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- $tmp .= UTF8_REPLACEMENT;
- $dump = $sort = 0;
-
- $tmp_pos = $starter_pos = $pos;
- continue 2;
- }
- break;
-
- case "\xF0":
- if ($utf_char <= "\xF0\x8F\xBF\xBF")
- {
- // Unicode char U+0000..U+FFFF encoded in 4 bytes
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- $tmp .= UTF8_REPLACEMENT;
- $dump = $sort = 0;
-
- $tmp_pos = $starter_pos = $pos;
- continue 2;
- }
- break;
-
- default:
- if ($utf_char > UTF8_MAX)
- {
- // Out of the Unicode range
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- if (!empty($utf_sort))
- {
- ksort($utf_sort);
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- $utf_sort = array();
- }
-
- $tmp .= UTF8_REPLACEMENT;
- $dump = $sort = 0;
-
- $tmp_pos = $starter_pos = $pos;
- continue 2;
- }
- break;
- }
- }
- }
- else
- {
- // Hangul syllable
- $idx = (((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F)) - UNICODE_HANGUL_SBASE;
-
- // LIndex can only range from 0 to 18, therefore it cannot influence the first two bytes of the L Jamo, which allows us to hardcode them (based on LBase).
- //
- // The same goes for VIndex, but for TIndex there's a catch: the value of the third byte could exceed 0xBF and we would have to increment the second byte
- if ($t_index = $idx % UNICODE_HANGUL_TCOUNT)
- {
- if ($t_index < 25)
- {
- $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x86\x00";
- $utf_char[8] = chr(0xA7 + $t_index);
- }
- else
- {
- $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x87\x00";
- $utf_char[8] = chr(0x67 + $t_index);
- }
- }
- else
- {
- $utf_char = "\xE1\x84\x00\xE1\x85\x00";
- }
-
- $utf_char[2] = chr(0x80 + (int) ($idx / UNICODE_HANGUL_NCOUNT));
- $utf_char[5] = chr(0xA1 + (int) (($idx % UNICODE_HANGUL_NCOUNT) / UNICODE_HANGUL_TCOUNT));
-
- // Just like other decompositions, the resulting Jamos must be dumped to the tmp string
- $dump = 1;
- }
-
- // Do we need to dump stuff to the tmp string?
- if ($dump)
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- // Dump combiners
- if (!empty($utf_sort))
- {
- if ($sort)
- {
- ksort($utf_sort);
- }
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- }
-
- $tmp .= $utf_char;
- $dump = $sort = 0;
- $tmp_pos = $pos;
- }
-
- $last_cc = 0;
- $utf_sort = array();
- $starter_pos = $pos;
- }
- }
- else
- {
- // ASCII char, which happens to be a starter (as any other ASCII char)
- if ($dump)
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- // Dump combiners
- if (!empty($utf_sort))
- {
- if ($sort)
- {
- ksort($utf_sort);
- }
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- }
-
- $tmp .= $str[$pos];
- $dump = $sort = 0;
- $tmp_pos = ++$pos;
-
- $pos += strspn($str, UTF8_ASCII_RANGE, $pos);
- }
- else
- {
- $pos += strspn($str, UTF8_ASCII_RANGE, ++$pos);
- }
-
- $last_cc = 0;
- $utf_sort = array();
- $starter_pos = $pos;
- }
- }
- while ($pos < $len);
-
- // Now is time to return the string
- if ($dump)
- {
- $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
-
- // Dump combiners
- if (!empty($utf_sort))
- {
- if ($sort)
- {
- ksort($utf_sort);
- }
-
- foreach ($utf_sort as $utf_chars)
- {
- $tmp .= implode('', $utf_chars);
- }
- }
-
- return $tmp;
- }
- else if ($tmp_pos)
- {
- // If the $tmp_pos cursor was moved then at least one character was not in normal form. Replace $str with the fixed version
- if ($tmp_pos == $len)
- {
- // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str
- return $tmp;
- }
- else
- {
- // The rightmost chunk of $str has not been appended to $tmp yet
- return $tmp . substr($str, $tmp_pos);
- }
- }
-
- // The string was already in normal form
- return $str;
- }
-}
diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php
index e60a40a195..01caf47349 100644
--- a/phpBB/includes/utf/utf_tools.php
+++ b/phpBB/includes/utf/utf_tools.php
@@ -22,6 +22,13 @@ if (!defined('IN_PHPBB'))
setlocale(LC_CTYPE, 'C');
/**
+* Setup the UTF-8 portability layer
+*/
+Patchwork\Utf8\Bootup::initUtf8Encode();
+Patchwork\Utf8\Bootup::initMbstring();
+Patchwork\Utf8\Bootup::initIntl();
+
+/**
* UTF-8 tools
*
* Whenever possible, these functions will try to use PHP's built-in functions or
@@ -29,544 +36,85 @@ setlocale(LC_CTYPE, 'C');
*
*/
-if (!extension_loaded('xml'))
-{
- /**
- * Implementation of PHP's native utf8_encode for people without XML support
- * This function exploits some nice things that ISO-8859-1 and UTF-8 have in common
- *
- * @param string $str ISO-8859-1 encoded data
- * @return string UTF-8 encoded data
- */
- function utf8_encode($str)
- {
- $out = '';
- for ($i = 0, $len = strlen($str); $i < $len; $i++)
- {
- $letter = $str[$i];
- $num = ord($letter);
- if ($num < 0x80)
- {
- $out .= $letter;
- }
- else if ($num < 0xC0)
- {
- $out .= "\xC2" . $letter;
- }
- else
- {
- $out .= "\xC3" . chr($num - 64);
- }
- }
- return $out;
- }
-
- /**
- * Implementation of PHP's native utf8_decode for people without XML support
- *
- * @param string $str UTF-8 encoded data
- * @return string ISO-8859-1 encoded data
- */
- function utf8_decode($str)
- {
- $pos = 0;
- $len = strlen($str);
- $ret = '';
-
- while ($pos < $len)
- {
- $ord = ord($str[$pos]) & 0xF0;
- if ($ord === 0xC0 || $ord === 0xD0)
- {
- $charval = ((ord($str[$pos]) & 0x1F) << 6) | (ord($str[$pos + 1]) & 0x3F);
- $pos += 2;
- $ret .= (($charval < 256) ? chr($charval) : '?');
- }
- else if ($ord === 0xE0)
- {
- $ret .= '?';
- $pos += 3;
- }
- else if ($ord === 0xF0)
- {
- $ret .= '?';
- $pos += 4;
- }
- else
- {
- $ret .= $str[$pos];
- ++$pos;
- }
- }
- return $ret;
- }
-}
-
-// mbstring is old and has it's functions around for older versions of PHP.
-// if mbstring is not loaded, we go into native mode.
-if (extension_loaded('mbstring'))
+/**
+* UTF-8 aware alternative to strrpos
+* @ignore
+*/
+function utf8_strrpos($str, $needle, $offset = null)
{
- mb_internal_encoding('UTF-8');
-
- /**
- * UTF-8 aware alternative to strrpos
- * Find position of last occurrence of a char in a string
- */
- /**
- * UTF-8 aware alternative to strrpos
- * @ignore
- */
- function utf8_strrpos($str, $needle, $offset = null)
+ // Emulate behaviour of strrpos rather than raising warning
+ if (empty($str))
{
- // Emulate behaviour of strrpos rather than raising warning
- if (empty($str))
- {
- return false;
- }
-
- if (is_null($offset))
- {
- return mb_strrpos($str, $needle);
- }
- else
- {
- return mb_strrpos($str, $needle, $offset);
- }
- }
-
- /**
- * UTF-8 aware alternative to strpos
- * @ignore
- */
- function utf8_strpos($str, $needle, $offset = null)
- {
- if (is_null($offset))
- {
- return mb_strpos($str, $needle);
- }
- else
- {
- return mb_strpos($str, $needle, $offset);
- }
+ return false;
}
- /**
- * UTF-8 aware alternative to strtolower
- * @ignore
- */
- function utf8_strtolower($str)
+ if (is_null($offset))
{
- return mb_strtolower($str);
+ return mb_strrpos($str, $needle);
}
-
- /**
- * UTF-8 aware alternative to strtoupper
- * @ignore
- */
- function utf8_strtoupper($str)
+ else
{
- return mb_strtoupper($str);
+ return mb_strrpos($str, $needle, $offset);
}
+}
- /**
- * UTF-8 aware alternative to substr
- * @ignore
- */
- function utf8_substr($str, $offset, $length = null)
+/**
+* UTF-8 aware alternative to strpos
+* @ignore
+*/
+function utf8_strpos($str, $needle, $offset = null)
+{
+ if (is_null($offset))
{
- if (is_null($length))
- {
- return mb_substr($str, $offset);
- }
- else
- {
- return mb_substr($str, $offset, $length);
- }
+ return mb_strpos($str, $needle);
}
-
- /**
- * Return the length (in characters) of a UTF-8 string
- * @ignore
- */
- function utf8_strlen($text)
+ else
{
- return mb_strlen($text, 'utf-8');
+ return mb_strpos($str, $needle, $offset);
}
}
-else
-{
- /**
- * UTF-8 aware alternative to strrpos
- * Find position of last occurrence of a char in a string
- *
- * @author Harry Fuecks
- * @param string $str haystack
- * @param string $needle needle
- * @param integer $offset (optional) offset (from left)
- * @return mixed integer position or FALSE on failure
- */
- function utf8_strrpos($str, $needle, $offset = null)
- {
- if (is_null($offset))
- {
- $ar = explode($needle, $str);
-
- if (sizeof($ar) > 1)
- {
- // Pop off the end of the string where the last match was made
- array_pop($ar);
- $str = join($needle, $ar);
-
- return utf8_strlen($str);
- }
- return false;
- }
- else
- {
- if (!is_int($offset))
- {
- trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_ERROR);
- return false;
- }
-
- $str = utf8_substr($str, $offset);
-
- if (false !== ($pos = utf8_strrpos($str, $needle)))
- {
- return $pos + $offset;
- }
-
- return false;
- }
- }
- /**
- * UTF-8 aware alternative to strpos
- * Find position of first occurrence of a string
- *
- * @author Harry Fuecks
- * @param string $str haystack
- * @param string $needle needle
- * @param integer $offset offset in characters (from left)
- * @return mixed integer position or FALSE on failure
- */
- function utf8_strpos($str, $needle, $offset = null)
- {
- if (is_null($offset))
- {
- $ar = explode($needle, $str);
- if (sizeof($ar) > 1)
- {
- return utf8_strlen($ar[0]);
- }
- return false;
- }
- else
- {
- if (!is_int($offset))
- {
- trigger_error('utf8_strpos: Offset must be an integer', E_USER_ERROR);
- return false;
- }
-
- $str = utf8_substr($str, $offset);
-
- if (false !== ($pos = utf8_strpos($str, $needle)))
- {
- return $pos + $offset;
- }
+/**
+* UTF-8 aware alternative to strtolower
+* @ignore
+*/
+function utf8_strtolower($str)
+{
+ return mb_strtolower($str);
+}
- return false;
- }
- }
+/**
+* UTF-8 aware alternative to strtoupper
+* @ignore
+*/
+function utf8_strtoupper($str)
+{
+ return mb_strtoupper($str);
+}
- /**
- * UTF-8 aware alternative to strtolower
- * Make a string lowercase
- * Note: The concept of a characters "case" only exists is some alphabets
- * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
- * not exist in the Chinese alphabet, for example. See Unicode Standard
- * Annex #21: Case Mappings
- *
- * @param string
- * @return string string in lowercase
- */
- function utf8_strtolower($string)
+/**
+* UTF-8 aware alternative to substr
+* @ignore
+*/
+function utf8_substr($str, $offset, $length = null)
+{
+ if (is_null($length))
{
- static $utf8_upper_to_lower = array(
- "\xC3\x80" => "\xC3\xA0", "\xC3\x81" => "\xC3\xA1",
- "\xC3\x82" => "\xC3\xA2", "\xC3\x83" => "\xC3\xA3", "\xC3\x84" => "\xC3\xA4", "\xC3\x85" => "\xC3\xA5",
- "\xC3\x86" => "\xC3\xA6", "\xC3\x87" => "\xC3\xA7", "\xC3\x88" => "\xC3\xA8", "\xC3\x89" => "\xC3\xA9",
- "\xC3\x8A" => "\xC3\xAA", "\xC3\x8B" => "\xC3\xAB", "\xC3\x8C" => "\xC3\xAC", "\xC3\x8D" => "\xC3\xAD",
- "\xC3\x8E" => "\xC3\xAE", "\xC3\x8F" => "\xC3\xAF", "\xC3\x90" => "\xC3\xB0", "\xC3\x91" => "\xC3\xB1",
- "\xC3\x92" => "\xC3\xB2", "\xC3\x93" => "\xC3\xB3", "\xC3\x94" => "\xC3\xB4", "\xC3\x95" => "\xC3\xB5",
- "\xC3\x96" => "\xC3\xB6", "\xC3\x98" => "\xC3\xB8", "\xC3\x99" => "\xC3\xB9", "\xC3\x9A" => "\xC3\xBA",
- "\xC3\x9B" => "\xC3\xBB", "\xC3\x9C" => "\xC3\xBC", "\xC3\x9D" => "\xC3\xBD", "\xC3\x9E" => "\xC3\xBE",
- "\xC4\x80" => "\xC4\x81", "\xC4\x82" => "\xC4\x83", "\xC4\x84" => "\xC4\x85", "\xC4\x86" => "\xC4\x87",
- "\xC4\x88" => "\xC4\x89", "\xC4\x8A" => "\xC4\x8B", "\xC4\x8C" => "\xC4\x8D", "\xC4\x8E" => "\xC4\x8F",
- "\xC4\x90" => "\xC4\x91", "\xC4\x92" => "\xC4\x93", "\xC4\x96" => "\xC4\x97", "\xC4\x98" => "\xC4\x99",
- "\xC4\x9A" => "\xC4\x9B", "\xC4\x9C" => "\xC4\x9D", "\xC4\x9E" => "\xC4\x9F", "\xC4\xA0" => "\xC4\xA1",
- "\xC4\xA2" => "\xC4\xA3", "\xC4\xA4" => "\xC4\xA5", "\xC4\xA6" => "\xC4\xA7", "\xC4\xA8" => "\xC4\xA9",
- "\xC4\xAA" => "\xC4\xAB", "\xC4\xAE" => "\xC4\xAF", "\xC4\xB4" => "\xC4\xB5", "\xC4\xB6" => "\xC4\xB7",
- "\xC4\xB9" => "\xC4\xBA", "\xC4\xBB" => "\xC4\xBC", "\xC4\xBD" => "\xC4\xBE", "\xC5\x81" => "\xC5\x82",
- "\xC5\x83" => "\xC5\x84", "\xC5\x85" => "\xC5\x86", "\xC5\x87" => "\xC5\x88", "\xC5\x8A" => "\xC5\x8B",
- "\xC5\x8C" => "\xC5\x8D", "\xC5\x90" => "\xC5\x91", "\xC5\x94" => "\xC5\x95", "\xC5\x96" => "\xC5\x97",
- "\xC5\x98" => "\xC5\x99", "\xC5\x9A" => "\xC5\x9B", "\xC5\x9C" => "\xC5\x9D", "\xC5\x9E" => "\xC5\x9F",
- "\xC5\xA0" => "\xC5\xA1", "\xC5\xA2" => "\xC5\xA3", "\xC5\xA4" => "\xC5\xA5", "\xC5\xA6" => "\xC5\xA7",
- "\xC5\xA8" => "\xC5\xA9", "\xC5\xAA" => "\xC5\xAB", "\xC5\xAC" => "\xC5\xAD", "\xC5\xAE" => "\xC5\xAF",
- "\xC5\xB0" => "\xC5\xB1", "\xC5\xB2" => "\xC5\xB3", "\xC5\xB4" => "\xC5\xB5", "\xC5\xB6" => "\xC5\xB7",
- "\xC5\xB8" => "\xC3\xBF", "\xC5\xB9" => "\xC5\xBA", "\xC5\xBB" => "\xC5\xBC", "\xC5\xBD" => "\xC5\xBE",
- "\xC6\xA0" => "\xC6\xA1", "\xC6\xAF" => "\xC6\xB0", "\xC8\x98" => "\xC8\x99", "\xC8\x9A" => "\xC8\x9B",
- "\xCE\x86" => "\xCE\xAC", "\xCE\x88" => "\xCE\xAD", "\xCE\x89" => "\xCE\xAE", "\xCE\x8A" => "\xCE\xAF",
- "\xCE\x8C" => "\xCF\x8C", "\xCE\x8E" => "\xCF\x8D", "\xCE\x8F" => "\xCF\x8E", "\xCE\x91" => "\xCE\xB1",
- "\xCE\x92" => "\xCE\xB2", "\xCE\x93" => "\xCE\xB3", "\xCE\x94" => "\xCE\xB4", "\xCE\x95" => "\xCE\xB5",
- "\xCE\x96" => "\xCE\xB6", "\xCE\x97" => "\xCE\xB7", "\xCE\x98" => "\xCE\xB8", "\xCE\x99" => "\xCE\xB9",
- "\xCE\x9A" => "\xCE\xBA", "\xCE\x9B" => "\xCE\xBB", "\xCE\x9C" => "\xCE\xBC", "\xCE\x9D" => "\xCE\xBD",
- "\xCE\x9E" => "\xCE\xBE", "\xCE\x9F" => "\xCE\xBF", "\xCE\xA0" => "\xCF\x80", "\xCE\xA1" => "\xCF\x81",
- "\xCE\xA3" => "\xCF\x83", "\xCE\xA4" => "\xCF\x84", "\xCE\xA5" => "\xCF\x85", "\xCE\xA6" => "\xCF\x86",
- "\xCE\xA7" => "\xCF\x87", "\xCE\xA8" => "\xCF\x88", "\xCE\xA9" => "\xCF\x89", "\xCE\xAA" => "\xCF\x8A",
- "\xCE\xAB" => "\xCF\x8B", "\xD0\x81" => "\xD1\x91", "\xD0\x82" => "\xD1\x92", "\xD0\x83" => "\xD1\x93",
- "\xD0\x84" => "\xD1\x94", "\xD0\x85" => "\xD1\x95", "\xD0\x86" => "\xD1\x96", "\xD0\x87" => "\xD1\x97",
- "\xD0\x88" => "\xD1\x98", "\xD0\x89" => "\xD1\x99", "\xD0\x8A" => "\xD1\x9A", "\xD0\x8B" => "\xD1\x9B",
- "\xD0\x8C" => "\xD1\x9C", "\xD0\x8E" => "\xD1\x9E", "\xD0\x8F" => "\xD1\x9F", "\xD0\x90" => "\xD0\xB0",
- "\xD0\x91" => "\xD0\xB1", "\xD0\x92" => "\xD0\xB2", "\xD0\x93" => "\xD0\xB3", "\xD0\x94" => "\xD0\xB4",
- "\xD0\x95" => "\xD0\xB5", "\xD0\x96" => "\xD0\xB6", "\xD0\x97" => "\xD0\xB7", "\xD0\x98" => "\xD0\xB8",
- "\xD0\x99" => "\xD0\xB9", "\xD0\x9A" => "\xD0\xBA", "\xD0\x9B" => "\xD0\xBB", "\xD0\x9C" => "\xD0\xBC",
- "\xD0\x9D" => "\xD0\xBD", "\xD0\x9E" => "\xD0\xBE", "\xD0\x9F" => "\xD0\xBF", "\xD0\xA0" => "\xD1\x80",
- "\xD0\xA1" => "\xD1\x81", "\xD0\xA2" => "\xD1\x82", "\xD0\xA3" => "\xD1\x83", "\xD0\xA4" => "\xD1\x84",
- "\xD0\xA5" => "\xD1\x85", "\xD0\xA6" => "\xD1\x86", "\xD0\xA7" => "\xD1\x87", "\xD0\xA8" => "\xD1\x88",
- "\xD0\xA9" => "\xD1\x89", "\xD0\xAA" => "\xD1\x8A", "\xD0\xAB" => "\xD1\x8B", "\xD0\xAC" => "\xD1\x8C",
- "\xD0\xAD" => "\xD1\x8D", "\xD0\xAE" => "\xD1\x8E", "\xD0\xAF" => "\xD1\x8F", "\xD2\x90" => "\xD2\x91",
- "\xE1\xB8\x82" => "\xE1\xB8\x83", "\xE1\xB8\x8A" => "\xE1\xB8\x8B", "\xE1\xB8\x9E" => "\xE1\xB8\x9F", "\xE1\xB9\x80" => "\xE1\xB9\x81",
- "\xE1\xB9\x96" => "\xE1\xB9\x97", "\xE1\xB9\xA0" => "\xE1\xB9\xA1", "\xE1\xB9\xAA" => "\xE1\xB9\xAB", "\xE1\xBA\x80" => "\xE1\xBA\x81",
- "\xE1\xBA\x82" => "\xE1\xBA\x83", "\xE1\xBA\x84" => "\xE1\xBA\x85", "\xE1\xBB\xB2" => "\xE1\xBB\xB3"
- );
-
- return strtr(strtolower($string), $utf8_upper_to_lower);
+ return mb_substr($str, $offset);
}
-
- /**
- * UTF-8 aware alternative to strtoupper
- * Make a string uppercase
- * Note: The concept of a characters "case" only exists is some alphabets
- * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
- * not exist in the Chinese alphabet, for example. See Unicode Standard
- * Annex #21: Case Mappings
- *
- * @param string
- * @return string string in uppercase
- */
- function utf8_strtoupper($string)
+ else
{
- static $utf8_lower_to_upper = array(
- "\xC3\xA0" => "\xC3\x80", "\xC3\xA1" => "\xC3\x81",
- "\xC3\xA2" => "\xC3\x82", "\xC3\xA3" => "\xC3\x83", "\xC3\xA4" => "\xC3\x84", "\xC3\xA5" => "\xC3\x85",
- "\xC3\xA6" => "\xC3\x86", "\xC3\xA7" => "\xC3\x87", "\xC3\xA8" => "\xC3\x88", "\xC3\xA9" => "\xC3\x89",
- "\xC3\xAA" => "\xC3\x8A", "\xC3\xAB" => "\xC3\x8B", "\xC3\xAC" => "\xC3\x8C", "\xC3\xAD" => "\xC3\x8D",
- "\xC3\xAE" => "\xC3\x8E", "\xC3\xAF" => "\xC3\x8F", "\xC3\xB0" => "\xC3\x90", "\xC3\xB1" => "\xC3\x91",
- "\xC3\xB2" => "\xC3\x92", "\xC3\xB3" => "\xC3\x93", "\xC3\xB4" => "\xC3\x94", "\xC3\xB5" => "\xC3\x95",
- "\xC3\xB6" => "\xC3\x96", "\xC3\xB8" => "\xC3\x98", "\xC3\xB9" => "\xC3\x99", "\xC3\xBA" => "\xC3\x9A",
- "\xC3\xBB" => "\xC3\x9B", "\xC3\xBC" => "\xC3\x9C", "\xC3\xBD" => "\xC3\x9D", "\xC3\xBE" => "\xC3\x9E",
- "\xC3\xBF" => "\xC5\xB8", "\xC4\x81" => "\xC4\x80", "\xC4\x83" => "\xC4\x82", "\xC4\x85" => "\xC4\x84",
- "\xC4\x87" => "\xC4\x86", "\xC4\x89" => "\xC4\x88", "\xC4\x8B" => "\xC4\x8A", "\xC4\x8D" => "\xC4\x8C",
- "\xC4\x8F" => "\xC4\x8E", "\xC4\x91" => "\xC4\x90", "\xC4\x93" => "\xC4\x92", "\xC4\x97" => "\xC4\x96",
- "\xC4\x99" => "\xC4\x98", "\xC4\x9B" => "\xC4\x9A", "\xC4\x9D" => "\xC4\x9C", "\xC4\x9F" => "\xC4\x9E",
- "\xC4\xA1" => "\xC4\xA0", "\xC4\xA3" => "\xC4\xA2", "\xC4\xA5" => "\xC4\xA4", "\xC4\xA7" => "\xC4\xA6",
- "\xC4\xA9" => "\xC4\xA8", "\xC4\xAB" => "\xC4\xAA", "\xC4\xAF" => "\xC4\xAE", "\xC4\xB5" => "\xC4\xB4",
- "\xC4\xB7" => "\xC4\xB6", "\xC4\xBA" => "\xC4\xB9", "\xC4\xBC" => "\xC4\xBB", "\xC4\xBE" => "\xC4\xBD",
- "\xC5\x82" => "\xC5\x81", "\xC5\x84" => "\xC5\x83", "\xC5\x86" => "\xC5\x85", "\xC5\x88" => "\xC5\x87",
- "\xC5\x8B" => "\xC5\x8A", "\xC5\x8D" => "\xC5\x8C", "\xC5\x91" => "\xC5\x90", "\xC5\x95" => "\xC5\x94",
- "\xC5\x97" => "\xC5\x96", "\xC5\x99" => "\xC5\x98", "\xC5\x9B" => "\xC5\x9A", "\xC5\x9D" => "\xC5\x9C",
- "\xC5\x9F" => "\xC5\x9E", "\xC5\xA1" => "\xC5\xA0", "\xC5\xA3" => "\xC5\xA2", "\xC5\xA5" => "\xC5\xA4",
- "\xC5\xA7" => "\xC5\xA6", "\xC5\xA9" => "\xC5\xA8", "\xC5\xAB" => "\xC5\xAA", "\xC5\xAD" => "\xC5\xAC",
- "\xC5\xAF" => "\xC5\xAE", "\xC5\xB1" => "\xC5\xB0", "\xC5\xB3" => "\xC5\xB2", "\xC5\xB5" => "\xC5\xB4",
- "\xC5\xB7" => "\xC5\xB6", "\xC5\xBA" => "\xC5\xB9", "\xC5\xBC" => "\xC5\xBB", "\xC5\xBE" => "\xC5\xBD",
- "\xC6\xA1" => "\xC6\xA0", "\xC6\xB0" => "\xC6\xAF", "\xC8\x99" => "\xC8\x98", "\xC8\x9B" => "\xC8\x9A",
- "\xCE\xAC" => "\xCE\x86", "\xCE\xAD" => "\xCE\x88", "\xCE\xAE" => "\xCE\x89", "\xCE\xAF" => "\xCE\x8A",
- "\xCE\xB1" => "\xCE\x91", "\xCE\xB2" => "\xCE\x92", "\xCE\xB3" => "\xCE\x93", "\xCE\xB4" => "\xCE\x94",
- "\xCE\xB5" => "\xCE\x95", "\xCE\xB6" => "\xCE\x96", "\xCE\xB7" => "\xCE\x97", "\xCE\xB8" => "\xCE\x98",
- "\xCE\xB9" => "\xCE\x99", "\xCE\xBA" => "\xCE\x9A", "\xCE\xBB" => "\xCE\x9B", "\xCE\xBC" => "\xCE\x9C",
- "\xCE\xBD" => "\xCE\x9D", "\xCE\xBE" => "\xCE\x9E", "\xCE\xBF" => "\xCE\x9F", "\xCF\x80" => "\xCE\xA0",
- "\xCF\x81" => "\xCE\xA1", "\xCF\x83" => "\xCE\xA3", "\xCF\x84" => "\xCE\xA4", "\xCF\x85" => "\xCE\xA5",
- "\xCF\x86" => "\xCE\xA6", "\xCF\x87" => "\xCE\xA7", "\xCF\x88" => "\xCE\xA8", "\xCF\x89" => "\xCE\xA9",
- "\xCF\x8A" => "\xCE\xAA", "\xCF\x8B" => "\xCE\xAB", "\xCF\x8C" => "\xCE\x8C", "\xCF\x8D" => "\xCE\x8E",
- "\xCF\x8E" => "\xCE\x8F", "\xD0\xB0" => "\xD0\x90", "\xD0\xB1" => "\xD0\x91", "\xD0\xB2" => "\xD0\x92",
- "\xD0\xB3" => "\xD0\x93", "\xD0\xB4" => "\xD0\x94", "\xD0\xB5" => "\xD0\x95", "\xD0\xB6" => "\xD0\x96",
- "\xD0\xB7" => "\xD0\x97", "\xD0\xB8" => "\xD0\x98", "\xD0\xB9" => "\xD0\x99", "\xD0\xBA" => "\xD0\x9A",
- "\xD0\xBB" => "\xD0\x9B", "\xD0\xBC" => "\xD0\x9C", "\xD0\xBD" => "\xD0\x9D", "\xD0\xBE" => "\xD0\x9E",
- "\xD0\xBF" => "\xD0\x9F", "\xD1\x80" => "\xD0\xA0", "\xD1\x81" => "\xD0\xA1", "\xD1\x82" => "\xD0\xA2",
- "\xD1\x83" => "\xD0\xA3", "\xD1\x84" => "\xD0\xA4", "\xD1\x85" => "\xD0\xA5", "\xD1\x86" => "\xD0\xA6",
- "\xD1\x87" => "\xD0\xA7", "\xD1\x88" => "\xD0\xA8", "\xD1\x89" => "\xD0\xA9", "\xD1\x8A" => "\xD0\xAA",
- "\xD1\x8B" => "\xD0\xAB", "\xD1\x8C" => "\xD0\xAC", "\xD1\x8D" => "\xD0\xAD", "\xD1\x8E" => "\xD0\xAE",
- "\xD1\x8F" => "\xD0\xAF", "\xD1\x91" => "\xD0\x81", "\xD1\x92" => "\xD0\x82", "\xD1\x93" => "\xD0\x83",
- "\xD1\x94" => "\xD0\x84", "\xD1\x95" => "\xD0\x85", "\xD1\x96" => "\xD0\x86", "\xD1\x97" => "\xD0\x87",
- "\xD1\x98" => "\xD0\x88", "\xD1\x99" => "\xD0\x89", "\xD1\x9A" => "\xD0\x8A", "\xD1\x9B" => "\xD0\x8B",
- "\xD1\x9C" => "\xD0\x8C", "\xD1\x9E" => "\xD0\x8E", "\xD1\x9F" => "\xD0\x8F", "\xD2\x91" => "\xD2\x90",
- "\xE1\xB8\x83" => "\xE1\xB8\x82", "\xE1\xB8\x8B" => "\xE1\xB8\x8A", "\xE1\xB8\x9F" => "\xE1\xB8\x9E", "\xE1\xB9\x81" => "\xE1\xB9\x80",
- "\xE1\xB9\x97" => "\xE1\xB9\x96", "\xE1\xB9\xA1" => "\xE1\xB9\xA0", "\xE1\xB9\xAB" => "\xE1\xB9\xAA", "\xE1\xBA\x81" => "\xE1\xBA\x80",
- "\xE1\xBA\x83" => "\xE1\xBA\x82", "\xE1\xBA\x85" => "\xE1\xBA\x84", "\xE1\xBB\xB3" => "\xE1\xBB\xB2"
- );
-
- return strtr(strtoupper($string), $utf8_lower_to_upper);
- }
-
- /**
- * UTF-8 aware alternative to substr
- * Return part of a string given character offset (and optionally length)
- *
- * Note arguments: comparied to substr - if offset or length are
- * not integers, this version will not complain but rather massages them
- * into an integer.
- *
- * Note on returned values: substr documentation states false can be
- * returned in some cases (e.g. offset > string length)
- * mb_substr never returns false, it will return an empty string instead.
- * This adopts the mb_substr approach
- *
- * Note on implementation: PCRE only supports repetitions of less than
- * 65536, in order to accept up to MAXINT values for offset and length,
- * we'll repeat a group of 65535 characters when needed.
- *
- * Note on implementation: calculating the number of characters in the
- * string is a relatively expensive operation, so we only carry it out when
- * necessary. It isn't necessary for +ve offsets and no specified length
- *
- * @author Chris Smith<chris@jalakai.co.uk>
- * @param string $str
- * @param integer $offset number of UTF-8 characters offset (from left)
- * @param integer $length (optional) length in UTF-8 characters from offset
- * @return mixed string or FALSE if failure
- */
- function utf8_substr($str, $offset, $length = NULL)
- {
- // generates E_NOTICE
- // for PHP4 objects, but not PHP5 objects
- $str = (string) $str;
- $offset = (int) $offset;
- if (!is_null($length))
- {
- $length = (int) $length;
- }
-
- // handle trivial cases
- if ($length === 0 || ($offset < 0 && $length < 0 && $length < $offset))
- {
- return '';
- }
-
- // normalise negative offsets (we could use a tail
- // anchored pattern, but they are horribly slow!)
- if ($offset < 0)
- {
- // see notes
- $strlen = utf8_strlen($str);
- $offset = $strlen + $offset;
- if ($offset < 0)
- {
- $offset = 0;
- }
- }
-
- $op = '';
- $lp = '';
-
- // establish a pattern for offset, a
- // non-captured group equal in length to offset
- if ($offset > 0)
- {
- $ox = (int) ($offset / 65535);
- $oy = $offset % 65535;
-
- if ($ox)
- {
- $op = '(?:.{65535}){' . $ox . '}';
- }
-
- $op = '^(?:' . $op . '.{' . $oy . '})';
- }
- else
- {
- // offset == 0; just anchor the pattern
- $op = '^';
- }
-
- // establish a pattern for length
- if (is_null($length))
- {
- // the rest of the string
- $lp = '(.*)$';
- }
- else
- {
- if (!isset($strlen))
- {
- // see notes
- $strlen = utf8_strlen($str);
- }
-
- // another trivial case
- if ($offset > $strlen)
- {
- return '';
- }
-
- if ($length > 0)
- {
- // reduce any length that would
- // go passed the end of the string
- $length = min($strlen - $offset, $length);
-
- $lx = (int) ($length / 65535);
- $ly = $length % 65535;
-
- // negative length requires a captured group
- // of length characters
- if ($lx)
- {
- $lp = '(?:.{65535}){' . $lx . '}';
- }
- $lp = '(' . $lp . '.{'. $ly . '})';
- }
- else if ($length < 0)
- {
- if ($length < ($offset - $strlen))
- {
- return '';
- }
-
- $lx = (int) ((-$length) / 65535);
- $ly = (-$length) % 65535;
-
- // negative length requires ... capture everything
- // except a group of -length characters
- // anchored at the tail-end of the string
- if ($lx)
- {
- $lp = '(?:.{65535}){' . $lx . '}';
- }
- $lp = '(.*)(?:' . $lp . '.{' . $ly . '})$';
- }
- }
-
- if (!preg_match('#' . $op . $lp . '#us', $str, $match))
- {
- return '';
- }
-
- return $match[1];
+ return mb_substr($str, $offset, $length);
}
+}
- /**
- * Return the length (in characters) of a UTF-8 string
- *
- * @param string $text UTF-8 string
- * @return integer Length (in chars) of given string
- */
- function utf8_strlen($text)
- {
- // Since utf8_decode is replacing multibyte characters to ? strlen works fine
- return strlen(utf8_decode($text));
- }
+/**
+* Return the length (in characters) of a UTF-8 string
+* @ignore
+*/
+function utf8_strlen($text)
+{
+ return mb_strlen($text, 'utf-8');
}
/**
@@ -867,7 +415,6 @@ function utf8_recode($string, $encoding)
// Trigger an error?! Fow now just give bad data :-(
trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR);
- //return $string; // use utf_normalizer::cleanup() ?
}
/**
@@ -1606,19 +1153,12 @@ function utf8_case_fold_nfkc($text, $option = 'full')
"\xF0\x9D\x9E\xBB" => "\xCF\x83",
"\xF0\x9D\x9F\x8A" => "\xCF\x9D",
);
- global $phpbb_root_path, $phpEx;
// do the case fold
$text = utf8_case_fold($text, $option);
- if (!class_exists('utf_normalizer'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
- }
-
// convert to NFKC
- utf_normalizer::nfkc($text);
+ Normalizer::normalize($text, Normalizer::NFKC);
// FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt
$text = strtr($text, $fc_nfkc_closure);
@@ -1703,7 +1243,6 @@ function utf8_case_fold_nfc($text, $option = 'full')
"\xE1\xBF\xB7" => "\xE1\xBF\xB6\xCD\x85",
"\xE1\xBF\xBC" => "\xCE\xA9\xCD\x85",
);
- global $phpbb_root_path, $phpEx;
// perform a small trick, avoid further normalization on composed points that contain U+0345 in their decomposition
$text = strtr($text, $ypogegrammeni);
@@ -1714,106 +1253,56 @@ function utf8_case_fold_nfc($text, $option = 'full')
return $text;
}
-if (extension_loaded('intl'))
+/**
+* wrapper around PHP's native normalizer from intl
+* previously a PECL extension, included in the core since PHP 5.3.0
+* http://php.net/manual/en/normalizer.normalize.php
+*
+* @param mixed $strings a string or an array of strings to normalize
+* @return mixed the normalized content, preserving array keys if array given.
+*/
+function utf8_normalize_nfc($strings)
{
- /**
- * wrapper around PHP's native normalizer from intl
- * previously a PECL extension, included in the core since PHP 5.3.0
- * http://php.net/manual/en/normalizer.normalize.php
- *
- * @param mixed $strings a string or an array of strings to normalize
- * @return mixed the normalized content, preserving array keys if array given.
- */
- function utf8_normalize_nfc($strings)
+ if (empty($strings))
{
- if (empty($strings))
- {
- return $strings;
- }
-
- if (!is_array($strings))
- {
- if (Normalizer::isNormalized($strings))
- {
- return $strings;
- }
- return (string) Normalizer::normalize($strings);
- }
- else
- {
- foreach ($strings as $key => $string)
- {
- if (is_array($string))
- {
- foreach ($string as $_key => $_string)
- {
- if (Normalizer::isNormalized($strings[$key][$_key]))
- {
- continue;
- }
- $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]);
- }
- }
- else
- {
- if (Normalizer::isNormalized($strings[$key]))
- {
- continue;
- }
- $strings[$key] = (string) Normalizer::normalize($strings[$key]);
- }
- }
- }
-
return $strings;
}
-}
-else
-{
- /**
- * A wrapper function for the normalizer which takes care of including the class if
- * required and modifies the passed strings to be in NFC (Normalization Form Composition).
- *
- * @param mixed $strings a string or an array of strings to normalize
- * @return mixed the normalized content, preserving array keys if array given.
- */
- function utf8_normalize_nfc($strings)
+
+ if (!is_array($strings))
{
- if (empty($strings))
+ if (Normalizer::isNormalized($strings))
{
return $strings;
}
-
- if (!class_exists('utf_normalizer'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
- }
-
- if (!is_array($strings))
- {
- utf_normalizer::nfc($strings);
- }
- else if (is_array($strings))
+ return (string) Normalizer::normalize($strings);
+ }
+ else
+ {
+ foreach ($strings as $key => $string)
{
- foreach ($strings as $key => $string)
+ if (is_array($string))
{
- if (is_array($string))
+ foreach ($string as $_key => $_string)
{
- foreach ($string as $_key => $_string)
+ if (Normalizer::isNormalized($strings[$key][$_key]))
{
- utf_normalizer::nfc($strings[$key][$_key]);
+ continue;
}
+ $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]);
}
- else
+ }
+ else
+ {
+ if (Normalizer::isNormalized($strings[$key]))
{
- utf_normalizer::nfc($strings[$key]);
+ continue;
}
+ $strings[$key] = (string) Normalizer::normalize($strings[$key]);
}
}
-
- return $strings;
}
+
+ return $strings;
}
/**
@@ -1959,50 +1448,3 @@ function utf8_basename($filename)
return $filename;
}
-
-/**
-* UTF8-safe str_replace() function
-*
-* @param string $search The value to search for
-* @param string $replace The replacement string
-* @param string $subject The target string
-* @return string The resultant string
-*/
-function utf8_str_replace($search, $replace, $subject)
-{
- if (!is_array($search))
- {
- $search = array($search);
- if (is_array($replace))
- {
- $replace = (string) $replace;
- trigger_error('Array to string conversion', E_USER_NOTICE);
- }
- }
-
- $length = sizeof($search);
-
- if (!is_array($replace))
- {
- $replace = array_fill(0, $length, $replace);
- }
- else
- {
- $replace = array_pad($replace, $length, '');
- }
-
- for ($i = 0; $i < $length; $i++)
- {
- $search_length = utf8_strlen($search[$i]);
- $replace_length = utf8_strlen($replace[$i]);
-
- $offset = 0;
- while (($start = utf8_strpos($subject, $search[$i], $offset)) !== false)
- {
- $subject = utf8_substr($subject, 0, $start) . $replace[$i] . utf8_substr($subject, $start + $search_length);
- $offset = $start + $replace_length;
- }
- }
-
- return $subject;
-}
diff --git a/phpBB/index.php b/phpBB/index.php
index e4c03949c1..83535b50af 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -42,9 +42,10 @@ if (($mark_notification = $request->variable('mark_notification', 0)))
if (check_link_hash($request->variable('hash', ''), 'mark_notification_read'))
{
+ /* @var $phpbb_notifications \phpbb\notification\manager */
$phpbb_notifications = $phpbb_container->get('notification_manager');
- $notification = $phpbb_notifications->load_notifications(array(
+ $notification = $phpbb_notifications->load_notifications('notification.method.board', array(
'notification_id' => $mark_notification,
));
@@ -99,11 +100,14 @@ else
}
$result = $db->sql_query($sql);
+/** @var \phpbb\group\helper $group_helper */
+$group_helper = $phpbb_container->get('group_helper');
+
$legend = array();
while ($row = $db->sql_fetchrow($result))
{
$colour_text = ($row['group_colour']) ? ' style="color:#' . $row['group_colour'] . '"' : '';
- $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $group_name = $group_helper->get_name($row['group_name']);
if ($row['group_name'] == 'BOTS' || ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')))
{
diff --git a/phpBB/install/app.php b/phpBB/install/app.php
new file mode 100644
index 0000000000..9664f92cf1
--- /dev/null
+++ b/phpBB/install/app.php
@@ -0,0 +1,58 @@
+<?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.
+ *
+ */
+
+/**
+ * @ignore
+ */
+define('IN_PHPBB', true);
+define('IN_INSTALL', true);
+define('PHPBB_ENVIRONMENT', 'production');
+$phpbb_root_path = '../';
+$phpEx = substr(strrchr(__FILE__, '.'), 1);
+
+$startup_new_path = $phpbb_root_path . 'install/update/update/new/install/startup.' . $phpEx;
+$startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install/startup.' . $phpEx;
+require($startup_path);
+
+/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */
+$phpbb_filesystem = $phpbb_installer_container->get('filesystem');
+
+/** @var \phpbb\template\template $template */
+$template = $phpbb_installer_container->get('template');
+
+// Path to templates
+$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
+$paths = array_filter($paths, 'is_dir');
+
+$template->set_custom_style(array(
+ array(
+ 'name' => 'adm',
+ 'ext_path' => 'adm/style/',
+ ),
+), $paths);
+
+/** @var $phpbb_dispatcher \phpbb\event\dispatcher */
+$phpbb_dispatcher = $phpbb_installer_container->get('dispatcher');
+
+/** @var \phpbb\language\language $language */
+$language = $phpbb_installer_container->get('language');
+$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
+
+/** @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */
+$http_kernel = $phpbb_installer_container->get('http_kernel');
+
+/** @var $symfony_request \phpbb\symfony_request */
+$symfony_request = $phpbb_installer_container->get('symfony_request');
+$response = $http_kernel->handle($symfony_request);
+$response->send();
+$http_kernel->terminate($symfony_request, $response);
diff --git a/phpBB/install/convert/controller/convertor.php b/phpBB/install/convert/controller/convertor.php
new file mode 100644
index 0000000000..9a46117fe6
--- /dev/null
+++ b/phpBB/install/convert/controller/convertor.php
@@ -0,0 +1,865 @@
+<?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\convert\controller;
+
+use phpbb\cache\driver\driver_interface;
+use phpbb\exception\http_exception;
+use phpbb\install\controller\helper;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\database;
+use phpbb\install\helper\install_helper;
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\navigation\navigation_provider;
+use phpbb\language\language;
+use phpbb\request\request_interface;
+use phpbb\template\template;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+
+/**
+ * Controller for forum convertors
+ *
+ * WARNING: This file did not meant to be present in a production environment, so moving
+ * this file to a location which is accessible after board installation might
+ * lead to security issues.
+ */
+class convertor
+{
+ /**
+ * @var driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var driver_interface
+ */
+ protected $installer_cache;
+
+ /**
+ * @var \phpbb\config\db
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\config_php_file
+ */
+ protected $config_php_file;
+
+ /**
+ * @var string
+ */
+ protected $config_table;
+
+ /**
+ * @var helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var database
+ */
+ protected $db_helper;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var install_helper
+ */
+ protected $install_helper;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var navigation_provider
+ */
+ protected $navigation_provider;
+
+ /**
+ * @var request_interface
+ */
+ protected $request;
+
+ /**
+ * @var string
+ */
+ protected $session_keys_table;
+
+ /**
+ * @var string
+ */
+ protected $session_table;
+
+ /**
+ * @var template
+ */
+ protected $template;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param driver_interface $cache
+ * @param container_factory $container
+ * @param database $db_helper
+ * @param helper $controller_helper
+ * @param install_helper $install_helper
+ * @param factory $iohandler
+ * @param language $language
+ * @param navigation_provider $nav
+ * @param request_interface $request
+ * @param template $template
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(driver_interface $cache, container_factory $container, database $db_helper, helper $controller_helper, install_helper $install_helper, factory $iohandler, language $language, navigation_provider $nav, request_interface $request, template $template, $phpbb_root_path, $php_ext)
+ {
+ $this->installer_cache = $cache;
+ $this->controller_helper = $controller_helper;
+ $this->db_helper = $db_helper;
+ $this->install_helper = $install_helper;
+ $this->language = $language;
+ $this->navigation_provider = $nav;
+ $this->request = $request;
+ $this->template = $template;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $iohandler->set_environment('ajax');
+ $this->iohandler = $iohandler->get();
+
+ if (!$this->install_helper->is_phpbb_installed() || !defined('IN_INSTALL'))
+ {
+ throw new http_exception(403, 'INSTALL_PHPBB_NOT_INSTALLED');
+ }
+
+ $this->controller_helper->handle_language_select();
+
+ $this->cache = $container->get('cache.driver');
+ $this->config = $container->get('config');
+ $this->config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext);
+ $this->db = $container->get('dbal.conn.driver');
+
+ $this->config_table = $container->get_parameter('tables.config');
+ $this->session_keys_table = $container->get_parameter('tables.sessions_keys');
+ $this->session_table = $container->get_parameter('tables.sessions');
+ }
+
+ /**
+ * Render the intro page
+ *
+ * @param bool|int $start_new Whether or not to force to start a new convertor
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function intro($start_new)
+ {
+ $this->setup_navigation('intro');
+
+ if ($start_new)
+ {
+ if ($this->request->is_ajax())
+ {
+ $response = new StreamedResponse();
+ $iohandler = $this->iohandler;
+ $url = $this->controller_helper->route('phpbb_convert_intro', array('start_new' => 'new'));
+ $response->setCallback(function() use ($iohandler, $url) {
+ $iohandler->redirect($url);
+ });
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+
+ $this->config['convert_progress'] = '';
+ $this->config['convert_db_server'] = '';
+ $this->config['convert_db_user'] = '';
+ $this->db->sql_query('DELETE FROM ' . $this->config_table . "
+ WHERE config_name = 'convert_progress'
+ OR config_name = 'convert_db_server'
+ OR config_name = 'convert_db_user'"
+ );
+ }
+
+ // Let's see if there is a conversion in the works...
+ $options = array();
+ if (!empty($this->config['convert_progress']) &&
+ !empty($this->config['convert_db_server']) &&
+ !empty($this->config['convert_db_user']) &&
+ !empty($this->config['convert_options']))
+ {
+ $options = unserialize($this->config['convert_progress']);
+ $options = array_merge($options,
+ unserialize($this->config['convert_db_server']),
+ unserialize($this->config['convert_db_user']),
+ unserialize($this->config['convert_options'])
+ );
+ }
+
+ // This information should have already been checked once, but do it again for safety
+ if (!empty($options) && !empty($options['tag']) &&
+ isset($options['dbms']) &&
+ isset($options['dbhost']) &&
+ isset($options['dbport']) &&
+ isset($options['dbuser']) &&
+ isset($options['dbpasswd']) &&
+ isset($options['dbname']) &&
+ isset($options['table_prefix']))
+ {
+ $this->template->assign_vars(array(
+ 'TITLE' => $this->language->lang('CONTINUE_CONVERT'),
+ 'BODY' => $this->language->lang('CONTINUE_CONVERT_BODY'),
+ 'S_CONTINUE' => true,
+ 'U_NEW_ACTION' => $this->controller_helper->route('phpbb_convert_intro', array('start_new' => 'new')),
+ 'U_CONTINUE_ACTION' => $this->controller_helper->route('phpbb_convert_convert', array('converter' => $options['tag'])),
+ ));
+
+ return $this->controller_helper->render('installer_convert.html', 'CONTINUE_CONVERT', true);
+ }
+
+ return $this->render_convert_list();
+ }
+
+ /**
+ * Obtain convertor settings
+ *
+ * @param string $convertor Name of the convertor
+ *
+ * @return \Symfony\Component\HttpFoundation\Response|StreamedResponse
+ */
+ public function settings($convertor)
+ {
+ $this->setup_navigation('settings');
+
+ require_once ($this->phpbb_root_path . 'includes/constants.' . $this->php_ext);
+ require_once ($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext);
+
+ // Include convertor if available
+ $convertor_file_path = $this->phpbb_root_path . 'install/convertors/convert_' . $convertor . '.' . $this->php_ext;
+ if (!file_exists($convertor_file_path))
+ {
+ if ($this->request->is_ajax())
+ {
+ $response = new StreamedResponse();
+ $ref = $this;
+ $response->setCallback(function() use ($ref) {
+ $ref->render_error('CONVERT_NOT_EXIST');
+ });
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+
+ $this->render_error('CONVERT_NOT_EXIST');
+ return $this->controller_helper->render('installer_convert.html', 'STAGE_SETTINGS', true);
+ }
+
+ $get_info = true;
+ $phpbb_root_path = $this->phpbb_root_path; // These globals are required
+ $phpEx = $this->php_ext; // See above
+ include_once ($convertor_file_path);
+
+ // The test_file is a file that should be present in the location of the old board.
+ if (!isset($test_file))
+ {
+ if ($this->request->is_ajax())
+ {
+ $response = new StreamedResponse();
+ $ref = $this;
+ $response->setCallback(function() use ($ref) {
+ $ref->render_error('DEV_NO_TEST_FILE');
+ });
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+
+ $this->render_error('DEV_NO_TEST_FILE');
+ return $this->controller_helper->render('installer_convert.html', 'STAGE_SETTINGS', true);
+ }
+
+ if ($this->request->variable('submit', false))
+ {
+ // It must be an AJAX request at this point
+ $response = new StreamedResponse();
+ $ref = $this;
+ $response->setCallback(function() use ($ref, $convertor) {
+ $ref->proccess_settings_form($convertor);
+ });
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+ else
+ {
+ $this->template->assign_vars(array(
+ 'U_ACTION' => $this->controller_helper->route('phpbb_convert_settings', array(
+ 'convertor' => $convertor,
+ ))
+ ));
+
+ if ($this->request->is_ajax())
+ {
+ $response = new StreamedResponse();
+ $ref = $this;
+ $response->setCallback(function() use ($ref) {
+ $ref->render_settings_form();
+ });
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+
+ $this->render_settings_form();
+ }
+
+ return $this->controller_helper->render('installer_convert.html', 'STAGE_SETTINGS', true);
+ }
+
+ /**
+ * Run conversion
+ */
+ public function convert($converter)
+ {
+ $this->setup_navigation('convert');
+
+ if ($this->request->is_ajax())
+ {
+ $route = $this->controller_helper->route('phpbb_convert_convert', array('converter' => $converter));
+ $response = new StreamedResponse();
+ $ref = $this;
+ $response->setCallback(function() use ($ref, $route) {
+ $ref->redirect_to_html($route);
+ });
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+
+ $convertor = new \phpbb\convert\convertor($this->template, $this->controller_helper);
+ $convertor->convert_data($converter);
+
+ return $this->controller_helper->render('installer_convert.html', 'STAGE_IN_PROGRESS');
+ }
+
+ /**
+ * Render the final page of the convertor
+ */
+ public function finish()
+ {
+ $this->setup_navigation('finish');
+
+ $this->template->assign_vars(array(
+ 'TITLE' => $this->language->lang('CONVERT_COMPLETE'),
+ 'BODY' => $this->language->lang('CONVERT_COMPLETE_EXPLAIN'),
+ ));
+
+ // If we reached this step (conversion completed) we want to purge the cache and log the user out.
+ // This is for making sure the session get not screwed due to the 3.0.x users table being completely new.
+ $this->cache->purge();
+ $this->installer_cache->purge();
+
+ require_once($this->phpbb_root_path . 'includes/constants.' . $this->php_ext);
+ require_once($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext);
+
+ $sql = 'SELECT config_value
+ FROM ' . $this->config_table . '
+ WHERE config_name = \'search_type\'';
+ $result = $this->db->sql_query($sql);
+
+ if ($this->db->sql_fetchfield('config_value') != 'fulltext_mysql')
+ {
+ $this->template->assign_vars(array(
+ 'S_ERROR_BOX' => true,
+ 'ERROR_TITLE' => $this->language->lang('SEARCH_INDEX_UNCONVERTED'),
+ 'ERROR_MSG' => $this->language->lang('SEARCH_INDEX_UNCONVERTED_EXPLAIN'),
+ ));
+ }
+
+ $this->db->sql_freeresult($result);
+
+ switch ($this->db->get_sql_layer())
+ {
+ case 'sqlite3':
+ $this->db->sql_query('DELETE FROM ' . $this->session_keys_table);
+ $this->db->sql_query('DELETE FROM ' . $this->session_table);
+ break;
+
+ default:
+ $this->db->sql_query('TRUNCATE TABLE ' . $this->session_keys_table);
+ $this->db->sql_query('TRUNCATE TABLE ' . $this->session_table);
+ break;
+ }
+
+ return $this->controller_helper->render('installer_convert.html', 'CONVERT_COMPLETE');
+ }
+
+ /**
+ * Validates settings form
+ *
+ * @param string $convertor
+ */
+ public function proccess_settings_form($convertor)
+ {
+ global $phpbb_root_path, $phpEx, $get_info;
+
+ $phpbb_root_path = $this->phpbb_root_path;
+ $phpEx = $this->php_ext;
+ $get_info = true;
+
+ require_once($this->phpbb_root_path . 'includes/constants.' . $this->php_ext);
+ require_once($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext);
+
+ // Include convertor if available
+ $convertor_file_path = $this->phpbb_root_path . 'install/convertors/convert_' . $convertor . '.' . $this->php_ext;
+ include ($convertor_file_path);
+
+ // We expect to have an AJAX request here
+ $src_dbms = $this->request->variable('src_dbms', $convertor_data['dbms']);
+ $src_dbhost = $this->request->variable('src_dbhost', $convertor_data['dbhost']);
+ $src_dbport = $this->request->variable('src_dbport', $convertor_data['dbport']);
+ $src_dbuser = $this->request->variable('src_dbuser', $convertor_data['dbuser']);
+ $src_dbpasswd = $this->request->variable('src_dbpasswd', $convertor_data['dbpasswd']);
+ $src_dbname = $this->request->variable('src_dbname', $convertor_data['dbname']);
+ $src_table_prefix = $this->request->variable('src_table_prefix', $convertor_data['table_prefix']);
+ $forum_path = $this->request->variable('forum_path', $convertor_data['forum_path']);
+ $refresh = $this->request->variable('refresh', 1);
+
+ // Default URL of the old board
+ // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it?
+ // -> We should convert old urls to the new relative urls format
+ // $src_url = $request->variable('src_url', 'Not in use at the moment');
+
+ // strip trailing slash from old forum path
+ $forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path, 0, -1) : $forum_path;
+
+ $error = array();
+ if (!file_exists($this->phpbb_root_path . $forum_path . '/' . $test_file))
+ {
+ $error[] = $this->language->lang('COULD_NOT_FIND_PATH', $forum_path);
+ }
+
+ $connect_test = false;
+ $available_dbms = $this->db_helper->get_available_dbms(false, true, true);
+ if (!isset($available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE'])
+ {
+ $error[] = $this->language->lang('INST_ERR_NO_DB');
+ }
+ else
+ {
+ $connect_test = $this->db_helper->check_database_connection($src_dbms, $src_dbhost, $src_dbport, $src_dbuser, $src_dbpasswd, $src_dbname, $src_table_prefix);
+ }
+
+ extract($this->config_php_file->get_all());
+
+ // The forum prefix of the old and the new forum can only be the same if two different databases are used.
+ if ($src_table_prefix === $table_prefix && $src_dbms === $dbms && $src_dbhost === $dbhost && $src_dbport === $dbport && $src_dbname === $dbname)
+ {
+ $error[] = $this->language->lang('TABLE_PREFIX_SAME', $src_table_prefix);
+ }
+
+ if (!$connect_test)
+ {
+ $error[] = $this->language->lang('INST_ERR_DB_CONNECT');
+ }
+
+ $src_dbms = $this->config_php_file->convert_30_dbms_to_31($src_dbms);
+
+ // Check table prefix
+ if (empty($error))
+ {
+ // initiate database connection to old db if old and new db differ
+ global $src_db, $same_db;
+ $src_db = $same_db = false;
+
+ if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser)
+ {
+ /** @var \phpbb\db\driver\driver_interface $src_db */
+ $src_db = new $src_dbms();
+ $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true);
+ $same_db = false;
+ }
+ else
+ {
+ $src_db = $this->db;
+ $same_db = true;
+ }
+
+ $src_db->sql_return_on_error(true);
+ $this->db->sql_return_on_error(true);
+
+ // Try to select one row from the first table to see if the prefix is OK
+ $result = $src_db->sql_query_limit('SELECT * FROM ' . $src_table_prefix . $tables[0], 1);
+
+ if (!$result)
+ {
+ $prefixes = array();
+
+ $db_tools_factory = new \phpbb\db\tools\factory();
+ $db_tools = $db_tools_factory->get($src_db);
+ $tables_existing = $db_tools->sql_list_tables();
+ $tables_existing = array_map('strtolower', $tables_existing);
+ foreach ($tables_existing as $table_name)
+ {
+ compare_table($tables, $table_name, $prefixes);
+ }
+ unset($tables_existing);
+
+ foreach ($prefixes as $prefix => $count)
+ {
+ if ($count >= sizeof($tables))
+ {
+ $possible_prefix = $prefix;
+ break;
+ }
+ }
+
+ $msg = '';
+ if (!empty($convertor_data['table_prefix']))
+ {
+ $msg .= $this->language->lang_array('DEFAULT_PREFIX_IS', array($convertor_data['forum_name'], $convertor_data['table_prefix']));
+ }
+
+ if (!empty($possible_prefix))
+ {
+ $msg .= '<br />';
+ $msg .= ($possible_prefix == '*') ? $this->language->lang('BLANK_PREFIX_FOUND') : $this->language->lang_array('PREFIX_FOUND', array($possible_prefix));
+ $src_table_prefix = ($possible_prefix == '*') ? '' : $possible_prefix;
+ }
+
+ $error[] = $msg;
+ }
+
+ $src_db->sql_freeresult($result);
+ $src_db->sql_return_on_error(false);
+ }
+
+ if (empty($error))
+ {
+ // Save convertor Status
+ $this->config->set('convert_progress', serialize(array(
+ 'step' => '',
+ 'table_prefix' => $src_table_prefix,
+ 'tag' => $convertor,
+ )), false);
+ $this->config->set('convert_db_server', serialize(array(
+ 'dbms' => $src_dbms,
+ 'dbhost' => $src_dbhost,
+ 'dbport' => $src_dbport,
+ 'dbname' => $src_dbname,
+ )), false);
+ $this->config->set('convert_db_user', serialize(array(
+ 'dbuser' => $src_dbuser,
+ 'dbpasswd' => $src_dbpasswd,
+ )), false);
+
+ // Save options
+ $this->config->set('convert_options', serialize(array(
+ 'forum_path' => $this->phpbb_root_path . $forum_path,
+ 'refresh' => $refresh
+ )), false);
+
+ $url = $this->controller_helper->route('phpbb_convert_convert', array('converter' => $convertor));
+ $this->iohandler->redirect($url);
+ $this->iohandler->send_response(true);
+ }
+ else
+ {
+ $this->render_settings_form($error);
+ }
+ }
+
+ /**
+ * Renders settings form
+ *
+ * @param array $error Array of errors
+ */
+ public function render_settings_form($error = array())
+ {
+ foreach ($error as $msg)
+ {
+ $this->iohandler->add_error_message($msg);
+ }
+
+ $dbms_options = array();
+ foreach ($this->db_helper->get_available_dbms() as $dbms_key => $dbms_array)
+ {
+ $dbms_options[] = array(
+ 'value' => $dbms_key,
+ 'label' => 'DB_OPTION_' . strtoupper($dbms_key),
+ );
+ }
+
+ $form_title = 'SPECIFY_OPTIONS';
+ $form_data = array(
+ 'src_dbms' => array(
+ 'label' => 'DBMS',
+ 'type' => 'select',
+ 'options' => $dbms_options,
+ ),
+ 'src_dbhost' => array(
+ 'label' => 'DB_HOST',
+ 'description' => 'DB_HOST_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'src_dbport' => array(
+ 'label' => 'DB_PORT',
+ 'description' => 'DB_PORT_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'src_dbname' => array(
+ 'label' => 'DB_NAME',
+ 'type' => 'text',
+ ),
+ 'src_dbuser' => array(
+ 'label' => 'DB_USERNAME',
+ 'type' => 'text',
+ ),
+ 'src_dbpasswd' => array(
+ 'label' => 'DB_PASSWORD',
+ 'type' => 'password',
+ ),
+ 'src_table_prefix' => array(
+ 'label' => 'TABLE_PREFIX',
+ 'description' => 'TABLE_PREFIX_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'forum_path' => array(
+ 'label' => 'FORUM_PATH',
+ 'description' => 'FORUM_PATH_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'refresh' => array(
+ 'label' => 'REFRESH_PAGE',
+ 'description' => 'REFRESH_PAGE_EXPLAIN',
+ 'type' => 'radio',
+ 'options' => array(
+ array(
+ 'value' => 0,
+ 'label' => 'NO',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 1,
+ 'label' => 'YES',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'submit' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ );
+
+ if ($this->request->is_ajax())
+ {
+ $this->iohandler->add_user_form_group($form_title, $form_data);
+ $this->iohandler->send_response(true);
+ }
+ else
+ {
+ $rendered_form = $this->iohandler->generate_form_render_data($form_title, $form_data);
+
+ $this->template->assign_vars(array(
+ 'TITLE' => $this->language->lang('STAGE_SETTINGS'),
+ 'CONTENT' => $rendered_form,
+ ));
+ }
+ }
+
+ /**
+ * Render the list of available convertors
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ protected function render_convert_list()
+ {
+ $this->template->assign_vars(array(
+ 'TITLE' => $this->language->lang('CONVERT_INTRO'),
+ 'BODY' => $this->language->lang('CONVERT_INTRO_BODY'),
+ 'S_LIST' => true,
+ ));
+
+ $convertors = $sort = array();
+ $get_info = true; // Global flag
+
+ $handle = @opendir($this->phpbb_root_path . 'install/convertors/');
+
+ if (!$handle)
+ {
+ die('Unable to access the convertors directory');
+ }
+
+ while ($entry = readdir($handle))
+ {
+ if (preg_match('/^convert_([a-z0-9_]+).' . $this->php_ext . '$/i', $entry, $m))
+ {
+ $phpbb_root_path = $this->phpbb_root_path; // These globals are required
+ $phpEx = $this->php_ext; // See above
+ include_once($this->phpbb_root_path . 'install/convertors/' . $entry);
+ if (isset($convertor_data))
+ {
+ $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors);
+
+ $convertors[] = array(
+ 'tag' => $m[1],
+ 'forum_name' => $convertor_data['forum_name'],
+ 'version' => $convertor_data['version'],
+ 'dbms' => $convertor_data['dbms'],
+ 'dbhost' => $convertor_data['dbhost'],
+ 'dbport' => $convertor_data['dbport'],
+ 'dbuser' => $convertor_data['dbuser'],
+ 'dbpasswd' => $convertor_data['dbpasswd'],
+ 'dbname' => $convertor_data['dbname'],
+ 'table_prefix' => $convertor_data['table_prefix'],
+ 'author' => $convertor_data['author']
+ );
+ }
+ unset($convertor_data);
+ }
+ }
+ closedir($handle);
+
+ @ksort($sort);
+
+ foreach ($sort as $void => $index)
+ {
+ $this->template->assign_block_vars('convertors', array(
+ 'AUTHOR' => $convertors[$index]['author'],
+ 'SOFTWARE' => $convertors[$index]['forum_name'],
+ 'VERSION' => $convertors[$index]['version'],
+
+ 'U_CONVERT' => $this->controller_helper->route('phpbb_convert_settings', array('convertor' => $convertors[$index]['tag'])),
+ ));
+ }
+
+ return $this->controller_helper->render('installer_convert.html', 'SUB_INTRO', true);
+ }
+
+ /**
+ * Renders an error form
+ *
+ * @param string $msg
+ * @param string|bool $desc
+ */
+ public function render_error($msg, $desc = false)
+ {
+ if ($this->request->is_ajax())
+ {
+ $this->iohandler->add_error_message($msg, $desc);
+ $this->iohandler->send_response(true);
+ }
+ else
+ {
+ $this->template->assign_vars(array(
+ 'S_ERROR_BOX' => true,
+ 'ERROR_TITLE' => $this->language->lang($msg),
+ ));
+
+ if ($desc)
+ {
+ $this->template->assign_var('ERROR_MSG', $this->language->lang($desc));
+ }
+ }
+ }
+
+ /**
+ * Redirects an AJAX request to a non-JS version
+ *
+ * @param string $url URL to redirect to
+ */
+ public function redirect_to_html($url)
+ {
+ $this->iohandler->redirect($url);
+ $this->iohandler->send_response(true);
+ }
+
+ private function setup_navigation($stage)
+ {
+ $active = true;
+ $completed = false;
+
+ switch ($stage)
+ {
+ case 'finish':
+ $this->navigation_provider->set_nav_property(
+ array('convert', 0, 'finish'),
+ array(
+ 'selected' => $active,
+ 'completed' => $completed,
+ )
+ );
+
+ $active = false;
+ $completed = true;
+ // no break;
+
+ case 'convert':
+ $this->navigation_provider->set_nav_property(
+ array('convert', 0, 'convert'),
+ array(
+ 'selected' => $active,
+ 'completed' => $completed,
+ )
+ );
+
+ $active = false;
+ $completed = true;
+ // no break;
+
+ case 'settings':
+ $this->navigation_provider->set_nav_property(
+ array('convert', 0, 'settings'),
+ array(
+ 'selected' => $active,
+ 'completed' => $completed,
+ )
+ );
+
+ $active = false;
+ $completed = true;
+ // no break;
+
+ case 'intro':
+ $this->navigation_provider->set_nav_property(
+ array('convert', 0, 'intro'),
+ array(
+ 'selected' => $active,
+ 'completed' => $completed,
+ )
+ );
+ break;
+ }
+ }
+}
diff --git a/phpBB/install/convert/convert.php b/phpBB/install/convert/convert.php
new file mode 100644
index 0000000000..03913d6ae6
--- /dev/null
+++ b/phpBB/install/convert/convert.php
@@ -0,0 +1,60 @@
+<?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\convert;
+
+/**
+ * Class holding all convertor-specific details.
+ *
+ * WARNING: This file did not meant to be present in a production environment, so moving this file to a location which
+ * is accessible after board installation might lead to security issues.
+ */
+class convert
+{
+ var $options = array();
+
+ var $convertor_tag = '';
+ var $src_dbms = '';
+ var $src_dbhost = '';
+ var $src_dbport = '';
+ var $src_dbuser = '';
+ var $src_dbpasswd = '';
+ var $src_dbname = '';
+ var $src_table_prefix = '';
+
+ var $convertor_data = array();
+ var $tables = array();
+ var $config_schema = array();
+ var $convertor = array();
+ var $src_truncate_statement = 'DELETE FROM ';
+ var $truncate_statement = 'DELETE FROM ';
+
+ var $fulltext_search;
+
+ // Batch size, can be adjusted by the conversion file
+ // For big boards a value of 6000 seems to be optimal
+ var $batch_size = 2000;
+ // Number of rows to be inserted at once (extended insert) if supported
+ // For installations having enough memory a value of 60 may be good.
+ var $num_wait_rows = 20;
+
+ // Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor.
+ var $mysql_convert = false;
+
+ var $p_master;
+
+ function convert($p_master)
+ {
+ $this->p_master = $p_master;
+ }
+}
diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php
new file mode 100644
index 0000000000..f7f05ebdae
--- /dev/null
+++ b/phpBB/install/convert/convertor.php
@@ -0,0 +1,1614 @@
+<?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\convert;
+
+use phpbb\install\controller\helper;
+use phpbb\template\template;
+
+/**
+ * Convertor backend class
+ *
+ * WARNING: This file did not meant to be present in a production environment, so moving this file to a location which
+ * is accessible after board installation might lead to security issues.
+ */
+class convertor
+{
+ /**
+ * @var helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var \phpbb\filesystem\filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * Constructor
+ *
+ * @param template $template
+ * @param helper $controller_helper
+ */
+ public function __construct(template $template, helper $controller_helper)
+ {
+ global $convert, $phpbb_filesystem;
+
+ $this->template = $template;
+ $this->filesystem = $phpbb_filesystem;
+ $this->controller_helper = $controller_helper;
+
+ $convert = new convert($this);
+ }
+
+ /**
+ * The function which does the actual work (or dispatches it to the relevant places)
+ */
+ function convert_data($converter)
+ {
+ global $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth;
+ global $convert, $convert_row, $message_parser, $skip_rows, $language;
+ global $request, $phpbb_dispatcher;
+
+ $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
+ extract($phpbb_config_php_file->get_all());
+
+ require_once($phpbb_root_path . 'includes/constants.' . $phpEx);
+ require_once($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
+
+ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+ /** @var \phpbb\db\driver\driver_interface $db */
+ $db = new $dbms();
+ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
+ unset($dbpasswd);
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ // Override a couple of config variables for the duration
+ $config['max_quote_depth'] = 0;
+
+ // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
+ $config['max_post_chars'] = $config['min_post_chars'] = 0;
+
+ // Set up a user as well. We _should_ have enough of a database here at this point to do this
+ // and it helps for any core code we call
+ $user->session_begin();
+ $user->page = $user->extract_current_page($phpbb_root_path);
+
+ $convert->options = array();
+ if (isset($config['convert_progress']))
+ {
+ $convert->options = unserialize($config['convert_progress']);
+ $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
+ }
+
+ // This information should have already been checked once, but do it again for safety
+ if (empty($convert->options) || empty($convert->options['tag']) ||
+ !isset($convert->options['dbms']) ||
+ !isset($convert->options['dbhost']) ||
+ !isset($convert->options['dbport']) ||
+ !isset($convert->options['dbuser']) ||
+ !isset($convert->options['dbpasswd']) ||
+ !isset($convert->options['dbname']) ||
+ !isset($convert->options['table_prefix']))
+ {
+ $this->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
+ }
+
+ $this->template->assign_var('S_CONV_IN_PROGRESS', true);
+
+ // Make some short variables accessible, for easier referencing
+ $convert->convertor_tag = basename($convert->options['tag']);
+ $convert->src_dbms = $convert->options['dbms'];
+ $convert->src_dbhost = $convert->options['dbhost'];
+ $convert->src_dbport = $convert->options['dbport'];
+ $convert->src_dbuser = $convert->options['dbuser'];
+ $convert->src_dbpasswd = $convert->options['dbpasswd'];
+ $convert->src_dbname = $convert->options['dbname'];
+ $convert->src_table_prefix = $convert->options['table_prefix'];
+
+ // initiate database connection to old db if old and new db differ
+ global $src_db, $same_db;
+ $src_db = $same_db = null;
+ if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser)
+ {
+ $dbms = $convert->src_dbms;
+ /** @var \phpbb\db\driver\driver $src_db */
+ $src_db = new $dbms();
+ $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true);
+ $same_db = false;
+ }
+ else
+ {
+ $src_db = $db;
+ $same_db = true;
+ }
+
+ $convert->mysql_convert = false;
+ switch ($src_db->sql_layer)
+ {
+ case 'sqlite3':
+ $convert->src_truncate_statement = 'DELETE FROM ';
+ break;
+
+ // Thanks MySQL, for silently converting...
+ case 'mysql':
+ case 'mysql4':
+ if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>='))
+ {
+ $convert->mysql_convert = true;
+ }
+ $convert->src_truncate_statement = 'TRUNCATE TABLE ';
+ break;
+
+ case 'mysqli':
+ $convert->mysql_convert = true;
+ $convert->src_truncate_statement = 'TRUNCATE TABLE ';
+ break;
+
+ default:
+ $convert->src_truncate_statement = 'TRUNCATE TABLE ';
+ break;
+ }
+
+ if ($convert->mysql_convert && !$same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ switch ($db->get_sql_layer())
+ {
+ case 'sqlite3':
+ $convert->truncate_statement = 'DELETE FROM ';
+ break;
+
+ default:
+ $convert->truncate_statement = 'TRUNCATE TABLE ';
+ break;
+ }
+
+ $get_info = false;
+
+ // check security implications of direct inclusion
+ if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx))
+ {
+ $this->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
+ }
+
+ if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx))
+ {
+ include_once('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx);
+ }
+
+ $get_info = true;
+ include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
+
+ // Map some variables...
+ $convert->convertor_data = $convertor_data;
+ $convert->tables = $tables;
+ $convert->config_schema = $config_schema;
+
+ // Now include the real data
+ $get_info = false;
+ include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
+
+ $convert->convertor_data = $convertor_data;
+ $convert->tables = $tables;
+ $convert->config_schema = $config_schema;
+ $convert->convertor = $convertor;
+
+ // The test_file is a file that should be present in the location of the old board.
+ if (!file_exists($convert->options['forum_path'] . '/' . $test_file))
+ {
+ $this->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__);
+ }
+
+ $search_type = $config['search_type'];
+
+ // For conversions we are a bit less strict and set to a search backend we know exist...
+ if (!class_exists($search_type))
+ {
+ $search_type = '\phpbb\search\fulltext_native';
+ $config->set('search_type', $search_type);
+ }
+
+ if (!class_exists($search_type))
+ {
+ trigger_error('NO_SUCH_SEARCH_MODULE');
+ }
+
+ $error = false;
+ $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
+
+ if ($error)
+ {
+ trigger_error($error);
+ }
+
+ include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ $message_parser = new \parse_message();
+
+ $jump = $request->variable('jump', 0);
+ $final_jump = $request->variable('final_jump', 0);
+ $sync_batch = $request->variable('sync_batch', -1);
+ $last_statement = $request->variable('last', 0);
+
+ // We are running sync...
+ if ($sync_batch >= 0)
+ {
+ $this->sync_forums($converter, $sync_batch);
+ return;
+ }
+
+ if ($jump)
+ {
+ $this->jump($converter, $jump, $last_statement);
+ return;
+ }
+
+ if ($final_jump)
+ {
+ $this->final_jump($final_jump);
+ return;
+ }
+
+ $current_table = $request->variable('current_table', 0);
+ $old_current_table = min(-1, $current_table - 1);
+ $skip_rows = $request->variable('skip_rows', 0);
+
+ if (!$current_table && !$skip_rows)
+ {
+ if (!$request->variable('confirm', false))
+ {
+ // If avatars / ranks / smilies folders are specified make sure they are writable
+ $bad_folders = array();
+
+ $local_paths = array(
+ 'avatar_path' => path($config['avatar_path']),
+ 'avatar_gallery_path' => path($config['avatar_gallery_path']),
+ 'icons_path' => path($config['icons_path']),
+ 'ranks_path' => path($config['ranks_path']),
+ 'smilies_path' => path($config['smilies_path'])
+ );
+
+ foreach ($local_paths as $folder => $local_path)
+ {
+ if (isset($convert->convertor[$folder]))
+ {
+ if (empty($convert->convertor['test_file']))
+ {
+ // test_file is mandantory at the moment so this should never be reached, but just in case...
+ $this->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
+ }
+
+ if (!$local_path || !$this->filesystem->is_writable($phpbb_root_path . $local_path))
+ {
+ if (!$local_path)
+ {
+ $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder);
+ }
+ else
+ {
+ $bad_folders[] = $local_path;
+ }
+ }
+ }
+ }
+
+ if (sizeof($bad_folders))
+ {
+ $msg = (sizeof($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);
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['INSTALL_TEST'],
+ 'U_ACTION' => $this->controller_helper->route('phpbb_convert_convert', array('converter' => $converter)),
+ ));
+ return;
+ }
+
+ // Grab all the tables used in convertor
+ $missing_tables = $tables_list = $aliases = array();
+
+ foreach ($convert->convertor['schema'] as $schema)
+ {
+ // Skip those not used (because of addons/plugins not detected)
+ if (!$schema['target'])
+ {
+ continue;
+ }
+
+ foreach ($schema as $key => $val)
+ {
+ // we're dealing with an array like:
+ // array('forum_status', 'forums.forum_status', 'is_item_locked')
+ if (is_int($key) && !empty($val[1]))
+ {
+ $temp_data = $val[1];
+ if (!is_array($temp_data))
+ {
+ $temp_data = array($temp_data);
+ }
+
+ foreach ($temp_data as $value)
+ {
+ if (preg_match('/([a-z0-9_]+)\.([a-z0-9_]+)\)* ?A?S? ?([a-z0-9_]*?)\.?([a-z0-9_]*)$/i', $value, $m))
+ {
+ $table = $convert->src_table_prefix . $m[1];
+ $tables_list[$table] = $table;
+
+ if (!empty($m[3]))
+ {
+ $aliases[] = $convert->src_table_prefix . $m[3];
+ }
+ }
+ }
+ }
+ // 'left_join' => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1'
+ else if ($key == 'left_join')
+ {
+ // Convert the value if it wasn't an array already.
+ if (!is_array($val))
+ {
+ $val = array($val);
+ }
+
+ for ($j = 0, $size = sizeof($val); $j < $size; ++$j)
+ {
+ if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m))
+ {
+ $table = $convert->src_table_prefix . $m[1];
+ $tables_list[$table] = $table;
+
+ if (!empty($m[2]))
+ {
+ $aliases[] = $convert->src_table_prefix . $m[2];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Remove aliased tables from $tables_list
+ foreach ($aliases as $alias)
+ {
+ unset($tables_list[$alias]);
+ }
+
+ // Check if the tables that we need exist
+ $src_db->sql_return_on_error(true);
+ foreach ($tables_list as $table => $null)
+ {
+ $sql = 'SELECT 1 FROM ' . $table;
+ $_result = $src_db->sql_query_limit($sql, 1);
+
+ if (!$_result)
+ {
+ $missing_tables[] = $table;
+ }
+ $src_db->sql_freeresult($_result);
+ }
+ $src_db->sql_return_on_error(false);
+
+ // 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))
+ {
+ $this->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
+ }
+ else if (sizeof($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__);
+ }
+
+ $url = $this->save_convert_progress($converter, 'confirm=1');
+ $msg = $user->lang['PRE_CONVERT_COMPLETE'];
+
+ if ($convert->convertor_data['author_notes'])
+ {
+ $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']);
+ }
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
+ 'BODY' => $msg,
+ 'U_ACTION' => $url,
+ ));
+
+ return;
+ } // if (!$request->variable('confirm', false)))
+
+ $this->template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $user->lang['STARTING_CONVERT'],
+ ));
+
+ // Convert the config table and load the settings of the old board
+ if (!empty($convert->config_schema))
+ {
+ restore_config($convert->config_schema);
+
+ // Override a couple of config variables for the duration
+ $config['max_quote_depth'] = 0;
+
+ // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
+ $config['max_post_chars'] = $config['min_post_chars'] = 0;
+ }
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => $user->lang['CONFIG_CONVERT'],
+ 'RESULT' => $user->lang['DONE'],
+ ));
+
+ // Now process queries and execute functions that have to be executed prior to the conversion
+ if (!empty($convert->convertor['execute_first']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($convert->convertor['execute_first']);
+ // @codingStandardsIgnoreEnd
+ }
+
+ if (!empty($convert->convertor['query_first']))
+ {
+ if (!is_array($convert->convertor['query_first']))
+ {
+ $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first']));
+ }
+ else if (!is_array($convert->convertor['query_first'][0]))
+ {
+ $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1]));
+ }
+
+ foreach ($convert->convertor['query_first'] as $query_first)
+ {
+ if ($query_first[0] == 'src')
+ {
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ $src_db->sql_query($query_first[1]);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+ }
+ else
+ {
+ $db->sql_query($query_first[1]);
+ }
+ }
+ }
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => $user->lang['PREPROCESS_STEP'],
+ 'RESULT' => $user->lang['DONE'],
+ ));
+ } // if (!$current_table && !$skip_rows)
+
+ $this->template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $user->lang['FILLING_TABLES'],
+ ));
+
+ // This loop takes one target table and processes it
+ while ($current_table < sizeof($convert->convertor['schema']))
+ {
+ $schema = $convert->convertor['schema'][$current_table];
+
+ // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this.
+ if (empty($schema['target']))
+ {
+ $current_table++;
+ continue;
+ }
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => sprintf($user->lang['FILLING_TABLE'], $schema['target']),
+ ));
+
+ // This is only the case when we first start working on the tables.
+ if (!$skip_rows)
+ {
+ // process execute_first and query_first for this table...
+ if (!empty($schema['execute_first']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($schema['execute_first']);
+ // @codingStandardsIgnoreEnd
+ }
+
+ if (!empty($schema['query_first']))
+ {
+ if (!is_array($schema['query_first']))
+ {
+ $schema['query_first'] = array('target', array($schema['query_first']));
+ }
+ else if (!is_array($schema['query_first'][0]))
+ {
+ $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1]));
+ }
+
+ foreach ($schema['query_first'] as $query_first)
+ {
+ if ($query_first[0] == 'src')
+ {
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+ $src_db->sql_query($query_first[1]);
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+ }
+ else
+ {
+ $db->sql_query($query_first[1]);
+ }
+ }
+ }
+
+ if (!empty($schema['autoincrement']))
+ {
+ switch ($db->get_sql_layer())
+ {
+ case 'postgres':
+ $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
+ break;
+
+ case 'oracle':
+ $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $largest_id = (int) $row['max_id'];
+
+ if ($largest_id)
+ {
+ $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
+ $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
+ }
+ break;
+ }
+ }
+ }
+
+ // Process execute_always for this table
+ // This is for code which needs to be executed on every pass of this table if
+ // it gets split because of time restrictions
+ if (!empty($schema['execute_always']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($schema['execute_always']);
+ // @codingStandardsIgnoreEnd
+ }
+
+ //
+ // Set up some variables
+ //
+ // $waiting_rows holds rows for multirows insertion (MySQL only)
+ // $src_tables holds unique tables with aliases to select from
+ // $src_fields will quickly refer source fields (or aliases) corresponding to the current index
+ // $select_fields holds the names of the fields to retrieve
+ //
+
+ $sql_data = array(
+ 'source_fields' => array(),
+ 'target_fields' => array(),
+ 'source_tables' => array(),
+ 'select_fields' => array(),
+ );
+
+ // This statement is building the keys for later insertion.
+ $insert_query = $this->build_insert_query($schema, $sql_data, $current_table);
+
+ // If no source table is affected, we skip the table
+ if (empty($sql_data['source_tables']))
+ {
+ $skip_rows = 0;
+ $current_table++;
+ continue;
+ }
+
+ $distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' : '';
+
+ $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']);
+
+ // Where
+ $sql .= (!empty($schema['where'])) ? "\nWHERE (" . $schema['where'] . ')' : '';
+
+ // Group By
+ if (!empty($schema['group_by']))
+ {
+ $schema['group_by'] = array($schema['group_by']);
+ foreach ($sql_data['select_fields'] as $select)
+ {
+ $alias = strpos(strtolower($select), ' as ');
+ $select = ($alias) ? substr($select, 0, $alias) : $select;
+ if (!in_array($select, $schema['group_by']))
+ {
+ $schema['group_by'][] = $select;
+ }
+ }
+ }
+ $sql .= (!empty($schema['group_by'])) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : '';
+
+ // Having
+ $sql .= (!empty($schema['having'])) ? "\nHAVING " . $schema['having'] : '';
+
+ // Order By
+ if (empty($schema['order_by']) && !empty($schema['primary']))
+ {
+ $schema['order_by'] = $schema['primary'];
+ }
+ $sql .= (!empty($schema['order_by'])) ? "\nORDER BY " . $schema['order_by'] : '';
+
+ // Counting basically holds the amount of rows processed.
+ $counting = -1;
+ $batch_time = 0;
+
+ while ($counting === -1 || ($counting >= $convert->batch_size && still_on_time()))
+ {
+ $old_current_table = $current_table;
+
+ $rows = '';
+ $waiting_rows = array();
+
+ if (!empty($batch_time))
+ {
+ $mtime = explode(' ', microtime());
+ $mtime = $mtime[0] + $mtime[1];
+ $rows = ceil($counting/($mtime - $batch_time)) . " rows/s ($counting rows) | ";
+ }
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => "skip_rows = $skip_rows",
+ 'RESULT' => $rows . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] : ''),
+ ));
+
+ $mtime = explode(' ', microtime());
+ $batch_time = $mtime[0] + $mtime[1];
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ // Take skip rows into account and only fetch batch_size amount of rows
+ $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ // This loop processes each row
+ $counting = 0;
+
+ $convert->row = $convert_row = array();
+
+ if (!empty($schema['autoincrement']))
+ {
+ switch ($db->get_sql_layer())
+ {
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON');
+ break;
+ }
+ }
+
+ // Now handle the rows until time is over or no more rows to process...
+ while ($counting === 0 || still_on_time())
+ {
+ $convert_row = $src_db->sql_fetchrow($___result);
+
+ if (!$convert_row)
+ {
+ // move to the next batch or table
+ break;
+ }
+
+ // With this we are able to always save the last state
+ $convert->row = $convert_row;
+
+ // Increment the counting variable, it stores the number of rows we have processed
+ $counting++;
+
+ $insert_values = array();
+
+ $sql_flag = $this->process_row($schema, $sql_data, $insert_values);
+
+ if ($sql_flag === true)
+ {
+ switch ($db->get_sql_layer())
+ {
+ // If MySQL, we'll wait to have num_wait_rows rows to submit at once
+ case 'mysql':
+ case 'mysql4':
+ case 'mysqli':
+ $waiting_rows[] = '(' . implode(', ', $insert_values) . ')';
+
+ if (sizeof($waiting_rows) >= $convert->num_wait_rows)
+ {
+ $errored = false;
+
+ $db->sql_return_on_error(true);
+
+ if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
+ {
+ $errored = true;
+ }
+ $db->sql_return_on_error(false);
+
+ if ($errored)
+ {
+ $db->sql_return_on_error(true);
+
+ // Because it errored out we will try to insert the rows one by one... most of the time this
+ // is caused by duplicate entries - but we also do not want to miss one...
+ foreach ($waiting_rows as $waiting_sql)
+ {
+ if (!$db->sql_query($insert_query . $waiting_sql))
+ {
+ $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
+ }
+ }
+
+ $db->sql_return_on_error(false);
+ }
+
+ $waiting_rows = array();
+ }
+
+ break;
+
+ default:
+ $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')';
+
+ $db->sql_return_on_error(true);
+
+ if (!$db->sql_query($insert_sql))
+ {
+ $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
+ }
+ $db->sql_return_on_error(false);
+
+ $waiting_rows = array();
+
+ break;
+ }
+ }
+
+ $skip_rows++;
+ }
+ $src_db->sql_freeresult($___result);
+
+ // We might still have some rows waiting
+ if (sizeof($waiting_rows))
+ {
+ $errored = false;
+ $db->sql_return_on_error(true);
+
+ if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
+ {
+ $errored = true;
+ }
+ $db->sql_return_on_error(false);
+
+ if ($errored)
+ {
+ $db->sql_return_on_error(true);
+
+ // Because it errored out we will try to insert the rows one by one... most of the time this
+ // is caused by duplicate entries - but we also do not want to miss one...
+ foreach ($waiting_rows as $waiting_sql)
+ {
+ $db->sql_query($insert_query . $waiting_sql);
+ $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
+ }
+
+ $db->sql_return_on_error(false);
+ }
+
+ $waiting_rows = array();
+ }
+
+ if (!empty($schema['autoincrement']))
+ {
+ switch ($db->get_sql_layer())
+ {
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF');
+ break;
+
+ case 'postgres':
+ $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
+ break;
+
+ case 'oracle':
+ $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $largest_id = (int) $row['max_id'];
+
+ if ($largest_id)
+ {
+ $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
+ $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
+ }
+ break;
+ }
+ }
+ }
+
+ // When we reach this point, either the current table has been processed or we're running out of time.
+ if (still_on_time() && $counting < $convert->batch_size/* && !defined('DEBUG')*/)
+ {
+ $skip_rows = 0;
+ $current_table++;
+ }
+ else
+ {/*
+ if (still_on_time() && $counting < $convert->batch_size)
+ {
+ $skip_rows = 0;
+ $current_table++;
+ }*/
+
+ // Looks like we ran out of time.
+ $url = $this->save_convert_progress($converter, 'current_table=' . $current_table . '&amp;skip_rows=' . $skip_rows);
+
+ $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']));
+
+ $this->template->assign_vars(array(
+ 'BODY' => $msg,
+ 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+ }
+
+ // Process execute_last then we'll be done
+ $url = $this->save_convert_progress($converter, 'jump=1');
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['FINAL_STEP'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+
+ /**
+ * Sync function being executed at the middle, some functions need to be executed after a successful sync.
+ */
+ function sync_forums($converter, $sync_batch)
+ {
+ global $user, $db, $phpbb_root_path, $phpEx, $config, $cache;
+ global $convert;
+
+ include_once ($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
+
+ $this->template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $user->lang['SYNC_TOPICS'],
+ ));
+
+ $batch_size = $convert->batch_size;
+
+ $sql = 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value
+ FROM ' . TOPICS_TABLE;
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ // Set values of minimum/maximum primary value for this table.
+ $primary_min = $row['min_value'];
+ $primary_max = $row['max_value'];
+
+ if ($sync_batch == 0)
+ {
+ $sync_batch = (int) $primary_min;
+ }
+
+ if ($sync_batch == 0)
+ {
+ $sync_batch = 1;
+ }
+
+ // Fetch a batch of rows, process and insert them.
+ while ($sync_batch <= $primary_max && still_on_time())
+ {
+ $end = ($sync_batch + $batch_size - 1);
+
+ // Sync all topics in batch mode...
+ sync('topic', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true);
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''),
+ 'RESULT' => $user->lang['DONE'],
+ ));
+
+ $sync_batch += $batch_size;
+ }
+
+ if ($sync_batch >= $primary_max)
+ {
+ $url = $this->save_convert_progress($converter, 'final_jump=1');
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+ else
+ {
+ $sync_batch--;
+ }
+
+ $url = $this->save_convert_progress($converter, 'sync_batch=' . $sync_batch);
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+
+ /**
+ * Save the convertor status
+ */
+ function save_convert_progress($convertor_tag, $step)
+ {
+ global $config, $convert, $language;
+
+ // Save convertor Status
+ $config->set('convert_progress', serialize(array(
+ 'step' => $step,
+ 'table_prefix' => $convert->src_table_prefix,
+ 'tag' => $convert->convertor_tag,
+ )), false);
+
+ $config->set('convert_db_server', serialize(array(
+ 'dbms' => $convert->src_dbms,
+ 'dbhost' => $convert->src_dbhost,
+ 'dbport' => $convert->src_dbport,
+ 'dbname' => $convert->src_dbname,
+ )), false);
+
+ $config->set('convert_db_user', serialize(array(
+ 'dbuser' => $convert->src_dbuser,
+ 'dbpasswd' => $convert->src_dbpasswd,
+ )), false);
+
+ return $this->controller_helper->route('phpbb_convert_convert', array('converter' => $convertor_tag)) . '?' . $step;
+ }
+
+ /**
+ * Finish conversion, the last function to be called.
+ */
+ function finish_conversion()
+ {
+ global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user;
+ global $cache, $auth, $phpbb_container, $phpbb_log;
+
+ include_once ($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
+
+ $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
+ WHERE config_name = 'convert_progress'
+ OR config_name = 'convert_options'
+ OR config_name = 'convert_db_server'
+ OR config_name = 'convert_db_user'");
+ $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
+
+ @unlink($phpbb_container->getParameter('core.cache_dir') . 'data_global.' . $phpEx);
+ phpbb_cache_moderators($db, $cache, $auth);
+
+ // And finally, add a note to the log
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_CONVERTED', false, array($convert->convertor_data['forum_name'], $config['version']));
+
+ $url = $this->controller_helper->route('phpbb_convert_finish');
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['FINAL_STEP'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+
+ /**
+ * This function marks the steps after syncing
+ */
+ function final_jump($final_jump)
+ {
+ global $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
+ global $convert;
+
+ $this->template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $user->lang['PROCESS_LAST'],
+ ));
+
+ if ($final_jump == 1)
+ {
+ $db->sql_return_on_error(true);
+
+ update_topics_posted();
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => $user->lang['UPDATE_TOPICS_POSTED'],
+ 'RESULT' => $user->lang['DONE'],
+ ));
+
+ if ($db->get_sql_error_triggered())
+ {
+ $this->template->assign_vars(array(
+ 'S_ERROR_BOX' => true,
+ 'ERROR_TITLE' => $user->lang['UPDATE_TOPICS_POSTED'],
+ 'ERROR_MSG' => $user->lang['UPDATE_TOPICS_POSTED_ERR'],
+ ));
+ }
+ $db->sql_return_on_error(false);
+
+ $this->finish_conversion();
+ return;
+ }
+ }
+
+ /**
+ * This function marks the steps before syncing (jump=1)
+ */
+ function jump($converter, $jump, $last_statement)
+ {
+ /** @var \phpbb\db\driver\driver_interface $src_db */
+ /** @var \phpbb\cache\driver\driver_interface $cache */
+ global $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
+ global $convert;
+
+ include_once ($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
+
+ $this->template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $user->lang['PROCESS_LAST'],
+ ));
+
+ if ($jump == 1)
+ {
+ // Execute 'last' statements/queries
+ if (!empty($convert->convertor['execute_last']))
+ {
+ if (!is_array($convert->convertor['execute_last']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($convert->convertor['execute_last']);
+ // @codingStandardsIgnoreEnd
+ }
+ else
+ {
+ while ($last_statement < sizeof($convert->convertor['execute_last']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($convert->convertor['execute_last'][$last_statement]);
+ // @codingStandardsIgnoreEnd
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => $convert->convertor['execute_last'][$last_statement],
+ 'RESULT' => $user->lang['DONE'],
+ ));
+
+ $last_statement++;
+ $url = $this->save_convert_progress($converter, 'jump=1&amp;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);
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['CONTINUE_LAST'],
+ 'BODY' => $msg,
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+ }
+ }
+
+ if (!empty($convert->convertor['query_last']))
+ {
+ if (!is_array($convert->convertor['query_last']))
+ {
+ $convert->convertor['query_last'] = array('target', array($convert->convertor['query_last']));
+ }
+ else if (!is_array($convert->convertor['query_last'][0]))
+ {
+ $convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1]));
+ }
+
+ foreach ($convert->convertor['query_last'] as $query_last)
+ {
+ if ($query_last[0] == 'src')
+ {
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ $src_db->sql_query($query_last[1]);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+ }
+ else
+ {
+ $db->sql_query($query_last[1]);
+ }
+ }
+ }
+
+ // Sanity check
+ $db->sql_return_on_error(false);
+ $src_db->sql_return_on_error(false);
+
+ fix_empty_primary_groups();
+
+ $sql = 'SELECT MIN(user_regdate) AS board_startdate
+ FROM ' . USERS_TABLE;
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0))
+ {
+ $config->set('board_startdate', $row['board_startdate']);
+ $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS);
+ }
+
+ update_dynamic_config();
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => $user->lang['CLEAN_VERIFY'],
+ 'RESULT' => $user->lang['DONE'],
+ ));
+
+ $url = $this->save_convert_progress($converter, 'jump=2');
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+
+ if ($jump == 2)
+ {
+ $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_permissions = ''");
+
+ // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics.
+ // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing)
+ sync('forum', '', '', false, true);
+ $cache->destroy('sql', FORUMS_TABLE);
+
+ $this->template->assign_block_vars('checks', array(
+ 'TITLE' => $user->lang['SYNC_FORUMS'],
+ 'RESULT' => $user->lang['DONE'],
+ ));
+
+ // Continue with synchronizing the forums...
+ $url = $this->save_convert_progress($converter, 'sync_batch=0');
+
+ $this->template->assign_vars(array(
+ 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
+ 'U_ACTION' => $url,
+ ));
+
+ $this->meta_refresh($url);
+ return;
+ }
+ }
+
+ function build_insert_query(&$schema, &$sql_data, $current_table)
+ {
+ global $db, $user;
+ global $convert;
+
+ // Can we use IGNORE with this DBMS?
+ $sql_ignore = (strpos($db->get_sql_layer(), 'mysql') === 0 && !defined('DEBUG')) ? 'IGNORE ' : '';
+ $insert_query = 'INSERT ' . $sql_ignore . 'INTO ' . $schema['target'] . ' (';
+
+ $aliases = array();
+
+ $sql_data = array(
+ 'source_fields' => array(),
+ 'target_fields' => array(),
+ 'source_tables' => array(),
+ 'select_fields' => array(),
+ );
+
+ foreach ($schema as $key => $val)
+ {
+ // Example: array('group_name', 'extension_groups.group_name', 'htmlspecialchars'),
+ if (is_int($key))
+ {
+ if (!empty($val[0]))
+ {
+ // Target fields
+ $sql_data['target_fields'][$val[0]] = $key;
+ $insert_query .= $val[0] . ', ';
+ }
+
+ if (!is_array($val[1]))
+ {
+ $val[1] = array($val[1]);
+ }
+
+ foreach ($val[1] as $valkey => $value_1)
+ {
+ // This should cover about any case:
+ //
+ // table.field => SELECT table.field FROM table
+ // table.field AS alias => SELECT table.field AS alias FROM table
+ // table.field AS table2.alias => SELECT table2.field AS alias FROM table table2
+ // table.field AS table2.field => SELECT table2.field FROM table table2
+ //
+ if (preg_match('/^([a-z0-9_]+)\.([a-z0-9_]+)( +AS +(([a-z0-9_]+?)\.)?([a-z0-9_]+))?$/i', $value_1, $m))
+ {
+ // There is 'AS ...' in the field names
+ if (!empty($m[3]))
+ {
+ $value_1 = ($m[2] == $m[6]) ? $m[1] . '.' . $m[2] : $m[1] . '.' . $m[2] . ' AS ' . $m[6];
+
+ // Table alias: store it then replace the source table with it
+ if (!empty($m[5]) && $m[5] != $m[1])
+ {
+ $aliases[$m[5]] = $m[1];
+ $value_1 = str_replace($m[1] . '.' . $m[2], $m[5] . '.' . $m[2], $value_1);
+ }
+ }
+ else
+ {
+ // No table alias
+ $sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix . $m[1] . ' ' . $m[1];
+ }
+
+ $sql_data['select_fields'][$value_1] = $value_1;
+ $sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2];
+ }
+ }
+ }
+ else if ($key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having')
+ {
+ if (@preg_match_all('/([a-z0-9_]+)\.([a-z0-9_]+)/i', $val, $m))
+ {
+ foreach ($m[1] as $value)
+ {
+ $sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value : $convert->src_table_prefix . $value . ' ' . $value;
+ }
+ }
+ }
+ }
+
+ // Add the aliases to the list of tables
+ foreach ($aliases as $alias => $table)
+ {
+ $sql_data['source_tables'][$alias] = $convert->src_table_prefix . $table . ' ' . $alias;
+ }
+
+ // 'left_join' => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id',
+ if (!empty($schema['left_join']))
+ {
+ if (!is_array($schema['left_join']))
+ {
+ $schema['left_join'] = array($schema['left_join']);
+ }
+
+ foreach ($schema['left_join'] as $left_join)
+ {
+ // This won't handle concatened LEFT JOINs
+ if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i', $left_join, $m))
+ {
+ $this->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN', $left_join, $current_table, $schema['target']), __LINE__, __FILE__);
+ }
+
+ if (!empty($aliases[$m[2]]))
+ {
+ if (!empty($m[3]))
+ {
+ $this->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE__, __FILE__);
+ }
+
+ $m[2] = $aliases[$m[2]];
+ $m[3] = $m[2];
+ }
+
+ $right_table = $convert->src_table_prefix . $m[2];
+ if (!empty($m[3]))
+ {
+ unset($sql_data['source_tables'][$m[3]]);
+ }
+ else if ($m[2] != $m[1])
+ {
+ unset($sql_data['source_tables'][$m[2]]);
+ }
+
+ if (strpos($sql_data['source_tables'][$m[1]], "\nLEFT JOIN") !== false)
+ {
+ $sql_data['source_tables'][$m[1]] = '(' . $sql_data['source_tables'][$m[1]] . ")\nLEFT JOIN $right_table";
+ }
+ else
+ {
+ $sql_data['source_tables'][$m[1]] .= "\nLEFT JOIN $right_table";
+ }
+
+ if (!empty($m[3]))
+ {
+ unset($sql_data['source_tables'][$m[3]]);
+ $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[3];
+ }
+ else if (!empty($convert->src_table_prefix))
+ {
+ $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[2];
+ }
+ $sql_data['source_tables'][$m[1]] .= ' ' . $m[4] . $m[5];
+ }
+ }
+
+ // Remove ", " from the end of the insert query
+ $insert_query = substr($insert_query, 0, -2) . ') VALUES ';
+
+ return $insert_query;
+ }
+
+ /**
+ * Function for processing the currently handled row
+ */
+ function process_row(&$schema, &$sql_data, &$insert_values)
+ {
+ global $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache;
+ global $convert, $convert_row;
+
+ $sql_flag = false;
+
+ foreach ($schema as $key => $fields)
+ {
+ // We are only interested in the lines with:
+ // array('comment', 'attachments_desc.comment', 'htmlspecialchars'),
+ if (is_int($key))
+ {
+ if (!is_array($fields[1]))
+ {
+ $fields[1] = array($fields[1]);
+ }
+
+ $firstkey_set = false;
+ $firstkey = 0;
+
+ foreach ($fields[1] as $inner_key => $inner_value)
+ {
+ if (!$firstkey_set)
+ {
+ $firstkey = $inner_key;
+ $firstkey_set = true;
+ }
+
+ $src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : '';
+
+ if (!empty($src_field))
+ {
+ $fields[1][$inner_key] = $convert->row[$src_field];
+ }
+ }
+
+ if (!empty($fields[0]))
+ {
+ // We have a target field, if we haven't set $sql_flag yet it will be set to TRUE.
+ // If a function has already set it to FALSE it won't change it.
+ if ($sql_flag === false)
+ {
+ $sql_flag = true;
+ }
+
+ // No function assigned?
+ if (empty($fields[2]))
+ {
+ $value = $fields[1][$firstkey];
+ }
+ else if (is_array($fields[2]) && !is_callable($fields[2]))
+ {
+ // Execute complex function/eval/typecast
+ $value = $fields[1];
+
+ foreach ($fields[2] as $type => $execution)
+ {
+ if (strpos($type, 'typecast') === 0)
+ {
+ if (!is_array($value))
+ {
+ $value = array($value);
+ }
+ $value = $value[0];
+ settype($value, $execution);
+ }
+ else if (strpos($type, 'function') === 0)
+ {
+ if (!is_array($value))
+ {
+ $value = array($value);
+ }
+
+ $value = call_user_func_array($execution, $value);
+ }
+ else if (strpos($type, 'execute') === 0)
+ {
+ if (!is_array($value))
+ {
+ $value = array($value);
+ }
+
+ $execution = str_replace('{RESULT}', '$value', $execution);
+ $execution = str_replace('{VALUE}', '$value', $execution);
+ // @codingStandardsIgnoreStart
+ eval($execution);
+ // @codingStandardsIgnoreEnd
+ }
+ }
+ }
+ else
+ {
+ $value = call_user_func_array($fields[2], $fields[1]);
+ }
+
+ if (is_null($value))
+ {
+ $value = '';
+ }
+
+ $insert_values[] = $db->_sql_validate_value($value);
+ }
+ else if (!empty($fields[2]))
+ {
+ if (is_array($fields[2]))
+ {
+ // Execute complex function/eval/typecast
+ $value = '';
+
+ foreach ($fields[2] as $type => $execution)
+ {
+ if (strpos($type, 'typecast') === 0)
+ {
+ $value = settype($value, $execution);
+ }
+ else if (strpos($type, 'function') === 0)
+ {
+ if (!is_array($value))
+ {
+ $value = array($value);
+ }
+
+ $value = call_user_func_array($execution, $value);
+ }
+ else if (strpos($type, 'execute') === 0)
+ {
+ if (!is_array($value))
+ {
+ $value = array($value);
+ }
+
+ $execution = str_replace('{RESULT}', '$value', $execution);
+ $execution = str_replace('{VALUE}', '$value', $execution);
+ // @codingStandardsIgnoreStart
+ eval($execution);
+ // @codingStandardsIgnoreEnd
+ }
+ }
+ }
+ else
+ {
+ call_user_func_array($fields[2], $fields[1]);
+ }
+ }
+ }
+ }
+
+ return $sql_flag;
+ }
+
+ /**
+ * Own meta refresh function to be able to change the global time used
+ */
+ function meta_refresh($url)
+ {
+ global $convert;
+
+ if ($convert->options['refresh'])
+ {
+ // Because we should not rely on correct settings, we simply use the relative path here directly.
+ $this->template->assign_vars(array(
+ 'S_REFRESH' => true,
+ 'META' => '<meta http-equiv="refresh" content="5; url=' . $url . '" />')
+ );
+ }
+ }
+
+ /**
+ * Error handler function
+ *
+ * This function needs to be kept for BC
+ *
+ * @param $error
+ * @param $line
+ * @param $file
+ * @param bool|false $skip
+ */
+ public function error($error, $line, $file, $skip = false)
+ {
+ $this->template->assign_block_vars('errors', array(
+ 'TITLE' => $error,
+ 'DESCRIPTION' => 'In ' . $file . ' on line ' . $line,
+ ));
+ }
+
+ /**
+ * Database error handler function
+ *
+ * This function needs to be kept for BC
+ *
+ * @param $error
+ * @param $sql
+ * @param $line
+ * @param $file
+ * @param bool|false $skip
+ */
+ public function db_error($error, $sql, $line, $file, $skip = false)
+ {
+ $this->template->assign_block_vars('errors', array(
+ 'TITLE' => $error,
+ 'DESCRIPTION' => 'In ' . $file . ' on line ' . $line . '<br /><br /><strong>SQL:</strong> ' . $sql,
+ ));
+ }
+}
diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php
index 2afec68de6..e5866add7d 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.1.10',
+ 'phpbb_version' => '3.2.0-RC1',
'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>',
'dbms' => $dbms,
'dbhost' => $dbhost,
@@ -233,11 +233,11 @@ if (!$get_info)
$user_id = (int) $src_db->sql_fetchfield('max_user_id');
$src_db->sql_freeresult($result);
- set_config('increment_user_id', ($user_id + 1), true);
+ $config->set('increment_user_id', ($user_id + 1), false);
}
else
{
- set_config('increment_user_id', 0, true);
+ $config->set('increment_user_id', 0, false);
}
// Overwrite maximum avatar width/height
@@ -963,7 +963,6 @@ if (!$get_info)
array('pf_phpbb_interests', 'users.user_interests', array('function1' => 'phpbb_set_encoding')),
array('pf_phpbb_location', 'users.user_from', array('function1' => 'phpbb_set_encoding')),
array('pf_phpbb_icq', 'users.user_icq', array('function1' => 'phpbb_set_encoding')),
- array('pf_phpbb_wlm', 'users.user_msnm', array('function1' => 'phpbb_set_encoding')),
array('pf_phpbb_yahoo', 'users.user_yim', array('function1' => 'phpbb_set_encoding')),
array('pf_phpbb_aol', 'users.user_aim', array('function1' => 'phpbb_set_encoding')),
array('pf_phpbb_website', 'users.user_website', 'validate_website'),
diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php
index 817c007274..6f43e1915e 100644
--- a/phpBB/install/convertors/functions_phpbb20.php
+++ b/phpBB/install/convertors/functions_phpbb20.php
@@ -54,7 +54,7 @@ function phpbb_forum_flags()
*/
function phpbb_insert_forums()
{
- global $db, $src_db, $same_db, $convert, $user, $config;
+ global $db, $src_db, $same_db, $convert, $user;
$db->sql_query($convert->truncate_statement . FORUMS_TABLE);
@@ -94,7 +94,6 @@ function phpbb_insert_forums()
switch ($db->get_sql_layer())
{
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$db->sql_query('SET IDENTITY_INSERT ' . FORUMS_TABLE . ' ON');
@@ -179,7 +178,6 @@ function phpbb_insert_forums()
$db->sql_query($sql);
$cats_added[$unknown_cat_id] = $max_forum_id;
- $max_forum_id++;
}
// Now insert the forums
@@ -295,7 +293,6 @@ function phpbb_insert_forums()
$db->sql_query("SELECT SETVAL('" . FORUMS_TABLE . "_seq',(select case when max(forum_id)>0 then max(forum_id)+1 else 1 end from " . FORUMS_TABLE . '));');
break;
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$db->sql_query('SET IDENTITY_INSERT ' . FORUMS_TABLE . ' OFF');
@@ -422,8 +419,6 @@ function phpbb_set_encoding($text, $grab_user_lang = true)
}
}
- $encoding = $lang_enc_array[$get_lang];
-
return utf8_recode($text, $lang_enc_array[$get_lang]);
}
@@ -514,12 +509,12 @@ function phpbb_user_id($user_id)
// If there is a user id 1, we need to increment user ids. :/
if ($id === 1)
{
- set_config('increment_user_id', ($max_id + 1), true);
+ $config->set('increment_user_id', ($max_id + 1), false);
$config['increment_user_id'] = $max_id + 1;
}
else
{
- set_config('increment_user_id', 0, true);
+ $config->set('increment_user_id', 0, false);
$config['increment_user_id'] = 0;
}
}
@@ -564,7 +559,7 @@ function phpbb_copy_table_fields()
*/
function phpbb_convert_authentication($mode)
{
- global $db, $src_db, $same_db, $convert, $user, $config, $cache;
+ global $db, $src_db, $same_db, $convert, $config;
if ($mode == 'start')
{
@@ -661,7 +656,7 @@ function phpbb_convert_authentication($mode)
'auth_delete' => 'f_delete',
'auth_pollcreate' => 'f_poll',
'auth_vote' => 'f_vote',
- 'auth_announce' => 'f_announce',
+ 'auth_announce' => array('f_announce', 'f_announce_global'),
'auth_sticky' => 'f_sticky',
'auth_attachments' => array('f_attach', 'f_download'),
'auth_download' => 'f_download',
@@ -990,7 +985,7 @@ function phpbb_convert_authentication($mode)
// We make sure that they have at least standard access to the forums they moderate in addition to the moderating permissions
$mod_post_map = array(
- 'auth_announce' => 'f_announce',
+ 'auth_announce' => array('f_announce', 'f_announce_global'),
'auth_sticky' => 'f_sticky'
);
@@ -1221,7 +1216,7 @@ function phpbb_replace_size($matches)
*/
function phpbb_prepare_message($message)
{
- global $phpbb_root_path, $phpEx, $db, $convert, $user, $config, $cache, $convert_row, $message_parser;
+ global $convert, $user, $convert_row, $message_parser;
if (!$message)
{
@@ -1251,9 +1246,6 @@ function phpbb_prepare_message($message)
$message = str_replace('\&quot;', '&quot;', $message);
}
- // Already the new user id ;)
- $user_id = $convert->row['poster_id'];
-
$message = str_replace('<br />', "\n", $message);
$message = str_replace('<', '&lt;', $message);
$message = str_replace('>', '&gt;', $message);
@@ -1305,7 +1297,7 @@ function get_bbcode_bitfield()
*/
function phpbb_post_edit_user()
{
- global $convert_row, $config;
+ global $convert_row;
if (isset($convert_row['post_edit_count']))
{
@@ -1326,7 +1318,7 @@ function phpbb_get_files_dir()
return;
}
- global $src_db, $same_db, $convert, $user, $config, $cache;
+ global $src_db, $same_db, $convert, $user;
if ($convert->mysql_convert && $same_db)
{
@@ -1365,7 +1357,7 @@ function phpbb_get_files_dir()
*/
function phpbb_copy_thumbnails()
{
- global $db, $convert, $user, $config, $cache, $phpbb_root_path;
+ global $convert, $config, $phpbb_root_path;
$src_path = $convert->options['forum_path'] . '/' . phpbb_get_files_dir() . '/thumbs/';
@@ -1611,8 +1603,6 @@ function phpbb_get_avatar_width($user_avatar)
*/
function phpbb_privmsgs_to_userid($to_userid)
{
- global $config;
-
return 'u_' . phpbb_user_id($to_userid);
}
@@ -1659,7 +1649,7 @@ function phpbb_get_savebox_id($user_id)
*/
function phpbb_import_attach_config()
{
- global $db, $src_db, $same_db, $convert, $config;
+ global $src_db, $same_db, $convert, $config;
if ($convert->mysql_convert && $same_db)
{
@@ -1682,29 +1672,29 @@ function phpbb_import_attach_config()
}
$src_db->sql_freeresult($result);
- set_config('allow_attachments', 1);
+ $config->set('allow_attachments', 1);
// old attachment mod? Must be very old if this entry do not exist...
if (!empty($attach_config['display_order']))
{
- set_config('display_order', $attach_config['display_order']);
- }
- set_config('max_filesize', $attach_config['max_filesize']);
- set_config('max_filesize_pm', $attach_config['max_filesize_pm']);
- set_config('attachment_quota', $attach_config['attachment_quota']);
- set_config('max_attachments', $attach_config['max_attachments']);
- set_config('max_attachments_pm', $attach_config['max_attachments_pm']);
- set_config('allow_pm_attach', $attach_config['allow_pm_attach']);
-
- set_config('img_display_inlined', $attach_config['img_display_inlined']);
- set_config('img_max_width', $attach_config['img_max_width']);
- set_config('img_max_height', $attach_config['img_max_height']);
- set_config('img_link_width', $attach_config['img_link_width']);
- set_config('img_link_height', $attach_config['img_link_height']);
- set_config('img_create_thumbnail', $attach_config['img_create_thumbnail']);
- set_config('img_max_thumb_width', 400);
- set_config('img_min_thumb_filesize', $attach_config['img_min_thumb_filesize']);
- set_config('img_imagick', $attach_config['img_imagick']);
+ $config->set('display_order', $attach_config['display_order']);
+ }
+ $config->set('max_filesize', $attach_config['max_filesize']);
+ $config->set('max_filesize_pm', $attach_config['max_filesize_pm']);
+ $config->set('attachment_quota', $attach_config['attachment_quota']);
+ $config->set('max_attachments', $attach_config['max_attachments']);
+ $config->set('max_attachments_pm', $attach_config['max_attachments_pm']);
+ $config->set('allow_pm_attach', $attach_config['allow_pm_attach']);
+
+ $config->set('img_display_inlined', $attach_config['img_display_inlined']);
+ $config->set('img_max_width', $attach_config['img_max_width']);
+ $config->set('img_max_height', $attach_config['img_max_height']);
+ $config->set('img_link_width', $attach_config['img_link_width']);
+ $config->set('img_link_height', $attach_config['img_link_height']);
+ $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']);
}
/**
@@ -1765,9 +1755,8 @@ function phpbb_disallowed_username($username)
*/
function phpbb_create_userconv_table()
{
- global $db, $src_db, $convert, $table_prefix, $user, $lang;
+ global $db;
- $map_dbms = '';
switch ($db->get_sql_layer())
{
case 'mysql':
@@ -1789,7 +1778,6 @@ function phpbb_create_userconv_table()
$map_dbms = 'mysql_41';
break;
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$map_dbms = 'mssql';
@@ -1839,7 +1827,6 @@ function phpbb_create_userconv_table()
)';
break;
- case 'sqlite':
case 'sqlite3':
$create_sql = 'CREATE TABLE ' . USERCONV_TABLE . ' (
user_id INTEGER NOT NULL DEFAULT \'0\',
@@ -1856,7 +1843,7 @@ function phpbb_create_userconv_table()
function phpbb_check_username_collisions()
{
- global $db, $src_db, $convert, $table_prefix, $user, $lang;
+ global $db, $src_db, $convert, $user, $lang;
// now find the clean version of the usernames that collide
$sql = 'SELECT username_clean
@@ -1926,7 +1913,9 @@ function phpbb_check_username_collisions()
function phpbb_convert_timezone($timezone)
{
global $config, $db, $phpbb_root_path, $phpEx, $table_prefix;
- $timezone_migration = new \phpbb\db\migration\data\v310\timezone($config, $db, new \phpbb\db\tools($db), $phpbb_root_path, $phpEx, $table_prefix);
+
+ $factory = new \phpbb\db\tools\factory();
+ $timezone_migration = new \phpbb\db\migration\data\v310\timezone($config, $db, $factory->get($db), $phpbb_root_path, $phpEx, $table_prefix);
return $timezone_migration->convert_phpbb30_timezone($timezone, 0);
}
@@ -1967,13 +1956,14 @@ function phpbb_add_notification_options($user_notify_pm)
);
}
- $sql = $db->sql_multi_insert(USER_NOTIFICATIONS_TABLE, $rows);
+ $db->sql_multi_insert(USER_NOTIFICATIONS_TABLE, $rows);
}
function phpbb_convert_password_hash($hash)
{
global $phpbb_container;
+ /* @var $manager \phpbb\passwords\manager */
$manager = $phpbb_container->get('passwords.manager');
$hash = $manager->hash($hash, '$H$');
diff --git a/phpBB/install/data/confusables.php b/phpBB/install/data/confusables.php
index e3e8c41e62..00e806f639 100644
--- a/phpBB/install/data/confusables.php
+++ b/phpBB/install/data/confusables.php
@@ -628,19 +628,12 @@ function utf8_new_case_fold_nfkc($text, $option = 'full')
"\xF0\x9D\x9E\xBB" => "\xCF\x83",
"\xF0\x9D\x9F\x8A" => "\xCF\x9D",
);
- global $phpbb_root_path, $phpEx;
// do the case fold
$text = utf8_new_case_fold($text, $option);
- if (!class_exists('utf_normalizer'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
- }
-
// convert to NFKC
- utf_new_normalizer::nfkc($text);
+ $text = Normalizer::normalize($text, Normalizer::NFKC);
// FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt
$text = strtr($text, $fc_nfkc_closure);
diff --git a/phpBB/install/data/new_normalizer.php b/phpBB/install/data/new_normalizer.php
deleted file mode 100644
index 52652a4f6d..0000000000
--- a/phpBB/install/data/new_normalizer.php
+++ /dev/null
@@ -1,197 +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.
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings
-* to be in NFC (Normalization Form Composition).
-*
-* @param mixed $strings a string or an array of strings to normalize
-* @return mixed the normalized content, preserving array keys if array given.
-*/
-function utf8_new_normalize_nfc($strings)
-{
- if (empty($strings))
- {
- return $strings;
- }
-
- if (!is_array($strings))
- {
- utf_new_normalizer::nfc($strings);
- }
- else if (is_array($strings))
- {
- foreach ($strings as $key => $string)
- {
- if (is_array($string))
- {
- foreach ($string as $_key => $_string)
- {
- utf_new_normalizer::nfc($strings[$key][$_key]);
- }
- }
- else
- {
- utf_new_normalizer::nfc($strings[$key]);
- }
- }
- }
-
- return $strings;
-}
-
-class utf_new_normalizer
-{
- /**
- * Validate, cleanup and normalize a string
- *
- * The ultimate convenience function! Clean up invalid UTF-8 sequences,
- * and convert to Normal Form C, canonical composition.
- *
- * @param string &$str The dirty string
- * @return string The same string, all shiny and cleaned-up
- */
- function cleanup(&$str)
- {
- // The string below is the list of all autorized characters, sorted by frequency in latin text
- $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D");
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings with no special chars return immediately
- return;
- }
-
- // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together
- if (!isset($GLOBALS['utf_nfc_qc']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx);
- }
-
- if (!isset($GLOBALS['utf_canonical_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx);
- }
-
- // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t
- // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char
- $str = strtr(
- $str,
- "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
- );
-
- $str = utf_new_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']);
- }
-
- /**
- * Validate and normalize a UTF string to NFC
- *
- * @param string &$str Unchecked UTF string
- * @return string The string, validated and in normal form
- */
- function nfc(&$str)
- {
- $pos = strspn($str, UTF8_ASCII_RANGE);
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings return immediately
- return;
- }
-
- if (!isset($GLOBALS['utf_nfc_qc']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx);
- }
-
- if (!isset($GLOBALS['utf_canonical_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx);
- }
-
- $str = utf_new_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']);
- }
-
- /**
- * Validate and normalize a UTF string to NFKC
- *
- * @param string &$str Unchecked UTF string
- * @return string The string, validated and in normal form
- */
- function nfkc(&$str)
- {
- $pos = strspn($str, UTF8_ASCII_RANGE);
- $len = strlen($str);
-
- if ($pos == $len)
- {
- // ASCII strings return immediately
- return;
- }
-
- if (!isset($GLOBALS['utf_nfkc_qc']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx);
- }
-
- if (!isset($GLOBALS['utf_compatibility_decomp']))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx);
- }
-
- $str = utf_new_normalizer::recompose($str, $pos, $len, $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']);
- }
-
- /**
- * Recompose a UTF string
- *
- * @param string $str Unchecked UTF string
- * @param integer $pos Position of the first UTF char (in bytes)
- * @param integer $len Length of the string (in bytes)
- * @param array &$qc Quick-check array, passed by reference but never modified
- * @param array &$decomp_map Decomposition mapping, passed by reference but never modified
- * @return string The string, validated and recomposed
- *
- * @access private
- */
- function recompose($str, $pos, $len, &$qc, &$decomp_map)
- {
- global $utf_canonical_comp;
-
- // Load the canonical composition table
- if (!isset($utf_canonical_comp))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx);
- }
-
- return utf_normalizer::recompose($str, $pos, $len, $qc, $decomp_map);
- }
-}
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
deleted file mode 100644
index f367ae1fc0..0000000000
--- a/phpBB/install/database_update.php
+++ /dev/null
@@ -1,244 +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.
-*
-*/
-
-$update_start_time = time();
-
-/**
-* @ignore
-*/
-define('IN_PHPBB', true);
-define('IN_INSTALL', true);
-$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-function phpbb_end_update($cache, $config)
-{
- $cache->purge();
-
- $config->increment('assets_version', 1);
-
-?>
- </p>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <div id="page-footer">
- <div class="copyright">
- Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited
- </div>
- </div>
- </div>
-</body>
-</html>
-
-<?php
-
- garbage_collection();
- exit_handler();
-}
-
-require($phpbb_root_path . 'includes/startup.' . $phpEx);
-require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
-
-$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
-$phpbb_class_loader->register();
-
-$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
-extract($phpbb_config_php_file->get_all());
-
-if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
-{
- die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
-}
-
-// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
-$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
-$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
-
-// Include files
-require($phpbb_root_path . 'includes/functions.' . $phpEx);
-require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
-
-require($phpbb_root_path . 'includes/constants.' . $phpEx);
-include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
-require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
-
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
-
-// Set up container (must be done here because extensions table may not exist)
-$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
-$phpbb_container_builder->set_use_extensions(false);
-$phpbb_container_builder->set_use_kernel_pass(false);
-$phpbb_container_builder->set_dump_container(false);
-$phpbb_container = $phpbb_container_builder->get_container();
-
-// set up caching
-$cache = $phpbb_container->get('cache');
-
-// Instantiate some basic classes
-$phpbb_dispatcher = $phpbb_container->get('dispatcher');
-$request = $phpbb_container->get('request');
-$user = $phpbb_container->get('user');
-$auth = $phpbb_container->get('auth');
-$db = $phpbb_container->get('dbal.conn');
-$phpbb_log = $phpbb_container->get('log');
-
-// make sure request_var uses this request instance
-request_var('', 0, false, false, $request); // "dependency injection" for a function
-
-// Grab global variables, re-cache if necessary
-$config = $phpbb_container->get('config');
-set_config(null, null, null, $config);
-set_config_count(null, null, null, $config);
-
-if (!isset($config['version_update_from']))
-{
- $config->set('version_update_from', $config['version']);
-}
-
-$orig_version = $config['version_update_from'];
-
-$user->add_lang(array('common', 'acp/common', 'install', 'migrator'));
-
-// Add own hook handler, if present. :o
-if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
-{
- require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
- $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
-
- $phpbb_hook_finder = $phpbb_container->get('hook_finder');
- foreach ($phpbb_hook_finder->find() as $hook)
- {
- @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
- }
-}
-else
-{
- $phpbb_hook = false;
-}
-
-header('Content-type: text/html; charset=UTF-8');
-?>
-<!DOCTYPE html>
-<html dir="<?php echo $user->lang['DIRECTION']; ?>" lang="<?php echo $user->lang['USER_LANG']; ?>">
-<head>
-<meta charset="utf-8">
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-
-<title><?php echo $user->lang['UPDATING_TO_LATEST_STABLE']; ?></title>
-
-<link href="<?php echo htmlspecialchars($phpbb_admin_path); ?>style/admin.css" rel="stylesheet" type="text/css" media="screen" />
-
-</head>
-
-<body>
- <div id="wrap">
- <div id="page-header">&nbsp;</div>
-
- <div id="page-body">
- <div id="acp">
- <div class="panel">
- <div id="content">
- <div id="main" class="install-body">
-
- <h1><?php echo $user->lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
-
- <br />
-
- <p><?php echo $user->lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->get_sql_layer(); ?></strong><br />
- <?php echo $user->lang['PREVIOUS_VERSION']; ?> :: <strong><?php echo $config['version']; ?></strong><br />
-
-<?php
-
-define('IN_DB_UPDATE', true);
-
-/**
-* @todo mysql update?
-*/
-
-// End startup code
-
-$migrator = $phpbb_container->get('migrator');
-$migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log'));
-
-$migrator->create_migrations_table();
-
-$phpbb_extension_manager = $phpbb_container->get('ext.manager');
-
-$migrations = $phpbb_extension_manager
- ->get_finder()
- ->core_path('phpbb/db/migration/data/')
- ->extension_directory('/migrations')
- ->get_classes();
-
-$migrator->set_migrations($migrations);
-
-// What is a safe limit of execution time? Half the max execution time should be safe.
-// No more than 15 seconds so the user isn't sitting and waiting for a very long time
-$phpbb_ini = new \phpbb\php\ini();
-$safe_time_limit = min(15, ($phpbb_ini->get_int('max_execution_time') / 2));
-
-// While we're going to try limit this to half the max execution time,
-// we want to try and take additional measures to prevent hitting the
-// max execution time (if, say, one migration step takes much longer
-// than the max execution time)
-@set_time_limit(0);
-
-while (!$migrator->finished())
-{
- try
- {
- $migrator->update();
- }
- catch (\phpbb\db\migration\exception $e)
- {
- echo $e->getLocalisedMessage($user);
-
- phpbb_end_update($cache, $config);
- }
-
- // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
- if ((time() - $update_start_time) >= $safe_time_limit)
- {
- echo '<br />' . $user->lang['DATABASE_UPDATE_NOT_COMPLETED'] . '<br /><br />';
- echo '<a href="' . append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=' . $request->variable('type', 0) . '&amp;language=' . $request->variable('language', 'en')) . '" class="button1">' . $user->lang['DATABASE_UPDATE_CONTINUE'] . '</a>';
-
- phpbb_end_update($cache, $config);
- }
-}
-
-if ($orig_version != $config['version'])
-{
- add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $config['version']);
-}
-
-echo $user->lang['DATABASE_UPDATE_COMPLETE'] . '<br />';
-
-if ($request->variable('type', 0))
-{
- echo $user->lang['INLINE_UPDATE_SUCCESSFUL'] . '<br /><br />';
- echo '<a href="' . append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update&amp;sub=update_db&amp;language=' . $request->variable('language', 'en')) . '" class="button1">' . $user->lang['CONTINUE_UPDATE_NOW'] . '</a>';
-}
-else
-{
- echo '<div class="errorbox">' . $user->lang['UPDATE_FILES_NOTICE'] . '</div>';
- echo $user->lang['COMPLETE_LOGIN_TO_BOARD'];
-}
-
-$config->delete('version_update_from');
-
-phpbb_end_update($cache, $config);
diff --git a/phpBB/install/index.html b/phpBB/install/index.html
new file mode 100644
index 0000000000..8f8bfb4fb2
--- /dev/null
+++ b/phpBB/install/index.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<title></title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="refresh" content="0; url=./app.php" />
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000">
+
+</body>
+</html>
diff --git a/phpBB/install/index.php b/phpBB/install/index.php
deleted file mode 100644
index b5d14f27cf..0000000000
--- a/phpBB/install/index.php
+++ /dev/null
@@ -1,834 +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.
-*
-*/
-
-/**#@+
-* @ignore
-*/
-define('IN_PHPBB', true);
-define('IN_INSTALL', true);
-/**#@-*/
-
-$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-if (version_compare(PHP_VERSION, '5.3.3') < 0)
-{
- die('You are running an unsupported PHP version. Please upgrade to PHP 5.3.3 or higher before trying to install phpBB 3.1');
-}
-
-function phpbb_require_updated($path, $optional = false)
-{
- global $phpbb_root_path, $table_prefix;
-
- $new_path = $phpbb_root_path . 'install/update/new/' . $path;
- $old_path = $phpbb_root_path . $path;
-
- if (file_exists($new_path))
- {
- require($new_path);
- }
- else if (!$optional || file_exists($old_path))
- {
- require($old_path);
- }
-}
-
-function phpbb_include_updated($path, $optional = false)
-{
- global $phpbb_root_path;
-
- $new_path = $phpbb_root_path . 'install/update/new/' . $path;
- $old_path = $phpbb_root_path . $path;
-
- if (file_exists($new_path))
- {
- include($new_path);
- }
- else if (!$optional || file_exists($old_path))
- {
- include($old_path);
- }
-}
-
-phpbb_require_updated('includes/startup.' . $phpEx);
-
-// Try to override some limits - maybe it helps some...
-@set_time_limit(0);
-$mem_limit = @ini_get('memory_limit');
-if (!empty($mem_limit))
-{
- $unit = strtolower(substr($mem_limit, -1, 1));
- $mem_limit = (int) $mem_limit;
-
- if ($unit == 'k')
- {
- $mem_limit = floor($mem_limit / 1024);
- }
- else if ($unit == 'g')
- {
- $mem_limit *= 1024;
- }
- else if (is_numeric($unit))
- {
- $mem_limit = floor((int) ($mem_limit . $unit) / 1048576);
- }
- $mem_limit = max(128, $mem_limit) . 'M';
-}
-else
-{
- $mem_limit = '128M';
-}
-@ini_set('memory_limit', $mem_limit);
-
-// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
-$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
-$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
-
-// Include essential scripts
-phpbb_require_updated('phpbb/class_loader.' . $phpEx);
-
-phpbb_require_updated('includes/functions.' . $phpEx);
-
-phpbb_require_updated('includes/functions_content.' . $phpEx, true);
-
-phpbb_include_updated('includes/functions_admin.' . $phpEx);
-phpbb_include_updated('includes/utf/utf_normalizer.' . $phpEx);
-phpbb_include_updated('includes/utf/utf_tools.' . $phpEx);
-phpbb_require_updated('includes/functions_install.' . $phpEx);
-
-// Setup class loader first
-$phpbb_class_loader_new = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}install/update/new/phpbb/", $phpEx);
-$phpbb_class_loader_new->register();
-$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
-$phpbb_class_loader->register();
-$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
-$phpbb_class_loader_ext->register();
-
-// Set up container
-$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
-$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
-$phpbb_container_builder->set_use_extensions(false);
-$phpbb_container_builder->set_dump_container(false);
-$phpbb_container_builder->set_use_custom_pass(false);
-$phpbb_container_builder->set_inject_config(false);
-$phpbb_container_builder->set_compile_container(false);
-
-$other_config_path = $phpbb_root_path . 'install/update/new/config/';
-$config_path = file_exists($other_config_path . 'services.yml') ? $other_config_path : $phpbb_root_path . 'config/';
-$phpbb_container_builder->set_config_path($config_path);
-
-$phpbb_container_builder->set_custom_parameters(array(
- 'core.root_path' => $phpbb_root_path,
- 'core.adm_relative_path' => $phpbb_adm_relative_path,
- 'core.php_ext' => $phpEx,
- 'core.table_prefix' => '',
- 'cache.driver.class' => 'phpbb\cache\driver\file',
-));
-
-$phpbb_container = $phpbb_container_builder->get_container();
-$phpbb_container->register('dbal.conn.driver')->setSynthetic(true);
-$phpbb_container->compile();
-
-$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
-$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
-
-$phpbb_dispatcher = $phpbb_container->get('dispatcher');
-$request = $phpbb_container->get('request');
-
-// make sure request_var uses this request instance
-request_var('', 0, false, false, $request); // "dependency injection" for a function
-
-// Try and load an appropriate language if required
-$language = basename($request->variable('language', ''));
-
-if ($request->header('Accept-Language') && !$language)
-{
- $accept_lang_ary = explode(',', strtolower($request->header('Accept-Language')));
- foreach ($accept_lang_ary as $accept_lang)
- {
- // Set correct format ... guess full xx_yy form
- $accept_lang = substr($accept_lang, 0, 2) . '_' . substr($accept_lang, 3, 2);
-
- if (file_exists($phpbb_root_path . 'language/' . $accept_lang) && is_dir($phpbb_root_path . 'language/' . $accept_lang))
- {
- $language = $accept_lang;
- break;
- }
- else
- {
- // No match on xx_yy so try xx
- $accept_lang = substr($accept_lang, 0, 2);
- if (file_exists($phpbb_root_path . 'language/' . $accept_lang) && is_dir($phpbb_root_path . 'language/' . $accept_lang))
- {
- $language = $accept_lang;
- break;
- }
- }
- }
-}
-
-// No appropriate language found ... so let's use the first one in the language
-// dir, this may or may not be English
-if (!$language)
-{
- $dir = @opendir($phpbb_root_path . 'language');
-
- if (!$dir)
- {
- die('Unable to access the language directory');
- exit;
- }
-
- while (($file = readdir($dir)) !== false)
- {
- $path = $phpbb_root_path . 'language/' . $file;
-
- if (!is_file($path) && !is_link($path) && file_exists($path . '/iso.txt'))
- {
- $language = $file;
- break;
- }
- }
- closedir($dir);
-}
-
-if (!file_exists($phpbb_root_path . 'language/' . $language) || !is_dir($phpbb_root_path . 'language/' . $language))
-{
- die('No language found!');
-}
-
-// And finally, load the relevant language files
-$load_lang_files = array('common', 'acp/common', 'acp/board', 'install', 'posting');
-$new_path = $phpbb_root_path . 'install/update/new/language/' . $language . '/';
-$old_path = $phpbb_root_path . 'language/' . $language . '/';
-
-// NOTE: we can not use "phpbb_include_updated" as the files uses vars which would be required
-// to be global while loading.
-foreach ($load_lang_files as $lang_file)
-{
- if (file_exists($new_path . $lang_file . '.' . $phpEx))
- {
- include($new_path . $lang_file . '.' . $phpEx);
- }
- else
- {
- include($old_path . $lang_file . '.' . $phpEx);
- }
-}
-
-// usually we would need every single constant here - and it would be consistent. For 3.0.x, use a dirty hack... :(
-
-// Define needed constants
-define('CHMOD_ALL', 7);
-define('CHMOD_READ', 4);
-define('CHMOD_WRITE', 2);
-define('CHMOD_EXECUTE', 1);
-
-$mode = $request->variable('mode', 'overview');
-$sub = $request->variable('sub', '');
-
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
-
-$user = new \phpbb\user('\phpbb\datetime');
-$auth = new \phpbb\auth\auth();
-
-// Add own hook handler, if present. :o
-if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
-{
- require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
- $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
-
- $phpbb_hook_finder = $phpbb_container->get('hook_finder');
- foreach ($phpbb_hook_finder->find() as $hook)
- {
- @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
- }
-}
-else
-{
- $phpbb_hook = false;
-}
-
-// Set some standard variables we want to force
-$config = new \phpbb\config\config(array(
- 'load_tplcompile' => '1'
-));
-
-$symfony_request = $phpbb_container->get('symfony_request');
-$phpbb_filesystem = $phpbb_container->get('filesystem');
-$phpbb_path_helper = $phpbb_container->get('path_helper');
-$template = new \phpbb\template\twig\twig($phpbb_path_helper, $config, $user, new \phpbb\template\context());
-$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
-$paths = array_filter($paths, 'is_dir');
-$template->set_custom_style(array(
- array(
- 'name' => 'adm',
- 'ext_path' => 'adm/style/',
- ),
-), $paths);
-
-$path = array_shift($paths);
-
-$template->assign_var('T_ASSETS_PATH', $path . '/../../assets');
-$template->assign_var('T_TEMPLATE_PATH', $path);
-
-$install = new module();
-
-$install->create('install', "index.$phpEx", $mode, $sub);
-$install->load();
-
-// Generate the page
-$install->page_header();
-$install->generate_navigation();
-
-$template->set_filenames(array(
- 'body' => $install->get_tpl_name())
-);
-
-$install->page_footer();
-
-class module
-{
- var $id = 0;
- var $type = 'install';
- var $module_ary = array();
- var $filename;
- var $module_url = '';
- var $tpl_name = '';
- var $mode;
- var $sub;
-
- /**
- * Private methods, should not be overwritten
- */
- function create($module_type, $module_url, $selected_mod = false, $selected_submod = false)
- {
- global $db, $config, $phpEx, $phpbb_root_path;
-
- $module = array();
-
- // Grab module information using Bart's "neat-o-module" system (tm)
- $dir = @opendir('.');
-
- if (!$dir)
- {
- $this->error('Unable to access the installation directory', __LINE__, __FILE__);
- }
-
- $setmodules = 1;
- while (($file = readdir($dir)) !== false)
- {
- if (preg_match('#^install_(.*?)\.' . $phpEx . '$#', $file))
- {
- include($file);
- }
- }
- closedir($dir);
-
- unset($setmodules);
-
- if (!sizeof($module))
- {
- $this->error('No installation modules found', __LINE__, __FILE__);
- }
-
- // Order to use and count further if modules get assigned to the same position or not having an order
- $max_module_order = 1000;
-
- foreach ($module as $row)
- {
- // Module order not specified or module already assigned at this position?
- if (!isset($row['module_order']) || isset($this->module_ary[$row['module_order']]))
- {
- $row['module_order'] = $max_module_order;
- $max_module_order++;
- }
-
- $this->module_ary[$row['module_order']]['name'] = $row['module_title'];
- $this->module_ary[$row['module_order']]['filename'] = $row['module_filename'];
- $this->module_ary[$row['module_order']]['subs'] = $row['module_subs'];
- $this->module_ary[$row['module_order']]['stages'] = $row['module_stages'];
-
- if (strtolower($selected_mod) == strtolower($row['module_title']))
- {
- $this->id = (int) $row['module_order'];
- $this->filename = (string) $row['module_filename'];
- $this->module_url = (string) $module_url;
- $this->mode = (string) $selected_mod;
- // Check that the sub-mode specified is valid or set a default if not
- if (is_array($row['module_subs']))
- {
- $this->sub = strtolower((in_array(strtoupper($selected_submod), $row['module_subs'])) ? $selected_submod : $row['module_subs'][0]);
- }
- else if (is_array($row['module_stages']))
- {
- $this->sub = strtolower((in_array(strtoupper($selected_submod), $row['module_stages'])) ? $selected_submod : $row['module_stages'][0]);
- }
- else
- {
- $this->sub = '';
- }
- }
- } // END foreach
- } // END create
-
- /**
- * Load and run the relevant module if applicable
- */
- function load($mode = false, $run = true)
- {
- global $phpbb_root_path, $phpEx;
-
- if ($run)
- {
- if (!empty($mode))
- {
- $this->mode = $mode;
- }
-
- $module = $this->filename;
- if (!class_exists($module))
- {
- $this->error('Module "' . htmlspecialchars($module) . '" not accessible.', __LINE__, __FILE__);
- }
- $this->module = new $module($this);
-
- if (method_exists($this->module, 'main'))
- {
- $this->module->main($this->mode, $this->sub);
- }
- }
- }
-
- /**
- * Output the standard page header
- */
- function page_header()
- {
- if (defined('HEADER_INC'))
- {
- return;
- }
-
- define('HEADER_INC', true);
- global $template, $lang, $stage, $phpbb_admin_path, $path;
-
- $template->assign_vars(array(
- 'L_CHANGE' => $lang['CHANGE'],
- 'L_COLON' => $lang['COLON'],
- 'L_INSTALL_PANEL' => $lang['INSTALL_PANEL'],
- 'L_SELECT_LANG' => $lang['SELECT_LANG'],
- 'L_SKIP' => $lang['SKIP'],
- 'PAGE_TITLE' => $this->get_page_title(),
- 'T_IMAGE_PATH' => htmlspecialchars($phpbb_admin_path) . 'images/',
- 'T_JQUERY_LINK' => $path . '/../../assets/javascript/jquery.min.js',
-
- 'S_CONTENT_DIRECTION' => $lang['DIRECTION'],
- 'S_CONTENT_FLOW_BEGIN' => ($lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
- 'S_CONTENT_FLOW_END' => ($lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
- 'S_CONTENT_ENCODING' => 'UTF-8',
-
- 'S_USER_LANG' => $lang['USER_LANG'],
- )
- );
-
- header('Content-type: text/html; charset=UTF-8');
- header('Cache-Control: private, no-cache="set-cookie"');
- header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
-
- return;
- }
-
- /**
- * Output the standard page footer
- */
- function page_footer()
- {
- global $db, $template;
-
- $template->display('body');
-
- // Close our DB connection.
- if (!empty($db) && is_object($db))
- {
- $db->sql_close();
- }
-
- if (function_exists('exit_handler'))
- {
- exit_handler();
- }
- }
-
- /**
- * Returns desired template name
- */
- function get_tpl_name()
- {
- return $this->module->tpl_name . '.html';
- }
-
- /**
- * Returns the desired page title
- */
- function get_page_title()
- {
- global $lang;
-
- if (!isset($this->module->page_title))
- {
- return '';
- }
-
- return (isset($lang[$this->module->page_title])) ? $lang[$this->module->page_title] : $this->module->page_title;
- }
-
- /**
- * Generate an HTTP/1.1 header to redirect the user to another page
- * This is used during the installation when we do not have a database available to call the normal redirect function
- * @param string $page The page to redirect to relative to the installer root path
- */
- function redirect($page)
- {
- global $request;
-
- // HTTP_HOST is having the correct browser url in most cases...
- $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
- $server_port = $request->server('SERVER_PORT', 0);
- $secure = $request->is_secure() ? 1 : 0;
-
- $script_name = htmlspecialchars_decode($request->server('PHP_SELF'));
- if (!$script_name)
- {
- $script_name = htmlspecialchars_decode($request->server('REQUEST_URI'));
- }
-
- // Replace backslashes and doubled slashes (could happen on some proxy setups)
- $script_name = str_replace(array('\\', '//'), '/', $script_name);
- $script_path = trim(dirname($script_name));
-
- $url = (($secure) ? 'https://' : 'http://') . $server_name;
-
- if ($server_port && (($secure && $server_port <> 443) || (!$secure && $server_port <> 80)))
- {
- // HTTP HOST can carry a port number...
- if (strpos($server_name, ':') === false)
- {
- $url .= ':' . $server_port;
- }
- }
-
- $url .= $script_path . '/' . $page;
- header('Location: ' . $url);
- exit;
- }
-
- /**
- * Generate the navigation tabs
- */
- function generate_navigation()
- {
- global $lang, $template, $phpEx, $language;
-
- if (is_array($this->module_ary))
- {
- @ksort($this->module_ary);
- foreach ($this->module_ary as $cat_ary)
- {
- $cat = $cat_ary['name'];
- $l_cat = (!empty($lang['CAT_' . $cat])) ? $lang['CAT_' . $cat] : preg_replace('#_#', ' ', $cat);
- $cat = strtolower($cat);
- $url = $this->module_url . "?mode=$cat&amp;language=$language";
-
- if ($this->mode == $cat)
- {
- $template->assign_block_vars('t_block1', array(
- 'L_TITLE' => $l_cat,
- 'S_SELECTED' => true,
- 'U_TITLE' => $url,
- ));
-
- if (is_array($this->module_ary[$this->id]['subs']))
- {
- $subs = $this->module_ary[$this->id]['subs'];
- foreach ($subs as $option)
- {
- $l_option = (!empty($lang['SUB_' . $option])) ? $lang['SUB_' . $option] : preg_replace('#_#', ' ', $option);
- $option = strtolower($option);
- $url = $this->module_url . '?mode=' . $this->mode . "&amp;sub=$option&amp;language=$language";
-
- $template->assign_block_vars('l_block1', array(
- 'L_TITLE' => $l_option,
- 'S_SELECTED' => ($this->sub == $option),
- 'U_TITLE' => $url,
- ));
- }
- }
-
- if (is_array($this->module_ary[$this->id]['stages']))
- {
- $subs = $this->module_ary[$this->id]['stages'];
- $matched = false;
- foreach ($subs as $option)
- {
- $l_option = (!empty($lang['STAGE_' . $option])) ? $lang['STAGE_' . $option] : preg_replace('#_#', ' ', $option);
- $option = strtolower($option);
- $matched = ($this->sub == $option) ? true : $matched;
-
- $template->assign_block_vars('l_block2', array(
- 'L_TITLE' => $l_option,
- 'S_SELECTED' => ($this->sub == $option),
- 'S_COMPLETE' => !$matched,
- ));
- }
- }
- }
- else
- {
- $template->assign_block_vars('t_block1', array(
- 'L_TITLE' => $l_cat,
- 'S_SELECTED' => false,
- 'U_TITLE' => $url,
- ));
- }
- }
- }
- }
-
- /**
- * Output an error message
- * If skip is true, return and continue execution, else exit
- */
- function error($error, $line, $file, $skip = false)
- {
- global $lang, $db, $template, $phpbb_admin_path;
-
- if ($skip)
- {
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['INST_ERR'],
- ));
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => basename($file) . ' [ ' . $line . ' ]',
- 'RESULT' => '<b style="color:red">' . $error . '</b>',
- ));
-
- return;
- }
-
- echo '<!DOCTYPE html>';
- echo '<html dir="ltr">';
- echo '<head>';
- echo '<meta charset="utf-8">';
- echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
- echo '<title>' . $lang['INST_ERR_FATAL'] . '</title>';
- echo '<link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" />';
- echo '</head>';
- echo '<body id="errorpage">';
- echo '<div id="wrap">';
- echo ' <div id="page-header">';
- echo ' </div>';
- echo ' <div id="page-body">';
- echo ' <div id="acp">';
- echo ' <div class="panel">';
- echo ' <span class="corners-top"><span></span></span>';
- echo ' <div id="content">';
- echo ' <h1>' . $lang['INST_ERR_FATAL'] . '</h1>';
- echo ' <p>' . $lang['INST_ERR_FATAL'] . "</p>\n";
- echo ' <p>' . basename($file) . ' [ ' . $line . " ]</p>\n";
- echo ' <p><b>' . $error . "</b></p>\n";
- echo ' </div>';
- echo ' <span class="corners-bottom"><span></span></span>';
- echo ' </div>';
- echo ' </div>';
- echo ' </div>';
- echo ' <div id="page-footer">';
- echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited';
- echo ' </div>';
- echo '</div>';
- echo '</body>';
- echo '</html>';
-
- if (!empty($db) && is_object($db))
- {
- $db->sql_close();
- }
-
- exit_handler();
- }
-
- /**
- * Output an error message for a database related problem
- * If skip is true, return and continue execution, else exit
- */
- function db_error($error, $sql, $line, $file, $skip = false)
- {
- global $lang, $db, $template;
-
- if ($skip)
- {
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['INST_ERR_FATAL'],
- ));
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => basename($file) . ' [ ' . $line . ' ]',
- 'RESULT' => '<b style="color:red">' . $error . '</b><br />&#187; SQL:' . $sql,
- ));
-
- return;
- }
-
- $template->set_filenames(array(
- 'body' => 'install_error.html')
- );
- $this->page_header();
- $this->generate_navigation();
-
- $template->assign_vars(array(
- 'MESSAGE_TITLE' => $lang['INST_ERR_FATAL_DB'],
- 'MESSAGE_TEXT' => '<p>' . basename($file) . ' [ ' . $line . ' ]</p><p>SQL : ' . $sql . '</p><p><b>' . $error . '</b></p>',
- ));
-
- // Rollback if in transaction
- if ($db->get_transaction())
- {
- $db->sql_transaction('rollback');
- }
-
- $this->page_footer();
- }
-
- /**
- * Generate the relevant HTML for an input field and the associated label and explanatory text
- */
- function input_field($name, $type, $value = '', $options = '')
- {
- global $lang;
- $tpl_type = explode(':', $type);
- $tpl = '';
-
- switch ($tpl_type[0])
- {
- case 'text':
- case 'password':
- // HTML5 text-like input types
- case 'color':
- case 'date':
- case 'time':
- case 'datetime':
- case 'datetime-local':
- case 'email':
- case 'month':
- case 'number':
- case 'range':
- case 'search':
- case 'tel':
- case 'url':
- case 'week':
-
- $size = (int) $tpl_type[1];
- $maxlength = (int) $tpl_type[2];
- $autocomplete = (isset($options['autocomplete']) && $options['autocomplete'] == 'off') ? ' autocomplete="off"' : '';
-
- $tpl = '<input id="' . $name . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '"' . $autocomplete . ' value="' . $value . '" />';
- break;
-
- case 'textarea':
- $rows = (int) $tpl_type[1];
- $cols = (int) $tpl_type[2];
-
- $tpl = '<textarea id="' . $name . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $value . '</textarea>';
- break;
-
- case 'radio':
- $key_yes = ($value) ? ' checked="checked" id="' . $name . '"' : '';
- $key_no = (!$value) ? ' checked="checked" id="' . $name . '"' : '';
-
- $tpl_type_cond = explode('_', $tpl_type[1]);
- $type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true;
-
- $tpl_no = '<label><input type="radio" name="' . $name . '" value="0"' . $key_no . ' class="radio" /> ' . (($type_no) ? $lang['NO'] : $lang['DISABLED']) . '</label>';
- $tpl_yes = '<label><input type="radio" name="' . $name . '" value="1"' . $key_yes . ' class="radio" /> ' . (($type_no) ? $lang['YES'] : $lang['ENABLED']) . '</label>';
-
- $tpl = ($tpl_type_cond[0] == 'yes' || $tpl_type_cond[0] == 'enabled') ? $tpl_yes . '&nbsp;&nbsp;' . $tpl_no : $tpl_no . '&nbsp;&nbsp;' . $tpl_yes;
- break;
-
- case 'select':
- // @codingStandardsIgnoreStart
- eval('$s_options = ' . str_replace('{VALUE}', $value, $options) . ';');
- // @codingStandardsIgnoreEnd
- $tpl = '<select id="' . $name . '" name="' . $name . '">' . $s_options . '</select>';
- break;
-
- case 'custom':
- // @codingStandardsIgnoreStart
- eval('$tpl = ' . str_replace('{VALUE}', $value, $options) . ';');
- // @codingStandardsIgnoreEnd
- break;
-
- default:
- break;
- }
-
- return $tpl;
- }
-
- /**
- * Generate the drop down of available language packs
- */
- function inst_language_select($default = '')
- {
- global $phpbb_root_path, $phpEx;
-
- $dir = @opendir($phpbb_root_path . 'language');
-
- if (!$dir)
- {
- $this->error('Unable to access the language directory', __LINE__, __FILE__);
- }
-
- while ($file = readdir($dir))
- {
- $path = $phpbb_root_path . 'language/' . $file;
-
- if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS')
- {
- continue;
- }
-
- if (file_exists($path . '/iso.txt'))
- {
- list($displayname, $localname) = @file($path . '/iso.txt');
- $lang[$localname] = $file;
- }
- }
- closedir($dir);
-
- @asort($lang);
- @reset($lang);
-
- $user_select = '';
- foreach ($lang as $displayname => $filename)
- {
- $selected = (strtolower($default) == strtolower($filename)) ? ' selected="selected"' : '';
- $user_select .= '<option value="' . $filename . '"' . $selected . '>' . ucwords($displayname) . '</option>';
- }
-
- return $user_select;
- }
-}
diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php
deleted file mode 100644
index 10b05eb559..0000000000
--- a/phpBB/install/install_convert.php
+++ /dev/null
@@ -1,2150 +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.
-*
-*/
-
-/**
-*/
-
-if (!defined('IN_INSTALL'))
-{
- // Someone has tried to access the file direct. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- $module[] = array(
- 'module_type' => 'install',
- 'module_title' => 'CONVERT',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 20,
- 'module_subs' => '',
- 'module_stages' => array('INTRO', 'SETTINGS', 'IN_PROGRESS', 'FINAL'),
- 'module_reqs' => ''
- );
-}
-
-/**
-* Class holding all convertor-specific details.
-*/
-class convert
-{
- var $options = array();
-
- var $convertor_tag = '';
- var $src_dbms = '';
- var $src_dbhost = '';
- var $src_dbport = '';
- var $src_dbuser = '';
- var $src_dbpasswd = '';
- var $src_dbname = '';
- var $src_table_prefix = '';
-
- var $convertor_data = array();
- var $tables = array();
- var $config_schema = array();
- var $convertor = array();
- var $src_truncate_statement = 'DELETE FROM ';
- var $truncate_statement = 'DELETE FROM ';
-
- var $fulltext_search;
-
- // Batch size, can be adjusted by the conversion file
- // For big boards a value of 6000 seems to be optimal
- var $batch_size = 2000;
- // Number of rows to be inserted at once (extended insert) if supported
- // For installations having enough memory a value of 60 may be good.
- var $num_wait_rows = 20;
-
- // Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor.
- var $mysql_convert = false;
-
- var $p_master;
-
- function convert(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-}
-
-/**
-* Convert class for conversions
-*/
-class install_convert extends module
-{
- /** @var array */
- protected $lang;
-
- /** @var string */
- protected $language;
-
- /** @var \phpbb\template\template */
- protected $template;
-
- /** @var string */
- protected $phpbb_root_path;
-
- /** @var string */
- protected $php_ext;
-
- /**
- * Variables used while converting, they are accessible from the global variable $convert
- */
- function install_convert(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $lang, $template, $phpbb_root_path, $phpEx, $cache, $config, $language, $table_prefix;
- global $convert, $request, $phpbb_container, $phpbb_config_php_file;
-
- $this->tpl_name = 'install_convert';
- $this->mode = $mode;
- $this->lang = $lang;
- $this->language = $language;
- $this->template = $template;
- $this->phpbb_root_path = $phpbb_root_path;
- $this->php_ext = $phpEx;
-
- if (!$this->check_phpbb_installed())
- {
- return;
- }
-
- $convert = new convert($this->p_master);
-
- // Enable super globals to prevent issues with the new \phpbb\request\request object
- $request->enable_super_globals();
- // Create a normal container now
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
- $phpbb_container = $phpbb_container_builder->get_container();
-
- // Create cache
- $cache = $phpbb_container->get('cache');
-
- switch ($sub)
- {
- case 'intro':
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- // Detect if there is already a conversion in progress at this point and offer to resume
- // It's quite possible that the user will get disconnected during a large conversion so they need to be able to resume it
- $new_conversion = request_var('new_conv', 0);
-
- if ($new_conversion)
- {
- $config['convert_progress'] = '';
- $config['convert_db_server'] = '';
- $config['convert_db_user'] = '';
- $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
- WHERE config_name = 'convert_progress'
- OR config_name = 'convert_db_server'
- OR config_name = 'convert_db_user'"
- );
- }
-
- // Let's see if there is a conversion in the works...
- $options = array();
- if (!empty($config['convert_progress']) && !empty($config['convert_db_server']) && !empty($config['convert_db_user']) && !empty($config['convert_options']))
- {
- $options = unserialize($config['convert_progress']);
- $options = array_merge($options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
- }
-
- // This information should have already been checked once, but do it again for safety
- if (!empty($options) && !empty($options['tag']) &&
- isset($options['dbms']) &&
- isset($options['dbhost']) &&
- isset($options['dbport']) &&
- isset($options['dbuser']) &&
- isset($options['dbpasswd']) &&
- isset($options['dbname']) &&
- isset($options['table_prefix']))
- {
- $this->page_title = $lang['CONTINUE_CONVERT'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['CONTINUE_CONVERT'],
- 'BODY' => $lang['CONTINUE_CONVERT_BODY'],
- 'L_NEW' => $lang['CONVERT_NEW_CONVERSION'],
- 'L_CONTINUE' => $lang['CONTINUE_OLD_CONVERSION'],
- 'S_CONTINUE' => true,
-
- 'U_NEW_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=intro&amp;new_conv=1&amp;language=$language",
- 'U_CONTINUE_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$options['tag']}{$options['step']}&amp;language=$language",
- ));
-
- return;
- }
-
- $this->list_convertors($sub);
-
- break;
-
- case 'settings':
- $this->get_convert_settings($sub);
- break;
-
- case 'in_progress':
- $this->convert_data($sub);
- break;
-
- case 'final':
- $this->page_title = $lang['CONVERT_COMPLETE'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['CONVERT_COMPLETE'],
- 'BODY' => $lang['CONVERT_COMPLETE_EXPLAIN'],
- ));
-
- // If we reached this step (conversion completed) we want to purge the cache and log the user out.
- // This is for making sure the session get not screwed due to the 3.0.x users table being completely new.
- $cache->purge();
-
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- $sql = 'SELECT config_value
- FROM ' . CONFIG_TABLE . '
- WHERE config_name = \'search_type\'';
- $result = $db->sql_query($sql);
-
- if ($db->sql_fetchfield('config_value') != 'fulltext_mysql')
- {
- $template->assign_vars(array(
- 'S_ERROR_BOX' => true,
- 'ERROR_TITLE' => $lang['SEARCH_INDEX_UNCONVERTED'],
- 'ERROR_MSG' => $lang['SEARCH_INDEX_UNCONVERTED_EXPLAIN'],
- ));
- }
-
- switch ($db->get_sql_layer())
- {
- case 'sqlite':
- case 'sqlite3':
- $db->sql_query('DELETE FROM ' . SESSIONS_KEYS_TABLE);
- $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
- break;
-
- default:
- $db->sql_query('TRUNCATE TABLE ' . SESSIONS_KEYS_TABLE);
- $db->sql_query('TRUNCATE TABLE ' . SESSIONS_TABLE);
- break;
- }
-
- break;
- }
- }
-
- /**
- * Check whether phpBB is installed.
- * Assigns error template vars if not installed.
- *
- * @return bool Returns true if phpBB is installed.
- */
- public function check_phpbb_installed()
- {
- if (phpbb_check_installation_exists($this->phpbb_root_path, $this->php_ext))
- {
- return true;
- }
-
- $this->page_title = 'BOARD_NOT_INSTALLED';
- $install_url = append_sid($this->phpbb_root_path . 'install/index.' . $this->php_ext, 'mode=install&amp;language=' . $this->language);
-
- $this->template->assign_vars(array(
- 'S_NOT_INSTALLED' => true,
- 'BODY' => sprintf($this->lang['BOARD_NOT_INSTALLED_EXPLAIN'], $install_url),
- ));
-
- return false;
- }
-
- /**
- * Generate a list of all available conversion modules
- */
- function list_convertors($sub)
- {
- global $lang, $language, $template, $phpbb_root_path, $phpEx;
-
- $this->page_title = $lang['SUB_INTRO'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['CONVERT_INTRO'],
- 'BODY' => $lang['CONVERT_INTRO_BODY'],
-
- 'L_AUTHOR' => $lang['AUTHOR'],
- 'L_AVAILABLE_CONVERTORS' => $lang['AVAILABLE_CONVERTORS'],
- 'L_CONVERT' => $lang['CONVERT'],
- 'L_NO_CONVERTORS' => $lang['NO_CONVERTORS'],
- 'L_OPTIONS' => $lang['CONVERT_OPTIONS'],
- 'L_SOFTWARE' => $lang['SOFTWARE'],
- 'L_VERSION' => $lang['VERSION'],
-
- 'S_LIST' => true,
- ));
-
- $convertors = $sort = array();
- $get_info = true;
-
- $handle = @opendir('./convertors/');
-
- if (!$handle)
- {
- $this->error('Unable to access the convertors directory', __LINE__, __FILE__);
- }
-
- while ($entry = readdir($handle))
- {
- if (preg_match('/^convert_([a-z0-9_]+).' . $phpEx . '$/i', $entry, $m))
- {
- include('./convertors/' . $entry);
- if (isset($convertor_data))
- {
- $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors);
-
- $convertors[] = array(
- 'tag' => $m[1],
- 'forum_name' => $convertor_data['forum_name'],
- 'version' => $convertor_data['version'],
- 'dbms' => $convertor_data['dbms'],
- 'dbhost' => $convertor_data['dbhost'],
- 'dbport' => $convertor_data['dbport'],
- 'dbuser' => $convertor_data['dbuser'],
- 'dbpasswd' => $convertor_data['dbpasswd'],
- 'dbname' => $convertor_data['dbname'],
- 'table_prefix' => $convertor_data['table_prefix'],
- 'author' => $convertor_data['author']
- );
- }
- unset($convertor_data);
- }
- }
- closedir($handle);
-
- @ksort($sort);
-
- foreach ($sort as $void => $index)
- {
- $template->assign_block_vars('convertors', array(
- 'AUTHOR' => $convertors[$index]['author'],
- 'SOFTWARE' => $convertors[$index]['forum_name'],
- 'VERSION' => $convertors[$index]['version'],
-
- 'U_CONVERT' => $this->p_master->module_url . "?mode={$this->mode}&amp;language=$language&amp;sub=settings&amp;tag=" . $convertors[$index]['tag'],
- ));
- }
- }
-
- /**
- */
- function get_convert_settings($sub)
- {
- global $lang, $language, $template, $db, $phpbb_root_path, $phpEx, $config, $cache, $phpbb_config_php_file;
-
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- $this->page_title = $lang['STAGE_SETTINGS'];
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- $convertor_tag = request_var('tag', '');
-
- if (empty($convertor_tag))
- {
- $this->p_master->error($lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
- }
- $get_info = true;
-
- // check security implications of direct inclusion
- $convertor_tag = basename($convertor_tag);
- if (!file_exists('./convertors/convert_' . $convertor_tag . '.' . $phpEx))
- {
- $this->p_master->error($lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
- }
-
- include('./convertors/convert_' . $convertor_tag . '.' . $phpEx);
-
- // The test_file is a file that should be present in the location of the old board.
- if (!isset($test_file))
- {
- $this->p_master->error($lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
- }
-
- $submit = (isset($_POST['submit'])) ? true : false;
-
- $src_dbms = request_var('src_dbms', $convertor_data['dbms']);
- $src_dbhost = request_var('src_dbhost', $convertor_data['dbhost']);
- $src_dbport = request_var('src_dbport', $convertor_data['dbport']);
- $src_dbuser = request_var('src_dbuser', $convertor_data['dbuser']);
- $src_dbpasswd = request_var('src_dbpasswd', $convertor_data['dbpasswd']);
- $src_dbname = request_var('src_dbname', $convertor_data['dbname']);
- $src_table_prefix = request_var('src_table_prefix', $convertor_data['table_prefix']);
- $forum_path = request_var('forum_path', $convertor_data['forum_path']);
- $refresh = request_var('refresh', 1);
-
- // Default URL of the old board
- // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it?
- // -> We should convert old urls to the new relative urls format
- // $src_url = request_var('src_url', 'Not in use at the moment');
-
- // strip trailing slash from old forum path
- $forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path, 0, -1) : $forum_path;
-
- $error = array();
- if ($submit)
- {
- if (!@file_exists('./../' . $forum_path . '/' . $test_file))
- {
- $error[] = sprintf($lang['COULD_NOT_FIND_PATH'], $forum_path);
- }
-
- $connect_test = false;
- $available_dbms = get_available_dbms(false, true, true);
-
- if (!isset($available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE'])
- {
- $error[] = $lang['INST_ERR_NO_DB'];
- $connect_test = false;
- }
- else
- {
- $connect_test = connect_check_db(true, $error, $available_dbms[$src_dbms], $src_table_prefix, $src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, true, ($src_dbms == $dbms) ? false : true, false);
- }
-
- // The forum prefix of the old and the new forum can only be the same if two different databases are used.
- if ($src_table_prefix == $table_prefix && $src_dbms == $dbms && $src_dbhost == $dbhost && $src_dbport == $dbport && $src_dbname == $dbname)
- {
- $error[] = sprintf($lang['TABLE_PREFIX_SAME'], $src_table_prefix);
- }
-
- $src_dbms = $phpbb_config_php_file->convert_30_dbms_to_31($src_dbms);
-
- // Check table prefix
- if (!sizeof($error))
- {
- // initiate database connection to old db if old and new db differ
- global $src_db, $same_db;
- $src_db = $same_db = false;
-
- if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser)
- {
- $src_db = new $src_dbms();
- $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true);
- $same_db = false;
- }
- else
- {
- $src_db = $db;
- $same_db = true;
- }
-
- $src_db->sql_return_on_error(true);
- $db->sql_return_on_error(true);
-
- // Try to select one row from the first table to see if the prefix is OK
- $result = $src_db->sql_query_limit('SELECT * FROM ' . $src_table_prefix . $tables[0], 1);
-
- if (!$result)
- {
- $prefixes = array();
-
- $tables_existing = get_tables($src_db);
- $tables_existing = array_map('strtolower', $tables_existing);
- foreach ($tables_existing as $table_name)
- {
- compare_table($tables, $table_name, $prefixes);
- }
- unset($tables_existing);
-
- foreach ($prefixes as $prefix => $count)
- {
- if ($count >= sizeof($tables))
- {
- $possible_prefix = $prefix;
- break;
- }
- }
-
- $msg = '';
- if (!empty($convertor_data['table_prefix']))
- {
- $msg .= sprintf($lang['DEFAULT_PREFIX_IS'], $convertor_data['forum_name'], $convertor_data['table_prefix']);
- }
-
- if (!empty($possible_prefix))
- {
- $msg .= '<br />';
- $msg .= ($possible_prefix == '*') ? $lang['BLANK_PREFIX_FOUND'] : sprintf($lang['PREFIX_FOUND'], $possible_prefix);
- $src_table_prefix = ($possible_prefix == '*') ? '' : $possible_prefix;
- }
-
- $error[] = $msg;
- }
- $src_db->sql_freeresult($result);
- $src_db->sql_return_on_error(false);
- }
-
- if (!sizeof($error))
- {
- // Save convertor Status
- set_config('convert_progress', serialize(array(
- 'step' => '',
- 'table_prefix' => $src_table_prefix,
- 'tag' => $convertor_tag,
- )), true);
- set_config('convert_db_server', serialize(array(
- 'dbms' => $src_dbms,
- 'dbhost' => $src_dbhost,
- 'dbport' => $src_dbport,
- 'dbname' => $src_dbname,
- )), true);
- set_config('convert_db_user', serialize(array(
- 'dbuser' => $src_dbuser,
- 'dbpasswd' => $src_dbpasswd,
- )), true);
-
- // Save options
- set_config('convert_options', serialize(array('forum_path' => './../' . $forum_path, 'refresh' => $refresh)), true);
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['VERIFY_OPTIONS'],
- 'RESULT' => $lang['CONVERT_SETTINGS_VERIFIED'],
- ));
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $lang['BEGIN_CONVERT'],
-// 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag=$convertor_tag&amp;language=$language",
- ));
-
- return;
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['VERIFY_OPTIONS'],
- 'RESULT' => '<b style="color:red">' . implode('<br />', $error) . '</b>',
- ));
- }
- } // end submit
-
- foreach ($this->convert_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], ${$config_key}, $options),
- )
- );
- }
-
- $template->assign_vars(array(
- 'TITLE' => $lang['STAGE_SETTINGS'],
- 'BODY' => $lang['CONV_OPTIONS_BODY'],
- 'L_SUBMIT' => $lang['BEGIN_CONVERT'],
- 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=settings&amp;tag=$convertor_tag&amp;language=$language",
- ));
- }
-
- /**
- * The function which does the actual work (or dispatches it to the relevant places)
- */
- function convert_data($sub)
- {
- global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth;
- global $convert, $convert_row, $message_parser, $skip_rows, $language;
- global $request, $phpbb_config_php_file, $phpbb_dispatcher;
-
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- // Override a couple of config variables for the duration
- $config['max_quote_depth'] = 0;
-
- // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
- $config['max_post_chars'] = $config['min_post_chars'] = 0;
-
- // Set up a user as well. We _should_ have enough of a database here at this point to do this
- // and it helps for any core code we call
- $user->session_begin();
- $user->page = $user->extract_current_page($phpbb_root_path);
-
- // This is a little bit of a fudge, but it allows the language entries to be available to the
- // core code without us loading them again
- $user->lang = &$lang;
-
- $this->page_title = $user->lang['STAGE_IN_PROGRESS'];
-
- $convert->options = array();
- if (isset($config['convert_progress']))
- {
- $convert->options = unserialize($config['convert_progress']);
- $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
- }
-
- // This information should have already been checked once, but do it again for safety
- if (empty($convert->options) || empty($convert->options['tag']) ||
- !isset($convert->options['dbms']) ||
- !isset($convert->options['dbhost']) ||
- !isset($convert->options['dbport']) ||
- !isset($convert->options['dbuser']) ||
- !isset($convert->options['dbpasswd']) ||
- !isset($convert->options['dbname']) ||
- !isset($convert->options['table_prefix']))
- {
- $this->p_master->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
- }
-
- // Make some short variables accessible, for easier referencing
- $convert->convertor_tag = basename($convert->options['tag']);
- $convert->src_dbms = $convert->options['dbms'];
- $convert->src_dbhost = $convert->options['dbhost'];
- $convert->src_dbport = $convert->options['dbport'];
- $convert->src_dbuser = $convert->options['dbuser'];
- $convert->src_dbpasswd = $convert->options['dbpasswd'];
- $convert->src_dbname = $convert->options['dbname'];
- $convert->src_table_prefix = $convert->options['table_prefix'];
-
- // initiate database connection to old db if old and new db differ
- global $src_db, $same_db;
- $src_db = $same_db = null;
- if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser)
- {
- $dbms = $convert->src_dbms;
- $src_db = new $dbms();
- $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true);
- $same_db = false;
- }
- else
- {
- $src_db = $db;
- $same_db = true;
- }
-
- $convert->mysql_convert = false;
- switch ($src_db->sql_layer)
- {
- case 'sqlite':
- case 'sqlite3':
- $convert->src_truncate_statement = 'DELETE FROM ';
- break;
-
- // Thanks MySQL, for silently converting...
- case 'mysql':
- case 'mysql4':
- if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>='))
- {
- $convert->mysql_convert = true;
- }
- $convert->src_truncate_statement = 'TRUNCATE TABLE ';
- break;
-
- case 'mysqli':
- $convert->mysql_convert = true;
- $convert->src_truncate_statement = 'TRUNCATE TABLE ';
- break;
-
- default:
- $convert->src_truncate_statement = 'TRUNCATE TABLE ';
- break;
- }
-
- if ($convert->mysql_convert && !$same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- switch ($db->get_sql_layer())
- {
- case 'sqlite':
- case 'sqlite3':
- $convert->truncate_statement = 'DELETE FROM ';
- break;
-
- default:
- $convert->truncate_statement = 'TRUNCATE TABLE ';
- break;
- }
-
- $get_info = false;
-
- // check security implications of direct inclusion
- if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx))
- {
- $this->p_master->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
- }
-
- if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx))
- {
- include('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx);
- }
-
- $get_info = true;
- include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
-
- // Map some variables...
- $convert->convertor_data = $convertor_data;
- $convert->tables = $tables;
- $convert->config_schema = $config_schema;
-
- // Now include the real data
- $get_info = false;
- include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
-
- $convert->convertor_data = $convertor_data;
- $convert->tables = $tables;
- $convert->config_schema = $config_schema;
- $convert->convertor = $convertor;
-
- // The test_file is a file that should be present in the location of the old board.
- if (!file_exists($convert->options['forum_path'] . '/' . $test_file))
- {
- $this->p_master->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__);
- }
-
- $search_type = $config['search_type'];
-
- // For conversions we are a bit less strict and set to a search backend we know exist...
- if (!class_exists($search_type))
- {
- $search_type = '\phpbb\search\fulltext_native';
- set_config('search_type', $search_type);
- }
-
- if (!class_exists($search_type))
- {
- trigger_error('NO_SUCH_SEARCH_MODULE');
- }
-
- $error = false;
- $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
-
- if ($error)
- {
- trigger_error($error);
- }
-
- include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
- $message_parser = new parse_message();
-
- $jump = request_var('jump', 0);
- $final_jump = request_var('final_jump', 0);
- $sync_batch = request_var('sync_batch', -1);
- $last_statement = request_var('last', 0);
-
- // We are running sync...
- if ($sync_batch >= 0)
- {
- $this->sync_forums($sync_batch);
- return;
- }
-
- if ($jump)
- {
- $this->jump($jump, $last_statement);
- return;
- }
-
- if ($final_jump)
- {
- $this->final_jump($final_jump);
- return;
- }
-
- $current_table = request_var('current_table', 0);
- $old_current_table = min(-1, $current_table - 1);
- $skip_rows = request_var('skip_rows', 0);
-
- if (!$current_table && !$skip_rows)
- {
- if (!$request->variable('confirm', false))
- {
- // If avatars / ranks / smilies folders are specified make sure they are writable
- $bad_folders = array();
-
- $local_paths = array(
- 'avatar_path' => path($config['avatar_path']),
- 'avatar_gallery_path' => path($config['avatar_gallery_path']),
- 'icons_path' => path($config['icons_path']),
- 'ranks_path' => path($config['ranks_path']),
- 'smilies_path' => path($config['smilies_path'])
- );
-
- foreach ($local_paths as $folder => $local_path)
- {
- if (isset($convert->convertor[$folder]))
- {
- if (empty($convert->convertor['test_file']))
- {
- // test_file is mandantory at the moment so this should never be reached, but just in case...
- $this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
- }
-
- if (!$local_path || !phpbb_is_writable($phpbb_root_path . $local_path))
- {
- if (!$local_path)
- {
- $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder);
- }
- else
- {
- $bad_folders[] = $local_path;
- }
- }
- }
- }
-
- if (sizeof($bad_folders))
- {
- $msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
- sort($bad_folders);
- $this->p_master->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true);
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['INSTALL_TEST'],
- 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}&amp;language=$language",
- ));
- return;
- }
-
- // Grab all the tables used in convertor
- $missing_tables = $tables_list = $aliases = array();
-
- foreach ($convert->convertor['schema'] as $schema)
- {
- // Skip those not used (because of addons/plugins not detected)
- if (!$schema['target'])
- {
- continue;
- }
-
- foreach ($schema as $key => $val)
- {
- // we're dealing with an array like:
- // array('forum_status', 'forums.forum_status', 'is_item_locked')
- if (is_int($key) && !empty($val[1]))
- {
- $temp_data = $val[1];
- if (!is_array($temp_data))
- {
- $temp_data = array($temp_data);
- }
-
- foreach ($temp_data as $val)
- {
- if (preg_match('/([a-z0-9_]+)\.([a-z0-9_]+)\)* ?A?S? ?([a-z0-9_]*?)\.?([a-z0-9_]*)$/i', $val, $m))
- {
- $table = $convert->src_table_prefix . $m[1];
- $tables_list[$table] = $table;
-
- if (!empty($m[3]))
- {
- $aliases[] = $convert->src_table_prefix . $m[3];
- }
- }
- }
- }
- // 'left_join' => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1'
- else if ($key == 'left_join')
- {
- // Convert the value if it wasn't an array already.
- if (!is_array($val))
- {
- $val = array($val);
- }
-
- for ($j = 0, $size = sizeof($val); $j < $size; ++$j)
- {
- if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m))
- {
- $table = $convert->src_table_prefix . $m[1];
- $tables_list[$table] = $table;
-
- if (!empty($m[2]))
- {
- $aliases[] = $convert->src_table_prefix . $m[2];
- }
- }
- }
- }
- }
- }
-
- // Remove aliased tables from $tables_list
- foreach ($aliases as $alias)
- {
- unset($tables_list[$alias]);
- }
-
- // Check if the tables that we need exist
- $src_db->sql_return_on_error(true);
- foreach ($tables_list as $table => $null)
- {
- $sql = 'SELECT 1 FROM ' . $table;
- $_result = $src_db->sql_query_limit($sql, 1);
-
- if (!$_result)
- {
- $missing_tables[] = $table;
- }
- $src_db->sql_freeresult($_result);
- }
- $src_db->sql_return_on_error(false);
-
- // 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))
- {
- $this->p_master->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
- }
- else if (sizeof($missing_tables))
- {
- $this->p_master->error(sprintf($user->lang['TABLES_MISSING'], implode($user->lang['COMMA_SEPARATOR'], $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
- }
-
- $url = $this->save_convert_progress('&amp;confirm=1');
- $msg = $user->lang['PRE_CONVERT_COMPLETE'];
-
- if ($convert->convertor_data['author_notes'])
- {
- $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']);
- }
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'L_MESSAGE' => $msg,
- 'U_ACTION' => $url,
- ));
-
- return;
- } // if (!$request->variable('confirm', false)))
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['STARTING_CONVERT'],
- ));
-
- // Convert the config table and load the settings of the old board
- if (!empty($convert->config_schema))
- {
- restore_config($convert->config_schema);
-
- // Override a couple of config variables for the duration
- $config['max_quote_depth'] = 0;
-
- // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
- $config['max_post_chars'] = $config['min_post_chars'] = 0;
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['CONFIG_CONVERT'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- // Now process queries and execute functions that have to be executed prior to the conversion
- if (!empty($convert->convertor['execute_first']))
- {
- // @codingStandardsIgnoreStart
- eval($convert->convertor['execute_first']);
- // @codingStandardsIgnoreEnd
- }
-
- if (!empty($convert->convertor['query_first']))
- {
- if (!is_array($convert->convertor['query_first']))
- {
- $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first']));
- }
- else if (!is_array($convert->convertor['query_first'][0]))
- {
- $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1]));
- }
-
- foreach ($convert->convertor['query_first'] as $query_first)
- {
- if ($query_first[0] == 'src')
- {
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- $src_db->sql_query($query_first[1]);
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
- }
- else
- {
- $db->sql_query($query_first[1]);
- }
- }
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['PREPROCESS_STEP'],
- 'RESULT' => $user->lang['DONE'],
- ));
- } // if (!$current_table && !$skip_rows)
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['FILLING_TABLES'],
- ));
-
- // This loop takes one target table and processes it
- while ($current_table < sizeof($convert->convertor['schema']))
- {
- $schema = $convert->convertor['schema'][$current_table];
-
- // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this.
- if (empty($schema['target']))
- {
- $current_table++;
- continue;
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => sprintf($user->lang['FILLING_TABLE'], $schema['target']),
- ));
-
- // This is only the case when we first start working on the tables.
- if (!$skip_rows)
- {
- // process execute_first and query_first for this table...
- if (!empty($schema['execute_first']))
- {
- // @codingStandardsIgnoreStart
- eval($schema['execute_first']);
- // @codingStandardsIgnoreEnd
- }
-
- if (!empty($schema['query_first']))
- {
- if (!is_array($schema['query_first']))
- {
- $schema['query_first'] = array('target', array($schema['query_first']));
- }
- else if (!is_array($schema['query_first'][0]))
- {
- $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1]));
- }
-
- foreach ($schema['query_first'] as $query_first)
- {
- if ($query_first[0] == 'src')
- {
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
- $src_db->sql_query($query_first[1]);
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
- }
- else
- {
- $db->sql_query($query_first[1]);
- }
- }
- }
-
- if (!empty($schema['autoincrement']))
- {
- switch ($db->get_sql_layer())
- {
- case 'postgres':
- $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
- break;
-
- case 'oracle':
- $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $largest_id = (int) $row['max_id'];
-
- if ($largest_id)
- {
- $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
- $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
- }
- break;
- }
- }
- }
-
- // Process execute_always for this table
- // This is for code which needs to be executed on every pass of this table if
- // it gets split because of time restrictions
- if (!empty($schema['execute_always']))
- {
- // @codingStandardsIgnoreStart
- eval($schema['execute_always']);
- // @codingStandardsIgnoreEnd
- }
-
- //
- // Set up some variables
- //
- // $waiting_rows holds rows for multirows insertion (MySQL only)
- // $src_tables holds unique tables with aliases to select from
- // $src_fields will quickly refer source fields (or aliases) corresponding to the current index
- // $select_fields holds the names of the fields to retrieve
- //
-
- $sql_data = array(
- 'source_fields' => array(),
- 'target_fields' => array(),
- 'source_tables' => array(),
- 'select_fields' => array(),
- );
-
- // This statement is building the keys for later insertion.
- $insert_query = $this->build_insert_query($schema, $sql_data, $current_table);
-
- // If no source table is affected, we skip the table
- if (empty($sql_data['source_tables']))
- {
- $skip_rows = 0;
- $current_table++;
- continue;
- }
-
- $distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' : '';
-
- $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']);
-
- // Where
- $sql .= (!empty($schema['where'])) ? "\nWHERE (" . $schema['where'] . ')' : '';
-
- // Group By
- if (!empty($schema['group_by']))
- {
- $schema['group_by'] = array($schema['group_by']);
- foreach ($sql_data['select_fields'] as $select)
- {
- $alias = strpos(strtolower($select), ' as ');
- $select = ($alias) ? substr($select, 0, $alias) : $select;
- if (!in_array($select, $schema['group_by']))
- {
- $schema['group_by'][] = $select;
- }
- }
- }
- $sql .= (!empty($schema['group_by'])) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : '';
-
- // Having
- $sql .= (!empty($schema['having'])) ? "\nHAVING " . $schema['having'] : '';
-
- // Order By
- if (empty($schema['order_by']) && !empty($schema['primary']))
- {
- $schema['order_by'] = $schema['primary'];
- }
- $sql .= (!empty($schema['order_by'])) ? "\nORDER BY " . $schema['order_by'] : '';
-
- // Counting basically holds the amount of rows processed.
- $counting = -1;
- $batch_time = 0;
-
- while ($counting === -1 || ($counting >= $convert->batch_size && still_on_time()))
- {
- $old_current_table = $current_table;
-
- $rows = '';
- $waiting_rows = array();
-
- if (!empty($batch_time))
- {
- $mtime = explode(' ', microtime());
- $mtime = $mtime[0] + $mtime[1];
- $rows = ceil($counting/($mtime - $batch_time)) . " rows/s ($counting rows) | ";
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => "skip_rows = $skip_rows",
- 'RESULT' => $rows . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] : ''),
- ));
-
- $mtime = explode(' ', microtime());
- $batch_time = $mtime[0] + $mtime[1];
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- // Take skip rows into account and only fetch batch_size amount of rows
- $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows);
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
-
- // This loop processes each row
- $counting = 0;
-
- $convert->row = $convert_row = array();
-
- if (!empty($schema['autoincrement']))
- {
- switch ($db->get_sql_layer())
- {
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON');
- break;
- }
- }
-
- // Now handle the rows until time is over or no more rows to process...
- while ($counting === 0 || still_on_time())
- {
- $convert_row = $src_db->sql_fetchrow($___result);
-
- if (!$convert_row)
- {
- // move to the next batch or table
- break;
- }
-
- // With this we are able to always save the last state
- $convert->row = $convert_row;
-
- // Increment the counting variable, it stores the number of rows we have processed
- $counting++;
-
- $insert_values = array();
-
- $sql_flag = $this->process_row($schema, $sql_data, $insert_values);
-
- if ($sql_flag === true)
- {
- switch ($db->get_sql_layer())
- {
- // If MySQL, we'll wait to have num_wait_rows rows to submit at once
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $waiting_rows[] = '(' . implode(', ', $insert_values) . ')';
-
- if (sizeof($waiting_rows) >= $convert->num_wait_rows)
- {
- $errored = false;
-
- $db->sql_return_on_error(true);
-
- if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
- {
- $errored = true;
- }
- $db->sql_return_on_error(false);
-
- if ($errored)
- {
- $db->sql_return_on_error(true);
-
- // Because it errored out we will try to insert the rows one by one... most of the time this
- // is caused by duplicate entries - but we also do not want to miss one...
- foreach ($waiting_rows as $waiting_sql)
- {
- if (!$db->sql_query($insert_query . $waiting_sql))
- {
- $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
- }
- }
-
- $db->sql_return_on_error(false);
- }
-
- $waiting_rows = array();
- }
-
- break;
-
- default:
- $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')';
-
- $db->sql_return_on_error(true);
-
- if (!$db->sql_query($insert_sql))
- {
- $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
- }
- $db->sql_return_on_error(false);
-
- $waiting_rows = array();
-
- break;
- }
- }
-
- $skip_rows++;
- }
- $src_db->sql_freeresult($___result);
-
- // We might still have some rows waiting
- if (sizeof($waiting_rows))
- {
- $errored = false;
- $db->sql_return_on_error(true);
-
- if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
- {
- $errored = true;
- }
- $db->sql_return_on_error(false);
-
- if ($errored)
- {
- $db->sql_return_on_error(true);
-
- // Because it errored out we will try to insert the rows one by one... most of the time this
- // is caused by duplicate entries - but we also do not want to miss one...
- foreach ($waiting_rows as $waiting_sql)
- {
- $db->sql_query($insert_query . $waiting_sql);
- $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
- }
-
- $db->sql_return_on_error(false);
- }
-
- $waiting_rows = array();
- }
-
- if (!empty($schema['autoincrement']))
- {
- switch ($db->get_sql_layer())
- {
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF');
- break;
-
- case 'postgres':
- $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
- break;
-
- case 'oracle':
- $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $largest_id = (int) $row['max_id'];
-
- if ($largest_id)
- {
- $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
- $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
- }
- break;
- }
- }
- }
-
- // When we reach this point, either the current table has been processed or we're running out of time.
- if (still_on_time() && $counting < $convert->batch_size/* && !defined('DEBUG')*/)
- {
- $skip_rows = 0;
- $current_table++;
- }
- else
- {/*
- if (still_on_time() && $counting < $convert->batch_size)
- {
- $skip_rows = 0;
- $current_table++;
- }*/
-
- // Looks like we ran out of time.
- $url = $this->save_convert_progress('&amp;current_table=' . $current_table . '&amp;skip_rows=' . $skip_rows);
-
- $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']));
-
- $template->assign_vars(array(
- 'L_MESSAGE' => $msg,
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- }
-
- // Process execute_last then we'll be done
- $url = $this->save_convert_progress('&amp;jump=1');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['FINAL_STEP'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- /**
- * Sync function being executed at the middle, some functions need to be executed after a successful sync.
- */
- function sync_forums($sync_batch)
- {
- global $template, $user, $db, $phpbb_root_path, $phpEx, $config, $cache;
- global $convert;
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['SYNC_TOPICS'],
- ));
-
- $batch_size = $convert->batch_size;
-
- $sql = 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value
- FROM ' . TOPICS_TABLE;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- // Set values of minimum/maximum primary value for this table.
- $primary_min = $row['min_value'];
- $primary_max = $row['max_value'];
-
- if ($sync_batch == 0)
- {
- $sync_batch = (int) $primary_min;
- }
-
- if ($sync_batch == 0)
- {
- $sync_batch = 1;
- }
-
- // Fetch a batch of rows, process and insert them.
- while ($sync_batch <= $primary_max && still_on_time())
- {
- $end = ($sync_batch + $batch_size - 1);
-
- // Sync all topics in batch mode...
- sync('topic', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true);
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''),
- 'RESULT' => $user->lang['DONE'],
- ));
-
- $sync_batch += $batch_size;
- }
-
- if ($sync_batch >= $primary_max)
- {
- $url = $this->save_convert_progress('&amp;final_jump=1');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- else
- {
- $sync_batch--;
- }
-
- $url = $this->save_convert_progress('&amp;sync_batch=' . $sync_batch);
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- /**
- * Save the convertor status
- */
- function save_convert_progress($step)
- {
- global $convert, $language;
-
- // Save convertor Status
- set_config('convert_progress', serialize(array(
- 'step' => $step,
- 'table_prefix' => $convert->src_table_prefix,
- 'tag' => $convert->convertor_tag,
- )), true);
-
- set_config('convert_db_server', serialize(array(
- 'dbms' => $convert->src_dbms,
- 'dbhost' => $convert->src_dbhost,
- 'dbport' => $convert->src_dbport,
- 'dbname' => $convert->src_dbname,
- )), true);
-
- set_config('convert_db_user', serialize(array(
- 'dbuser' => $convert->src_dbuser,
- 'dbpasswd' => $convert->src_dbpasswd,
- )), true);
-
- return $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}$step&amp;language=$language";
- }
-
- /**
- * Finish conversion, the last function to be called.
- */
- function finish_conversion()
- {
- global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user, $template;
- global $cache, $auth, $phpbb_container, $phpbb_log;
-
- $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
- WHERE config_name = 'convert_progress'
- OR config_name = 'convert_options'
- OR config_name = 'convert_db_server'
- OR config_name = 'convert_db_user'");
- $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
-
- @unlink($phpbb_root_path . 'cache/data_global.' . $phpEx);
- phpbb_cache_moderators($db, $cache, $auth);
-
- // And finally, add a note to the log
- $phpbb_log = $phpbb_container->get('log');
- add_log('admin', 'LOG_INSTALL_CONVERTED', $convert->convertor_data['forum_name'], $config['version']);
-
- $url = $this->p_master->module_url . "?mode={$this->mode}&amp;sub=final&amp;language=$language";
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['FINAL_STEP'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- /**
- * This function marks the steps after syncing
- */
- function final_jump($final_jump)
- {
- global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
- global $convert;
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['PROCESS_LAST'],
- ));
-
- if ($final_jump == 1)
- {
- $db->sql_return_on_error(true);
-
- update_topics_posted();
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['UPDATE_TOPICS_POSTED'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- if ($db->get_sql_error_triggered())
- {
- $template->assign_vars(array(
- 'S_ERROR_BOX' => true,
- 'ERROR_TITLE' => $user->lang['UPDATE_TOPICS_POSTED'],
- 'ERROR_MSG' => $user->lang['UPDATE_TOPICS_POSTED_ERR'],
- ));
- }
- $db->sql_return_on_error(false);
-
- $this->finish_conversion();
- return;
- }
- }
-
- /**
- * This function marks the steps before syncing (jump=1)
- */
- function jump($jump, $last_statement)
- {
- global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
- global $convert;
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['PROCESS_LAST'],
- ));
-
- if ($jump == 1)
- {
- // Execute 'last' statements/queries
- if (!empty($convert->convertor['execute_last']))
- {
- if (!is_array($convert->convertor['execute_last']))
- {
- // @codingStandardsIgnoreStart
- eval($convert->convertor['execute_last']);
- // @codingStandardsIgnoreEnd
- }
- else
- {
- while ($last_statement < sizeof($convert->convertor['execute_last']))
- {
- // @codingStandardsIgnoreStart
- eval($convert->convertor['execute_last'][$last_statement]);
- // @codingStandardsIgnoreEnd
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $convert->convertor['execute_last'][$last_statement],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- $last_statement++;
- $url = $this->save_convert_progress('&amp;jump=1&amp;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);
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_LAST'],
- 'L_MESSAGE' => $msg,
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- }
- }
-
- if (!empty($convert->convertor['query_last']))
- {
- if (!is_array($convert->convertor['query_last']))
- {
- $convert->convertor['query_last'] = array('target', array($convert->convertor['query_last']));
- }
- else if (!is_array($convert->convertor['query_last'][0]))
- {
- $convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1]));
- }
-
- foreach ($convert->convertor['query_last'] as $query_last)
- {
- if ($query_last[0] == 'src')
- {
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- $src_db->sql_query($query_last[1]);
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
- }
- else
- {
- $db->sql_query($query_last[1]);
- }
- }
- }
-
- // Sanity check
- $db->sql_return_on_error(false);
- $src_db->sql_return_on_error(false);
-
- fix_empty_primary_groups();
-
- $sql = 'SELECT MIN(user_regdate) AS board_startdate
- FROM ' . USERS_TABLE;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0))
- {
- set_config('board_startdate', $row['board_startdate']);
- $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS);
- }
-
- update_dynamic_config();
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['CLEAN_VERIFY'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- $url = $this->save_convert_progress('&amp;jump=2');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- if ($jump == 2)
- {
- $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_permissions = ''");
-
- // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics.
- // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing)
- sync('forum', '', '', false, true);
- $cache->destroy('sql', FORUMS_TABLE);
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['SYNC_FORUMS'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- // Continue with synchronizing the forums...
- $url = $this->save_convert_progress('&amp;sync_batch=0');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- }
-
- function build_insert_query(&$schema, &$sql_data, $current_table)
- {
- global $db, $user;
- global $convert;
-
- // Can we use IGNORE with this DBMS?
- $sql_ignore = (strpos($db->get_sql_layer(), 'mysql') === 0 && !defined('DEBUG')) ? 'IGNORE ' : '';
- $insert_query = 'INSERT ' . $sql_ignore . 'INTO ' . $schema['target'] . ' (';
-
- $aliases = array();
-
- $sql_data = array(
- 'source_fields' => array(),
- 'target_fields' => array(),
- 'source_tables' => array(),
- 'select_fields' => array(),
- );
-
- foreach ($schema as $key => $val)
- {
- // Example: array('group_name', 'extension_groups.group_name', 'htmlspecialchars'),
- if (is_int($key))
- {
- if (!empty($val[0]))
- {
- // Target fields
- $sql_data['target_fields'][$val[0]] = $key;
- $insert_query .= $val[0] . ', ';
- }
-
- if (!is_array($val[1]))
- {
- $val[1] = array($val[1]);
- }
-
- foreach ($val[1] as $valkey => $value_1)
- {
- // This should cover about any case:
- //
- // table.field => SELECT table.field FROM table
- // table.field AS alias => SELECT table.field AS alias FROM table
- // table.field AS table2.alias => SELECT table2.field AS alias FROM table table2
- // table.field AS table2.field => SELECT table2.field FROM table table2
- //
- if (preg_match('/^([a-z0-9_]+)\.([a-z0-9_]+)( +AS +(([a-z0-9_]+?)\.)?([a-z0-9_]+))?$/i', $value_1, $m))
- {
- // There is 'AS ...' in the field names
- if (!empty($m[3]))
- {
- $value_1 = ($m[2] == $m[6]) ? $m[1] . '.' . $m[2] : $m[1] . '.' . $m[2] . ' AS ' . $m[6];
-
- // Table alias: store it then replace the source table with it
- if (!empty($m[5]) && $m[5] != $m[1])
- {
- $aliases[$m[5]] = $m[1];
- $value_1 = str_replace($m[1] . '.' . $m[2], $m[5] . '.' . $m[2], $value_1);
- }
- }
- else
- {
- // No table alias
- $sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix . $m[1] . ' ' . $m[1];
- }
-
- $sql_data['select_fields'][$value_1] = $value_1;
- $sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2];
- }
- }
- }
- else if ($key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having')
- {
- if (@preg_match_all('/([a-z0-9_]+)\.([a-z0-9_]+)/i', $val, $m))
- {
- foreach ($m[1] as $value)
- {
- $sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value : $convert->src_table_prefix . $value . ' ' . $value;
- }
- }
- }
- }
-
- // Add the aliases to the list of tables
- foreach ($aliases as $alias => $table)
- {
- $sql_data['source_tables'][$alias] = $convert->src_table_prefix . $table . ' ' . $alias;
- }
-
- // 'left_join' => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id',
- if (!empty($schema['left_join']))
- {
- if (!is_array($schema['left_join']))
- {
- $schema['left_join'] = array($schema['left_join']);
- }
-
- foreach ($schema['left_join'] as $left_join)
- {
- // This won't handle concatened LEFT JOINs
- if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i', $left_join, $m))
- {
- $this->p_master->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN', $left_join, $current_table, $schema['target']), __LINE__, __FILE__);
- }
-
- if (!empty($aliases[$m[2]]))
- {
- if (!empty($m[3]))
- {
- $this->p_master->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE__, __FILE__);
- }
-
- $m[2] = $aliases[$m[2]];
- $m[3] = $m[2];
- }
-
- $right_table = $convert->src_table_prefix . $m[2];
- if (!empty($m[3]))
- {
- unset($sql_data['source_tables'][$m[3]]);
- }
- else if ($m[2] != $m[1])
- {
- unset($sql_data['source_tables'][$m[2]]);
- }
-
- if (strpos($sql_data['source_tables'][$m[1]], "\nLEFT JOIN") !== false)
- {
- $sql_data['source_tables'][$m[1]] = '(' . $sql_data['source_tables'][$m[1]] . ")\nLEFT JOIN $right_table";
- }
- else
- {
- $sql_data['source_tables'][$m[1]] .= "\nLEFT JOIN $right_table";
- }
-
- if (!empty($m[3]))
- {
- unset($sql_data['source_tables'][$m[3]]);
- $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[3];
- }
- else if (!empty($convert->src_table_prefix))
- {
- $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[2];
- }
- $sql_data['source_tables'][$m[1]] .= ' ' . $m[4] . $m[5];
- }
- }
-
- // Remove ", " from the end of the insert query
- $insert_query = substr($insert_query, 0, -2) . ') VALUES ';
-
- return $insert_query;
- }
-
- /**
- * Function for processing the currently handled row
- */
- function process_row(&$schema, &$sql_data, &$insert_values)
- {
- global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache;
- global $convert, $convert_row;
-
- $sql_flag = false;
-
- foreach ($schema as $key => $fields)
- {
- // We are only interested in the lines with:
- // array('comment', 'attachments_desc.comment', 'htmlspecialchars'),
- if (is_int($key))
- {
- if (!is_array($fields[1]))
- {
- $fields[1] = array($fields[1]);
- }
-
- $firstkey_set = false;
- $firstkey = 0;
-
- foreach ($fields[1] as $inner_key => $inner_value)
- {
- if (!$firstkey_set)
- {
- $firstkey = $inner_key;
- $firstkey_set = true;
- }
-
- $src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : '';
-
- if (!empty($src_field))
- {
- $fields[1][$inner_key] = $convert->row[$src_field];
- }
- }
-
- if (!empty($fields[0]))
- {
- // We have a target field, if we haven't set $sql_flag yet it will be set to TRUE.
- // If a function has already set it to FALSE it won't change it.
- if ($sql_flag === false)
- {
- $sql_flag = true;
- }
-
- // No function assigned?
- if (empty($fields[2]))
- {
- $value = $fields[1][$firstkey];
- }
- else if (is_array($fields[2]) && !is_callable($fields[2]))
- {
- // Execute complex function/eval/typecast
- $value = $fields[1];
-
- foreach ($fields[2] as $type => $execution)
- {
- if (strpos($type, 'typecast') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
- $value = $value[0];
- settype($value, $execution);
- }
- else if (strpos($type, 'function') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $value = call_user_func_array($execution, $value);
- }
- else if (strpos($type, 'execute') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $execution = str_replace('{RESULT}', '$value', $execution);
- $execution = str_replace('{VALUE}', '$value', $execution);
- // @codingStandardsIgnoreStart
- eval($execution);
- // @codingStandardsIgnoreEnd
- }
- }
- }
- else
- {
- $value = call_user_func_array($fields[2], $fields[1]);
- }
-
- if (is_null($value))
- {
- $value = '';
- }
-
- $insert_values[] = $db->_sql_validate_value($value);
- }
- else if (!empty($fields[2]))
- {
- if (is_array($fields[2]))
- {
- // Execute complex function/eval/typecast
- $value = '';
-
- foreach ($fields[2] as $type => $execution)
- {
- if (strpos($type, 'typecast') === 0)
- {
- $value = settype($value, $execution);
- }
- else if (strpos($type, 'function') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $value = call_user_func_array($execution, $value);
- }
- else if (strpos($type, 'execute') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $execution = str_replace('{RESULT}', '$value', $execution);
- $execution = str_replace('{VALUE}', '$value', $execution);
- // @codingStandardsIgnoreStart
- eval($execution);
- // @codingStandardsIgnoreEnd
- }
- }
- }
- else
- {
- call_user_func_array($fields[2], $fields[1]);
- }
- }
- }
- }
-
- return $sql_flag;
- }
-
- /**
- * Own meta refresh function to be able to change the global time used
- */
- function meta_refresh($url)
- {
- global $convert, $template;
-
- if ($convert->options['refresh'])
- {
- // Because we should not rely on correct settings, we simply use the relative path here directly.
- $template->assign_vars(array(
- 'S_REFRESH' => true,
- 'META' => '<meta http-equiv="refresh" content="5; url=' . $url . '" />')
- );
- }
- }
-
- /**
- * The information below will be used to build the input fields presented to the user
- */
- var $convert_options = array(
- 'legend1' => 'SPECIFY_OPTIONS',
- 'src_dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\', true)', 'explain' => false),
- 'src_dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true),
- 'src_dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true),
- 'src_dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false),
- 'src_dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false),
- 'src_dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false),
- 'src_table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => false),
- //'src_url' => array('lang' => 'FORUM_ADDRESS', 'type' => 'text:50:100', 'explain' => true),
- 'forum_path' => array('lang' => 'FORUM_PATH', 'type' => 'text:25:100', 'explain' => true),
- 'refresh' => array('lang' => 'REFRESH_PAGE', 'type' => 'radio:yes_no', 'explain' => true),
- );
-}
diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php
deleted file mode 100644
index 8e57ed3edd..0000000000
--- a/phpBB/install/install_install.php
+++ /dev/null
@@ -1,2331 +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.
-*
-*/
-
-/**
-*/
-if (!defined('IN_INSTALL'))
-{
- // Someone has tried to access the file direct. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- // If phpBB is already installed we do not include this module
- if (phpbb_check_installation_exists($phpbb_root_path, $phpEx) && !file_exists($phpbb_root_path . 'cache/install_lock'))
- {
- return;
- }
-
- $module[] = array(
- 'module_type' => 'install',
- 'module_title' => 'INSTALL',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 10,
- 'module_subs' => '',
- 'module_stages' => array('INTRO', 'REQUIREMENTS', 'DATABASE', 'ADMINISTRATOR', 'CONFIG_FILE', 'ADVANCED', 'CREATE_TABLE', 'FINAL'),
- 'module_reqs' => ''
- );
-}
-
-/**
-* Installation
-*/
-class install_install extends module
-{
- function install_install(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $lang, $template, $language, $phpbb_root_path, $phpEx;
- global $phpbb_container, $cache, $phpbb_log, $request, $phpbb_config_php_file;
-
- switch ($sub)
- {
- case 'intro':
- $phpbb_container->get('cache.driver')->purge();
-
- $this->page_title = $lang['SUB_INTRO'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['INSTALL_INTRO'],
- 'BODY' => $lang['INSTALL_INTRO_BODY'],
- 'L_SUBMIT' => $lang['NEXT_STEP'],
- 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
- 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language",
- ));
-
- break;
-
- case 'requirements':
- $this->check_server_requirements($mode, $sub);
-
- break;
-
- case 'database':
- $this->obtain_database_settings($mode, $sub);
-
- break;
-
- case 'administrator':
- $this->obtain_admin_settings($mode, $sub);
-
- break;
-
- case 'config_file':
- $this->create_config_file($mode, $sub);
-
- break;
-
- case 'advanced':
- $this->obtain_advanced_settings($mode, $sub);
-
- break;
-
- case 'create_table':
- $this->load_schema($mode, $sub);
- break;
-
- case 'final':
- // Enable super globals to prevent issues with the new \phpbb\request\request object
- $request->enable_super_globals();
-
- // Create a normal container now
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
- $phpbb_container = $phpbb_container_builder->get_container();
-
- // Sets the global variables
- $cache = $phpbb_container->get('cache');
- $phpbb_log = $phpbb_container->get('log');
-
- $this->build_search_index($mode, $sub);
- $this->add_modules($mode, $sub);
- $this->add_language($mode, $sub);
- $this->add_bots($mode, $sub);
- $this->email_admin($mode, $sub);
- $this->disable_avatars_if_unwritable();
- $this->populate_migrations($phpbb_container->get('ext.manager'), $phpbb_container->get('migrator'));
-
- // Remove the lock file
- @unlink($phpbb_root_path . 'cache/install_lock');
-
- break;
- }
-
- $this->tpl_name = 'install_install';
- }
-
- /**
- * Checks that the server we are installing on meets the requirements for running phpBB
- */
- function check_server_requirements($mode, $sub)
- {
- global $lang, $template, $phpbb_root_path, $phpEx, $language;
-
- $this->page_title = $lang['STAGE_REQUIREMENTS'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['REQUIREMENTS_TITLE'],
- 'BODY' => $lang['REQUIREMENTS_EXPLAIN'],
- ));
-
- $passed = array('php' => false, 'db' => false, 'files' => false, 'pcre' => false, 'imagesize' => false, 'json' => false,);
-
- // Test for basic PHP settings
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['PHP_SETTINGS'],
- 'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'],
- ));
-
- // Test the minimum and maximum version of PHP
- $php_version = PHP_VERSION;
-
- if ((version_compare($php_version, '5.3.3') < 0) || (version_compare($php_version, '7.0.0-dev', '>=')))
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
- else
- {
- $passed['php'] = true;
-
- // We also give feedback on whether we're running in safe mode
- $result = '<strong style="color:green">' . $lang['YES'];
- if (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) == 'on')
- {
- $result .= ', ' . $lang['PHP_SAFE_MODE'];
- }
- $result .= '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_VERSION_REQD'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
-
- // Don't check for register_globals on 5.4+
- if (version_compare($php_version, '5.4.0-dev') < 0)
- {
- // Check for register_globals being enabled
- if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on')
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_REGISTER_GLOBALS'],
- 'TITLE_EXPLAIN' => $lang['PHP_REGISTER_GLOBALS_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
- }
-
- // Check for url_fopen
- if (@ini_get('allow_url_fopen') == '1' || strtolower(@ini_get('allow_url_fopen')) == 'on')
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_URL_FOPEN_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PHP_URL_FOPEN_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- // Check for getimagesize
- if (@function_exists('getimagesize'))
- {
- $passed['imagesize'] = true;
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_GETIMAGESIZE_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- // Check for PCRE UTF-8 support
- if (@preg_match('//u', ''))
- {
- $passed['pcre'] = true;
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PCRE_UTF_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PCRE_UTF_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- // Check for php json support
- if (@extension_loaded('json'))
- {
- $passed['json'] = true;
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_JSON_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PHP_JSON_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- $passed['mbstring'] = true;
- if (@extension_loaded('mbstring'))
- {
- // Test for available database modules
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['MBSTRING_CHECK'],
- 'LEGEND_EXPLAIN' => $lang['MBSTRING_CHECK_EXPLAIN'],
- ));
-
- $checks = array(
- array('func_overload', '&', MB_OVERLOAD_MAIL|MB_OVERLOAD_STRING),
- array('encoding_translation', '!=', 0),
- array('http_input', '!=', array('pass', '')),
- array('http_output', '!=', array('pass', ''))
- );
-
- foreach ($checks as $mb_checks)
- {
- $ini_val = @ini_get('mbstring.' . $mb_checks[0]);
- switch ($mb_checks[1])
- {
- case '&':
- if (intval($ini_val) & $mb_checks[2])
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- $passed['mbstring'] = false;
- }
- else
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- break;
-
- case '!=':
- if (!is_array($mb_checks[2]) && $ini_val != $mb_checks[2] ||
- is_array($mb_checks[2]) && !in_array($ini_val, $mb_checks[2]))
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- $passed['mbstring'] = false;
- }
- else
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- break;
- }
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['MBSTRING_' . strtoupper($mb_checks[0])],
- 'TITLE_EXPLAIN' => $lang['MBSTRING_' . strtoupper($mb_checks[0]) . '_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- // Test for available database modules
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['PHP_SUPPORTED_DB'],
- 'LEGEND_EXPLAIN' => $lang['PHP_SUPPORTED_DB_EXPLAIN'],
- ));
-
- $available_dbms = get_available_dbms(false, true);
- $passed['db'] = $available_dbms['ANY_DB_SUPPORT'];
- unset($available_dbms['ANY_DB_SUPPORT']);
-
- foreach ($available_dbms as $db_name => $db_ary)
- {
- if (!$db_ary['AVAILABLE'])
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
- 'RESULT' => '<span style="color:red">' . $lang['UNAVAILABLE'] . '</span>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
- 'RESULT' => '<strong style="color:green">' . $lang['AVAILABLE'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- // Test for other modules
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['PHP_OPTIONAL_MODULE'],
- 'LEGEND_EXPLAIN' => $lang['PHP_OPTIONAL_MODULE_EXPLAIN'],
- ));
-
- foreach ($this->php_dlls_other as $dll)
- {
- if (!@extension_loaded($dll))
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($dll)],
- 'RESULT' => '<strong style="color:red">' . $lang['UNAVAILABLE'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- continue;
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($dll)],
- 'RESULT' => '<strong style="color:green">' . $lang['AVAILABLE'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
-
- // 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);
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['APP_MAGICK'],
- 'RESULT' => ($img_imagick) ? '<strong style="color:green">' . $lang['AVAILABLE'] . ', ' . $img_imagick . '</strong>' : '<strong style="color:blue">' . $lang['NO_LOCATION'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
-
- // Check permissions on files/directories we need access to
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['FILES_REQUIRED'],
- 'LEGEND_EXPLAIN' => $lang['FILES_REQUIRED_EXPLAIN'],
- ));
-
- $directories = array('cache/', 'files/', 'store/');
-
- umask(0);
-
- $passed['files'] = true;
- foreach ($directories as $dir)
- {
- $exists = $write = false;
-
- // Try to create the directory if it does not exist
- if (!file_exists($phpbb_root_path . $dir))
- {
- @mkdir($phpbb_root_path . $dir, 0777);
- phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE);
- }
-
- // Now really check
- if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir))
- {
- phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE);
- $exists = true;
- }
-
- // Now check if it is writable by storing a simple file
- $fp = @fopen($phpbb_root_path . $dir . 'test_lock', 'wb');
- if ($fp !== false)
- {
- $write = true;
- }
- @fclose($fp);
-
- @unlink($phpbb_root_path . $dir . 'test_lock');
-
- $passed['files'] = ($exists && $write && $passed['files']) ? true : false;
-
- $exists = ($exists) ? '<strong style="color:green">' . $lang['FOUND'] . '</strong>' : '<strong style="color:red">' . $lang['NOT_FOUND'] . '</strong>';
- $write = ($write) ? ', <strong style="color:green">' . $lang['WRITABLE'] . '</strong>' : (($exists) ? ', <strong style="color:red">' . $lang['UNWRITABLE'] . '</strong>' : '');
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $dir,
- 'RESULT' => $exists . $write,
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
-
- // Check permissions on files/directories it would be useful access to
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['FILES_OPTIONAL'],
- 'LEGEND_EXPLAIN' => $lang['FILES_OPTIONAL_EXPLAIN'],
- ));
-
- $directories = array('config.' . $phpEx, 'images/avatars/upload/');
-
- foreach ($directories as $dir)
- {
- $write = $exists = true;
- if (file_exists($phpbb_root_path . $dir))
- {
- if (!phpbb_is_writable($phpbb_root_path . $dir))
- {
- $write = false;
- }
- }
- else
- {
- $write = $exists = false;
- }
-
- $exists_str = ($exists) ? '<strong style="color:green">' . $lang['FOUND'] . '</strong>' : '<strong style="color:red">' . $lang['NOT_FOUND'] . '</strong>';
- $write_str = ($write) ? ', <strong style="color:green">' . $lang['WRITABLE'] . '</strong>' : (($exists) ? ', <strong style="color:red">' . $lang['UNWRITABLE'] . '</strong>' : '');
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $dir,
- 'RESULT' => $exists_str . $write_str,
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
-
- // And finally where do we want to go next (well today is taken isn't it :P)
- $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
-
- $url = (!in_array(false, $passed)) ? $this->p_master->module_url . "?mode=$mode&amp;sub=database&amp;language=$language" : $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language ";
- $submit = (!in_array(false, $passed)) ? $lang['INSTALL_START'] : $lang['INSTALL_TEST'];
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Obtain the information required to connect to the database
- */
- function obtain_database_settings($mode, $sub)
- {
- global $lang, $template, $phpEx;
-
- $this->page_title = $lang['STAGE_DATABASE'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- $connect_test = false;
- $error = array();
- $available_dbms = get_available_dbms(false, true);
-
- // Has the user opted to test the connection?
- if (isset($_POST['testdb']))
- {
- if (!isset($available_dbms[$data['dbms']]) || !$available_dbms[$data['dbms']]['AVAILABLE'])
- {
- $error[] = $lang['INST_ERR_NO_DB'];
- $connect_test = false;
- }
- else if (!preg_match(get_preg_expression('table_prefix'), $data['table_prefix']))
- {
- $error[] = $lang['INST_ERR_DB_INVALID_PREFIX'];
- $connect_test = false;
- }
- else
- {
- $connect_test = connect_check_db(true, $error, $available_dbms[$data['dbms']], $data['table_prefix'], $data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport']);
- }
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['DB_CONNECTION'],
- 'LEGEND_EXPLAIN' => false,
- ));
-
- if ($connect_test)
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DB_TEST'],
- 'RESULT' => '<strong style="color:green">' . $lang['SUCCESSFUL_CONNECT'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DB_TEST'],
- 'RESULT' => '<strong style="color:red">' . implode('<br />', $error) . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- if (!$connect_test)
- {
- // Update the list of available DBMS modules to only contain those which can be used
- $available_dbms_temp = array();
- foreach ($available_dbms as $type => $dbms_ary)
- {
- if (!$dbms_ary['AVAILABLE'])
- {
- continue;
- }
-
- $available_dbms_temp[$type] = $dbms_ary;
- }
-
- $available_dbms = &$available_dbms_temp;
-
- // And now for the main part of this page
- $data['table_prefix'] = (!empty($data['table_prefix']) ? $data['table_prefix'] : 'phpbb_');
-
- foreach ($this->db_config_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options),
- )
- );
- }
- }
-
- // And finally where do we want to go next (well today is taken isn't it :P)
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
- if ($connect_test)
- {
- foreach ($this->db_config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
- }
-
- $url = ($connect_test) ? $this->p_master->module_url . "?mode=$mode&amp;sub=administrator" : $this->p_master->module_url . "?mode=$mode&amp;sub=database";
- $s_hidden_fields .= ($connect_test) ? '' : '<input type="hidden" name="testdb" value="true" />';
-
- $submit = $lang['NEXT_STEP'];
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Obtain the administrator's name, password and email address
- */
- function obtain_admin_settings($mode, $sub)
- {
- global $lang, $template, $phpEx;
-
- $this->page_title = $lang['STAGE_ADMINISTRATOR'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $passed = false;
-
- $data['default_lang'] = ($data['default_lang'] !== '') ? $data['default_lang'] : $data['language'];
-
- if (isset($_POST['check']))
- {
- $error = array();
-
- // Check the entered email address and password
- if ($data['admin_name'] == '' || $data['admin_pass1'] == '' || $data['admin_pass2'] == '' || $data['board_email'] == '')
- {
- $error[] = $lang['INST_ERR_MISSING_DATA'];
- }
-
- if ($data['admin_pass1'] != $data['admin_pass2'] && $data['admin_pass1'] != '')
- {
- $error[] = $lang['INST_ERR_PASSWORD_MISMATCH'];
- }
-
- // Test against the default username rules
- if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) < 3)
- {
- $error[] = $lang['INST_ERR_USER_TOO_SHORT'];
- }
-
- if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) > 20)
- {
- $error[] = $lang['INST_ERR_USER_TOO_LONG'];
- }
-
- // Test against the default password rules
- if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) < 6)
- {
- $error[] = $lang['INST_ERR_PASSWORD_TOO_SHORT'];
- }
-
- if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) > 30)
- {
- $error[] = $lang['INST_ERR_PASSWORD_TOO_LONG'];
- }
-
- if ($data['board_email'] != '' && !preg_match('/^' . get_preg_expression('email') . '$/i', $data['board_email']))
- {
- $error[] = $lang['INST_ERR_EMAIL_INVALID'];
- }
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['STAGE_ADMINISTRATOR'],
- 'LEGEND_EXPLAIN' => false,
- ));
-
- if (!sizeof($error))
- {
- $passed = true;
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['ADMIN_TEST'],
- 'RESULT' => '<strong style="color:green">' . $lang['TESTS_PASSED'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['ADMIN_TEST'],
- 'RESULT' => '<strong style="color:red">' . implode('<br />', $error) . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- if (!$passed)
- {
- foreach ($this->admin_config_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options),
- )
- );
- }
- }
- else
- {
- foreach ($this->admin_config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
- }
-
- $s_hidden_fields .= ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
-
- foreach ($this->db_config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
-
- $submit = $lang['NEXT_STEP'];
-
- $url = ($passed) ? $this->p_master->module_url . "?mode=$mode&amp;sub=config_file" : $this->p_master->module_url . "?mode=$mode&amp;sub=administrator";
- $s_hidden_fields .= ($passed) ? '' : '<input type="hidden" name="check" value="true" />';
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Writes the config file to disk, or if unable to do so offers alternative methods
- */
- function create_config_file($mode, $sub)
- {
- global $lang, $template, $phpbb_root_path, $phpEx;
-
- $this->page_title = $lang['STAGE_CONFIG_FILE'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
- $written = false;
-
- // Create a list of any PHP modules we wish to have loaded
- $available_dbms = get_available_dbms($data['dbms']);
-
- // Create a lock file to indicate that there is an install in progress
- $fp = @fopen($phpbb_root_path . 'cache/install_lock', 'wb');
- if ($fp === false)
- {
- // We were unable to create the lock file - abort
- $this->p_master->error($lang['UNABLE_WRITE_LOCK'], __LINE__, __FILE__);
- }
- @fclose($fp);
-
- @chmod($phpbb_root_path . 'cache/install_lock', 0777);
-
- // Time to convert the data provided into a config file
- $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER']);
-
- // Attempt to write out the config file directly. If it works, this is the easiest way to do it ...
- if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) || phpbb_is_writable($phpbb_root_path))
- {
- // Assume it will work ... if nothing goes wrong below
- $written = true;
-
- if (!($fp = @fopen($phpbb_root_path . 'config.' . $phpEx, 'w')))
- {
- // Something went wrong ... so let's try another method
- $written = false;
- }
-
- if (!(@fwrite($fp, $config_data)))
- {
- // Something went wrong ... so let's try another method
- $written = false;
- }
-
- @fclose($fp);
-
- if ($written)
- {
- // We may revert back to chmod() if we see problems with users not able to change their config.php file directly
- phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ);
- }
- }
-
- if (isset($_POST['dldone']))
- {
- // Do a basic check to make sure that the file has been uploaded
- // Note that all we check is that the file has _something_ in it
- // We don't compare the contents exactly - if they can't upload
- // a single file correctly, it's likely they will have other problems....
- if (filesize($phpbb_root_path . 'config.' . $phpEx) > 10)
- {
- $written = true;
- }
- }
-
- $config_options = array_merge($this->db_config_options, $this->admin_config_options);
-
- foreach ($config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
-
- if (!$written)
- {
- // OK, so it didn't work let's try the alternatives
-
- if (isset($_POST['dlconfig']))
- {
- // They want a copy of the file to download, so send the relevant headers and dump out the data
- header("Content-Type: text/x-delimtext; name=\"config.$phpEx\"");
- header("Content-disposition: attachment; filename=config.$phpEx");
- echo $config_data;
- exit;
- }
-
- // The option to download the config file is always available, so output it here
- $template->assign_vars(array(
- 'BODY' => $lang['CONFIG_FILE_UNABLE_WRITE'],
- 'L_DL_CONFIG' => $lang['DL_CONFIG'],
- 'L_DL_CONFIG_EXPLAIN' => $lang['DL_CONFIG_EXPLAIN'],
- 'L_DL_DONE' => $lang['DONE'],
- 'L_DL_DOWNLOAD' => $lang['DL_DOWNLOAD'],
- 'S_HIDDEN' => $s_hidden_fields,
- 'S_SHOW_DOWNLOAD' => true,
- 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=config_file",
- ));
- return;
- }
- else
- {
- $template->assign_vars(array(
- 'BODY' => $lang['CONFIG_FILE_WRITTEN'],
- 'L_SUBMIT' => $lang['NEXT_STEP'],
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=advanced",
- ));
- return;
- }
- }
-
- /**
- * Provide an opportunity to customise some advanced settings during the install
- * in case it is necessary for them to be set to access later
- */
- function obtain_advanced_settings($mode, $sub)
- {
- global $lang, $template, $phpEx, $request;
-
- $this->page_title = $lang['STAGE_ADVANCED'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
-
- // HTTP_HOST is having the correct browser url in most cases...
- $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
-
- // HTTP HOST can carry a port number...
- if (strpos($server_name, ':') !== false)
- {
- $server_name = substr($server_name, 0, strpos($server_name, ':'));
- }
-
- $data['email_enable'] = ($data['email_enable'] !== '') ? $data['email_enable'] : true;
- $data['server_name'] = ($data['server_name'] !== '') ? $data['server_name'] : $server_name;
- $data['server_port'] = ($data['server_port'] !== '') ? $data['server_port'] : $request->server('SERVER_PORT', 0);
- $data['server_protocol'] = ($data['server_protocol'] !== '') ? $data['server_protocol'] : ($request->is_secure() ? 'https://' : 'http://');
- $data['cookie_secure'] = ($data['cookie_secure'] !== '') ? $data['cookie_secure'] : $request->is_secure();
-
- if ($data['script_path'] === '')
- {
- $name = htmlspecialchars_decode($request->server('PHP_SELF'));
- if (!$name)
- {
- $name = htmlspecialchars_decode($request->server('REQUEST_URI'));
- }
-
- // Replace backslashes and doubled slashes (could happen on some proxy setups)
- $name = str_replace(array('\\', '//'), '/', $name);
- $data['script_path'] = trim(dirname(dirname($name)));
- }
-
- foreach ($this->advanced_config_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options),
- )
- );
- }
-
- $config_options = array_merge($this->db_config_options, $this->admin_config_options);
- foreach ($config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
-
- $submit = $lang['NEXT_STEP'];
-
- $url = $this->p_master->module_url . "?mode=$mode&amp;sub=create_table";
-
- $template->assign_vars(array(
- 'BODY' => $lang['STAGE_ADVANCED_EXPLAIN'],
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Load the contents of the schema into the database and then alter it based on what has been input during the installation
- */
- function load_schema($mode, $sub)
- {
- global $db, $lang, $template, $phpbb_root_path, $phpEx, $request;
-
- $this->page_title = $lang['STAGE_CREATE_TABLE'];
- $s_hidden_fields = '';
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- // HTTP_HOST is having the correct browser url in most cases...
- $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
- $referer = strtolower($request->header('Referer'));
-
- // HTTP HOST can carry a port number...
- if (strpos($server_name, ':') !== false)
- {
- $server_name = substr($server_name, 0, strpos($server_name, ':'));
- }
-
- $cookie_domain = ($data['server_name'] != '') ? $data['server_name'] : $server_name;
-
- // Try to come up with the best solution for cookie domain...
- if (strpos($cookie_domain, 'www.') === 0)
- {
- $cookie_domain = str_replace('www.', '.', $cookie_domain);
- }
-
- // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
- $available_dbms = get_available_dbms($data['dbms']);
-
- if (!isset($available_dbms[$data['dbms']]))
- {
- // Someone's been silly and tried providing a non-existant dbms
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $dbms = $available_dbms[$data['dbms']]['DRIVER'];
-
- // Instantiate the database
- $db = new $dbms();
- $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false);
-
- // NOTE: trigger_error does not work here.
- $db->sql_return_on_error(true);
-
- // If mysql is chosen, we need to adjust the schema filename slightly to reflect the correct version. ;)
- if ($data['dbms'] == 'mysql')
- {
- if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
- {
- $available_dbms[$data['dbms']]['SCHEMA'] .= '_41';
- }
- else
- {
- $available_dbms[$data['dbms']]['SCHEMA'] .= '_40';
- }
- }
-
- // Ok we have the db info go ahead and read in the relevant schema
- // and work on building the table
- $dbms_schema = 'schemas/' . $available_dbms[$data['dbms']]['SCHEMA'] . '_schema.sql';
-
- // How should we treat this schema?
- $delimiter = $available_dbms[$data['dbms']]['DELIM'];
-
- if (file_exists($dbms_schema))
- {
- $sql_query = @file_get_contents($dbms_schema);
- $sql_query = preg_replace('#phpbb_#i', $data['table_prefix'], $sql_query);
- $sql_query = phpbb_remove_comments($sql_query);
- $sql_query = split_sql_file($sql_query, $delimiter);
-
- foreach ($sql_query as $sql)
- {
- // Ignore errors when the functions or types already exist
- // to allow installing phpBB twice in the same database with
- // a different prefix
- $db->sql_query($sql);
- }
- unset($sql_query);
- }
-
- // Ok we have the db info go ahead and work on building the table
- if (file_exists('schemas/schema.json'))
- {
- $db_table_schema = @file_get_contents('schemas/schema.json');
- $db_table_schema = json_decode($db_table_schema, true);
- }
- else
- {
- global $phpbb_root_path, $phpEx, $table_prefix;
- $table_prefix = 'phpbb_';
-
- if (!defined('CONFIG_TABLE'))
- {
- // We need to include the constants file for the table constants
- // when we generate the schema from the migration files.
- include($phpbb_root_path . 'includes/constants.' . $phpEx);
- }
-
- $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx);
- $classes = $finder->core_path('phpbb/db/migration/data/')
- ->get_classes();
-
- $sqlite_db = new \phpbb\db\driver\sqlite();
- $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, new \phpbb\db\tools($sqlite_db, true), $phpbb_root_path, $phpEx, $table_prefix);
- $db_table_schema = $schema_generator->get_schema();
- }
-
- if (!defined('CONFIG_TABLE'))
- {
- // CONFIG_TABLE is required by sql_create_index() to check the
- // length of index names. However table_prefix is not defined
- // here yet, so we need to create the constant ourselves.
- define('CONFIG_TABLE', $data['table_prefix'] . 'config');
- }
-
- $db_tools = new \phpbb\db\tools($db);
- foreach ($db_table_schema as $table_name => $table_data)
- {
- $db_tools->sql_create_table(
- $data['table_prefix'] . substr($table_name, 6),
- $table_data
- );
- }
-
- // Ok tables have been built, let's fill in the basic information
- $sql_query = file_get_contents('schemas/schema_data.sql');
-
- // Deal with any special comments and characters
- switch ($data['dbms'])
- {
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query);
- break;
-
- case 'postgres':
- $sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query);
- break;
-
- case 'mysql':
- case 'mysqli':
- $sql_query = str_replace('\\', '\\\\', $sql_query);
- break;
- }
-
- // Change prefix
- $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $data['table_prefix'] . '\1 ', $sql_query);
-
- // Change language strings...
- $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query);
-
- $sql_query = phpbb_remove_comments($sql_query);
- $sql_query = split_sql_file($sql_query, ';');
-
- foreach ($sql_query as $sql)
- {
- //$sql = trim(str_replace('|', ';', $sql));
- if (!$db->sql_query($sql))
- {
- $error = $db->sql_error();
- $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
- }
- }
- unset($sql_query);
-
- $current_time = time();
-
- $user_ip = $request->server('REMOTE_ADDR') ? phpbb_ip_normalise($request->server('REMOTE_ADDR')) : '';
-
- if ($data['script_path'] !== '/')
- {
- // Adjust destination path (no trailing slash)
- if (substr($data['script_path'], -1) == '/')
- {
- $data['script_path'] = substr($data['script_path'], 0, -1);
- }
-
- $data['script_path'] = str_replace(array('../', './'), '', $data['script_path']);
-
- if ($data['script_path'][0] != '/')
- {
- $data['script_path'] = '/' . $data['script_path'];
- }
- }
-
- // Set default config and post data, this applies to all DB's
- $sql_ary = array(
- 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value)
- VALUES ('board_startdate', '$current_time')",
-
- 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value)
- VALUES ('default_lang', '" . $db->sql_escape($data['default_lang']) . "')",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['img_imagick']) . "'
- WHERE config_name = 'img_imagick'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['server_name']) . "'
- WHERE config_name = 'server_name'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['server_port']) . "'
- WHERE config_name = 'server_port'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['board_email']) . "'
- WHERE config_name = 'board_email'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['board_email']) . "'
- WHERE config_name = 'board_contact'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($cookie_domain) . "'
- WHERE config_name = 'cookie_domain'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($lang['default_dateformat']) . "'
- WHERE config_name = 'default_dateformat'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['email_enable']) . "'
- WHERE config_name = 'email_enable'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_delivery']) . "'
- WHERE config_name = 'smtp_delivery'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_host']) . "'
- WHERE config_name = 'smtp_host'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_auth']) . "'
- WHERE config_name = 'smtp_auth_method'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_user']) . "'
- WHERE config_name = 'smtp_username'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_pass']) . "'
- WHERE config_name = 'smtp_password'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['cookie_secure']) . "'
- WHERE config_name = 'cookie_secure'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['force_server_vars']) . "'
- WHERE config_name = 'force_server_vars'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['script_path']) . "'
- WHERE config_name = 'script_path'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['server_protocol']) . "'
- WHERE config_name = 'server_protocol'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE config_name = 'newest_username'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . md5(mt_rand()) . "'
- WHERE config_name = 'avatar_salt'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . md5(mt_rand()) . "'
- WHERE config_name = 'plupload_salt'",
-
- 'UPDATE ' . $data['table_prefix'] . "users
- SET username = '" . $db->sql_escape($data['admin_name']) . "', user_password='" . $db->sql_escape(md5($data['admin_pass1'])) . "', user_ip = '" . $db->sql_escape($user_ip) . "', user_lang = '" . $db->sql_escape($data['default_lang']) . "', user_email='" . $db->sql_escape($data['board_email']) . "', user_dateformat='" . $db->sql_escape($lang['default_dateformat']) . "', user_email_hash = " . $db->sql_escape(phpbb_email_hash($data['board_email'])) . ", username_clean = '" . $db->sql_escape(utf8_clean_string($data['admin_name'])) . "'
- WHERE username = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "moderator_cache
- SET username = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE username = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "forums
- SET forum_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE forum_last_poster_name = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "topics
- SET topic_first_poster_name = '" . $db->sql_escape($data['admin_name']) . "', topic_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE topic_first_poster_name = 'Admin'
- OR topic_last_poster_name = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "users
- SET user_regdate = $current_time",
-
- 'UPDATE ' . $data['table_prefix'] . "posts
- SET post_time = $current_time, poster_ip = '" . $db->sql_escape($user_ip) . "'",
-
- 'UPDATE ' . $data['table_prefix'] . "topics
- SET topic_time = $current_time, topic_last_post_time = $current_time",
-
- 'UPDATE ' . $data['table_prefix'] . "forums
- SET forum_last_post_time = $current_time",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($db->sql_server_info(true)) . "'
- WHERE config_name = 'dbms_version'",
- );
-
- if (@extension_loaded('gd'))
- {
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = 'core.captcha.plugins.gd'
- WHERE config_name = 'captcha_plugin'";
-
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '1'
- WHERE config_name = 'captcha_gd'";
- }
-
- $ref = substr($referer, strpos($referer, '://') + 3);
-
- if (!(stripos($ref, $server_name) === 0))
- {
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '0'
- WHERE config_name = 'referer_validation'";
- }
-
- // We set a (semi-)unique cookie name to bypass login issues related to the cookie name.
- $cookie_name = 'phpbb3_';
- $rand_str = md5(mt_rand());
- $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35));
- $rand_str = substr($rand_str, 0, 5);
- $cookie_name .= strtolower($rand_str);
-
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($cookie_name) . "'
- WHERE config_name = 'cookie_name'";
-
- foreach ($sql_ary as $sql)
- {
- //$sql = trim(str_replace('|', ';', $sql));
-
- if (!$db->sql_query($sql))
- {
- $error = $db->sql_error();
- $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
- }
- }
-
- $submit = $lang['NEXT_STEP'];
-
- $url = $this->p_master->module_url . "?mode=$mode&amp;sub=final";
-
- $template->assign_vars(array(
- 'BODY' => $lang['STAGE_CREATE_TABLE_EXPLAIN'],
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => build_hidden_fields($data),
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Build the search index...
- */
- function build_search_index($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpbb_dispatcher, $phpEx, $config, $auth, $user;
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
- $table_prefix = $data['table_prefix'];
-
- // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
- $available_dbms = get_available_dbms($data['dbms']);
-
- if (!isset($available_dbms[$data['dbms']]))
- {
- // Someone's been silly and tried providing a non-existant dbms
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $dbms = $available_dbms[$data['dbms']]['DRIVER'];
-
- // Instantiate the database
- $db = new $dbms();
- $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false);
-
- // NOTE: trigger_error does not work here.
- $db->sql_return_on_error(true);
-
- include_once($phpbb_root_path . 'includes/constants.' . $phpEx);
- include_once($phpbb_root_path . 'phpbb/search/fulltext_native.' . $phpEx);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- $error = false;
- $search = new \phpbb\search\fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
-
- $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id
- FROM ' . POSTS_TABLE;
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']);
- }
- $db->sql_freeresult($result);
- }
-
- /**
- * Populate the module tables
- */
- function add_modules($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager, $config, $phpbb_container;
-
- // modules require an extension manager
- if (empty($phpbb_extension_manager))
- {
- $phpbb_extension_manager = $phpbb_container->get('ext.manager');
- }
-
- include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx);
-
- $_module = new acp_modules();
- $module_classes = array('acp', 'mcp', 'ucp');
-
- // Add categories
- foreach ($module_classes as $module_class)
- {
- $categories = array();
-
- // Set the module class
- $_module->module_class = $module_class;
-
- foreach ($this->module_categories[$module_class] as $cat_name => $subs)
- {
- $basename = '';
- // Check if this sub-category has a basename. If it has, use it.
- if (isset($this->module_categories_basenames[$cat_name]))
- {
- $basename = $this->module_categories_basenames[$cat_name];
- }
- $module_data = array(
- 'module_basename' => $basename,
- 'module_enabled' => 1,
- 'module_display' => 1,
- 'parent_id' => 0,
- 'module_class' => $module_class,
- 'module_langname' => $cat_name,
- 'module_mode' => '',
- 'module_auth' => '',
- );
-
- // Add category
- $_module->update_module_data($module_data, true);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
-
- $categories[$cat_name]['id'] = (int) $module_data['module_id'];
- $categories[$cat_name]['parent_id'] = 0;
-
- // Create sub-categories...
- if (is_array($subs))
- {
- foreach ($subs as $level2_name)
- {
- $basename = '';
- // Check if this sub-category has a basename. If it has, use it.
- if (isset($this->module_categories_basenames[$level2_name]))
- {
- $basename = $this->module_categories_basenames[$level2_name];
- }
- $module_data = array(
- 'module_basename' => $basename,
- 'module_enabled' => 1,
- 'module_display' => 1,
- 'parent_id' => (int) $categories[$cat_name]['id'],
- 'module_class' => $module_class,
- 'module_langname' => $level2_name,
- 'module_mode' => '',
- 'module_auth' => '',
- );
-
- $_module->update_module_data($module_data, true);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
-
- $categories[$level2_name]['id'] = (int) $module_data['module_id'];
- $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id'];
- }
- }
- }
-
- // Get the modules we want to add... returned sorted by name
- $module_info = $_module->get_module_infos('', $module_class);
-
- foreach ($module_info as $module_basename => $fileinfo)
- {
- foreach ($fileinfo['modes'] as $module_mode => $row)
- {
- foreach ($row['cat'] as $cat_name)
- {
- if (!isset($categories[$cat_name]))
- {
- continue;
- }
-
- $module_data = array(
- 'module_basename' => $module_basename,
- 'module_enabled' => 1,
- 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1,
- 'parent_id' => (int) $categories[$cat_name]['id'],
- 'module_class' => $module_class,
- 'module_langname' => $row['title'],
- 'module_mode' => $module_mode,
- 'module_auth' => $row['auth'],
- );
-
- $_module->update_module_data($module_data, true);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
- }
- }
- }
-
- // Move some of the modules around since the code above will put them in the wrong place
- if ($module_class == 'acp')
- {
- // Move main module 4 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'acp_main'
- AND module_class = 'acp'
- AND module_mode = 'main'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_up', 4);
-
- // Move permissions intro screen module 4 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'acp_permissions'
- AND module_class = 'acp'
- AND module_mode = 'intro'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_up', 4);
-
- // Move manage users screen module 5 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'acp_users'
- AND module_class = 'acp'
- AND module_mode = 'overview'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_up', 5);
-
- // Move extension management module 1 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT'
- AND module_class = 'acp'
- AND module_mode = ''
- AND module_basename = ''";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_up', 1);
- }
-
- if ($module_class == 'mcp')
- {
- // Move pm report details module 3 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'mcp_pm_reports'
- AND module_class = 'mcp'
- AND module_mode = 'pm_report_details'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_down', 3);
-
- // Move closed pm reports module 3 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'mcp_pm_reports'
- AND module_class = 'mcp'
- AND module_mode = 'pm_reports_closed'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_down', 3);
-
- // Move open pm reports module 3 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'mcp_pm_reports'
- AND module_class = 'mcp'
- AND module_mode = 'pm_reports'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_down', 3);
- }
-
- if ($module_class == 'ucp')
- {
- // Move attachment module 4 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'ucp_attachments'
- AND module_class = 'ucp'
- AND module_mode = 'attachments'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_down', 4);
-
- // Move notification options module 4 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'ucp_notifications'
- AND module_class = 'ucp'
- AND module_mode = 'notification_options'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_down', 4);
-
- // Move OAuth module 5 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'ucp_auth_link'
- AND module_class = 'ucp'
- AND module_mode = 'auth_link'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'move_down', 5);
- }
-
- // And now for the special ones
- // (these are modules which appear in multiple categories and thus get added manually to some for more control)
- if (isset($this->module_extras[$module_class]))
- {
- foreach ($this->module_extras[$module_class] as $cat_name => $mods)
- {
- $sql = 'SELECT module_id, left_id, right_id
- FROM ' . MODULES_TABLE . "
- WHERE module_langname = '" . $db->sql_escape($cat_name) . "'
- AND module_class = '" . $db->sql_escape($module_class) . "'";
- $result = $db->sql_query_limit($sql, 1);
- $row2 = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- foreach ($mods as $mod_name)
- {
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_langname = '" . $db->sql_escape($mod_name) . "'
- AND module_class = '" . $db->sql_escape($module_class) . "'
- AND module_basename <> ''";
- $result = $db->sql_query_limit($sql, 1);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $module_data = array(
- 'module_basename' => $row['module_basename'],
- 'module_enabled' => (int) $row['module_enabled'],
- 'module_display' => (int) $row['module_display'],
- 'parent_id' => (int) $row2['module_id'],
- 'module_class' => $row['module_class'],
- 'module_langname' => $row['module_langname'],
- 'module_mode' => $row['module_mode'],
- 'module_auth' => $row['module_auth'],
- );
-
- $_module->update_module_data($module_data, true);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
- }
- }
- }
-
- $_module->remove_cache_file();
- }
- }
-
- /**
- * Populate the language tables
- */
- function add_language($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpEx;
-
- $dir = @opendir($phpbb_root_path . 'language');
-
- if (!$dir)
- {
- $this->error('Unable to access the language directory', __LINE__, __FILE__);
- }
-
- $installed_languages = array();
- while (($file = readdir($dir)) !== false)
- {
- $path = $phpbb_root_path . 'language/' . $file;
-
- if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS')
- {
- continue;
- }
-
- if (is_dir($path) && file_exists($path . '/iso.txt'))
- {
- $lang_file = file("$path/iso.txt");
-
- $lang_pack = array(
- 'lang_iso' => basename($path),
- 'lang_dir' => basename($path),
- 'lang_english_name' => trim(htmlspecialchars($lang_file[0])),
- 'lang_local_name' => trim(htmlspecialchars($lang_file[1], ENT_COMPAT, 'UTF-8')),
- 'lang_author' => trim(htmlspecialchars($lang_file[2], ENT_COMPAT, 'UTF-8')),
- );
-
- $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $lang_pack));
-
- $installed_languages[] = (int) $db->sql_nextid();
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
- }
- }
- closedir($dir);
-
- $sql = 'SELECT *
- FROM ' . PROFILE_FIELDS_TABLE;
- $result = $db->sql_query($sql);
-
- $profile_fields = array();
- $insert_buffer = new \phpbb\db\sql_insert_buffer($db, PROFILE_LANG_TABLE);
- while ($row = $db->sql_fetchrow($result))
- {
- foreach ($installed_languages as $lang_id)
- {
- $insert_buffer->insert(array(
- 'field_id' => $row['field_id'],
- 'lang_id' => $lang_id,
- 'lang_name' => strtoupper(substr($row['field_name'], 6)),// Remove phpbb_ from field name
- 'lang_explain' => '',
- 'lang_default_value' => '',
- ));
- }
- }
- $db->sql_freeresult($result);
-
- $insert_buffer->flush();
- }
-
- /**
- * Add search robots to the database
- */
- function add_bots($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpEx, $config;
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- $sql = 'SELECT group_id
- FROM ' . GROUPS_TABLE . "
- WHERE group_name = 'BOTS'";
- $result = $db->sql_query($sql);
- $group_id = (int) $db->sql_fetchfield('group_id');
- $db->sql_freeresult($result);
-
- if (!$group_id)
- {
- // If we reach this point then something has gone very wrong
- $this->p_master->error($lang['NO_GROUP'], __LINE__, __FILE__);
- }
-
- if (!function_exists('user_add'))
- {
- include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
- }
-
- foreach ($this->bot_list as $bot_name => $bot_ary)
- {
- $user_row = array(
- 'user_type' => USER_IGNORE,
- 'group_id' => $group_id,
- 'username' => $bot_name,
- 'user_regdate' => time(),
- 'user_password' => '',
- 'user_colour' => '9E8DA7',
- 'user_email' => '',
- 'user_lang' => $data['default_lang'],
- 'user_style' => 1,
- 'user_timezone' => 'UTC',
- 'user_dateformat' => $lang['default_dateformat'],
- 'user_allow_massemail' => 0,
- 'user_allow_pm' => 0,
- );
-
- $user_id = user_add($user_row);
-
- if (!$user_id)
- {
- // If we can't insert this user then continue to the next one to avoid inconsistent data
- $this->p_master->db_error('Unable to insert bot into users table', $db->get_sql_error_sql(), __LINE__, __FILE__, true);
- continue;
- }
-
- $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'bot_active' => 1,
- 'bot_name' => (string) $bot_name,
- 'user_id' => (int) $user_id,
- 'bot_agent' => (string) $bot_ary[0],
- 'bot_ip' => (string) $bot_ary[1],
- ));
-
- $db->sql_query($sql);
- }
- }
-
- /**
- * Sends an email to the board administrator with their password and some useful links
- */
- function email_admin($mode, $sub)
- {
- global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx;
-
- $this->page_title = $lang['STAGE_FINAL'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- $user->session_begin();
- $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true);
-
- // OK, Now that we've reached this point we can be confident that everything
- // is installed and working......I hope :)
- // So it's time to send an email to the administrator confirming the details
- // they entered
-
- if ($config['email_enable'])
- {
- include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
-
- $messenger = new messenger(false);
-
- $messenger->template('installed', $data['language']);
-
- $messenger->to($data['board_email'], $data['admin_name']);
-
- $messenger->anti_abuse_headers($config, $user);
-
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($data['admin_name']),
- 'PASSWORD' => htmlspecialchars_decode($data['admin_pass1']))
- );
-
- $messenger->send(NOTIFY_EMAIL);
- }
-
- // And finally, add a note to the log
- add_log('admin', 'LOG_INSTALL_INSTALLED', $config['version']);
-
- $template->assign_vars(array(
- 'TITLE' => $lang['INSTALL_CONGRATS'],
- 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&amp;language=' . $data['language']), '../docs/README.html'),
- 'L_SUBMIT' => $lang['INSTALL_LOGIN'],
- 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&amp;mode=send_statistics'),
- ));
- }
-
- /**
- * Check if the avatar directory is writable and disable avatars
- * if it isn't writable.
- */
- function disable_avatars_if_unwritable()
- {
- global $phpbb_root_path;
-
- if (!phpbb_is_writable($phpbb_root_path . 'images/avatars/upload/'))
- {
- set_config('allow_avatar', 0);
- set_config('allow_avatar_upload', 0);
- }
- }
-
- /**
- * Populate migrations for the installation
- *
- * This "installs" all migrations from (root path)/phpbb/db/migrations/data.
- * "installs" means it adds all migrations to the migrations table, but does not
- * perform any of the actions in the migrations.
- *
- * @param \phpbb\extension\manager $extension_manager
- * @param \phpbb\db\migrator $migrator
- */
- function populate_migrations($extension_manager, $migrator)
- {
- $finder = $extension_manager->get_finder();
-
- $migrations = $finder
- ->core_path('phpbb/db/migration/data/')
- ->get_classes();
- $migrator->populate_migrations($migrations);
- }
-
- /**
- * Generate a list of available mail server authentication methods
- */
- function mail_auth_select($selected_method)
- {
- global $lang;
-
- $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP');
- $s_smtp_auth_options = '';
-
- foreach ($auth_methods as $method)
- {
- $s_smtp_auth_options .= '<option value="' . $method . '"' . (($selected_method == $method) ? ' selected="selected"' : '') . '>' . $lang['SMTP_' . str_replace('-', '_', $method)] . '</option>';
- }
-
- return $s_smtp_auth_options;
- }
-
- /**
- * Get submitted data
- */
- function get_submitted_data()
- {
- return array(
- 'language' => basename(request_var('language', '')),
- 'dbms' => request_var('dbms', ''),
- 'dbhost' => request_var('dbhost', '', true),
- 'dbport' => request_var('dbport', ''),
- 'dbuser' => request_var('dbuser', ''),
- 'dbpasswd' => request_var('dbpasswd', '', true),
- 'dbname' => request_var('dbname', ''),
- 'table_prefix' => request_var('table_prefix', ''),
- 'default_lang' => basename(request_var('default_lang', '')),
- 'admin_name' => utf8_normalize_nfc(request_var('admin_name', '', true)),
- 'admin_pass1' => request_var('admin_pass1', '', true),
- 'admin_pass2' => request_var('admin_pass2', '', true),
- 'board_email' => strtolower(request_var('board_email', '')),
- 'img_imagick' => request_var('img_imagick', ''),
- 'ftp_path' => request_var('ftp_path', ''),
- 'ftp_user' => request_var('ftp_user', ''),
- 'ftp_pass' => request_var('ftp_pass', ''),
- 'email_enable' => request_var('email_enable', ''),
- 'smtp_delivery' => request_var('smtp_delivery', ''),
- 'smtp_host' => request_var('smtp_host', ''),
- 'smtp_auth' => request_var('smtp_auth', ''),
- 'smtp_user' => request_var('smtp_user', ''),
- 'smtp_pass' => request_var('smtp_pass', ''),
- 'cookie_secure' => request_var('cookie_secure', ''),
- 'force_server_vars' => request_var('force_server_vars', ''),
- 'server_protocol' => request_var('server_protocol', ''),
- 'server_name' => request_var('server_name', ''),
- 'server_port' => request_var('server_port', ''),
- 'script_path' => request_var('script_path', ''),
- );
- }
-
- /**
- * The information below will be used to build the input fields presented to the user
- */
- var $db_config_options = array(
- 'legend1' => 'DB_CONFIG',
- 'dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\')', 'explain' => false),
- 'dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true),
- 'dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true),
- 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false),
- 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false),
- 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false),
- 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => true),
- );
- var $admin_config_options = array(
- 'legend1' => 'ADMIN_CONFIG',
- 'default_lang' => array('lang' => 'DEFAULT_LANG', 'type' => 'select', 'options' => '$this->module->inst_language_select(\'{VALUE}\')', 'explain' => false),
- 'admin_name' => array('lang' => 'ADMIN_USERNAME', 'type' => 'text:25:100', 'explain' => true),
- 'admin_pass1' => array('lang' => 'ADMIN_PASSWORD', 'type' => 'password:25:100', 'explain' => true),
- 'admin_pass2' => array('lang' => 'ADMIN_PASSWORD_CONFIRM', 'type' => 'password:25:100', 'explain' => false),
- 'board_email' => array('lang' => 'CONTACT_EMAIL', 'type' => 'email:25:100', 'explain' => false),
- );
- var $advanced_config_options = array(
- 'legend1' => 'ACP_EMAIL_SETTINGS',
- 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true),
- 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true),
- 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false),
- 'smtp_auth' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'options' => '$this->module->mail_auth_select(\'{VALUE}\')', 'explain' => true),
- 'smtp_user' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')),
- 'smtp_pass' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')),
-
- 'legend2' => 'SERVER_URL_SETTINGS',
- 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:enabled_disabled', 'explain' => true),
- 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true),
- 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true),
- 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true),
- 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true),
- 'script_path' => array('lang' => 'SCRIPT_PATH', 'type' => 'text::255', 'explain' => true),
- );
-
- /**
- * Specific PHP modules we may require for certain optional or extended features
- */
- var $php_dlls_other = array('zlib', 'ftp', 'gd', 'xml');
-
- /**
- * A list of the web-crawlers/bots we recognise by default
- *
- * Candidates but not included:
- * 'Accoona [Bot]' 'Accoona-AI-Agent/'
- * 'ASPseek [Crawler]' 'ASPseek/'
- * 'Boitho [Crawler]' 'boitho.com-dc/'
- * 'Bunnybot [Bot]' 'powered by www.buncat.de'
- * 'Cosmix [Bot]' 'cfetch/'
- * 'Crawler Search [Crawler]' '.Crawler-Search.de'
- * 'Findexa [Crawler]' 'Findexa Crawler ('
- * 'GBSpider [Spider]' 'GBSpider v'
- * 'genie [Bot]' 'genieBot ('
- * 'Hogsearch [Bot]' 'oegp v. 1.3.0'
- * 'Insuranco [Bot]' 'InsurancoBot'
- * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler'
- * 'ISC Systems [Bot]' 'ISC Systems iRc Search'
- * 'Jyxobot [Bot]' 'Jyxobot/'
- * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/'
- * 'LinkWalker' 'LinkWalker'
- * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html'
- * 'Naver [Bot]' 'nhnbot@naver.com)'
- * 'NetResearchServer' 'NetResearchServer/'
- * 'Nimble [Crawler]' 'NimbleCrawler'
- * 'Ocelli [Bot]' 'Ocelli/'
- * 'Onsearch [Bot]' 'onCHECK-Robot'
- * 'Orange [Spider]' 'OrangeSpider'
- * 'Sproose [Bot]' 'http://www.sproose.com/bot'
- * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)'
- * 'Tbot [Bot]' 'Tbot/'
- * 'Thumbshots [Capture]' 'thumbshots-de-Bot'
- * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/'
- * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)'
- * 'WissenOnline [Bot]' 'WissenOnline-Bot'
- * 'WWWeasel [Bot]' 'WWWeasel Robot v'
- * 'Xaldon [Spider]' 'Xaldon WebSpider'
- */
- var $bot_list = array(
- 'AdsBot [Google]' => array('AdsBot-Google', ''),
- 'Alexa [Bot]' => array('ia_archiver', ''),
- 'Alta Vista [Bot]' => array('Scooter/', ''),
- 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
- 'Baidu [Spider]' => array('Baiduspider', ''),
- 'Bing [Bot]' => array('bingbot/', ''),
- 'Exabot [Bot]' => array('Exabot', ''),
- 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
- 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
- 'Francis [Bot]' => array('http://www.neomo.de/', ''),
- 'Gigabot [Bot]' => array('Gigabot/', ''),
- 'Google Adsense [Bot]' => array('Mediapartners-Google', ''),
- 'Google Desktop' => array('Google Desktop', ''),
- 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
- 'Google [Bot]' => array('Googlebot', ''),
- 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
- 'Heritrix [Crawler]' => array('heritrix/1.', ''),
- 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
- 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
- 'ichiro [Crawler]' => array('ichiro/', ''),
- 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
- 'Metager [Bot]' => array('MetagerBot/', ''),
- 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
- 'MSN [Bot]' => array('msnbot/', ''),
- 'MSNbot Media' => array('msnbot-media/', ''),
- 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
- 'Online link [Validator]' => array('online link validator', ''),
- 'psbot [Picsearch]' => array('psbot/0', ''),
- 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
- 'SEO Crawler' => array('SEO search Crawler/', ''),
- 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
- 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
- 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
- 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
- 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
- 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
- 'Voyager [Bot]' => array('voyager/', ''),
- 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
- 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
- 'W3C [Validator]' => array('W3C_Validator', ''),
- 'YaCy [Bot]' => array('yacybot', ''),
- 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
- 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
- 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
- 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
- );
-
- /**
- * Define the module structure so that we can populate the database without
- * needing to hard-code module_id values
- */
- var $module_categories = array(
- 'acp' => array(
- 'ACP_CAT_GENERAL' => array(
- 'ACP_QUICK_ACCESS',
- 'ACP_BOARD_CONFIGURATION',
- 'ACP_CLIENT_COMMUNICATION',
- 'ACP_SERVER_CONFIGURATION',
- ),
- 'ACP_CAT_FORUMS' => array(
- 'ACP_MANAGE_FORUMS',
- 'ACP_FORUM_BASED_PERMISSIONS',
- ),
- 'ACP_CAT_POSTING' => array(
- 'ACP_MESSAGES',
- 'ACP_ATTACHMENTS',
- ),
- 'ACP_CAT_USERGROUP' => array(
- 'ACP_CAT_USERS',
- 'ACP_GROUPS',
- 'ACP_USER_SECURITY',
- ),
- 'ACP_CAT_PERMISSIONS' => array(
- 'ACP_GLOBAL_PERMISSIONS',
- 'ACP_FORUM_BASED_PERMISSIONS',
- 'ACP_PERMISSION_ROLES',
- 'ACP_PERMISSION_MASKS',
- ),
- 'ACP_CAT_CUSTOMISE' => array(
- 'ACP_STYLE_MANAGEMENT',
- 'ACP_EXTENSION_MANAGEMENT',
- 'ACP_LANGUAGE',
- ),
- 'ACP_CAT_MAINTENANCE' => array(
- 'ACP_FORUM_LOGS',
- 'ACP_CAT_DATABASE',
- ),
- 'ACP_CAT_SYSTEM' => array(
- 'ACP_AUTOMATION',
- 'ACP_GENERAL_TASKS',
- 'ACP_MODULE_MANAGEMENT',
- ),
- 'ACP_CAT_DOT_MODS' => null,
- ),
- 'mcp' => array(
- 'MCP_MAIN' => null,
- 'MCP_QUEUE' => null,
- 'MCP_REPORTS' => null,
- 'MCP_NOTES' => null,
- 'MCP_WARN' => null,
- 'MCP_LOGS' => null,
- 'MCP_BAN' => null,
- ),
- 'ucp' => array(
- 'UCP_MAIN' => null,
- 'UCP_PROFILE' => null,
- 'UCP_PREFS' => null,
- 'UCP_PM' => null,
- 'UCP_USERGROUPS' => null,
- 'UCP_ZEBRA' => null,
- ),
- );
- var $module_categories_basenames = array(
- 'UCP_PM' => 'ucp_pm',
- );
-
- var $module_extras = array(
- 'acp' => array(
- 'ACP_QUICK_ACCESS' => array(
- 'ACP_MANAGE_USERS',
- 'ACP_GROUPS_MANAGE',
- 'ACP_MANAGE_FORUMS',
- 'ACP_MOD_LOGS',
- 'ACP_BOTS',
- 'ACP_PHP_INFO',
- ),
- 'ACP_FORUM_BASED_PERMISSIONS' => array(
- 'ACP_FORUM_PERMISSIONS',
- 'ACP_FORUM_PERMISSIONS_COPY',
- 'ACP_FORUM_MODERATORS',
- 'ACP_USERS_FORUM_PERMISSIONS',
- 'ACP_GROUPS_FORUM_PERMISSIONS',
- ),
- ),
- );
-}
diff --git a/phpBB/install/install_main.php b/phpBB/install/install_main.php
deleted file mode 100644
index d5874dac83..0000000000
--- a/phpBB/install/install_main.php
+++ /dev/null
@@ -1,78 +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.
-*
-*/
-
-/**
-*/
-
-if ( !defined('IN_INSTALL') )
-{
- // Someone has tried to access the file direct. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- $module[] = array(
- 'module_type' => 'install',
- 'module_title' => 'OVERVIEW',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 0,
- 'module_subs' => array('INTRO', 'LICENSE', 'SUPPORT'),
- 'module_stages' => '',
- 'module_reqs' => ''
- );
-}
-
-/**
-* Main Tab - Installation
-*/
-class install_main extends module
-{
- function install_main(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $lang, $template, $language;
-
- switch ($sub)
- {
- case 'intro' :
- $title = $lang['SUB_INTRO'];
- $body = $lang['OVERVIEW_BODY'];
- break;
-
- case 'license' :
- $title = $lang['GPL'];
- $body = implode("<br/>\n", file(__DIR__ . '/../docs/LICENSE.txt'));
- break;
-
- case 'support' :
- $title = $lang['SUB_SUPPORT'];
- $body = $lang['SUPPORT_BODY'];
- break;
- }
-
- $this->tpl_name = 'install_main';
- $this->page_title = $title;
-
- $template->assign_vars(array(
- 'TITLE' => $title,
- 'BODY' => $body,
-
- 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
- ));
- }
-}
diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php
deleted file mode 100644
index a00280a925..0000000000
--- a/phpBB/install/install_update.php
+++ /dev/null
@@ -1,1782 +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.
-*
-*/
-
-/**
-* @todo check for writable cache/store/files directory
-*/
-
-if (!defined('IN_INSTALL'))
-{
- // Someone has tried to access the file directly. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- // If phpBB is not installed we do not include this module
- if (!phpbb_check_installation_exists($phpbb_root_path, $phpEx) || file_exists($phpbb_root_path . 'cache/install_lock'))
- {
- return;
- }
-
- $module[] = array(
- 'module_type' => 'update',
- 'module_title' => 'UPDATE',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 30,
- 'module_subs' => '',
- 'module_stages' => array('INTRO', 'VERSION_CHECK', 'FILE_CHECK', 'UPDATE_FILES', 'UPDATE_DB'),
- 'module_reqs' => ''
- );
-}
-
-/**
-* Update Installation
-*/
-class install_update extends module
-{
- var $p_master;
- var $update_info;
-
- var $old_location;
- var $new_location;
- var $latest_version;
- var $current_version;
-
- var $update_to_version;
-
- // Set to false
- var $test_update = false;
-
- function install_update(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language;
- global $request, $phpbb_admin_path, $phpbb_adm_relative_path, $phpbb_container, $phpbb_config_php_file;
-
- // We must enable super globals, otherwise creating a new instance of the request class,
- // using the new container with a dbal connection will fail with the following PHP Notice:
- // Object of class phpbb_request_deactivated_super_global could not be converted to int
- $request->enable_super_globals();
-
- // Create a normal container now
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
- $phpbb_container_builder->set_dump_container(false);
- $phpbb_container_builder->set_use_extensions(false);
- if (file_exists($phpbb_root_path . 'install/update/new/config'))
- {
- $phpbb_container_builder->set_config_path($phpbb_root_path . 'install/update/new/config');
- }
- $phpbb_container = $phpbb_container_builder->get_container();
-
- // Writes into global $cache
- $cache = $phpbb_container->get('cache');
-
- $this->tpl_name = 'install_update';
- $this->page_title = 'UPDATE_INSTALLATION';
-
- $this->old_location = $phpbb_root_path . 'install/update/old/';
- $this->new_location = $phpbb_root_path . 'install/update/new/';
-
- // Init DB
- extract($phpbb_config_php_file->get_all());
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
-
- // Special options for conflicts/modified files
- define('MERGE_NO_MERGE_NEW', 1);
- define('MERGE_NO_MERGE_MOD', 2);
- define('MERGE_NEW_FILE', 3);
- define('MERGE_MOD_FILE', 4);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
-
- // Connect to DB
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
-
- // We do not need this any longer, unset for safety purposes
- unset($dbpasswd);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
-
- // Force template recompile
- $config['load_tplcompile'] = 1;
-
- // First of all, init the user session
- $user->session_begin();
- $auth->acl($user->data);
-
- // Overwrite user's language with the selected one.
- // Config needs to be changed to ensure that guests also get the selected language.
- $config_default_lang = $config['default_lang'];
- $config['default_lang'] = $language;
- $user->data['user_lang'] = $language;
-
- $user->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
-
- // Reset the default_lang
- $config['default_lang'] = $config_default_lang;
- unset($config_default_lang);
-
- // If we are within the intro page we need to make sure we get up-to-date version info
- if ($sub == 'intro')
- {
- $cache->destroy('_version_info');
- }
-
- // Set custom template again. ;)
- $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
- $paths = array_filter($paths, 'is_dir');
- $template->set_custom_style(array(
- array(
- 'name' => 'adm',
- 'ext_path' => 'adm/style/',
- ),
- ), $paths);
-
- $template->assign_vars(array(
- 'S_USER_LANG' => $user->lang['USER_LANG'],
- 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'],
- 'S_CONTENT_ENCODING' => 'UTF-8',
- 'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
- 'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
- ));
-
- // Get current and latest version
- $version_helper = $phpbb_container->get('version_helper');
- try
- {
- $this->latest_version = $version_helper->get_latest_on_current_branch(true);
- }
- catch (\RuntimeException $e)
- {
- $this->latest_version = false;
-
- $update_info = array();
- include($phpbb_root_path . 'install/update/index.' . $phpEx);
- $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
-
- if ($info !== false)
- {
- $this->latest_version = (!empty($info['version']['to'])) ? trim($info['version']['to']) : false;
- }
- }
-
- // For the current version we trick a bit. ;)
- $this->current_version = (!empty($config['version_update_from'])) ? $config['version_update_from'] : $config['version'];
-
- $up_to_date = (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->latest_version)), '<')) ? false : true;
-
- // Check for a valid update directory, else point the user to the phpbb.com website
- if (!file_exists($phpbb_root_path . 'install/update') || !file_exists($phpbb_root_path . 'install/update/index.' . $phpEx) || !file_exists($this->old_location) || !file_exists($this->new_location))
- {
- $template->assign_vars(array(
- 'S_ERROR' => true,
- 'ERROR_MSG' => ($up_to_date) ? $user->lang['NO_UPDATE_FILES_UP_TO_DATE'] : sprintf($user->lang['NO_UPDATE_FILES_OUTDATED'], $config['version'], $this->current_version, $this->latest_version))
- );
-
- return;
- }
-
- $this->update_info = $this->get_file('update_info');
-
- // Make sure the update directory holds the correct information
- // Since admins are able to run the update/checks more than once we only check if the current version is lower or equal than the version to which we update to.
- if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '>'))
- {
- $template->assign_vars(array(
- 'S_ERROR' => true,
- 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $config['version'], $this->update_info['version']['from'], $this->update_info['version']['to']))
- );
-
- return;
- }
-
- // Check if the update files are actually meant to update from the current version
- if ($this->current_version != $this->update_info['version']['from'])
- {
- $template->assign_vars(array(
- 'S_ERROR' => true,
- 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $this->current_version, $this->update_info['version']['from'], $this->update_info['version']['to']),
- ));
- }
-
- // Check if the update files stored are for the latest version...
- if (version_compare(strtolower($this->latest_version), strtolower($this->update_info['version']['to']), '>'))
- {
- $template->assign_vars(array(
- 'S_WARNING' => true,
- 'WARNING_MSG' => sprintf($user->lang['OLD_UPDATE_FILES'], $this->update_info['version']['from'], $this->update_info['version']['to'], $this->latest_version))
- );
- }
-
- // We store the "update to" version, because it is not always the latest. ;)
- $this->update_to_version = $this->update_info['version']['to'];
-
- // Fill DB version
- if (empty($config['dbms_version']))
- {
- set_config('dbms_version', $db->sql_server_info(true));
- }
-
- if ($this->test_update === false)
- {
- // What about the language file? Got it updated?
- if (in_array('language/' . $language . '/install.' . $phpEx, $this->update_info['files']))
- {
- $lang = array();
- include($this->new_location . 'language/' . $language . '/install.' . $phpEx);
- // this is the user's language.. just merge it
- $user->lang = array_merge($user->lang, $lang);
- }
- if ($language != 'en' && in_array('language/en/install.' . $phpEx, $this->update_info['files']))
- {
- $lang = array();
- include($this->new_location . 'language/en/install.' . $phpEx);
- // only add new keys to user's language in english
- $new_keys = array_diff(array_keys($lang), array_keys($user->lang));
- foreach ($new_keys as $i => $new_key)
- {
- $user->lang[$new_key] = $lang[$new_key];
- }
- }
- }
-
- // Include renderer and engine
- $this->include_file('includes/diff/diff.' . $phpEx);
- $this->include_file('includes/diff/engine.' . $phpEx);
- $this->include_file('includes/diff/renderer.' . $phpEx);
-
- // Make sure we stay at the file check if checking the files again
- if ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST))
- {
- $sub = $this->p_master->sub = 'file_check';
- }
-
- switch ($sub)
- {
- case 'intro':
- $this->page_title = 'UPDATE_INSTALLATION';
-
- $template->assign_vars(array(
- 'S_INTRO' => true,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=version_check"),
- ));
-
- // Make sure the update list is destroyed.
- $cache->destroy('_update_list');
- $cache->destroy('_update_list_time');
- $cache->destroy('_diff_files');
- $cache->destroy('_expected_files');
- break;
-
- case 'version_check':
- $this->page_title = 'STAGE_VERSION_CHECK';
-
- $template->assign_vars(array(
- 'S_VERSION_CHECK' => true,
-
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
-
- 'S_UP_TO_DATE' => $up_to_date,
- 'LATEST_VERSION' => $this->latest_version,
- 'CURRENT_VERSION' => $this->current_version,
- ));
-
- // Print out version the update package updates to
- if ($this->latest_version != $this->update_info['version']['to'])
- {
- $template->assign_var('PACKAGE_VERSION', $this->update_info['version']['to']);
- }
-
- // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
- // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
- // We now try to cope with this by triggering the update process
- if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<'))
- {
- $template->assign_vars(array(
- 'S_UP_TO_DATE' => false,
- ));
- }
-
- break;
-
- case 'update_db':
- // Redirect the user to the database update script with some explanations...
- $template->assign_vars(array(
- 'S_DB_UPDATE' => true,
- 'S_DB_UPDATE_FINISHED' => ($config['version'] == $this->update_info['version']['to']) ? true : false,
- 'U_DB_UPDATE' => append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=1&amp;language=' . $user->data['user_lang']),
- 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_db"),
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
- 'L_EVERYTHING_UP_TO_DATE' => $user->lang('EVERYTHING_UP_TO_DATE', append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'), append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login&amp;redirect=' . $phpbb_adm_relative_path . 'index.php%3Fi=send_statistics%26mode=send_statistics')),
- ));
-
- // Do not display incompatible package note after successful update
- if ($config['version'] == $this->update_info['version']['to'])
- {
- $template->assign_var('S_ERROR', false);
- }
- break;
-
- case 'file_check':
-
- // retrieve info on what changes should have already been made to the files.
- $expected_files = $cache->get('_expected_files');
- if (!$expected_files)
- {
- $expected_files = array();
- }
-
- // Now make sure the previous file collection is no longer valid...
- $cache->destroy('_diff_files');
-
- $this->page_title = 'STAGE_FILE_CHECK';
-
- // Now make sure our update list is correct if the admin refreshes
- $action = request_var('action', '');
-
- // We are directly within an update. To make sure our update list is correct we check its status.
- $update_list = ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST)) ? false : $cache->get('_update_list');
- $modified = ($update_list !== false) ? $cache->get('_update_list_time') : 0;
-
- // Make sure the list is up-to-date
- if ($update_list !== false)
- {
- $get_new_list = false;
- foreach ($this->update_info['files'] as $file)
- {
- if (file_exists($phpbb_root_path . $file) && filemtime($phpbb_root_path . $file) > $modified)
- {
- $get_new_list = true;
- break;
- }
- }
- }
- else
- {
- $get_new_list = true;
- }
-
- if (!$get_new_list && $update_list['status'] != -1)
- {
- $get_new_list = true;
- }
-
- if ($get_new_list)
- {
- $this->get_update_structure($update_list, $expected_files);
- $cache->put('_update_list', $update_list);
- $cache->put('_update_list_time', time());
-
- // Refresh the page if we are still not finished...
- if ($update_list['status'] != -1)
- {
- $refresh_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check");
- meta_refresh(2, $refresh_url);
-
- $template->assign_vars(array(
- 'S_IN_PROGRESS' => true,
- 'S_COLLECTED' => (int) $update_list['status'],
- 'S_TO_COLLECT' => sizeof($this->update_info['files']),
- 'L_IN_PROGRESS' => $user->lang['COLLECTING_FILE_DIFFS'],
- 'L_IN_PROGRESS_EXPLAIN' => sprintf($user->lang['NUMBER_OF_FILES_COLLECTED'], (int) $update_list['status'], sizeof($this->update_info['files']) + sizeof($this->update_info['deleted'])),
- ));
-
- return;
- }
- }
-
- if ($action == 'diff')
- {
- $this->show_diff($update_list);
- return;
- }
-
- if (sizeof($update_list['no_update']))
- {
- $template->assign_vars(array(
- 'S_NO_UPDATE_FILES' => true,
- 'NO_UPDATE_FILES' => implode(', ', array_map('htmlspecialchars', $update_list['no_update'])))
- );
- }
-
- $new_expected_files = array();
-
- // Now assign the list to the template
- foreach ($update_list as $status => $filelist)
- {
- if ($status == 'no_update' || !sizeof($filelist) || $status == 'status' || $status == 'status_deleted')
- {
- continue;
- }
-
-/* $template->assign_block_vars('files', array(
- 'S_STATUS' => true,
- 'STATUS' => $status,
- 'L_STATUS' => $user->lang['STATUS_' . strtoupper($status)],
- 'TITLE' => $user->lang['FILES_' . strtoupper($status)],
- 'EXPLAIN' => $user->lang['FILES_' . strtoupper($status) . '_EXPLAIN'],
- )
- );*/
-
- foreach ($filelist as $file_struct)
- {
- $s_binary = (!empty($this->update_info['binary']) && in_array($file_struct['filename'], $this->update_info['binary'])) ? true : false;
-
- $filename = htmlspecialchars($file_struct['filename']);
- if (strrpos($filename, '/') !== false)
- {
- $dir_part = substr($filename, 0, strrpos($filename, '/') + 1);
- $file_part = substr($filename, strrpos($filename, '/') + 1);
- }
- else
- {
- $dir_part = '';
- $file_part = $filename;
- }
-
- $diff_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check&amp;action=diff&amp;status=$status&amp;file=" . urlencode($file_struct['filename']));
-
- if (isset($file_struct['as_expected']) && $file_struct['as_expected'])
- {
- $new_expected_files[$file_struct['filename']] = $expected_files[$file_struct['filename']];
- }
- else
- {
- $template->assign_block_vars($status, array(
- 'STATUS' => $status,
-
- 'FILENAME' => $filename,
- 'DIR_PART' => $dir_part,
- 'FILE_PART' => $file_part,
- 'NUM_CONFLICTS' => (isset($file_struct['conflicts'])) ? $file_struct['conflicts'] : 0,
-
- 'S_CUSTOM' => ($file_struct['custom']) ? true : false,
- 'S_BINARY' => $s_binary,
- 'CUSTOM_ORIGINAL' => ($file_struct['custom']) ? $file_struct['original'] : '',
-
- 'U_SHOW_DIFF' => $diff_url,
- 'L_SHOW_DIFF' => ($status != 'up_to_date') ? $user->lang['SHOW_DIFF_' . strtoupper($status)] : '',
-
- 'U_VIEW_MOD_FILE' => $diff_url . '&amp;op=' . MERGE_MOD_FILE,
- 'U_VIEW_NEW_FILE' => $diff_url . '&amp;op=' . MERGE_NEW_FILE,
- 'U_VIEW_NO_MERGE_MOD' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_MOD,
- 'U_VIEW_NO_MERGE_NEW' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_NEW,
- ));
- }
- }
- }
-
- $cache->put('_expected_files', $new_expected_files);
-
- $all_up_to_date = true;
- foreach ($update_list as $status => $filelist)
- {
- if ($status != 'up_to_date' && $status != 'custom' && $status != 'status' && $status != 'status_deleted' && sizeof($filelist))
- {
- $all_up_to_date = false;
- break;
- }
- }
-
- $template->assign_vars(array(
- 'S_FILE_CHECK' => true,
- 'S_ALL_UP_TO_DATE' => $all_up_to_date,
- 'S_VERSION_UP_TO_DATE' => $up_to_date,
- 'S_UP_TO_DATE' => $up_to_date,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
- 'U_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
- 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_db"),
- ));
-
- // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
- // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
- // We now try to cope with this by triggering the update process
- if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<'))
- {
- $template->assign_vars(array(
- 'S_UP_TO_DATE' => false,
- ));
- }
-
- if ($all_up_to_date)
- {
- global $phpbb_container;
- $phpbb_log = $phpbb_container->get('log');
-
- // Add database update to log
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_PHPBB', time(), array($this->current_version, $this->update_to_version));
-
- $db->sql_return_on_error(true);
- $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
- $db->sql_return_on_error(false);
-
- $cache->purge();
- }
-
- break;
-
- case 'update_files':
-
- $this->page_title = 'STAGE_UPDATE_FILES';
-
- $s_hidden_fields = '';
- $params = array();
- $conflicts = request_var('conflict', array('' => 0));
- $modified = request_var('modified', array('' => 0));
-
- foreach ($conflicts as $filename => $merge_option)
- {
- $s_hidden_fields .= '<input type="hidden" name="conflict[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
- $params[] = 'conflict[' . urlencode($filename) . ']=' . urlencode($merge_option);
- }
-
- foreach ($modified as $filename => $merge_option)
- {
- if (!$merge_option)
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="modified[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
- $params[] = 'modified[' . urlencode($filename) . ']=' . urlencode($merge_option);
- }
-
- $no_update = request_var('no_update', array(0 => ''));
-
- foreach ($no_update as $index => $filename)
- {
- $s_hidden_fields .= '<input type="hidden" name="no_update[]" value="' . htmlspecialchars($filename) . '" />';
- $params[] = 'no_update[]=' . urlencode($filename);
- }
-
- // Before the user is choosing his preferred method, let's create the content list...
- $update_list = $cache->get('_update_list');
-
- if ($update_list === false)
- {
- trigger_error($user->lang['NO_UPDATE_INFO'], E_USER_ERROR);
- }
-
- // Check if the conflicts data is valid
- if (sizeof($conflicts))
- {
- $conflict_filenames = array();
- foreach ($update_list['conflict'] as $files)
- {
- $conflict_filenames[] = $files['filename'];
- }
-
- $new_conflicts = array();
- foreach ($conflicts as $filename => $diff_method)
- {
- if (in_array($filename, $conflict_filenames))
- {
- $new_conflicts[$filename] = $diff_method;
- }
- }
-
- $conflicts = $new_conflicts;
- }
-
- // Build list for modifications
- if (sizeof($modified))
- {
- $modified_filenames = array();
- foreach ($update_list['modified'] as $files)
- {
- $modified_filenames[] = $files['filename'];
- }
-
- $new_modified = array();
- foreach ($modified as $filename => $diff_method)
- {
- if (in_array($filename, $modified_filenames))
- {
- $new_modified[$filename] = $diff_method;
- }
- }
-
- $modified = $new_modified;
- }
-
- // Check number of conflicting files, they need to be equal. For modified files the number can differ
- if (sizeof($update_list['conflict']) != sizeof($conflicts))
- {
- trigger_error($user->lang['MERGE_SELECT_ERROR'], E_USER_ERROR);
- }
-
- // Before we do anything, let us diff the files and store the raw file information "somewhere"
- $get_files = false;
- $file_list = $cache->get('_diff_files');
- $expected_files = $cache->get('_expected_files');
-
- if ($file_list === false || $file_list['status'] != -1)
- {
- $get_files = true;
- }
-
- if ($get_files)
- {
- if ($file_list === false)
- {
- $file_list = array(
- 'status' => 0,
- );
- }
-
- if (!isset($expected_files) || $expected_files === false)
- {
- $expected_files = array();
- }
-
- $processed = 0;
- foreach ($update_list as $status => $files)
- {
- if (!is_array($files))
- {
- continue;
- }
-
- foreach ($files as $file_struct)
- {
- // Skip this file if the user selected to not update it
- if (in_array($file_struct['filename'], $no_update))
- {
- $expected_files[$file_struct['filename']] = false;
- continue;
- }
-
- // Already handled... then skip of course...
- if (isset($file_list[$file_struct['filename']]))
- {
- continue;
- }
-
- // Refresh if we reach 5 diffs...
- if ($processed >= 5)
- {
- $cache->put('_diff_files', $file_list);
-
- if ($request->variable('download', false))
- {
- $params[] = 'download=1';
- }
-
- $redirect_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files&amp;" . implode('&amp;', $params));
- meta_refresh(3, $redirect_url);
-
- $template->assign_vars(array(
- 'S_IN_PROGRESS' => true,
- 'L_IN_PROGRESS' => $user->lang['MERGING_FILES'],
- 'L_IN_PROGRESS_EXPLAIN' => $user->lang['MERGING_FILES_EXPLAIN'],
- ));
-
- return;
- }
-
- if (file_exists($phpbb_root_path . $file_struct['filename']))
- {
- $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
- if (isset($expected_files[$file_struct['filename']]) && md5($contents) == $expected_files[$file_struct['filename']])
- {
- continue;
- }
- }
-
- $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename'];
-
- switch ($status)
- {
- case 'modified':
-
- $option = (isset($modified[$file_struct['filename']])) ? $modified[$file_struct['filename']] : 0;
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- $contents = file_get_contents($this->new_location . $original_filename);
- break;
-
- case MERGE_NO_MERGE_MOD:
- $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
- break;
-
- default:
- $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
-
- $contents = implode("\n", $diff->merged_output());
- unset($diff);
- break;
- }
-
- $expected_files[$file_struct['filename']] = md5($contents);
- $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
- $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
-
- $file_list['status']++;
- $processed++;
-
- break;
-
- case 'conflict':
-
- $option = $conflicts[$file_struct['filename']];
- $contents = '';
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- $contents = file_get_contents($this->new_location . $original_filename);
- break;
-
- case MERGE_NO_MERGE_MOD:
- $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
- break;
-
- default:
-
- $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
-
- if ($option == MERGE_NEW_FILE)
- {
- $contents = implode("\n", $diff->merged_new_output());
- }
- else if ($option == MERGE_MOD_FILE)
- {
- $contents = implode("\n", $diff->merged_orig_output());
- }
- else
- {
- unset($diff);
- break 2;
- }
-
- unset($diff);
- break;
- }
-
- $expected_files[$file_struct['filename']] = md5($contents);
- $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
- $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
-
- $file_list['status']++;
- $processed++;
-
- break;
- }
- }
- }
- $cache->put('_expected_files', $expected_files);
- }
-
- $file_list['status'] = -1;
- $cache->put('_diff_files', $file_list);
-
- if ($request->variable('download', false))
- {
- $this->include_file('includes/functions_compress.' . $phpEx);
-
- $use_method = request_var('use_method', '');
- $methods = array('.tar');
-
- $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
- foreach ($available_methods as $type => $module)
- {
- if (!@extension_loaded($module))
- {
- continue;
- }
-
- $methods[] = $type;
- }
-
- // Let the user decide in which format he wants to have the pack
- if (!$use_method)
- {
- $this->page_title = 'SELECT_DOWNLOAD_FORMAT';
-
- $radio_buttons = '';
- foreach ($methods as $method)
- {
- $radio_buttons .= '<label><input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>';
- }
-
- $template->assign_vars(array(
- 'S_DOWNLOAD_FILES' => true,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
- 'RADIO_BUTTONS' => $radio_buttons,
- 'S_HIDDEN_FIELDS' => $s_hidden_fields)
- );
-
- // To ease the update process create a file location map
- $update_list = $cache->get('_update_list');
- $script_path = ($config['force_server_vars']) ? (($config['script_path'] == '/') ? '/' : $config['script_path'] . '/') : $user->page['root_script_path'];
-
- foreach ($update_list as $status => $files)
- {
- if ($status == 'up_to_date' || $status == 'no_update' || $status == 'status' || $status == 'status_deleted')
- {
- continue;
- }
-
- foreach ($files as $file_struct)
- {
- if (in_array($file_struct['filename'], $no_update))
- {
- continue;
- }
-
- $template->assign_block_vars('location', array(
- 'SOURCE' => htmlspecialchars($file_struct['filename']),
- 'DESTINATION' => $script_path . htmlspecialchars($file_struct['filename']),
- ));
- }
- }
- return;
- }
-
- if (!in_array($use_method, $methods))
- {
- $use_method = '.tar';
- }
-
- $update_mode = 'download';
- }
- else
- {
- $this->include_file('includes/functions_transfer.' . $phpEx);
-
- // Choose FTP, if not available use fsock...
- $method = basename(request_var('method', ''));
- $submit = (isset($_POST['submit'])) ? true : false;
- $test_ftp_connection = request_var('test_connection', '');
-
- if (!$method || !class_exists($method))
- {
- $method = 'ftp';
- $methods = transfer::methods();
-
- if (!in_array('ftp', $methods))
- {
- $method = $methods[0];
- }
- }
-
- $test_connection = false;
- if ($test_ftp_connection || $submit)
- {
- $transfer = new $method(
- request_var('host', ''),
- request_var('username', ''),
- htmlspecialchars_decode($request->untrimmed_variable('password', '')),
- request_var('root_path', ''),
- request_var('port', ''),
- request_var('timeout', '')
- );
- $test_connection = $transfer->open_session();
-
- // Make sure that the directory is correct by checking for the existence of common.php
- if ($test_connection === true)
- {
- // Check for common.php file
- if (!$transfer->file_exists($phpbb_root_path, 'common.' . $phpEx))
- {
- $test_connection = 'ERR_WRONG_PATH_TO_PHPBB';
- }
- }
-
- $transfer->close_session();
-
- // Make sure the login details are correct before continuing
- if ($submit && $test_connection !== true)
- {
- $submit = false;
- $test_ftp_connection = true;
- }
- }
-
- $s_hidden_fields .= build_hidden_fields(array('method' => $method));
-
- if (!$submit)
- {
- $this->page_title = 'SELECT_FTP_SETTINGS';
-
- if (!class_exists($method))
- {
- trigger_error('Method does not exist.', E_USER_ERROR);
- }
-
- $requested_data = call_user_func(array($method, 'data'));
- foreach ($requested_data as $data => $default)
- {
- $template->assign_block_vars('data', array(
- 'DATA' => $data,
- 'NAME' => $user->lang[strtoupper($method . '_' . $data)],
- 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'],
- 'DEFAULT' => $request->variable($data, (string) $default),
- ));
- }
-
- $template->assign_vars(array(
- 'S_CONNECTION_SUCCESS' => ($test_ftp_connection && $test_connection === true) ? true : false,
- 'S_CONNECTION_FAILED' => ($test_ftp_connection && $test_connection !== true) ? true : false,
- 'ERROR_MSG' => ($test_ftp_connection && $test_connection !== true) ? $user->lang[$test_connection] : '',
-
- 'S_FTP_UPLOAD' => true,
- 'UPLOAD_METHOD' => $method,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
- 'U_DOWNLOAD_METHOD' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files&amp;download=1"),
- 'S_HIDDEN_FIELDS' => $s_hidden_fields,
- ));
-
- return;
- }
-
- $update_mode = 'upload';
- }
-
- // Now update the installation or download the archive...
- $download_filename = 'update_' . $this->update_info['version']['from'] . '_to_' . $this->update_info['version']['to'];
- $archive_filename = $download_filename . '_' . time() . '_' . unique_id();
-
- // Now init the connection
- if ($update_mode == 'download')
- {
- if (function_exists('phpbb_is_writable') && !phpbb_is_writable($phpbb_root_path . 'store/'))
- {
- trigger_error(sprintf('The directory “%s†is not writable.', $phpbb_root_path . 'store/'), E_USER_ERROR);
- }
-
- if ($use_method == '.zip')
- {
- $compress = new compress_zip('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method);
- }
- else
- {
- $compress = new compress_tar('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method, $use_method);
- }
- }
- else
- {
- $transfer = new $method(
- request_var('host', ''),
- request_var('username', ''),
- htmlspecialchars_decode($request->untrimmed_variable('password', '')),
- request_var('root_path', ''),
- request_var('port', ''),
- request_var('timeout', '')
- );
- $transfer->open_session();
- }
-
- // Ok, go through the update list and do the operations based on their status
- foreach ($update_list as $status => $files)
- {
- if (!is_array($files))
- {
- continue;
- }
-
- foreach ($files as $file_struct)
- {
- // Skip this file if the user selected to not update it
- if (in_array($file_struct['filename'], $no_update))
- {
- continue;
- }
-
- $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename'];
-
- switch ($status)
- {
- case 'new':
- case 'new_conflict':
- case 'not_modified':
-
- if ($update_mode == 'download')
- {
- $compress->add_custom_file($this->new_location . $original_filename, $file_struct['filename']);
- }
- else
- {
- if ($status != 'new')
- {
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- }
-
- // New directory too?
- $dirname = dirname($file_struct['filename']);
-
- if ($dirname && !file_exists($phpbb_root_path . $dirname))
- {
- $transfer->make_dir($dirname);
- }
-
- $transfer->copy_file($this->new_location . $original_filename, $file_struct['filename']);
- }
- break;
-
- case 'modified':
-
- $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
-
- if ($update_mode == 'download')
- {
- $compress->add_data($contents, $file_struct['filename']);
- }
- else
- {
- // @todo add option to specify if a backup file should be created?
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- $transfer->write_file($file_struct['filename'], $contents);
- }
- break;
-
- case 'conflict':
-
- $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
-
- if ($update_mode == 'download')
- {
- $compress->add_data($contents, $file_struct['filename']);
- }
- else
- {
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- $transfer->write_file($file_struct['filename'], $contents);
- }
- break;
-
- case 'deleted':
-
- if ($update_mode != 'download')
- {
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- }
- break;
- }
- }
- }
-
- if ($update_mode == 'download')
- {
- $compress->close();
-
- $compress->download($archive_filename, $download_filename);
- @unlink($phpbb_root_path . 'store/' . $archive_filename . $use_method);
-
- exit;
- }
- else
- {
- $transfer->close_session();
-
- $template->assign_vars(array(
- 'S_UPLOAD_SUCCESS' => true,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"))
- );
- return;
- }
-
- break;
-
- }
- }
-
- /**
- * Show file diff
- */
- function show_diff(&$update_list)
- {
- global $phpbb_root_path, $template, $user, $phpbb_adm_relative_path;
-
- $this->tpl_name = 'install_update_diff';
-
- $this->page_title = 'VIEWING_FILE_DIFF';
-
- $status = request_var('status', '');
- $file = request_var('file', '');
- $diff_mode = request_var('diff_mode', 'inline');
-
- // First of all make sure the file is within our file update list with the correct status
- $found_entry = array();
- foreach ($update_list[$status] as $index => $file_struct)
- {
- if ($file_struct['filename'] === $file)
- {
- $found_entry = $update_list[$status][$index];
- }
- }
-
- if (empty($found_entry))
- {
- trigger_error($user->lang['FILE_DIFF_NOT_ALLOWED'], E_USER_ERROR);
- }
-
- // If the status is 'up_to_date' then we do not need to show a diff
- if ($status == 'up_to_date')
- {
- trigger_error($user->lang['FILE_ALREADY_UP_TO_DATE'], E_USER_ERROR);
- }
-
- $original_file = ($found_entry['custom']) ? $found_entry['original'] : $file;
-
- // Get the correct diff
- switch ($status)
- {
- case 'conflict':
- $option = request_var('op', 0);
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- case MERGE_NO_MERGE_MOD:
-
- $diff = $this->return_diff(array(), ($option == MERGE_NO_MERGE_NEW) ? $this->new_location . $original_file : $phpbb_root_path . $file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
-
- // Merge differences and use new phpBB code for conflicted blocks
- case MERGE_NEW_FILE:
- case MERGE_MOD_FILE:
-
- $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file);
-
- $template->assign_vars(array(
- 'S_DIFF_CONFLICT_FILE' => true,
- 'NUM_CONFLICTS' => $diff->get_num_conflicts())
- );
-
- $diff = $this->return_diff($phpbb_root_path . $file, ($option == MERGE_NEW_FILE) ? $diff->merged_new_output() : $diff->merged_orig_output());
- break;
-
- // Download conflict file
- default:
-
- $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file);
-
- header('Pragma: no-cache');
- header("Content-Type: application/octetstream; name=\"$file\"");
- header("Content-disposition: attachment; filename=$file");
-
- @set_time_limit(0);
-
- echo implode("\n", $diff->get_conflicts_content());
-
- flush();
- exit;
-
- break;
- }
-
- break;
-
- case 'modified':
- $option = request_var('op', 0);
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- case MERGE_NO_MERGE_MOD:
-
- $diff = $this->return_diff(array(), ($option == MERGE_NO_MERGE_NEW) ? $this->new_location . $original_file : $phpbb_root_path . $file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
-
- default:
- $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $original_file, $this->new_location . $file);
- $diff = $this->return_diff($phpbb_root_path . $file, $diff->merged_output());
- break;
- }
- break;
-
- case 'not_modified':
- case 'new_conflict':
- $diff = $this->return_diff($phpbb_root_path . $file, $this->new_location . $original_file);
- break;
-
- case 'new':
-
- $diff = $this->return_diff(array(), $this->new_location . $original_file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
-
- case 'deleted':
-
- $diff = $this->return_diff(array(), $phpbb_root_path . $original_file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
- }
-
- $diff_mode_options = '';
- foreach (array('side_by_side', 'inline', 'unified', 'raw') as $option)
- {
- $diff_mode_options .= '<option value="' . $option . '"' . (($diff_mode == $option) ? ' selected="selected"' : '') . '>' . $user->lang['DIFF_' . strtoupper($option)] . '</option>';
- }
-
- // Now the correct renderer
- $render_class = 'diff_renderer_' . $diff_mode;
-
- if (!class_exists($render_class))
- {
- trigger_error('Chosen diff mode is not supported', E_USER_ERROR);
- }
-
- $renderer = new $render_class();
-
- $template->assign_vars(array(
- 'DIFF_CONTENT' => $renderer->get_diff_content($diff),
- 'DIFF_MODE' => $diff_mode,
- 'S_DIFF_MODE_OPTIONS' => $diff_mode_options,
- 'S_SHOW_DIFF' => true,
- ));
-
- unset($diff, $renderer);
- }
-
- /**
- * Collect all file status infos we need for the update by diffing all files
- */
- function get_update_structure(&$update_list, $expected_files)
- {
- global $phpbb_root_path, $phpEx, $user;
-
- if ($update_list === false)
- {
- $update_list = array(
- 'up_to_date' => array(),
- 'new' => array(),
- 'not_modified' => array(),
- 'modified' => array(),
- 'new_conflict' => array(),
- 'conflict' => array(),
- 'no_update' => array(),
- 'deleted' => array(),
- 'status' => 0,
- 'status_deleted'=> 0,
- );
- }
-
- /* if (!empty($this->update_info['custom']))
- {
- foreach ($this->update_info['custom'] as $original_file => $file_ary)
- {
- foreach ($file_ary as $index => $file)
- {
- $this->make_update_diff($update_list, $original_file, $file, true);
- }
- }
- } */
-
- // Get a list of those files which are completely new by checking with file_exists...
- $num_bytes_processed = 0;
-
- foreach ($this->update_info['files'] as $index => $file)
- {
- if (is_int($update_list['status']) && $index < $update_list['status'])
- {
- continue;
- }
-
- if ($num_bytes_processed >= 500 * 1024)
- {
- return;
- }
-
- if (!file_exists($phpbb_root_path . $file))
- {
- // Make sure the update files are consistent by checking if the file is in new_files...
- if (!file_exists($this->new_location . $file))
- {
- trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
- }
-
- // If the file exists within the old directory the file got removed and we will write it back
- // not a biggie, but we might want to state this circumstance separately later.
- // if (file_exists($this->old_location . $file))
- // {
- // $update_list['removed'][] = $file;
- // }
-
- /* Only include a new file as new if the underlying path exist
- // The path normally do not exist if the original style or language has been removed
- if (file_exists($phpbb_root_path . dirname($file)))
- {
- $this->get_custom_info($update_list['new'], $file);
- $update_list['new'][] = array('filename' => $file, 'custom' => false);
- }
- else
- {
- // Do not include style-related or language-related content
- if (strpos($file, 'styles/') !== 0 && strpos($file, 'language/') !== 0)
- {
- $update_list['no_update'][] = $file;
- }
- }*/
-
- if (!phpbb_ignore_new_file_on_update($phpbb_root_path, $file))
- {
- $this->get_custom_info($update_list['new'], $file);
- $update_list['new'][] = array('filename' => $file, 'custom' => false);
- }
-
- // unset($this->update_info['files'][$index]);
- }
- else
- {
- // not modified?
- $this->make_update_diff($update_list, $file, $file, $expected_files);
- }
-
- $num_bytes_processed += (file_exists($this->new_location . $file)) ? filesize($this->new_location . $file) : 100 * 1024;
- $update_list['status']++;
- }
-
- foreach ($this->update_info['deleted'] as $index => $file)
- {
- if (is_int($update_list['status_deleted']) && $index < $update_list['status_deleted'])
- {
- continue;
- }
-
- if ($num_bytes_processed >= 500 * 1024)
- {
- return;
- }
-
- if (file_exists($phpbb_root_path . $file))
- {
- $update_list['deleted'][] = array('filename' => $file, 'custom' => false, 'as_expected' => false);
- $num_bytes_processed += filesize($phpbb_root_path . $file);
- }
-
- $update_list['status_deleted']++;
- $update_list['status']++;
- }
-
- $update_list['status_deleted'] = -1;
- $update_list['status'] = -1;
-
-/* if (!sizeof($this->update_info['files']))
- {
- return $update_list;
- }
-
- // Now diff the remaining files to get information about their status (not modified/modified/up-to-date)
-
- // not modified?
- foreach ($this->update_info['files'] as $index => $file)
- {
- $this->make_update_diff($update_list, $file, $file);
- }
-
- // Now to the styles...
- if (empty($this->update_info['custom']))
- {
- return $update_list;
- }
-
- foreach ($this->update_info['custom'] as $original_file => $file_ary)
- {
- foreach ($file_ary as $index => $file)
- {
- $this->make_update_diff($update_list, $original_file, $file, true);
- }
- }
-
- return $update_list;*/
- }
-
- /**
- * Compare files for storage in update_list
- */
- function make_update_diff(&$update_list, $original_file, $file, $expected_files, $custom = false)
- {
- global $phpbb_root_path, $user;
-
- $update_ary = array('filename' => $file, 'custom' => $custom, 'as_expected' => false);
-
- if ($custom)
- {
- $update_ary['original'] = $original_file;
- }
-
- if (file_exists($phpbb_root_path . $file))
- {
- $content = file_get_contents($phpbb_root_path . $file);
-
- if (isset($expected_files[$file]) && // the user already selected what to do with this file
- ($expected_files[$file] === false || // the user wanted this file to stay the same, so just assume it's alright
- $expected_files[$file] === md5($content)))
- {
- // the file contains what it was supposed to contain after the merge
- $update_ary['as_expected'] = true;
- $update_ary['was_ignored'] = ($expected_files[$file] === false);
- $update_list['up_to_date'][] = $update_ary;
-
- return;
- }
- }
-
- // we only want to know if the files are successfully merged and newlines could result in errors (duplicate addition of lines and such things)
- // Therefore we check for empty diffs with two methods, preserving newlines and not preserving them (which mostly works best, therefore the first option)
-
- // On a successfull update the new location file exists but the old one does not exist.
- // Check for this circumstance, the new file need to be up-to-date with the current file then...
- if (!file_exists($this->old_location . $original_file) && file_exists($this->new_location . $original_file) && file_exists($phpbb_root_path . $file))
- {
- $tmp = array(
- 'file1' => file_get_contents($this->new_location . $original_file),
- 'file2' => $content,
- );
-
- // We need to diff the contents here to make sure the file is really the one we expect
- $diff = new diff($tmp['file1'], $tmp['file2'], false);
- $empty = $diff->is_empty();
-
- unset($tmp, $diff);
-
- // if there are no differences we have an up-to-date file...
- if ($empty)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
-
- // If no other status matches we have another file in the way...
- $update_list['new_conflict'][] = $update_ary;
- return;
- }
-
- // Old file removed?
- if (file_exists($this->old_location . $original_file) && !file_exists($this->new_location . $original_file))
- {
- return;
- }
-
- // Check for existance, else abort immediately
- if (!file_exists($this->old_location . $original_file) || !file_exists($this->new_location . $original_file))
- {
- trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
- }
-
- $preserve_cr_ary = array(false, true);
-
- foreach ($preserve_cr_ary as $preserve_cr)
- {
- $tmp = array(
- 'file1' => file_get_contents($this->old_location . $original_file),
- 'file2' => $content,
- );
-
- // We need to diff the contents here to make sure the file is really the one we expect
- $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty_1 = $diff->is_empty();
-
- unset($tmp, $diff);
-
- $tmp = array(
- 'file1' => file_get_contents($this->new_location . $original_file),
- 'file2' => $content,
- );
-
- $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty_2 = $diff->is_empty();
-
- unset($tmp, $diff);
-
- // If the file is not modified we are finished here...
- if ($empty_1)
- {
- // Further check if it is already up to date - it could happen that non-modified files
- // slip through
- if ($empty_2)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
-
- $update_list['not_modified'][] = $update_ary;
- return;
- }
-
- // If the file had been modified then we need to check if it is already up to date
-
- // if there are no differences we have an up-to-date file...
- if ($empty_2)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
- }
-
- $conflicts = false;
-
- foreach ($preserve_cr_ary as $preserve_cr)
- {
- // if the file is modified we try to make sure a merge succeed
- $tmp = array(
- 'orig' => file_get_contents($this->old_location . $original_file),
- 'final1' => file_get_contents($phpbb_root_path . $file),
- 'final2' => file_get_contents($this->new_location . $original_file),
- );
-
- $diff = new diff3($tmp['orig'], $tmp['final1'], $tmp['final2'], $preserve_cr);
- unset($tmp);
-
- if (!$diff->get_num_conflicts())
- {
- $tmp = array(
- 'file1' => file_get_contents($phpbb_root_path . $file),
- 'file2' => implode("\n", $diff->merged_output()),
- );
-
- // now compare the merged output with the original file to see if the modified file is up to date
- $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty = $diff2->is_empty();
-
- unset($diff, $diff2);
-
- if ($empty)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
-
- // If we preserve cr tag it as modified because the conflict would not show in this mode anyway
- if ($preserve_cr)
- {
- $update_list['modified'][] = $update_ary;
- return;
- }
- }
- else
- {
- // There is one special case... users having merged with a conflicting file... we need to check this
- $tmp = array(
- 'file1' => file_get_contents($phpbb_root_path . $file),
- 'file2' => implode("\n", $diff->merged_new_output()),
- );
-
- $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty = $diff2->is_empty();
-
- if (!$empty)
- {
- unset($tmp, $diff2);
-
- // We check if the user merged with his output
- $tmp = array(
- 'file1' => file_get_contents($phpbb_root_path . $file),
- 'file2' => implode("\n", $diff->merged_orig_output()),
- );
-
- $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty = $diff2->is_empty();
- }
-
- if (!$empty)
- {
- $conflicts = $diff->get_num_conflicts();
- }
-
- unset($diff, $diff2);
-
- if ($empty)
- {
- // A conflict got resolved...
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
- }
- }
-
- if ($conflicts !== false)
- {
- $update_ary['conflicts'] = $conflicts;
- $update_list['conflict'][] = $update_ary;
- return;
- }
-
- // If no other status matches we have a modified file...
- $update_list['modified'][] = $update_ary;
- }
-
- /**
- * Update update_list with custom new files
- */
- function get_custom_info(&$update_list, $file)
- {
- if (empty($this->update_info['custom']))
- {
- return;
- }
-
- if (isset($this->update_info['custom'][$file]))
- {
- foreach ($this->update_info['custom'][$file] as $_file)
- {
- $update_list[] = array('filename' => $_file, 'custom' => true, 'original' => $file);
- }
- }
- }
-
- /**
- * Get remote file
- */
- function get_file($mode)
- {
- global $user, $db;
-
- $errstr = '';
- $errno = 0;
-
- switch ($mode)
- {
- case 'update_info':
- global $phpbb_root_path, $phpEx;
-
- $update_info = array();
- include($phpbb_root_path . 'install/update/index.' . $phpEx);
-
- $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
- $errstr = ($info === false) ? $user->lang['WRONG_INFO_FILE_FORMAT'] : '';
-
- if ($info !== false)
- {
- // We assume that all file extensions have been renamed to .$phpEx,
- // if someone is using a non .php file extension for php files.
- // However, in $update_info['files'] we use hardcoded .php.
- // We therefore replace .php with .$phpEx.
- $info['files'] = preg_replace('/\.php$/i', ".$phpEx", $info['files']);
-
- // Adjust the update info file to hold some specific style-related information
- $info['custom'] = array();
-/*
- // Get custom installed styles...
- $sql = 'SELECT style_name, style_path
- FROM ' . STYLES_TABLE . "
- WHERE LOWER(style_name) NOT IN ('subsilver2', 'prosilver')";
- $result = $db->sql_query($sql);
-
- $templates = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $templates[] = $row;
- }
- $db->sql_freeresult($result);
-
- if (sizeof($templates))
- {
- foreach ($info['files'] as $filename)
- {
- // Template update?
- if (strpos(strtolower($filename), 'styles/prosilver/template/') === 0)
- {
- foreach ($templates as $row)
- {
- $info['custom'][$filename][] = str_replace('/prosilver/', '/' . $row['style_path'] . '/', $filename);
- }
- }
- }
- }
-*/
- }
- break;
-
- default:
- trigger_error('Mode for getting remote file not specified', E_USER_ERROR);
- break;
- }
-
- if ($info === false)
- {
- trigger_error($errstr, E_USER_ERROR);
- }
-
- return $info;
- }
-
- /**
- * Function for including files...
- */
- function include_file($filename)
- {
- global $phpbb_root_path, $phpEx;
-
- if (!empty($this->update_info['files']) && in_array($filename, $this->update_info['files']))
- {
- include_once($this->new_location . $filename);
- }
- else
- {
- include_once($phpbb_root_path . $filename);
- }
- }
-
- /**
- * Wrapper for returning a diff object
- */
- function return_diff()
- {
- $args = func_get_args();
- $three_way_diff = (func_num_args() > 2) ? true : false;
-
- $file1 = array_shift($args);
- $file2 = array_shift($args);
-
- $tmp['file1'] = (!empty($file1) && is_string($file1)) ? file_get_contents($file1) : $file1;
- $tmp['file2'] = (!empty($file2) && is_string($file2)) ? file_get_contents($file2) : $file2;
-
- if ($three_way_diff)
- {
- $file3 = array_shift($args);
- $tmp['file3'] = (!empty($file3) && is_string($file3)) ? file_get_contents($file3) : $file3;
-
- $diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3']);
- }
- else
- {
- $diff = new diff($tmp['file1'], $tmp['file2']);
- }
-
- unset($tmp);
-
- return $diff;
- }
-}
diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php
new file mode 100755
index 0000000000..3803fe7034
--- /dev/null
+++ b/phpBB/install/phpbbcli.php
@@ -0,0 +1,52 @@
+#!/usr/bin/env php
+<?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.
+*
+*/
+
+use Symfony\Component\Console\Input\ArgvInput;
+
+if (php_sapi_name() !== 'cli')
+{
+ echo 'This program must be run from the command line.' . PHP_EOL;
+ exit(1);
+}
+
+define('IN_PHPBB', true);
+define('IN_INSTALL', true);
+define('PHPBB_ENVIRONMENT', 'production');
+define('PHPBB_VERSION', '3.2.0-RC1');
+$phpbb_root_path = __DIR__ . '/../';
+$phpEx = substr(strrchr(__FILE__, '.'), 1);
+
+//
+// Let's do the common.php logic
+//
+$startup_new_path = $phpbb_root_path . 'install/update/update/new/install/startup.' . $phpEx;
+$startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install/startup.' . $phpEx;
+require($startup_path);
+
+$input = new ArgvInput();
+
+// Enable superglobals for cli support
+$phpbb_installer_container->get('request')->enable_super_globals();
+
+/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */
+$phpbb_filesystem = $phpbb_installer_container->get('filesystem');
+
+/** @var \phpbb\language\language $language */
+$language = $phpbb_installer_container->get('language');
+$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting', 'cli'));
+
+$application = new \phpbb\console\application('phpBB Installer', PHPBB_VERSION, $language);
+$application->setDispatcher($phpbb_installer_container->get('dispatcher'));
+$application->register_container_commands($phpbb_installer_container->get('console.installer.command_collection'));
+$application->run($input);
diff --git a/phpBB/install/phpinfo.php b/phpBB/install/phpinfo.php
deleted file mode 100644
index 1512b00563..0000000000
--- a/phpBB/install/phpinfo.php
+++ /dev/null
@@ -1,14 +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.
-*
-*/
-
-phpinfo();
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
index 3449829d8c..0cff26977e 100644
--- a/phpBB/install/schemas/schema_data.sql
+++ b/phpBB/install/schemas/schema_data.sql
@@ -41,6 +41,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_pm', '1'
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_smilies', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_smilies', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_topic_notify', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allowed_schemes_links', 'http,https,ftp');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('assets_version', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('attachment_quota', '52428800');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_bbcode_pm', '1');
@@ -107,6 +108,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_si
INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20');
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');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_pm_icons', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_post_confirm', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_enable', '1');
@@ -237,6 +239,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_interval', '
INSERT INTO phpbb_config (config_name, config_value) VALUES ('ranks_path', 'images/ranks');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_expire_days', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_gc', '86400');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('remote_upload_verify', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('script_path', '');
@@ -273,7 +276,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.1.10');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-RC2-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');
@@ -309,6 +312,7 @@ INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin
# -- Forum related auth options
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_', 1);
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce_global', 1);
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_attach', 1);
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bbcode', 1);
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bump', 1);
@@ -552,7 +556,7 @@ INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT
INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 14, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%';
# Standard Access (f_)
-INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock');
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock');
# No Access (f_)
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_';
@@ -561,20 +565,20 @@ 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 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');
# 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_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg');
+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');
# 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_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove');
+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');
INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove');
# Standard Access + Polls (f_)
-INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock');
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock');
# Limited Access + Polls (f_)
-INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg');
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg');
# New Member (u_)
INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group', 'u_chgprofileinfo');
@@ -716,10 +720,7 @@ INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mo
INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('ARCHIVES', 0, 1, 1, '', 0, '');
INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('PLAIN_TEXT', 0, 0, 1, '', 0, '');
INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOCUMENTS', 0, 0, 1, '', 0, '');
-INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('REAL_MEDIA', 3, 0, 1, '', 0, '');
-INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('WINDOWS_MEDIA', 2, 0, 1, '', 0, '');
INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('FLASH_FILES', 5, 0, 1, '', 0, '');
-INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('QUICKTIME_MEDIA', 6, 0, 1, '', 0, '');
INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOWNLOADABLE_FILES', 0, 0, 1, '', 0, '');
# -- extensions
@@ -776,27 +777,13 @@ INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ods');
INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odt');
INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'rtf');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'rm');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'ram');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'swf');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wma');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wmv');
-
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (7, 'swf');
-
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mov');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4v');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4a');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mp4');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3gp');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3g2');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'qt');
-
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpeg');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpg');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mp3');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogg');
-INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'mp3');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'mpeg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'mpg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'ogg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'ogm');
# Add default profile fields
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_location', 'profilefields.type.string', 'phpbb_location', '20', '2', '100', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, '', '');
@@ -805,7 +792,6 @@ INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_len
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_occupation', 'profilefields.type.text', 'phpbb_occupation', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, '', '');
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_aol', 'profilefields.type.string', 'phpbb_aol', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 5, 1, '', '');
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_icq', 'profilefields.type.string', 'phpbb_icq', '20', '3', '15', '', '', '[0-9]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 6, 1, 'SEND_ICQ_MESSAGE', 'https://www.icq.com/people/%s/');
-INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_wlm', 'profilefields.type.string', 'phpbb_wlm', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 7, 1, '', '');
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_yahoo', 'profilefields.type.string', 'phpbb_yahoo', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 8, 1, 'SEND_YIM_MESSAGE', 'ymsgr:sendim?%s');
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_facebook', 'profilefields.type.string', 'phpbb_facebook', '20', '5', '50', '', '', '[\w.]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 9, 1, 'VIEW_FACEBOOK_PROFILE', 'http://facebook.com/%s/');
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_twitter', 'profilefields.type.string', 'phpbb_twitter', '20', '1', '15', '', '', '[\w_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 10, 1, 'VIEW_TWITTER_PROFILE', 'http://twitter.com/%s');
@@ -814,9 +800,9 @@ INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_len
INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_googleplus', 'profilefields.type.googleplus', 'phpbb_googleplus', '20', '3', '255', '', '', '[\w]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 13, 1, 'VIEW_GOOGLEPLUS_PROFILE', 'http://plus.google.com/%s');
# User Notification Options (for first user)
-INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, '');
+INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.board');
INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.email');
-INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, '');
+INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.board');
INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.email');
# POSTGRES COMMIT #
diff --git a/phpBB/install/startup.php b/phpBB/install/startup.php
new file mode 100644
index 0000000000..9a4f9bfe39
--- /dev/null
+++ b/phpBB/install/startup.php
@@ -0,0 +1,143 @@
+<?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.
+ *
+ */
+
+/** @ignore */
+if (!defined('IN_PHPBB') || !defined('IN_INSTALL'))
+{
+ exit;
+}
+
+function phpbb_require_updated($path, $phpbb_root_path, $optional = false)
+{
+ $new_path = $phpbb_root_path . 'install/update/new/' . $path;
+ $old_path = $phpbb_root_path . $path;
+
+ if (file_exists($new_path))
+ {
+ require($new_path);
+ }
+ else if (!$optional || file_exists($old_path))
+ {
+ require($old_path);
+ }
+}
+
+function phpbb_include_updated($path, $phpbb_root_path, $optional = false)
+{
+ $new_path = $phpbb_root_path . 'install/update/new/' . $path;
+ $old_path = $phpbb_root_path . $path;
+
+ if (file_exists($new_path))
+ {
+ include($new_path);
+ }
+ else if (!$optional || file_exists($old_path))
+ {
+ include($old_path);
+ }
+}
+
+function installer_msg_handler($errno, $msg_text, $errfile, $errline)
+{
+ global $phpbb_installer_container;
+
+ if (error_reporting() == 0)
+ {
+ return true;
+ }
+
+ switch ($errno)
+ {
+ case E_NOTICE:
+ case E_WARNING:
+ case E_USER_WARNING:
+ case E_USER_NOTICE:
+ $msg = '[phpBB Debug] "' . $msg_text . '" in file ' . $errfile . ' on line ' . $errline;
+
+ if (!empty($phpbb_installer_container))
+ {
+ try
+ {
+ /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
+ $iohandler = $phpbb_installer_container->get('installer.helper.iohandler');
+ $iohandler->add_warning_message($msg);
+ }
+ catch (\phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception $e)
+ {
+ print($msg);
+ }
+ }
+ else
+ {
+ print($msg);
+ }
+
+ return;
+ break;
+ case E_USER_ERROR:
+ $msg = '<b>General Error:</b><br />' . $msg_text . '<br /> in file ' . $errfile . ' on line ' . $errline;
+
+ $backtrace = get_backtrace();
+ if ($backtrace)
+ {
+ $msg .= '<br /><br />BACKTRACE<br />' . $backtrace;
+ }
+
+ throw new \phpbb\exception\runtime_exception($msg);
+ break;
+ case E_DEPRECATED:
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+phpbb_require_updated('includes/startup.' . $phpEx, $phpbb_root_path);
+phpbb_require_updated('phpbb/class_loader.' . $phpEx, $phpbb_root_path);
+
+$phpbb_class_loader_new = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}install/update/new/phpbb/", $phpEx);
+$phpbb_class_loader_new->register();
+$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
+$phpbb_class_loader->register();
+$phpbb_class_loader = new \phpbb\class_loader('phpbb\\convert\\', "{$phpbb_root_path}install/convert/", $phpEx);
+$phpbb_class_loader->register();
+$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
+$phpbb_class_loader_ext->register();
+
+// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
+$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
+$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
+
+// Include files
+phpbb_require_updated('includes/functions.' . $phpEx, $phpbb_root_path);
+phpbb_require_updated('includes/functions_content.' . $phpEx, $phpbb_root_path);
+phpbb_include_updated('includes/functions_compatibility.' . $phpEx, $phpbb_root_path);
+phpbb_require_updated('includes/functions_user.' . $phpEx, $phpbb_root_path);
+phpbb_require_updated('includes/utf/utf_tools.' . $phpEx, $phpbb_root_path);
+
+// Set PHP error handler to ours
+set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'installer_msg_handler');
+
+$phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+$phpbb_installer_container_builder
+ ->with_environment('installer')
+ ->without_extensions();
+
+$other_config_path = $phpbb_root_path . 'install/update/new/config';
+$config_path = (file_exists($other_config_path . '/installer/config.yml')) ? $other_config_path : $phpbb_root_path . 'config';
+
+$phpbb_installer_container = $phpbb_installer_container_builder
+ ->with_config_path($config_path)
+ ->with_custom_parameters(array('cache.driver.class' => 'phpbb\cache\driver\file'))
+ ->get_container();
diff --git a/phpBB/language/en/acp/attachments.php b/phpBB/language/en/acp/attachments.php
index 7d3d93d693..20264536ff 100644
--- a/phpBB/language/en/acp/attachments.php
+++ b/phpBB/language/en/acp/attachments.php
@@ -70,9 +70,6 @@ $lang = array_merge($lang, array(
'CAT_FLASH_FILES' => 'Flash files',
'CAT_IMAGES' => 'Images',
- 'CAT_QUICKTIME_FILES' => 'Quicktime media files',
- 'CAT_RM_FILES' => 'RealMedia media files',
- 'CAT_WM_FILES' => 'Windows Media media files',
'CHECK_CONTENT' => 'Check attachment files',
'CHECK_CONTENT_EXPLAIN' => 'Some browsers can be tricked to assume an incorrect mimetype for uploaded files. This option ensures that such files likely to cause this are rejected.',
'CREATE_GROUP' => 'Create new group',
@@ -105,9 +102,6 @@ $lang = array_merge($lang, array(
'EXT_GROUP_FLASH_FILES' => 'Flash Files',
'EXT_GROUP_IMAGES' => 'Images',
'EXT_GROUP_PLAIN_TEXT' => 'Plain Text',
- 'EXT_GROUP_QUICKTIME_MEDIA' => 'Quicktime Media',
- 'EXT_GROUP_REAL_MEDIA' => 'Real Media',
- 'EXT_GROUP_WINDOWS_MEDIA' => 'Windows Media',
'FILES_GONE' => 'Some of the attachments you selected for deletion do not exist. They may have been already deleted. Attachments that did exist were deleted.',
'FILES_STATS_WRONG' => 'Your file statistics are likely inaccurate and need to be resynchronised. Actual values: number of attachments = %1$d, total size of attachments = %2$s.<br />Click %3$shere%4$s to resynchronise them.',
diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php
index 8b4db6a061..e3d8e6742f 100644
--- a/phpBB/language/en/acp/board.php
+++ b/phpBB/language/en/acp/board.php
@@ -99,6 +99,7 @@ $lang = array_merge($lang, array(
'ALLOW_TOPIC_NOTIFY' => 'Allow subscribing to topics',
'BOARD_PM' => 'Private messaging',
'BOARD_PM_EXPLAIN' => 'Enable private messaging for all users.',
+ 'ALLOW_BOARD_NOTIFICATIONS' => 'Allow board notifications',
));
// Avatar Settings
@@ -534,6 +535,8 @@ $lang = array_merge($lang, array(
'REFERRER_VALID_EXPLAIN' => 'If enabled, the referrer of POST requests will be checked against the host/script path settings. This may cause issues with boards using several domains and or external logins.',
'TPL_ALLOW_PHP' => 'Allow php in templates',
'TPL_ALLOW_PHP_EXPLAIN' => 'If this option is enabled, <code>PHP</code> and <code>INCLUDEPHP</code> statements will be recognised and parsed in templates.',
+ 'UPLOAD_CERT_VALID' => 'Validate upload certificate',
+ 'UPLOAD_CERT_VALID_EXPLAIN' => 'If enabled, certificates of remote uploads will be validated. This requires the CA bundle to be defined by the <samp>openssl.cafile</samp> or <samp>curl.cainfo</samp> setting in your php.ini.',
));
// Email Settings
@@ -558,6 +561,8 @@ $lang = array_merge($lang, array(
'EMAIL_SIG_EXPLAIN' => 'This text will be attached to all emails the board sends.',
'ENABLE_EMAIL' => 'Enable board-wide emails',
'ENABLE_EMAIL_EXPLAIN' => 'If this is set to disabled no emails will be sent by the board at all. <em>Note the user and admin account activation settings require this setting to be enabled. If currently using “user†or “admin†activation in the activation settings, disabling this setting will disable registration.</em>',
+ '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_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',
@@ -574,6 +579,7 @@ $lang = array_merge($lang, array(
'SMTP_SETTINGS' => 'SMTP settings',
'SMTP_USERNAME' => 'SMTP username',
'SMTP_USERNAME_EXPLAIN' => 'Only enter a username if your SMTP server requires it.',
+ '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.',
));
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index 88e60d00a3..f30d1e7198 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -225,12 +225,26 @@ $lang = array_merge($lang, array(
'BACK' => 'Back',
+ 'CANNOT_CHANGE_FILE_GROUP' => 'Unable to change file group',
+ 'CANNOT_CHANGE_FILE_PERMISSIONS' => 'Unable to change file permissions',
+ 'CANNOT_COPY_FILES' => 'Unable to copy files',
+ 'CANNOT_CREATE_SYMLINK' => 'Unable to create a symlink',
+ 'CANNOT_DELETE_FILES' => 'Unable to delete files from the system',
+ 'CANNOT_DUMP_FILE' => 'Unable to dump file',
+ 'CANNOT_MIRROR_DIRECTORY' => 'Unable to mirror directory',
+ 'CANNOT_RENAME_FILE' => 'Unable to rename a file from the system',
+ 'CANNOT_TOUCH_FILES' => 'Unable to determine if the file exists',
+
+ 'CONTAINER_EXCEPTION' => 'phpBB encountered an error building the container due to an installed extension. For this reason, all extensions have been temporarily disabled. Please try purging your forum cache. All extensions will automatically be re-enabled once the container error is resolved. If this error continues, please visit <a href="https://www.phpbb.com/support">phpBB.com</a> for support.',
+ 'EXCEPTION' => 'Exception',
+
'COLOUR_SWATCH' => 'Web-safe colour swatch',
'CONFIG_UPDATED' => 'Configuration updated successfully.',
'CRON_LOCK_ERROR' => 'Could not obtain cron lock.',
'CRON_NO_SUCH_TASK' => 'Could not find cron task “%sâ€.',
'CRON_NO_TASK' => 'No cron tasks need to be run right now.',
'CRON_NO_TASKS' => 'No cron tasks could be found.',
+ 'CURRENT_VERSION' => 'Current version',
'DEACTIVATE' => 'Deactivate',
'DIRECTORY_DOES_NOT_EXIST' => 'The entered path “%s†does not exist.',
@@ -256,6 +270,7 @@ $lang = array_merge($lang, array(
'IP' => 'User IP',
'IP_HOSTNAME' => 'IP addresses or hostnames',
+ 'LATEST_VERSION' => 'Latest version',
'LOAD_NOTIFICATIONS' => 'Display Notifications',
'LOAD_NOTIFICATIONS_EXPLAIN' => 'Display the notifications list on every page (typically in the header).',
'LOGGED_IN_AS' => 'You are logged in as:',
@@ -288,7 +303,9 @@ $lang = array_merge($lang, array(
'PERMISSIONS_TRANSFERRED_EXPLAIN' => 'You currently have the permissions from %1$s. You are able to browse the board with this user’s permissions, but not access the administration control panel since admin permissions were not transferred. You can <a href="%2$s"><strong>revert to your permission set</strong></a> at any time.',
'PROCEED_TO_ACP' => '%sProceed to the ACP%s',
+ 'RELEASE_ANNOUNCEMENT' => 'Announcement',
'REMIND' => 'Remind',
+ 'REPARSE_LOCK_ERROR' => 'Reparsing is already in progress by another process.',
'RESYNC' => 'Resynchronise',
'RUNNING_TASK' => 'Running task: %s.',
@@ -420,6 +437,11 @@ $lang = array_merge($lang, array(
'VALUE' => 'Value',
'VERSIONCHECK_FAIL' => 'Failed to obtain latest version information.',
'VERSIONCHECK_FORCE_UPDATE' => 'Re-Check version',
+ 'VERSION_CHECK' => 'Version check',
+ 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.',
+ 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.<br />Below is a link to the release announcement, which contains more information as well as instructions on updating.',
+ 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.',
+ 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.',
'VIEW_ADMIN_LOG' => 'View administrator log',
'VIEW_INACTIVE_USERS' => 'View inactive users',
diff --git a/phpBB/language/en/acp/groups.php b/phpBB/language/en/acp/groups.php
index a7700ed681..9d0bb5f8b9 100644
--- a/phpBB/language/en/acp/groups.php
+++ b/phpBB/language/en/acp/groups.php
@@ -83,7 +83,7 @@ $lang = array_merge($lang, array(
'GROUP_MEMBERS' => 'Group members',
'GROUP_MEMBERS_EXPLAIN' => 'This is a complete listing of all the members of this usergroup. It includes separate sections for leaders, pending and existing members. From here you can manage all aspects of who has membership of this group and what their role is. To remove a leader but keep them in the group use Demote rather than delete. Similarly use Promote to make an existing member a leader.',
'GROUP_MESSAGE_LIMIT' => 'Group private message limit per folder',
- 'GROUP_MESSAGE_LIMIT_EXPLAIN' => 'This setting overrides the per-user folder message limit. A value of 0 means the user default limit will be used.',
+ 'GROUP_MESSAGE_LIMIT_EXPLAIN' => 'This setting overrides the per-user folder message limit. 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_MODS_ADDED' => 'New group leaders added successfully.',
'GROUP_MODS_DEMOTED' => 'Group leaders demoted successfully.',
'GROUP_MODS_PROMOTED' => 'Group members promoted successfully.',
@@ -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. If 0 is entered, the board-wide setting is used.',
+ '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',
@@ -130,6 +130,8 @@ $lang = array_merge($lang, array(
'NO_USERS_ADDED' => 'No users were added to the group.',
'NO_VALID_USERS' => 'You haven’t entered any users eligible for that action.',
+ 'PENDING_MEMBERS' => 'Pending',
+
'SELECT_GROUP' => 'Select a group',
'SPECIAL_GROUPS' => 'Pre-defined groups',
'SPECIAL_GROUPS_EXPLAIN' => 'Pre-defined groups are special groups, they cannot be deleted or directly modified. However you can still add users and alter basic settings.',
diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php
index 2e80e61adc..f986eced38 100644
--- a/phpBB/language/en/acp/permissions_phpbb.php
+++ b/phpBB/language/en/acp/permissions_phpbb.php
@@ -120,6 +120,7 @@ $lang = array_merge($lang, array(
'ACL_F_POST' => 'Can start new topics',
'ACL_F_STICKY' => 'Can post stickies',
'ACL_F_ANNOUNCE' => 'Can post announcements',
+ 'ACL_F_ANNOUNCE_GLOBAL' => 'Can post global announcements',
'ACL_F_REPLY' => 'Can reply to topics',
'ACL_F_EDIT' => 'Can edit own posts',
'ACL_F_DELETE' => 'Can permanently delete own posts',
diff --git a/phpBB/language/en/captcha_recaptcha.php b/phpBB/language/en/captcha_recaptcha.php
index df2ad4e51b..0acf850043 100644
--- a/phpBB/language/en/captcha_recaptcha.php
+++ b/phpBB/language/en/captcha_recaptcha.php
@@ -40,13 +40,13 @@ $lang = array_merge($lang, array(
'RECAPTCHA_LANG' => 'en',
'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 visual confirmation code you submitted was incorrect',
+ 'RECAPTCHA_INCORRECT' => 'The solution you provided was incorrect',
+ 'RECAPTCHA_NOSCRIPT' => 'Please enable JavaScript in your browser to load the challenge.',
'RECAPTCHA_PUBLIC' => 'Public reCaptcha key',
'RECAPTCHA_PUBLIC_EXPLAIN' => 'Your public reCaptcha key. Keys can be obtained on <a href="http://www.google.com/recaptcha">www.google.com/recaptcha</a>.',
'RECAPTCHA_PRIVATE' => 'Private reCaptcha key',
'RECAPTCHA_PRIVATE_EXPLAIN' => 'Your private reCaptcha key. Keys can be obtained on <a href="http://www.google.com/recaptcha">www.google.com/recaptcha</a>.',
- 'RECAPTCHA_EXPLAIN' => 'In an effort to prevent automatic submissions, we require that you type the text displayed into the field underneath.',
- 'RECAPTCHA_SOCKET_ERROR' => 'There was a problem connecting to the RECAPTCHA service: could not open socket. Try again later.',
+ 'RECAPTCHA_EXPLAIN' => 'In an effort to prevent automatic submissions, we require that you complete the following challenge.',
));
diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php
index 6989f26f72..db4b5f9ec6 100644
--- a/phpBB/language/en/cli.php
+++ b/phpBB/language/en/cli.php
@@ -50,7 +50,9 @@ $lang = array_merge($lang, array(
'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.',
'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.',
'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run',
+ 'CLI_DESCRIPTION_DB_LIST' => 'List all installed and available migrations.',
'CLI_DESCRIPTION_DB_MIGRATE' => 'Updates the database by applying migrations.',
+ 'CLI_DESCRIPTION_DB_REVERT' => 'Revert a migration.',
'CLI_DESCRIPTION_DELETE_CONFIG' => 'Deletes a configuration option',
'CLI_DESCRIPTION_DISABLE_EXTENSION' => 'Disables the specified extension.',
'CLI_DESCRIPTION_ENABLE_EXTENSION' => 'Enables the specified extension.',
@@ -58,13 +60,43 @@ $lang = array_merge($lang, array(
'CLI_DESCRIPTION_GET_CONFIG' => 'Gets a configuration option’s value',
'CLI_DESCRIPTION_INCREMENT_CONFIG' => 'Increments a configuration option’s integer value',
'CLI_DESCRIPTION_LIST_EXTENSIONS' => 'Lists all extensions in the database and on the filesystem.',
+
+ 'CLI_DESCRIPTION_OPTION_ENV' => 'The Environment name.',
'CLI_DESCRIPTION_OPTION_SAFE_MODE' => 'Run in Safe Mode (without extensions).',
'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.',
+
'CLI_DESCRIPTION_PURGE_EXTENSION' => 'Purges the specified extension.',
+ 'CLI_DESCRIPTION_REPARSER_LIST' => 'Lists the types of text that can be reparsed.',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE' => 'Reparses stored text with the current text_formatter services.',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1' => 'Type of text to reparse. Leave blank to reparse everything.',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN' => 'Do not save any changes; just print what would happen',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN' => 'Lowest record ID to process',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX' => 'Highest record ID to process',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE' => 'Approximate number of records to process at a time',
+ 'CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RESUME' => 'Start reparsing where the last execution stopped',
'CLI_DESCRIPTION_RECALCULATE_EMAIL_HASH' => 'Recalculates the user_email_hash column of the users table.',
'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value',
'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value',
+ 'CLI_DESCRIPTION_THUMBNAIL_DELETE' => 'Delete all existing thumbnails.',
+ 'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.',
+ 'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.',
+
+ 'CLI_DESCRIPTION_USER_ACTIVATE' => 'Activate (or deactivate) a user account.',
+ 'CLI_DESCRIPTION_USER_ACTIVATE_USERNAME' => 'Username of the account to activate.',
+ 'CLI_DESCRIPTION_USER_ACTIVATE_DEACTIVATE' => 'Deactivate the user’s account',
+ 'CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE' => 'The user is already active.',
+ 'CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE' => 'The user is already inactive.',
+ 'CLI_DESCRIPTION_USER_ADD' => 'Add a new user.',
+ 'CLI_DESCRIPTION_USER_ADD_OPTION_USERNAME' => 'Username of the new user',
+ 'CLI_DESCRIPTION_USER_ADD_OPTION_PASSWORD' => 'Password of the new user',
+ 'CLI_DESCRIPTION_USER_ADD_OPTION_EMAIL' => 'E-mail address of the new user',
+ 'CLI_DESCRIPTION_USER_ADD_OPTION_NOTIFY' => 'Send account activation email to the new user (not sent by default)',
+ 'CLI_DESCRIPTION_USER_DELETE' => 'Delete a user account.',
+ 'CLI_DESCRIPTION_USER_DELETE_USERNAME' => 'Username of the user to delete',
+ 'CLI_DESCRIPTION_USER_DELETE_OPTION_POSTS' => 'Delete all posts by the user. Without this option, the user’s posts will be retained.',
+ 'CLI_DESCRIPTION_USER_RECLEAN' => 'Re-clean usernames.',
+
'CLI_EXTENSION_DISABLE_FAILURE' => 'Could not disable extension %s',
'CLI_EXTENSION_DISABLE_SUCCESS' => 'Successfully disabled extension %s',
'CLI_EXTENSION_ENABLE_FAILURE' => 'Could not enable extension %s',
@@ -78,9 +110,47 @@ $lang = array_merge($lang, array(
'CLI_EXTENSIONS_ENABLED' => 'Enabled',
'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.',
+
+ 'CLI_MIGRATION_NAME' => 'Migration name, including the namespace (use forward slashes instead of backslashes to avoid problems).',
+ 'CLI_MIGRATIONS_AVAILABLE' => 'Available migrations',
+ 'CLI_MIGRATIONS_INSTALLED' => 'Installed migrations',
+ 'CLI_MIGRATIONS_ONLY_AVAILABLE' => 'Show only available migrations',
+ 'CLI_MIGRATIONS_EMPTY' => 'No migrations.',
+
+ 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)',
+ 'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...',
+ 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success',
+
+ // In all the case %1$s is the logical name of the file and %2$s the real name on the filesystem
+ // eg: big_image.png (2_a51529ae7932008cf8454a95af84cacd) generated.
+ 'CLI_THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.',
+ 'CLI_THUMBNAIL_DELETING' => 'Deleting thumbnails',
+ 'CLI_THUMBNAIL_SKIPPED' => '%1$s (%2$s) skipped.',
+ 'CLI_THUMBNAIL_GENERATED' => '%1$s (%2$s) generated.',
+ 'CLI_THUMBNAIL_GENERATING' => 'Generating thumbnails',
+ 'CLI_THUMBNAIL_GENERATING_DONE' => 'All thumbnails have been regenerated.',
+ 'CLI_THUMBNAIL_DELETING_DONE' => 'All thumbnails have been deleted.',
+
+ 'CLI_THUMBNAIL_NOTHING_TO_GENERATE' => 'No thumbnails to generate.',
+ 'CLI_THUMBNAIL_NOTHING_TO_DELETE' => 'No thumbnails to delete.',
+
+ 'CLI_USER_ADD_SUCCESS' => 'Successfully added user %s.',
+ 'CLI_USER_DELETE_CONFIRM' => 'Are you sure you want to delete ‘%s’? [y/N]',
+ 'CLI_USER_RECLEAN_START' => 'Re-cleaning usernames',
+ 'CLI_USER_RECLEAN_DONE' => [
+ 0 => 'Re-cleaning complete. No usernames needed to be cleaned.',
+ 1 => 'Re-cleaning complete. %d username was cleaned.',
+ 2 => 'Re-cleaning complete. %d usernames were cleaned.',
+ ],
));
// Additional help for commands.
$lang = array_merge($lang, array(
'CLI_HELP_CRON_RUN' => $lang['CLI_DESCRIPTION_CRON_RUN'] . ' Optionally you can specify a cron task name to run only the specified cron task.',
+ 'CLI_HELP_USER_ACTIVATE' => 'Activate a user account, or deactivate an account using the <info>--deactivate</info> option.
+To optionally send an activation email to the user, use the <info>--send-email</info> option.',
+ 'CLI_HELP_USER_ADD' => 'The <info>%command.name%</info> command adds a new user:
+If this command is run without options, you will be prompted to enter them.
+To optionally send an email to the new user, use the <info>--send-email</info> option.',
+ 'CLI_HELP_USER_RECLEAN' => 'Re-clean usernames will check all stored usernames and ensure clean versions are also stored. Cleaned usernames are a case insensitive form, NFC normalized and transformed to ASCII.',
));
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index a2cfd958aa..c66f728c06 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -81,8 +81,9 @@ $lang = array_merge($lang, array(
'ALL_FORUMS' => 'All forums',
'ALL_MESSAGES' => 'All messages',
'ALL_POSTS' => 'All posts',
- 'ALL_TIMES' => 'All times are <abbr title="%2$s">%1$s</abbr>',
+ 'ALL_TIMES' => 'All times are <span title="%2$s">%1$s</span>',
'ALL_TOPICS' => 'All Topics',
+ 'ALT_TEXT' => 'Alternative text',
'AND' => 'And',
'ARE_WATCHING_FORUM' => 'You have subscribed to be notified of new posts in this forum.',
'ARE_WATCHING_TOPIC' => 'You have subscribed to be notified of new posts in this topic.',
@@ -97,6 +98,7 @@ $lang = array_merge($lang, array(
'AUTH_PROVIDER_OAUTH_SERVICE_BITLY' => 'Bitly',
'AUTH_PROVIDER_OAUTH_SERVICE_FACEBOOK' => 'Facebook',
'AUTH_PROVIDER_OAUTH_SERVICE_GOOGLE' => 'Google',
+ 'AUTH_PROVIDER_OAUTH_SERVICE_TWITTER' => 'Twitter',
'AUTH_PROVIDER_OAUTH_TOKEN_ERROR_NOT_STORED' => 'OAuth token not stored.',
'AUTH_PROVIDER_OAUTH_TOKEN_ERROR_INCORRECTLY_STORED' => 'OAuth token incorrectly stored.',
'AVATAR_DISALLOWED_CONTENT' => 'The upload was rejected because the uploaded file was identified as a possible attack vector.',
@@ -105,11 +107,13 @@ $lang = array_merge($lang, array(
'AVATAR_EMPTY_FILEUPLOAD' => 'The uploaded avatar file is empty.',
'AVATAR_INVALID_FILENAME' => '%s is an invalid filename.',
'AVATAR_NOT_UPLOADED' => 'Avatar could not be uploaded.',
+ 'AVATAR_NO_TEMP_DIR' => 'Temporary folder could not be found or is not writable.',
'AVATAR_NO_SIZE' => 'The width or height of the linked avatar could not be determined. Please enter them manually.',
'AVATAR_PARTIAL_UPLOAD' => 'The specified file was only partially uploaded.',
'AVATAR_PHP_SIZE_NA' => 'The avatar’s filesize is too large.<br />The maximum allowed filesize set in php.ini could not be determined.',
'AVATAR_PHP_SIZE_OVERRUN' => 'The avatar’s filesize is too large. The maximum allowed upload size is %1$d %2$s.<br />Please note this is set in php.ini and cannot be overridden.',
'AVATAR_REMOTE_UPLOAD_TIMEOUT' => 'The specified avatar could not be uploaded because the request timed out.',
+ 'AVATAR_PHP_UPLOAD_STOPPED' => 'A PHP extension has stopped the file upload.',
'AVATAR_URL_INVALID' => 'The URL you specified is invalid.',
'AVATAR_URL_NOT_FOUND' => 'The file specified could not be found.',
'AVATAR_WRONG_FILESIZE' => 'The avatar’s filesize must be between 0 and %1$d %2$s.',
@@ -229,6 +233,7 @@ $lang = array_merge($lang, array(
'FACEBOOK' => 'Facebook',
'FAQ' => 'FAQ',
'FAQ_EXPLAIN' => 'Frequently Asked Questions',
+ 'FEATURE_NOT_AVAILABLE' => 'The requested feature is not available on this board.',
'FILENAME' => 'Filename',
'FILESIZE' => 'File size',
'FILEDATE' => 'File date',
@@ -448,6 +453,7 @@ $lang = array_merge($lang, array(
'NOTIFICATION_FORUM' => '<em>Forum:</em> %1$s',
'NOTIFICATION_GROUP_REQUEST' => '<strong>Group request</strong> from %1$s to join the group %2$s.',
'NOTIFICATION_GROUP_REQUEST_APPROVED' => '<strong>Group request approved</strong> to join the group %1$s.',
+ 'NOTIFICATION_METHOD_INVALID' => 'The method "%s" does not refer to a valid notification method.',
'NOTIFICATION_PM' => '<strong>Private Message</strong> from %1$s:',
'NOTIFICATION_POST' => array(
1 => '<strong>Reply</strong> from %1$s in topic:',
@@ -553,7 +559,6 @@ $lang = array_merge($lang, array(
1 => '%d pixel',
2 => '%d pixels',
),
- 'PLAY_QUICKTIME_FILE' => 'Play Quicktime file',
'PLEASE_WAIT' => 'Please wait.',
'PM' => 'PM',
'PM_REPORTED' => 'Click to view report',
@@ -691,10 +696,13 @@ $lang = array_merge($lang, array(
'SKYPE' => 'Skype',
'SMTP_NO_AUTH_SUPPORT' => 'SMTP server does not support authentication.',
'SORRY_AUTH_READ' => 'You are not authorised to read this forum.',
+ 'SORRY_AUTH_READ_TOPIC' => 'You are not authorised to read this topic.',
'SORRY_AUTH_VIEW_ATTACH' => 'You are not authorised to download this attachment.',
'SORT_BY' => 'Sort by',
+ 'SORT_DIRECTION' => 'Direction',
'SORT_JOINED' => 'Joined date',
'SORT_LOCATION' => 'Location',
+ 'SORT_OPTIONS' => 'Display and sorting options',
'SORT_RANK' => 'Rank',
'SORT_POSTS' => 'Posts',
'SORT_TOPIC_TITLE' => 'Topic title',
@@ -863,7 +871,6 @@ $lang = array_merge($lang, array(
'WEBSITE' => 'Website',
'WHOIS' => 'Whois',
'WHO_IS_ONLINE' => 'Who is online',
- 'WLM' => 'WLM',
'WRONG_PASSWORD' => 'You entered an incorrect password.',
'WRONG_DATA_COLOUR' => 'The colour value you entered is invalid.',
diff --git a/phpBB/language/en/email/test.txt b/phpBB/language/en/email/test.txt
new file mode 100644
index 0000000000..91a737248b
--- /dev/null
+++ b/phpBB/language/en/email/test.txt
@@ -0,0 +1,9 @@
+Subject: phpBB is correctly configured to send emails
+
+Hello {USERNAME},
+
+Congratulations. If you received this email, phpBB is correctly configured to send emails.
+
+In case you require assistance, please visit the phpBB support forums - https://www.phpbb.com/community/
+
+{EMAIL_SIG}
diff --git a/phpBB/language/en/help/bbcode.php b/phpBB/language/en/help/bbcode.php
new file mode 100644
index 0000000000..dc39749963
--- /dev/null
+++ b/phpBB/language/en/help/bbcode.php
@@ -0,0 +1,66 @@
+<?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.
+ *
+ */
+
+/**
+ * DO NOT CHANGE
+ */
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+if (empty($lang) || !is_array($lang))
+{
+ $lang = array();
+}
+
+$lang = array_merge($lang, array(
+ 'HELP_BBCODE_BLOCK_IMAGES' => 'Showing images in posts',
+ 'HELP_BBCODE_BLOCK_INTRO' => 'Introduction',
+ 'HELP_BBCODE_BLOCK_LINKS' => 'Creating Links',
+ 'HELP_BBCODE_BLOCK_LISTS' => 'Generating lists',
+ 'HELP_BBCODE_BLOCK_OTHERS' => 'Other matters',
+ 'HELP_BBCODE_BLOCK_QUOTES' => 'Quoting and outputting fixed-width text',
+ 'HELP_BBCODE_BLOCK_TEXT' => 'Text Formatting',
+
+ 'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER' => 'Attachments can now be placed in any part of a post by using the new <strong>[attachment=][/attachment]</strong> BBCode, if the attachments functionality has been enabled by a board administrator and if you are given the appropriate permissions to create attachments. Within the posting screen is a drop-down box (respectively a button) for placing attachments inline.',
+ 'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => 'Adding attachments into a post',
+ 'HELP_BBCODE_IMAGES_BASIC_ANSWER' => 'phpBB BBCode incorporates a tag for including images in your posts. Two very important things to remember when using this tag are: many users do not appreciate lots of images being shown in posts and secondly the image you display must already be available on the internet (it cannot exist only on your computer for example, unless you run a webserver!). To display an image you must surround the URL pointing to the image with <strong>[img][/img]</strong> tags. For example:<br /><br /><strong>[img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img]</strong><br /><br />As noted in the URL section above you can wrap an image in a <strong>[url][/url]</strong> tag if you wish, e.g.<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img][/url]</strong><br /><br />would generate:<br /><br /><a href="https://www.phpbb.com/"><img src="https://www.phpbb.com/theme/images/logos/blue/160x52.png" alt="" /></a>',
+ 'HELP_BBCODE_IMAGES_BASIC_QUESTION' => 'Adding an image to a post',
+
+ 'HELP_BBCODE_INTRO_BBCODE_ANSWER' => 'BBCode is a special implementation of HTML. Whether you can actually use BBCode in your posts on the forum is determined by the administrator. In addition you can disable BBCode on a per post basis via the posting form. BBCode itself is similar in style to HTML, tags are enclosed in square brackets [ and ] rather than &lt; and &gt; and it offers greater control over what and how something is displayed. Depending on the template you are using you may find adding BBCode to your posts is made much easier through a clickable interface above the message area on the posting form. Even with this you may find the following guide useful.',
+ 'HELP_BBCODE_INTRO_BBCODE_QUESTION' => 'What is BBCode?',
+
+ 'HELP_BBCODE_LINKS_BASIC_ANSWER' => 'phpBB BBCode supports a number of ways of creating URIs (Uniform Resource Indicators) better known as URLs.<ul><li>The first of these uses the <strong>[url=][/url]</strong> tag, whatever you type after the = sign will cause the contents of that tag to act as a URL. For example to link to phpBB.com you could use:<br /><br /><strong>[url=https://www.phpbb.com/]</strong>Visit phpBB!<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">Visit phpBB!</a> Please notice that the link opens in the same window or a new window depending on the users browser preferences.</li><li>If you want the URL itself displayed as the link you can do this by simply using:<br /><br /><strong>[url]</strong>https://www.phpbb.com/<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">https://www.phpbb.com/</a></li><li>Additionally, phpBB features something called <i>Magic Links</i>, this will turn any syntactically correct URL into a link without you needing to specify any tags or even the leading http://. For example typing www.phpbb.com into your message will automatically lead to <a href="http://www.phpbb.com/">www.phpbb.com</a> being output when you view the message.</li><li>The same thing applies equally to email addresses, you can either specify an address explicitly for example:<br /><br /><strong>[email]</strong>no.one@domain.adr<strong>[/email]</strong><br /><br />which will output <a href="mailto:no.one@domain.adr">no.one@domain.adr</a> or you can just type no.one@domain.adr into your message and it will be automatically converted when you view.</li></ul>As with all the BBCode tags you can wrap URLs around any of the other tags such as <strong>[img][/img]</strong> (see next entry), <strong>[b][/b]</strong>, etc. As with the formatting tags it is up to you to ensure the correct open and close order is following, for example:<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/url][/img]</strong><br /><br />is <span style="text-decoration: underline">not</span> correct which may lead to your post being deleted so take care.',
+ 'HELP_BBCODE_LINKS_BASIC_QUESTION' => 'Linking to another site',
+
+ 'HELP_BBCODE_LISTS_ORDERER_ANSWER' => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use <strong>[list=1][/list]</strong> to create a numbered list or alternatively <strong>[list=a][/list]</strong> for an alphabetical list. As with the unordered list, items are specified using <strong>[*]</strong>. For example:<br /><br /><strong>[list=1]</strong><br /><strong>[*]</strong>Go to the shops<br /><strong>[*]</strong>Buy a new computer<br /><strong>[*]</strong>Swear at computer when it crashes<br /><strong>[/list]</strong><br /><br />will generate the following:<ol style="list-style-type: decimal;"><li>Go to the shops</li><li>Buy a new computer</li><li>Swear at computer when it crashes</li></ol>Whereas for an alphabetical list you would use:<br /><br /><strong>[list=a]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=A]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: upper-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=i]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-roman"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=I]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: upper-roman"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol>',
+ 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => 'Creating an Ordered list',
+ 'HELP_BBCODE_LISTS_UNORDERER_ANSWER' => 'BBCode supports two types of lists, unordered and ordered. They are essentially the same as their HTML equivalents. An unordered list outputs each item in your list sequentially one after the other indenting each with a bullet character. To create an unordered list you use <strong>[list][/list]</strong> and define each item within the list using <strong>[*]</strong>. For example to list your favourite colours you could use:<br /><br /><strong>[list]</strong><br /><strong>[*]</strong>Red<br /><strong>[*]</strong>Blue<br /><strong>[*]</strong>Yellow<br /><strong>[/list]</strong><br /><br />This would generate the following list:<ul><li>Red</li><li>Blue</li><li>Yellow</li></ul><br />Alternatively you can specify the list’s bullet style using <strong>[list=disc][/list]</strong>, <strong>[list=circle][/list]</strong>, or <strong>[list=square][/list]</strong>.',
+ 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => 'Creating an Unordered list',
+
+ 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER' => 'If you are an administrator on this board and have the proper permissions, you can add further BBCodes through the Custom BBCodes section.',
+ 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => 'Can I add my own tags?',
+
+ 'HELP_BBCODE_QUOTES_CODE_ANSWER' => 'If you want to output a piece of code or in fact anything that requires a fixed width, e.g. Courier type font you should enclose the text in <strong>[code][/code]</strong> tags, e.g.<br /><br /><strong>[code]</strong>echo &quot;This is some code&quot;;<strong>[/code]</strong><br /><br />All formatting used within <strong>[code][/code]</strong> tags is retained when you later view it. PHP syntax highlighting can be enabled using <strong>[code=php][/code]</strong> and is recommended when posting PHP code samples as it improves readability.',
+ 'HELP_BBCODE_QUOTES_CODE_QUESTION' => 'Outputting code or fixed width data',
+ 'HELP_BBCODE_QUOTES_TEXT_ANSWER' => 'There are two ways you can quote text, with a reference or without.<ul><li>When you utilise the Quote function to reply to a post on the board you should notice that the post text is added to the message window enclosed in a <strong>[quote=&quot;&quot;][/quote]</strong> block. This method allows you to quote with a reference to a person or whatever else you choose to put! For example to quote a piece of text Mr. Blobby wrote you would enter:<br /><br /><strong>[quote=&quot;Mr. Blobby&quot;]</strong>The text Mr. Blobby wrote would go here<strong>[/quote]</strong><br /><br />The resulting output will automatically add &quot;Mr. Blobby wrote:&quot; before the actual text. Remember you <strong>must</strong> include the quotation marks &quot;&quot; around the name you are quoting, they are not optional.</li><li>The second method allows you to blindly quote something. To utilise this enclose the text in <strong>[quote][/quote]</strong> tags. When you view the message it will simply show the text within a quotation block.</li></ul>',
+ 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => 'Quoting text in replies',
+
+ 'HELP_BBCODE_TEXT_BASIC_ANSWER' => 'BBCode includes tags to allow you to quickly change the basic style of your text. This is achieved in the following ways: <ul><li>To make a piece of text bold enclose it in <strong>[b][/b]</strong>, e.g. <br /><br /><strong>[b]</strong>Hello<strong>[/b]</strong><br /><br />will become <strong>Hello</strong></li><li>For underlining use <strong>[u][/u]</strong>, for example:<br /><br /><strong>[u]</strong>Good Morning<strong>[/u]</strong><br /><br />becomes <span style="text-decoration: underline">Good Morning</span></li><li>To italicise text use <strong>[i][/i]</strong>, e.g.<br /><br />This is <strong>[i]</strong>Great!<strong>[/i]</strong><br /><br />would give This is <i>Great!</i></li></ul>',
+ 'HELP_BBCODE_TEXT_BASIC_QUESTION' => 'How to create bold, italic and underlined text',
+ 'HELP_BBCODE_TEXT_COLOR_ANSWER' => 'To alter the colour or size of your text the following tags can be used. Keep in mind that how the output appears will depend on the viewers browser and system: <ul><li>Changing the colour of text is achieved by wrapping it in <strong>[color=][/color]</strong>. You can specify either a recognised colour name (eg. red, blue, yellow, etc.) or the hexadecimal triplet alternative, e.g. #FFFFFF, #000000. For example, to create red text you could use:<br /><br /><strong>[color=red]</strong>Hello!<strong>[/color]</strong><br /><br />or<br /><br /><strong>[color=#FF0000]</strong>Hello!<strong>[/color]</strong><br /><br />Both will output <span style="color:red">Hello!</span></li><li>Changing the text size is achieved in a similar way using <strong>[size=][/size]</strong>. This tag is dependent on the template the user has selected but the recommended format is a numerical value representing the text size in percent, starting at 20 (very small) through to 200 (very large) by default. For example:<br /><br /><strong>[size=30]</strong>SMALL<strong>[/size]</strong><br /><br />will generally be <span style="font-size:30%;">SMALL</span><br /><br />whereas:<br /><br /><strong>[size=200]</strong>HUGE!<strong>[/size]</strong><br /><br />will be <span style="font-size:200%;">HUGE!</span></li></ul>',
+ 'HELP_BBCODE_TEXT_COLOR_QUESTION' => 'How to change the text colour or size',
+ 'HELP_BBCODE_TEXT_COMBINE_ANSWER' => 'Yes, of course you can, for example to get someones attention you may write:<br /><br /><strong>[size=200][color=red][b]</strong>LOOK AT ME!<strong>[/b][/color][/size]</strong><br /><br />this would output <span style="color:red;font-size:200%;"><strong>LOOK AT ME!</strong></span><br /><br />We don’t recommend you output lots of text that looks like this though! Remember it is up to you, the poster, to ensure tags are closed correctly. For example the following is incorrect:<br /><br /><strong>[b][u]</strong>This is wrong<strong>[/b][/u]</strong>',
+ 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => 'Can I combine formatting tags?',
+));
diff --git a/phpBB/language/en/help/faq.php b/phpBB/language/en/help/faq.php
new file mode 100644
index 0000000000..e59d950948
--- /dev/null
+++ b/phpBB/language/en/help/faq.php
@@ -0,0 +1,186 @@
+<?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.
+ *
+ */
+
+/**
+ * DO NOT CHANGE
+ */
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+if (empty($lang) || !is_array($lang))
+{
+ $lang = array();
+}
+
+$lang = array_merge($lang, array(
+ 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER' => 'Each board administrator can allow or disallow certain attachment types. If you are unsure what is allowed to be uploaded, contact the board administrator for assistance.',
+ 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => 'What attachments are allowed on this board?',
+ 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER' => 'To find your list of attachments that you have uploaded, go to your User Control Panel and follow the links to the attachments section.',
+ 'HELP_FAQ_ATTACHMENTS_OWN_QUESTION' => 'How do I find all my attachments?',
+
+ 'HELP_FAQ_BLOCK_ATTACHMENTS' => 'Attachments',
+ 'HELP_FAQ_BLOCK_BOOKMARKS' => 'Subscriptions and Bookmarks',
+ 'HELP_FAQ_BLOCK_FORMATTING' => 'Formatting and Topic Types',
+ 'HELP_FAQ_BLOCK_FRIENDS' => 'Friends and Foes',
+ 'HELP_FAQ_BLOCK_GROUPS' => 'User Levels and Groups',
+ 'HELP_FAQ_BLOCK_ISSUES' => 'phpBB Issues',
+ 'HELP_FAQ_BLOCK_LOGIN' => 'Login and Registration Issues',
+ 'HELP_FAQ_BLOCK_PMS' => 'Private Messaging',
+ 'HELP_FAQ_BLOCK_POSTING' => 'Posting Issues',
+ 'HELP_FAQ_BLOCK_SEARCH' => 'Searching the Forums',
+ 'HELP_FAQ_BLOCK_USERSETTINGS' => 'User Preferences and settings',
+
+ 'HELP_FAQ_BOOKMARKS_DIFFERENCE_ANSWER' => 'In phpBB 3.0, bookmarking topics worked much like bookmarking in a web browser. You were not alerted when there was an update. As of phpBB 3.1, bookmarking is more like subscribing to a topic. You can be notified when a bookmarked topic is updated. Subscribing, however, will notify you when there is an update to a topic or forum on the board. Notification options for bookmarks and subscriptions can be configured in the User Control Panel, under “Board preferencesâ€.',
+ 'HELP_FAQ_BOOKMARKS_DIFFERENCE_QUESTION' => 'What is the difference between bookmarking and subscribing?',
+ 'HELP_FAQ_BOOKMARKS_FORUM_ANSWER' => 'To subscribe to a specific forum, click the “Subscribe forum†link, at the bottom of page, upon entering the forum.',
+ 'HELP_FAQ_BOOKMARKS_FORUM_QUESTION' => 'How do I subscribe to specific forums?',
+ 'HELP_FAQ_BOOKMARKS_REMOVE_ANSWER' => 'To remove your subscriptions, go to your User Control Panel and follow the links to your subscriptions.',
+ 'HELP_FAQ_BOOKMARKS_REMOVE_QUESTION' => 'How do I remove my subscriptions?',
+ 'HELP_FAQ_BOOKMARKS_TOPIC_ANSWER' => 'You can bookmark or subscribe to a specific topic by clicking the appropriate link in the “Topic tools†menu, conveniently located near the top and bottom of a topic discussion.<br />Replying to a topic with the “Notify me when a reply is posted†option checked will also subscribe you to the topic.',
+ 'HELP_FAQ_BOOKMARKS_TOPIC_QUESTION' => 'How do I bookmark or subscribe to specific topics?',
+
+ 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_ANSWER' => 'Announcements often contain important information for the forum you are currently reading and you should read them whenever possible. Announcements appear at the top of every page in the forum to which they are posted. As with global announcements, announcement permissions are granted by the board administrator.',
+ 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_QUESTION' => 'What are announcements?',
+ 'HELP_FAQ_FORMATTING_BBOCDE_ANSWER' => 'BBCode is a special implementation of HTML, offering great formatting control on particular objects in a post. The use of BBCode is granted by the administrator, but it can also be disabled on a per post basis from the posting form. BBCode itself is similar in style to HTML, but tags are enclosed in square brackets [ and ] rather than &lt; and &gt;. For more information on BBCode see the guide which can be accessed from the posting page.',
+ 'HELP_FAQ_FORMATTING_BBOCDE_QUESTION' => 'What is BBCode?',
+ 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_ANSWER' => 'Global announcements contain important information and you should read them whenever possible. They will appear at the top of every forum and within your User Control Panel. Global announcement permissions are granted by the board administrator.',
+ 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_QUESTION' => 'What are global announcements?',
+ 'HELP_FAQ_FORMATTING_HTML_ANSWER' => 'No. It is not possible to post HTML on this board and have it rendered as HTML. Most formatting which can be carried out using HTML can be applied using BBCode instead.',
+ 'HELP_FAQ_FORMATTING_HTML_QUESTION' => 'Can I use HTML?',
+ 'HELP_FAQ_FORMATTING_ICONS_ANSWER' => 'Topic icons are author chosen images associated with posts to indicate their content. The ability to use topic icons depends on the permissions set by the board administrator.',
+ 'HELP_FAQ_FORMATTING_ICONS_QUESTION' => 'What are topic icons?',
+ 'HELP_FAQ_FORMATTING_IMAGES_ANSWER' => 'Yes, images can be shown in your posts. If the administrator has allowed attachments, you may be able to upload the image to the board. Otherwise, you must link to an image stored on a publicly accessible web server, e.g. http://www.example.com/my-picture.gif. You cannot link to pictures stored on your own PC (unless it is a publicly accessible server) nor images stored behind authentication mechanisms, e.g. hotmail or yahoo mailboxes, password protected sites, etc. To display the image use the BBCode [img] tag.',
+ 'HELP_FAQ_FORMATTING_IMAGES_QUESTION' => 'Can I post images?',
+ 'HELP_FAQ_FORMATTING_LOCKED_ANSWER' => 'Locked topics are topics where users can no longer reply and any poll it contained was automatically ended. Topics may be locked for many reasons and were set this way by either the forum moderator or board administrator. You may also be able to lock your own topics depending on the permissions you are granted by the board administrator.',
+ 'HELP_FAQ_FORMATTING_LOCKED_QUESTION' => 'What are locked topics?',
+ 'HELP_FAQ_FORMATTING_SMILIES_ANSWER' => 'Smilies, or Emoticons, are small images which can be used to express a feeling using a short code, e.g. :) denotes happy, while :( denotes sad. The full list of emoticons can be seen in the posting form. Try not to overuse smilies, however, as they can quickly render a post unreadable and a moderator may edit them out or remove the post altogether. The board administrator may also have set a limit to the number of smilies you may use within a post.',
+ 'HELP_FAQ_FORMATTING_SMILIES_QUESTION' => 'What are Smilies?',
+ 'HELP_FAQ_FORMATTING_STICKIES_ANSWER' => 'Sticky topics within the forum appear below announcements and only on the first page. They are often quite important so you should read them whenever possible. As with announcements and global announcements, sticky topic permissions are granted by the board administrator.',
+ 'HELP_FAQ_FORMATTING_STICKIES_QUESTION' => 'What are sticky topics?',
+
+ 'HELP_FAQ_FRIENDS_BASIC_ANSWER' => 'You can use these lists to organise other members of the board. Members added to your friends list will be listed within your User Control Panel for quick access to see their online status and to send them private messages. Subject to template support, posts from these users may also be highlighted. If you add a user to your foes list, any posts they make will be hidden by default.',
+ 'HELP_FAQ_FRIENDS_BASIC_QUESTION' => 'What are my Friends and Foes lists?',
+ 'HELP_FAQ_FRIENDS_MANAGE_ANSWER' => 'You can add users to your list in two ways. Within each user’s profile, there is a link to add them to either your Friend or Foe list. Alternatively, from your User Control Panel, you can directly add users by entering their member name. You may also remove users from your list using the same page.',
+ 'HELP_FAQ_FRIENDS_MANAGE_QUESTION' => 'How can I add / remove users to my Friends or Foes list?',
+
+ 'HELP_FAQ_GROUPS_ADMINISTRATORS_ANSWER' => 'Administrators are members assigned with the highest level of control over the entire board. These members can control all facets of board operation, including setting permissions, banning users, creating usergroups or moderators, etc., dependent upon the board founder and what permissions he or she has given the other administrators. They may also have full moderator capabilities in all forums, depending on the settings put forth by the board founder.',
+ 'HELP_FAQ_GROUPS_ADMINISTRATORS_QUESTION' => 'What are Administrators?',
+ 'HELP_FAQ_GROUPS_COLORS_ANSWER' => 'It is possible for the board administrator to assign a colour to the members of a usergroup to make it easy to identify the members of this group.',
+ 'HELP_FAQ_GROUPS_COLORS_QUESTION' => 'Why do some usergroups appear in a different colour?',
+ 'HELP_FAQ_GROUPS_DEFAULT_ANSWER' => 'If you are a member of more than one usergroup, your default is used to determine which group colour and group rank should be shown for you by default. The board administrator may grant you permission to change your default usergroup via your User Control Panel.',
+ 'HELP_FAQ_GROUPS_DEFAULT_QUESTION' => 'What is a “Default usergroup�',
+ 'HELP_FAQ_GROUPS_MODERATORS_ANSWER' => 'Moderators are individuals (or groups of individuals) who look after the forums from day to day. They have the authority to edit or delete posts and lock, unlock, move, delete and split topics in the forum they moderate. Generally, moderators are present to prevent users from going off-topic or posting abusive or offensive material.',
+ 'HELP_FAQ_GROUPS_MODERATORS_QUESTION' => 'What are Moderators?',
+ 'HELP_FAQ_GROUPS_TEAM_ANSWER' => 'This page provides you with a list of board staff, including board administrators and moderators and other details such as the forums they moderate.',
+ 'HELP_FAQ_GROUPS_TEAM_QUESTION' => 'What is “The team†link?',
+ 'HELP_FAQ_GROUPS_USERGROUPS_ANSWER' => 'Usergroups are groups of users that divide the community into manageable sections board administrators can work with. Each user can belong to several groups and each group can be assigned individual permissions. This provides an easy way for administrators to change permissions for many users at once, such as changing moderator permissions or granting users access to a private forum.',
+ 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_ANSWER' => 'You can view all usergroups via the “Usergroups†link within your User Control Panel. If you would like to join one, proceed by clicking the appropriate button. Not all groups have open access, however. Some may require approval to join, some may be closed and some may even have hidden memberships. If the group is open, you can join it by clicking the appropriate button. If a group requires approval to join you may request to join by clicking the appropriate button. The user group leader will need to approve your request and may ask why you want to join the group. Please do not harass a group leader if they reject your request; they will have their reasons.',
+ 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_QUESTION' => 'Where are the usergroups and how do I join one?',
+ 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_ANSWER' => 'A usergroup leader is usually assigned when usergroups are initially created by a board administrator. If you are interested in creating a usergroup, your first point of contact should be an administrator; try sending a private message.',
+ 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_QUESTION' => 'How do I become a usergroup leader?',
+ 'HELP_FAQ_GROUPS_USERGROUPS_QUESTION' => 'What are usergroups?',
+
+ 'HELP_FAQ_ISSUES_ADMIN_ANSWER' => 'All users of the board can use the “Contact us†form, if the option was enabled by the board administrator.<br />Members of the board can also use the “The team†link.',
+ 'HELP_FAQ_ISSUES_ADMIN_QUESTION' => 'How do I contact a board administrator?',
+ 'HELP_FAQ_ISSUES_FEATURE_ANSWER' => 'This software was written by and licensed through phpBB Limited. If you believe a feature needs to be added please visit the <a href="https://www.phpbb.com/ideas/">phpBB Ideas Centre</a>, where you can upvote existing ideas or suggest new features.',
+ 'HELP_FAQ_ISSUES_FEATURE_QUESTION' => 'Why isn’t X feature available?',
+ 'HELP_FAQ_ISSUES_LEGAL_ANSWER' => 'Any of the administrators listed on the “The team†page should be an appropriate point of contact for your complaints. If this still gets no response then you should contact the owner of the domain (do a <a href="http://www.google.com/search?q=whois">whois lookup</a>) or, if this is running on a free service (e.g. Yahoo!, free.fr, f2s.com, etc.), the management or abuse department of that service. Please note that the phpBB Limited has <strong>absolutely no jurisdiction</strong> and cannot in any way be held liable over how, where or by whom this board is used. Do not contact the phpBB Limited in relation to any legal (cease and desist, liable, defamatory comment, etc.) matter <strong>not directly related</strong> to the phpBB.com website or the discrete software of phpBB itself. If you do email phpBB Limited <strong>about any third party</strong> use of this software then you should expect a terse response or no response at all.',
+ 'HELP_FAQ_ISSUES_LEGAL_QUESTION' => 'Who do I contact about abusive and/or legal matters related to this board?',
+ 'HELP_FAQ_ISSUES_WHOIS_PHPBB_ANSWER' => 'This software (in its unmodified form) is produced, released and is copyright <a href="https://www.phpbb.com/">phpBB Limited</a>. It is made available under the GNU General Public License, version 2 (GPL-2.0) and may be freely distributed. See <a href="https://www.phpbb.com/about/">About phpBB</a> for more details.',
+ 'HELP_FAQ_ISSUES_WHOIS_PHPBB_QUESTION' => 'Who wrote this bulletin board?',
+
+ 'HELP_FAQ_LOGIN_AUTO_LOGOUT_ANSWER' => 'If you do not check the <em>Remember me</em> box when you login, the board will only keep you logged in for a preset time. This prevents misuse of your account by anyone else. To stay logged in, check the <em>Remember me</em> box during login. This is not recommended if you access the board from a shared computer, e.g. library, internet cafe, university computer lab, etc. If you do not see this checkbox, it means a board administrator has disabled this feature.',
+ 'HELP_FAQ_LOGIN_AUTO_LOGOUT_QUESTION' => 'Why do I get logged off automatically?',
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANSWER' => 'There are several reasons why this could occur. First, ensure your username and password are correct. If they are, contact a board administrator to make sure you haven’t been banned. It is also possible the website owner has a configuration error on their end, and they would need to fix it.',
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_ANSWER' => 'It is possible an administrator has deactivated or deleted your account for some reason. Also, many boards periodically remove users who have not posted for a long time to reduce the size of the database. If this has happened, try registering again and being more involved in discussions.',
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_QUESTION' => 'I registered in the past but cannot login any more?!',
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_QUESTION' => 'Why can’t I login?',
+ 'HELP_FAQ_LOGIN_CANNOT_REGISTER_ANSWER' => 'It is possible a board administrator has disabled registration to prevent new visitors from signing up. A board administrator could have also banned your IP address or disallowed the username you are attempting to register. Contact a board administrator for assistance.',
+ '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_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.',
+ 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_ANSWER' => 'First, check your username and password. If they are correct, then one of two things may have happened. If COPPA support is enabled and you specified being under 13 years old during registration, you will have to follow the instructions you received. Some boards will also require new registrations to be activated, either by yourself or by an administrator before you can logon; this information was present during registration. If you were sent an email, follow the instructions. If you did not receive an email, you may have provided an incorrect email address or the email may have been picked up by a spam filer. If you are sure the email address you provided is correct, try contacting an administrator.',
+ 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_QUESTION' => 'I registered but cannot login!',
+ 'HELP_FAQ_LOGIN_REGISTER_QUESTION' => 'Why do I need to register?',
+
+ 'HELP_FAQ_PMS_CANNOT_SEND_ANSWER' => 'There are three reasons for this; you are not registered and/or not logged on, the board administrator has disabled private messaging for the entire board, or the board administrator has prevented you from sending messages. Contact a board administrator for more information.',
+ 'HELP_FAQ_PMS_CANNOT_SEND_QUESTION' => 'I cannot send private messages!',
+ 'HELP_FAQ_PMS_SPAM_ANSWER' => 'We are sorry to hear that. The email form feature of this board includes safeguards to try and track users who send such posts, so email the board administrator with a full copy of the email you received. It is very important that this includes the headers that contain the details of the user that sent the email. The board administrator can then take action.',
+ 'HELP_FAQ_PMS_SPAM_QUESTION' => 'I have received a spamming or abusive email from someone on this board!',
+ 'HELP_FAQ_PMS_UNWANTED_ANSWER' => 'You can automatically delete private messages from a user by using message rules within your User Control Panel. If you are receiving abusive private messages from a particular user, report the messages to the moderators; they have the power to prevent a user from sending private messages.',
+ 'HELP_FAQ_PMS_UNWANTED_QUESTION' => 'I keep getting unwanted private messages!',
+
+ 'HELP_FAQ_POSTING_BUMP_ANSWER' => 'By clicking the “Bump topic†link when you are viewing it, you can “bump†the topic to the top of the forum on the first page. However, if you do not see this, then topic bumping may be disabled or the time allowance between bumps has not yet been reached. It is also possible to bump the topic simply by replying to it, however, be sure to follow the board rules when doing so.',
+ 'HELP_FAQ_POSTING_BUMP_QUESTION' => 'How do I bump my topic?',
+ 'HELP_FAQ_POSTING_CREATE_ANSWER' => 'To post a new topic in a forum, click "New Topic". To post a reply to a topic, click "Post Reply". You may need to register before you can post a message. A list of your permissions in each forum is available at the bottom of the forum and topic screens. Example: You can post new topics, You can post attachments, etc.',
+ 'HELP_FAQ_POSTING_CREATE_QUESTION' => 'How do I create a new topic or post a reply?',
+ 'HELP_FAQ_POSTING_DRAFT_ANSWER' => 'This allows you to save drafts to be completed and submitted at a later date. To reload a saved draft, visit the User Control Panel.',
+ 'HELP_FAQ_POSTING_DRAFT_QUESTION' => 'What is the “Save†button for in topic posting?',
+ 'HELP_FAQ_POSTING_EDIT_DELETE_ANSWER' => 'Unless you are a board administrator or moderator, you can only edit or delete your own posts. You can edit a post by clicking the edit button for the relevant post, sometimes for only a limited time after the post was made. If someone has already replied to the post, you will find a small piece of text output below the post when you return to the topic which lists the number of times you edited it along with the date and time. This will only appear if someone has made a reply; it will not appear if a moderator or administrator edited the post, though they may leave a note as to why they’ve edited the post at their own discretion. Please note that normal users cannot delete a post once someone has replied.',
+ 'HELP_FAQ_POSTING_EDIT_DELETE_QUESTION' => 'How do I edit or delete a post?',
+ 'HELP_FAQ_POSTING_FORUM_RESTRICTED_ANSWER' => 'Some forums may be limited to certain users or groups. To view, read, post or perform another action you may need special permissions. Contact a moderator or board administrator to grant you access.',
+ 'HELP_FAQ_POSTING_FORUM_RESTRICTED_QUESTION' => 'Why can’t I access a forum?',
+ 'HELP_FAQ_POSTING_NO_ATTACHMENTS_ANSWER' => 'Attachment permissions are granted on a per forum, per group, or per user basis. The board administrator may not have allowed attachments to be added for the specific forum you are posting in, or perhaps only certain groups can post attachments. Contact the board administrator if you are unsure about why you are unable to add attachments.',
+ 'HELP_FAQ_POSTING_NO_ATTACHMENTS_QUESTION' => 'Why can’t I add attachments?',
+ 'HELP_FAQ_POSTING_POLL_ADD_ANSWER' => 'The limit for poll options is set by the board administrator. If you feel you need to add more options to your poll than the allowed amount, contact the board administrator.',
+ 'HELP_FAQ_POSTING_POLL_ADD_QUESTION' => 'Why can’t I add more poll options?',
+ 'HELP_FAQ_POSTING_POLL_CREATE_ANSWER' => 'When posting a new topic or editing the first post of a topic, click the “Poll creation†tab below the main posting form; if you cannot see this, you do not have appropriate permissions to create polls. Enter a title and at least two options in the appropriate fields, making sure each option is on a separate line in the textarea. You can also set the number of options users may select during voting under “Options per userâ€, a time limit in days for the poll (0 for infinite duration) and lastly the option to allow users to amend their votes.',
+ 'HELP_FAQ_POSTING_POLL_CREATE_QUESTION' => 'How do I create a poll?',
+ 'HELP_FAQ_POSTING_POLL_EDIT_ANSWER' => 'As with posts, polls can only be edited by the original poster, a moderator or an administrator. To edit a poll, click to edit the first post in the topic; this always has the poll associated with it. If no one has cast a vote, users can delete the poll or edit any poll option. However, if members have already placed votes, only moderators or administrators can edit or delete it. This prevents the poll’s options from being changed mid-way through a poll.',
+ 'HELP_FAQ_POSTING_POLL_EDIT_QUESTION' => 'How do I edit or delete a poll?',
+ 'HELP_FAQ_POSTING_QUEUE_ANSWER' => 'The board administrator may have decided that posts in the forum you are posting to require review before submission. It is also possible that the administrator has placed you in a group of users whose posts require review before submission. Please contact the board administrator for further details.',
+ 'HELP_FAQ_POSTING_QUEUE_QUESTION' => 'Why does my post need to be approved?',
+ 'HELP_FAQ_POSTING_REPORT_ANSWER' => 'If the board administrator has allowed it, you should see a button for reporting posts next to the post you wish to report. Clicking this will walk you through the steps necessary to report the post.',
+ 'HELP_FAQ_POSTING_REPORT_QUESTION' => 'How can I report posts to a moderator?',
+ 'HELP_FAQ_POSTING_SIGNATURE_ANSWER' => 'To add a signature to a post you must first create one via your User Control Panel. Once created, you can check the <em>Attach a signature</em> box on the posting form to add your signature. You can also add a signature by default to all your posts by checking the appropriate radio button in the User Control Panel. If you do so, you can still prevent a signature being added to individual posts by un-checking the add signature box within the posting form.',
+ 'HELP_FAQ_POSTING_SIGNATURE_QUESTION' => 'How do I add a signature to my post?',
+ 'HELP_FAQ_POSTING_WARNING_ANSWER' => 'Each board administrator has their own set of rules for their site. If you have broken a rule, you may be issued a warning. Please note that this is the board administrator’s decision, and the phpBB Limited has nothing to do with the warnings on the given site. Contact the board administrator if you are unsure about why you were issued a warning.',
+ 'HELP_FAQ_POSTING_WARNING_QUESTION' => 'Why did I receive a warning?',
+
+ 'HELP_FAQ_SEARCH_BLANK_ANSWER' => 'Your search returned too many results for the webserver to handle. Use “Advanced search†and be more specific in the terms used and forums that are to be searched.',
+ 'HELP_FAQ_SEARCH_BLANK_QUESTION' => 'Why does my search return a blank page!?',
+ 'HELP_FAQ_SEARCH_FORUM_ANSWER' => 'Enter a search term in the search box located on the index, forum or topic pages. Advanced search can be accessed by clicking the “Advance Search†link which is available on all pages on the forum. How to access the search may depend on the style used.',
+ 'HELP_FAQ_SEARCH_FORUM_QUESTION' => 'How can I search a forum or forums?',
+ 'HELP_FAQ_SEARCH_MEMBERS_ANSWER' => 'Visit to the “Members†page and click the “Find a member†link.',
+ 'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => 'How do I search for members?',
+ 'HELP_FAQ_SEARCH_NO_RESULT_ANSWER' => 'Your search was probably too vague and included many common terms which are not indexed by phpBB. Be more specific and use the options available within Advanced search.',
+ 'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => 'Why does my search return no results?',
+ 'HELP_FAQ_SEARCH_OWN_ANSWER' => 'Your own posts can be retrieved either by clicking the “Show your posts†link within the User Control Panel or by clicking the “Search user’s posts†link via your own profile page or by clicking the “Quick links†menu at the top of the board. To search for your topics, use the Advanced search page and fill in the various options appropriately.',
+ 'HELP_FAQ_SEARCH_OWN_QUESTION' => 'How can I find my own posts and topics?',
+
+ 'HELP_FAQ_USERSETTINGS_AVATAR_ANSWER' => 'There are two images which may appear along with a username when viewing posts. One of them may be an image associated with your rank, generally in the form of stars, blocks or dots, indicating how many posts you have made or your status on the board. Another, usually larger, image is known as an avatar and is generally unique or personal to each user.',
+ 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_ANSWER' => 'Within your User Control Panel, under “Profile†you can add an avatar by using one of the four following methods: Gravatar, Gallery, Remote or Upload. It is up to the board administrator to enable avatars and to choose the way in which avatars can be made available. If you are unable to use avatars, contact a board administrator.',
+ 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_QUESTION' => 'How do I display an avatar?',
+ 'HELP_FAQ_USERSETTINGS_AVATAR_QUESTION' => 'What are the images next to my username?',
+ 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_ANSWER' => 'If you are a registered user, all your settings are stored in the board database. To alter them, visit your User Control Panel; a link can usually be found by clicking on your username at the top of board pages. This system will allow you to change all your settings and preferences.',
+ 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_QUESTION' => 'How do I change my settings?',
+ 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_ANSWER' => 'Only registered users can send email to other users via the built-in email form, and only if the administrator has enabled this feature. This is to prevent malicious use of the email system by anonymous users.',
+ 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_QUESTION' => 'When I click the email link for a user it asks me to login?',
+ 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_ANSWER' => 'Within your User Control Panel, under “Board preferencesâ€, you will find the option <em>Hide your online status</em>. Enable this option and you will only appear to the administrators, moderators and yourself. You will be counted as a hidden user.',
+ 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_QUESTION' => 'How do I prevent my username appearing in the online user listings?',
+ 'HELP_FAQ_USERSETTINGS_LANGUAGE_ANSWER' => 'Either the administrator has not installed your language or nobody has translated this board into your language. Try asking a board administrator if they can install the language pack you need. If the language pack does not exist, feel free to create a new translation. More information can be found at the <a href="https://www.phpbb.com/">phpBB</a>&reg; website.',
+ 'HELP_FAQ_USERSETTINGS_LANGUAGE_QUESTION' => 'My language is not in the list!',
+ 'HELP_FAQ_USERSETTINGS_RANK_ANSWER' => 'Ranks, which appear below your username, indicate the number of posts you have made or identify certain users, e.g. moderators and administrators. In general, you cannot directly change the wording of any board ranks as they are set by the board administrator. Please do not abuse the board by posting unnecessarily just to increase your rank. Most boards will not tolerate this and the moderator or administrator will simply lower your post count.',
+ 'HELP_FAQ_USERSETTINGS_RANK_QUESTION' => 'What is my rank and how do I change it?',
+ 'HELP_FAQ_USERSETTINGS_SERVERTIME_ANSWER' => 'If you are sure you have set the timezone correctly and the time is still incorrect, then the time stored on the server clock is incorrect. Please notify an administrator to correct the problem.',
+ 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => 'I changed the timezone and the time is still wrong!',
+ 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER' => 'It is possible the time displayed is from a timezone different from the one you are in. If this is the case, visit your User Control Panel and change your timezone to match your particular area, e.g. London, Paris, New York, Sydney, etc. Please note that changing the timezone, like most settings, can only be done by registered users. If you are not registered, this is a good time to do so.',
+ 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => 'The times are not correct!',
+));
diff --git a/phpBB/language/en/help_bbcode.php b/phpBB/language/en/help_bbcode.php
deleted file mode 100644
index 800ce3dfb7..0000000000
--- a/phpBB/language/en/help_bbcode.php
+++ /dev/null
@@ -1,115 +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.
-*
-*/
-
-/**
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-// DEVELOPERS PLEASE NOTE
-//
-// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
-//
-// Placeholders can now contain order information, e.g. instead of
-// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
-// translators to re-order the output of data while ensuring it remains correct
-//
-// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
-// equally where a string contains only two placeholders which are used to wrap text
-// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
-
-$help = array(
- array(
- 0 => '--',
- 1 => 'Introduction'
- ),
- array(
- 0 => 'What is BBCode?',
- 1 => 'BBCode is a special implementation of HTML. Whether you can actually use BBCode in your posts on the forum is determined by the administrator. In addition you can disable BBCode on a per post basis via the posting form. BBCode itself is similar in style to HTML, tags are enclosed in square brackets [ and ] rather than &lt; and &gt; and it offers greater control over what and how something is displayed. Depending on the template you are using you may find adding BBCode to your posts is made much easier through a clickable interface above the message area on the posting form. Even with this you may find the following guide useful.'
- ),
- array(
- 0 => '--',
- 1 => 'Text Formatting'
- ),
- array(
- 0 => 'How to create bold, italic and underlined text',
- 1 => 'BBCode includes tags to allow you to quickly change the basic style of your text. This is achieved in the following ways: <ul><li>To make a piece of text bold enclose it in <strong>[b][/b]</strong>, e.g. <br /><br /><strong>[b]</strong>Hello<strong>[/b]</strong><br /><br />will become <strong>Hello</strong></li><li>For underlining use <strong>[u][/u]</strong>, for example:<br /><br /><strong>[u]</strong>Good Morning<strong>[/u]</strong><br /><br />becomes <span style="text-decoration: underline">Good Morning</span></li><li>To italicise text use <strong>[i][/i]</strong>, e.g.<br /><br />This is <strong>[i]</strong>Great!<strong>[/i]</strong><br /><br />would give This is <i>Great!</i></li></ul>'
- ),
- array(
- 0 => 'How to change the text colour or size',
- 1 => 'To alter the colour or size of your text the following tags can be used. Keep in mind that how the output appears will depend on the viewers browser and system: <ul><li>Changing the colour of text is achieved by wrapping it in <strong>[color=][/color]</strong>. You can specify either a recognised colour name (eg. red, blue, yellow, etc.) or the hexadecimal triplet alternative, e.g. #FFFFFF, #000000. For example, to create red text you could use:<br /><br /><strong>[color=red]</strong>Hello!<strong>[/color]</strong><br /><br />or<br /><br /><strong>[color=#FF0000]</strong>Hello!<strong>[/color]</strong><br /><br />Both will output <span style="color:red">Hello!</span></li><li>Changing the text size is achieved in a similar way using <strong>[size=][/size]</strong>. This tag is dependent on the template the user has selected but the recommended format is a numerical value representing the text size in percent, starting at 20 (very small) through to 200 (very large) by default. For example:<br /><br /><strong>[size=30]</strong>SMALL<strong>[/size]</strong><br /><br />will generally be <span style="font-size:30%;">SMALL</span><br /><br />whereas:<br /><br /><strong>[size=200]</strong>HUGE!<strong>[/size]</strong><br /><br />will be <span style="font-size:200%;">HUGE!</span></li></ul>'
- ),
- array(
- 0 => 'Can I combine formatting tags?',
- 1 => 'Yes, of course you can, for example to get someones attention you may write:<br /><br /><strong>[size=200][color=red][b]</strong>LOOK AT ME!<strong>[/b][/color][/size]</strong><br /><br />this would output <span style="color:red;font-size:200%;"><strong>LOOK AT ME!</strong></span><br /><br />We don’t recommend you output lots of text that looks like this though! Remember it is up to you, the poster, to ensure tags are closed correctly. For example the following is incorrect:<br /><br /><strong>[b][u]</strong>This is wrong<strong>[/b][/u]</strong>'
- ),
- array(
- 0 => '--',
- 1 => 'Quoting and outputting fixed-width text'
- ),
- array(
- 0 => 'Quoting text in replies',
- 1 => 'There are two ways you can quote text, with a reference or without.<ul><li>When you utilise the Quote function to reply to a post on the board you should notice that the post text is added to the message window enclosed in a <strong>[quote=&quot;&quot;][/quote]</strong> block. This method allows you to quote with a reference to a person or whatever else you choose to put! For example to quote a piece of text Mr. Blobby wrote you would enter:<br /><br /><strong>[quote=&quot;Mr. Blobby&quot;]</strong>The text Mr. Blobby wrote would go here<strong>[/quote]</strong><br /><br />The resulting output will automatically add &quot;Mr. Blobby wrote:&quot; before the actual text. Remember you <strong>must</strong> include the quotation marks &quot;&quot; around the name you are quoting, they are not optional.</li><li>The second method allows you to blindly quote something. To utilise this enclose the text in <strong>[quote][/quote]</strong> tags. When you view the message it will simply show the text within a quotation block.</li></ul>'
- ),
- array(
- 0 => 'Outputting code or fixed width data',
- 1 => 'If you want to output a piece of code or in fact anything that requires a fixed width, e.g. Courier type font you should enclose the text in <strong>[code][/code]</strong> tags, e.g.<br /><br /><strong>[code]</strong>echo &quot;This is some code&quot;;<strong>[/code]</strong><br /><br />All formatting used within <strong>[code][/code]</strong> tags is retained when you later view it. PHP syntax highlighting can be enabled using <strong>[code=php][/code]</strong> and is recommended when posting PHP code samples as it improves readability.'
- ),
- array(
- 0 => '--',
- 1 => 'Generating lists'
- ),
- array(
- 0 => 'Creating an Unordered list',
- 1 => 'BBCode supports two types of lists, unordered and ordered. They are essentially the same as their HTML equivalents. An unordered list outputs each item in your list sequentially one after the other indenting each with a bullet character. To create an unordered list you use <strong>[list][/list]</strong> and define each item within the list using <strong>[*]</strong>. For example to list your favourite colours you could use:<br /><br /><strong>[list]</strong><br /><strong>[*]</strong>Red<br /><strong>[*]</strong>Blue<br /><strong>[*]</strong>Yellow<br /><strong>[/list]</strong><br /><br />This would generate the following list:<ul><li>Red</li><li>Blue</li><li>Yellow</li></ul><br />Alternatively you can specify the list’s bullet style using <strong>[list=disc][/list]</strong>, <strong>[list=circle][/list]</strong>, or <strong>[list=square][/list]</strong>.'
- ),
- array(
- 0 => 'Creating an Ordered list',
- 1 => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use <strong>[list=1][/list]</strong> to create a numbered list or alternatively <strong>[list=a][/list]</strong> for an alphabetical list. As with the unordered list, items are specified using <strong>[*]</strong>. For example:<br /><br /><strong>[list=1]</strong><br /><strong>[*]</strong>Go to the shops<br /><strong>[*]</strong>Buy a new computer<br /><strong>[*]</strong>Swear at computer when it crashes<br /><strong>[/list]</strong><br /><br />will generate the following:<ol style="list-style-type: decimal;"><li>Go to the shops</li><li>Buy a new computer</li><li>Swear at computer when it crashes</li></ol>Whereas for an alphabetical list you would use:<br /><br /><strong>[list=a]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=A]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: upper-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=i]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-roman"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=I]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: upper-roman"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol>'
- ),
- // This block will switch the FAQ-Questions to the second template column
- array(
- 0 => '--',
- 1 => '--'
- ),
- array(
- 0 => '--',
- 1 => 'Creating Links'
- ),
- array(
- 0 => 'Linking to another site',
- 1 => 'phpBB BBCode supports a number of ways of creating URIs (Uniform Resource Indicators) better known as URLs.<ul><li>The first of these uses the <strong>[url=][/url]</strong> tag, whatever you type after the = sign will cause the contents of that tag to act as a URL. For example to link to phpBB.com you could use:<br /><br /><strong>[url=https://www.phpbb.com/]</strong>Visit phpBB!<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">Visit phpBB!</a> Please notice that the link opens in the same window or a new window depending on the users browser preferences.</li><li>If you want the URL itself displayed as the link you can do this by simply using:<br /><br /><strong>[url]</strong>https://www.phpbb.com/<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">https://www.phpbb.com/</a></li><li>Additionally, phpBB features something called <i>Magic Links</i>, this will turn any syntactically correct URL into a link without you needing to specify any tags or even the leading http://. For example typing www.phpbb.com into your message will automatically lead to <a href="http://www.phpbb.com/">www.phpbb.com</a> being output when you view the message.</li><li>The same thing applies equally to email addresses, you can either specify an address explicitly for example:<br /><br /><strong>[email]</strong>no.one@domain.adr<strong>[/email]</strong><br /><br />which will output <a href="mailto:no.one@domain.adr">no.one@domain.adr</a> or you can just type no.one@domain.adr into your message and it will be automatically converted when you view.</li></ul>As with all the BBCode tags you can wrap URLs around any of the other tags such as <strong>[img][/img]</strong> (see next entry), <strong>[b][/b]</strong>, etc. As with the formatting tags it is up to you to ensure the correct open and close order is following, for example:<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/url][/img]</strong><br /><br />is <span style="text-decoration: underline">not</span> correct which may lead to your post being deleted so take care.'
- ),
- array(
- 0 => '--',
- 1 => 'Showing images in posts'
- ),
- array(
- 0 => 'Adding an image to a post',
- 1 => 'phpBB BBCode incorporates a tag for including images in your posts. Two very important things to remember when using this tag are: many users do not appreciate lots of images being shown in posts and secondly the image you display must already be available on the internet (it cannot exist only on your computer for example, unless you run a webserver!). To display an image you must surround the URL pointing to the image with <strong>[img][/img]</strong> tags. For example:<br /><br /><strong>[img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img]</strong><br /><br />As noted in the URL section above you can wrap an image in a <strong>[url][/url]</strong> tag if you wish, e.g.<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img][/url]</strong><br /><br />would generate:<br /><br /><a href="https://www.phpbb.com/"><img src="https://www.phpbb.com/theme/images/logos/blue/160x52.png" alt="" /></a>'
- ),
- array(
- 0 => 'Adding attachments into a post',
- 1 => 'Attachments can now be placed in any part of a post by using the new <strong>[attachment=][/attachment]</strong> BBCode, if the attachments functionality has been enabled by a board administrator and if you are given the appropriate permissions to create attachments. Within the posting screen is a drop-down box (respectively a button) for placing attachments inline.'
- ),
- array(
- 0 => '--',
- 1 => 'Other matters'
- ),
- array(
- 0 => 'Can I add my own tags?',
- 1 => 'If you are an administrator on this board and have the proper permissions, you can add further BBCodes through the Custom BBCodes section.'
- ),
-);
diff --git a/phpBB/language/en/help_faq.php b/phpBB/language/en/help_faq.php
deleted file mode 100644
index 8f08ac1cd3..0000000000
--- a/phpBB/language/en/help_faq.php
+++ /dev/null
@@ -1,355 +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.
-*
-*/
-
-/**
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-// DEVELOPERS PLEASE NOTE
-//
-// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
-//
-// Placeholders can now contain order information, e.g. instead of
-// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
-// translators to re-order the output of data while ensuring it remains correct
-//
-// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
-// equally where a string contains only two placeholders which are used to wrap text
-// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
-
-$help = array(
- array(
- 0 => '--',
- 1 => 'Login and Registration Issues'
- ),
- array(
- 0 => 'Why do I need to register?',
- 1 => '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.'
- ),
- array(
- 0 => 'What is COPPA?',
- 1 => '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?â€.',
- ),
- array(
- 0 => 'Why can’t I register?',
- 1 => 'It is possible a board administrator has disabled registration to prevent new visitors from signing up. A board administrator could have also banned your IP address or disallowed the username you are attempting to register. Contact a board administrator for assistance.',
- ),
- array(
- 0 => 'I registered but cannot login!',
- 1 => 'First, check your username and password. If they are correct, then one of two things may have happened. If COPPA support is enabled and you specified being under 13 years old during registration, you will have to follow the instructions you received. Some boards will also require new registrations to be activated, either by yourself or by an administrator before you can logon; this information was present during registration. If you were sent an email, follow the instructions. If you did not receive an email, you may have provided an incorrect email address or the email may have been picked up by a spam filer. If you are sure the email address you provided is correct, try contacting an administrator.'
- ),
- array(
- 0 => 'Why can’t I login?',
- 1 => 'There are several reasons why this could occur. First, ensure your username and password are correct. If they are, contact a board administrator to make sure you haven’t been banned. It is also possible the website owner has a configuration error on their end, and they would need to fix it.',
- ),
- array(
- 0 => 'I registered in the past but cannot login any more?!',
- 1 => 'It is possible an administrator has deactivated or deleted your account for some reason. Also, many boards periodically remove users who have not posted for a long time to reduce the size of the database. If this has happened, try registering again and being more involved in discussions.'
- ),
- array(
- 0 => 'I’ve lost my password!',
- 1 => '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.',
- ),
- array(
- 0 => 'Why do I get logged off automatically?',
- 1 => 'If you do not check the <em>Remember me</em> box when you login, the board will only keep you logged in for a preset time. This prevents misuse of your account by anyone else. To stay logged in, check the <em>Remember me</em> box during login. This is not recommended if you access the board from a shared computer, e.g. library, internet cafe, university computer lab, etc. If you do not see this checkbox, it means a board administrator has disabled this feature.',
- ),
- array(
- 0 => 'What does the “Delete all board cookies†do?',
- 1 => '“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.',
- ),
- array(
- 0 => '--',
- 1 => 'User Preferences and settings'
- ),
- array(
- 0 => 'How do I change my settings?',
- 1 => 'If you are a registered user, all your settings are stored in the board database. To alter them, visit your User Control Panel; a link can usually be found by clicking on your username at the top of board pages. This system will allow you to change all your settings and preferences.',
- ),
- array(
- 0 => 'How do I prevent my username appearing in the online user listings?',
- 1 => 'Within your User Control Panel, under “Board preferencesâ€, you will find the option <em>Hide your online status</em>. Enable this option and you will only appear to the administrators, moderators and yourself. You will be counted as a hidden user.'
- ),
- array(
- 0 => 'The times are not correct!',
- 1 => 'It is possible the time displayed is from a timezone different from the one you are in. If this is the case, visit your User Control Panel and change your timezone to match your particular area, e.g. London, Paris, New York, Sydney, etc. Please note that changing the timezone, like most settings, can only be done by registered users. If you are not registered, this is a good time to do so.'
- ),
- array(
- 0 => 'I changed the timezone and the time is still wrong!',
- 1 => 'If you are sure you have set the timezone correctly and the time is still incorrect, then the time stored on the server clock is incorrect. Please notify an administrator to correct the problem.'
- ),
- array(
- 0 => 'My language is not in the list!',
- 1 => 'Either the administrator has not installed your language or nobody has translated this board into your language. Try asking a board administrator if they can install the language pack you need. If the language pack does not exist, feel free to create a new translation. More information can be found at the <a href="https://www.phpbb.com/">phpBB</a>&reg; website.',
- ),
- array(
- 0 => 'What are the images next to my username?',
- 1 => 'There are two images which may appear along with a username when viewing posts. One of them may be an image associated with your rank, generally in the form of stars, blocks or dots, indicating how many posts you have made or your status on the board. Another, usually larger, image is known as an avatar and is generally unique or personal to each user.',
- ),
- array(
- 0 => 'How do I display an avatar?',
- 1 => 'Within your User Control Panel, under “Profile†you can add an avatar by using one of the four following methods: Gravatar, Gallery, Remote or Upload. It is up to the board administrator to enable avatars and to choose the way in which avatars can be made available. If you are unable to use avatars, contact a board administrator.',
- ),
- array(
- 0 => 'What is my rank and how do I change it?',
- 1 => 'Ranks, which appear below your username, indicate the number of posts you have made or identify certain users, e.g. moderators and administrators. In general, you cannot directly change the wording of any board ranks as they are set by the board administrator. Please do not abuse the board by posting unnecessarily just to increase your rank. Most boards will not tolerate this and the moderator or administrator will simply lower your post count.'
- ),
- array(
- 0 => 'When I click the email link for a user it asks me to login?',
- 1 => 'Only registered users can send email to other users via the built-in email form, and only if the administrator has enabled this feature. This is to prevent malicious use of the email system by anonymous users.'
- ),
- array(
- 0 => '--',
- 1 => 'Posting Issues'
- ),
- array(
- 0 => 'How do I create a new topic or post a reply?',
- 1 => 'To post a new topic in a forum, click "New Topic". To post a reply to a topic, click "Post Reply". You may need to register before you can post a message. A list of your permissions in each forum is available at the bottom of the forum and topic screens. Example: You can post new topics, You can post attachments, etc.',
- ),
- array(
- 0 => 'How do I edit or delete a post?',
- 1 => 'Unless you are a board administrator or moderator, you can only edit or delete your own posts. You can edit a post by clicking the edit button for the relevant post, sometimes for only a limited time after the post was made. If someone has already replied to the post, you will find a small piece of text output below the post when you return to the topic which lists the number of times you edited it along with the date and time. This will only appear if someone has made a reply; it will not appear if a moderator or administrator edited the post, though they may leave a note as to why they’ve edited the post at their own discretion. Please note that normal users cannot delete a post once someone has replied.'
- ),
- array(
- 0 => 'How do I add a signature to my post?',
- 1 => 'To add a signature to a post you must first create one via your User Control Panel. Once created, you can check the <em>Attach a signature</em> box on the posting form to add your signature. You can also add a signature by default to all your posts by checking the appropriate radio button in the User Control Panel. If you do so, you can still prevent a signature being added to individual posts by un-checking the add signature box within the posting form.'
- ),
- array(
- 0 => 'How do I create a poll?',
- 1 => 'When posting a new topic or editing the first post of a topic, click the “Poll creation†tab below the main posting form; if you cannot see this, you do not have appropriate permissions to create polls. Enter a title and at least two options in the appropriate fields, making sure each option is on a separate line in the textarea. You can also set the number of options users may select during voting under “Options per userâ€, a time limit in days for the poll (0 for infinite duration) and lastly the option to allow users to amend their votes.'
- ),
- array(
- 0 => 'Why can’t I add more poll options?',
- 1 => 'The limit for poll options is set by the board administrator. If you feel you need to add more options to your poll than the allowed amount, contact the board administrator.'
- ),
- array(
- 0 => 'How do I edit or delete a poll?',
- 1 => 'As with posts, polls can only be edited by the original poster, a moderator or an administrator. To edit a poll, click to edit the first post in the topic; this always has the poll associated with it. If no one has cast a vote, users can delete the poll or edit any poll option. However, if members have already placed votes, only moderators or administrators can edit or delete it. This prevents the poll’s options from being changed mid-way through a poll.'
- ),
- array(
- 0 => 'Why can’t I access a forum?',
- 1 => 'Some forums may be limited to certain users or groups. To view, read, post or perform another action you may need special permissions. Contact a moderator or board administrator to grant you access.'
- ),
- array(
- 0 => 'Why can’t I add attachments?',
- 1 => 'Attachment permissions are granted on a per forum, per group, or per user basis. The board administrator may not have allowed attachments to be added for the specific forum you are posting in, or perhaps only certain groups can post attachments. Contact the board administrator if you are unsure about why you are unable to add attachments.'
- ),
- array(
- 0 => 'Why did I receive a warning?',
- 1 => 'Each board administrator has their own set of rules for their site. If you have broken a rule, you may be issued a warning. Please note that this is the board administrator’s decision, and the phpBB Limited has nothing to do with the warnings on the given site. Contact the board administrator if you are unsure about why you were issued a warning.'
- ),
- array(
- 0 => 'How can I report posts to a moderator?',
- 1 => 'If the board administrator has allowed it, you should see a button for reporting posts next to the post you wish to report. Clicking this will walk you through the steps necessary to report the post.'
- ),
- array(
- 0 => 'What is the “Save†button for in topic posting?',
- 1 => 'This allows you to save drafts to be completed and submitted at a later date. To reload a saved draft, visit the User Control Panel.'
- ),
- array(
- 0 => 'Why does my post need to be approved?',
- 1 => 'The board administrator may have decided that posts in the forum you are posting to require review before submission. It is also possible that the administrator has placed you in a group of users whose posts require review before submission. Please contact the board administrator for further details.'
- ),
- array(
- 0 => 'How do I bump my topic?',
- 1 => 'By clicking the “Bump topic†link when you are viewing it, you can “bump†the topic to the top of the forum on the first page. However, if you do not see this, then topic bumping may be disabled or the time allowance between bumps has not yet been reached. It is also possible to bump the topic simply by replying to it, however, be sure to follow the board rules when doing so.'
- ),
- array(
- 0 => '--',
- 1 => 'Formatting and Topic Types'
- ),
- array(
- 0 => 'What is BBCode?',
- 1 => 'BBCode is a special implementation of HTML, offering great formatting control on particular objects in a post. The use of BBCode is granted by the administrator, but it can also be disabled on a per post basis from the posting form. BBCode itself is similar in style to HTML, but tags are enclosed in square brackets [ and ] rather than &lt; and &gt;. For more information on BBCode see the guide which can be accessed from the posting page.'
- ),
- array(
- 0 => 'Can I use HTML?',
- 1 => 'No. It is not possible to post HTML on this board and have it rendered as HTML. Most formatting which can be carried out using HTML can be applied using BBCode instead.'
- ),
- array(
- 0 => 'What are Smilies?',
- 1 => 'Smilies, or Emoticons, are small images which can be used to express a feeling using a short code, e.g. :) denotes happy, while :( denotes sad. The full list of emoticons can be seen in the posting form. Try not to overuse smilies, however, as they can quickly render a post unreadable and a moderator may edit them out or remove the post altogether. The board administrator may also have set a limit to the number of smilies you may use within a post.'
- ),
- array(
- 0 => 'Can I post images?',
- 1 => 'Yes, images can be shown in your posts. If the administrator has allowed attachments, you may be able to upload the image to the board. Otherwise, you must link to an image stored on a publicly accessible web server, e.g. http://www.example.com/my-picture.gif. You cannot link to pictures stored on your own PC (unless it is a publicly accessible server) nor images stored behind authentication mechanisms, e.g. hotmail or yahoo mailboxes, password protected sites, etc. To display the image use the BBCode [img] tag.'
- ),
- array(
- 0 => 'What are global announcements?',
- 1 => 'Global announcements contain important information and you should read them whenever possible. They will appear at the top of every forum and within your User Control Panel. Global announcement permissions are granted by the board administrator.'
- ),
- array(
- 0 => 'What are announcements?',
- 1 => 'Announcements often contain important information for the forum you are currently reading and you should read them whenever possible. Announcements appear at the top of every page in the forum to which they are posted. As with global announcements, announcement permissions are granted by the board administrator.'
- ),
- array(
- 0 => 'What are sticky topics?',
- 1 => 'Sticky topics within the forum appear below announcements and only on the first page. They are often quite important so you should read them whenever possible. As with announcements and global announcements, sticky topic permissions are granted by the board administrator.'
- ),
- array(
- 0 => 'What are locked topics?',
- 1 => 'Locked topics are topics where users can no longer reply and any poll it contained was automatically ended. Topics may be locked for many reasons and were set this way by either the forum moderator or board administrator. You may also be able to lock your own topics depending on the permissions you are granted by the board administrator.'
- ),
- array(
- 0 => 'What are topic icons?',
- 1 => 'Topic icons are author chosen images associated with posts to indicate their content. The ability to use topic icons depends on the permissions set by the board administrator.'
- ),
- // This block will switch the FAQ-Questions to the second template column
- array(
- 0 => '--',
- 1 => '--'
- ),
- array(
- 0 => '--',
- 1 => 'User Levels and Groups'
- ),
- array(
- 0 => 'What are Administrators?',
- 1 => 'Administrators are members assigned with the highest level of control over the entire board. These members can control all facets of board operation, including setting permissions, banning users, creating usergroups or moderators, etc., dependent upon the board founder and what permissions he or she has given the other administrators. They may also have full moderator capabilities in all forums, depending on the settings put forth by the board founder.'
- ),
- array(
- 0 => 'What are Moderators?',
- 1 => 'Moderators are individuals (or groups of individuals) who look after the forums from day to day. They have the authority to edit or delete posts and lock, unlock, move, delete and split topics in the forum they moderate. Generally, moderators are present to prevent users from going off-topic or posting abusive or offensive material.'
- ),
- array(
- 0 => 'What are usergroups?',
- 1 => 'Usergroups are groups of users that divide the community into manageable sections board administrators can work with. Each user can belong to several groups and each group can be assigned individual permissions. This provides an easy way for administrators to change permissions for many users at once, such as changing moderator permissions or granting users access to a private forum.'
- ),
- array(
- 0 => 'Where are the usergroups and how do I join one?',
- 1 => 'You can view all usergroups via the “Usergroups†link within your User Control Panel. If you would like to join one, proceed by clicking the appropriate button. Not all groups have open access, however. Some may require approval to join, some may be closed and some may even have hidden memberships. If the group is open, you can join it by clicking the appropriate button. If a group requires approval to join you may request to join by clicking the appropriate button. The user group leader will need to approve your request and may ask why you want to join the group. Please do not harass a group leader if they reject your request; they will have their reasons.'
- ),
- array(
- 0 => 'How do I become a usergroup leader?',
- 1 => 'A usergroup leader is usually assigned when usergroups are initially created by a board administrator. If you are interested in creating a usergroup, your first point of contact should be an administrator; try sending a private message.',
- ),
- array(
- 0 => 'Why do some usergroups appear in a different colour?',
- 1 => 'It is possible for the board administrator to assign a colour to the members of a usergroup to make it easy to identify the members of this group.'
- ),
- array(
- 0 => 'What is a “Default usergroup�',
- 1 => 'If you are a member of more than one usergroup, your default is used to determine which group colour and group rank should be shown for you by default. The board administrator may grant you permission to change your default usergroup via your User Control Panel.'
- ),
- array(
- 0 => 'What is “The team†link?',
- 1 => 'This page provides you with a list of board staff, including board administrators and moderators and other details such as the forums they moderate.'
- ),
- array(
- 0 => '--',
- 1 => 'Private Messaging'
- ),
- array(
- 0 => 'I cannot send private messages!',
- 1 => 'There are three reasons for this; you are not registered and/or not logged on, the board administrator has disabled private messaging for the entire board, or the board administrator has prevented you from sending messages. Contact a board administrator for more information.'
- ),
- array(
- 0 => 'I keep getting unwanted private messages!',
- 1 => 'You can automatically delete private messages from a user by using message rules within your User Control Panel. If you are receiving abusive private messages from a particular user, report the messages to the moderators; they have the power to prevent a user from sending private messages.'
- ),
- array(
- 0 => 'I have received a spamming or abusive email from someone on this board!',
- 1 => 'We are sorry to hear that. The email form feature of this board includes safeguards to try and track users who send such posts, so email the board administrator with a full copy of the email you received. It is very important that this includes the headers that contain the details of the user that sent the email. The board administrator can then take action.'
- ),
- array(
- 0 => '--',
- 1 => 'Friends and Foes'
- ),
- array(
- 0 => 'What are my Friends and Foes lists?',
- 1 => 'You can use these lists to organise other members of the board. Members added to your friends list will be listed within your User Control Panel for quick access to see their online status and to send them private messages. Subject to template support, posts from these users may also be highlighted. If you add a user to your foes list, any posts they make will be hidden by default.'
- ),
- array(
- 0 => 'How can I add / remove users to my Friends or Foes list?',
- 1 => 'You can add users to your list in two ways. Within each user’s profile, there is a link to add them to either your Friend or Foe list. Alternatively, from your User Control Panel, you can directly add users by entering their member name. You may also remove users from your list using the same page.'
- ),
- array(
- 0 => '--',
- 1 => 'Searching the Forums'
- ),
- array(
- 0 => 'How can I search a forum or forums?',
- 1 => 'Enter a search term in the search box located on the index, forum or topic pages. Advanced search can be accessed by clicking the “Advance Search†link which is available on all pages on the forum. How to access the search may depend on the style used.'
- ),
- array(
- 0 => 'Why does my search return no results?',
- 1 => 'Your search was probably too vague and included many common terms which are not indexed by phpBB. Be more specific and use the options available within Advanced search.',
- ),
- array(
- 0 => 'Why does my search return a blank page!?',
- 1 => 'Your search returned too many results for the webserver to handle. Use “Advanced search†and be more specific in the terms used and forums that are to be searched.'
- ),
- array(
- 0 => 'How do I search for members?',
- 1 => 'Visit to the “Members†page and click the “Find a member†link.'
- ),
- array(
- 0 => 'How can I find my own posts and topics?',
- 1 => 'Your own posts can be retrieved either by clicking the “Show your posts†link within the User Control Panel or by clicking the “Search user’s posts†link via your own profile page or by clicking the “Quick links†menu at the top of the board. To search for your topics, use the Advanced search page and fill in the various options appropriately.',
- ),
- array(
- 0 => '--',
- 1 => 'Subscriptions and Bookmarks',
- ),
- array(
- 0 => 'What is the difference between bookmarking and subscribing?',
- 1 => 'In phpBB 3.0, bookmarking topics worked much like bookmarking in a web browser. You were not alerted when there was an update. As of phpBB 3.1, bookmarking is more like subscribing to a topic. You can be notified when a bookmarked topic is updated. Subscribing, however, will notify you when there is an update to a topic or forum on the board. Notification options for bookmarks and subscriptions can be configured in the User Control Panel, under “Board preferencesâ€.',
- ),
- array(
- 0 => 'How do I bookmark or subscribe to specific topics?',
- 1 => 'You can bookmark or subscribe to a specific topic by clicking the appropriate link in the “Topic tools†menu, conveniently located near the top and bottom of a topic discussion.<br />Replying to a topic with the “Notify me when a reply is posted†option checked will also subscribe you to the topic.',
- ),
- array(
- 0 => 'How do I subscribe to specific forums?',
- 1 => 'To subscribe to a specific forum, click the “Subscribe forum†link, at the bottom of page, upon entering the forum.',
- ),
- array(
- 0 => 'How do I remove my subscriptions?',
- 1 => 'To remove your subscriptions, go to your User Control Panel and follow the links to your subscriptions.'
- ),
- array(
- 0 => '--',
- 1 => 'Attachments'
- ),
- array(
- 0 => 'What attachments are allowed on this board?',
- 1 => 'Each board administrator can allow or disallow certain attachment types. If you are unsure what is allowed to be uploaded, contact the board administrator for assistance.'
- ),
- array(
- 0 => 'How do I find all my attachments?',
- 1 => 'To find your list of attachments that you have uploaded, go to your User Control Panel and follow the links to the attachments section.'
- ),
- array(
- 0 => '--',
- 1 => 'phpBB Issues',
- ),
- array(
- 0 => 'Who wrote this bulletin board?',
- 1 => 'This software (in its unmodified form) is produced, released and is copyright <a href="https://www.phpbb.com/">phpBB Limited</a>. It is made available under the GNU General Public License, version 2 (GPL-2.0) and may be freely distributed. See <a href="https://www.phpbb.com/about/">About phpBB</a> for more details.',
- ),
- array(
- 0 => 'Why isn’t X feature available?',
- 1 => 'This software was written by and licensed through phpBB Limited. If you believe a feature needs to be added please visit the <a href="https://www.phpbb.com/ideas/">phpBB Ideas Centre</a>, where you can upvote existing ideas or suggest new features.'
- ),
- array(
- 0 => 'Who do I contact about abusive and/or legal matters related to this board?',
- 1 => 'Any of the administrators listed on the “The team†page should be an appropriate point of contact for your complaints. If this still gets no response then you should contact the owner of the domain (do a <a href="http://www.google.com/search?q=whois">whois lookup</a>) or, if this is running on a free service (e.g. Yahoo!, free.fr, f2s.com, etc.), the management or abuse department of that service. Please note that the phpBB Limited has <strong>absolutely no jurisdiction</strong> and cannot in any way be held liable over how, where or by whom this board is used. Do not contact the phpBB Limited in relation to any legal (cease and desist, liable, defamatory comment, etc.) matter <strong>not directly related</strong> to the phpBB.com website or the discrete software of phpBB itself. If you do email phpBB Limited <strong>about any third party</strong> use of this software then you should expect a terse response or no response at all.'
- ),
- array(
- 0 => 'How do I contact a board administrator?',
- 1 => 'All users of the board can use the “Contact us†form, if the option was enabled by the board administrator.<br />Members of the board can also use the “The team†link.',
- ),
-);
diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php
index 6477a929e9..35cea17a24 100644
--- a/phpBB/language/en/install.php
+++ b/phpBB/language/en/install.php
@@ -1,19 +1,19 @@
<?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.
-*
-*/
+ *
+ * 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.
+ *
+ */
/**
-* DO NOT CHANGE
-*/
+ * DO NOT CHANGE
+ */
if (!defined('IN_PHPBB'))
{
exit;
@@ -36,166 +36,27 @@ 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
+// Common installer pages
$lang = array_merge($lang, array(
- 'ADMIN_CONFIG' => 'Administrator configuration',
- 'ADMIN_PASSWORD' => 'Administrator password',
- 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password',
- 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.',
- 'ADMIN_TEST' => 'Check administrator settings',
- 'ADMIN_USERNAME' => 'Administrator username',
- 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.',
- 'APP_MAGICK' => 'ImageMagick support [ Attachments ]',
- 'AUTHOR_NOTES' => 'Author notes<br />» %s',
- 'AVAILABLE' => 'Available',
- 'AVAILABLE_CONVERTORS' => 'Available convertors',
-
- 'BEGIN_CONVERT' => 'Begin conversion',
- 'BLANK_PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using no table prefix.',
- 'BOARD_NOT_INSTALLED' => 'No installation found',
- 'BOARD_NOT_INSTALLED_EXPLAIN' => 'The phpBB Unified Convertor Framework requires a default installation of phpBB3 to function, please <a href="%s">proceed by first installing phpBB3</a>.',
- 'BACKUP_NOTICE' => 'Please backup your board before updating in case any problems arise during the update process.',
-
- 'CATEGORY' => 'Category',
- 'CACHE_STORE' => 'Cache type',
- 'CACHE_STORE_EXPLAIN' => 'The physical location where data is cached, filesystem is preferred.',
- 'CAT_CONVERT' => 'Convert',
- 'CAT_INSTALL' => 'Install',
- 'CAT_OVERVIEW' => 'Overview',
- 'CAT_UPDATE' => 'Update',
- 'CHANGE' => 'Change',
- 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.',
- 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure',
- 'CLEANING_USERNAMES' => 'Cleaning usernames',
- 'COLLIDING_CLEAN_USERNAME' => '<strong>%s</strong> is the clean username for:',
- 'COLLIDING_USERNAMES_FOUND' => 'Colliding usernames were found on your old board. In order to complete the conversion please delete or rename these users so that there is only one user on your old board for each clean username.',
- 'COLLIDING_USER' => '» user id: <strong>%d</strong> username: <strong>%s</strong> (%d posts)',
- 'CONFIG_CONVERT' => 'Converting the configuration',
- 'CONFIG_FILE_UNABLE_WRITE' => 'It was not possible to write the configuration file. Alternative methods for this file to be created are presented below.',
- 'CONFIG_FILE_WRITTEN' => 'The configuration file has been written. You may now proceed to the next step of the installation.',
- 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s†is empty.',
- 'CONFIG_RETRY' => 'Retry',
- 'CONTINUE_CONVERT' => 'Continue conversion',
- 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.',
- 'CONTINUE_LAST' => 'Continue last statements',
- 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion',
- 'CONVERT' => 'Convert',
- 'CONVERT_COMPLETE' => 'Conversion completed',
- 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.1. You can now login and <a href="../">access your board</a>. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">Documentation</a> and the <a href="https://www.phpbb.com/community/viewforum.php?f=466">support forums</a>.',
- 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework',
- 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.',
- 'CONVERT_NEW_CONVERSION' => 'New conversion',
- 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.',
- 'CONVERT_OPTIONS' => 'Options',
- 'CONVERT_SETTINGS_VERIFIED' => 'The information you entered has been verified. To start the conversion process, please push the button below.',
- 'CONV_ERR_FATAL' => 'Fatal conversion error',
-
- 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.',
- 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.',
- 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.',
- 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.',
- 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.',
- 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%sâ€.',
- 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.',
- 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.',
- 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.',
- 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.',
- 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.',
- 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error',
- 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.',
- 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.',
- 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.',
- 'CONV_ERROR_NO_GROUP' => 'Group “%1$s†could not be found in %2$s.',
- 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.',
- 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.',
- 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.',
- 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.',
- 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.',
- 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.',
- 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.',
- 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.',
- 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s†defined in %2$s.',
- 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.',
- 'CONV_SAVED_MESSAGES' => 'Saved messages',
+ 'INSTALL_PANEL' => 'Installation Panel',
+ 'SELECT_LANG' => 'Select language',
- 'COULD_NOT_COPY' => 'Could not copy file <strong>%1$s</strong> to <strong>%2$s</strong><br /><br />Please check that the target directory exists and is writable by the webserver.',
- 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.<br />» %s was specified as the source path.',
+ 'STAGE_INSTALL' => 'Installing phpBB',
- 'DBMS' => 'Database type',
- 'DB_CONFIG' => 'Database configuration',
- 'DB_CONNECTION' => 'Database connection',
- 'DB_ERR_INSERT' => 'Error while processing <code>INSERT</code> query.',
- 'DB_ERR_LAST' => 'Error while processing <var>query_last</var>.',
- 'DB_ERR_QUERY_FIRST' => 'Error while executing <var>query_first</var>.',
- 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing <var>query_first</var>, %s (“%sâ€).',
- 'DB_ERR_SELECT' => 'Error while running <code>SELECT</code> query.',
- 'DB_HOST' => 'Database server hostname or DSN',
- 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.',
- 'DB_NAME' => 'Database name',
- 'DB_PASSWORD' => 'Database password',
- 'DB_PORT' => 'Database server port',
- 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.',
- 'DB_UPDATE_NOT_SUPPORTED' => 'We are sorry, but this script does not support updating from versions of phpBB prior to “%1$sâ€. The version you currently have installed is “%2$sâ€. Please update to a previous version before running this script. Assistance with this is available in the Support Forum on phpBB.com.',
- 'DB_USERNAME' => 'Database username',
- 'DB_TEST' => 'Test connection',
- 'DEFAULT_LANG' => 'Default board language',
- 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is <strong>%2$s</strong>.',
- 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.',
- 'DIRECTORIES_AND_FILES' => 'Directory and file setup',
- 'DISABLE_KEYS' => 'Disabling keys',
- 'DLL_FTP' => 'Remote FTP support [ Installation ]',
- 'DLL_GD' => 'GD graphics support [ Visual Confirmation ]',
- 'DLL_MBSTRING' => 'Multi-byte character support',
- 'DLL_MSSQL' => 'MSSQL Server 2000+',
- 'DLL_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC',
- 'DLL_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]',
- 'DLL_MYSQL' => 'MySQL',
- 'DLL_MYSQLI' => 'MySQL with MySQLi Extension',
- 'DLL_ORACLE' => 'Oracle',
- 'DLL_POSTGRES' => 'PostgreSQL',
- 'DLL_SQLITE' => 'SQLite 2',
- 'DLL_SQLITE3' => 'SQLite 3',
- 'DLL_XML' => 'XML support [ Jabber ]',
- 'DLL_ZLIB' => 'zlib compression support [ gz, .tar.gz, .zip ]',
- 'DL_CONFIG' => 'Download config',
- 'DL_CONFIG_EXPLAIN' => 'You may download the complete config.php to your own PC. You will then need to upload the file manually, replacing any existing config.php in your phpBB 3.1 root directory. Please remember to upload the file in ASCII format (see your FTP application documentation if you are unsure how to achieve this). When you have uploaded the config.php please click “Done†to move to the next stage.',
- 'DL_DOWNLOAD' => 'Download',
- 'DONE' => 'Done',
+ // Introduction page
+ 'INTRODUCTION_TITLE' => 'Introduction',
+ 'INTRODUCTION_BODY' => 'Welcome to phpBB3!<br /><br />phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.<br /><br />This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read <a href="../docs/INSTALL.html">the installation guide</a>.<br /><br />To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.',
- 'ENABLE_KEYS' => 'Re-enabling keys. This can take a while.',
+ // 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&amp;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 />',
- 'FILES_OPTIONAL' => 'Optional files and directories',
- 'FILES_OPTIONAL_EXPLAIN' => '<strong>Optional</strong> - These files, directories or permission settings are not required. The installation system will attempt to use various techniques to create them if they do not exist or cannot be written to. However, the presence of these will speed installation.',
- 'FILES_REQUIRED' => 'Files and Directories',
- 'FILES_REQUIRED_EXPLAIN' => '<strong>Required</strong> - In order to function correctly phpBB needs to be able to access or write to certain files or directories. If you see “Not Found†you need to create the relevant file or directory. If you see “Unwritable†you need to change the permissions on the file or directory to allow phpBB to write to it.',
- 'FILLING_TABLE' => 'Filling table <strong>%s</strong>',
- 'FILLING_TABLES' => 'Filling tables',
+ // License
+ 'LICENSE_TITLE' => 'General Public License',
- 'FINAL_STEP' => 'Process final step',
- 'FORUM_ADDRESS' => 'Board address',
- 'FORUM_ADDRESS_EXPLAIN' => 'This is the URL of your former board, for example <samp>http://www.example.com/phpBB2/</samp>. If an address is entered here and not left empty every instance of this address will be replaced by your new board address within messages, private messages and signatures.',
- 'FORUM_PATH' => 'Board path',
- 'FORUM_PATH_EXPLAIN' => 'This is the <strong>relative</strong> path on disk to your former board from the <strong>root of this phpBB3 installation</strong>.',
- 'FOUND' => 'Found',
- 'FTP_CONFIG' => 'Transfer config by FTP',
- 'FTP_CONFIG_EXPLAIN' => 'phpBB has detected the presence of the FTP module on this server. You may attempt to install your config.php via this if you wish. You will need to supply the information listed below. Remember your username and password are those to your server! (ask your hosting provider for details if you are unsure what these are).',
- 'FTP_PATH' => 'FTP path',
- 'FTP_PATH_EXPLAIN' => 'This is the path from your root directory to that of phpBB, e.g. <samp>htdocs/phpBB3/</samp>.',
- 'FTP_UPLOAD' => 'Upload',
-
- 'GPL' => 'General Public License',
-
- 'INITIAL_CONFIG' => 'Basic configuration',
- 'INITIAL_CONFIG_EXPLAIN' => 'Now that install has determined your server can run phpBB you need to supply some specific information. If you do not know how to connect to your database please contact your hosting provider (in the first instance) or use the phpBB support forums. When entering data please ensure you check it thoroughly before continuing.',
- 'INSTALL_CONGRATS' => 'Congratulations!',
- 'INSTALL_CONGRATS_EXPLAIN' => '
- You have successfully installed phpBB %1$s. Please proceed by choosing one of the following options:</p>
- <h2>Convert an existing board to phpBB3</h2>
- <p>The phpBB Unified Convertor Framework supports the conversion of phpBB 2.0.x and other board systems to phpBB3. If you have an existing board that you wish to convert, please <a href="%2$s">proceed to the convertor</a>.</p>
- <h2>Go live with your phpBB3!</h2>
- <p>Clicking the button below will take you to a form for submitting statistical data to phpBB in your Administration Control Panel (ACP). We would appreciate it if you could help us by sending that information. Afterwards you should take some time to examine the options available to you. Remember that help is available online via the <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">Documentation</a>, <a href="%3$s">README</a> and the <a href="https://www.phpbb.com/community/viewforum.php?f=466">Support Forums</a>.</p><p><strong>Please delete, move or rename the install directory before using your board. While this directory exists, only the Administration Control Panel (ACP) will be accessible.</strong>',
- 'INSTALL_INTRO' => 'Welcome to Installation',
-
- 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.</p><p>In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:</p>
+ // Install page
+ 'INSTALL_INTRO' => 'Welcome to Installation',
+ 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.</p><p>In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:</p>
<ul>
<li>The Database Type - the database you will be using.</li>
@@ -211,7 +72,6 @@ $lang = array_merge($lang, array(
<ul>
<li>MySQL 3.23 or above (MySQLi supported)</li>
<li>PostgreSQL 8.3+</li>
- <li>SQLite 2.8.2+</li>
<li>SQLite 3.6.15+</li>
<li>MS SQL Server 2000 or above (directly or via ODBC)</li>
<li>MS SQL Server 2005 or above (native)</li>
@@ -219,379 +79,154 @@ $lang = array_merge($lang, array(
</ul>
<p>Only those databases supported on your server will be displayed.',
- 'INSTALL_INTRO_NEXT' => 'To commence the installation, please press the button below.',
- 'INSTALL_LOGIN' => 'Login',
- 'INSTALL_NEXT' => 'Next stage',
- 'INSTALL_NEXT_FAIL' => 'Some tests failed and you should correct these problems before proceeding to the next stage. Failure to do so may result in an incomplete installation.',
- 'INSTALL_NEXT_PASS' => 'All the basic tests have been passed and you may proceed to the next stage of installation. If you have changed any permissions, modules, etc. and wish to re-test you can do so if you wish.',
- 'INSTALL_PANEL' => 'Installation Panel',
- 'INSTALL_SEND_CONFIG' => 'Unfortunately phpBB could not write the configuration information directly to your config.php. This may be because the file does not exist or is not writable. A number of options will be listed below enabling you to complete installation of config.php.',
- 'INSTALL_START' => 'Start install',
- 'INSTALL_TEST' => 'Test again',
- 'INST_ERR' => 'Installation error',
- 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.',
- 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.',
- '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_DB_NO_ERROR' => 'No error message given.',
- 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.',
- 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.',
- 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.',
- 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the <var>NLS_CHARACTERSET</var> parameter to <var>UTF8</var>. Either upgrade your installation to 9.2+ or change the parameter.',
- 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
- 'INST_ERR_DB_NO_NAME' => 'No database name specified.',
- 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.',
- 'INST_ERR_EMAIL_MISMATCH' => 'The emails you entered did not match.',
- 'INST_ERR_FATAL' => 'Fatal installation error',
- 'INST_ERR_FATAL_DB' => 'A fatal and unrecoverable database error has occurred. This may be because the specified user does not have appropriate permissions to <code>CREATE TABLES</code> or <code>INSERT</code> data, etc. Further information may be given below. Please contact your hosting provider in the first instance or the support forums of phpBB for further assistance.',
- 'INST_ERR_FTP_PATH' => 'Could not change to the given directory, please check the path.',
- 'INST_ERR_FTP_LOGIN' => 'Could not login to FTP server, check your username and password.',
- 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.',
- 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.',
- 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.',
- 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.',
- 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.',
- 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.',
- 'INST_ERR_PREFIX_INVALID' => 'The table prefix you have specified is invalid for your database. Please try another, removing characters such as the hyphen.',
- 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.',
- 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.',
- 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.',
- 'INVALID_PRIMARY_KEY' => 'Invalid primary key : %s',
-
- 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.',
-
- // mbstring
- 'MBSTRING_CHECK' => '<samp>mbstring</samp> extension check',
- 'MBSTRING_CHECK_EXPLAIN' => '<strong>Required</strong> - <samp>mbstring</samp> is a PHP extension that provides multibyte string functions. Certain features of mbstring are not compatible with phpBB and must be disabled.',
- 'MBSTRING_FUNC_OVERLOAD' => 'Function overloading',
- 'MBSTRING_FUNC_OVERLOAD_EXPLAIN' => '<var>mbstring.func_overload</var> must be set to either 0 or 4.',
- 'MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding',
- 'MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => '<var>mbstring.encoding_translation</var> must be set to 0.',
- 'MBSTRING_HTTP_INPUT' => 'HTTP input character conversion',
- 'MBSTRING_HTTP_INPUT_EXPLAIN' => '<var>mbstring.http_input</var> must be set to <samp>pass</samp>.',
- 'MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion',
- 'MBSTRING_HTTP_OUTPUT_EXPLAIN' => '<var>mbstring.http_output</var> must be set to <samp>pass</samp>.',
-
- 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:<br />»<strong>%s</strong>.',
- 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:<br />»<strong>%s</strong>.',
-
- 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.<br /><strong>Before you proceed the update, you need to upgrade the schema.</strong><br /><br />Please refer to the <a href="https://www.phpbb.com/kb/article/doesnt-have-a-default-value-errors/">Knowledge Base article about upgrading the MySQL schema</a>. If you encounter problems, please use <a href="https://www.phpbb.com/community/viewforum.php?f=466">our support forums</a>.',
-
- 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases<br /><br />%s',
- 'NEXT_STEP' => 'Proceed to next step',
- 'NOT_FOUND' => 'Cannot find',
- 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%sâ€)',
- 'NO_CONVERTORS' => 'No convertors are available for use.',
- 'NO_CONVERT_SPECIFIED' => 'No convertor specified.',
- 'NO_LOCATION' => 'Cannot determine location. If you know ImageMagick is installed, you may specify the location later within your administration control panel',
- 'NO_TABLES_FOUND' => 'No tables found.',
-
- 'OVERVIEW_BODY' => 'Welcome to phpBB3!<br /><br />phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.<br /><br />This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read <a href="../docs/INSTALL.html">the installation guide</a>.<br /><br />To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.',
-
- 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support',
- 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will <strong>not</strong> run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.',
- 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP function getimagesize() is available',
- 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => '<strong>Required</strong> - In order for phpBB to function correctly, the getimagesize function needs to be available.',
- 'PHP_JSON_SUPPORT' => 'PHP JSON support',
- 'PHP_JSON_SUPPORT_EXPLAIN' => '<strong>Required</strong> - In order for phpBB to function correctly, the PHP JSON extension needs to be available.',
- 'PHP_OPTIONAL_MODULE' => 'Optional modules',
- 'PHP_OPTIONAL_MODULE_EXPLAIN' => '<strong>Optional</strong> - These modules or applications are optional. However, if they are available they will enable extra features.',
- 'PHP_SUPPORTED_DB' => 'Supported databases',
- 'PHP_SUPPORTED_DB_EXPLAIN' => '<strong>Required</strong> - You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.',
- 'PHP_REGISTER_GLOBALS' => 'PHP setting <var>register_globals</var> is disabled',
- 'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.',
- 'PHP_SAFE_MODE' => 'Safe mode',
- 'PHP_SETTINGS' => 'PHP version and settings',
- 'PHP_SETTINGS_EXPLAIN' => '<strong>Required</strong> - You must be running at least version 5.3.3 of PHP (PHP 7 is not supported) in order to install phpBB. If <var>safe mode</var> is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.',
- 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting <var>allow_url_fopen</var> is enabled',
- 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => '<strong>Optional</strong> - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.',
- 'PHP_VERSION_REQD' => 'PHP version: >= 5.3.3, < 7.0.0-dev',
- 'POST_ID' => 'Post ID',
- 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using <strong>%s</strong> as table prefix.',
- 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries',
- 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.',
- 'PROCESS_LAST' => 'Processing last statements',
-
- 'REFRESH_PAGE' => 'Refresh page to continue conversion',
- 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.',
- 'REQUIREMENTS_TITLE' => 'Installation compatibility',
- 'REQUIREMENTS_EXPLAIN' => 'Before proceeding with the full installation phpBB will carry out some tests on your server configuration and files to ensure that you are able to install and run phpBB. Please ensure you read through the results thoroughly and do not proceed until all the required tests are passed. If you wish to use any of the features depending on the optional tests, you should ensure that these tests are passed also.',
- 'RETRY_WRITE' => 'Retry writing config',
- 'RETRY_WRITE_EXPLAIN' => 'If you wish you can change the permissions on config.php to allow phpBB to write to it. Should you wish to do that you can click Retry below to try again. Remember to return the permissions on config.php after phpBB has finished installation.',
-
- 'SCRIPT_PATH' => 'Script path',
- 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. <samp>/phpBB3</samp>.',
- 'SELECT_LANG' => 'Select language',
- 'SERVER_CONFIG' => 'Server configuration',
- 'SEARCH_INDEX_UNCONVERTED' => 'Search index was not converted',
- 'SEARCH_INDEX_UNCONVERTED_EXPLAIN' => 'Your old search index was not converted. Searching will always yield an empty result. To create a new search index go to the Administration Control Panel, select Maintenance and then choose Search index from the submenu.',
- 'SELECT_FORUM_GA' => 'In phpBB 3.1 the global announcements are linked to forums. Select a forum for your current global announcements (can be moved later):',
- 'SOFTWARE' => 'Board software',
- 'SPECIFY_OPTIONS' => 'Specify conversion options',
- 'STAGE_ADMINISTRATOR' => 'Administrator details',
- 'STAGE_ADVANCED' => 'Advanced settings',
- 'STAGE_ADVANCED_EXPLAIN' => 'The settings on this page are only necessary to set if you know that you require something different from the default. If you are unsure, just proceed to the next page, as these settings can be altered from the Administration Control Panel later.',
- 'STAGE_CONFIG_FILE' => 'Configuration file',
- 'STAGE_CREATE_TABLE' => 'Create database tables',
- 'STAGE_CREATE_TABLE_EXPLAIN' => 'The database tables used by phpBB 3.1 have been created and populated with some initial data. Proceed to the next screen to finish installing phpBB.',
- 'STAGE_DATABASE' => 'Database settings',
- 'STAGE_FINAL' => 'Final stage',
- 'STAGE_INTRO' => 'Introduction',
- 'STAGE_IN_PROGRESS' => 'Conversion in progress',
- 'STAGE_REQUIREMENTS' => 'Requirements',
- 'STAGE_SETTINGS' => 'Settings',
- 'STARTING_CONVERT' => 'Starting conversion process',
- 'STEP_PERCENT_COMPLETED' => 'Step <strong>%d</strong> of <strong>%d</strong>',
- 'SUB_INTRO' => 'Introduction',
- 'SUB_LICENSE' => 'License',
- 'SUB_SUPPORT' => 'Support',
- 'SUCCESSFUL_CONNECT' => 'Successful connection',
- '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&amp;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 />',
- 'SYNC_FORUMS' => 'Starting to synchronise forums',
- 'SYNC_POST_COUNT' => 'Synchronising post_counts',
- 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from <var>entry</var> %1$s to %2$s.',
- 'SYNC_TOPICS' => 'Starting to synchronise topics',
- 'SYNC_TOPIC_ID' => 'Synchronising topics from <var>topic_id</var> %1$s to %2$s.',
- 'TABLES_MISSING' => 'Could not find these tables<br />» <strong>%s</strong>.',
- 'TABLE_PREFIX' => 'Prefix for tables in database',
- 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.',
- 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.<br />» Specified table prefix was %s.',
- 'TESTS_PASSED' => 'Tests passed',
- 'TESTS_FAILED' => 'Tests failed',
+ 'ACP_LINK' => 'Take me to <a href="%1$s">the ACP</a>',
- 'UNABLE_WRITE_LOCK' => 'Unable to write lock file.',
- 'UNAVAILABLE' => 'Unavailable',
- 'UNWRITABLE' => 'Unwritable',
- 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information',
- 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.',
- 'VERIFY_OPTIONS' => 'Verifying conversion options',
- 'VERSION' => 'Version',
+ 'INSTALL_PHPBB_INSTALLED' => 'phpBB is already installed.',
+ 'INSTALL_PHPBB_NOT_INSTALLED' => 'phpBB is not installed yet.'
+));
- 'WELCOME_INSTALL' => 'Welcome to phpBB3 Installation',
- 'WRITABLE' => 'Writable',
+// Requirements translation
+$lang = array_merge($lang, array(
+ // Filesystem requirements
+ 'FILE_NOT_EXISTS' => 'File does not exist',
+ 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB the %1$s file needs to exist.',
+ 'FILE_NOT_EXISTS_EXPLAIN_OPTIONAL' => 'It is recommended that the %1$s file exist for a better forum user experience.',
+ 'FILE_NOT_WRITABLE' => 'File is not writable',
+ 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB the %1$s file needs to be writable.',
+ 'FILE_NOT_WRITABLE_EXPLAIN_OPTIONAL' => 'It is recommended that the %1$s file be writable for a better forum user experience.',
+
+ 'DIRECTORY_NOT_EXISTS' => 'Directory does not exist',
+ 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB the %1$s directory needs to exist.',
+ 'DIRECTORY_NOT_EXISTS_EXPLAIN_OPTIONAL' => 'It is recommended that the %1$s directory exist for a better forum user experience.',
+ 'DIRECTORY_NOT_WRITABLE' => 'Directory is not writable',
+ 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB the %1$s directory needs to be writable.',
+ 'DIRECTORY_NOT_WRITABLE_EXPLAIN_OPTIONAL' => 'It is recommended that the %1$s directory be writable for a better forum user experience.',
+
+ // Server requirements
+ 'PHP_VERSION_REQD' => 'PHP version',
+ 'PHP_VERSION_REQD_EXPLAIN' => 'phpBB requires PHP version 5.4.0 or higher.',
+ 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP getimagesize() function is required',
+ 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the getimagesize function needs to be available.',
+ 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support',
+ 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.',
+ 'PHP_JSON_SUPPORT' => 'PHP JSON support',
+ 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.',
+ 'PHP_XML_SUPPORT' => 'PHP XML/DOM support',
+ 'PHP_XML_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP XML/DOM extension needs to be available.',
+ 'PHP_SUPPORTED_DB' => 'Supported databases',
+ 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.',
+
+ 'RETEST_REQUIREMENTS' => 'Retest requirements',
+
+ 'STAGE_REQUIREMENTS' => 'Check requirements'
));
-// Updater
+// General error messages
$lang = array_merge($lang, array(
- 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version.',
- 'ARCHIVE_FILE' => 'Source file within archive',
-
- 'BACK' => 'Back',
- 'BINARY_FILE' => 'Binary file',
- 'BOT' => 'Spider/Robot',
-
- 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.',
- 'CHECK_FILES' => 'Check files',
- 'CHECK_FILES_AGAIN' => 'Check files again',
- 'CHECK_FILES_EXPLAIN' => 'Within the next step all files will be checked against the update files - this can take a while if this is the first file check.',
- 'CHECK_FILES_UP_TO_DATE' => 'According to your database your version is up to date. You may want to proceed with the file check to make sure all files are really up to date with the latest phpBB version.',
- 'CHECK_UPDATE_DATABASE' => 'Continue update process',
- 'COLLECTED_INFORMATION' => 'File information',
- 'COLLECTED_INFORMATION_EXPLAIN' => 'The list below shows information about the files needing an update. Please read the information in front of every status block to see what they mean and what you may need to do to perform a successful update.',
- 'COLLECTING_FILE_DIFFS' => 'Collecting file differences',
- 'COMPLETE_LOGIN_TO_BOARD' => 'You should now <a href="../ucp.php?mode=login">login to your board</a> and check if everything is working fine. Do not forget to delete, rename or move your install directory!',
- 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater
- 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished
- 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update',
- 'CURRENT_VERSION' => 'Current version',
-
- 'DATABASE_TYPE' => 'Database type',
- 'DATABASE_UPDATE_COMPLETE' => 'Database updater has completed!',
- 'DATABASE_UPDATE_CONTINUE' => 'Continue database update',
- 'DATABASE_UPDATE_INFO_OLD' => 'The database update file within the install directory is outdated. Please make sure you uploaded the correct version of the file.',
- 'DATABASE_UPDATE_NOT_COMPLETED' => 'The database update has not yet completed.',
- 'DATABASE_VERSION' => 'Database version',
- 'DELETE_USER_REMOVE' => 'Delete user and remove posts',
- 'DELETE_USER_RETAIN' => 'Delete user but keep posts',
- 'DESTINATION' => 'Destination file',
- 'DIFF_INLINE' => 'Inline',
- 'DIFF_RAW' => 'Raw unified diff',
- 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file',
- 'DIFF_SIDE_BY_SIDE' => 'Side by Side',
- 'DIFF_UNIFIED' => 'Unified diff',
- 'DO_NOT_UPDATE' => 'Do not update this file',
- 'DONE' => 'Done',
- 'DOWNLOAD' => 'Download',
- 'DOWNLOAD_AS' => 'Download as',
- 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)',
- 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file',
- 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for &lt;&lt;&lt; to spot conflicts',
- 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive',
- 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.',
+ 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.',
- 'EDIT_USERNAME' => 'Edit username',
- 'ERROR' => 'Error',
- 'EVERYTHING_UP_TO_DATE' => 'Everything is up to date with the latest phpBB version. You should now <a href="%1$s">login to your board</a> and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the <a href="%2$s">Send statistics</a> module in your ACP.',
+ 'TIMEOUT_DETECTED_TITLE' => 'The installer detected a timeout',
+ 'TIMEOUT_DETECTED_MESSAGE' => 'The installer has detected a timeout, you may try to refresh the page, which may lead to data corruption. We suggest that you either increase your timeout settings or try to use the CLI.',
+));
- 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.',
- 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.',
- 'FILE_USED' => 'Information used from', // Single file
- 'FILES_CONFLICT' => 'Conflict files',
- 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.',
- 'FILES_DELETED' => 'Deleted files',
- 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.',
- 'FILES_MODIFIED' => 'Modified files',
- 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.',
- 'FILES_NEW' => 'New files',
- 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.',
- 'FILES_NEW_CONFLICT' => 'New conflicting files',
- 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.',
- 'FILES_NOT_MODIFIED' => 'Not modified files',
- 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.',
- 'FILES_UP_TO_DATE' => 'Already updated files',
- 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.',
- 'FILES_VERSION' => 'Files Version',
- 'FTP_SETTINGS' => 'FTP settings',
- 'FTP_UPDATE_METHOD' => 'FTP upload',
+// Data obtaining translations
+$lang = array_merge($lang, array(
+ 'STAGE_OBTAIN_DATA' => 'Set installation data',
- 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.',
- 'INCOMPLETE_UPDATE_FILES' => 'The update files are incomplete.',
- 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful. Now you need to continue the update process.',
-
- 'KEEP_OLD_NAME' => 'Keep username',
-
- 'LATEST_VERSION' => 'Latest version',
- 'LINE' => 'Line',
- 'LINE_ADDED' => 'Added',
- 'LINE_MODIFIED' => 'Modified',
- 'LINE_REMOVED' => 'Removed',
- 'LINE_UNMODIFIED' => 'Unmodified',
- 'LOGIN_UPDATE_EXPLAIN' => 'In order to update your installation you need to login first.',
-
- 'MAPPING_FILE_STRUCTURE' => 'To ease the upload here are the file locations which map your phpBB installation.',
-
- 'MERGE_MODIFICATIONS_OPTION' => 'Merge modifications',
-
- 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file',
- 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file',
- 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)',
- 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)',
- 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.',
- 'MERGING_FILES' => 'Merging differences',
- 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.<br /><br />Please wait until phpBB has completed all operations on changed files.',
-
- 'NEW_FILE' => 'End of Conflict',
- 'NEW_USERNAME' => 'New username',
- 'NO_AUTH_UPDATE' => 'Not authorised to update',
- 'NO_ERRORS' => 'No errors',
- 'NO_UPDATE_FILES' => 'Not updating the following files',
- 'NO_UPDATE_FILES_EXPLAIN' => 'The following files are new or modified but the directory they normally reside in could not be found on your installation. If this list contains files to other directories than language/ or styles/ than you may have modified your directory structure and the update may be incomplete.',
- 'NO_UPDATE_FILES_OUTDATED' => 'No valid update directory was found, please make sure you uploaded the relevant files.<br /><br />Your installation does <strong>not</strong> seem to be up to date. Updates are available for your version of phpBB %1$s, please visit <a href="https://www.phpbb.com/downloads/" rel="external">https://www.phpbb.com/downloads/</a> to obtain the correct package to update from Version %2$s to Version %3$s.',
- 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.',
- 'NO_UPDATE_INFO' => 'Update file information could not be found.',
- 'NO_UPDATES_REQUIRED' => 'No updates required',
- 'NO_VISIBLE_CHANGES' => 'No visible changes',
- 'NOTICE' => 'Notice',
- 'NUM_CONFLICTS' => 'Number of conflicts',
- 'NUMBER_OF_FILES_COLLECTED' => 'Currently differences from %1$d of %2$d files have been checked.<br />Please wait until all files are checked.',
+ //
+ // Admin data
+ //
+ 'STAGE_ADMINISTRATOR' => 'Administrator details',
- 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.',
+ // Form labels
+ 'ADMIN_CONFIG' => 'Administrator configuration',
+ 'ADMIN_PASSWORD' => 'Administrator password',
+ 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password',
+ 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.',
+ 'ADMIN_USERNAME' => 'Administrator username',
+ 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.',
- 'PACKAGE_UPDATES_TO' => 'Current package updates to version',
+ // Errors
+ 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.',
+ 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.',
+ 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.',
+ 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.',
+ 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.',
+ 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.',
+
+ //
+ // Board data
+ //
+ // Form labels
+ 'BOARD_CONFIG' => 'Bulletin board configuration',
+ 'DEFAULT_LANGUAGE' => 'Default language',
+ 'BOARD_NAME' => 'Title of the board',
+ 'BOARD_DESCRIPTION' => 'Short description of the board',
+
+ //
+ // Database data
+ //
+ 'STAGE_DATABASE' => 'Database settings',
+
+ // Form labels
+ 'DB_CONFIG' => 'Database configuration',
+ 'DBMS' => 'Database type',
+ 'DB_HOST' => 'Database server hostname or DSN',
+ 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.',
+ 'DB_PORT' => 'Database server port',
+ 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.',
+ 'DB_PASSWORD' => 'Database password',
+ 'DB_NAME' => 'Database name',
+ 'DB_USERNAME' => 'Database username',
+ 'DATABASE_VERSION' => 'Database version',
+ 'TABLE_PREFIX' => 'Prefix for tables in database',
+ 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.',
+
+ // Database options
+ 'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC',
+ 'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]',
+ 'DB_OPTION_MYSQL' => 'MySQL',
+ 'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension',
+ 'DB_OPTION_ORACLE' => 'Oracle',
+ 'DB_OPTION_POSTGRES' => 'PostgreSQL',
+ 'DB_OPTION_SQLITE3' => 'SQLite 3',
+
+ // Errors
+ '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.',
+ 'INST_ERR_DB_NO_NAME' => 'No database name specified.',
+ 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.',
+ 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.',
+ 'INST_ERR_DB_NO_ERROR' => 'No error message given.',
+ 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.',
+ 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension†option you have selected. Please try the “MySQL†option instead.',
+ 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.',
+ 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the <var>NLS_CHARACTERSET</var> parameter to <var>UTF8</var>. Either upgrade your installation to 9.2+ or change the parameter.',
+ 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
+ 'INST_SCHEMA_FILE_NOT_WRITABLE' => 'The schema file is not writable',
+
+ //
+ // Email data
+ //
+ 'EMAIL_CONFIG' => 'E-mail configuration',
+
+ // Package info
'PACKAGE_VERSION' => 'Package version installed',
- 'PERFORM_DATABASE_UPDATE' => 'Perform database update',
- 'PERFORM_DATABASE_UPDATE_EXPLAIN' => 'Below you will find a button to the database update script. The database update can take a while, so please do not stop the execution if it seems to hang. After the database update has been performed just follow the instructions to continue the update process.',
- 'PREVIOUS_VERSION' => 'Previous version',
- 'PROGRESS' => 'Progress',
-
- 'RELEASE_ANNOUNCEMENT' => 'Announcement',
- 'RESULT' => 'Result',
- 'RUN_DATABASE_SCRIPT' => 'Update my database now',
-
- 'SELECT_DIFF_MODE' => 'Select diff mode',
- 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format',
- 'SELECT_FTP_SETTINGS' => 'Select FTP settings',
- 'SHOW_DIFF_CONFLICT' => 'Show differences/conflicts',
- 'SHOW_DIFF_DELETED' => 'Show file contents',
- 'SHOW_DIFF_FINAL' => 'Show resulting file',
- 'SHOW_DIFF_MODIFIED' => 'Show merged differences',
- 'SHOW_DIFF_NEW' => 'Show file contents',
- 'SHOW_DIFF_NEW_CONFLICT' => 'Show differences',
- 'SHOW_DIFF_NOT_MODIFIED' => 'Show differences',
- 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.',
- 'SQL' => 'SQL',
- 'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See <a href="../docs/README.html">README</a> for details on how to obtain advice.',
- 'STAGE_FILE_CHECK' => 'Check files',
- 'STAGE_UPDATE_DB' => 'Update database',
- 'STAGE_UPDATE_FILES' => 'Update files',
- 'STAGE_VERSION_CHECK' => 'Version check',
- 'STATUS_CONFLICT' => 'Modified file producing conflicts',
- 'STATUS_DELETED' => 'Deleted file',
- 'STATUS_MODIFIED' => 'Modified file',
- 'STATUS_NEW' => 'New file',
- 'STATUS_NEW_CONFLICT' => 'Conflicting new file',
- 'STATUS_NOT_MODIFIED' => 'Not modified file',
- 'STATUS_UP_TO_DATE' => 'Already updated file',
-
- 'TOGGLE_DISPLAY' => 'View/Hide file list',
- 'TRY_DOWNLOAD_METHOD' => 'You may want to try the download modified files method.<br />This method always works and is also the recommended update path.',
- 'TRY_DOWNLOAD_METHOD_BUTTON'=> 'Try this method now',
-
- 'UPDATE_COMPLETED' => 'Update completed',
- 'UPDATE_DATABASE' => 'Update database',
- 'UPDATE_DATABASE_EXPLAIN' => 'Within the next step the database will be updated.',
- 'UPDATE_DATABASE_SCHEMA' => 'Updating database schema',
- 'UPDATE_FILES' => 'Update files',
- 'UPDATE_FILES_NOTICE' => 'Please make sure you have updated your board files too, this file is only updating your database.',
'UPDATE_INCOMPLETE' => 'Your phpBB installation has not been correctly updated.',
'UPDATE_INCOMPLETE_MORE' => 'Please read the information below in order to fix this error.',
'UPDATE_INCOMPLETE_EXPLAIN' => '<h1>Incomplete update</h1>
- <p>We noticed that the last update of your phpBB installation hasn’t been completed. Visit the <a href="%1$s" title="%1$s">database_update script</a> and run it. If it is missing, please <a href="https://www.phpbb.com/downloads/" title="phpBB downloads">download your package version</a>, upload the "install" folder to your phpBB root directory (where your config.php file is) and <a href="%1$s" title="%1$s">run the database update script</a>.</p>',
-
- 'UPDATE_INSTALLATION' => 'Update phpBB installation',
- 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.<br />During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.<br /><br />The file update itself can be done in two different ways.</p><h2>Manual Update</h2><p>With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.</p><h2>Automatic Update with FTP</h2><p>This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.<br /><br />',
- 'UPDATE_INSTRUCTIONS' => '
-
- <h1>Release announcement</h1>
-
- <p>Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.</p>
-
- <br />
-
- <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>We noticed that the last update of your phpBB installation hasn’t been completed. Visit the <a href="%1$s" title="%1$s">database updater</a>, ensure <em>Update database only</em> is selected and click on <strong>Submit</strong>. Don\'t forget to delete the "install"-directory after you have updated the database sucessfully.</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>
-
- <p>Once uploaded your board will be offline for normal users due to the install directory you uploaded now 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.
- </p>
- ',
- 'UPDATE_METHOD' => 'Update method',
- 'UPDATE_METHOD_EXPLAIN' => 'You are now able to choose your preferred update method. Using the FTP upload will present you with a form you need to enter your FTP account details into. With this method the files will be automatically moved to the new location and backups of the old files being created by appending .bak to the filename. If you choose to download the modified files you are able to unpack and upload them to their correct location manually later.',
- 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s',
- 'UPDATE_SUCCESS' => 'Update was successful',
- 'UPDATE_SUCCESS_EXPLAIN' => 'Successfully updated all files. The next step involves checking all files again to make sure the files got updated correctly.',
- 'UPDATE_VERSION_OPTIMIZE' => 'Updating version and optimising tables',
- 'UPDATING_DATA' => 'Updating data',
- 'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release',
- 'UPDATED_VERSION' => 'Updated version',
- 'UPLOAD_METHOD' => 'Upload method',
-
- 'UPDATE_DB_SUCCESS' => 'Database update was successful.',
- 'UPDATE_FILE_SUCCESS' => 'File update was successful.',
- 'USER_ACTIVE' => 'Active user',
- 'USER_INACTIVE' => 'Inactive user',
-
- 'VERSION_CHECK' => 'Version check',
- 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.',
- 'VERSION_NOT_UP_TO_DATE' => 'Your phpBB installation is not up to date. Please continue the update process.',
- 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.<br />Below is a link to the release announcement, which contains more information as well as instructions on updating.',
- 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.',
- 'VERSION_UP_TO_DATE' => 'Your phpBB installation is up to date. Although there are no updates available at this time, you may continue in order to perform a file validity check.',
- 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.',
- 'VIEWING_FILE_CONTENTS' => 'Viewing file contents',
- 'VIEWING_FILE_DIFF' => 'Viewing file differences',
-
- 'WRONG_INFO_FILE_FORMAT' => 'Wrong info file format',
+ //
+ // Server data
+ //
+ // Form labels
+ 'SERVER_CONFIG' => 'Server configuration',
+ 'SCRIPT_PATH' => 'Script path',
+ 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. <samp>/phpBB3</samp>.',
));
// Default database schema entries...
@@ -639,3 +274,296 @@ $lang = array_merge($lang, array(
'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3',
));
+
+// Common navigation items' translation
+$lang = array_merge($lang, array(
+ 'MENU_OVERVIEW' => 'Overview',
+ 'MENU_INTRO' => 'Introduction',
+ 'MENU_LICENSE' => 'License',
+ 'MENU_SUPPORT' => 'Support',
+));
+
+// Task names
+$lang = array_merge($lang, array(
+ // Install filesystem
+ 'TASK_CREATE_CONFIG_FILE' => 'Creating configuration file',
+
+ // Install database
+ 'TASK_ADD_CONFIG_SETTINGS' => 'Adding configuration settings',
+ 'TASK_ADD_DEFAULT_DATA' => 'Adding default settings to the database',
+ 'TASK_CREATE_DATABASE_SCHEMA_FILE' => 'Creating database schema file',
+ 'TASK_SETUP_DATABASE' => 'Setting up database',
+ 'TASK_CREATE_TABLES' => 'Creating tables',
+
+ // Install data
+ 'TASK_ADD_BOTS' => 'Registering bots',
+ 'TASK_ADD_LANGUAGES' => 'Installing available languages',
+ 'TASK_ADD_MODULES' => 'Installing modules',
+
+ // Install finish tasks
+ 'TASK_NOTIFY_USER' => 'Sending notification e-mail',
+ 'TASK_POPULATE_MIGRATIONS' => 'Populating migrations',
+
+ // Installer general progress messages
+ 'INSTALLER_FINISHED' => 'The installer has finished successfully',
+));
+
+// Installer's general messages
+$lang = array_merge($lang, array(
+ 'MODULE_NOT_FOUND' => 'Module not found',
+ 'MODULE_NOT_FOUND_DESCRIPTION' => 'A module could not be found because the service, %s, is undefined.',
+
+ 'TASK_NOT_FOUND' => 'Task not found',
+ 'TASK_NOT_FOUND_DESCRIPTION' => 'A task could not be found because the service, %s, is undefined.',
+
+ 'SKIP_MODULE' => 'Skip “%s†module',
+ 'SKIP_TASK' => 'Skip “%s†task',
+
+ 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installerâ€',
+ 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s†given, the expected class namespace is “%2$s†for that. For more information please see the documentation of task_interface.',
+
+ 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.',
+));
+
+// CLI messages
+$lang = array_merge($lang, array(
+ 'CLI_INSTALL_BOARD' => 'Install phpBB',
+ 'CLI_UPDATE_BOARD' => 'Update phpBB',
+ 'CLI_INSTALL_SHOW_CONFIG' => 'Show the configuration which will be used',
+ 'CLI_INSTALL_VALIDATE_CONFIG' => 'Validate a configuration file',
+ 'CLI_CONFIG_FILE' => 'Config file to use',
+ 'MISSING_FILE' => 'Unable to access file %1$s',
+ 'MISSING_DATA' => 'Config file is missing data or might contain invalid settings.',
+ 'INVALID_YAML_FILE' => 'Could not parse YAML file %1$s',
+ 'CONFIGURATION_VALID' => 'The configuration file is valid',
+));
+
+// Common updater messages
+$lang = array_merge($lang, array(
+ 'UPDATE_INSTALLATION' => 'Update phpBB installation',
+ 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.<br />During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.<br /><br />The file update itself can be done in two different ways.</p><h2>Manual Update</h2><p>With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.</p><h2>Automatic Update with FTP</h2><p>This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.<br /><br />',
+ 'UPDATE_INSTRUCTIONS' => '
+
+ <h1>Release announcement</h1>
+
+ <p>Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.</p>
+
+ <br />
+
+ <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>
+
+ <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>
+
+ <p>Once uploaded your board will be offline for normal users due to the install directory you uploaded now 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.
+ </p>
+ ',
+));
+
+// Updater forms
+$lang = array_merge($lang, array(
+ // Updater types
+ 'UPDATE_TYPE' => 'Type of update to run',
+
+ 'UPDATE_TYPE_ALL' => 'Update filesystem and database',
+ 'UPDATE_TYPE_DB_ONLY' => 'Update database only',
+
+ // File updater methods
+ 'UPDATE_FILE_METHOD_TITLE' => 'File updater methods',
+
+ 'UPDATE_FILE_METHOD' => 'File updater method',
+ 'UPDATE_FILE_METHOD_DOWNLOAD' => 'Download modified files in an archive',
+ 'UPDATE_FILE_METHOD_FTP' => 'Update files via FTP (Automatic)',
+ 'UPDATE_FILE_METHOD_FILESYSTEM' => 'Update files via direct file access (Automatic)',
+
+ // File updater archives
+ 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format',
+
+ // FTP settings
+ 'FTP_SETTINGS' => 'FTP settings',
+));
+
+// Requirements messages
+$lang = array_merge($lang, array(
+ 'UPDATE_FILES_NOT_FOUND' => 'No valid update directory was found, please make sure you uploaded the relevant files.',
+
+ 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.',
+ 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.',
+ 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.',
+));
+
+// Update files
+$lang = array_merge($lang, array(
+ 'STAGE_UPDATE_FILES' => 'Update files',
+
+ // Check files
+ 'UPDATE_CHECK_FILES' => 'Check files to update',
+
+ // Update file differ
+ 'FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ' => 'The file differ failed to open %s.',
+
+ 'UPDATE_FILE_DIFF' => 'Diffing changed files',
+ 'ALL_FILES_DIFFED' => 'All modified files has been diffed.',
+
+ // File status
+ 'UPDATE_CONTINUE_FILE_UPDATE' => 'Update files',
+
+ 'DOWNLOAD' => 'Download',
+ 'DOWNLOAD_CONFLICTS' => 'Download merge conflicts archive',
+ 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for &lt;&lt;&lt; to spot conflicts',
+ 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive',
+ 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, you may continue with the update process.',
+
+ 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.',
+ 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.',
+ 'FILE_USED' => 'Information used from', // Single file
+ 'FILES_CONFLICT' => 'Conflict files',
+ 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.',
+ 'FILES_DELETED' => 'Deleted files',
+ 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.',
+ 'FILES_MODIFIED' => 'Modified files',
+ 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.',
+ 'FILES_NEW' => 'New files',
+ 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.',
+ 'FILES_NEW_CONFLICT' => 'New conflicting files',
+ 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.',
+ 'FILES_NOT_MODIFIED' => 'Not modified files',
+ 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.',
+ 'FILES_UP_TO_DATE' => 'Already updated files',
+ 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.',
+ 'FILES_VERSION' => 'Files Version',
+ 'TOGGLE_DISPLAY' => 'View/Hide file list',
+
+ // File updater
+ 'UPDATE_UPDATING_FILES' => 'Updating files',
+
+ 'UPDATE_FILE_UPDATER_HAS_FAILED' => 'File updater “%1$s“ has failed. The installer will try to fallback to “%2$s“.',
+ 'UPDATE_FILE_UPDATERS_HAVE_FAILED' => 'The file updater failed. No further fallback methods are available.',
+
+ 'UPDATE_CONTINUE_UPDATE_PROCESS' => 'Continue update process',
+ 'UPDATE_RECHECK_UPDATE_FILES' => 'Check files again',
+));
+
+// Update database
+$lang = array_merge($lang, array(
+ 'STAGE_UPDATE_DATABASE' => 'Update database',
+
+ 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful.',
+));
+
+// Converter
+$lang = array_merge($lang, array(
+ // Common converter messages
+ 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.',
+ 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.',
+ 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.<br />» %s was specified as the source path.',
+ 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s†is empty.',
+
+ 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:<br />»<strong>%s</strong>.',
+ 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:<br />»<strong>%s</strong>.',
+
+ 'INSTALL_TEST' => 'Test again',
+
+ 'NO_TABLES_FOUND' => 'No tables found.',
+ 'TABLES_MISSING' => 'Could not find these tables<br />» <strong>%s</strong>.',
+ 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.',
+
+ // Conversion in progress
+ 'CONTINUE_CONVERT' => 'Continue conversion',
+ 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.',
+ 'CONVERT_NEW_CONVERSION' => 'New conversion',
+ 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion',
+
+ // Start conversion
+ 'SUB_INTRO' => 'Introduction',
+ 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework',
+ 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.',
+ 'AVAILABLE_CONVERTORS' => 'Available convertors',
+ 'NO_CONVERTORS' => 'No convertors are available for use.',
+ 'CONVERT_OPTIONS' => 'Options',
+ 'SOFTWARE' => 'Board software',
+ 'VERSION' => 'Version',
+ 'CONVERT' => 'Convert',
+
+ // Settings
+ 'STAGE_SETTINGS' => 'Settings',
+ 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.<br />» Specified table prefix was %s.',
+ 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is <strong>%2$s</strong>.',
+ 'SPECIFY_OPTIONS' => 'Specify conversion options',
+ 'FORUM_PATH' => 'Board path',
+ 'FORUM_PATH_EXPLAIN' => 'This is the <strong>relative</strong> path on disk to your former board from the <strong>root of this phpBB3 installation</strong>.',
+ 'REFRESH_PAGE' => 'Refresh page to continue conversion',
+ 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.',
+
+ // Conversion
+ 'STAGE_IN_PROGRESS' => 'Conversion in progress',
+
+ 'AUTHOR_NOTES' => 'Author notes<br />» %s',
+ 'STARTING_CONVERT' => 'Starting conversion process',
+ 'CONFIG_CONVERT' => 'Converting the configuration',
+ 'DONE' => 'Done',
+ 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries',
+ 'FILLING_TABLE' => 'Filling table <strong>%s</strong>',
+ 'FILLING_TABLES' => 'Filling tables',
+ 'DB_ERR_INSERT' => 'Error while processing <code>INSERT</code> query.',
+ 'DB_ERR_LAST' => 'Error while processing <var>query_last</var>.',
+ 'DB_ERR_QUERY_FIRST' => 'Error while executing <var>query_first</var>.',
+ 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing <var>query_first</var>, %s (“%sâ€).',
+ 'DB_ERR_SELECT' => 'Error while running <code>SELECT</code> query.',
+ 'STEP_PERCENT_COMPLETED' => 'Step <strong>%d</strong> of <strong>%d</strong>',
+ 'FINAL_STEP' => 'Process final step',
+ 'SYNC_FORUMS' => 'Starting to synchronise forums',
+ 'SYNC_POST_COUNT' => 'Synchronising post_counts',
+ 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from <var>entry</var> %1$s to %2$s.',
+ 'SYNC_TOPICS' => 'Starting to synchronise topics',
+ 'SYNC_TOPIC_ID' => 'Synchronising topics from <var>topic_id</var> %1$s to %2$s.',
+ 'PROCESS_LAST' => 'Processing last statements',
+ 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information',
+ 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.',
+ 'CONTINUE_LAST' => 'Continue last statements',
+ 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure',
+ 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%sâ€)',
+ 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases<br /><br />%s',
+
+ // Finish conversion
+ 'CONVERT_COMPLETE' => 'Conversion completed',
+ 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.2. You can now login and <a href="../">access your board</a>. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the <a href="https://www.phpbb.com/support/docs/en/3.2/ug/">Documentation</a> and the <a href="https://www.phpbb.com/community/viewforum.php?f=466">support forums</a>.',
+
+ 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.',
+ 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.',
+ 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.',
+ 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.',
+ 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.',
+ 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%sâ€.',
+ 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.',
+ 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.',
+ 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.',
+ 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.',
+ 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.',
+ 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error',
+ 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.',
+ 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.',
+ 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.',
+ 'CONV_ERROR_NO_GROUP' => 'Group “%1$s†could not be found in %2$s.',
+ 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.',
+ 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.',
+ 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.',
+ 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.',
+ 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.',
+ 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.',
+ 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.',
+ 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.',
+ 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s†defined in %2$s.',
+ 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.',
+ 'CONV_SAVED_MESSAGES' => 'Saved messages',
+
+ 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.',
+));
diff --git a/phpBB/language/en/mcp.php b/phpBB/language/en/mcp.php
index a961068657..b196a1d658 100644
--- a/phpBB/language/en/mcp.php
+++ b/phpBB/language/en/mcp.php
@@ -135,6 +135,7 @@ $lang = array_merge($lang, array(
'LOCK_TOPICS_CONFIRM' => 'Are you sure you want to lock all selected topics?',
'LOGS_CURRENT_TOPIC' => 'Currently viewing logs of:',
'LOGIN_EXPLAIN_MCP' => 'To moderate this forum you must login.',
+ 'LOGVIEW_VIEWPOST' => 'View post',
'LOGVIEW_VIEWTOPIC' => 'View topic',
'LOGVIEW_VIEWLOGS' => 'View topic log',
'LOGVIEW_VIEWFORUM' => 'View forum',
diff --git a/phpBB/language/en/migrator.php b/phpBB/language/en/migrator.php
index b3b5995cc0..8a82d40be5 100644
--- a/phpBB/language/en/migrator.php
+++ b/phpBB/language/en/migrator.php
@@ -48,11 +48,19 @@ $lang = array_merge($lang, array(
'MIGRATION_EFFECTIVELY_INSTALLED' => 'Migration already effectively installed (skipped): %s',
'MIGRATION_EXCEPTION_ERROR' => 'Something went wrong during the request and an exception was thrown. The changes made before the error occurred were reversed to the best of our abilities, but you should check the board for errors.',
'MIGRATION_NOT_FULFILLABLE' => 'The migration "%1$s" is not fulfillable, missing migration "%2$s".',
+ 'MIGRATION_NOT_INSTALLED' => 'The migration "%s" is not installed.',
'MIGRATION_NOT_VALID' => '%s is not a valid migration.',
'MIGRATION_SCHEMA_DONE' => 'Installed Schema: %1$s; Time: %2$.2f seconds',
'MIGRATION_SCHEMA_IN_PROGRESS' => 'Installing Schema: %1$s; Time: %2$.2f seconds',
'MIGRATION_SCHEMA_RUNNING' => 'Installing Schema: %s.',
+ 'MIGRATION_REVERT_DATA_DONE' => 'Reverted Data: %1$s; Time: %2$.2f seconds',
+ 'MIGRATION_REVERT_DATA_IN_PROGRESS' => 'Reverting Data: %1$s; Time: %2$.2f seconds',
+ 'MIGRATION_REVERT_DATA_RUNNING' => 'Reverting Data: %s.',
+ 'MIGRATION_REVERT_SCHEMA_DONE' => 'Reverted Schema: %1$s; Time: %2$.2f seconds',
+ 'MIGRATION_REVERT_SCHEMA_IN_PROGRESS' => 'Reverting Schema: %1$s; Time: %2$.2f seconds',
+ 'MIGRATION_REVERT_SCHEMA_RUNNING' => 'Reverting Schema: %s.',
+
'MIGRATION_INVALID_DATA_MISSING_CONDITION' => 'A migration is invalid. An if statement helper is missing a condition.',
'MIGRATION_INVALID_DATA_MISSING_STEP' => 'A migration is invalid. An if statement helper is missing a valid call to a migration step.',
'MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE' => 'A migration is invalid. A custom callable function could not be called.',
diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php
index ef52f59753..68b81a6eaf 100644
--- a/phpBB/language/en/posting.php
+++ b/phpBB/language/en/posting.php
@@ -182,8 +182,10 @@ $lang = array_merge($lang, array(
'NO_POLL_TITLE' => 'You have to enter a poll title.',
'NO_POST' => 'The requested post does not exist.',
'NO_POST_MODE' => 'No post mode specified.',
+ 'NO_TEMP_DIR' => 'Temporary folder could not be found or is not writable.',
'PARTIAL_UPLOAD' => 'The uploaded file was only partially uploaded.',
+ 'PHP_UPLOAD_STOPPED' => 'A PHP extension has stopped the file upload.',
'PHP_SIZE_NA' => 'The attachment’s file size is too large.<br />Could not determine the maximum size defined by PHP in php.ini.',
'PHP_SIZE_OVERRUN' => 'The attachment’s file size is too large, the maximum upload size is %1$d %2$s.<br />Please note this is set in php.ini and cannot be overridden.',
'PLACE_INLINE' => 'Place inline',
diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php
index 59525c6b16..ec7f3fe714 100644
--- a/phpBB/language/en/ucp.php
+++ b/phpBB/language/en/ucp.php
@@ -327,6 +327,7 @@ $lang = array_merge($lang, array(
'NOTIFICATION_GROUP_MODERATION' => 'Moderation Notifications',
'NOTIFICATION_GROUP_ADMINISTRATION' => 'Administration Notifications',
'NOTIFICATION_GROUP_POSTING' => 'Posting Notifications',
+ 'NOTIFICATION_METHOD_BOARD' => 'Notifications',
'NOTIFICATION_METHOD_EMAIL' => 'Email',
'NOTIFICATION_METHOD_JABBER' => 'Jabber',
'NOTIFICATION_TYPE' => 'Notification type',
diff --git a/phpBB/mcp.php b/phpBB/mcp.php
index f9d46db528..a5464f4a73 100644
--- a/phpBB/mcp.php
+++ b/phpBB/mcp.php
@@ -33,10 +33,10 @@ $module = new p_master();
$template->assign_var('S_IN_MCP', true);
// Basic parameter data
-$id = request_var('i', '');
+$id = $request->variable('i', '');
-$mode = request_var('mode', array(''));
-$mode = sizeof($mode) ? array_shift($mode) : request_var('mode', '');
+$mode = $request->variable('mode', array(''));
+$mode = sizeof($mode) ? array_shift($mode) : $request->variable('mode', '');
// Only Moderators can go beyond this point
if (!$user->data['is_registered'])
@@ -50,10 +50,10 @@ if (!$user->data['is_registered'])
}
$quickmod = (isset($_REQUEST['quickmod'])) ? true : false;
-$action = request_var('action', '');
-$action_ary = request_var('action', array('' => 0));
+$action = $request->variable('action', '');
+$action_ary = $request->variable('action', array('' => 0));
-$forum_action = request_var('forum_action', '');
+$forum_action = $request->variable('forum_action', '');
if ($forum_action !== '' && $request->variable('sort', false, false, \phpbb\request\request_interface::POST))
{
$action = $forum_action;
@@ -71,12 +71,12 @@ if ($mode == 'topic_logs')
$quickmod = false;
}
-$post_id = request_var('p', 0);
-$topic_id = request_var('t', 0);
-$forum_id = request_var('f', 0);
-$report_id = request_var('r', 0);
-$user_id = request_var('u', 0);
-$username = utf8_normalize_nfc(request_var('username', '', true));
+$post_id = $request->variable('p', 0);
+$topic_id = $request->variable('t', 0);
+$forum_id = $request->variable('f', 0);
+$report_id = $request->variable('r', 0);
+$user_id = $request->variable('u', 0);
+$username = $request->variable('username', '', true);
if ($post_id)
{
@@ -111,8 +111,8 @@ if (!$auth->acl_getf_global('m_'))
'lock' => 'f_user_lock',
'make_sticky' => 'f_sticky',
'make_announce' => 'f_announce',
- 'make_global' => 'f_announce',
- 'make_normal' => array('f_announce', 'f_sticky')
+ 'make_global' => 'f_announce_global',
+ 'make_normal' => array('f_announce', 'f_announce_global', 'f_sticky')
);
$allow_user = false;
@@ -127,6 +127,7 @@ if (!$auth->acl_getf_global('m_'))
if (!$allow_user)
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
}
@@ -134,6 +135,7 @@ if (!$auth->acl_getf_global('m_'))
// if the user cannot read the forum he tries to access then we won't allow mcp access either
if ($forum_id && !$auth->acl_get('f_read', $forum_id))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -192,7 +194,7 @@ if ($quickmod)
case 'topic_logs':
// Reset start parameter if we jumped from the quickmod dropdown
- if (request_var('start', 0))
+ if ($request->variable('start', 0))
{
$request->overwrite('start', 0);
}
diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php
index b93476b3bb..e816e06488 100644
--- a/phpBB/memberlist.php
+++ b/phpBB/memberlist.php
@@ -20,7 +20,7 @@ $phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
-$mode = request_var('mode', '');
+$mode = $request->variable('mode', '');
if ($mode === 'contactadmin')
{
@@ -37,11 +37,11 @@ $user->setup(array('memberlist', 'groups'));
$template->assign_var('S_IN_MEMBERLIST', true);
// Grab data
-$action = request_var('action', '');
-$user_id = request_var('u', ANONYMOUS);
-$username = request_var('un', '', true);
-$group_id = request_var('g', 0);
-$topic_id = request_var('t', 0);
+$action = $request->variable('action', '');
+$user_id = $request->variable('u', ANONYMOUS);
+$username = $request->variable('un', '', true);
+$group_id = $request->variable('g', 0);
+$topic_id = $request->variable('t', 0);
// Redirect when old mode is used
if ($mode == 'leaders')
@@ -75,6 +75,7 @@ switch ($mode)
{
if ($user->data['user_id'] != ANONYMOUS)
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_VIEW_USERS');
}
@@ -83,12 +84,15 @@ switch ($mode)
break;
}
-$start = request_var('start', 0);
+/** @var \phpbb\group\helper $group_helper */
+$group_helper = $phpbb_container->get('group_helper');
+
+$start = $request->variable('start', 0);
$submit = (isset($_POST['submit'])) ? true : false;
$default_key = 'c';
-$sort_key = request_var('sk', $default_key);
-$sort_dir = request_var('sd', 'a');
+$sort_key = $request->variable('sk', $default_key);
+$sort_dir = $request->variable('sd', 'a');
$user_types = array(USER_NORMAL, USER_FOUNDER);
if ($auth->acl_get('a_user'))
@@ -142,7 +146,7 @@ switch ($mode)
}
else
{
- $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
+ $row['group_name'] = $group_helper->get_name($row['group_name']);
$row['u_group'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $row['group_id']);
}
@@ -369,6 +373,7 @@ switch ($mode)
if (!$auth->acl_get('u_sendim'))
{
+ send_status_line(403, 'Forbidden');
trigger_error('NOT_AUTHORISED');
}
@@ -419,7 +424,7 @@ switch ($mode)
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$subject = sprintf($user->lang['IM_JABBER_SUBJECT'], $user->data['username'], $config['server_name']);
- $message = utf8_normalize_nfc(request_var('message', '', true));
+ $message = $request->variable('message', '', true);
if (empty($message))
{
@@ -544,20 +549,14 @@ switch ($mode)
$group_data = $group_sort = array();
foreach ($profile_groups as $row)
{
- if ($row['group_type'] == GROUP_SPECIAL)
- {
- // Lookup group name in language dictionary
- if (isset($user->lang['G_' . $row['group_name']]))
- {
- $row['group_name'] = $user->lang['G_' . $row['group_name']];
- }
- }
- else if (!$auth_hidden_groups && $row['group_type'] == GROUP_HIDDEN && !isset($user_groups[$row['group_id']]))
+ if (!$auth_hidden_groups && $row['group_type'] == GROUP_HIDDEN && !isset($user_groups[$row['group_id']]))
{
// Skip over hidden groups the user cannot see
continue;
}
+ $row['group_name'] = $group_helper->get_name($row['group_name']);
+
$group_sort[$row['group_id']] = utf8_clean_string($row['group_name']);
$group_data[$row['group_id']] = $row;
}
@@ -646,6 +645,7 @@ switch ($mode)
$profile_fields = array();
if ($config['load_cpf_viewprofile'])
{
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$profile_fields = $cp->grab_profile_fields_data($user_id);
$profile_fields = (isset($profile_fields[$user_id])) ? $cp->generate_profile_fields_template_data($profile_fields[$user_id]) : array();
@@ -794,8 +794,8 @@ switch ($mode)
include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
}
- $user_id = request_var('u', 0);
- $topic_id = request_var('t', 0);
+ $user_id = $request->variable('u', 0);
+ $topic_id = $request->variable('t', 0);
if ($user_id)
{
@@ -813,6 +813,8 @@ switch ($mode)
{
trigger_error('NO_EMAIL');
}
+
+ /** @var $form \phpbb\message\form */
$form = $phpbb_container->get('message.form.' . $form_name);
$form->bind($request);
@@ -868,6 +870,8 @@ switch ($mode)
// The basic memberlist
$page_title = $user->lang['MEMBERLIST'];
$template_html = 'memberlist_body.html';
+
+ /* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
// Sorting
@@ -916,9 +920,9 @@ switch ($mode)
$sql_select = $sql_where_data = $sql_from = $sql_where = $order_by = '';
- $form = request_var('form', '');
- $field = request_var('field', '');
- $select_single = request_var('select_single', false);
+ $form = $request->variable('form', '');
+ $field = $request->variable('field', '');
+ $select_single = $request->variable('select_single', false);
// Search URL parameters, if any of these are in the URL we do a search
$search_params = array('username', 'email', 'jabber', 'search_group_id', 'joined_select', 'active_select', 'count_select', 'joined', 'active', 'count', 'ip');
@@ -928,20 +932,20 @@ switch ($mode)
$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_')))
{
- $username = request_var('username', '', true);
- $email = strtolower(request_var('email', ''));
- $jabber = request_var('jabber', '');
- $search_group_id = request_var('search_group_id', 0);
+ $username = $request->variable('username', '', true);
+ $email = strtolower($request->variable('email', ''));
+ $jabber = $request->variable('jabber', '');
+ $search_group_id = $request->variable('search_group_id', 0);
// when using these, make sure that we actually have values defined in $find_key_match
- $joined_select = request_var('joined_select', 'lt');
- $active_select = request_var('active_select', 'lt');
- $count_select = request_var('count_select', 'eq');
+ $joined_select = $request->variable('joined_select', 'lt');
+ $active_select = $request->variable('active_select', 'lt');
+ $count_select = $request->variable('count_select', 'eq');
- $joined = explode('-', request_var('joined', ''));
- $active = explode('-', request_var('active', ''));
- $count = (request_var('count', '') !== '') ? request_var('count', 0) : '';
- $ipdomain = request_var('ip', '');
+ $joined = explode('-', $request->variable('joined', ''));
+ $active = explode('-', $request->variable('active', ''));
+ $count = ($request->variable('count', '') !== '') ? $request->variable('count', 0) : '';
+ $ipdomain = $request->variable('ip', '');
$find_key_match = array('lt' => '<', 'gt' => '>', 'eq' => '=');
@@ -1075,7 +1079,7 @@ switch ($mode)
}
}
- $first_char = request_var('first_char', '');
+ $first_char = $request->variable('first_char', '');
if ($first_char == 'other')
{
@@ -1174,7 +1178,7 @@ switch ($mode)
$template->assign_vars(array(
'GROUP_DESC' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']),
- 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'],
+ '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'],
@@ -1247,7 +1251,7 @@ switch ($mode)
// Build a relevant pagination_url
$params = $sort_params = array();
- // We do not use request_var() here directly to save some calls (not all variables are set)
+ // We do not use $request->variable() here directly to save some calls (not all variables are set)
$check_params = array(
'g' => array('g', 0),
'sk' => array('sk', $default_key),
@@ -1264,7 +1268,7 @@ switch ($mode)
'count_select' => array('count_select', 'eq'),
'joined' => array('joined', ''),
'active' => array('active', ''),
- 'count' => (request_var('count', '') !== '') ? array('count', 0) : array('count', ''),
+ 'count' => ($request->variable('count', '') !== '') ? array('count', 0) : array('count', ''),
'ip' => array('ip', ''),
'first_char' => array('first_char', ''),
);
@@ -1277,7 +1281,7 @@ switch ($mode)
continue;
}
- $param = call_user_func_array('request_var', $call);
+ $param = call_user_func_array(array($request, 'variable'), $call);
// Encode strings, convert everything else to int in order to prevent empty parameters.
$param = urlencode($key) . '=' . ((is_string($param)) ? urlencode($param) : (int) $param);
$params[] = $param;
@@ -1330,7 +1334,7 @@ switch ($mode)
// Some search user specific data
if (($mode == '' || $mode == 'searchuser') && ($config['load_search'] || $auth->acl_get('a_')))
{
- $group_selected = request_var('search_group_id', 0);
+ $group_selected = $request->variable('search_group_id', 0);
$s_group_select = '<option value="0"' . ((!$group_selected) ? ' selected="selected"' : '') . '>&nbsp;</option>';
$group_ids = array();
@@ -1374,7 +1378,7 @@ switch ($mode)
while ($row = $db->sql_fetchrow($result))
{
$group_ids[] = $row['group_id'];
- $s_group_select .= '<option value="' . $row['group_id'] . '"' . (($group_selected == $row['group_id']) ? ' selected="selected"' : '') . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ $s_group_select .= '<option value="' . $row['group_id'] . '"' . (($group_selected == $row['group_id']) ? ' selected="selected"' : '') . '>' . $group_helper->get_name($row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
@@ -1430,6 +1434,7 @@ switch ($mode)
// Load custom profile fields
if ($config['load_cpf_memberlist'])
{
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$cp_row = $cp->generate_profile_fields_template_headlines('field_show_on_ml');
diff --git a/phpBB/phpbb/attachment/delete.php b/phpBB/phpbb/attachment/delete.php
new file mode 100644
index 0000000000..922f24b5dc
--- /dev/null
+++ b/phpBB/phpbb/attachment/delete.php
@@ -0,0 +1,432 @@
+<?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\attachment;
+
+use \phpbb\config\config;
+use \phpbb\db\driver\driver_interface;
+use \phpbb\event\dispatcher;
+use \phpbb\filesystem\filesystem;
+
+/**
+ * Attachment delete class
+ */
+class delete
+{
+ /** @var config */
+ protected $config;
+
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var dispatcher */
+ protected $dispatcher;
+
+ /** @var filesystem */
+ protected $filesystem;
+
+ /** @var resync */
+ protected $resync;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ /** @var array Attachement IDs */
+ protected $ids;
+
+ /** @var string SQL ID string */
+ private $sql_id;
+
+ /** @var string SQL where string */
+ private $sql_where = '';
+
+ /** @var int Number of deleted items */
+ private $num_deleted;
+
+ /** @var array Post IDs */
+ private $post_ids = array();
+
+ /** @var array Message IDs */
+ private $message_ids = array();
+
+ /** @var array Topic IDs */
+ private $topic_ids = array();
+
+ /** @var array Info of physical file */
+ private $physical = array();
+
+ /**
+ * Attachment delete class constructor
+ *
+ * @param config $config
+ * @param driver_interface $db
+ * @param dispatcher $dispatcher
+ * @param filesystem $filesystem
+ * @param resync $resync
+ * @param string $phpbb_root_path
+ */
+ public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, filesystem $filesystem, resync $resync, $phpbb_root_path)
+ {
+ $this->config = $config;
+ $this->db = $db;
+ $this->dispatcher = $dispatcher;
+ $this->filesystem = $filesystem;
+ $this->resync = $resync;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Delete Attachments
+ *
+ * @param string $mode can be: post|message|topic|attach|user
+ * @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
+ * @param bool $resync set this to false if you are deleting posts or topics
+ *
+ * @return int|bool Number of deleted attachments or false if something
+ * went wrong during attachment deletion
+ */
+ public function delete($mode, $ids, $resync = true)
+ {
+ if (!$this->set_attachment_ids($ids))
+ {
+ return false;
+ }
+
+ $this->set_sql_constraints($mode);
+
+ /**
+ * Perform additional actions before collecting data for attachment(s) deletion
+ *
+ * @event core.delete_attachments_collect_data_before
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_collect_data_before', compact($vars)));
+
+ // 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();
+
+ /**
+ * Perform additional actions after attachment(s) deletion from the database
+ *
+ * @event core.delete_attachments_from_database_after
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @var array post_ids Array with post ids for deleted attachment(s)
+ * @var array topic_ids Array with topic ids for deleted attachment(s)
+ * @var array message_ids Array with private message ids for deleted attachment(s)
+ * @var array physical Array with deleted attachment(s) physical file(s) data
+ * @var int num_deleted The number of deleted attachment(s) from the database
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ 'post_ids',
+ 'topic_ids',
+ 'message_ids',
+ 'physical',
+ 'num_deleted',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_from_database_after', compact($vars)));
+
+ if (!$this->num_deleted)
+ {
+ return 0;
+ }
+
+ // Delete attachments from filesystem
+ $this->remove_from_filesystem();
+
+ // If we do not resync, we do not need to adjust any message, post, topic or user entries
+ if (!$resync)
+ {
+ return $this->num_deleted;
+ }
+
+ // No more use for the original ids
+ unset($ids);
+
+ // Update post indicators for posts now no longer having attachments
+ $this->resync->resync('post', $this->post_ids);
+
+ // Update message table if messages are affected
+ $this->resync->resync('message', $this->message_ids);
+
+ // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
+ $this->resync->resync('topic', $this->topic_ids);
+
+ return $this->num_deleted;
+ }
+
+ /**
+ * Set attachment IDs
+ *
+ * @param mixed $ids ID or array of IDs
+ *
+ * @return bool True if attachment IDs were set, false if not
+ */
+ protected function set_attachment_ids($ids)
+ {
+ // 0 is as bad as an empty array
+ if (empty($ids))
+ {
+ return false;
+ }
+
+ if (is_array($ids))
+ {
+ $ids = array_unique($ids);
+ $this->ids = array_map('intval', $ids);
+ }
+ else
+ {
+ $this->ids = array((int) $ids);
+ }
+
+ return true;
+ }
+
+ /**
+ * Set SQL constraints based on mode
+ *
+ * @param string $mode Delete mode; can be: post|message|topic|attach|user
+ */
+ private function set_sql_constraints($mode)
+ {
+ switch ($mode)
+ {
+ case 'post':
+ case 'message':
+ $this->sql_id = 'post_msg_id';
+ $this->sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0);
+ break;
+
+ case 'topic':
+ $this->sql_id = 'topic_id';
+ break;
+
+ case 'user':
+ $this->sql_id = 'poster_id';
+ break;
+
+ case 'attach':
+ default:
+ $this->sql_id = 'attach_id';
+ break;
+ }
+ }
+
+ /**
+ * Collect info about attachment IDs
+ *
+ * @param bool $resync Whether topics/posts should be resynced after delete
+ */
+ protected function collect_attachment_info($resync)
+ {
+ // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
+ $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids);
+
+ $sql .= $this->sql_where;
+
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
+ if ($resync && !$row['is_orphan'])
+ {
+ if (!$row['in_message'])
+ {
+ $this->post_ids[] = $row['post_msg_id'];
+ $this->topic_ids[] = $row['topic_id'];
+ }
+ else
+ {
+ $this->message_ids[] = $row['post_msg_id'];
+ }
+ }
+
+ $this->physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
+ }
+ $this->db->sql_freeresult($result);
+
+ // IDs should be unique
+ $this->post_ids = array_unique($this->post_ids);
+ $this->message_ids = array_unique($this->message_ids);
+ $this->topic_ids = array_unique($this->topic_ids);
+ }
+
+ /**
+ * Delete attachments from database table
+ */
+ protected function delete_attachments_from_db()
+ {
+ /**
+ * Perform additional actions before attachment(s) deletion
+ *
+ * @event core.delete_attachments_before
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @var array post_ids Array with post ids for deleted attachment(s)
+ * @var array topic_ids Array with topic ids for deleted attachment(s)
+ * @var array message_ids Array with private message ids for deleted attachment(s)
+ * @var array physical Array with deleted attachment(s) physical file(s) data
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ 'post_ids',
+ 'topic_ids',
+ 'message_ids',
+ 'physical',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_before', compact($vars)));
+
+ // Delete attachments
+ $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids);
+
+ $sql .= $this->sql_where;
+
+ $this->db->sql_query($sql);
+ $this->num_deleted = $this->db->sql_affectedrows();
+ }
+
+ /**
+ * Delete attachments from filesystem
+ */
+ protected function remove_from_filesystem()
+ {
+ $space_removed = $files_removed = 0;
+
+ foreach ($this->physical as $file_ary)
+ {
+ if ($this->unlink_attachment($file_ary['filename'], 'file', true) && !$file_ary['is_orphan'])
+ {
+ // Only non-orphaned files count to the file size
+ $space_removed += $file_ary['filesize'];
+ $files_removed++;
+ }
+
+ if ($file_ary['thumbnail'])
+ {
+ $this->unlink_attachment($file_ary['filename'], 'thumbnail', true);
+ }
+ }
+
+ /**
+ * Perform additional actions after attachment(s) deletion from the filesystem
+ *
+ * @event core.delete_attachments_from_filesystem_after
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @var array post_ids Array with post ids for deleted attachment(s)
+ * @var array topic_ids Array with topic ids for deleted attachment(s)
+ * @var array message_ids Array with private message ids for deleted attachment(s)
+ * @var array physical Array with deleted attachment(s) physical file(s) data
+ * @var int num_deleted The number of deleted attachment(s) from the database
+ * @var int space_removed The size of deleted files(s) from the filesystem
+ * @var int files_removed The number of deleted file(s) from the filesystem
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ 'post_ids',
+ 'topic_ids',
+ 'message_ids',
+ 'physical',
+ 'num_deleted',
+ 'space_removed',
+ 'files_removed',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars)));
+
+ if ($space_removed || $files_removed)
+ {
+ $this->config->increment('upload_dir_size', $space_removed * (-1), false);
+ $this->config->increment('num_files', $files_removed * (-1), false);
+ }
+ }
+
+ /**
+ * Delete attachment from filesystem
+ *
+ * @param string $filename Filename of attachment
+ * @param string $mode Delete mode
+ * @param bool $entry_removed Whether entry was removed. Defaults to false
+ * @return bool True if file was removed, false if not
+ */
+ public function unlink_attachment($filename, $mode = 'file', $entry_removed = false)
+ {
+ // Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself.
+ $sql = 'SELECT COUNT(attach_id) AS num_entries
+ FROM ' . ATTACHMENTS_TABLE . "
+ WHERE physical_filename = '" . $this->db->sql_escape(utf8_basename($filename)) . "'";
+ $result = $this->db->sql_query($sql);
+ $num_entries = (int) $this->db->sql_fetchfield('num_entries');
+ $this->db->sql_freeresult($result);
+
+ // Do not remove file if at least one additional entry with the same name exist.
+ if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1))
+ {
+ return false;
+ }
+
+ $filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename);
+ $filepath = $this->phpbb_root_path . $this->config['upload_path'] . '/' . $filename;
+
+ try
+ {
+ if ($this->filesystem->exists($filepath))
+ {
+ $this->filesystem->remove($this->phpbb_root_path . $this->config['upload_path'] . '/' . $filename);
+ return true;
+ }
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $exception)
+ {
+ // Fail is covered by return statement below
+ }
+
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/attachment/manager.php b/phpBB/phpbb/attachment/manager.php
new file mode 100644
index 0000000000..3c47171b2f
--- /dev/null
+++ b/phpBB/phpbb/attachment/manager.php
@@ -0,0 +1,99 @@
+<?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\attachment;
+
+/**
+ * Attachment manager
+ */
+class manager
+{
+ /** @var delete Attachment delete class */
+ protected $delete;
+
+ /** @var resync Attachment resync class */
+ protected $resync;
+
+ /** @var upload Attachment upload class */
+ protected $upload;
+
+ /**
+ * Constructor for attachment manager
+ *
+ * @param delete $delete Attachment delete class
+ * @param resync $resync Attachment resync class
+ * @param upload $upload Attachment upload class
+ */
+ public function __construct(delete $delete, resync $resync, upload $upload)
+ {
+ $this->delete = $delete;
+ $this->resync = $resync;
+ $this->upload = $upload;
+ }
+
+ /**
+ * Wrapper method for deleting attachments
+ *
+ * @param string $mode can be: post|message|topic|attach|user
+ * @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
+ * @param bool $resync set this to false if you are deleting posts or topics
+ *
+ * @return int|bool Number of deleted attachments or false if something
+ * went wrong during attachment deletion
+ */
+ public function delete($mode, $ids, $resync = true)
+ {
+ return $this->delete->delete($mode, $ids, $resync);
+ }
+
+ /**
+ * Wrapper method for deleting attachments from filesystem
+ *
+ * @param string $filename Filename of attachment
+ * @param string $mode Delete mode
+ * @param bool $entry_removed Whether entry was removed. Defaults to false
+ * @return bool True if file was removed, false if not
+ */
+ public function unlink($filename, $mode = 'file', $entry_removed = false)
+ {
+ return $this->delete->unlink_attachment($filename, $mode, $entry_removed);
+ }
+
+ /**
+ * Wrapper method for resyncing specified type
+ *
+ * @param string $type Type of resync
+ * @param array $ids IDs to resync
+ */
+ public function resync($type, $ids)
+ {
+ $this->resync->resync($type, $ids);
+ }
+
+ /**
+ * Wrapper method for uploading attachment
+ *
+ * @param string $form_name The form name of the file upload input
+ * @param int $forum_id The id of the forum
+ * @param bool $local Whether the file is local or not
+ * @param string $local_storage The path to the local file
+ * @param bool $is_message Whether it is a PM or not
+ * @param array $local_filedata An file data object created for the local file
+ *
+ * @return array File data array
+ */
+ public function upload($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = [])
+ {
+ return $this->upload->upload($form_name, $forum_id, $local, $local_storage, $is_message, $local_filedata);
+ }
+}
diff --git a/phpBB/phpbb/attachment/resync.php b/phpBB/phpbb/attachment/resync.php
new file mode 100644
index 0000000000..6c2e0a8b0d
--- /dev/null
+++ b/phpBB/phpbb/attachment/resync.php
@@ -0,0 +1,124 @@
+<?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\attachment;
+
+use \phpbb\db\driver\driver_interface;
+
+/**
+ * Attachment resync class
+ */
+class resync
+{
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var string Attachment table SQL ID */
+ private $attach_sql_id;
+
+ /** @var string Resync table SQL ID */
+ private $resync_sql_id;
+
+ /** @var string Resync SQL table */
+ private $resync_table;
+
+ /** @var string SQL where statement */
+ private $sql_where;
+
+ /**
+ * Constructor for attachment resync class
+ *
+ * @param driver_interface $db Database driver
+ */
+ public function __construct(driver_interface $db)
+ {
+ $this->db = $db;
+ }
+
+ /**
+ * Set type constraints for attachment resync
+ *
+ * @param string $type Type of resync; can be: message|post|topic
+ */
+ protected function set_type_constraints($type)
+ {
+ switch ($type)
+ {
+ case 'message':
+ $this->attach_sql_id = 'post_msg_id';
+ $this->sql_where = ' AND in_message = 1
+ AND is_orphan = 0';
+ $this->resync_table = PRIVMSGS_TABLE;
+ $this->resync_sql_id = 'msg_id';
+ break;
+
+ case 'post':
+ $this->attach_sql_id = 'post_msg_id';
+ $this->sql_where = ' AND in_message = 0
+ AND is_orphan = 0';
+ $this->resync_table = POSTS_TABLE;
+ $this->resync_sql_id = 'post_id';
+ break;
+
+ case 'topic':
+ $this->attach_sql_id = 'topic_id';
+ $this->sql_where = ' AND is_orphan = 0';
+ $this->resync_table = TOPICS_TABLE;
+ $this->resync_sql_id = 'topic_id';
+ break;
+ }
+ }
+
+ /**
+ * Resync specified type
+ *
+ * @param string $type Type of resync
+ * @param array $ids IDs to resync
+ */
+ public function resync($type, $ids)
+ {
+ if (empty($type) || !is_array($ids) || !sizeof($ids) || !in_array($type, array('post', 'topic', 'message')))
+ {
+ return;
+ }
+
+ $this->set_type_constraints($type);
+
+ // Just check which elements are still having an assigned attachment
+ // not orphaned by querying the attachments table
+ $sql = 'SELECT ' . $this->attach_sql_id . '
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set($this->attach_sql_id, $ids)
+ . $this->sql_where;
+ $result = $this->db->sql_query($sql);
+
+ $remaining_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $remaining_ids[] = $row[$this->attach_sql_id];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Now only unset those ids remaining
+ $ids = array_diff($ids, $remaining_ids);
+
+ if (sizeof($ids))
+ {
+ $sql = 'UPDATE ' . $this->resync_table . '
+ SET ' . $type . '_attachment = 0
+ WHERE ' . $this->db->sql_in_set($this->resync_sql_id, $ids);
+ $this->db->sql_query($sql);
+ }
+ }
+
+}
diff --git a/phpBB/phpbb/attachment/upload.php b/phpBB/phpbb/attachment/upload.php
new file mode 100644
index 0000000000..f9863b372c
--- /dev/null
+++ b/phpBB/phpbb/attachment/upload.php
@@ -0,0 +1,334 @@
+<?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\attachment;
+
+use phpbb\auth\auth;
+use \phpbb\cache\service;
+use \phpbb\config\config;
+use \phpbb\event\dispatcher;
+use \phpbb\language\language;
+use \phpbb\mimetype\guesser;
+use \phpbb\plupload\plupload;
+use \phpbb\user;
+
+/**
+ * Attachment upload class
+ */
+class upload
+{
+ /** @var auth */
+ protected $auth;
+
+ /** @var service */
+ protected $cache;
+
+ /** @var config */
+ protected $config;
+
+ /** @var \phpbb\files\upload Upload class */
+ protected $files_upload;
+
+ /** @var language */
+ protected $language;
+
+ /** @var guesser Mimetype guesser */
+ protected $mimetype_guesser;
+
+ /** @var dispatcher */
+ protected $phpbb_dispatcher;
+
+ /** @var plupload Plupload */
+ protected $plupload;
+
+ /** @var user */
+ protected $user;
+
+ /** @var \phpbb\files\filespec Current filespec instance */
+ private $file;
+
+ /** @var array File data */
+ private $file_data = array(
+ 'error' => array()
+ );
+
+ /** @var array Extensions array */
+ private $extensions;
+
+ /**
+ * Constructor for attachments upload class
+ *
+ * @param auth $auth
+ * @param service $cache
+ * @param config $config
+ * @param \phpbb\files\upload $files_upload
+ * @param language $language
+ * @param guesser $mimetype_guesser
+ * @param dispatcher $phpbb_dispatcher
+ * @param plupload $plupload
+ * @param user $user
+ * @param $phpbb_root_path
+ */
+ public function __construct(auth $auth, service $cache, config $config, \phpbb\files\upload $files_upload, language $language, guesser $mimetype_guesser, dispatcher $phpbb_dispatcher, plupload $plupload, user $user, $phpbb_root_path)
+ {
+ $this->auth = $auth;
+ $this->cache = $cache;
+ $this->config = $config;
+ $this->files_upload = $files_upload;
+ $this->language = $language;
+ $this->mimetype_guesser = $mimetype_guesser;
+ $this->phpbb_dispatcher = $phpbb_dispatcher;
+ $this->plupload = $plupload;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Upload Attachment - filedata is generated here
+ * Uses upload class
+ *
+ * @param string $form_name The form name of the file upload input
+ * @param int $forum_id The id of the forum
+ * @param bool $local Whether the file is local or not
+ * @param string $local_storage The path to the local file
+ * @param bool $is_message Whether it is a PM or not
+ * @param array $local_filedata An file data object created for the local file
+ *
+ * @return array File data array
+ */
+ public function upload($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = array())
+ {
+ $this->init_files_upload($forum_id, $is_message);
+
+ $this->file_data['post_attach'] = $local || $this->files_upload->is_valid($form_name);
+
+ if (!$this->file_data['post_attach'])
+ {
+ $this->file_data['error'][] = $this->language->lang('NO_UPLOAD_FORM_FOUND');
+ return $this->file_data;
+ }
+
+ $this->file = ($local) ? $this->files_upload->handle_upload('files.types.local', $local_storage, $local_filedata) : $this->files_upload->handle_upload('files.types.form', $form_name);
+
+ if ($this->file->init_error())
+ {
+ $this->file_data['post_attach'] = false;
+ return $this->file_data;
+ }
+
+ // Whether the uploaded file is in the image category
+ $is_image = (isset($this->extensions[$this->file->get('extension')]['display_cat'])) ? $this->extensions[$this->file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false;
+
+ if (!$this->auth->acl_get('a_') && !$this->auth->acl_get('m_', $forum_id))
+ {
+ // Check Image Size, if it is an image
+ if ($is_image)
+ {
+ $this->file->upload->set_allowed_dimensions(0, 0, $this->config['img_max_width'], $this->config['img_max_height']);
+ }
+
+ // Admins and mods are allowed to exceed the allowed filesize
+ if (!empty($this->extensions[$this->file->get('extension')]['max_filesize']))
+ {
+ $allowed_filesize = $this->extensions[$this->file->get('extension')]['max_filesize'];
+ }
+ else
+ {
+ $allowed_filesize = ($is_message) ? $this->config['max_filesize_pm'] : $this->config['max_filesize'];
+ }
+
+ $this->file->upload->set_max_filesize($allowed_filesize);
+ }
+
+ $this->file->clean_filename('unique', $this->user->data['user_id'] . '_');
+
+ // Are we uploading an image *and* this image being within the image category?
+ // Only then perform additional image checks.
+ $this->file->move_file($this->config['upload_path'], false, !$is_image);
+
+ // Do we have to create a thumbnail?
+ $this->file_data['thumbnail'] = ($is_image && $this->config['img_create_thumbnail']) ? 1 : 0;
+
+ // Make sure the image category only holds valid images...
+ $this->check_image($is_image);
+
+ if (sizeof($this->file->error))
+ {
+ $this->file->remove();
+ $this->file_data['error'] = array_merge($this->file_data['error'], $this->file->error);
+ $this->file_data['post_attach'] = false;
+
+ return $this->file_data;
+ }
+
+ $this->fill_file_data();
+
+ $filedata = $this->file_data;
+
+ /**
+ * Event to modify uploaded file before submit to the post
+ *
+ * @event core.modify_uploaded_file
+ * @var array filedata Array containing uploaded file data
+ * @var bool is_image Flag indicating if the file is an image
+ * @since 3.1.0-RC3
+ */
+ $vars = array(
+ 'filedata',
+ 'is_image',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.modify_uploaded_file', compact($vars)));
+ $this->file_data = $filedata;
+ unset($filedata);
+
+ // Check for attachment quota and free space
+ if (!$this->check_attach_quota() || !$this->check_disk_space())
+ {
+ return $this->file_data;
+ }
+
+ // Create Thumbnail
+ $this->create_thumbnail();
+
+ return $this->file_data;
+ }
+
+ /**
+ * Create thumbnail for file if necessary
+ *
+ * @return array Updated $filedata
+ */
+ protected function create_thumbnail()
+ {
+ if ($this->file_data['thumbnail'])
+ {
+ $source = $this->file->get('destination_file');
+ $destination = $this->file->get('destination_path') . '/thumb_' . $this->file->get('realname');
+
+ if (!create_thumbnail($source, $destination, $this->file->get('mimetype')))
+ {
+ $this->file_data['thumbnail'] = 0;
+ }
+ }
+ }
+
+ /**
+ * Init files upload class
+ *
+ * @param int $forum_id Forum ID
+ * @param bool $is_message Whether attachment is inside PM or not
+ */
+ protected function init_files_upload($forum_id, $is_message)
+ {
+ if ($this->config['check_attachment_content'] && isset($this->config['mime_triggers']))
+ {
+ $this->files_upload->set_disallowed_content(explode('|', $this->config['mime_triggers']));
+ }
+ else if (!$this->config['check_attachment_content'])
+ {
+ $this->files_upload->set_disallowed_content(array());
+ }
+
+ $this->extensions = $this->cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id));
+ $this->files_upload->set_allowed_extensions(array_keys($this->extensions['_allowed_']));
+ }
+
+ /**
+ * Check if uploaded file is really an image
+ *
+ * @param bool $is_image Whether file is image
+ */
+ protected function check_image($is_image)
+ {
+ // Make sure the image category only holds valid images...
+ if ($is_image && !$this->file->is_image())
+ {
+ $this->file->remove();
+
+ if ($this->plupload && $this->plupload->is_active())
+ {
+ $this->plupload->emit_error(104, 'ATTACHED_IMAGE_NOT_IMAGE');
+ }
+
+ // If this error occurs a user tried to exploit an IE Bug by renaming extensions
+ // Since the image category is displaying content inline we need to catch this.
+ $this->file->set_error($this->language->lang('ATTACHED_IMAGE_NOT_IMAGE'));
+ }
+ }
+
+ /**
+ * Check if attachment quota was reached
+ *
+ * @return bool False if attachment quota was reached, true if not
+ */
+ protected function check_attach_quota()
+ {
+ if ($this->config['attachment_quota'])
+ {
+ if (intval($this->config['upload_dir_size']) + $this->file->get('filesize') > $this->config['attachment_quota'])
+ {
+ $this->file_data['error'][] = $this->language->lang('ATTACH_QUOTA_REACHED');
+ $this->file_data['post_attach'] = false;
+
+ $this->file->remove();
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if there is enough free space available on disk
+ *
+ * @return bool True if disk space is available, false if not
+ */
+ protected function check_disk_space()
+ {
+ if ($free_space = @disk_free_space($this->phpbb_root_path . $this->config['upload_path']))
+ {
+ if ($free_space <= $this->file->get('filesize'))
+ {
+ if ($this->auth->acl_get('a_'))
+ {
+ $this->file_data['error'][] = $this->language->lang('ATTACH_DISK_FULL');
+ }
+ else
+ {
+ $this->file_data['error'][] = $this->language->lang('ATTACH_QUOTA_REACHED');
+ }
+ $this->file_data['post_attach'] = false;
+
+ $this->file->remove();
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Fills file data with file information and current time as filetime
+ */
+ protected function fill_file_data()
+ {
+ $this->file_data['filesize'] = $this->file->get('filesize');
+ $this->file_data['mimetype'] = $this->file->get('mimetype');
+ $this->file_data['extension'] = $this->file->get('extension');
+ $this->file_data['physical_filename'] = $this->file->get('realname');
+ $this->file_data['real_filename'] = $this->file->get('uploadname');
+ $this->file_data['filetime'] = time();
+ }
+}
diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php
index b7634e04ce..fc7cc1a0b1 100644
--- a/phpBB/phpbb/auth/auth.php
+++ b/phpBB/phpbb/auth/auth.php
@@ -930,6 +930,7 @@ class auth
global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
global $phpbb_dispatcher;
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$provider = $provider_collection->get_provider();
diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php
index d8c5fb72de..1adf85ee05 100644
--- a/phpBB/phpbb/auth/provider/db.php
+++ b/phpBB/phpbb/auth/provider/db.php
@@ -155,6 +155,7 @@ class db extends \phpbb\auth\provider\base
// Every auth module is able to define what to do by itself...
if ($show_captcha)
{
+ /* @var $captcha_factory \phpbb\captcha\factory */
$captcha_factory = $this->phpbb_container->get('captcha.factory');
$captcha = $captcha_factory->get_instance($this->config['captcha_plugin']);
$captcha->init(CONFIRM_LOGIN);
diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php
index bd2a414033..fdc5f57df0 100644
--- a/phpBB/phpbb/auth/provider/oauth/oauth.php
+++ b/phpBB/phpbb/auth/provider/oauth/oauth.php
@@ -63,6 +63,13 @@ class oauth extends \phpbb\auth\provider\base
protected $auth_provider_oauth_token_storage_table;
/**
+ * OAuth state table
+ *
+ * @var string
+ */
+ protected $auth_provider_oauth_state_table;
+
+ /**
* OAuth account association table
*
* @var string
@@ -127,6 +134,7 @@ class oauth extends \phpbb\auth\provider\base
* @param \phpbb\request\request_interface $request
* @param \phpbb\user $user
* @param string $auth_provider_oauth_token_storage_table
+ * @param string $auth_provider_oauth_state_table
* @param string $auth_provider_oauth_token_account_assoc
* @param \phpbb\di\service_collection $service_providers Contains \phpbb\auth\provider\oauth\service_interface
* @param string $users_table
@@ -135,7 +143,7 @@ class oauth extends \phpbb\auth\provider\base
* @param string $phpbb_root_path
* @param string $php_ext
*/
- public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $php_ext)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request_interface $request, \phpbb\user $user, $auth_provider_oauth_token_storage_table, $auth_provider_oauth_state_table, $auth_provider_oauth_token_account_assoc, \phpbb\di\service_collection $service_providers, $users_table, \Symfony\Component\DependencyInjection\ContainerInterface $phpbb_container, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->config = $config;
@@ -143,6 +151,7 @@ class oauth extends \phpbb\auth\provider\base
$this->request = $request;
$this->user = $user;
$this->auth_provider_oauth_token_storage_table = $auth_provider_oauth_token_storage_table;
+ $this->auth_provider_oauth_state_table = $auth_provider_oauth_state_table;
$this->auth_provider_oauth_token_account_assoc = $auth_provider_oauth_token_account_assoc;
$this->service_providers = $service_providers;
$this->users_table = $users_table;
@@ -197,11 +206,12 @@ class oauth extends \phpbb\auth\provider\base
// Get the service credentials for the given service
$service_credentials = $this->service_providers[$service_name]->get_service_credentials();
- $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table);
+ $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);
$query = 'mode=login&login=external&oauth_service=' . $service_name_original;
$service = $this->get_service($service_name_original, $storage, $service_credentials, $query, $this->service_providers[$service_name]->get_auth_scope());
- if ($this->request->is_set('code', \phpbb\request\request_interface::GET))
+ if (($service::OAUTH_VERSION === 2 && $this->request->is_set('code', \phpbb\request\request_interface::GET))
+ || ($service::OAUTH_VERSION === 1 && $this->request->is_set('oauth_token', \phpbb\request\request_interface::GET)))
{
$this->service_providers[$service_name]->set_external_service_provider($service);
$unique_id = $this->service_providers[$service_name]->perform_auth_login();
@@ -268,7 +278,15 @@ class oauth extends \phpbb\auth\provider\base
}
else
{
- $url = $service->getAuthorizationUri();
+ if ($service::OAUTH_VERSION === 1)
+ {
+ $token = $service->requestRequestToken();
+ $url = $service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken()));
+ }
+ else
+ {
+ $url = $service->getAuthorizationUri();
+ }
header('Location: ' . $url);
}
}
@@ -483,7 +501,7 @@ class oauth extends \phpbb\auth\provider\base
*/
protected function link_account_login_link(array $link_data, $service_name)
{
- $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table);
+ $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);
// Check for an access token, they should have one
if (!$storage->has_access_token_by_session($service_name))
@@ -526,13 +544,14 @@ class oauth extends \phpbb\auth\provider\base
*/
protected function link_account_auth_link(array $link_data, $service_name)
{
- $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table);
+ $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);
$query = 'i=ucp_auth_link&mode=auth_link&link=1&oauth_service=' . strtolower($link_data['oauth_service']);
$service_credentials = $this->service_providers[$service_name]->get_service_credentials();
$scopes = $this->service_providers[$service_name]->get_auth_scope();
$service = $this->get_service(strtolower($link_data['oauth_service']), $storage, $service_credentials, $query, $scopes);
- if ($this->request->is_set('code', \phpbb\request\request_interface::GET))
+ if (($service::OAUTH_VERSION === 2 && $this->request->is_set('code', \phpbb\request\request_interface::GET))
+ || ($service::OAUTH_VERSION === 1 && $this->request->is_set('oauth_token', \phpbb\request\request_interface::GET)))
{
$this->service_providers[$service_name]->set_external_service_provider($service);
$unique_id = $this->service_providers[$service_name]->perform_auth_login();
@@ -548,7 +567,15 @@ class oauth extends \phpbb\auth\provider\base
}
else
{
- $url = $service->getAuthorizationUri();
+ if ($service::OAUTH_VERSION === 1)
+ {
+ $token = $service->requestRequestToken();
+ $url = $service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken()));
+ }
+ else
+ {
+ $url = $service->getAuthorizationUri();
+ }
header('Location: ' . $url);
}
}
@@ -583,7 +610,7 @@ class oauth extends \phpbb\auth\provider\base
public function logout($data, $new_session)
{
// Clear all tokens belonging to the user
- $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table);
+ $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->clearAllTokens();
return;
@@ -666,7 +693,7 @@ class oauth extends \phpbb\auth\provider\base
// Clear all tokens belonging to the user on this servce
$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);
+ $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/oauth/service/twitter.php b/phpBB/phpbb/auth/provider/oauth/service/twitter.php
new file mode 100644
index 0000000000..06beac51e2
--- /dev/null
+++ b/phpBB/phpbb/auth/provider/oauth/service/twitter.php
@@ -0,0 +1,102 @@
+<?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\auth\provider\oauth\service;
+
+/**
+* Twitter OAuth service
+*/
+class twitter extends \phpbb\auth\provider\oauth\service\base
+{
+ /**
+ * phpBB config
+ *
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * phpBB request
+ *
+ * @var \phpbb\request\request_interface
+ */
+ protected $request;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\config\config $config
+ * @param \phpbb\request\request_interface $request
+ */
+ public function __construct(\phpbb\config\config $config, \phpbb\request\request_interface $request)
+ {
+ $this->config = $config;
+ $this->request = $request;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_service_credentials()
+ {
+ return array(
+ 'key' => $this->config['auth_oauth_twitter_key'],
+ 'secret' => $this->config['auth_oauth_twitter_secret'],
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function perform_auth_login()
+ {
+ if (!($this->service_provider instanceof \OAuth\OAuth1\Service\Twitter))
+ {
+ throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');
+ }
+
+ $storage = $this->service_provider->getStorage();
+ $token = $storage->retrieveAccessToken('Twitter');
+ $tokensecret = $token->getRequestTokenSecret();
+
+ // This was a callback request from twitter, get the token
+ $this->service_provider->requestAccessToken(
+ $this->request->variable('oauth_token', ''),
+ $this->request->variable('oauth_verifier', ''),
+ $tokensecret
+ );
+
+ // Send a request with it
+ $result = json_decode($this->service_provider->request('account/verify_credentials.json'), true);
+
+ // Return the unique identifier returned from twitter
+ return $result['id'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function perform_token_auth()
+ {
+ if (!($this->service_provider instanceof \OAuth\OAuth1\Service\Twitter))
+ {
+ throw new \phpbb\auth\provider\oauth\service\exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE');
+ }
+
+ // Send a request with it
+ $result = json_decode($this->service_provider->request('account/verify_credentials.json'), true);
+
+ // Return the unique identifier returned from twitter
+ return $result['id'];
+ }
+}
diff --git a/phpBB/phpbb/auth/provider/oauth/token_storage.php b/phpBB/phpbb/auth/provider/oauth/token_storage.php
index 9b6afae255..b0c2fd0d62 100644
--- a/phpBB/phpbb/auth/provider/oauth/token_storage.php
+++ b/phpBB/phpbb/auth/provider/oauth/token_storage.php
@@ -17,6 +17,7 @@ use OAuth\OAuth1\Token\StdOAuth1Token;
use OAuth\Common\Token\TokenInterface;
use OAuth\Common\Storage\TokenStorageInterface;
use OAuth\Common\Storage\Exception\TokenNotFoundException;
+use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;
/**
* OAuth storage wrapper for phpbb's cache
@@ -42,7 +43,14 @@ class token_storage implements TokenStorageInterface
*
* @var string
*/
- protected $auth_provider_oauth_table;
+ protected $oauth_token_table;
+
+ /**
+ * OAuth state table
+ *
+ * @var string
+ */
+ protected $oauth_state_table;
/**
* @var object|TokenInterface
@@ -50,17 +58,24 @@ class token_storage implements TokenStorageInterface
protected $cachedToken;
/**
+ * @var string
+ */
+ protected $cachedState;
+
+ /**
* Creates token storage for phpBB.
*
* @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\user $user
- * @param string $auth_provider_oauth_table
+ * @param string $oauth_token_table
+ * @param string $oauth_state_table
*/
- public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $auth_provider_oauth_table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $oauth_token_table, $oauth_state_table)
{
$this->db = $db;
$this->user = $user;
- $this->auth_provider_oauth_table = $auth_provider_oauth_table;
+ $this->oauth_token_table = $oauth_token_table;
+ $this->oauth_state_table = $oauth_state_table;
}
/**
@@ -98,15 +113,31 @@ class token_storage implements TokenStorageInterface
$this->cachedToken = $token;
$data = array(
- 'user_id' => (int) $this->user->data['user_id'],
- 'provider' => $service,
'oauth_token' => $this->json_encode_token($token),
- 'session_id' => $this->user->data['session_id'],
);
- $sql = 'INSERT INTO ' . $this->auth_provider_oauth_table . '
- ' . $this->db->sql_build_array('INSERT', $data);
+ $sql = 'UPDATE ' . $this->oauth_token_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $data) . '
+ WHERE user_id = ' . (int) $this->user->data['user_id'] . '
+ ' . ((int) $this->user->data['user_id'] === ANONYMOUS ? "AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'" : '') . "
+ AND provider = '" . $this->db->sql_escape($service) . "'";
$this->db->sql_query($sql);
+
+ if (!$this->db->sql_affectedrows())
+ {
+ $data = array(
+ 'user_id' => (int) $this->user->data['user_id'],
+ 'provider' => $service,
+ 'oauth_token' => $this->json_encode_token($token),
+ 'session_id' => $this->user->data['session_id'],
+ );
+
+ $sql = 'INSERT INTO ' . $this->oauth_token_table . $this->db->sql_build_array('INSERT', $data);
+
+ $this->db->sql_query($sql);
+ }
+
+ return $this;
}
/**
@@ -143,7 +174,7 @@ class token_storage implements TokenStorageInterface
$this->cachedToken = null;
- $sql = 'DELETE FROM ' . $this->auth_provider_oauth_table . '
+ $sql = 'DELETE FROM ' . $this->oauth_token_table . '
WHERE user_id = ' . (int) $this->user->data['user_id'] . "
AND provider = '" . $this->db->sql_escape($service) . "'";
@@ -153,6 +184,8 @@ class token_storage implements TokenStorageInterface
}
$this->db->sql_query($sql);
+
+ return $this;
}
/**
@@ -162,7 +195,7 @@ class token_storage implements TokenStorageInterface
{
$this->cachedToken = null;
- $sql = 'DELETE FROM ' . $this->auth_provider_oauth_table . '
+ $sql = 'DELETE FROM ' . $this->oauth_token_table . '
WHERE user_id = ' . (int) $this->user->data['user_id'];
if ((int) $this->user->data['user_id'] === ANONYMOUS)
@@ -171,6 +204,124 @@ class token_storage implements TokenStorageInterface
}
$this->db->sql_query($sql);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function storeAuthorizationState($service, $state)
+ {
+ $service = $this->get_service_name_for_db($service);
+
+ $this->cachedState = $state;
+
+ $data = array(
+ 'user_id' => (int) $this->user->data['user_id'],
+ 'provider' => $service,
+ 'oauth_state' => $state,
+ 'session_id' => $this->user->data['session_id'],
+ );
+
+ $sql = 'INSERT INTO ' . $this->oauth_state_table . '
+ ' . $this->db->sql_build_array('INSERT', $data);
+ $this->db->sql_query($sql);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasAuthorizationState($service)
+ {
+ $service = $this->get_service_name_for_db($service);
+
+ if ($this->cachedState)
+ {
+ return true;
+ }
+
+ $data = array(
+ 'user_id' => (int) $this->user->data['user_id'],
+ 'provider' => $service,
+ );
+
+ if ((int) $this->user->data['user_id'] === ANONYMOUS)
+ {
+ $data['session_id'] = $this->user->data['session_id'];
+ }
+
+ return (bool) $this->get_state_row($data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function retrieveAuthorizationState($service)
+ {
+ $service = $this->get_service_name_for_db($service);
+
+ if ($this->cachedState)
+ {
+ return $this->cachedState;
+ }
+
+ $data = array(
+ 'user_id' => (int) $this->user->data['user_id'],
+ 'provider' => $service,
+ );
+
+ if ((int) $this->user->data['user_id'] === ANONYMOUS)
+ {
+ $data['session_id'] = $this->user->data['session_id'];
+ }
+
+ return $this->get_state_row($data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clearAuthorizationState($service)
+ {
+ $service = $this->get_service_name_for_db($service);
+
+ $this->cachedState = null;
+
+ $sql = 'DELETE FROM ' . $this->oauth_state_table . '
+ WHERE user_id = ' . (int) $this->user->data['user_id'] . "
+ AND provider = '" . $this->db->sql_escape($service) . "'";
+
+ if ((int) $this->user->data['user_id'] === ANONYMOUS)
+ {
+ $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
+ }
+
+ $this->db->sql_query($sql);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clearAllAuthorizationStates()
+ {
+ $this->cachedState = null;
+
+ $sql = 'DELETE FROM ' . $this->oauth_state_table . '
+ WHERE user_id = ' . (int) $this->user->data['user_id'];
+
+ if ((int) $this->user->data['user_id'] === ANONYMOUS)
+ {
+ $sql .= " AND session_id = '" . $this->db->sql_escape($this->user->data['session_id']) . "'";
+ }
+
+ $this->db->sql_query($sql);
+
+ return $this;
}
/**
@@ -185,7 +336,7 @@ class token_storage implements TokenStorageInterface
return;
}
- $sql = 'UPDATE ' . $this->auth_provider_oauth_table . '
+ $sql = 'UPDATE ' . $this->oauth_token_table . '
SET ' . $this->db->sql_build_array('UPDATE', array(
'user_id' => (int) $user_id
)) . '
@@ -218,6 +369,29 @@ class token_storage implements TokenStorageInterface
}
/**
+ * Checks to see if a state exists solely by the session_id of the user
+ *
+ * @param string $service The name of the OAuth service
+ * @return bool true if they have state, false if they don't
+ */
+ public function has_state_by_session($service)
+ {
+ $service = $this->get_service_name_for_db($service);
+
+ if ($this->cachedState)
+ {
+ return true;
+ }
+
+ $data = array(
+ 'session_id' => $this->user->data['session_id'],
+ 'provider' => $service,
+ );
+
+ return (bool) $this->get_state_row($data);
+ }
+
+ /**
* A helper function that performs the query for has access token functions
*
* @param array $data
@@ -245,6 +419,23 @@ class token_storage implements TokenStorageInterface
return $this->_retrieve_access_token($data);
}
+ public function retrieve_state_by_session($service)
+ {
+ $service = $this->get_service_name_for_db($service);
+
+ if ($this->cachedState)
+ {
+ return $this->cachedState;
+ }
+
+ $data = array(
+ 'session_id' => $this->user->data['session_id'],
+ 'provider' => $service,
+ );
+
+ return $this->_retrieve_state($data);
+ }
+
/**
* A helper function that performs the query for retrieve access token functions
* Also checks if the token is a valid token
@@ -276,6 +467,26 @@ class token_storage implements TokenStorageInterface
}
/**
+ * A helper function that performs the query for retrieve state functions
+ *
+ * @param array $data
+ * @return mixed
+ * @throws \OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException
+ */
+ protected function _retrieve_state($data)
+ {
+ $row = $this->get_state_row($data);
+
+ if (!$row)
+ {
+ throw new AuthorizationStateNotFoundException();
+ }
+
+ $this->cachedState = $row['oauth_state'];
+ return $this->cachedState;
+ }
+
+ /**
* A helper function that performs the query for retrieving an access token
*
* @param array $data
@@ -283,7 +494,24 @@ class token_storage implements TokenStorageInterface
*/
protected function get_access_token_row($data)
{
- $sql = 'SELECT oauth_token FROM ' . $this->auth_provider_oauth_table . '
+ $sql = 'SELECT oauth_token FROM ' . $this->oauth_token_table . '
+ 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);
+
+ return $row;
+ }
+
+ /**
+ * A helper function that performs the query for retrieving a state
+ *
+ * @param array $data
+ * @return mixed
+ */
+ protected function get_state_row($data)
+ {
+ $sql = 'SELECT oauth_state FROM ' . $this->oauth_state_table . '
WHERE ' . $this->db->sql_build_array('SELECT', $data);
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
diff --git a/phpBB/phpbb/avatar/driver/driver.php b/phpBB/phpbb/avatar/driver/driver.php
index ad186635f2..45681f3e59 100644
--- a/phpBB/phpbb/avatar/driver/driver.php
+++ b/phpBB/phpbb/avatar/driver/driver.php
@@ -30,6 +30,9 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface
*/
protected $config;
+ /** @var \FastImageSize\FastImageSize */
+ protected $imagesize;
+
/**
* Current $phpbb_root_path
* @var string
@@ -73,14 +76,16 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface
* Construct a driver object
*
* @param \phpbb\config\config $config phpBB configuration
+ * @param \FastImageSize\FastImageSize $imagesize FastImageSize class
* @param string $phpbb_root_path Path to the phpBB root
* @param string $php_ext PHP file extension
* @param \phpbb\path_helper $path_helper phpBB path helper
* @param \phpbb\cache\driver\driver_interface $cache Cache driver
*/
- public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null)
+ public function __construct(\phpbb\config\config $config, \FastImageSize\FastImageSize $imagesize, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null)
{
$this->config = $config;
+ $this->imagesize = $imagesize;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->path_helper = $path_helper;
diff --git a/phpBB/phpbb/avatar/driver/gravatar.php b/phpBB/phpbb/avatar/driver/gravatar.php
index 7a43b55852..3e4e7ff98b 100644
--- a/phpBB/phpbb/avatar/driver/gravatar.php
+++ b/phpBB/phpbb/avatar/driver/gravatar.php
@@ -98,8 +98,8 @@ class gravatar extends \phpbb\avatar\driver\driver
return false;
}
- // Make sure getimagesize works...
- if (function_exists('getimagesize') && ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0))
+ // Get image dimensions if they are not set
+ if ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0)
{
/**
* default to the minimum of the maximum allowed avatar size if the size
@@ -108,20 +108,20 @@ class gravatar extends \phpbb\avatar\driver\driver
$row['avatar_width'] = $row['avatar_height'] = min($this->config['avatar_max_width'], $this->config['avatar_max_height']);
$url = $this->get_gravatar_url($row);
- if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = getimagesize($url)) === false))
+ if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = $this->imagesize->getImageSize($url)) === false))
{
$error[] = 'UNABLE_GET_IMAGE_SIZE';
return false;
}
- if (!empty($image_data) && ($image_data[0] <= 0 || $image_data[1] <= 0))
+ if (!empty($image_data) && ($image_data['width'] <= 0 || $image_data['width'] <= 0))
{
$error[] = 'AVATAR_NO_SIZE';
return false;
}
- $row['avatar_width'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_width'] : $image_data[0];
- $row['avatar_height'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_height'] : $image_data[1];
+ $row['avatar_width'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_width'] : $image_data['width'];
+ $row['avatar_height'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_height'] : $image_data['height'];
}
if ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0)
diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php
index 75c384f31e..f5547c4bc6 100644
--- a/phpBB/phpbb/avatar/driver/local.php
+++ b/phpBB/phpbb/avatar/driver/local.php
@@ -174,13 +174,15 @@ class local extends \phpbb\avatar\driver\driver
// Match all images in the gallery folder
if (preg_match('#^[^&\'"<>]+\.(?:' . implode('|', $this->allowed_extensions) . ')$#i', $image) && is_file($file_path . '/' . $image))
{
- if (function_exists('getimagesize'))
+ $dims = $this->imagesize->getImageSize($file_path . '/' . $image);
+
+ if ($dims === false)
{
- $dims = getimagesize($file_path . '/' . $image);
+ $dims = array(0, 0);
}
else
{
- $dims = array(0, 0);
+ $dims = array($dims['width'], $dims['height']);
}
$cat = ($path == $file_path) ? $user->lang['NO_AVATAR_CATEGORY'] : str_replace("$path/", '', $file_path);
$avatar_list[$cat][$image] = array(
diff --git a/phpBB/phpbb/avatar/driver/remote.php b/phpBB/phpbb/avatar/driver/remote.php
index bec54897b2..3a88a432d1 100644
--- a/phpBB/phpbb/avatar/driver/remote.php
+++ b/phpBB/phpbb/avatar/driver/remote.php
@@ -92,38 +92,30 @@ class remote extends \phpbb\avatar\driver\driver
return false;
}
- // Make sure getimagesize works...
- if (function_exists('getimagesize'))
+ // Get image dimensions
+ if (($width <= 0 || $height <= 0) && (($image_data = $this->imagesize->getImageSize($url)) === false))
{
- if (($width <= 0 || $height <= 0) && (($image_data = @getimagesize($url)) === false))
- {
- $error[] = 'UNABLE_GET_IMAGE_SIZE';
- return false;
- }
-
- if (!empty($image_data) && ($image_data[0] <= 0 || $image_data[1] <= 0))
- {
- $error[] = 'AVATAR_NO_SIZE';
- return false;
- }
-
- $width = ($width && $height) ? $width : $image_data[0];
- $height = ($width && $height) ? $height : $image_data[1];
+ $error[] = 'UNABLE_GET_IMAGE_SIZE';
+ return false;
}
- if ($width <= 0 || $height <= 0)
+ if (!empty($image_data) && ($image_data['width'] <= 0 || $image_data['height'] <= 0))
{
$error[] = 'AVATAR_NO_SIZE';
return false;
}
- if (!class_exists('fileupload'))
+ $width = ($width && $height) ? $width : $image_data['width'];
+ $height = ($width && $height) ? $height : $image_data['height'];
+
+ if ($width <= 0 || $height <= 0)
{
- include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext);
+ $error[] = 'AVATAR_NO_SIZE';
+ return false;
}
- $types = \fileupload::image_types();
- $extension = strtolower(\filespec::get_extension($url));
+ $types = \phpbb\files\upload::image_types();
+ $extension = strtolower(\phpbb\files\filespec::get_extension($url));
// Check if this is actually an image
if ($file_stream = @fopen($url, 'r'))
@@ -172,15 +164,15 @@ class remote extends \phpbb\avatar\driver\driver
return false;
}
- if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]])))
+ if (!empty($image_data) && (!isset($types[$image_data['type']]) || !in_array($extension, $types[$image_data['type']])))
{
- if (!isset($types[$image_data[2]]))
+ if (!isset($types[$image_data['type']]))
{
$error[] = 'UNABLE_GET_IMAGE_SIZE';
}
else
{
- $error[] = array('IMAGE_FILETYPE_MISMATCH', $types[$image_data[2]][0], $extension);
+ $error[] = array('IMAGE_FILETYPE_MISMATCH', $types[$image_data['type']][0], $extension);
}
return false;
diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php
index cb8dfcad4f..2640e1ad1e 100644
--- a/phpBB/phpbb/avatar/driver/upload.php
+++ b/phpBB/phpbb/avatar/driver/upload.php
@@ -19,9 +19,9 @@ namespace phpbb\avatar\driver;
class upload extends \phpbb\avatar\driver\driver
{
/**
- * @var \phpbb\mimetype\guesser
- */
- protected $mimetype_guesser;
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
/**
* @var \phpbb\event\dispatcher_interface
@@ -29,24 +29,31 @@ class upload extends \phpbb\avatar\driver\driver
protected $dispatcher;
/**
+ * @var \phpbb\files\factory
+ */
+ protected $files_factory;
+
+ /**
* Construct a driver object
*
* @param \phpbb\config\config $config phpBB configuration
* @param string $phpbb_root_path Path to the phpBB root
* @param string $php_ext PHP file extension
- * @param \phpbb_path_helper $path_helper phpBB path helper
- * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
+ * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB filesystem helper
+ * @param \phpbb\path_helper $path_helper phpBB path helper
* @param \phpbb\event\dispatcher_interface $dispatcher phpBB Event dispatcher object
+ * @param \phpbb\files\factory $files_factory File classes factory
* @param \phpbb\cache\driver\driver_interface $cache Cache driver
*/
- public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\cache\driver\driver_interface $cache = null)
+ public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\path_helper $path_helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\files\factory $files_factory, \phpbb\cache\driver\driver_interface $cache = null)
{
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
+ $this->filesystem = $filesystem;
$this->path_helper = $path_helper;
- $this->mimetype_guesser = $mimetype_guesser;
$this->dispatcher = $dispatcher;
+ $this->files_factory = $files_factory;
$this->cache = $cache;
}
@@ -92,19 +99,24 @@ class upload extends \phpbb\avatar\driver\driver
return false;
}
- if (!class_exists('fileupload'))
- {
- include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext);
- }
-
- $upload = new \fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false));
+ /** @var \phpbb\files\upload $upload */
+ $upload = $this->files_factory->get('upload')
+ ->set_error_prefix('AVATAR_')
+ ->set_allowed_extensions($this->allowed_extensions)
+ ->set_max_filesize($this->config['avatar_filesize'])
+ ->set_allowed_dimensions(
+ $this->config['avatar_min_width'],
+ $this->config['avatar_min_height'],
+ $this->config['avatar_max_width'],
+ $this->config['avatar_max_height'])
+ ->set_disallowed_content((isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false));
$url = $request->variable('avatar_upload_url', '');
$upload_file = $request->file('avatar_upload_file');
if (!empty($upload_file['name']))
{
- $file = $upload->form_upload('avatar_upload_file', $this->mimetype_guesser);
+ $file = $upload->handle_upload('files.types.form', 'avatar_upload_file');
}
else if (!empty($this->config['allow_avatar_remote_upload']) && !empty($url))
{
@@ -134,7 +146,7 @@ class upload extends \phpbb\avatar\driver\driver
return false;
}
- $file = $upload->remote_upload($url, $this->mimetype_guesser);
+ $file = $upload->handle_upload('files.types.remote', $url);
}
else
{
@@ -292,6 +304,6 @@ class upload extends \phpbb\avatar\driver\driver
*/
protected function can_upload()
{
- return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && phpbb_is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on'));
+ return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && $this->filesystem->is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on'));
}
}
diff --git a/phpBB/phpbb/cache/driver/base.php b/phpBB/phpbb/cache/driver/base.php
index 53c50eeda3..f4b3dc278d 100644
--- a/phpBB/phpbb/cache/driver/base.php
+++ b/phpBB/phpbb/cache/driver/base.php
@@ -49,7 +49,9 @@ abstract class base implements \phpbb\cache\driver\driver_interface
$this->remove_dir($fileInfo->getPathname());
}
else if (strpos($filename, 'container_') === 0 ||
+ strpos($filename, 'autoload_') === 0 ||
strpos($filename, 'url_matcher') === 0 ||
+ strpos($filename, 'url_generator') === 0 ||
strpos($filename, 'sql_') === 0 ||
strpos($filename, 'data_') === 0)
{
@@ -95,14 +97,14 @@ abstract class base implements \phpbb\cache\driver\driver_interface
{
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
+ $query_id = md5($query);
- if (($rowset = $this->_read('sql_' . md5($query))) === false)
+ if (($result = $this->_read('sql_' . $query_id)) === false)
{
return false;
}
- $query_id = sizeof($this->sql_rowset);
- $this->sql_rowset[$query_id] = $rowset;
+ $this->sql_rowset[$query_id] = $result;
$this->sql_row_pointer[$query_id] = 0;
return $query_id;
@@ -181,13 +183,9 @@ abstract class base implements \phpbb\cache\driver\driver_interface
*/
function remove_file($filename, $check = false)
{
- if (!function_exists('phpbb_is_writable'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/functions.' . $phpEx);
- }
+ global $phpbb_filesystem;
- if ($check && !phpbb_is_writable($this->cache_dir))
+ if ($check && !$phpbb_filesystem->is_writable($this->cache_dir))
{
// E_USER_ERROR - not using language entry - intended.
trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR);
diff --git a/phpBB/phpbb/cache/driver/dummy.php b/phpBB/phpbb/cache/driver/dummy.php
new file mode 100644
index 0000000000..1f74f6dd77
--- /dev/null
+++ b/phpBB/phpbb/cache/driver/dummy.php
@@ -0,0 +1,153 @@
+<?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\cache\driver;
+
+/**
+* ACM dummy Caching
+*/
+class dummy extends \phpbb\cache\driver\base
+{
+ /**
+ * Set cache path
+ */
+ function __construct()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function load()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function unload()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function save()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function tidy()
+ {
+ global $config;
+
+ // This cache always has a tidy room.
+ $config->set('cache_last_gc', time(), false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function get($var_name)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function put($var_name, $var, $ttl = 0)
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function purge()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function destroy($var_name, $table = '')
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function _exists($var_name)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_load($query)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl)
+ {
+ return $query_result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_exists($query_id)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_fetchrow($query_id)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_fetchfield($query_id, $field)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_rowseek($rownum, $query_id)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_freeresult($query_id)
+ {
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/cache/driver/eaccelerator.php b/phpBB/phpbb/cache/driver/eaccelerator.php
index 1697758acc..740855144f 100644
--- a/phpBB/phpbb/cache/driver/eaccelerator.php
+++ b/phpBB/phpbb/cache/driver/eaccelerator.php
@@ -44,9 +44,11 @@ class eaccelerator extends \phpbb\cache\driver\memory
*/
function tidy()
{
+ global $config;
+
eaccelerator_gc();
- set_config('cache_last_gc', time(), true);
+ $config->set('cache_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php
index fae4614039..a210d877f0 100644
--- a/phpBB/phpbb/cache/driver/file.php
+++ b/phpBB/phpbb/cache/driver/file.php
@@ -21,14 +21,26 @@ class file extends \phpbb\cache\driver\base
var $var_expires = array();
/**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
* Set cache path
*
* @param string $cache_dir Define the path to the cache directory (default: $phpbb_root_path . 'cache/')
*/
function __construct($cache_dir = null)
{
- global $phpbb_root_path;
- $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/';
+ global $phpbb_container;
+
+ $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_container->getParameter('core.cache_dir');
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+
+ if (!is_dir($this->cache_dir))
+ {
+ @mkdir($this->cache_dir, 0777, true);
+ }
}
/**
@@ -63,14 +75,8 @@ class file extends \phpbb\cache\driver\base
if (!$this->_write('data_global'))
{
- if (!function_exists('phpbb_is_writable'))
- {
- global $phpbb_root_path;
- include($phpbb_root_path . 'includes/functions.' . $phpEx);
- }
-
// Now, this occurred how often? ... phew, just tell the user then...
- if (!phpbb_is_writable($this->cache_dir))
+ if (!$this->filesystem->is_writable($this->cache_dir))
{
// We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload())
die('Fatal: ' . $this->cache_dir . ' is NOT writable.');
@@ -89,7 +95,7 @@ class file extends \phpbb\cache\driver\base
*/
function tidy()
{
- global $phpEx;
+ global $config, $phpEx;
$dir = @opendir($this->cache_dir);
@@ -143,7 +149,7 @@ class file extends \phpbb\cache\driver\base
}
}
- set_config('cache_last_gc', time(), true);
+ $config->set('cache_last_gc', time(), false);
}
/**
@@ -306,7 +312,7 @@ class file extends \phpbb\cache\driver\base
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
- $query_id = sizeof($this->sql_rowset);
+ $query_id = md5($query);
$this->sql_rowset[$query_id] = array();
$this->sql_row_pointer[$query_id] = 0;
@@ -316,7 +322,7 @@ class file extends \phpbb\cache\driver\base
}
$db->sql_freeresult($query_result);
- if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query))
+ if ($this->_write('sql_' . $query_id, $this->sql_rowset[$query_id], $ttl + time(), $query))
{
return $query_id;
}
@@ -570,16 +576,17 @@ class file extends \phpbb\cache\driver\base
if (function_exists('opcache_invalidate'))
{
- @opcache_invalidate($file);
+ @opcache_invalidate($this->cache_file);
}
- if (!function_exists('phpbb_chmod'))
+ try
{
- global $phpbb_root_path;
- include($phpbb_root_path . 'includes/functions.' . $phpEx);
+ $this->filesystem->phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
}
-
- phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
$return_value = true;
}
diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php
index 0b0e323e3d..cc03804705 100644
--- a/phpBB/phpbb/cache/driver/memory.php
+++ b/phpBB/phpbb/cache/driver/memory.php
@@ -25,9 +25,9 @@ abstract class memory extends \phpbb\cache\driver\base
*/
function __construct()
{
- global $phpbb_root_path, $dbname, $table_prefix;
+ global $phpbb_root_path, $dbname, $table_prefix, $phpbb_container;
- $this->cache_dir = $phpbb_root_path . 'cache/';
+ $this->cache_dir = $phpbb_container->getParameter('core.cache_dir');
$this->key_prefix = substr(md5($dbname . $table_prefix), 0, 8) . '_';
if (!isset($this->extension) || !extension_loaded($this->extension))
@@ -81,9 +81,10 @@ abstract class memory extends \phpbb\cache\driver\base
*/
function tidy()
{
- // cache has auto GC, no need to have any code here :)
+ global $config;
- set_config('cache_last_gc', time(), true);
+ // cache has auto GC, no need to have any code here :)
+ $config->set('cache_last_gc', time(), false);
}
/**
@@ -203,7 +204,7 @@ abstract class memory extends \phpbb\cache\driver\base
{
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
- $hash = md5($query);
+ $query_id = md5($query);
// determine which tables this query belongs to
// Some queries use backticks, namely the get_database_size() query
@@ -244,14 +245,13 @@ abstract class memory extends \phpbb\cache\driver\base
$temp = array();
}
- $temp[$hash] = true;
+ $temp[$query_id] = true;
// This must never expire
$this->_write('sql_' . $table_name, $temp, 0);
}
// store them in the right place
- $query_id = sizeof($this->sql_rowset);
$this->sql_rowset[$query_id] = array();
$this->sql_row_pointer[$query_id] = 0;
@@ -261,7 +261,7 @@ abstract class memory extends \phpbb\cache\driver\base
}
$db->sql_freeresult($query_result);
- $this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl);
+ $this->_write('sql_' . $query_id, $this->sql_rowset[$query_id], $ttl);
return $query_id;
}
diff --git a/phpBB/phpbb/cache/driver/null.php b/phpBB/phpbb/cache/driver/null.php
deleted file mode 100644
index a45cf97862..0000000000
--- a/phpBB/phpbb/cache/driver/null.php
+++ /dev/null
@@ -1,151 +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\cache\driver;
-
-/**
-* ACM Null Caching
-*/
-class null extends \phpbb\cache\driver\base
-{
- /**
- * Set cache path
- */
- function __construct()
- {
- }
-
- /**
- * {@inheritDoc}
- */
- function load()
- {
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- function unload()
- {
- }
-
- /**
- * {@inheritDoc}
- */
- function save()
- {
- }
-
- /**
- * {@inheritDoc}
- */
- function tidy()
- {
- // This cache always has a tidy room.
- set_config('cache_last_gc', time(), true);
- }
-
- /**
- * {@inheritDoc}
- */
- function get($var_name)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function put($var_name, $var, $ttl = 0)
- {
- }
-
- /**
- * {@inheritDoc}
- */
- function purge()
- {
- }
-
- /**
- * {@inheritDoc}
- */
- function destroy($var_name, $table = '')
- {
- }
-
- /**
- * {@inheritDoc}
- */
- function _exists($var_name)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_load($query)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl)
- {
- return $query_result;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_exists($query_id)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_fetchrow($query_id)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_fetchfield($query_id, $field)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_rowseek($rownum, $query_id)
- {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_freeresult($query_id)
- {
- return false;
- }
-}
diff --git a/phpBB/phpbb/cache/service.php b/phpBB/phpbb/cache/service.php
index 56727c2ad5..8a4366fed1 100644
--- a/phpBB/phpbb/cache/service.php
+++ b/phpBB/phpbb/cache/service.php
@@ -141,6 +141,7 @@ class service
$icons[$row['icons_id']]['img'] = $row['icons_url'];
$icons[$row['icons_id']]['width'] = (int) $row['icons_width'];
$icons[$row['icons_id']]['height'] = (int) $row['icons_height'];
+ $icons[$row['icons_id']]['alt'] = ($row['icons_alt']) ? $row['icons_alt'] : '';
$icons[$row['icons_id']]['display'] = (bool) $row['display_on_posting'];
}
$this->db->sql_freeresult($result);
@@ -301,7 +302,6 @@ class service
{
switch ($this->db->get_sql_layer())
{
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$sql = 'SELECT user_id, bot_agent, bot_ip
diff --git a/phpBB/phpbb/captcha/gd.php b/phpBB/phpbb/captcha/gd.php
index 652df28f8a..e9538439c6 100644
--- a/phpBB/phpbb/captcha/gd.php
+++ b/phpBB/phpbb/captcha/gd.php
@@ -97,13 +97,12 @@ class gd
if ($config['captcha_gd_3d_noise'])
{
- $xoffset = mt_rand(0,9);
$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'])));
- list($min, $max) = $noise[$i]->range();
+ $noise[$i]->range();
//$box = $noise[$i]->dimensions($sizes[$i]);
}
$xoffset = 0;
@@ -151,8 +150,6 @@ class gd
*/
function wave($img)
{
- global $config;
-
$period_x = mt_rand(12,18);
$period_y = mt_rand(7,14);
$amp_x = mt_rand(5,10);
diff --git a/phpBB/phpbb/captcha/gd_wave.php b/phpBB/phpbb/captcha/gd_wave.php
index d48fc753a5..f2ec4137d2 100644
--- a/phpBB/phpbb/captcha/gd_wave.php
+++ b/phpBB/phpbb/captcha/gd_wave.php
@@ -23,8 +23,6 @@ class gd_wave
function execute($code, $seed)
{
- global $starttime;
-
// seed the random generator
mt_srand($seed);
@@ -77,7 +75,6 @@ class gd_wave
// TODO
$background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));
imagefill($img, 0, 0, $background);
- $black = imagecolorallocate($img, 0, 0, 0);
$random = array();
$fontcolors = array();
@@ -155,7 +152,7 @@ class gd_wave
// rather than recalculating from absolute coordinates
// What we cache into the $img_buffer contains the raised text coordinates.
$img_pos_prev = $img_buffer[0][0] = array($box['upper_left']['x'], $box['upper_left']['y']);
- $cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor);
+ $prev_height = $this->wave_height(0, 0, $subdivision_factor);
$full_x = $plane_x * $subdivision_factor;
$full_y = $plane_y * $subdivision_factor;
diff --git a/phpBB/phpbb/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php
index 24ed7f939d..82b08704ff 100644
--- a/phpBB/phpbb/captcha/plugins/captcha_abstract.php
+++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php
@@ -34,12 +34,12 @@ abstract class captcha_abstract
function init($type)
{
- global $config, $db, $user;
+ global $config, $request;
// read input
- $this->confirm_id = request_var('confirm_id', '');
- $this->confirm_code = request_var('confirm_code', '');
- $refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
+ $this->confirm_id = $request->variable('confirm_id', '');
+ $this->confirm_code = $request->variable('confirm_code', '');
+ $refresh = $request->variable('refresh_vc', false) && $config['confirm_refresh'];
$this->type = (int) $type;
@@ -56,8 +56,6 @@ abstract class captcha_abstract
function execute_demo()
{
- global $user;
-
$this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
@@ -117,7 +115,7 @@ abstract class captcha_abstract
function get_demo_template($id)
{
- global $config, $user, $template, $phpbb_admin_path, $phpEx;
+ global $config, $template, $request, $phpbb_admin_path, $phpEx;
$variables = '';
@@ -125,7 +123,7 @@ abstract class captcha_abstract
{
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
- $variables .= '&amp;' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
+ $variables .= '&amp;' . rawurlencode($captcha_var) . '=' . $request->variable($captcha_var, (int) $config[$captcha_var]);
}
}
@@ -153,7 +151,7 @@ abstract class captcha_abstract
function garbage_collect($type)
{
- global $db, $config;
+ global $db;
$sql = 'SELECT DISTINCT c.session_id
FROM ' . CONFIRM_TABLE . ' c
@@ -193,9 +191,9 @@ abstract class captcha_abstract
function validate()
{
- global $config, $db, $user;
+ global $user;
- if (empty($user->lang))
+ if (!$user->is_setup())
{
$user->setup();
}
@@ -350,7 +348,9 @@ abstract class captcha_abstract
function is_solved()
{
- if (request_var('confirm_code', false) && $this->solved === 0)
+ global $request;
+
+ if ($request->variable('confirm_code', false) && $this->solved === 0)
{
$this->validate();
}
diff --git a/phpBB/phpbb/captcha/plugins/gd.php b/phpBB/phpbb/captcha/plugins/gd.php
index f6200b5b2f..831e5bcfdf 100644
--- a/phpBB/phpbb/captcha/plugins/gd.php
+++ b/phpBB/phpbb/captcha/plugins/gd.php
@@ -53,38 +53,31 @@ class gd extends captcha_abstract
function acp_page($id, &$module)
{
- global $db, $user, $auth, $template;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $user, $template, $phpbb_log, $request;
+ global $config;
$user->add_lang('acp/board');
- $config_vars = array(
- 'enable_confirm' => 'REG_ENABLE',
- 'enable_post_confirm' => 'POST_ENABLE',
- 'confirm_refresh' => 'CONFIRM_REFRESH',
- 'captcha_gd' => 'CAPTCHA_GD',
- );
-
$module->tpl_name = 'captcha_gd_acp';
$module->page_title = 'ACP_VC_SETTINGS';
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('submit', '');
+ $submit = $request->variable('submit', '');
if ($submit && check_form_key($form_key))
{
$captcha_vars = array_keys($this->captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
- $value = request_var($captcha_var, 0);
+ $value = $request->variable($captcha_var, 0);
if ($value >= 0)
{
- set_config($captcha_var, $value);
+ $config->set($captcha_var, $value);
}
}
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
}
else if ($submit)
@@ -95,7 +88,7 @@ class gd extends captcha_abstract
{
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
- $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
+ $var = (isset($_REQUEST[$captcha_var])) ? $request->variable($captcha_var, 0) : $config[$captcha_var];
$template->assign_var($template_var, $var);
}
@@ -109,7 +102,7 @@ class gd extends captcha_abstract
function execute_demo()
{
- global $config;
+ global $config, $request;
$config_old = $config;
@@ -121,7 +114,7 @@ class gd extends captcha_abstract
foreach ($this->captcha_vars as $captcha_var => $template_var)
{
- $config->set($captcha_var, request_var($captcha_var, (int) $config[$captcha_var]));
+ $config->set($captcha_var, $request->variable($captcha_var, (int) $config[$captcha_var]));
}
parent::execute_demo();
$config = $config_old;
diff --git a/phpBB/phpbb/captcha/plugins/gd_wave.php b/phpBB/phpbb/captcha/plugins/gd_wave.php
index e1d44df778..bde46f8815 100644
--- a/phpBB/phpbb/captcha/plugins/gd_wave.php
+++ b/phpBB/phpbb/captcha/plugins/gd_wave.php
@@ -35,7 +35,7 @@ class gd_wave extends captcha_abstract
function acp_page($id, &$module)
{
- global $config, $db, $template, $user;
+ global $user;
trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
}
diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php
index a9d133d8f2..9d481acc5d 100644
--- a/phpBB/phpbb/captcha/plugins/qa.php
+++ b/phpBB/phpbb/captcha/plugins/qa.php
@@ -58,14 +58,14 @@ class qa
*/
function init($type)
{
- global $config, $db, $user;
+ global $config, $db, $user, $request;
// load our language file
$user->add_lang('captcha_qa');
// read input
- $this->confirm_id = request_var('qa_confirm_id', '');
- $this->answer = utf8_normalize_nfc(request_var('qa_answer', '', true));
+ $this->confirm_id = $request->variable('qa_confirm_id', '');
+ $this->answer = $request->variable('qa_answer', '', true);
$this->type = (int) $type;
$this->question_lang = $user->lang_name;
@@ -135,9 +135,9 @@ class qa
*/
public function is_installed()
{
- global $db;
+ global $phpbb_container;
- $db_tool = new \phpbb\db\tools($db);
+ $db_tool = $phpbb_container->get('dbal.tools');
return $db_tool->sql_table_exists($this->table_captcha_questions);
}
@@ -334,10 +334,9 @@ class qa
*/
function install()
{
- global $db;
-
- $db_tool = new \phpbb\db\tools($db);
+ global $phpbb_container;
+ $db_tool = $phpbb_container->get('dbal.tools');
$schemas = array(
$this->table_captcha_questions => array (
'COLUMNS' => array(
@@ -572,9 +571,9 @@ class qa
*/
function check_answer()
{
- global $db;
+ global $db, $request;
- $answer = ($this->question_strict) ? utf8_normalize_nfc(request_var('qa_answer', '', true)) : utf8_clean_string(utf8_normalize_nfc(request_var('qa_answer', '', true)));
+ $answer = ($this->question_strict) ? $request->variable('qa_answer', '', true) : utf8_clean_string($request->variable('qa_answer', '', true));
$sql = 'SELECT answer_text
FROM ' . $this->table_captcha_answers . '
@@ -626,7 +625,9 @@ class qa
*/
function is_solved()
{
- if (request_var('qa_answer', false) && $this->solved === 0)
+ global $request;
+
+ if ($request->variable('qa_answer', false) && $this->solved === 0)
{
$this->validate();
}
@@ -639,8 +640,7 @@ class qa
*/
function acp_page($id, &$module)
{
- global $user, $template;
- global $config;
+ global $config, $request, $phpbb_log, $template, $user;
$user->add_lang('acp/board');
$user->add_lang('captcha_qa');
@@ -655,9 +655,9 @@ class qa
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('submit', false);
- $question_id = request_var('question_id', 0);
- $action = request_var('action', '');
+ $submit = $request->variable('submit', false);
+ $question_id = $request->variable('question_id', 0);
+ $action = $request->variable('action', '');
// we have two pages, so users might want to navigate from one to the other
$list_url = $module->u_action . "&amp;configure=1&amp;select_captcha=" . $this->get_service_name();
@@ -762,7 +762,7 @@ class qa
$this->acp_add_question($question_input);
}
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url));
}
}
@@ -848,7 +848,9 @@ class qa
*/
function acp_get_question_input()
{
- $answers = utf8_normalize_nfc(request_var('answers', '', true));
+ global $request;
+
+ $answers = $request->variable('answers', '', true);
// Convert answers into array and filter if answers are set
if (strlen($answers))
@@ -859,9 +861,9 @@ class qa
}
$question = array(
- 'question_text' => request_var('question_text', '', true),
- 'strict' => request_var('strict', false),
- 'lang_iso' => request_var('lang_iso', ''),
+ 'question_text' => $request->variable('question_text', '', true),
+ 'strict' => $request->variable('strict', false),
+ 'lang_iso' => $request->variable('lang_iso', ''),
'answers' => $answers,
);
return $question;
diff --git a/phpBB/phpbb/captcha/plugins/recaptcha.php b/phpBB/phpbb/captcha/plugins/recaptcha.php
index 584f3afec1..152709a9ea 100644
--- a/phpBB/phpbb/captcha/plugins/recaptcha.php
+++ b/phpBB/phpbb/captcha/plugins/recaptcha.php
@@ -18,12 +18,6 @@ class recaptcha extends captcha_abstract
var $recaptcha_server = 'http://www.google.com/recaptcha/api';
var $recaptcha_server_secure = 'https://www.google.com/recaptcha/api'; // class constants :(
- // We are opening a socket to port 80 of this host and send
- // the POST request asking for verification to the path specified here.
- var $recaptcha_verify_server = 'www.google.com';
- var $recaptcha_verify_path = '/recaptcha/api/verify';
-
- var $challenge;
var $response;
/**
@@ -37,12 +31,11 @@ class recaptcha extends captcha_abstract
function init($type)
{
- global $config, $db, $user;
+ global $user, $request;
$user->add_lang('captcha_recaptcha');
parent::init($type);
- $this->challenge = request_var('recaptcha_challenge_field', '');
- $this->response = request_var('recaptcha_response_field', '');
+ $this->response = $request->variable('g-recaptcha-response', '');
}
public function is_available()
@@ -75,7 +68,7 @@ class recaptcha extends captcha_abstract
function acp_page($id, &$module)
{
- global $config, $db, $template, $user;
+ global $config, $template, $user, $phpbb_log, $request;
$captcha_vars = array(
'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY',
@@ -87,21 +80,21 @@ class recaptcha extends captcha_abstract
$form_key = 'acp_captcha';
add_form_key($form_key);
- $submit = request_var('submit', '');
+ $submit = $request->variable('submit', '');
if ($submit && check_form_key($form_key))
{
$captcha_vars = array_keys($captcha_vars);
foreach ($captcha_vars as $captcha_var)
{
- $value = request_var($captcha_var, '');
+ $value = $request->variable($captcha_var, '');
if ($value)
{
- set_config($captcha_var, $value);
+ $config->set($captcha_var, $value);
}
}
- add_log('admin', 'LOG_CONFIG_VISUAL');
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
}
else if ($submit)
@@ -112,7 +105,7 @@ class recaptcha extends captcha_abstract
{
foreach ($captcha_vars as $captcha_var => $template_var)
{
- $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
+ $var = (isset($_REQUEST[$captcha_var])) ? $request->variable($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
$template->assign_var($template_var, $var);
}
@@ -151,7 +144,6 @@ class recaptcha extends captcha_abstract
$template->assign_vars(array(
'RECAPTCHA_SERVER' => $this->recaptcha_server,
'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '',
- 'RECAPTCHA_ERRORGET' => '',
'S_RECAPTCHA_AVAILABLE' => self::is_available(),
'S_CONFIRM_CODE' => true,
'S_TYPE' => $this->type,
@@ -202,106 +194,25 @@ class recaptcha extends captcha_abstract
}
}
-// Code from here on is based on recaptchalib.php
-/*
- * This is a PHP library that handles calling reCAPTCHA.
- * - Documentation and latest version
- * http://recaptcha.net/plugins/php/
- * - Get a reCAPTCHA API Key
- * http://recaptcha.net/api/getkey
- * - Discussion group
- * http://groups.google.com/group/recaptcha
- *
- * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
- * AUTHORS:
- * Mike Crawford
- * Ben Maurer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
- /**
- * Submits an HTTP POST to a reCAPTCHA server
- * @param string $host
- * @param string $path
- * @param array $data
- * @param int port
- * @return array response
- */
- function _recaptcha_http_post($host, $path, $data, $port = 80)
- {
- $req = $this->_recaptcha_qsencode ($data);
-
- $http_request = "POST $path HTTP/1.0\r\n";
- $http_request .= "Host: $host\r\n";
- $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
- $http_request .= "Content-Length: " . strlen($req) . "\r\n";
- $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n";
- $http_request .= "\r\n";
- $http_request .= $req;
-
- $response = '';
- if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10)))
- {
- trigger_error('RECAPTCHA_SOCKET_ERROR', E_USER_ERROR);
- }
-
- fwrite($fs, $http_request);
-
- while (!feof($fs))
- {
- // One TCP-IP packet
- $response .= fgets($fs, 1160);
- }
- fclose($fs);
- $response = explode("\r\n\r\n", $response, 2);
-
- return $response;
- }
-
/**
* Calls an HTTP POST function to verify if the user's guess was correct
- * @param array $extra_params an array of extra variables to post to the server
- * @return ReCaptchaResponse
+ *
+ * @return bool|string Returns false on success or error string on failure.
*/
- function recaptcha_check_answer($extra_params = array())
+ function recaptcha_check_answer()
{
global $config, $user;
//discard spam submissions
- if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0)
+ if ($this->response == null || strlen($this->response) == 0)
{
return $user->lang['RECAPTCHA_INCORRECT'];
}
- $response = $this->_recaptcha_http_post($this->recaptcha_verify_server, $this->recaptcha_verify_path,
- array(
- 'privatekey' => $config['recaptcha_privkey'],
- 'remoteip' => $user->ip,
- 'challenge' => $this->challenge,
- 'response' => $this->response
- ) + $extra_params
- );
-
- $answers = explode("\n", $response[1]);
+ $recaptcha = new \ReCaptcha\ReCaptcha($config['recaptcha_privkey']);
+ $result = $recaptcha->verify($this->response, $user->ip);
- if (trim($answers[0]) === 'true')
+ if ($result->isSuccess())
{
$this->solved = true;
return false;
@@ -311,22 +222,4 @@ class recaptcha extends captcha_abstract
return $user->lang['RECAPTCHA_INCORRECT'];
}
}
-
- /**
- * Encodes the given data into a query string format
- * @param $data - array of string elements to be encoded
- * @return string - encoded request
- */
- function _recaptcha_qsencode($data)
- {
- $req = '';
- foreach ($data as $key => $value)
- {
- $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
- }
-
- // Cut the last '&'
- $req = substr($req, 0, strlen($req) - 1);
- return $req;
- }
}
diff --git a/phpBB/phpbb/composer.json b/phpBB/phpbb/composer.json
index 6b3888ef64..0b6299d6bc 100644
--- a/phpBB/phpbb/composer.json
+++ b/phpBB/phpbb/composer.json
@@ -22,11 +22,11 @@
"classmap": [""]
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.4"
},
"extra": {
"branch-alias": {
- "dev-master": "3.1.x-dev"
+ "dev-master": "3.3.x-dev"
}
}
}
diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php
index bc4897af18..dc9b8016b2 100644
--- a/phpBB/phpbb/console/application.php
+++ b/phpBB/phpbb/console/application.php
@@ -13,6 +13,7 @@
namespace phpbb\console;
+use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Shell;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -26,18 +27,18 @@ class application extends \Symfony\Component\Console\Application
protected $in_shell = false;
/**
- * @var \phpbb\user User object
+ * @var \phpbb\language\language User object
*/
- protected $user;
+ protected $language;
/**
- * @param string $name The name of the application
- * @param string $version The version of the application
- * @param \phpbb\user $user The user which runs the application (used for translation)
+ * @param string $name The name of the application
+ * @param string $version The version of the application
+ * @param \phpbb\language\language $language The user which runs the application (used for translation)
*/
- public function __construct($name, $version, \phpbb\user $user)
+ public function __construct($name, $version, \phpbb\language\language $language)
{
- $this->user = $user;
+ $this->language = $language;
parent::__construct($name, $version);
}
@@ -49,12 +50,7 @@ class application extends \Symfony\Component\Console\Application
{
$input_definition = parent::getDefaultInputDefinition();
- $input_definition->addOption(new InputOption(
- 'safe-mode',
- null,
- InputOption::VALUE_NONE,
- $this->user->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE')
- ));
+ $this->register_global_options($input_definition);
return $input_definition;
}
@@ -76,12 +72,20 @@ class application extends \Symfony\Component\Console\Application
return parent::getHelp();
}
- $this->getDefinition()->addOption(new InputOption(
- '--shell',
- '-s',
- InputOption::VALUE_NONE,
- $this->user->lang('CLI_DESCRIPTION_OPTION_SHELL')
- ));
+ try
+ {
+ $definition = $this->getDefinition();
+ $definition->addOption(new InputOption(
+ '--shell',
+ '-s',
+ InputOption::VALUE_NONE,
+ $this->language->lang('CLI_DESCRIPTION_OPTION_SHELL')
+ ));
+ }
+ catch (\LogicException $e)
+ {
+ // Do nothing
+ }
return parent::getHelp();
}
@@ -117,4 +121,33 @@ class application extends \Symfony\Component\Console\Application
return parent::doRun($input, $output);
}
+
+ /**
+ * Register global options
+ *
+ * @param InputDefinition $definition An InputDefinition instance
+ */
+ protected function register_global_options(InputDefinition $definition)
+ {
+ try
+ {
+ $definition->addOption(new InputOption(
+ 'safe-mode',
+ null,
+ InputOption::VALUE_NONE,
+ $this->language->lang('CLI_DESCRIPTION_OPTION_SAFE_MODE')
+ ));
+
+ $definition->addOption(new InputOption(
+ 'env',
+ 'e',
+ InputOption::VALUE_REQUIRED,
+ $this->language->lang('CLI_DESCRIPTION_OPTION_ENV')
+ ));
+ }
+ catch (\LogicException $e)
+ {
+ // Do nothing
+ }
+ }
}
diff --git a/phpBB/phpbb/console/command/command.php b/phpBB/phpbb/console/command/command.php
index 638c989da2..0124c00d22 100644
--- a/phpBB/phpbb/console/command/command.php
+++ b/phpBB/phpbb/console/command/command.php
@@ -13,6 +13,10 @@
namespace phpbb\console\command;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
abstract class command extends \Symfony\Component\Console\Command\Command
{
/** @var \phpbb\user */
@@ -28,4 +32,45 @@ abstract class command extends \Symfony\Component\Console\Command\Command
$this->user = $user;
parent::__construct();
}
+
+ /**
+ * Create a styled progress bar
+ *
+ * @param int $max Max value for the progress bar
+ * @param SymfonyStyle $io Symfony style output decorator
+ * @param OutputInterface $output The output stream, used to print messages
+ * @param bool $message Should we display message output under the progress bar?
+ * @return ProgressBar
+ */
+ public function create_progress_bar($max, SymfonyStyle $io, OutputInterface $output, $message = false)
+ {
+ $progress = $io->createProgressBar($max);
+ if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE)
+ {
+ $progress->setFormat('<info>[%percent:3s%%]</info> %message%');
+ $progress->setOverwrite(false);
+ }
+ else if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE)
+ {
+ $progress->setFormat('<info>[%current:s%/%max:s%]</info><comment>[%elapsed%/%estimated%][%memory%]</comment> %message%');
+ $progress->setOverwrite(false);
+ }
+ else
+ {
+ $io->newLine(2);
+ $progress->setFormat(
+ " %current:s%/%max:s% %bar% %percent:3s%%\n" .
+ " " . ($message ? '%message%' : ' ') . " %elapsed:6s%/%estimated:-6s% %memory:6s%\n");
+ $progress->setBarWidth(60);
+ }
+
+ if (!defined('PHP_WINDOWS_VERSION_BUILD'))
+ {
+ $progress->setEmptyBarCharacter('â–‘'); // light shade character \u2591
+ $progress->setProgressCharacter('');
+ $progress->setBarCharacter('â–“'); // dark shade character \u2593
+ }
+
+ return $progress;
+ }
}
diff --git a/phpBB/phpbb/console/command/cron/run.php b/phpBB/phpbb/console/command/cron/run.php
index a9648fcd41..dea6493007 100644
--- a/phpBB/phpbb/console/command/cron/run.php
+++ b/phpBB/phpbb/console/command/cron/run.php
@@ -13,6 +13,7 @@
namespace phpbb\console\command\cron;
+use phpbb\exception\runtime_exception;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
@@ -93,8 +94,7 @@ class run extends \phpbb\console\command\command
}
else
{
- $output->writeln('<error>' . $this->user->lang('CRON_LOCK_ERROR') . '</error>');
- return 1;
+ throw new runtime_exception('CRON_LOCK_ERROR', array(), null, 1);
}
}
@@ -165,8 +165,7 @@ class run extends \phpbb\console\command\command
}
else
{
- $output->writeln('<error>' . $this->user->lang('CRON_NO_SUCH_TASK', $task_name) . '</error>');
- return 2;
+ throw new runtime_exception('CRON_NO_SUCH_TASK', array( $task_name), null, 2);
}
}
}
diff --git a/phpBB/phpbb/console/command/db/console_migrator_output_handler.php b/phpBB/phpbb/console/command/db/console_migrator_output_handler.php
index b9741a3838..568b2646d4 100644
--- a/phpBB/phpbb/console/command/db/console_migrator_output_handler.php
+++ b/phpBB/phpbb/console/command/db/console_migrator_output_handler.php
@@ -13,8 +13,8 @@
namespace phpbb\console\command\db;
+use phpbb\db\output_handler\migrator_output_handler_interface;
use phpbb\user;
-use phpbb\db\migrator_output_handler_interface;
use Symfony\Component\Console\Output\OutputInterface;
class console_migrator_output_handler implements migrator_output_handler_interface
diff --git a/phpBB/phpbb/console/command/db/list_command.php b/phpBB/phpbb/console/command/db/list_command.php
new file mode 100644
index 0000000000..708107b592
--- /dev/null
+++ b/phpBB/phpbb/console/command/db/list_command.php
@@ -0,0 +1,73 @@
+<?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\console\command\db;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class list_command extends \phpbb\console\command\db\migration_command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('db:list')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_DB_LIST'))
+ ->addOption(
+ 'available',
+ 'u',
+ InputOption::VALUE_NONE,
+ $this->user->lang('CLI_MIGRATIONS_ONLY_AVAILABLE')
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $show_installed = !$input->getOption('available');
+ $installed = $available = array();
+
+ foreach ($this->load_migrations() as $name)
+ {
+ if ($this->migrator->migration_state($name) !== false)
+ {
+ $installed[] = $name;
+ }
+ else
+ {
+ $available[] = $name;
+ }
+ }
+
+ if ($show_installed)
+ {
+ $output->writeln('<info>' . $this->user->lang('CLI_MIGRATIONS_INSTALLED') . $this->user->lang('COLON') . '</info>');
+ $output->writeln($installed);
+
+ if (empty($installed))
+ {
+ $output->writeln($this->user->lang('CLI_MIGRATIONS_EMPTY'));
+ }
+
+ $output->writeln('');
+ }
+
+ $output->writeln('<info>' . $this->user->lang('CLI_MIGRATIONS_AVAILABLE') . $this->user->lang('COLON') . '</info>');
+ $output->writeln($available);
+
+ if (empty($available))
+ {
+ $output->writeln($this->user->lang('CLI_MIGRATIONS_EMPTY'));
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php
index 87c2a057d1..ae4211f7be 100644
--- a/phpBB/phpbb/console/command/db/migrate.php
+++ b/phpBB/phpbb/console/command/db/migrate.php
@@ -12,38 +12,31 @@
*/
namespace phpbb\console\command\db;
+use phpbb\db\output_handler\log_wrapper_migrator_output_handler;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-class migrate extends \phpbb\console\command\command
+class migrate extends \phpbb\console\command\db\migration_command
{
- /** @var \phpbb\db\migrator */
- protected $migrator;
-
- /** @var \phpbb\extension\manager */
- protected $extension_manager;
-
- /** @var \phpbb\config\config */
- protected $config;
-
- /** @var \phpbb\cache\service */
- protected $cache;
-
/** @var \phpbb\log\log */
protected $log;
/** @var string phpBB root path */
protected $phpbb_root_path;
- function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, $phpbb_root_path)
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
{
- $this->migrator = $migrator;
- $this->extension_manager = $extension_manager;
- $this->config = $config;
- $this->cache = $cache;
+ $this->language = $language;
$this->log = $log;
+ $this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path;
- parent::__construct($user);
+ parent::__construct($user, $migrator, $extension_manager, $config, $cache);
$this->user->add_lang(array('common', 'install', 'migrator'));
}
@@ -57,7 +50,7 @@ class migrate extends \phpbb\console\command\command
protected function execute(InputInterface $input, OutputInterface $output)
{
- $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log'));
+ $this->migrator->set_output_handler(new log_wrapper_migrator_output_handler($this->language, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
$this->migrator->create_migrations_table();
@@ -87,21 +80,4 @@ class migrate extends \phpbb\console\command\command
$this->finalise_update();
$output->writeln($this->user->lang['DATABASE_UPDATE_COMPLETE']);
}
-
- protected function load_migrations()
- {
- $migrations = $this->extension_manager
- ->get_finder()
- ->core_path('phpbb/db/migration/data/')
- ->extension_directory('/migrations')
- ->get_classes();
-
- $this->migrator->set_migrations($migrations);
- }
-
- protected function finalise_update()
- {
- $this->cache->purge();
- $this->config->increment('assets_version', 1);
- }
}
diff --git a/phpBB/phpbb/console/command/db/migration_command.php b/phpBB/phpbb/console/command/db/migration_command.php
new file mode 100644
index 0000000000..b951560588
--- /dev/null
+++ b/phpBB/phpbb/console/command/db/migration_command.php
@@ -0,0 +1,56 @@
+<?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\console\command\db;
+
+abstract class migration_command extends \phpbb\console\command\command
+{
+ /** @var \phpbb\db\migrator */
+ protected $migrator;
+
+ /** @var \phpbb\extension\manager */
+ protected $extension_manager;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \phpbb\cache\service */
+ protected $cache;
+
+ function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache)
+ {
+ $this->migrator = $migrator;
+ $this->extension_manager = $extension_manager;
+ $this->config = $config;
+ $this->cache = $cache;
+ parent::__construct($user);
+ }
+
+ protected function load_migrations()
+ {
+ $migrations = $this->extension_manager
+ ->get_finder()
+ ->core_path('phpbb/db/migration/data/')
+ ->extension_directory('/migrations')
+ ->get_classes();
+
+ $this->migrator->set_migrations($migrations);
+
+ return $this->migrator->get_migrations();
+ }
+
+ protected function finalise_update()
+ {
+ $this->cache->purge();
+ $this->config->increment('assets_version', 1);
+ }
+}
diff --git a/phpBB/phpbb/console/command/db/revert.php b/phpBB/phpbb/console/command/db/revert.php
new file mode 100644
index 0000000000..3fa2e17515
--- /dev/null
+++ b/phpBB/phpbb/console/command/db/revert.php
@@ -0,0 +1,88 @@
+<?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\console\command\db;
+
+use phpbb\db\output_handler\log_wrapper_migrator_output_handler;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class revert extends \phpbb\console\command\db\migration_command
+{
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->language = $language;
+ $this->phpbb_root_path = $phpbb_root_path;
+ parent::__construct($user, $migrator, $extension_manager, $config, $cache);
+ $this->user->add_lang(array('common', 'migrator'));
+ }
+
+ protected function configure()
+ {
+ $this
+ ->setName('db:revert')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_DB_REVERT'))
+ ->addArgument(
+ 'name',
+ InputArgument::REQUIRED,
+ $this->user->lang('CLI_MIGRATION_NAME')
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $name = str_replace('/', '\\', $input->getArgument('name'));
+
+ $this->migrator->set_output_handler(new log_wrapper_migrator_output_handler($this->language, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
+
+ $this->cache->purge();
+
+ if (!in_array($name, $this->load_migrations()))
+ {
+ $output->writeln('<error>' . $this->user->lang('MIGRATION_NOT_VALID', $name) . '</error>');
+ return 1;
+ }
+ else if ($this->migrator->migration_state($name) === false)
+ {
+ $output->writeln('<error>' . $this->user->lang('MIGRATION_NOT_INSTALLED', $name) . '</error>');
+ return 1;
+ }
+
+ try
+ {
+ while ($this->migrator->migration_state($name) !== false)
+ {
+ $this->migrator->revert($name);
+ }
+ }
+ catch (\phpbb\db\migration\exception $e)
+ {
+ $output->writeln('<error>' . $e->getLocalisedMessage($this->user) . '</error>');
+ $this->finalise_update();
+ return 1;
+ }
+
+ $this->finalise_update();
+ }
+}
diff --git a/phpBB/phpbb/console/command/reparser/list_all.php b/phpBB/phpbb/console/command/reparser/list_all.php
new file mode 100644
index 0000000000..e42c3ac782
--- /dev/null
+++ b/phpBB/phpbb/console/command/reparser/list_all.php
@@ -0,0 +1,69 @@
+<?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\console\command\reparser;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class list_all extends \phpbb\console\command\command
+{
+ /**
+ * @var string[] Names of the reparser services
+ */
+ protected $reparser_names;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\user $user
+ * @param \phpbb\di\service_collection $reparsers
+ */
+ public function __construct(\phpbb\user $user, \phpbb\di\service_collection $reparsers)
+ {
+ parent::__construct($user);
+ $this->reparser_names = array();
+ foreach ($reparsers as $name => $reparser)
+ {
+ // Store the names without the "text_reparser." prefix
+ $this->reparser_names[] = preg_replace('(^text_reparser\\.)', '', $name);
+ }
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('reparser:list')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_LIST'))
+ ;
+ }
+
+ /**
+ * Executes the command reparser:reparse
+ *
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return integer
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $output->writeln('<info>' . implode(', ', $this->reparser_names) . '</info>');
+
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/console/command/reparser/reparse.php b/phpBB/phpbb/console/command/reparser/reparse.php
new file mode 100644
index 0000000000..cebeee0919
--- /dev/null
+++ b/phpBB/phpbb/console/command/reparser/reparse.php
@@ -0,0 +1,246 @@
+<?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\console\command\reparser;
+
+use phpbb\exception\runtime_exception;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class reparse extends \phpbb\console\command\command
+{
+ /**
+ * @var InputInterface
+ */
+ protected $input;
+
+ /**
+ * @var SymfonyStyle
+ */
+ protected $io;
+
+ /**
+ * @var OutputInterface
+ */
+ protected $output;
+
+ /**
+ * @var \phpbb\lock\db
+ */
+ protected $reparse_lock;
+
+ /**
+ * @var \phpbb\textreparser\manager
+ */
+ protected $reparser_manager;
+
+ /**
+ * @var \phpbb\di\service_collection
+ */
+ protected $reparsers;
+
+ /**
+ * @var array The reparser's last $current ID as values
+ */
+ protected $resume_data;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\user $user
+ * @param \phpbb\lock\db $reparse_lock
+ * @param \phpbb\textreparser\manager $reparser_manager
+ * @param \phpbb\di\service_collection $reparsers
+ */
+ public function __construct(\phpbb\user $user, \phpbb\lock\db $reparse_lock, \phpbb\textreparser\manager $reparser_manager, \phpbb\di\service_collection $reparsers)
+ {
+ require_once __DIR__ . '/../../../../includes/functions_content.php';
+
+ $this->reparse_lock = $reparse_lock;
+ $this->reparser_manager = $reparser_manager;
+ $this->reparsers = $reparsers;
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('reparser:reparse')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE'))
+ ->addArgument('reparser-name', InputArgument::OPTIONAL, $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_ARG_1'))
+ ->addOption(
+ 'dry-run',
+ null,
+ InputOption::VALUE_NONE,
+ $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_DRY_RUN')
+ )
+ ->addOption(
+ 'resume',
+ null,
+ InputOption::VALUE_NONE,
+ $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RESUME')
+ )
+ ->addOption(
+ 'range-min',
+ null,
+ InputOption::VALUE_REQUIRED,
+ $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MIN'),
+ 1
+ )
+ ->addOption(
+ 'range-max',
+ null,
+ InputOption::VALUE_REQUIRED,
+ $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_MAX')
+ )
+ ->addOption(
+ 'range-size',
+ null,
+ InputOption::VALUE_REQUIRED,
+ $this->user->lang('CLI_DESCRIPTION_REPARSER_REPARSE_OPT_RANGE_SIZE'),
+ 100
+ );
+ ;
+ }
+
+ /**
+ * Executes the command reparser:reparse
+ *
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return integer
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->input = $input;
+ $this->output = $output;
+ $this->io = new SymfonyStyle($input, $output);
+
+ if (!$this->reparse_lock->acquire())
+ {
+ throw new runtime_exception('REPARSE_LOCK_ERROR', array(), null, 1);
+ }
+
+ $name = $input->getArgument('reparser-name');
+ if (isset($name))
+ {
+ // Allow "post_text" to be an alias for "text_reparser.post_text"
+ if (!isset($this->reparsers[$name]))
+ {
+ $name = 'text_reparser.' . $name;
+ }
+ $this->reparse($name);
+ }
+ else
+ {
+ foreach ($this->reparsers as $name => $service)
+ {
+ $this->reparse($name);
+ }
+ }
+
+ $this->io->success($this->user->lang('CLI_REPARSER_REPARSE_SUCCESS'));
+
+ $this->reparse_lock->release();
+
+ return 0;
+ }
+
+ /**
+ * Get an option value, adjusted for given reparser
+ *
+ * Will use the last saved value if --resume is set and the option was not specified
+ * on the command line
+ *
+ * @param string $option_name Option name
+ * @return integer
+ */
+ protected function get_option($option_name)
+ {
+ // Return the option from the resume_data if applicable
+ if ($this->input->getOption('resume') && isset($this->resume_data[$option_name]) && !$this->input->hasParameterOption('--' . $option_name))
+ {
+ return $this->resume_data[$option_name];
+ }
+
+ return $this->input->getOption($option_name);
+ }
+
+ /**
+ * Reparse all text handled by given reparser within given range
+ *
+ * @param string $name Reparser name
+ */
+ protected function reparse($name)
+ {
+ $reparser = $this->reparsers[$name];
+ $this->resume_data = $this->reparser_manager->get_resume_data($name);
+ if ($this->input->getOption('dry-run'))
+ {
+ $reparser->disable_save();
+ }
+ else
+ {
+ $reparser->enable_save();
+ }
+
+ // Start at range-max if specified or at the highest ID otherwise
+ $max = $this->get_option('range-max');
+ $min = $this->get_option('range-min');
+ $size = $this->get_option('range-size');
+
+ // range-max has no default value, it must be computed for each reparser
+ if ($max === null)
+ {
+ $max = $reparser->get_max_id();
+ }
+
+ if ($max < $min)
+ {
+ return;
+ }
+
+ $this->io->section($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $min, $max));
+
+ $progress = $this->create_progress_bar($max, $this->io, $this->output, true);
+ $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING_START', preg_replace('(^text_reparser\\.)', '', $name)));
+ $progress->start();
+
+ // Start from $max and decrement $current by $size until we reach $min
+ $current = $max;
+ while ($current >= $min)
+ {
+ $start = max($min, $current + 1 - $size);
+ $end = max($min, $current);
+
+ $progress->setMessage($this->user->lang('CLI_REPARSER_REPARSE_REPARSING', preg_replace('(^text_reparser\\.)', '', $name), $start, $end));
+ $reparser->reparse_range($start, $end);
+
+ $current = $start - 1;
+ $progress->setProgress($max + 1 - $start);
+
+ $this->reparser_manager->update_resume_data($name, $min, $current, $size, !$this->input->getOption('dry-run'));
+ }
+ $progress->finish();
+
+ $this->io->newLine(2);
+ }
+}
diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php
new file mode 100644
index 0000000000..cfa9891fbc
--- /dev/null
+++ b/phpBB/phpbb/console/command/thumbnail/delete.php
@@ -0,0 +1,153 @@
+<?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\console\command\thumbnail;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class delete extends \phpbb\console\command\command
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * phpBB root path
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @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)
+ {
+ $this->db = $db;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('thumbnail:delete')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_DELETE'))
+ ;
+ }
+
+ /**
+ * Executes the command thumbnail:delete.
+ *
+ * Deletes all existing thumbnails and updates the database accordingly.
+ *
+ * @param InputInterface $input The input stream used to get the argument and verbose option.
+ * @param OutputInterface $output The output stream, used for printing verbose-mode and error information.
+ *
+ * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted.
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $io->section($this->user->lang('CLI_THUMBNAIL_DELETING'));
+
+ $sql = 'SELECT COUNT(*) AS nb_missing_thumbnails
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE thumbnail = 1';
+ $result = $this->db->sql_query($sql);
+ $nb_missing_thumbnails = (int) $this->db->sql_fetchfield('nb_missing_thumbnails');
+ $this->db->sql_freeresult($result);
+
+ if ($nb_missing_thumbnails === 0)
+ {
+ $io->warning($this->user->lang('CLI_THUMBNAIL_NOTHING_TO_DELETE'));
+ return 0;
+ }
+
+ $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE thumbnail = 1';
+ $result = $this->db->sql_query($sql);
+
+ $progress = $this->create_progress_bar($nb_missing_thumbnails, $io, $output);
+
+ $progress->setMessage($this->user->lang('CLI_THUMBNAIL_DELETING'));
+
+ $progress->start();
+
+ $thumbnail_deleted = array();
+ $return = 0;
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $thumbnail_path = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename'];
+
+ if (@unlink($thumbnail_path))
+ {
+ $thumbnail_deleted[] = $row['attach_id'];
+
+ if (sizeof($thumbnail_deleted) === 250)
+ {
+ $this->commit_changes($thumbnail_deleted);
+ $thumbnail_deleted = array();
+ }
+
+ $progress->setMessage($this->user->lang('CLI_THUMBNAIL_DELETED', $row['real_filename'], $row['physical_filename']));
+ }
+ else
+ {
+ $return = 1;
+ $progress->setMessage('<error>' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . '</error>');
+ }
+
+ $progress->advance();
+ }
+ $this->db->sql_freeresult($result);
+
+ if (!empty($thumbnail_deleted))
+ {
+ $this->commit_changes($thumbnail_deleted);
+ }
+
+ $progress->finish();
+
+ $io->newLine(2);
+ $io->success($this->user->lang('CLI_THUMBNAIL_DELETING_DONE'));
+
+ return $return;
+ }
+
+ /**
+ * Commits the changes to the database
+ *
+ * @param array $thumbnail_deleted
+ */
+ protected function commit_changes(array $thumbnail_deleted)
+ {
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET thumbnail = 0
+ WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_deleted);
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php
new file mode 100644
index 0000000000..64f7555336
--- /dev/null
+++ b/phpBB/phpbb/console/command/thumbnail/generate.php
@@ -0,0 +1,179 @@
+<?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\console\command\thumbnail;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class generate extends \phpbb\console\command\command
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\cache\service
+ */
+ protected $cache;
+
+ /**
+ * phpBB root path
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * PHP extension.
+ *
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @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)
+ {
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('thumbnail:generate')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_GENERATE'))
+ ;
+ }
+
+ /**
+ * Executes the command thumbnail:generate.
+ *
+ * Generate a thumbnail for all attachments which need one and don't have it yet.
+ *
+ * @param InputInterface $input The input stream used to get the argument and verboe option.
+ * @param OutputInterface $output The output stream, used for printing verbose-mode and error information.
+ *
+ * @return int 0.
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $io->section($this->user->lang('CLI_THUMBNAIL_GENERATING'));
+
+ $sql = 'SELECT COUNT(*) AS nb_missing_thumbnails
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE thumbnail = 0';
+ $result = $this->db->sql_query($sql);
+ $nb_missing_thumbnails = (int) $this->db->sql_fetchfield('nb_missing_thumbnails');
+ $this->db->sql_freeresult($result);
+
+ if ($nb_missing_thumbnails === 0)
+ {
+ $io->warning($this->user->lang('CLI_THUMBNAIL_NOTHING_TO_GENERATE'));
+ return 0;
+ }
+
+ $extensions = $this->cache->obtain_attach_extensions(true);
+
+ $sql = 'SELECT attach_id, physical_filename, extension, real_filename, mimetype
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE thumbnail = 0';
+ $result = $this->db->sql_query($sql);
+
+ if (!function_exists('create_thumbnail'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext);
+ }
+
+ $progress = $this->create_progress_bar($nb_missing_thumbnails, $io, $output);
+
+ $progress->setMessage($this->user->lang('CLI_THUMBNAIL_GENERATING'));
+
+ $progress->start();
+
+ $thumbnail_created = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ 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'];
+
+ if (create_thumbnail($source, $destination, $row['mimetype']))
+ {
+ $thumbnail_created[] = (int) $row['attach_id'];
+
+ if (count($thumbnail_created) === 250)
+ {
+ $this->commit_changes($thumbnail_created);
+ $thumbnail_created = array();
+ }
+
+ $progress->setMessage($this->user->lang('CLI_THUMBNAIL_GENERATED', $row['real_filename'], $row['physical_filename']));
+ }
+ else
+ {
+ $progress->setMessage('<info>' . $this->user->lang('CLI_THUMBNAIL_SKIPPED', $row['real_filename'], $row['physical_filename']) . '</info>');
+ }
+ }
+
+ $progress->advance();
+ }
+ $this->db->sql_freeresult($result);
+
+ if (!empty($thumbnail_created))
+ {
+ $this->commit_changes($thumbnail_created);
+ }
+
+ $progress->finish();
+
+ $io->newLine(2);
+ $io->success($this->user->lang('CLI_THUMBNAIL_GENERATING_DONE'));
+
+ return 0;
+ }
+
+ /**
+ * Commits the changes to the database
+ *
+ * @param array $thumbnail_created
+ */
+ protected function commit_changes(array $thumbnail_created)
+ {
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET thumbnail = 1
+ WHERE ' . $this->db->sql_in_set('attach_id', $thumbnail_created);
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/phpbb/console/command/thumbnail/recreate.php b/phpBB/phpbb/console/command/thumbnail/recreate.php
new file mode 100644
index 0000000000..382da290bf
--- /dev/null
+++ b/phpBB/phpbb/console/command/thumbnail/recreate.php
@@ -0,0 +1,72 @@
+<?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\console\command\thumbnail;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class recreate extends \phpbb\console\command\command
+{
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('thumbnail:recreate')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_THUMBNAIL_RECREATE'))
+ ;
+ }
+
+ /**
+ * Executes the command thumbnail:recreate.
+ *
+ * This command is a "macro" to execute thumbnail:delete and then thumbnail:generate.
+ *
+ * @param InputInterface $input The input stream used to get the argument and verboe option.
+ * @param OutputInterface $output The output stream, used for printing verbose-mode and error information.
+ *
+ * @return int 0 if all is ok, 1 if a thumbnail couldn't be deleted.
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $parameters = array(
+ 'command' => 'thumbnail:delete'
+ );
+
+ if ($input->getOption('verbose'))
+ {
+ $parameters['-' . str_repeat('v', $output->getVerbosity() - 1)] = true;
+ }
+
+ $this->getApplication()->setAutoExit(false);
+
+ $input_delete = new ArrayInput($parameters);
+ $return = $this->getApplication()->run($input_delete, $output);
+
+ if ($return === 0)
+ {
+ $parameters['command'] = 'thumbnail:generate';
+
+ $input_create = new ArrayInput($parameters);
+ $return = $this->getApplication()->run($input_create, $output);
+ }
+
+ $this->getApplication()->setAutoExit(true);
+
+ return $return;
+ }
+}
diff --git a/phpBB/phpbb/console/command/user/activate.php b/phpBB/phpbb/console/command/user/activate.php
new file mode 100644
index 0000000000..9c85718b4c
--- /dev/null
+++ b/phpBB/phpbb/console/command/user/activate.php
@@ -0,0 +1,218 @@
+<?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\console\command\user;
+
+use phpbb\config\config;
+use phpbb\console\command\command;
+use phpbb\db\driver\driver_interface;
+use phpbb\language\language;
+use phpbb\log\log_interface;
+use phpbb\notification\manager;
+use phpbb\user;
+use phpbb\user_loader;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class activate extends command
+{
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var config */
+ protected $config;
+
+ /** @var language */
+ protected $language;
+
+ /** @var log_interface */
+ protected $log;
+
+ /** @var manager */
+ protected $notifications;
+
+ /** @var user_loader */
+ protected $user_loader;
+
+ /**
+ * phpBB root path
+ *
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * PHP extension.
+ *
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Construct method
+ *
+ * @param user $user
+ * @param driver_interface $db
+ * @param config $config
+ * @param language $language
+ * @param log_interface $log
+ * @param manager $notifications
+ * @param user_loader $user_loader
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(user $user, driver_interface $db, config $config, language $language, log_interface $log, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->config = $config;
+ $this->language = $language;
+ $this->log = $log;
+ $this->notifications = $notifications;
+ $this->user_loader = $user_loader;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $this->language->add_lang('acp/users');
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('user:activate')
+ ->setDescription($this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE'))
+ ->setHelp($this->language->lang('CLI_HELP_USER_ACTIVATE'))
+ ->addArgument(
+ 'username',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_USERNAME')
+ )
+ ->addOption(
+ 'deactivate',
+ 'd',
+ InputOption::VALUE_NONE,
+ $this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_DEACTIVATE')
+ )
+ ->addOption(
+ 'send-email',
+ null,
+ InputOption::VALUE_NONE,
+ $this->language->lang('CLI_DESCRIPTION_USER_ADD_OPTION_NOTIFY')
+ )
+ ;
+ }
+
+ /**
+ * Executes the command user:activate
+ *
+ * Activate (or deactivate) a user account
+ *
+ * @param InputInterface $input The input stream used to get the options
+ * @param OutputInterface $output The output stream, used to print messages
+ *
+ * @return int 0 if all is well, 1 if any errors occurred
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $name = $input->getArgument('username');
+ $mode = ($input->getOption('deactivate')) ? 'deactivate' : 'activate';
+
+ $user_id = $this->user_loader->load_user_by_username($name);
+ $user_row = $this->user_loader->get_user($user_id);
+
+ if ($user_row['user_id'] == ANONYMOUS)
+ {
+ $io->error($this->language->lang('NO_USER'));
+ return 1;
+ }
+
+ // Check if the user is already active (or inactive)
+ if ($mode == 'activate' && $user_row['user_type'] != USER_INACTIVE)
+ {
+ $io->error($this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE'));
+ return 1;
+ }
+ else if ($mode == 'deactivate' && $user_row['user_type'] == USER_INACTIVE)
+ {
+ $io->error($this->language->lang('CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE'));
+ return 1;
+ }
+
+ // Activate the user account
+ if (!function_exists('user_active_flip'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
+ user_active_flip($mode, $user_row['user_id']);
+
+ // Notify the user upon activation
+ if ($mode == 'activate' && $this->config['require_activation'] == USER_ACTIVATION_ADMIN)
+ {
+ $this->send_notification($user_row, $input);
+ }
+
+ // Log and display the result
+ $msg = ($mode == 'activate') ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
+ $log = ($mode == 'activate') ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
+
+ $this->log->add('admin', ANONYMOUS, '', $log, false, array($user_row['username']));
+ $this->log->add('user', ANONYMOUS, '', $log . '_USER', false, array(
+ 'reportee_id' => $user_row['user_id']
+ ));
+
+ $io->success($this->language->lang($msg));
+
+ return 0;
+ }
+
+ /**
+ * Send account activation notification to user
+ *
+ * @param array $user_row The user data array
+ * @param InputInterface $input The input stream used to get the options
+ * @return null
+ */
+ protected function send_notification($user_row, InputInterface $input)
+ {
+ $this->notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']);
+
+ if ($input->getOption('send-email'))
+ {
+ if (!class_exists('messenger'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
+ }
+
+ $messenger = new \messenger(false);
+ $messenger->template('admin_welcome_activated', $user_row['user_lang']);
+ $messenger->set_addresses($user_row);
+ $messenger->anti_abuse_headers($this->config, $this->user);
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']))
+ );
+
+ $messenger->send(NOTIFY_EMAIL);
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php
new file mode 100644
index 0000000000..c60a059251
--- /dev/null
+++ b/phpBB/phpbb/console/command/user/add.php
@@ -0,0 +1,334 @@
+<?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\console\command\user;
+
+use phpbb\config\config;
+use phpbb\console\command\command;
+use phpbb\db\driver\driver_interface;
+use phpbb\exception\runtime_exception;
+use phpbb\language\language;
+use phpbb\passwords\manager;
+use phpbb\user;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\Question;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class add extends command
+{
+ /** @var array Array of interactively acquired options */
+ protected $data;
+
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var config */
+ protected $config;
+
+ /** @var language */
+ protected $language;
+
+ /** @var manager */
+ protected $password_manager;
+
+ /**
+ * phpBB root path
+ *
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * PHP extension.
+ *
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Construct method
+ *
+ * @param user $user
+ * @param driver_interface $db
+ * @param config $config
+ * @param language $language
+ * @param manager $password_manager
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(user $user, driver_interface $db, config $config, language $language, manager $password_manager, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->config = $config;
+ $this->language = $language;
+ $this->password_manager = $password_manager;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $this->language->add_lang('ucp');
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('user:add')
+ ->setDescription($this->language->lang('CLI_DESCRIPTION_USER_ADD'))
+ ->setHelp($this->language->lang('CLI_HELP_USER_ADD'))
+ ->addOption(
+ 'username',
+ 'U',
+ InputOption::VALUE_REQUIRED,
+ $this->language->lang('CLI_DESCRIPTION_USER_ADD_OPTION_USERNAME')
+ )
+ ->addOption(
+ 'password',
+ 'P',
+ InputOption::VALUE_REQUIRED,
+ $this->language->lang('CLI_DESCRIPTION_USER_ADD_OPTION_PASSWORD')
+ )
+ ->addOption(
+ 'email',
+ 'E',
+ InputOption::VALUE_REQUIRED,
+ $this->language->lang('CLI_DESCRIPTION_USER_ADD_OPTION_EMAIL')
+ )
+ ->addOption(
+ 'send-email',
+ null,
+ InputOption::VALUE_NONE,
+ $this->language->lang('CLI_DESCRIPTION_USER_ADD_OPTION_NOTIFY')
+ )
+ ;
+ }
+
+ /**
+ * Executes the command user:add
+ *
+ * Adds a new user to the database. If options are not provided, it will ask for the username, password and email.
+ * User is added to the registered user group. Language and timezone default to $config settings.
+ *
+ * @param InputInterface $input The input stream used to get the options
+ * @param OutputInterface $output The output stream, used to print messages
+ *
+ * @return int 0 if all is well, 1 if any errors occurred
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ try
+ {
+ $this->validate_user_data();
+ $group_id = $this->get_group_id();
+ }
+ catch (runtime_exception $e)
+ {
+ $io->error($e->getMessage());
+ return 1;
+ }
+
+ $user_row = array(
+ 'username' => $this->data['username'],
+ 'user_password' => $this->password_manager->hash($this->data['new_password']),
+ 'user_email' => $this->data['email'],
+ 'group_id' => $group_id,
+ 'user_timezone' => $this->config['board_timezone'],
+ 'user_lang' => $this->config['default_lang'],
+ 'user_type' => USER_NORMAL,
+ 'user_regdate' => time(),
+ );
+
+ $user_id = (int) user_add($user_row);
+
+ if (!$user_id)
+ {
+ $io->error($this->language->lang('AUTH_NO_PROFILE_CREATED'));
+ return 1;
+ }
+
+ if ($input->getOption('send-email') && $this->config['email_enable'])
+ {
+ $this->send_activation_email($user_id);
+ }
+
+ $io->success($this->language->lang('CLI_USER_ADD_SUCCESS', $this->data['username']));
+
+ return 0;
+ }
+
+ /**
+ * Interacts with the user.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ */
+ protected function interact(InputInterface $input, OutputInterface $output)
+ {
+ $helper = $this->getHelper('question');
+
+ $this->data = array(
+ 'username' => $input->getOption('username'),
+ 'new_password' => $input->getOption('password'),
+ 'email' => $input->getOption('email'),
+ );
+
+ if (!$this->data['username'])
+ {
+ $question = new Question($this->ask_user('USERNAME'));
+ $this->data['username'] = $helper->ask($input, $output, $question);
+ }
+
+ if (!$this->data['new_password'])
+ {
+ $question = new Question($this->ask_user('PASSWORD'));
+ $question->setValidator(function ($value) use ($helper, $input, $output) {
+ $question = new Question($this->ask_user('CONFIRM_PASSWORD'));
+ $question->setHidden(true);
+ if ($helper->ask($input, $output, $question) != $value)
+ {
+ throw new runtime_exception($this->language->lang('NEW_PASSWORD_ERROR'));
+ }
+ return $value;
+ });
+ $question->setHidden(true);
+ $question->setMaxAttempts(5);
+
+ $this->data['new_password'] = $helper->ask($input, $output, $question);
+ }
+
+ if (!$this->data['email'])
+ {
+ $question = new Question($this->ask_user('EMAIL_ADDRESS'));
+ $this->data['email'] = $helper->ask($input, $output, $question);
+ }
+ }
+
+ /**
+ * Validate the submitted user data
+ *
+ * @throws runtime_exception if any data fails validation
+ * @return null
+ */
+ protected function validate_user_data()
+ {
+ if (!function_exists('validate_data'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
+ $error = validate_data($this->data, array(
+ 'username' => array(
+ array('string', false, $this->config['min_name_chars'], $this->config['max_name_chars']),
+ array('username', '')),
+ 'new_password' => array(
+ array('string', false, $this->config['min_pass_chars'], $this->config['max_pass_chars']),
+ array('password')),
+ 'email' => array(
+ array('string', false, 6, 60),
+ array('user_email')),
+ ));
+
+ if ($error)
+ {
+ throw new runtime_exception(implode("\n", array_map(array($this->language, 'lang'), $error)));
+ }
+ }
+
+ /**
+ * Get the group id
+ *
+ * Go and find in the database the group_id corresponding to 'REGISTERED'
+ *
+ * @throws runtime_exception if the group id does not exist in database.
+ * @return null
+ */
+ protected function get_group_id()
+ {
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $this->db->sql_escape('REGISTERED') . "'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row || !$row['group_id'])
+ {
+ throw new runtime_exception($this->language->lang('NO_GROUP'));
+ }
+
+ return $row['group_id'];
+ }
+
+ /**
+ * Send account activation email
+ *
+ * @param int $user_id The new user's id
+ * @return null
+ */
+ protected function send_activation_email($user_id)
+ {
+ switch ($this->config['require_activation'])
+ {
+ case USER_ACTIVATION_SELF:
+ $email_template = 'user_welcome_inactive';
+ $user_actkey = gen_rand_string(mt_rand(6, 10));
+ break;
+ case USER_ACTIVATION_ADMIN:
+ $email_template = 'admin_welcome_inactive';
+ $user_actkey = gen_rand_string(mt_rand(6, 10));
+ break;
+ default:
+ $email_template = 'user_welcome';
+ $user_actkey = '';
+ break;
+ }
+
+ if (!class_exists('messenger'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
+ }
+
+ $messenger = new \messenger(false);
+ $messenger->template($email_template, $this->user->lang_name);
+ $messenger->to($this->data['email'], $this->data['username']);
+ $messenger->anti_abuse_headers($this->config, $this->user);
+ $messenger->assign_vars(array(
+ 'WELCOME_MSG' => htmlspecialchars_decode($this->language->lang('WELCOME_SUBJECT', $this->config['sitename'])),
+ 'USERNAME' => htmlspecialchars_decode($this->data['username']),
+ 'PASSWORD' => htmlspecialchars_decode($this->data['new_password']),
+ 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey")
+ );
+
+ $messenger->send(NOTIFY_EMAIL);
+ }
+
+ /**
+ * Helper to translate questions to the user
+ *
+ * @param string $key The language key
+ * @return string The language key translated with a colon and space appended
+ */
+ protected function ask_user($key)
+ {
+ return $this->language->lang($key) . $this->language->lang('COLON') . ' ';
+ }
+}
diff --git a/phpBB/phpbb/console/command/user/delete.php b/phpBB/phpbb/console/command/user/delete.php
new file mode 100644
index 0000000000..8593541c1a
--- /dev/null
+++ b/phpBB/phpbb/console/command/user/delete.php
@@ -0,0 +1,170 @@
+<?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\console\command\user;
+
+use phpbb\console\command\command;
+use phpbb\db\driver\driver_interface;
+use phpbb\language\language;
+use phpbb\log\log_interface;
+use phpbb\user;
+use phpbb\user_loader;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class delete extends command
+{
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var language */
+ protected $language;
+
+ /** @var log_interface */
+ protected $log;
+
+ /** @var user_loader */
+ protected $user_loader;
+
+ /**
+ * phpBB root path
+ *
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * PHP extension.
+ *
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Construct method
+ *
+ * @param user $user
+ * @param driver_interface $db
+ * @param language $language
+ * @param log_interface $log
+ * @param user_loader $user_loader
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(user $user, driver_interface $db, language $language, log_interface $log, user_loader $user_loader, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->language = $language;
+ $this->log = $log;
+ $this->user_loader = $user_loader;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $this->language->add_lang('acp/users');
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('user:delete')
+ ->setDescription($this->language->lang('CLI_DESCRIPTION_USER_DELETE'))
+ ->addArgument(
+ 'username',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_DESCRIPTION_USER_DELETE_USERNAME')
+ )
+ ->addOption(
+ 'delete-posts',
+ null,
+ InputOption::VALUE_NONE,
+ $this->language->lang('CLI_DESCRIPTION_USER_DELETE_OPTION_POSTS')
+ )
+ ;
+ }
+
+ /**
+ * Executes the command user:delete
+ *
+ * Deletes a user from the database. An option to delete the user's posts
+ * is available, by default posts will be retained.
+ *
+ * @param InputInterface $input The input stream used to get the options
+ * @param OutputInterface $output The output stream, used to print messages
+ *
+ * @return int 0 if all is well, 1 if any errors occurred
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $name = $input->getArgument('username');
+ $mode = ($input->getOption('delete-posts')) ? 'remove' : 'retain';
+
+ if ($name)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $user_id = $this->user_loader->load_user_by_username($name);
+ $user_row = $this->user_loader->get_user($user_id);
+
+ if ($user_row['user_id'] == ANONYMOUS)
+ {
+ $io->error($this->language->lang('NO_USER'));
+ return 1;
+ }
+
+ if (!function_exists('user_delete'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
+ user_delete($mode, $user_row['user_id'], $user_row['username']);
+
+ $this->log->add('admin', ANONYMOUS, '', 'LOG_USER_DELETED', false, array($user_row['username']));
+
+ $io->success($this->language->lang('USER_DELETED'));
+ }
+
+ return 0;
+ }
+
+ /**
+ * Interacts with the user.
+ * Confirm they really want to delete the account...last chance!
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ */
+ protected function interact(InputInterface $input, OutputInterface $output)
+ {
+ $helper = $this->getHelper('question');
+
+ $question = new ConfirmationQuestion(
+ $this->language->lang('CLI_USER_DELETE_CONFIRM', $input->getArgument('username')),
+ false
+ );
+
+ if (!$helper->ask($input, $output, $question))
+ {
+ $input->setArgument('username', false);
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/user/reclean.php b/phpBB/phpbb/console/command/user/reclean.php
new file mode 100644
index 0000000000..1a89f13382
--- /dev/null
+++ b/phpBB/phpbb/console/command/user/reclean.php
@@ -0,0 +1,158 @@
+<?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\console\command\user;
+
+use phpbb\console\command\command;
+use phpbb\db\driver\driver_interface;
+use phpbb\language\language;
+use phpbb\user;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class reclean extends command
+{
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var language */
+ protected $language;
+
+ /** @var int A count of the number of re-cleaned user names */
+ protected $processed;
+
+ /** @var ProgressBar */
+ protected $progress;
+
+ /**
+ * Construct method
+ *
+ * @param user $user
+ * @param driver_interface $db
+ * @param language $language
+ */
+ public function __construct(user $user, driver_interface $db, language $language)
+ {
+ $this->db = $db;
+ $this->language = $language;
+
+ parent::__construct($user);
+ }
+
+ /**
+ * Sets the command name and description
+ *
+ * @return null
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('user:reclean')
+ ->setDescription($this->language->lang('CLI_DESCRIPTION_USER_RECLEAN'))
+ ->setHelp($this->language->lang('CLI_HELP_USER_RECLEAN'))
+ ;
+ }
+
+ /**
+ * Executes the command user:reclean
+ *
+ * Cleans user names that are unclean.
+ *
+ * @param InputInterface $input The input stream used to get the options
+ * @param OutputInterface $output The output stream, used to print messages
+ *
+ * @return int 0 if all is well, 1 if any errors occurred
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $io->section($this->language->lang('CLI_USER_RECLEAN_START'));
+
+ $this->processed = 0;
+
+ $this->progress = $this->create_progress_bar($this->get_count(), $io, $output);
+ $this->progress->setMessage($this->language->lang('CLI_USER_RECLEAN_START'));
+ $this->progress->start();
+
+ $stage = 0;
+ while ($stage !== true)
+ {
+ $stage = $this->reclean_usernames($stage);
+ }
+
+ $this->progress->finish();
+
+ $io->newLine(2);
+ $io->success($this->language->lang('CLI_USER_RECLEAN_DONE', $this->processed));
+
+ return 0;
+ }
+
+ /**
+ * Re-clean user names
+ * Only user names that are unclean will be re-cleaned
+ *
+ * @param int $start An offset index
+ * @return bool|int Return the next offset index or true if all records have been processed.
+ */
+ protected function reclean_usernames($start = 0)
+ {
+ $limit = 500;
+ $i = 0;
+
+ $this->db->sql_transaction('begin');
+
+ $sql = 'SELECT user_id, username, username_clean FROM ' . USERS_TABLE;
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $i++;
+ $username_clean = $this->db->sql_escape(utf8_clean_string($row['username']));
+
+ if ($username_clean != $row['username_clean'])
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET username_clean = '$username_clean'
+ WHERE user_id = {$row['user_id']}";
+ $this->db->sql_query($sql);
+
+ $this->processed++;
+ }
+
+ $this->progress->advance();
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->db->sql_transaction('commit');
+
+ return ($i < $limit) ? true : $start + $i;
+ }
+
+ /**
+ * Get the count of users in the database
+ *
+ * @return int
+ */
+ protected function get_count()
+ {
+ $sql = 'SELECT COUNT(user_id) AS count FROM ' . USERS_TABLE;
+ $result = $this->db->sql_query($sql);
+ $count = (int) $this->db->sql_fetchfield('count');
+ $this->db->sql_freeresult($result);
+
+ return $count;
+ }
+}
diff --git a/phpBB/phpbb/console/exception_subscriber.php b/phpBB/phpbb/console/exception_subscriber.php
new file mode 100644
index 0000000000..b920d4abae
--- /dev/null
+++ b/phpBB/phpbb/console/exception_subscriber.php
@@ -0,0 +1,74 @@
+<?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\console;
+
+use phpbb\exception\exception_interface;
+use Symfony\Component\Console\ConsoleEvents;
+use Symfony\Component\Console\Event\ConsoleExceptionEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class exception_subscriber implements EventSubscriberInterface
+{
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * Construct method
+ *
+ * @param \phpbb\language\language $language Language object
+ * @param bool $debug Debug mode
+ */
+ public function __construct(\phpbb\language\language $language, $debug = false)
+ {
+ $this->language = $language;
+ $this->debug = $debug;
+ }
+
+ /**
+ * This listener is run when the ConsoleEvents::EXCEPTION event is triggered.
+ * It translate the exception message. If din debug mode the original exception is embedded.
+ *
+ * @param ConsoleExceptionEvent $event
+ */
+ public function on_exception(ConsoleExceptionEvent $event)
+ {
+ $original_exception = $event->getException();
+
+ if ($original_exception instanceof exception_interface)
+ {
+ $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());
+ }
+
+ $event->setException($exception);
+ }
+ }
+
+ static public function getSubscribedEvents()
+ {
+ return array(
+ ConsoleEvents::EXCEPTION => 'on_exception',
+ );
+ }
+}
diff --git a/phpBB/phpbb/controller/exception.php b/phpBB/phpbb/controller/exception.php
index 437558b06a..e227c7c37b 100644
--- a/phpBB/phpbb/controller/exception.php
+++ b/phpBB/phpbb/controller/exception.php
@@ -16,6 +16,6 @@ namespace phpbb\controller;
/**
* Controller exception class
*/
-class exception extends \RuntimeException
+class exception extends \phpbb\exception\runtime_exception
{
}
diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php
index ce6bfba981..664b4f4e0f 100644
--- a/phpBB/phpbb/controller/helper.php
+++ b/phpBB/phpbb/controller/helper.php
@@ -15,9 +15,7 @@ namespace phpbb\controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
-use Symfony\Component\Routing\RequestContext;
/**
* Controller helper class, contains methods that do things for controllers
@@ -49,49 +47,28 @@ class helper
protected $request;
/**
- * @var \phpbb\filesystem The filesystem object
- */
- protected $filesystem;
-
- /**
- * phpBB root path
- * @var string
- */
- protected $phpbb_root_path;
-
- /**
- * PHP file extension
- * @var string
- */
- protected $php_ext;
+ * @var \phpbb\routing\helper
+ */
+ protected $routing_helper;
/**
- * Constructor
- *
- * @param \phpbb\template\template $template Template object
- * @param \phpbb\user $user User object
- * @param \phpbb\config\config $config Config object
+ * Constructor
*
- * @param \phpbb\controller\provider $provider Path provider
- * @param \phpbb\extension\manager $manager Extension manager object
- * @param \phpbb\symfony_request $symfony_request Symfony Request object
- * @param \phpbb\request\request_interface $request phpBB request object
- * @param \phpbb\filesystem $filesystem The filesystem object
- * @param string $phpbb_root_path phpBB root path
- * @param string $php_ext PHP file extension
- */
- public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext)
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\user $user User object
+ * @param \phpbb\config\config $config Config object
+ * @param \phpbb\symfony_request $symfony_request Symfony Request object
+ * @param \phpbb\request\request_interface $request phpBB request object
+ * @param \phpbb\routing\helper $routing_helper Helper to generate the routes
+ */
+ public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\routing\helper $routing_helper)
{
$this->template = $template;
$this->user = $user;
$this->config = $config;
$this->symfony_request = $symfony_request;
$this->request = $request;
- $this->filesystem = $filesystem;
- $this->phpbb_root_path = $phpbb_root_path;
- $this->php_ext = $php_ext;
- $provider->find_routing_files($manager->get_finder());
- $this->route_collection = $provider->find($phpbb_root_path)->get_routes();
+ $this->routing_helper = $routing_helper;
}
/**
@@ -134,70 +111,7 @@ class helper
*/
public function route($route, array $params = array(), $is_amp = true, $session_id = false, $reference_type = UrlGeneratorInterface::ABSOLUTE_PATH)
{
- $anchor = '';
- if (isset($params['#']))
- {
- $anchor = '#' . $params['#'];
- unset($params['#']);
- }
-
- $context = new RequestContext();
- $context->fromRequest($this->symfony_request);
-
- if ($this->config['force_server_vars'])
- {
- $context->setHost($this->config['server_name']);
- $context->setScheme(substr($this->config['server_protocol'], 0, -3));
- $context->setHttpPort($this->config['server_port']);
- $context->setHttpsPort($this->config['server_port']);
- $context->setBaseUrl(rtrim($this->config['script_path'], '/'));
- }
-
- $script_name = $this->symfony_request->getScriptName();
- $page_name = substr($script_name, -1, 1) == '/' ? '' : utf8_basename($script_name);
-
- $base_url = $context->getBaseUrl();
-
- // Append page name if base URL does not contain it
- if (!empty($page_name) && strpos($base_url, '/' . $page_name) === false)
- {
- $base_url .= '/' . $page_name;
- }
-
- // If enable_mod_rewrite is false we need to replace the current front-end by app.php, otherwise we need to remove it.
- $base_url = str_replace('/' . $page_name, empty($this->config['enable_mod_rewrite']) ? '/app.' . $this->php_ext : '', $base_url);
-
- // We need to update the base url to move to the directory of the app.php file if the current script is not app.php
- if ($page_name !== 'app.php' && !$this->config['force_server_vars'])
- {
- if (empty($this->config['enable_mod_rewrite']))
- {
- $base_url = str_replace('/app.' . $this->php_ext, '/' . $this->phpbb_root_path . 'app.' . $this->php_ext, $base_url);
- }
- else
- {
- $base_url .= preg_replace(get_preg_expression('path_remove_dot_trailing_slash'), '$2', $this->phpbb_root_path);
- }
- }
-
- $base_url = $this->request->escape($this->filesystem->clean_path($base_url), true);
-
- $context->setBaseUrl($base_url);
-
- $url_generator = new UrlGenerator($this->route_collection, $context);
- $route_url = $url_generator->generate($route, $params, $reference_type);
-
- if ($is_amp)
- {
- $route_url = str_replace(array('&amp;', '&'), array('&', '&amp;'), $route_url);
- }
-
- if ($reference_type === UrlGeneratorInterface::RELATIVE_PATH && empty($this->config['enable_mod_rewrite']))
- {
- $route_url = 'app.' . $this->php_ext . '/' . $route_url;
- }
-
- return append_sid($route_url . $anchor, false, $is_amp, $session_id, true);
+ return $this->routing_helper->route($route, $params, $is_amp, $session_id, $reference_type);
}
/**
@@ -256,6 +170,20 @@ class helper
}
/**
+ * Assigns automatic refresh time meta tag in template
+ *
+ * @param int $time time in seconds, when redirection should occur
+ * @param string $url the URL where the user should be redirected
+ * @return null
+ */
+ public function assign_meta_refresh_var($time, $url)
+ {
+ $this->template->assign_vars(array(
+ 'META' => '<meta http-equiv="refresh" content="' . $time . '; url=' . $url . '" />',
+ ));
+ }
+
+ /**
* Return the current url
*
* @return string
diff --git a/phpBB/phpbb/controller/provider.php b/phpBB/phpbb/controller/provider.php
deleted file mode 100644
index 7e26848290..0000000000
--- a/phpBB/phpbb/controller/provider.php
+++ /dev/null
@@ -1,92 +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\controller;
-
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Loader\YamlFileLoader;
-use Symfony\Component\Config\FileLocator;
-
-/**
-* Controller interface
-*/
-class provider
-{
- /**
- * YAML file(s) containing route information
- * @var array
- */
- protected $routing_files;
-
- /**
- * Collection of the routes in phpBB and all found extensions
- * @var RouteCollection
- */
- protected $routes;
-
- /**
- * Construct method
- *
- * @param array $routing_files Array of strings containing paths
- * to YAML files holding route information
- */
- public function __construct($routing_files = array())
- {
- $this->routing_files = $routing_files;
- }
-
- /**
- * Find the list of routing files
- *
- * @param \phpbb\finder $finder
- * @return null
- */
- public function find_routing_files(\phpbb\finder $finder)
- {
- // We hardcode the path to the core config directory
- // because the finder cannot find it
- $this->routing_files = array_merge($this->routing_files, array('config/routing.yml'), array_keys($finder
- ->directory('/config')
- ->suffix('routing.yml')
- ->find()
- ));
- }
-
- /**
- * Find a list of controllers
- *
- * @param string $base_path Base path to prepend to file paths
- * @return provider
- */
- public function find($base_path = '')
- {
- $this->routes = new RouteCollection;
- foreach ($this->routing_files as $file_path)
- {
- $loader = new YamlFileLoader(new FileLocator(phpbb_realpath($base_path)));
- $this->routes->addCollection($loader->load($file_path));
- }
-
- return $this;
- }
-
- /**
- * Get the list of routes
- *
- * @return RouteCollection Get the route collection
- */
- public function get_routes()
- {
- return $this->routes;
- }
-}
diff --git a/phpBB/phpbb/controller/resolver.php b/phpBB/phpbb/controller/resolver.php
index 948a6a218c..f8dffc12de 100644
--- a/phpBB/phpbb/controller/resolver.php
+++ b/phpBB/phpbb/controller/resolver.php
@@ -23,12 +23,6 @@ use Symfony\Component\HttpFoundation\Request;
class resolver implements ControllerResolverInterface
{
/**
- * User object
- * @var \phpbb\user
- */
- protected $user;
-
- /**
* ContainerInterface object
* @var ContainerInterface
*/
@@ -55,14 +49,12 @@ class resolver implements ControllerResolverInterface
/**
* Construct method
*
- * @param \phpbb\user $user User Object
* @param ContainerInterface $container ContainerInterface object
* @param string $phpbb_root_path Relative path to phpBB root
* @param \phpbb\template\template $template
*/
- public function __construct(\phpbb\user $user, ContainerInterface $container, $phpbb_root_path, \phpbb\template\template $template = null)
+ public function __construct(ContainerInterface $container, $phpbb_root_path, \phpbb\template\template $template = null)
{
- $this->user = $user;
$this->container = $container;
$this->template = $template;
$this->type_cast_helper = new \phpbb\request\type_cast_helper();
@@ -82,20 +74,20 @@ class resolver implements ControllerResolverInterface
if (!$controller)
{
- throw new \phpbb\controller\exception($this->user->lang['CONTROLLER_NOT_SPECIFIED']);
+ throw new \phpbb\controller\exception('CONTROLLER_NOT_SPECIFIED');
}
// Require a method name along with the service name
if (stripos($controller, ':') === false)
{
- throw new \phpbb\controller\exception($this->user->lang['CONTROLLER_METHOD_NOT_SPECIFIED']);
+ throw new \phpbb\controller\exception('CONTROLLER_METHOD_NOT_SPECIFIED');
}
list($service, $method) = explode(':', $controller);
if (!$this->container->has($service))
{
- throw new \phpbb\controller\exception($this->user->lang('CONTROLLER_SERVICE_UNDEFINED', $service));
+ throw new \phpbb\controller\exception('CONTROLLER_SERVICE_UNDEFINED', array($service));
}
$controller_object = $this->container->get($service);
@@ -134,9 +126,21 @@ class resolver implements ControllerResolverInterface
*/
public function getArguments(Request $request, $controller)
{
- // At this point, $controller contains the object and method name
- list($object, $method) = $controller;
- $mirror = new \ReflectionMethod($object, $method);
+ // At this point, $controller should be a callable
+ if (is_array($controller))
+ {
+ list($object, $method) = $controller;
+ $mirror = new \ReflectionMethod($object, $method);
+ }
+ else if (is_object($controller) && !$controller instanceof \Closure)
+ {
+ $mirror = new \ReflectionObject($controller);
+ $mirror = $mirror->getMethod('__invoke');
+ }
+ else
+ {
+ $mirror = new \ReflectionFunction($controller);
+ }
$arguments = array();
$parameters = $mirror->getParameters();
@@ -166,7 +170,7 @@ class resolver implements ControllerResolverInterface
}
else
{
- throw new \phpbb\controller\exception($this->user->lang('CONTROLLER_ARGUMENT_VALUE_MISSING', $param->getPosition() + 1, get_class($object) . ':' . $method, $param->name));
+ throw new \phpbb\controller\exception('CONTROLLER_ARGUMENT_VALUE_MISSING', array($param->getPosition() + 1, get_class($object) . ':' . $method, $param->name));
}
}
diff --git a/phpBB/phpbb/cron/task/core/prune_forum.php b/phpBB/phpbb/cron/task/core/prune_forum.php
index ba68565197..abf91aee19 100644
--- a/phpBB/phpbb/cron/task/core/prune_forum.php
+++ b/phpBB/phpbb/cron/task/core/prune_forum.php
@@ -31,7 +31,7 @@ class prune_forum extends \phpbb\cron\task\base implements \phpbb\cron\task\para
* If $forum_data is given, it is assumed to contain necessary information
* about a single forum that is to be pruned.
*
- * If $forum_data is not given, forum id will be retrieved via request_var
+ * If $forum_data is not given, forum id will be retrieved via $request->variable()
* and a database query will be performed to load the necessary information
* about the forum.
*/
diff --git a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
index 97a4b0ea86..0ab59f9ed5 100644
--- a/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
+++ b/phpBB/phpbb/cron/task/core/prune_shadow_topics.php
@@ -33,7 +33,7 @@ class prune_shadow_topics extends \phpbb\cron\task\base implements \phpbb\cron\t
* If $forum_data is given, it is assumed to contain necessary information
* about a single forum that is to be pruned.
*
- * If $forum_data is not given, forum id will be retrieved via request_var
+ * If $forum_data is not given, forum id will be retrieved via $request->variable()
* and a database query will be performed to load the necessary information
* about the forum.
*/
diff --git a/phpBB/phpbb/cron/task/core/queue.php b/phpBB/phpbb/cron/task/core/queue.php
index a9345a44df..eca69a5041 100644
--- a/phpBB/phpbb/cron/task/core/queue.php
+++ b/phpBB/phpbb/cron/task/core/queue.php
@@ -20,20 +20,23 @@ class queue extends \phpbb\cron\task\base
{
protected $phpbb_root_path;
protected $php_ext;
+ protected $cache_dir;
protected $config;
/**
- * Constructor.
- *
- * @param string $phpbb_root_path The root path
- * @param string $php_ext PHP file extension
- * @param \phpbb\config\config $config The config
- */
- public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config)
+ * Constructor.
+ *
+ * @param string $phpbb_root_path The root path
+ * @param string $php_ext PHP file extension
+ * @param \phpbb\config\config $config The config
+ * @param string $cache_dir phpBB cache directory
+ */
+ public function __construct($phpbb_root_path, $php_ext, \phpbb\config\config $config, $cache_dir)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->config = $config;
+ $this->cache_dir = $cache_dir;
}
/**
@@ -60,7 +63,7 @@ class queue extends \phpbb\cron\task\base
*/
public function is_runnable()
{
- return file_exists($this->phpbb_root_path . 'cache/queue.' . $this->php_ext);
+ return file_exists($this->cache_dir . 'queue.' . $this->php_ext);
}
/**
diff --git a/phpBB/phpbb/cron/task/core/tidy_plupload.php b/phpBB/phpbb/cron/task/core/tidy_plupload.php
index b6aeecf4b4..37d0e9b21a 100644
--- a/phpBB/phpbb/cron/task/core/tidy_plupload.php
+++ b/phpBB/phpbb/cron/task/core/tidy_plupload.php
@@ -42,6 +42,12 @@ class tidy_plupload extends \phpbb\cron\task\base
*/
protected $config;
+ /** @var \phpbb\log\log_interface */
+ protected $log;
+
+ /** @var \phpbb\user */
+ protected $user;
+
/**
* Directory where plupload stores temporary files.
* @var string
@@ -53,11 +59,15 @@ class tidy_plupload extends \phpbb\cron\task\base
*
* @param string $phpbb_root_path The root path
* @param \phpbb\config\config $config The config
+ * @param \phpbb\log\log_interface $log Log
+ * @param \phpbb\user $user User object
*/
- public function __construct($phpbb_root_path, \phpbb\config\config $config)
+ public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\log\log_interface $log, \phpbb\user $user)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->config = $config;
+ $this->log = $log;
+ $this->user = $user;
$this->plupload_upload_path = $this->phpbb_root_path . $this->config['upload_path'] . '/plupload';
}
@@ -88,13 +98,11 @@ class tidy_plupload extends \phpbb\cron\task\base
}
catch (\UnexpectedValueException $e)
{
- add_log(
- 'critical',
- 'LOG_PLUPLOAD_TIDY_FAILED',
+ $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_PLUPLOAD_TIDY_FAILED', false, array(
$this->plupload_upload_path,
$e->getMessage(),
$e->getTraceAsString()
- );
+ ));
}
$this->config->set('plupload_last_gc', time(), true);
diff --git a/phpBB/phpbb/cron/task/text_reparser/reparser.php b/phpBB/phpbb/cron/task/text_reparser/reparser.php
new file mode 100644
index 0000000000..7099128efd
--- /dev/null
+++ b/phpBB/phpbb/cron/task/text_reparser/reparser.php
@@ -0,0 +1,168 @@
+<?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\cron\task\text_reparser;
+
+/**
+ * Reparse text cron task
+ */
+class reparser extends \phpbb\cron\task\base
+{
+ const MIN = 1;
+ const SIZE = 100;
+
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\config\db_text
+ */
+ protected $config_text;
+
+ /**
+ * @var \phpbb\lock\db
+ */
+ protected $reparse_lock;
+
+ /**
+ * @var \phpbb\textreparser\manager
+ */
+ protected $reparser_manager;
+
+ /**
+ * @var string
+ */
+ protected $reparser_name;
+
+ /**
+ * @var \phpbb\di\service_collection
+ */
+ protected $reparsers;
+
+ /**
+ * @var array
+ */
+ protected $resume_data;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\config\config $config
+ * @param \phpbb\config\db_text $config_text
+ * @param \phpbb\lock\db $reparse_lock
+ * @param \phpbb\textreparser\manager $reparser_manager
+ * @param \phpbb\di\service_collection $reparsers
+ */
+ public function __construct(\phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\lock\db $reparse_lock, \phpbb\textreparser\manager $reparser_manager, \phpbb\di\service_collection $reparsers)
+ {
+ $this->config = $config;
+ $this->config_text = $config_text;
+ $this->reparse_lock = $reparse_lock;
+ $this->reparser_manager = $reparser_manager;
+ $this->reparsers = $reparsers;
+ }
+
+ /**
+ * Sets the reparser for this cron task
+ *
+ * @param string $reparser
+ */
+ public function set_reparser($reparser)
+ {
+ $this->reparser_name = (!isset($this->reparsers[$reparser]) ? 'text_reparser.' : '') . $reparser;
+
+ if ($this->resume_data === null)
+ {
+ $this->reparser_manager->get_resume_data($this->reparser_name);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_runnable()
+ {
+ if ($this->resume_data === null)
+ {
+ $this->reparser_manager->get_resume_data($this->reparser_name);
+ }
+
+ if (!isset($this->resume_data['range-max']) || $this->resume_data['range-max'] >= $this->resume_data['range-min'])
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function should_run()
+ {
+ if (!empty($this->config['reparse_lock']))
+ {
+ $last_run = explode(' ', $this->config['reparse_lock']);
+
+ if ($last_run[0] + 3600 >= time())
+ {
+ return false;
+ }
+ }
+
+ if ($this->config[$this->reparser_name . '_cron_interval'])
+ {
+ return $this->config[$this->reparser_name . '_last_cron'] < time() - $this->config[$this->reparser_name . '_cron_interval'];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if ($this->reparse_lock->acquire())
+ {
+ if ($this->resume_data === null)
+ {
+ $this->resume_data = $this->reparser_manager->get_resume_data($this->reparser_name);
+ }
+
+ /**
+ * @var \phpbb\textreparser\reparser_interface $reparser
+ */
+ $reparser = $this->reparsers[$this->reparser_name];
+
+ $min = isset($this->resume_data['range-min']) ? $this->resume_data['range-min'] : self::MIN;
+ $current = isset($this->resume_data['range-max']) ? $this->resume_data['range-max'] : $reparser->get_max_id();
+ $size = isset($this->resume_data['range-size']) ? $this->resume_data['range-size'] : self::SIZE;
+
+ if ($current >= $min)
+ {
+ $start = max($min, $current + 1 - $size);
+ $end = max($min, $current);
+
+ $reparser->reparse_range($start, $end);
+
+ $this->reparser_manager->update_resume_data($this->reparser_name, $min, $start - 1, $size);
+ }
+
+ $this->config->set($this->reparser_name . '_last_cron', time());
+ $this->reparse_lock->release();
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php
index 01dd66cd6e..214c5590e7 100644
--- a/phpBB/phpbb/db/driver/driver.php
+++ b/phpBB/phpbb/db/driver/driver.php
@@ -66,6 +66,15 @@ abstract class driver implements driver_interface
*/
var $sql_server_version = false;
+ const LOGICAL_OP = 0;
+ const STATEMENTS = 1;
+ const LEFT_STMT = 0;
+ const COMPARE_OP = 1;
+ const RIGHT_STMT = 2;
+ const SUBQUERY_OP = 3;
+ const SUBQUERY_SELECT_TYPE = 4;
+ const SUBQUERY_BUILD = 5;
+
/**
* Constructor
*/
@@ -271,7 +280,7 @@ abstract class driver implements driver_interface
$query_id = $this->query_result;
}
- if ($query_id !== false)
+ if ($query_id)
{
$result = array();
while ($row = $this->sql_fetchrow($query_id))
@@ -302,7 +311,7 @@ abstract class driver implements driver_interface
return $cache->sql_rowseek($rownum, $query_id);
}
- if ($query_id === false)
+ if (!$query_id)
{
return false;
}
@@ -310,7 +319,7 @@ abstract class driver implements driver_interface
$this->sql_freeresult($query_id);
$query_id = $this->sql_query($this->last_query_text);
- if ($query_id === false)
+ if (!$query_id)
{
return false;
}
@@ -339,7 +348,7 @@ abstract class driver implements driver_interface
$query_id = $this->query_result;
}
- if ($query_id !== false)
+ if ($query_id)
{
if ($rownum !== false)
{
@@ -363,8 +372,8 @@ abstract class driver implements driver_interface
*/
function sql_like_expression($expression)
{
- $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression);
- $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
+ $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression);
+ $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\'');
}
@@ -374,8 +383,8 @@ abstract class driver implements driver_interface
*/
function sql_not_like_expression($expression)
{
- $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression);
- $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
+ $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression);
+ $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
return $this->_sql_not_like_expression('NOT LIKE \'' . $this->sql_escape($expression) . '\'');
}
@@ -774,7 +783,18 @@ abstract class driver implements driver_interface
if (!empty($array['WHERE']))
{
- $sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']);
+ $sql .= ' WHERE ';
+
+ if (is_array($array['WHERE']))
+ {
+ $sql_where = $this->_process_boolean_tree_first($array['WHERE']);
+ }
+ else
+ {
+ $sql_where = $array['WHERE'];
+ }
+
+ $sql .= $this->_sql_custom_build('WHERE', $sql_where);
}
if (!empty($array['GROUP_BY']))
@@ -793,6 +813,130 @@ abstract class driver implements driver_interface
return $sql;
}
+
+ protected function _process_boolean_tree_first($operations_ary)
+ {
+ // In cases where an array exists but there is no head condition,
+ // it should be because there's only 1 WHERE clause. This seems the best way to deal with it.
+ if ($operations_ary[self::LOGICAL_OP] !== 'AND' &&
+ $operations_ary[self::LOGICAL_OP] !== 'OR')
+ {
+ $operations_ary = array('AND', array($operations_ary));
+ }
+ return $this->_process_boolean_tree($operations_ary) . "\n";
+ }
+
+ protected function _process_boolean_tree($operations_ary)
+ {
+ $operation = $operations_ary[self::LOGICAL_OP];
+
+ foreach ($operations_ary[self::STATEMENTS] as &$condition)
+ {
+ switch ($condition[self::LOGICAL_OP])
+ {
+ case 'AND':
+ case 'OR':
+
+ $condition = ' ( ' . $this->_process_boolean_tree($condition) . ') ';
+
+ break;
+ case 'NOT':
+
+ $condition = ' NOT (' . $this->_process_boolean_tree($condition) . ') ';
+
+ break;
+
+ default:
+
+ switch (sizeof($condition))
+ {
+ case 3:
+
+ // Typical 3 element clause with {left hand} {operator} {right hand}
+ switch ($condition[self::COMPARE_OP])
+ {
+ case 'IN':
+ case 'NOT_IN':
+
+ // As this is used with an IN, assume it is a set of elements for sql_in_set()
+ $condition = $this->sql_in_set($condition[self::LEFT_STMT], $condition[self::RIGHT_STMT], $condition[self::COMPARE_OP] === 'NOT_IN', true);
+
+ break;
+
+ case 'LIKE':
+
+ $condition = $condition[self::LEFT_STMT] . ' ' . $this->sql_like_expression($condition[self::RIGHT_STMT]) . ' ';
+
+ break;
+
+ case 'NOT_LIKE':
+
+ $condition = $condition[self::LEFT_STMT] . ' ' . $this->sql_not_like_expression($condition[self::RIGHT_STMT]) . ' ';
+
+ break;
+
+ case 'IS_NOT':
+
+ $condition[self::COMPARE_OP] = 'IS NOT';
+
+ // no break
+ case 'IS':
+
+ // If the value is NULL, the string of it is the empty string ('') which is not the intended result.
+ // this should solve that
+ if ($condition[self::RIGHT_STMT] === null)
+ {
+ $condition[self::RIGHT_STMT] = 'NULL';
+ }
+
+ $condition = implode(' ', $condition);
+
+ break;
+
+ default:
+
+ $condition = implode(' ', $condition);
+
+ break;
+ }
+
+ break;
+
+ case 5:
+
+ // 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 .= ' )';
+
+ break;
+
+ default:
+ // This is an unpredicted clause setup. Just join all elements.
+ $condition = implode(' ', $condition);
+
+ break;
+ }
+
+ break;
+ }
+
+ }
+
+ if ($operation === 'NOT')
+ {
+ $operations_ary = implode("", $operations_ary[self::STATEMENTS]);
+ }
+ else
+ {
+ $operations_ary = implode(" \n $operation ", $operations_ary[self::STATEMENTS]);
+ }
+
+ return $operations_ary;
+ }
+
+
/**
* {@inheritDoc}
*/
@@ -868,7 +1012,7 @@ abstract class driver implements driver_interface
*/
function sql_report($mode, $query = '')
{
- global $cache, $starttime, $phpbb_root_path, $phpbb_path_helper, $user;
+ global $cache, $starttime, $phpbb_root_path, $phpbb_path_helper;
global $request;
if (is_object($request) && !$request->variable('explain', false))
diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php
deleted file mode 100644
index f9ea884ce2..0000000000
--- a/phpBB/phpbb/db/driver/mssql.php
+++ /dev/null
@@ -1,476 +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\db\driver;
-
-/**
-* MSSQL Database Abstraction Layer
-* Minimum Requirement is MSSQL 2000+
-*/
-class mssql extends \phpbb\db\driver\driver
-{
- var $connect_error = '';
-
- /**
- * {@inheritDoc}
- */
- function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
- {
- if (!function_exists('mssql_connect'))
- {
- $this->connect_error = 'mssql_connect function does not exist, is mssql extension installed?';
- return $this->sql_error('');
- }
-
- $this->persistency = $persistency;
- $this->user = $sqluser;
- $this->dbname = $database;
-
- $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':';
- $this->server = $sqlserver . (($port) ? $port_delimiter . $port : '');
-
- @ini_set('mssql.charset', 'UTF-8');
- @ini_set('mssql.textlimit', 2147483647);
- @ini_set('mssql.textsize', 2147483647);
-
- $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mssql_connect($this->server, $this->user, $sqlpassword, $new_link);
-
- if ($this->db_connect_id && $this->dbname != '')
- {
- if (!@mssql_select_db($this->dbname, $this->db_connect_id))
- {
- @mssql_close($this->db_connect_id);
- return false;
- }
- }
-
- return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_server_info($raw = false, $use_cache = true)
- {
- global $cache;
-
- if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false)
- {
- $result_id = @mssql_query("SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')", $this->db_connect_id);
-
- $row = false;
- if ($result_id)
- {
- $row = @mssql_fetch_assoc($result_id);
- @mssql_free_result($result_id);
- }
-
- $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0;
-
- if (!empty($cache) && $use_cache)
- {
- $cache->put('mssql_version', $this->sql_server_version);
- }
- }
-
- if ($raw)
- {
- return $this->sql_server_version;
- }
-
- return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL';
- }
-
- /**
- * {@inheritDoc}
- */
- public function sql_concatenate($expr1, $expr2)
- {
- return $expr1 . ' + ' . $expr2;
- }
-
- /**
- * SQL Transaction
- * @access private
- */
- function _sql_transaction($status = 'begin')
- {
- switch ($status)
- {
- case 'begin':
- return @mssql_query('BEGIN TRANSACTION', $this->db_connect_id);
- break;
-
- case 'commit':
- return @mssql_query('COMMIT TRANSACTION', $this->db_connect_id);
- break;
-
- case 'rollback':
- return @mssql_query('ROLLBACK TRANSACTION', $this->db_connect_id);
- break;
- }
-
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_query($query = '', $cache_ttl = 0)
- {
- if ($query != '')
- {
- global $cache;
-
- // EXPLAIN only in extra debug mode
- if (defined('DEBUG'))
- {
- $this->sql_report('start', $query);
- }
- else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
- {
- $this->curtime = microtime(true);
- }
-
- $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
- $this->sql_add_num_queries($this->query_result);
-
- if ($this->query_result === false)
- {
- if (($this->query_result = @mssql_query($query, $this->db_connect_id)) === false)
- {
- $this->sql_error($query);
- }
-
- if (defined('DEBUG'))
- {
- $this->sql_report('stop', $query);
- }
- else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
- {
- $this->sql_time += microtime(true) - $this->curtime;
- }
-
- if ($cache && $cache_ttl)
- {
- $this->open_queries[(int) $this->query_result] = $this->query_result;
- $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
- }
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
- {
- $this->open_queries[(int) $this->query_result] = $this->query_result;
- }
- }
- else if (defined('DEBUG'))
- {
- $this->sql_report('fromcache', $query);
- }
- }
- else
- {
- return false;
- }
-
- return $this->query_result;
- }
-
- /**
- * Build LIMIT query
- */
- function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
- {
- $this->query_result = false;
-
- // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows)
- if ($total)
- {
- // We need to grab the total number of rows + the offset number of rows to get the correct result
- if (strpos($query, 'SELECT DISTINCT') === 0)
- {
- $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15);
- }
- else
- {
- $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6);
- }
- }
-
- $result = $this->sql_query($query, $cache_ttl);
-
- // Seek by $offset rows
- if ($offset)
- {
- $this->sql_rowseek($offset, $result);
- }
-
- return $result;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_affectedrows()
- {
- return ($this->db_connect_id) ? @mssql_rows_affected($this->db_connect_id) : false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_fetchrow($query_id = false)
- {
- global $cache;
-
- if ($query_id === false)
- {
- $query_id = $this->query_result;
- }
-
- if ($cache && $cache->sql_exists($query_id))
- {
- return $cache->sql_fetchrow($query_id);
- }
-
- if ($query_id === false)
- {
- return false;
- }
-
- $row = @mssql_fetch_assoc($query_id);
-
- // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug
- if ($row)
- {
- foreach ($row as $key => $value)
- {
- $row[$key] = ($value === ' ' || $value === null) ? '' : $value;
- }
- }
-
- return $row;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_rowseek($rownum, &$query_id)
- {
- global $cache;
-
- if ($query_id === false)
- {
- $query_id = $this->query_result;
- }
-
- if ($cache && $cache->sql_exists($query_id))
- {
- return $cache->sql_rowseek($rownum, $query_id);
- }
-
- return ($query_id !== false) ? @mssql_data_seek($query_id, $rownum) : false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_nextid()
- {
- $result_id = @mssql_query('SELECT SCOPE_IDENTITY()', $this->db_connect_id);
- if ($result_id)
- {
- if ($row = @mssql_fetch_assoc($result_id))
- {
- @mssql_free_result($result_id);
- return $row['computed'];
- }
- @mssql_free_result($result_id);
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_freeresult($query_id = false)
- {
- global $cache;
-
- if ($query_id === false)
- {
- $query_id = $this->query_result;
- }
-
- if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
- {
- return $cache->sql_freeresult($query_id);
- }
-
- if (isset($this->open_queries[(int) $query_id]))
- {
- unset($this->open_queries[(int) $query_id]);
- return @mssql_free_result($query_id);
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_escape($msg)
- {
- return str_replace(array("'", "\0"), array("''", ''), $msg);
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_lower_text($column_name)
- {
- return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))";
- }
-
- /**
- * Build LIKE expression
- * @access private
- */
- function _sql_like_expression($expression)
- {
- return $expression . " ESCAPE '\\'";
- }
-
- /**
- * Build NOT LIKE expression
- * @access private
- */
- function _sql_not_like_expression($expression)
- {
- return $expression . " ESCAPE '\\'";
- }
-
- /**
- * return sql error array
- * @access private
- */
- function _sql_error()
- {
- if (function_exists('mssql_get_last_message'))
- {
- $error = array(
- 'message' => @mssql_get_last_message(),
- 'code' => '',
- );
-
- // Get error code number
- $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id);
- if ($result_id)
- {
- $row = @mssql_fetch_assoc($result_id);
- $error['code'] = $row['code'];
- @mssql_free_result($result_id);
- }
-
- // Get full error message if possible
- $sql = 'SELECT CAST(description as varchar(255)) as message
- FROM master.dbo.sysmessages
- WHERE error = ' . $error['code'];
- $result_id = @mssql_query($sql);
-
- if ($result_id)
- {
- $row = @mssql_fetch_assoc($result_id);
- if (!empty($row['message']))
- {
- $error['message'] .= '<br />' . $row['message'];
- }
- @mssql_free_result($result_id);
- }
- }
- else
- {
- $error = array(
- 'message' => $this->connect_error,
- 'code' => '',
- );
- }
-
- return $error;
- }
-
- /**
- * Build db-specific query data
- * @access private
- */
- function _sql_custom_build($stage, $data)
- {
- return $data;
- }
-
- /**
- * Close sql connection
- * @access private
- */
- function _sql_close()
- {
- return @mssql_close($this->db_connect_id);
- }
-
- /**
- * Build db-specific report
- * @access private
- */
- function _sql_report($mode, $query = '')
- {
- switch ($mode)
- {
- case 'start':
- $html_table = false;
- @mssql_query('SET SHOWPLAN_TEXT ON;', $this->db_connect_id);
- if ($result = @mssql_query($query, $this->db_connect_id))
- {
- @mssql_next_result($result);
- while ($row = @mssql_fetch_row($result))
- {
- $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
- }
- }
- @mssql_query('SET SHOWPLAN_TEXT OFF;', $this->db_connect_id);
- @mssql_free_result($result);
-
- if ($html_table)
- {
- $this->html_hold .= '</table>';
- }
- break;
-
- case 'fromcache':
- $endtime = explode(' ', microtime());
- $endtime = $endtime[0] + $endtime[1];
-
- $result = @mssql_query($query, $this->db_connect_id);
- while ($void = @mssql_fetch_assoc($result))
- {
- // Take the time spent on parsing rows into account
- }
- @mssql_free_result($result);
-
- $splittime = explode(' ', microtime());
- $splittime = $splittime[0] + $splittime[1];
-
- $this->sql_report('record_fromcache', $query, $endtime, $splittime);
-
- break;
- }
- }
-}
diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php
index 8e5d4c7a4c..9d9ad603e0 100644
--- a/phpBB/phpbb/db/driver/mssql_odbc.php
+++ b/phpBB/phpbb/db/driver/mssql_odbc.php
@@ -98,8 +98,8 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
$row = false;
if ($result_id)
{
- $row = @odbc_fetch_array($result_id);
- @odbc_free_result($result_id);
+ $row = odbc_fetch_array($result_id);
+ odbc_free_result($result_id);
}
$this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0;
@@ -181,12 +181,17 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
+ else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
@@ -261,7 +266,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
return $cache->sql_fetchrow($query_id);
}
- return ($query_id !== false) ? @odbc_fetch_array($query_id) : false;
+ return ($query_id) ? odbc_fetch_array($query_id) : false;
}
/**
@@ -273,13 +278,13 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
if ($result_id)
{
- if (@odbc_fetch_array($result_id))
+ if (odbc_fetch_array($result_id))
{
- $id = @odbc_result($result_id, 1);
- @odbc_free_result($result_id);
+ $id = odbc_result($result_id, 1);
+ odbc_free_result($result_id);
return $id;
}
- @odbc_free_result($result_id);
+ odbc_free_result($result_id);
}
return false;
@@ -305,7 +310,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
- return @odbc_free_result($query_id);
+ return odbc_free_result($query_id);
}
return false;
@@ -360,11 +365,14 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base
$endtime = $endtime[0] + $endtime[1];
$result = @odbc_exec($this->db_connect_id, $query);
- while ($void = @odbc_fetch_array($result))
+ if ($result)
{
- // Take the time spent on parsing rows into account
+ while ($void = odbc_fetch_array($result))
+ {
+ // Take the time spent on parsing rows into account
+ }
+ odbc_free_result($result);
}
- @odbc_free_result($result);
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php
index 46a9b3a477..50dce35baa 100644
--- a/phpBB/phpbb/db/driver/mssqlnative.php
+++ b/phpBB/phpbb/db/driver/mssqlnative.php
@@ -154,12 +154,17 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
+ else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
@@ -242,12 +247,12 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
return $cache->sql_fetchrow($query_id);
}
- if ($query_id === false)
+ if (!$query_id)
{
return false;
}
- $row = @sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC);
+ $row = sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC);
if ($row)
{
@@ -272,11 +277,11 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
{
$result_id = @sqlsrv_query($this->db_connect_id, 'SELECT @@IDENTITY');
- if ($result_id !== false)
+ if ($result_id)
{
- $row = @sqlsrv_fetch_array($result_id);
+ $row = sqlsrv_fetch_array($result_id);
$id = $row[0];
- @sqlsrv_free_stmt($result_id);
+ sqlsrv_free_stmt($result_id);
return $id;
}
else
@@ -305,7 +310,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
- return @sqlsrv_free_stmt($query_id);
+ return sqlsrv_free_stmt($query_id);
}
return false;
@@ -378,14 +383,14 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
@sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT ON;');
if ($result = @sqlsrv_query($this->db_connect_id, $query))
{
- @sqlsrv_next_result($result);
- while ($row = @sqlsrv_fetch_array($result))
+ sqlsrv_next_result($result);
+ while ($row = sqlsrv_fetch_array($result))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
+ sqlsrv_free_stmt($result);
}
@sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT OFF;');
- @sqlsrv_free_stmt($result);
if ($html_table)
{
@@ -398,11 +403,14 @@ class mssqlnative extends \phpbb\db\driver\mssql_base
$endtime = $endtime[0] + $endtime[1];
$result = @sqlsrv_query($this->db_connect_id, $query);
- while ($void = @sqlsrv_fetch_array($result))
+ if ($result)
{
- // Take the time spent on parsing rows into account
+ while ($void = sqlsrv_fetch_array($result))
+ {
+ // Take the time spent on parsing rows into account
+ }
+ sqlsrv_free_stmt($result);
}
- @sqlsrv_free_stmt($result);
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php
index e93c7239e8..a94e88b331 100644
--- a/phpBB/phpbb/db/driver/mysql.php
+++ b/phpBB/phpbb/db/driver/mysql.php
@@ -70,9 +70,16 @@ class mysql extends \phpbb\db\driver\mysql_base
if (version_compare($this->sql_server_info(true), '5.0.2', '>='))
{
$result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id);
- $row = @mysql_fetch_assoc($result);
- @mysql_free_result($result);
- $modes = array_map('trim', explode(',', $row['sql_mode']));
+ if ($result)
+ {
+ $row = mysql_fetch_assoc($result);
+ mysql_free_result($result);
+ $modes = array_map('trim', explode(',', $row['sql_mode']));
+ }
+ else
+ {
+ $modes = array();
+ }
// TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES
if (!in_array('TRADITIONAL', $modes))
@@ -114,14 +121,17 @@ class mysql extends \phpbb\db\driver\mysql_base
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysql_version')) === false)
{
$result = @mysql_query('SELECT VERSION() AS version', $this->db_connect_id);
- $row = @mysql_fetch_assoc($result);
- @mysql_free_result($result);
+ if ($result)
+ {
+ $row = mysql_fetch_assoc($result);
+ mysql_free_result($result);
- $this->sql_server_version = $row['version'];
+ $this->sql_server_version = $row['version'];
- if (!empty($cache) && $use_cache)
- {
- $cache->put('mysql_version', $this->sql_server_version);
+ if (!empty($cache) && $use_cache)
+ {
+ $cache->put('mysql_version', $this->sql_server_version);
+ }
}
}
@@ -190,12 +200,17 @@ class mysql extends \phpbb\db\driver\mysql_base
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
+ else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
@@ -257,7 +272,7 @@ class mysql extends \phpbb\db\driver\mysql_base
return $cache->sql_fetchrow($query_id);
}
- return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false;
+ return ($query_id) ? mysql_fetch_assoc($query_id) : false;
}
/**
@@ -308,7 +323,7 @@ class mysql extends \phpbb\db\driver\mysql_base
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
- return @mysql_free_result($query_id);
+ return mysql_free_result($query_id);
}
return false;
@@ -411,12 +426,12 @@ class mysql extends \phpbb\db\driver\mysql_base
if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id))
{
- while ($row = @mysql_fetch_assoc($result))
+ while ($row = mysql_fetch_assoc($result))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
+ mysql_free_result($result);
}
- @mysql_free_result($result);
if ($html_table)
{
@@ -431,7 +446,7 @@ class mysql extends \phpbb\db\driver\mysql_base
if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id))
{
$this->html_hold .= '<br />';
- while ($row = @mysql_fetch_assoc($result))
+ while ($row = mysql_fetch_assoc($result))
{
// make <unknown> HTML safe
if (!empty($row['Source_function']))
@@ -449,8 +464,8 @@ class mysql extends \phpbb\db\driver\mysql_base
}
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
+ mysql_free_result($result);
}
- @mysql_free_result($result);
if ($html_table)
{
@@ -468,11 +483,14 @@ class mysql extends \phpbb\db\driver\mysql_base
$endtime = $endtime[0] + $endtime[1];
$result = @mysql_query($query, $this->db_connect_id);
- while ($void = @mysql_fetch_assoc($result))
+ if ($result)
{
- // Take the time spent on parsing rows into account
+ while ($void = mysql_fetch_assoc($result))
+ {
+ // Take the time spent on parsing rows into account
+ }
+ mysql_free_result($result);
}
- @mysql_free_result($result);
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php
index c0ddfbf76c..d43e201526 100644
--- a/phpBB/phpbb/db/driver/mysqli.php
+++ b/phpBB/phpbb/db/driver/mysqli.php
@@ -74,9 +74,10 @@ class mysqli extends \phpbb\db\driver\mysql_base
if (version_compare($this->sql_server_info(true), '5.0.2', '>='))
{
$result = @mysqli_query($this->db_connect_id, 'SELECT @@session.sql_mode AS sql_mode');
- if ($result !== null)
+ if ($result)
{
- $row = @mysqli_fetch_assoc($result);
+ $row = mysqli_fetch_assoc($result);
+ mysqli_free_result($result);
$modes = array_map('trim', explode(',', $row['sql_mode']));
}
@@ -84,7 +85,6 @@ class mysqli extends \phpbb\db\driver\mysql_base
{
$modes = array();
}
- @mysqli_free_result($result);
// TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES
if (!in_array('TRADITIONAL', $modes))
@@ -119,9 +119,10 @@ class mysqli extends \phpbb\db\driver\mysql_base
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysqli_version')) === false)
{
$result = @mysqli_query($this->db_connect_id, 'SELECT VERSION() AS version');
- if ($result !== null)
+ if ($result)
{
- $row = @mysqli_fetch_assoc($result);
+ $row = mysqli_fetch_assoc($result);
+ mysqli_free_result($result);
$this->sql_server_version = $row['version'];
@@ -130,7 +131,6 @@ class mysqli extends \phpbb\db\driver\mysql_base
$cache->put('mysqli_version', $this->sql_server_version);
}
}
- @mysqli_free_result($result);
}
return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version;
@@ -202,6 +202,11 @@ class mysqli extends \phpbb\db\driver\mysql_base
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
@@ -245,9 +250,9 @@ class mysqli extends \phpbb\db\driver\mysql_base
return $cache->sql_fetchrow($query_id);
}
- if ($query_id !== false && $query_id !== null)
+ if ($query_id)
{
- $result = @mysqli_fetch_assoc($query_id);
+ $result = mysqli_fetch_assoc($query_id);
return $result !== null ? $result : false;
}
@@ -271,7 +276,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id !== false) ? @mysqli_data_seek($query_id, $rownum) : false;
+ return ($query_id) ? @mysqli_data_seek($query_id, $rownum) : false;
}
/**
@@ -299,7 +304,17 @@ class mysqli extends \phpbb\db\driver\mysql_base
return $cache->sql_freeresult($query_id);
}
- return @mysqli_free_result($query_id);
+ if (!$query_id)
+ {
+ return false;
+ }
+
+ if ($query_id === true)
+ {
+ return true;
+ }
+
+ return mysqli_free_result($query_id);
}
/**
@@ -398,12 +413,12 @@ class mysqli extends \phpbb\db\driver\mysql_base
if ($result = @mysqli_query($this->db_connect_id, "EXPLAIN $explain_query"))
{
- while ($row = @mysqli_fetch_assoc($result))
+ while ($row = mysqli_fetch_assoc($result))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
+ mysqli_free_result($result);
}
- @mysqli_free_result($result);
if ($html_table)
{
@@ -418,7 +433,7 @@ class mysqli extends \phpbb\db\driver\mysql_base
if ($result = @mysqli_query($this->db_connect_id, 'SHOW PROFILE ALL;'))
{
$this->html_hold .= '<br />';
- while ($row = @mysqli_fetch_assoc($result))
+ while ($row = mysqli_fetch_assoc($result))
{
// make <unknown> HTML safe
if (!empty($row['Source_function']))
@@ -436,8 +451,8 @@ class mysqli extends \phpbb\db\driver\mysql_base
}
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
+ mysqli_free_result($result);
}
- @mysqli_free_result($result);
if ($html_table)
{
@@ -455,14 +470,14 @@ class mysqli extends \phpbb\db\driver\mysql_base
$endtime = $endtime[0] + $endtime[1];
$result = @mysqli_query($this->db_connect_id, $query);
- if ($result !== null)
+ if ($result)
{
- while ($void = @mysqli_fetch_assoc($result))
+ while ($void = mysqli_fetch_assoc($result))
{
// Take the time spent on parsing rows into account
}
+ mysqli_free_result($result);
}
- @mysqli_free_result($result);
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php
index 6dcab5dd7d..54238a15ef 100644
--- a/phpBB/phpbb/db/driver/oracle.php
+++ b/phpBB/phpbb/db/driver/oracle.php
@@ -84,8 +84,6 @@ class oracle extends \phpbb\db\driver\driver
* but I assume its because the Oracle extension provides a direct method to access it
* without a query.
*/
-
- $use_cache = false;
/*
global $cache;
@@ -439,12 +437,17 @@ class oracle extends \phpbb\db\driver\driver
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
+ else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
@@ -499,10 +502,10 @@ class oracle extends \phpbb\db\driver\driver
return $cache->sql_fetchrow($query_id);
}
- if ($query_id !== false)
+ if ($query_id)
{
$row = array();
- $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS);
+ $result = ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS);
if (!$result || !$row)
{
@@ -550,7 +553,7 @@ class oracle extends \phpbb\db\driver\driver
return $cache->sql_rowseek($rownum, $query_id);
}
- if ($query_id === false)
+ if (!$query_id)
{
return false;
}
@@ -583,18 +586,24 @@ class oracle extends \phpbb\db\driver\driver
{
$query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL';
$stmt = @ociparse($this->db_connect_id, $query);
- @ociexecute($stmt, OCI_DEFAULT);
+ if ($stmt)
+ {
+ $success = @ociexecute($stmt, OCI_DEFAULT);
- $temp_result = @ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS);
- @ocifreestatement($stmt);
+ if ($success)
+ {
+ $temp_result = ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS);
+ ocifreestatement($stmt);
- if ($temp_result)
- {
- return $temp_array['CURRVAL'];
- }
- else
- {
- return false;
+ if ($temp_result)
+ {
+ return $temp_array['CURRVAL'];
+ }
+ else
+ {
+ return false;
+ }
+ }
}
}
}
@@ -622,7 +631,7 @@ class oracle extends \phpbb\db\driver\driver
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
- return @ocifreestatement($query_id);
+ return ocifreestatement($query_id);
}
return false;
@@ -787,14 +796,20 @@ class oracle extends \phpbb\db\driver\driver
$endtime = $endtime[0] + $endtime[1];
$result = @ociparse($this->db_connect_id, $query);
- $success = @ociexecute($result, OCI_DEFAULT);
- $row = array();
-
- while (@ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS))
+ if ($result)
{
- // Take the time spent on parsing rows into account
+ $success = @ociexecute($result, OCI_DEFAULT);
+ if ($success)
+ {
+ $row = array();
+
+ while (ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS))
+ {
+ // Take the time spent on parsing rows into account
+ }
+ @ocifreestatement($result);
+ }
}
- @ocifreestatement($result);
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php
index a3b9aa4c6b..44476612c3 100644
--- a/phpBB/phpbb/db/driver/postgres.php
+++ b/phpBB/phpbb/db/driver/postgres.php
@@ -123,14 +123,17 @@ class postgres extends \phpbb\db\driver\driver
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('pgsql_version')) === false)
{
$query_id = @pg_query($this->db_connect_id, 'SELECT VERSION() AS version');
- $row = @pg_fetch_assoc($query_id, null);
- @pg_free_result($query_id);
+ if ($query_id)
+ {
+ $row = pg_fetch_assoc($query_id, null);
+ pg_free_result($query_id);
- $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0;
+ $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0;
- if (!empty($cache) && $use_cache)
- {
- $cache->put('pgsql_version', $this->sql_server_version);
+ if (!empty($cache) && $use_cache)
+ {
+ $cache->put('pgsql_version', $this->sql_server_version);
+ }
}
}
@@ -200,12 +203,17 @@ class postgres extends \phpbb\db\driver\driver
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
+ else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
@@ -275,7 +283,7 @@ class postgres extends \phpbb\db\driver\driver
return $cache->sql_fetchrow($query_id);
}
- return ($query_id !== false) ? @pg_fetch_assoc($query_id, null) : false;
+ return ($query_id) ? pg_fetch_assoc($query_id, null) : false;
}
/**
@@ -295,7 +303,7 @@ class postgres extends \phpbb\db\driver\driver
return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id !== false) ? @pg_result_seek($query_id, $rownum) : false;
+ return ($query_id) ? @pg_result_seek($query_id, $rownum) : false;
}
/**
@@ -317,8 +325,8 @@ class postgres extends \phpbb\db\driver\driver
return false;
}
- $temp_result = @pg_fetch_assoc($temp_q_id, null);
- @pg_free_result($query_id);
+ $temp_result = pg_fetch_assoc($temp_q_id, null);
+ pg_free_result($query_id);
return ($temp_result) ? $temp_result['last_value'] : false;
}
@@ -347,7 +355,7 @@ class postgres extends \phpbb\db\driver\driver
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
- return @pg_free_result($query_id);
+ return pg_free_result($query_id);
}
return false;
@@ -453,12 +461,12 @@ class postgres extends \phpbb\db\driver\driver
if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query"))
{
- while ($row = @pg_fetch_assoc($result, null))
+ while ($row = pg_fetch_assoc($result, null))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
+ pg_free_result($result);
}
- @pg_free_result($result);
if ($html_table)
{
@@ -473,11 +481,14 @@ class postgres extends \phpbb\db\driver\driver
$endtime = $endtime[0] + $endtime[1];
$result = @pg_query($this->db_connect_id, $query);
- while ($void = @pg_fetch_assoc($result, null))
+ if ($result)
{
- // Take the time spent on parsing rows into account
+ while ($void = pg_fetch_assoc($result, null))
+ {
+ // Take the time spent on parsing rows into account
+ }
+ pg_free_result($result);
}
- @pg_free_result($result);
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php
deleted file mode 100644
index d5da0e2438..0000000000
--- a/phpBB/phpbb/db/driver/sqlite.php
+++ /dev/null
@@ -1,378 +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\db\driver;
-
-/**
-* Sqlite Database Abstraction Layer
-* Minimum Requirement: 2.8.2+
-*/
-class sqlite extends \phpbb\db\driver\driver
-{
- var $connect_error = '';
-
- /**
- * {@inheritDoc}
- */
- function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
- {
- $this->persistency = $persistency;
- $this->user = $sqluser;
- $this->server = $sqlserver . (($port) ? ':' . $port : '');
- $this->dbname = $database;
-
- $error = '';
- if ($this->persistency)
- {
- if (!function_exists('sqlite_popen'))
- {
- $this->connect_error = 'sqlite_popen function does not exist, is sqlite extension installed?';
- return $this->sql_error('');
- }
- $this->db_connect_id = @sqlite_popen($this->server, 0666, $error);
- }
- else
- {
- if (!function_exists('sqlite_open'))
- {
- $this->connect_error = 'sqlite_open function does not exist, is sqlite extension installed?';
- return $this->sql_error('');
- }
- $this->db_connect_id = @sqlite_open($this->server, 0666, $error);
- }
-
- if ($this->db_connect_id)
- {
- @sqlite_query('PRAGMA short_column_names = 1', $this->db_connect_id);
-// @sqlite_query('PRAGMA encoding = "UTF-8"', $this->db_connect_id);
- }
-
- return ($this->db_connect_id) ? true : array('message' => $error);
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_server_info($raw = false, $use_cache = true)
- {
- global $cache;
-
- if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false)
- {
- $result = @sqlite_query('SELECT sqlite_version() AS version', $this->db_connect_id);
- $row = @sqlite_fetch_array($result, SQLITE_ASSOC);
-
- $this->sql_server_version = (!empty($row['version'])) ? $row['version'] : 0;
-
- if (!empty($cache) && $use_cache)
- {
- $cache->put('sqlite_version', $this->sql_server_version);
- }
- }
-
- return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version;
- }
-
- /**
- * SQL Transaction
- * @access private
- */
- function _sql_transaction($status = 'begin')
- {
- switch ($status)
- {
- case 'begin':
- return @sqlite_query('BEGIN', $this->db_connect_id);
- break;
-
- case 'commit':
- return @sqlite_query('COMMIT', $this->db_connect_id);
- break;
-
- case 'rollback':
- return @sqlite_query('ROLLBACK', $this->db_connect_id);
- break;
- }
-
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_query($query = '', $cache_ttl = 0)
- {
- if ($query != '')
- {
- global $cache;
-
- // EXPLAIN only in extra debug mode
- if (defined('DEBUG'))
- {
- $this->sql_report('start', $query);
- }
- else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
- {
- $this->curtime = microtime(true);
- }
-
- $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
- $this->sql_add_num_queries($this->query_result);
-
- if ($this->query_result === false)
- {
- if (($this->query_result = @sqlite_query($query, $this->db_connect_id)) === false)
- {
- $this->sql_error($query);
- }
-
- if (defined('DEBUG'))
- {
- $this->sql_report('stop', $query);
- }
- else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
- {
- $this->sql_time += microtime(true) - $this->curtime;
- }
-
- if ($cache && $cache_ttl)
- {
- $this->open_queries[(int) $this->query_result] = $this->query_result;
- $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
- }
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
- {
- $this->open_queries[(int) $this->query_result] = $this->query_result;
- }
- }
- else if (defined('DEBUG'))
- {
- $this->sql_report('fromcache', $query);
- }
- }
- else
- {
- return false;
- }
-
- return $this->query_result;
- }
-
- /**
- * Build LIMIT query
- */
- function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
- {
- $this->query_result = false;
-
- // if $total is set to 0 we do not want to limit the number of rows
- if ($total == 0)
- {
- $total = -1;
- }
-
- $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
-
- return $this->sql_query($query, $cache_ttl);
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_affectedrows()
- {
- return ($this->db_connect_id) ? @sqlite_changes($this->db_connect_id) : false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_fetchrow($query_id = false)
- {
- global $cache;
-
- if ($query_id === false)
- {
- $query_id = $this->query_result;
- }
-
- if ($cache && $cache->sql_exists($query_id))
- {
- return $cache->sql_fetchrow($query_id);
- }
-
- return ($query_id !== false) ? @sqlite_fetch_array($query_id, SQLITE_ASSOC) : false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_rowseek($rownum, &$query_id)
- {
- global $cache;
-
- if ($query_id === false)
- {
- $query_id = $this->query_result;
- }
-
- if ($cache && $cache->sql_exists($query_id))
- {
- return $cache->sql_rowseek($rownum, $query_id);
- }
-
- return ($query_id !== false) ? @sqlite_seek($query_id, $rownum) : false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_nextid()
- {
- return ($this->db_connect_id) ? @sqlite_last_insert_rowid($this->db_connect_id) : false;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_freeresult($query_id = false)
- {
- global $cache;
-
- if ($query_id === false)
- {
- $query_id = $this->query_result;
- }
-
- if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
- {
- return $cache->sql_freeresult($query_id);
- }
-
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- function sql_escape($msg)
- {
- return @sqlite_escape_string($msg);
- }
-
- /**
- * {@inheritDoc}
- *
- * For SQLite an underscore is a not-known character... this may change with SQLite3
- */
- function sql_like_expression($expression)
- {
- // Unlike LIKE, GLOB is unfortunately case sensitive.
- // We only catch * and ? here, not the character map possible on file globbing.
- $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
-
- $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
- $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
-
- return 'GLOB \'' . $this->sql_escape($expression) . '\'';
- }
-
- /**
- * {@inheritDoc}
- *
- * For SQLite an underscore is a not-known character...
- */
- function sql_not_like_expression($expression)
- {
- // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive.
- // We only catch * and ? here, not the character map possible on file globbing.
- $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
-
- $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
- $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
-
- return 'NOT GLOB \'' . $this->sql_escape($expression) . '\'';
- }
-
- /**
- * return sql error array
- * @access private
- */
- function _sql_error()
- {
- if (function_exists('sqlite_error_string'))
- {
- $error = array(
- 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)),
- 'code' => @sqlite_last_error($this->db_connect_id),
- );
- }
- else
- {
- $error = array(
- 'message' => $this->connect_error,
- 'code' => '',
- );
- }
-
- return $error;
- }
-
- /**
- * Build db-specific query data
- * @access private
- */
- function _sql_custom_build($stage, $data)
- {
- return $data;
- }
-
- /**
- * Close sql connection
- * @access private
- */
- function _sql_close()
- {
- return @sqlite_close($this->db_connect_id);
- }
-
- /**
- * Build db-specific report
- * @access private
- */
- function _sql_report($mode, $query = '')
- {
- switch ($mode)
- {
- case 'start':
- break;
-
- case 'fromcache':
- $endtime = explode(' ', microtime());
- $endtime = $endtime[0] + $endtime[1];
-
- $result = @sqlite_query($query, $this->db_connect_id);
- while ($void = @sqlite_fetch_array($result, SQLITE_ASSOC))
- {
- // Take the time spent on parsing rows into account
- }
-
- $splittime = explode(' ', microtime());
- $splittime = $splittime[0] + $splittime[1];
-
- $this->sql_report('record_fromcache', $query, $endtime, $splittime);
-
- break;
- }
- }
-}
diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php
index cc3352af34..0508500c52 100644
--- a/phpBB/phpbb/db/driver/sqlite3.php
+++ b/phpBB/phpbb/db/driver/sqlite3.php
@@ -102,7 +102,7 @@ class sqlite3 extends \phpbb\db\driver\driver
break;
case 'rollback':
- return $this->dbo->exec('ROLLBACK');
+ return @$this->dbo->exec('ROLLBACK');
break;
}
@@ -134,9 +134,26 @@ class sqlite3 extends \phpbb\db\driver\driver
if ($this->query_result === false)
{
+ if ($this->transaction === true && strpos($query, 'INSERT') === 0)
+ {
+ $query = preg_replace('/^INSERT INTO/', 'INSERT OR ROLLBACK INTO', $query);
+ }
+
if (($this->query_result = @$this->dbo->query($query)) === false)
{
- $this->sql_error($query);
+ // Try to recover a lost database connection
+ if ($this->dbo && !@$this->dbo->lastErrorMsg())
+ {
+ if ($this->sql_connect($this->server, $this->user, '', $this->dbname))
+ {
+ $this->query_result = @$this->dbo->query($query);
+ }
+ }
+
+ if ($this->query_result === false)
+ {
+ $this->sql_error($query);
+ }
}
if (defined('DEBUG'))
@@ -148,6 +165,11 @@ class sqlite3 extends \phpbb\db\driver\driver
$this->sql_time += microtime(true) - $this->curtime;
}
+ if (!$this->query_result)
+ {
+ return false;
+ }
+
if ($cache && $cache_ttl)
{
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
@@ -208,6 +230,7 @@ class sqlite3 extends \phpbb\db\driver\driver
if ($query_id === false)
{
+ /** @var \SQLite3Result $query_id */
$query_id = $this->query_result;
}
@@ -216,7 +239,7 @@ class sqlite3 extends \phpbb\db\driver\driver
return $cache->sql_fetchrow($query_id);
}
- return is_object($query_id) ? $query_id->fetchArray(SQLITE3_ASSOC) : false;
+ return is_object($query_id) ? @$query_id->fetchArray(SQLITE3_ASSOC) : false;
}
/**
@@ -389,9 +412,12 @@ class sqlite3 extends \phpbb\db\driver\driver
$endtime = $endtime[0] + $endtime[1];
$result = $this->dbo->query($query);
- while ($void = $result->fetchArray(SQLITE3_ASSOC))
+ if ($result)
{
- // Take the time spent on parsing rows into account
+ while ($void = $result->fetchArray(SQLITE3_ASSOC))
+ {
+ // Take the time spent on parsing rows into account
+ }
}
$splittime = explode(' ', microtime());
diff --git a/phpBB/phpbb/db/extractor/base_extractor.php b/phpBB/phpbb/db/extractor/base_extractor.php
new file mode 100644
index 0000000000..547c85f066
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/base_extractor.php
@@ -0,0 +1,252 @@
+<?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\extractor;
+
+use phpbb\db\extractor\exception\invalid_format_exception;
+use phpbb\db\extractor\exception\extractor_not_initialized_exception;
+
+/**
+ * Abstract base class for database extraction
+ */
+abstract class base_extractor implements extractor_interface
+{
+ /**
+ * @var string phpBB root path
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var \phpbb\request\request_interface
+ */
+ protected $request;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var bool
+ */
+ protected $download;
+
+ /**
+ * @var bool
+ */
+ protected $store;
+
+ /**
+ * @var int
+ */
+ protected $time;
+
+ /**
+ * @var string
+ */
+ protected $format;
+
+ /**
+ * @var resource
+ */
+ protected $fp;
+
+ /**
+ * @var string
+ */
+ protected $write;
+
+ /**
+ * @var string
+ */
+ protected $close;
+
+ /**
+ * @var bool
+ */
+ protected $run_comp;
+
+ /**
+ * @var bool
+ */
+ protected $is_initialized;
+
+ /**
+ * Constructor
+ *
+ * @param string $phpbb_root_path
+ * @param \phpbb\request\request_interface $request
+ * @param \phpbb\db\driver\driver_interface $db
+ */
+ public function __construct($phpbb_root_path, \phpbb\request\request_interface $request, \phpbb\db\driver\driver_interface $db)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->request = $request;
+ $this->db = $db;
+ $this->fp = null;
+
+ $this->is_initialized = false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init_extractor($format, $filename, $time, $download = false, $store = false)
+ {
+ $this->download = $download;
+ $this->store = $store;
+ $this->time = $time;
+ $this->format = $format;
+
+ switch ($format)
+ {
+ case 'text':
+ $ext = '.sql';
+ $open = 'fopen';
+ $this->write = 'fwrite';
+ $this->close = 'fclose';
+ $mimetype = 'text/x-sql';
+ break;
+ case 'bzip2':
+ $ext = '.sql.bz2';
+ $open = 'bzopen';
+ $this->write = 'bzwrite';
+ $this->close = 'bzclose';
+ $mimetype = 'application/x-bzip2';
+ break;
+ case 'gzip':
+ $ext = '.sql.gz';
+ $open = 'gzopen';
+ $this->write = 'gzwrite';
+ $this->close = 'gzclose';
+ $mimetype = 'application/x-gzip';
+ break;
+ default:
+ throw new invalid_format_exception();
+ break;
+ }
+
+ if ($download === true)
+ {
+ $name = $filename . $ext;
+ header('Cache-Control: private, no-cache');
+ header("Content-Type: $mimetype; name=\"$name\"");
+ header("Content-disposition: attachment; filename=$name");
+
+ switch ($format)
+ {
+ case 'bzip2':
+ ob_start();
+ break;
+
+ case 'gzip':
+ if (strpos($this->request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($this->request->header('User-Agent')), 'msie') === false)
+ {
+ ob_start('ob_gzhandler');
+ }
+ else
+ {
+ $this->run_comp = true;
+ }
+ break;
+ }
+ }
+
+ if ($store === true)
+ {
+ $file = $this->phpbb_root_path . 'store/' . $filename . $ext;
+
+ $this->fp = $open($file, 'w');
+
+ if (!$this->fp)
+ {
+ trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
+ }
+ }
+
+ $this->is_initialized = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_end()
+ {
+ static $close;
+
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ if ($this->store)
+ {
+ if ($close === null)
+ {
+ $close = $this->close;
+ }
+ $close($this->fp);
+ }
+
+ // bzip2 must be written all the way at the end
+ if ($this->download && $this->format === 'bzip2')
+ {
+ $c = ob_get_clean();
+ echo bzcompress($c);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function flush($data)
+ {
+ static $write;
+
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ if ($this->store === true)
+ {
+ if ($write === null)
+ {
+ $write = $this->write;
+ }
+ $write($this->fp, $data);
+ }
+
+ if ($this->download === true)
+ {
+ if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp))
+ {
+ echo $data;
+ }
+
+ // we can write the gzip data as soon as we get it
+ if ($this->format === 'gzip')
+ {
+ if ($this->run_comp)
+ {
+ echo gzencode($data);
+ }
+ else
+ {
+ ob_flush();
+ flush();
+ }
+ }
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php b/phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php
new file mode 100644
index 0000000000..62eb434be1
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/exception/extractor_not_initialized_exception.php
@@ -0,0 +1,24 @@
+<?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\extractor\exception;
+
+use phpbb\exception\runtime_exception;
+
+/**
+* This exception is thrown when invalid format is given to the extractor
+*/
+class extractor_not_initialized_exception extends runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/db/extractor/exception/invalid_format_exception.php b/phpBB/phpbb/db/extractor/exception/invalid_format_exception.php
new file mode 100644
index 0000000000..6be24cb5dc
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/exception/invalid_format_exception.php
@@ -0,0 +1,22 @@
+<?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\extractor\exception;
+
+/**
+* This exception is thrown when invalid format is given to the extractor
+*/
+class invalid_format_exception extends \InvalidArgumentException
+{
+
+}
diff --git a/phpBB/phpbb/db/extractor/extractor_interface.php b/phpBB/phpbb/db/extractor/extractor_interface.php
new file mode 100644
index 0000000000..ff45df9bb7
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/extractor_interface.php
@@ -0,0 +1,80 @@
+<?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\extractor;
+
+/**
+* Database extractor interface
+*/
+interface extractor_interface
+{
+ /**
+ * Start the extraction of the database
+ *
+ * This function initialize the database extraction. It is required to call this
+ * function before calling any other extractor functions.
+ *
+ * @param string $format
+ * @param string $filename
+ * @param int $time
+ * @param bool $download
+ * @param bool $store
+ * @return null
+ * @throws \phpbb\db\extractor\exception\invalid_format_exception when $format is invalid
+ */
+ public function init_extractor($format, $filename, $time, $download = false, $store = false);
+
+ /**
+ * Writes header comments to the database backup
+ *
+ * @param string $table_prefix prefix of phpBB database tables
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_start($table_prefix);
+
+ /**
+ * Closes file and/or dumps download data
+ *
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_end();
+
+ /**
+ * Extracts database table structure
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_table($table_name);
+
+ /**
+ * Extracts data from database table
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_data($table_name);
+
+ /**
+ * Writes data to file/download content
+ *
+ * @param string $data
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function flush($data);
+}
diff --git a/phpBB/phpbb/db/extractor/factory.php b/phpBB/phpbb/db/extractor/factory.php
new file mode 100644
index 0000000000..f27aae720f
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/factory.php
@@ -0,0 +1,75 @@
+<?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\extractor;
+
+/**
+* A factory which serves the suitable extractor instance for the given dbal
+*/
+class factory
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * Extractor factory constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \Symfony\Component\DependencyInjection\ContainerInterface $container)
+ {
+ $this->db = $db;
+ $this->container = $container;
+ }
+
+ /**
+ * DB extractor factory getter
+ *
+ * @return \phpbb\db\extractor\extractor_interface an appropriate instance of the database extractor for the used database driver
+ * @throws \InvalidArgumentException when the database driver is unknown
+ */
+ public function get()
+ {
+ // Return the appropriate DB extractor
+ if ($this->db instanceof \phpbb\db\driver\mssql_base)
+ {
+ return $this->container->get('dbal.extractor.extractors.mssql_extractor');
+ }
+ else if ($this->db instanceof \phpbb\db\driver\mysql_base)
+ {
+ return $this->container->get('dbal.extractor.extractors.mysql_extractor');
+ }
+ else if ($this->db instanceof \phpbb\db\driver\oracle)
+ {
+ return $this->container->get('dbal.extractor.extractors.oracle_extractor');
+ }
+ else if ($this->db instanceof \phpbb\db\driver\postgres)
+ {
+ return $this->container->get('dbal.extractor.extractors.postgres_extractor');
+ }
+ else if ($this->db instanceof \phpbb\db\driver\sqlite3)
+ {
+ return $this->container->get('dbal.extractor.extractors.sqlite3_extractor');
+ }
+
+ throw new \InvalidArgumentException('Invalid database driver given');
+ }
+}
diff --git a/phpBB/phpbb/db/extractor/mssql_extractor.php b/phpBB/phpbb/db/extractor/mssql_extractor.php
new file mode 100644
index 0000000000..2817d3ebcc
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/mssql_extractor.php
@@ -0,0 +1,415 @@
+<?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\extractor;
+
+use phpbb\db\extractor\exception\extractor_not_initialized_exception;
+
+class mssql_extractor extends base_extractor
+{
+ /**
+ * Writes closing line(s) to database backup
+ *
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_end()
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $this->flush("COMMIT\nGO\n");
+ parent::write_end();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_start($table_prefix)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = "--\n";
+ $sql_data .= "-- phpBB Backup Script\n";
+ $sql_data .= "-- Dump of tables for $table_prefix\n";
+ $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
+ $sql_data .= "--\n";
+ $sql_data .= "BEGIN TRANSACTION\n";
+ $sql_data .= "GO\n";
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_table($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = '-- Table: ' . $table_name . "\n";
+ $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n";
+ $sql_data .= "DROP TABLE $table_name;\n";
+ $sql_data .= "GO\n";
+ $sql_data .= "\nCREATE TABLE [$table_name] (\n";
+ $rows = array();
+
+ $text_flag = false;
+
+ $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE TABLE_NAME = '$table_name'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]";
+
+ if ($row['DATA_TYPE'] == 'text')
+ {
+ $text_flag = true;
+ }
+
+ if ($row['IS_IDENTITY'])
+ {
+ $line .= ' IDENTITY (1 , 1)';
+ }
+
+ if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text')
+ {
+ $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')';
+ }
+
+ if ($row['IS_NULLABLE'] == 'YES')
+ {
+ $line .= ' NULL';
+ }
+ else
+ {
+ $line .= ' NOT NULL';
+ }
+
+ if ($row['COLUMN_DEFAULT'])
+ {
+ $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT'];
+ }
+
+ $rows[] = $line;
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql_data .= implode(",\n", $rows);
+ $sql_data .= "\n) ON [PRIMARY]";
+
+ if ($text_flag)
+ {
+ $sql_data .= " TEXTIMAGE_ON [PRIMARY]";
+ }
+
+ $sql_data .= "\nGO\n\n";
+ $rows = array();
+
+ $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME
+ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
+ WHERE TABLE_NAME = '$table_name'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!sizeof($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))
+ {
+ $sql_data .= implode(",\n", $rows);
+ $sql_data .= "\n\t) ON [PRIMARY] \nGO\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ $index = array();
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['TYPE'] == 3)
+ {
+ $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ foreach ($index as $index_name => $column_name)
+ {
+ $index[$index_name] = implode(', ', $column_name);
+ }
+
+ foreach ($index as $index_name => $columns)
+ {
+ $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n";
+ }
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_data($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ if ($this->db->get_sql_layer() === 'mssqlnative')
+ {
+ $this->write_data_mssqlnative($table_name);
+ }
+ else
+ {
+ $this->write_data_odbc($table_name);
+ }
+ }
+
+ /**
+ * Extracts data from database table (for MSSQL Native driver)
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ protected function write_data_mssqlnative($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $ary_type = $ary_name = array();
+ $ident_set = false;
+ $sql_data = '';
+
+ // Grab all of the data from current table.
+ $sql = "SELECT * FROM $table_name";
+ $this->db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
+ $result = $this->db->sql_query($sql);
+
+ $retrieved_data = $this->db->mssqlnative_num_rows($result);
+
+ if (!$retrieved_data)
+ {
+ $this->db->sql_freeresult($result);
+ return;
+ }
+
+ $sql = "SELECT COLUMN_NAME, DATA_TYPE
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $this->db->sql_escape($table_name) . "'";
+ $result_fields = $this->db->sql_query($sql);
+
+ $i_num_fields = 0;
+ while ($row = $this->db->sql_fetchrow($result_fields))
+ {
+ $ary_type[$i_num_fields] = $row['DATA_TYPE'];
+ $ary_name[$i_num_fields] = $row['COLUMN_NAME'];
+ $i_num_fields++;
+ }
+ $this->db->sql_freeresult($result_fields);
+
+ $sql = "SELECT 1 as has_identity
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
+ $result2 = $this->db->sql_query($sql);
+ $row2 = $this->db->sql_fetchrow($result2);
+
+ if (!empty($row2['has_identity']))
+ {
+ $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
+ $ident_set = true;
+ }
+ $this->db->sql_freeresult($result2);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $schema_vals = $schema_fields = array();
+
+ // Build the SQL statement to recreate the data.
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $str_val = $row[$ary_name[$i]];
+
+ // defaults to type number - better quote just to be safe, so check for is_int too
+ if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
+ {
+ $str_quote = '';
+ $str_empty = "''";
+ $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
+ }
+ else if (preg_match('#date|timestamp#i', $ary_type[$i]))
+ {
+ if (empty($str_val))
+ {
+ $str_quote = '';
+ }
+ else
+ {
+ $str_quote = "'";
+ }
+ }
+ else
+ {
+ $str_quote = '';
+ $str_empty = 'NULL';
+ }
+
+ if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
+ {
+ $str_val = $str_empty;
+ }
+
+ $schema_vals[$i] = $str_quote . $str_val . $str_quote;
+ $schema_fields[$i] = $ary_name[$i];
+ }
+
+ // Take the ordered fields and their associated data and build it
+ // into a valid sql statement to recreate that field in the data.
+ $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
+
+ $this->flush($sql_data);
+ $sql_data = '';
+ }
+ $this->db->sql_freeresult($result);
+
+ if ($ident_set)
+ {
+ $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
+ }
+ $this->flush($sql_data);
+ }
+
+ /**
+ * Extracts data from database table (for ODBC driver)
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ protected function write_data_odbc($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $ary_type = $ary_name = array();
+ $ident_set = false;
+ $sql_data = '';
+
+ // Grab all of the data from current table.
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = $this->db->sql_query($sql);
+
+ $retrieved_data = odbc_num_rows($result);
+
+ if ($retrieved_data)
+ {
+ $sql = "SELECT 1 as has_identity
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
+ $result2 = $this->db->sql_query($sql);
+ $row2 = $this->db->sql_fetchrow($result2);
+ if (!empty($row2['has_identity']))
+ {
+ $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
+ $ident_set = true;
+ }
+ $this->db->sql_freeresult($result2);
+ }
+
+ $i_num_fields = odbc_num_fields($result);
+
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $ary_type[$i] = odbc_field_type($result, $i + 1);
+ $ary_name[$i] = odbc_field_name($result, $i + 1);
+ }
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $schema_vals = $schema_fields = array();
+
+ // Build the SQL statement to recreate the data.
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $str_val = $row[$ary_name[$i]];
+
+ if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
+ {
+ $str_quote = '';
+ $str_empty = "''";
+ $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
+ }
+ else if (preg_match('#date|timestamp#i', $ary_type[$i]))
+ {
+ if (empty($str_val))
+ {
+ $str_quote = '';
+ }
+ else
+ {
+ $str_quote = "'";
+ }
+ }
+ else
+ {
+ $str_quote = '';
+ $str_empty = 'NULL';
+ }
+
+ if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
+ {
+ $str_val = $str_empty;
+ }
+
+ $schema_vals[$i] = $str_quote . $str_val . $str_quote;
+ $schema_fields[$i] = $ary_name[$i];
+ }
+
+ // Take the ordered fields and their associated data and build it
+ // into a valid sql statement to recreate that field in the data.
+ $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
+
+ $this->flush($sql_data);
+
+ $sql_data = '';
+
+ }
+ $this->db->sql_freeresult($result);
+
+ if ($retrieved_data && $ident_set)
+ {
+ $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
+ }
+ $this->flush($sql_data);
+ }
+}
diff --git a/phpBB/phpbb/db/extractor/mysql_extractor.php b/phpBB/phpbb/db/extractor/mysql_extractor.php
new file mode 100644
index 0000000000..34e309c19e
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/mysql_extractor.php
@@ -0,0 +1,403 @@
+<?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\extractor;
+
+use phpbb\db\extractor\exception\extractor_not_initialized_exception;
+
+class mysql_extractor extends base_extractor
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function write_start($table_prefix)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = "#\n";
+ $sql_data .= "# phpBB Backup Script\n";
+ $sql_data .= "# Dump of tables for $table_prefix\n";
+ $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
+ $sql_data .= "#\n";
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_table($table_name)
+ {
+ static $new_extract;
+
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ if ($new_extract === null)
+ {
+ if ($this->db->get_sql_layer() === 'mysqli' || version_compare($this->db->sql_server_info(true), '3.23.20', '>='))
+ {
+ $new_extract = true;
+ }
+ else
+ {
+ $new_extract = false;
+ }
+ }
+
+ if ($new_extract)
+ {
+ $this->new_write_table($table_name);
+ }
+ else
+ {
+ $this->old_write_table($table_name);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_data($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ if ($this->db->get_sql_layer() === 'mysqli')
+ {
+ $this->write_data_mysqli($table_name);
+ }
+ else
+ {
+ $this->write_data_mysql($table_name);
+ }
+ }
+
+ /**
+ * Extracts data from database table (for MySQLi driver)
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ protected function write_data_mysqli($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = mysqli_query($this->db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT);
+ if ($result != false)
+ {
+ $fields_cnt = mysqli_num_fields($result);
+
+ // Get field information
+ $field = mysqli_fetch_fields($result);
+ $field_set = array();
+
+ for ($j = 0; $j < $fields_cnt; $j++)
+ {
+ $field_set[] = $field[$j]->name;
+ }
+
+ $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
+ $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
+ $fields = implode(', ', $field_set);
+ $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
+ $first_set = true;
+ $query_len = 0;
+ $max_len = get_usable_memory();
+
+ while ($row = mysqli_fetch_row($result))
+ {
+ $values = array();
+ if ($first_set)
+ {
+ $query = $sql_data . '(';
+ }
+ else
+ {
+ $query .= ',(';
+ }
+
+ for ($j = 0; $j < $fields_cnt; $j++)
+ {
+ if (!isset($row[$j]) || is_null($row[$j]))
+ {
+ $values[$j] = 'NULL';
+ }
+ else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
+ {
+ $values[$j] = $row[$j];
+ }
+ else
+ {
+ $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
+ }
+ }
+ $query .= implode(', ', $values) . ')';
+
+ $query_len += strlen($query);
+ if ($query_len > $max_len)
+ {
+ $this->flush($query . ";\n\n");
+ $query = '';
+ $query_len = 0;
+ $first_set = true;
+ }
+ else
+ {
+ $first_set = false;
+ }
+ }
+ mysqli_free_result($result);
+
+ // check to make sure we have nothing left to flush
+ if (!$first_set && $query)
+ {
+ $this->flush($query . ";\n\n");
+ }
+ }
+ }
+
+ /**
+ * Extracts data from database table (for MySQL driver)
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ protected function write_data_mysql($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = mysql_unbuffered_query($sql, $this->db->get_db_connect_id());
+
+ if ($result != false)
+ {
+ $fields_cnt = mysql_num_fields($result);
+
+ // Get field information
+ $field = array();
+ for ($i = 0; $i < $fields_cnt; $i++)
+ {
+ $field[] = mysql_fetch_field($result, $i);
+ }
+ $field_set = array();
+
+ for ($j = 0; $j < $fields_cnt; $j++)
+ {
+ $field_set[] = $field[$j]->name;
+ }
+
+ $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
+ $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
+ $fields = implode(', ', $field_set);
+ $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
+ $first_set = true;
+ $query_len = 0;
+ $max_len = get_usable_memory();
+
+ while ($row = mysql_fetch_row($result))
+ {
+ $values = array();
+ if ($first_set)
+ {
+ $query = $sql_data . '(';
+ }
+ else
+ {
+ $query .= ',(';
+ }
+
+ for ($j = 0; $j < $fields_cnt; $j++)
+ {
+ if (!isset($row[$j]) || is_null($row[$j]))
+ {
+ $values[$j] = 'NULL';
+ }
+ else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
+ {
+ $values[$j] = $row[$j];
+ }
+ else
+ {
+ $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
+ }
+ }
+ $query .= implode(', ', $values) . ')';
+
+ $query_len += strlen($query);
+ if ($query_len > $max_len)
+ {
+ $this->flush($query . ";\n\n");
+ $query = '';
+ $query_len = 0;
+ $first_set = true;
+ }
+ else
+ {
+ $first_set = false;
+ }
+ }
+ mysql_free_result($result);
+
+ // check to make sure we have nothing left to flush
+ if (!$first_set && $query)
+ {
+ $this->flush($query . ";\n\n");
+ }
+ }
+ }
+
+ /**
+ * Extracts database table structure (for MySQLi or MySQL 3.23.20+)
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ protected function new_write_table($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql = 'SHOW CREATE TABLE ' . $table_name;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+
+ $sql_data = '# Table: ' . $table_name . "\n";
+ $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
+ $this->flush($sql_data . $row['Create Table'] . ";\n\n");
+
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Extracts database table structure (for MySQL verisons older than 3.23.20)
+ *
+ * @param string $table_name name of the database table
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ protected function old_write_table($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = '# Table: ' . $table_name . "\n";
+ $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
+ $sql_data .= "CREATE TABLE $table_name(\n";
+ $rows = array();
+
+ $sql = "SHOW FIELDS
+ FROM $table_name";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $line = ' ' . $row['Field'] . ' ' . $row['Type'];
+
+ if (!is_null($row['Default']))
+ {
+ $line .= " DEFAULT '{$row['Default']}'";
+ }
+
+ if ($row['Null'] != 'YES')
+ {
+ $line .= ' NOT NULL';
+ }
+
+ if ($row['Extra'] != '')
+ {
+ $line .= ' ' . $row['Extra'];
+ }
+
+ $rows[] = $line;
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql = "SHOW KEYS
+ FROM $table_name";
+
+ $result = $this->db->sql_query($sql);
+
+ $index = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $kname = $row['Key_name'];
+
+ if ($kname != 'PRIMARY')
+ {
+ if ($row['Non_unique'] == 0)
+ {
+ $kname = "UNIQUE|$kname";
+ }
+ }
+
+ if ($row['Sub_part'])
+ {
+ $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
+ }
+ $index[$kname][] = $row['Column_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ foreach ($index as $key => $columns)
+ {
+ $line = ' ';
+
+ if ($key == 'PRIMARY')
+ {
+ $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
+ }
+ else if (strpos($key, 'UNIQUE') === 0)
+ {
+ $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
+ }
+ else if (strpos($key, 'FULLTEXT') === 0)
+ {
+ $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
+ }
+ else
+ {
+ $line .= "KEY $key (" . implode(', ', $columns) . ')';
+ }
+
+ $rows[] = $line;
+ }
+
+ $sql_data .= implode(",\n", $rows);
+ $sql_data .= "\n);\n\n";
+
+ $this->flush($sql_data);
+ }
+}
diff --git a/phpBB/phpbb/db/extractor/oracle_extractor.php b/phpBB/phpbb/db/extractor/oracle_extractor.php
new file mode 100644
index 0000000000..79a991889b
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/oracle_extractor.php
@@ -0,0 +1,263 @@
+<?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\extractor;
+
+use phpbb\db\extractor\exception\extractor_not_initialized_exception;
+
+class oracle_extractor extends base_extractor
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function write_table($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = '-- Table: ' . $table_name . "\n";
+ $sql_data .= "DROP TABLE $table_name\n/\n";
+ $sql_data .= "\nCREATE TABLE $table_name (\n";
+
+ $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT
+ FROM ALL_TAB_COLS
+ WHERE table_name = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+
+ $rows = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $line = ' "' . $row['column_name'] . '" ' . $row['data_type'];
+
+ if ($row['data_type'] !== 'CLOB')
+ {
+ if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR')
+ {
+ $line .= '(' . $row['data_precision'] . ')';
+ }
+ else
+ {
+ $line .= '(' . $row['data_length'] . ')';
+ }
+ }
+
+ if (!empty($row['data_default']))
+ {
+ $line .= ' DEFAULT ' . $row['data_default'];
+ }
+
+ if ($row['nullable'] == 'N')
+ {
+ $line .= ' NOT NULL';
+ }
+ $rows[] = $line;
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
+ FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
+ WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
+ AND B.CONSTRAINT_TYPE = 'P'
+ AND A.TABLE_NAME = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+
+ $primary_key = array();
+ $constraint_name = '';
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $constraint_name = '"' . $row['constraint_name'] . '"';
+ $primary_key[] = '"' . $row['column_name'] . '"';
+ }
+ $this->db->sql_freeresult($result);
+
+ if (sizeof($primary_key))
+ {
+ $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')';
+ }
+
+ $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
+ FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
+ WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
+ AND B.CONSTRAINT_TYPE = 'U'
+ AND A.TABLE_NAME = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+
+ $unique = array();
+ $constraint_name = '';
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $constraint_name = '"' . $row['constraint_name'] . '"';
+ $unique[] = '"' . $row['column_name'] . '"';
+ }
+ $this->db->sql_freeresult($result);
+
+ if (sizeof($unique))
+ {
+ $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')';
+ }
+
+ $sql_data .= implode(",\n", $rows);
+ $sql_data .= "\n)\n/\n";
+
+ $sql = "SELECT A.REFERENCED_NAME, C.*
+ FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C
+ WHERE A.REFERENCED_TYPE = 'SEQUENCE'
+ AND A.NAME = B.TRIGGER_NAME
+ AND B.TABLE_NAME = '{$table_name}'
+ AND C.SEQUENCE_NAME = A.REFERENCED_NAME";
+ $result = $this->db->sql_query($sql);
+
+ $type = $this->request->variable('type', '');
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n";
+ $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\"";
+
+ if ($type == 'full')
+ {
+ $sql_data .= ' START WITH ' . $row['last_number'];
+ }
+
+ $sql_data .= "\n/\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
+ FROM USER_TRIGGERS
+ WHERE TABLE_NAME = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME
+ FROM USER_INDEXES A, USER_IND_COLUMNS B
+ WHERE A.UNIQUENESS = 'NONUNIQUE'
+ AND A.INDEX_NAME = B.INDEX_NAME
+ AND B.TABLE_NAME = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+
+ $index = array();
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $index[$row['index_name']][] = $row['column_name'];
+ }
+
+ foreach ($index as $index_name => $column_names)
+ {
+ $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n";
+ }
+ $this->db->sql_freeresult($result);
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_data($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $ary_type = $ary_name = array();
+
+ // Grab all of the data from current table.
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = $this->db->sql_query($sql);
+
+ $i_num_fields = ocinumcols($result);
+
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $ary_type[$i] = ocicolumntype($result, $i + 1);
+ $ary_name[$i] = ocicolumnname($result, $i + 1);
+ }
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $schema_vals = $schema_fields = array();
+
+ // Build the SQL statement to recreate the data.
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ // Oracle uses uppercase - we use lowercase
+ $str_val = $row[strtolower($ary_name[$i])];
+
+ if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i]))
+ {
+ $str_quote = '';
+ $str_empty = "''";
+ $str_val = sanitize_data_oracle($str_val);
+ }
+ else if (preg_match('#date|timestamp#i', $ary_type[$i]))
+ {
+ if (empty($str_val))
+ {
+ $str_quote = '';
+ }
+ else
+ {
+ $str_quote = "'";
+ }
+ }
+ else
+ {
+ $str_quote = '';
+ $str_empty = 'NULL';
+ }
+
+ if (empty($str_val) && $str_val !== '0')
+ {
+ $str_val = $str_empty;
+ }
+
+ $schema_vals[$i] = $str_quote . $str_val . $str_quote;
+ $schema_fields[$i] = '"' . $ary_name[$i] . '"';
+ }
+
+ // Take the ordered fields and their associated data and build it
+ // into a valid sql statement to recreate that field in the data.
+ $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n";
+
+ $this->flush($sql_data);
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_start($table_prefix)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = "--\n";
+ $sql_data .= "-- phpBB Backup Script\n";
+ $sql_data .= "-- Dump of tables for $table_prefix\n";
+ $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
+ $sql_data .= "--\n";
+ $this->flush($sql_data);
+ }
+}
diff --git a/phpBB/phpbb/db/extractor/postgres_extractor.php b/phpBB/phpbb/db/extractor/postgres_extractor.php
new file mode 100644
index 0000000000..a98e39621c
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/postgres_extractor.php
@@ -0,0 +1,339 @@
+<?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\extractor;
+
+use phpbb\db\extractor\exception\extractor_not_initialized_exception;
+
+class postgres_extractor extends base_extractor
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function write_start($table_prefix)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = "--\n";
+ $sql_data .= "-- phpBB Backup Script\n";
+ $sql_data .= "-- Dump of tables for $table_prefix\n";
+ $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
+ $sql_data .= "--\n";
+ $sql_data .= "BEGIN TRANSACTION;\n";
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_table($table_name)
+ {
+ static $domains_created = array();
+
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default
+ FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b
+ WHERE a.domain_name = b.domain_name
+ AND b.table_name = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (empty($domains_created[$row['domain_name']]))
+ {
+ $domains_created[$row['domain_name']] = true;
+ //$sql_data = "DROP DOMAIN {$row['domain_name']};\n";
+ $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}";
+ if (!empty($row['character_maximum_length']))
+ {
+ $sql_data .= '(' . $row['character_maximum_length'] . ')';
+ }
+ $sql_data .= ' NOT NULL';
+ if (!empty($row['domain_default']))
+ {
+ $sql_data .= ' DEFAULT ' . $row['domain_default'];
+ }
+ $this->flush($sql_data . ";\n");
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql_data = '-- Table: ' . $table_name . "\n";
+ $sql_data .= "DROP TABLE $table_name;\n";
+ // PGSQL does not "tightly" bind sequences and tables, we must guess...
+ $sql = "SELECT relname
+ FROM pg_class
+ WHERE relkind = 'S'
+ AND relname = '{$table_name}_seq'";
+ $result = $this->db->sql_query($sql);
+ // We don't even care about storing the results. We already know the answer if we get rows back.
+ if ($this->db->sql_fetchrow($result))
+ {
+ $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n";
+ $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull
+ FROM pg_class c, pg_attribute a, pg_type t
+ WHERE c.relname = '" . $this->db->sql_escape($table_name) . "'
+ AND a.attnum > 0
+ AND a.attrelid = c.oid
+ AND a.atttypid = t.oid
+ ORDER BY a.attnum";
+ $result = $this->db->sql_query($field_query);
+
+ $sql_data .= "CREATE TABLE $table_name(\n";
+ $lines = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Get the data from the table
+ $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
+ FROM pg_attrdef d, pg_class c
+ WHERE (c.relname = '" . $this->db->sql_escape($table_name) . "')
+ AND (c.oid = d.adrelid)
+ AND d.adnum = " . $row['attnum'];
+ $def_res = $this->db->sql_query($sql_get_default);
+ $def_row = $this->db->sql_fetchrow($def_res);
+ $this->db->sql_freeresult($def_res);
+
+ if (empty($def_row))
+ {
+ unset($row['rowdefault']);
+ }
+ else
+ {
+ $row['rowdefault'] = $def_row['rowdefault'];
+ }
+
+ if ($row['type'] == 'bpchar')
+ {
+ // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
+ $row['type'] = 'char';
+ }
+
+ $line = ' ' . $row['field'] . ' ' . $row['type'];
+
+ if (strpos($row['type'], 'char') !== false)
+ {
+ if ($row['lengthvar'] > 0)
+ {
+ $line .= '(' . ($row['lengthvar'] - 4) . ')';
+ }
+ }
+
+ if (strpos($row['type'], 'numeric') !== false)
+ {
+ $line .= '(';
+ $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
+ $line .= ')';
+ }
+
+ if (isset($row['rowdefault']))
+ {
+ $line .= ' DEFAULT ' . $row['rowdefault'];
+ }
+
+ if ($row['notnull'] == 't')
+ {
+ $line .= ' NOT NULL';
+ }
+
+ $lines[] = $line;
+ }
+ $this->db->sql_freeresult($result);
+
+ // Get the listing of primary keys.
+ $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key
+ FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (ia.attrelid = i.indexrelid)
+ AND (ta.attrelid = bc.oid)
+ AND (bc.relname = '" . $this->db->sql_escape($table_name) . "')
+ AND (ta.attrelid = i.indrelid)
+ AND (ta.attnum = i.indkey[ia.attnum-1])
+ ORDER BY index_name, tab_name, column_name";
+
+ $result = $this->db->sql_query($sql_pri_keys);
+
+ $index_create = $index_rows = $primary_key = array();
+
+ // We do this in two steps. It makes placing the comma easier
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['primary_key'] == 't')
+ {
+ $primary_key[] = $row['column_name'];
+ $primary_key_name = $row['index_name'];
+ }
+ else
+ {
+ // We have to store this all this info because it is possible to have a multi-column key...
+ // we can loop through it again and build the statement
+ $index_rows[$row['index_name']]['table'] = $table_name;
+ $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false;
+ $index_rows[$row['index_name']]['column_names'][] = $row['column_name'];
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (!empty($index_rows))
+ {
+ foreach ($index_rows as $idx_name => $props)
+ {
+ $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");";
+ }
+ }
+
+ if (!empty($primary_key))
+ {
+ $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")";
+ }
+
+ // Generate constraint clauses for CHECK constraints
+ $sql_checks = "SELECT conname as index_name, consrc
+ FROM pg_constraint, pg_class bc
+ WHERE conrelid = bc.oid
+ AND bc.relname = '" . $this->db->sql_escape($table_name) . "'
+ AND NOT EXISTS (
+ SELECT *
+ FROM pg_constraint as c, pg_inherits as i
+ WHERE i.inhrelid = pg_constraint.conrelid
+ AND c.conname = pg_constraint.conname
+ AND c.consrc = pg_constraint.consrc
+ AND c.conrelid = i.inhparent
+ )";
+ $result = $this->db->sql_query($sql_checks);
+
+ // Add the constraints to the sql file.
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!is_null($row['consrc']))
+ {
+ $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql_data .= implode(", \n", $lines);
+ $sql_data .= "\n);\n";
+
+ if (!empty($index_create))
+ {
+ $sql_data .= implode("\n", $index_create) . "\n\n";
+ }
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_data($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ // Grab all of the data from current table.
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = $this->db->sql_query($sql);
+
+ $i_num_fields = pg_num_fields($result);
+ $seq = '';
+
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $ary_type[] = pg_field_type($result, $i);
+ $ary_name[] = pg_field_name($result, $i);
+
+ $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
+ FROM pg_attrdef d, pg_class c
+ WHERE (c.relname = '{$table_name}')
+ AND (c.oid = d.adrelid)
+ AND d.adnum = " . strval($i + 1);
+ $result2 = $this->db->sql_query($sql);
+ if ($row = $this->db->sql_fetchrow($result2))
+ {
+ // Determine if we must reset the sequences
+ if (strpos($row['rowdefault'], "nextval('") === 0)
+ {
+ $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n";
+ }
+ }
+ }
+
+ $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n");
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $schema_vals = array();
+
+ // Build the SQL statement to recreate the data.
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $str_val = $row[$ary_name[$i]];
+
+ if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
+ {
+ $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val));
+ $str_empty = '';
+ }
+ else
+ {
+ $str_empty = '\N';
+ }
+
+ if (empty($str_val) && $str_val !== '0')
+ {
+ $str_val = $str_empty;
+ }
+
+ $schema_vals[] = $str_val;
+ }
+
+ // Take the ordered fields and their associated data and build it
+ // into a valid sql statement to recreate that field in the data.
+ $this->flush(implode("\t", $schema_vals) . "\n");
+ }
+ $this->db->sql_freeresult($result);
+ $this->flush("\\.\n");
+
+ // Write out the sequence statements
+ $this->flush($seq);
+ }
+
+ /**
+ * Writes closing line(s) to database backup
+ *
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_end()
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $this->flush("COMMIT;\n");
+ parent::write_end();
+ }
+}
diff --git a/phpBB/phpbb/db/extractor/sqlite3_extractor.php b/phpBB/phpbb/db/extractor/sqlite3_extractor.php
new file mode 100644
index 0000000000..ce8da6a652
--- /dev/null
+++ b/phpBB/phpbb/db/extractor/sqlite3_extractor.php
@@ -0,0 +1,151 @@
+<?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\extractor;
+
+use phpbb\db\extractor\exception\extractor_not_initialized_exception;
+
+class sqlite3_extractor extends base_extractor
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function write_start($table_prefix)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = "--\n";
+ $sql_data .= "-- phpBB Backup Script\n";
+ $sql_data .= "-- Dump of tables for $table_prefix\n";
+ $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
+ $sql_data .= "--\n";
+ $sql_data .= "BEGIN TRANSACTION;\n";
+ $this->flush($sql_data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_table($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $sql_data = '-- Table: ' . $table_name . "\n";
+ $sql_data .= "DROP TABLE $table_name;\n";
+
+ $sql = "SELECT sql
+ FROM sqlite_master
+ WHERE type = 'table'
+ AND name = '" . $this->db->sql_escape($table_name) . "'
+ ORDER BY name ASC;";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ // Create Table
+ $sql_data .= $row['sql'] . ";\n";
+
+ $result = $this->db->sql_query("PRAGMA index_list('" . $this->db->sql_escape($table_name) . "');");
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (strpos($row['name'], 'autoindex') !== false)
+ {
+ continue;
+ }
+
+ $result2 = $this->db->sql_query("PRAGMA index_info('" . $this->db->sql_escape($row['name']) . "');");
+
+ $fields = array();
+ while ($row2 = $this->db->sql_fetchrow($result2))
+ {
+ $fields[] = $row2['name'];
+ }
+ $this->db->sql_freeresult($result2);
+
+ $sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->flush($sql_data . "\n");
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write_data($table_name)
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $result = $this->db->sql_query("PRAGMA table_info('" . $this->db->sql_escape($table_name) . "');");
+
+ $col_types = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $col_types[$row['name']] = $row['type'];
+ }
+ $this->db->sql_freeresult($result);
+
+ $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
+
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ foreach ($row as $column_name => $column_data)
+ {
+ if (is_null($column_data))
+ {
+ $row[$column_name] = 'NULL';
+ }
+ else if ($column_data === '')
+ {
+ $row[$column_name] = "''";
+ }
+ else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false)
+ {
+ $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
+ }
+ }
+ $this->flush($sql_insert . implode(', ', $row) . ");\n");
+ }
+ }
+
+ /**
+ * Writes closing line(s) to database backup
+ *
+ * @return null
+ * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
+ */
+ public function write_end()
+ {
+ if (!$this->is_initialized)
+ {
+ throw new extractor_not_initialized_exception();
+ }
+
+ $this->flush("COMMIT;\n");
+ parent::write_end();
+ }
+}
diff --git a/phpBB/phpbb/db/html_migrator_output_handler.php b/phpBB/phpbb/db/html_migrator_output_handler.php
deleted file mode 100644
index e37c667463..0000000000
--- a/phpBB/phpbb/db/html_migrator_output_handler.php
+++ /dev/null
@@ -1,48 +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\db;
-
-use phpbb\user;
-
-class html_migrator_output_handler implements migrator_output_handler_interface
-{
- /**
- * User object.
- *
- * @var user
- */
- private $user;
-
- /**
- * Constructor
- *
- * @param user $user User object
- */
- public function __construct(user $user)
- {
- $this->user = $user;
- }
-
- /**
- * {@inheritdoc}
- */
- public function write($message, $verbosity)
- {
- if ($verbosity <= migrator_output_handler_interface::VERBOSITY_VERBOSE)
- {
- $final_message = call_user_func_array(array($this->user, 'lang'), $message);
- echo $final_message . "<br />\n";
- }
- }
-}
diff --git a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php b/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php
deleted file mode 100644
index 94c293dc45..0000000000
--- a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php
+++ /dev/null
@@ -1,95 +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\db;
-
-use phpbb\user;
-
-class log_wrapper_migrator_output_handler implements migrator_output_handler_interface
-{
- /**
- * User object.
- *
- * @var user
- */
- protected $user;
-
- /**
- * A migrator output handler
- *
- * @var migrator_output_handler_interface
- */
- protected $migrator;
-
- /**
- * Log file handle
- * @var resource
- */
- protected $file_handle = false;
-
- /**
- * Constructor
- *
- * @param user $user User object
- * @param migrator_output_handler_interface $migrator Migrator output handler
- * @param string $log_file File to log to
- */
- public function __construct(user $user, migrator_output_handler_interface $migrator, $log_file)
- {
- $this->user = $user;
- $this->migrator = $migrator;
- $this->file_open($log_file);
- }
-
- /**
- * Open file for logging
- *
- * @param string $file File to open
- */
- protected function file_open($file)
- {
- if (phpbb_is_writable(dirname($file)))
- {
- $this->file_handle = fopen($file, 'w');
- }
- else
- {
- throw new \RuntimeException('Unable to write to migrator log file');
- }
- }
-
- /**
- * {@inheritdoc}
- */
- public function write($message, $verbosity)
- {
- $this->migrator->write($message, $verbosity);
-
- if ($this->file_handle !== false)
- {
- $translated_message = call_user_func_array(array($this->user, 'lang'), $message) . "\n";
-
- if ($verbosity <= migrator_output_handler_interface::VERBOSITY_NORMAL)
- {
- $translated_message = '[INFO] ' . $translated_message;
- }
- else
- {
- $translated_message = '[DEBUG] ' . $translated_message;
- }
-
- fwrite($this->file_handle, $translated_message);
- fflush($this->file_handle);
- }
- }
-}
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
index 003ccf8f18..084d00a13a 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php
@@ -57,7 +57,9 @@ class release_3_0_5_rc1 extends container_aware_migration
public function hash_old_passwords()
{
+ /* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $this->container->get('passwords.manager');
+
$sql = 'SELECT user_id, user_password
FROM ' . $this->table_prefix . 'users
WHERE user_pass_convert = 1';
@@ -116,7 +118,7 @@ class release_3_0_5_rc1 extends container_aware_migration
$result = $this->db->sql_query($sql);
// Skip first row, this is our original auth option we want to preserve
- $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_fetchrow($result);
while ($row = $this->db->sql_fetchrow($result))
{
diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php
index 06e46d522f..5f928df47c 100644
--- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php
+++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_9_rc1.php
@@ -34,7 +34,7 @@ class release_3_0_9_rc1 extends \phpbb\db\migration\migration
// this column was removed from the database updater
// after 3.0.9-RC3 was released. It might still exist
// in 3.0.9-RCX installations and has to be dropped as
- // soon as the db_tools class is capable of properly
+ // soon as the \phpbb\db\tools\tools class is capable of properly
// removing a primary key.
// 'attempt_id' => array('UINT', NULL, 'auto_increment'),
'attempt_ip' => array('VCHAR:40', ''),
diff --git a/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php
index 0ca4f2f19c..725c57ca86 100644
--- a/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php
+++ b/phpBB/phpbb/db/migration/data/v310/acp_prune_users_module.php
@@ -13,7 +13,7 @@
namespace phpbb\db\migration\data\v310;
-class acp_prune_users_module extends \phpbb\db\migration\migration
+class acp_prune_users_module extends \phpbb\db\migration\container_aware_migration
{
public function effectively_installed()
{
@@ -70,12 +70,7 @@ class acp_prune_users_module extends \phpbb\db\migration\migration
$acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
- if (!class_exists('\acp_modules'))
- {
- include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
- }
- $module_manager = new \acp_modules();
- $module_manager->module_class = 'acp';
- $module_manager->move_module($acp_prune_users_id, $acp_cat_users_id);
+ $module_manager = $this->container->get('module.manager');
+ $module_manager->move_module($acp_prune_users_id, $acp_cat_users_id, 'acp');
}
}
diff --git a/phpBB/phpbb/db/migration/data/v310/dev.php b/phpBB/phpbb/db/migration/data/v310/dev.php
index f037191c2a..250258eea7 100644
--- a/phpBB/phpbb/db/migration/data/v310/dev.php
+++ b/phpBB/phpbb/db/migration/data/v310/dev.php
@@ -13,7 +13,7 @@
namespace phpbb\db\migration\data\v310;
-class dev extends \phpbb\db\migration\migration
+class dev extends \phpbb\db\migration\container_aware_migration
{
public function effectively_installed()
{
@@ -204,18 +204,13 @@ class dev extends \phpbb\db\migration\migration
$language_management_module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
- if (!class_exists('acp_modules'))
- {
- include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
- }
// acp_modules calls adm_back_link, which is undefined at this point
if (!function_exists('adm_back_link'))
{
include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext);
}
- $module_manager = new \acp_modules();
- $module_manager->module_class = 'acp';
- $module_manager->move_module($language_module_id, $language_management_module_id);
+ $module_manager = $this->container->get('module.manager');
+ $module_manager->move_module($language_module_id, $language_management_module_id, 'acp');
}
public function update_ucp_pm_basename()
diff --git a/phpBB/phpbb/db/migration/data/v310/timezone.php b/phpBB/phpbb/db/migration/data/v310/timezone.php
index 1f6b47ad50..03a8d1ab34 100644
--- a/phpBB/phpbb/db/migration/data/v310/timezone.php
+++ b/phpBB/phpbb/db/migration/data/v310/timezone.php
@@ -103,7 +103,7 @@ class timezone extends \phpbb\db\migration\migration
*/
public function convert_phpbb30_timezone($timezone, $dst)
{
- $offset = $timezone + $dst;
+ $offset = (float) $timezone + (int) $dst;
switch ($timezone)
{
diff --git a/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php b/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php
index 854ed1f568..14b7b7b0f6 100644
--- a/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php
+++ b/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php
@@ -45,7 +45,6 @@ class update_custom_bbcodes_with_idn extends \phpbb\db\migration\migration
$sql_ary = array();
while ($row = $this->db->sql_fetchrow($result))
{
- $data = array();
if (preg_match('/(URL|LOCAL_URL|RELATIVE_URL)/', $row['bbcode_match']))
{
$data = $bbcodes->build_regexp($row['bbcode_match'], $row['bbcode_tpl']);
diff --git a/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php b/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php
new file mode 100644
index 0000000000..726822bc71
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.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\v320;
+
+class allowed_schemes_links extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('allowed_schemes_links', 'http,https,ftp')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php b/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php
new file mode 100644
index 0000000000..7afecb884b
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php
@@ -0,0 +1,43 @@
+<?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\v320;
+
+class announce_global_permission extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ $sql = 'SELECT auth_option_id
+ FROM ' . ACL_OPTIONS_TABLE . "
+ WHERE auth_option = 'f_announce_global'";
+ $result = $this->db->sql_query($sql);
+ $auth_option_id = $this->db->sql_fetchfield('auth_option_id');
+ $this->db->sql_freeresult($result);
+
+ return $auth_option_id !== false;
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('permission.add', array('f_announce_global', false, 'f_announce')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/default_data_type_ids.php b/phpBB/phpbb/db/migration/data/v320/default_data_type_ids.php
new file mode 100644
index 0000000000..65e5b3fa73
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/default_data_type_ids.php
@@ -0,0 +1,361 @@
+<?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\v320;
+
+class default_data_type_ids extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\v320a2',
+ '\phpbb\db\migration\data\v320\oauth_states',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'acl_users' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'attachments' => array(
+ 'attach_id' => array('ULINT', null, 'auto_increment'),
+ 'post_msg_id' => array('ULINT', 0),
+ 'poster_id' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'banlist' => array(
+ 'ban_id' => array('ULINT', null, 'auto_increment'),
+ 'ban_userid' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'bookmarks' => array(
+ 'topic_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'bots' => array(
+ 'bot_id' => array('ULINT', null, 'auto_increment'),
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'drafts' => array(
+ 'draft_id' => array('ULINT', null, 'auto_increment'),
+ 'user_id' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'forums' => array(
+ 'forum_last_post_id' => array('ULINT', 0),
+ 'forum_last_poster_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'forums_access' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'forums_track' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'forums_watch' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'log' => array(
+ 'log_id' => array('ULINT', null, 'auto_increment'),
+ 'post_id' => array('ULINT', 0),
+ 'reportee_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'login_attempts' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'moderator_cache' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'notifications' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'oauth_accounts' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'oauth_states' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'oauth_tokens' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'poll_options' => array(
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'poll_votes' => array(
+ 'topic_id' => array('ULINT', 0),
+ 'vote_user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'posts' => array(
+ 'post_id' => array('ULINT', null, 'auto_increment'),
+ 'poster_id' => array('ULINT', 0),
+ 'post_delete_user' => array('ULINT', 0),
+ 'post_edit_user' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'privmsgs' => array(
+ 'author_id' => array('ULINT', 0),
+ 'message_edit_user' => array('ULINT', 0),
+ 'msg_id' => array('ULINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'privmsgs_folder' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'privmsgs_rules' => array(
+ 'rule_user_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'privmsgs_to' => array(
+ 'author_id' => array('ULINT', 0),
+ 'msg_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'reports' => array(
+ 'report_id' => array('ULINT', 0),
+ 'pm_id' => array('ULINT', 0),
+ 'post_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'search_wordlist' => array(
+ 'word_id' => array('ULINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'search_wordmatch' => array(
+ 'post_id' => array('ULINT', 0),
+ 'word_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'sessions' => array(
+ 'session_user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'sessions_keys' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'topics' => array(
+ 'topic_id' => array('ULINT', null, 'auto_increment'),
+ 'topic_poster' => array('ULINT', 0),
+ 'topic_first_post_id' => array('ULINT', 0),
+ 'topic_last_post_id' => array('ULINT', 0),
+ 'topic_last_poster_id' => array('ULINT', 0),
+ 'topic_moved_id' => array('ULINT', 0),
+ 'topic_delete_user' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'topics_track' => array(
+ 'user_id' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'topics_posted' => array(
+ 'user_id' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'topics_watch' => array(
+ 'user_id' => array('ULINT', 0),
+ 'topic_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'user_notifications' => array(
+ 'item_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'user_group' => array(
+ 'user_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'users' => array(
+ 'user_id' => array('ULINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'warnings' => array(
+ 'log_id' => array('ULINT', 0),
+ 'user_id' => array('ULINT', 0),
+ 'post_id' => array('ULINT', 0),
+ ),
+ $this->table_prefix . 'words' => array(
+ 'word_id' => array('ULINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'zebra' => array(
+ 'user_id' => array('ULINT', 0),
+ 'zebra_id' => array('ULINT', 0),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'acl_users' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'attachments' => array(
+ 'attach_id' => array('UINT', null, 'auto_increment'),
+ 'post_msg_id' => array('UINT', 0),
+ 'poster_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'banlist' => array(
+ 'ban_id' => array('UINT', null, 'auto_increment'),
+ 'ban_userid' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'bookmarks' => array(
+ 'topic_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'bots' => array(
+ 'bot_id' => array('UINT', null, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'drafts' => array(
+ 'draft_id' => array('UINT', null, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'forums' => array(
+ 'forum_last_post_id' => array('UINT', 0),
+ 'forum_last_poster_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'forums_access' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'forums_track' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'forums_watch' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'log' => array(
+ 'log_id' => array('UINT', null, 'auto_increment'),
+ 'post_id' => array('UINT', 0),
+ 'reportee_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'login_attempts' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'moderator_cache' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'notifications' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'oauth_accounts' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'oauth_states' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'oauth_tokens' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'poll_options' => array(
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'poll_votes' => array(
+ 'topic_id' => array('UINT', 0),
+ 'vote_user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'posts' => array(
+ 'post_id' => array('UINT', null, 'auto_increment'),
+ 'poster_id' => array('UINT', 0),
+ 'post_delete_user' => array('UINT', 0),
+ 'post_edit_user' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'privmsgs' => array(
+ 'author_id' => array('UINT', 0),
+ 'message_edit_user' => array('UINT', 0),
+ 'msg_id' => array('UINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'privmsgs_folder' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'privmsgs_rules' => array(
+ 'rule_user_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'privmsgs_to' => array(
+ 'author_id' => array('UINT', 0),
+ 'msg_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'reports' => array(
+ 'report_id' => array('UINT', 0),
+ 'pm_id' => array('UINT', 0),
+ 'post_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'search_wordlist' => array(
+ 'word_id' => array('UINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'search_wordmatch' => array(
+ 'post_id' => array('UINT', 0),
+ 'word_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'sessions' => array(
+ 'session_user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'sessions_keys' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'topics' => array(
+ 'topic_id' => array('UINT', null, 'auto_increment'),
+ 'topic_poster' => array('UINT', 0),
+ 'topic_first_post_id' => array('UINT', 0),
+ 'topic_last_post_id' => array('UINT', 0),
+ 'topic_last_poster_id' => array('UINT', 0),
+ 'topic_moved_id' => array('UINT', 0),
+ 'topic_delete_user' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'topics_track' => array(
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'topics_posted' => array(
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'topics_watch' => array(
+ 'user_id' => array('UINT', 0),
+ 'topic_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'user_notifications' => array(
+ 'item_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'user_group' => array(
+ 'user_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'users' => array(
+ 'user_id' => array('UINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'warnings' => array(
+ 'log_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'post_id' => array('UINT', 0),
+ ),
+ $this->table_prefix . 'words' => array(
+ 'word_id' => array('UINT', null, 'auto_increment'),
+ ),
+ $this->table_prefix . 'zebra' => array(
+ 'user_id' => array('UINT', 0),
+ 'zebra_id' => array('UINT', 0),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/dev.php b/phpBB/phpbb/db/migration/data/v320/dev.php
new file mode 100644
index 0000000000..ad2da3c1f4
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/dev.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\v320;
+
+class dev extends \phpbb\db\migration\container_aware_migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-dev', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v316',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-dev')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/font_awesome_update.php b/phpBB/phpbb/db/migration/data/v320/font_awesome_update.php
new file mode 100644
index 0000000000..817b638037
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/font_awesome_update.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\v320;
+
+class font_awesome_update extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function effectively_installed()
+ {
+ return isset($this->config['load_font_awesome_url']);
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('load_font_awesome_url', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/icons_alt.php b/phpBB/phpbb/db/migration/data/v320/icons_alt.php
new file mode 100644
index 0000000000..80132e579e
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/icons_alt.php
@@ -0,0 +1,46 @@
+<?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\v320;
+
+class icons_alt extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'icons' => array(
+ 'icons_alt' => array('VCHAR', '', 'after' => 'icons_height'),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'icons' => array(
+ 'icons_alt',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/log_post_id.php b/phpBB/phpbb/db/migration/data/v320/log_post_id.php
new file mode 100644
index 0000000000..ead53c8138
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/log_post_id.php
@@ -0,0 +1,46 @@
+<?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\v320;
+
+class log_post_id extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'log' => array(
+ 'post_id' => array('UINT', 0, 'after' => 'topic_id'),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'log' => array(
+ 'post_id',
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/notifications_board.php b/phpBB/phpbb/db/migration/data/v320/notifications_board.php
new file mode 100644
index 0000000000..ac1b3a0f2c
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/notifications_board.php
@@ -0,0 +1,75 @@
+<?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\v320;
+
+class notifications_board extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('allow_board_notifications', 1)),
+ array('custom', array(array($this, 'update_user_subscriptions'))),
+ array('custom', array(array($this, 'update_module'))),
+ );
+ }
+
+ public function update_module()
+ {
+ $sql = 'UPDATE ' . MODULES_TABLE . "
+ SET module_auth = 'cfg_allow_board_notifications'
+ WHERE module_basename = 'ucp_notifications'
+ AND module_mode = 'notification_list'";
+ $this->sql_query($sql);
+ }
+
+ public function update_user_subscriptions()
+ {
+ $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . "
+ SET method = 'notification.method.board'
+ WHERE method = ''";
+ $this->sql_query($sql);
+ }
+
+ public function revert_data()
+ {
+ return array(
+ array('custom', array(array($this, 'revert_user_subscriptions'))),
+ array('custom', array(array($this, 'revert_module'))),
+ );
+ }
+
+ public function revert_user_subscriptions()
+ {
+ $sql = 'UPDATE ' . USER_NOTIFICATIONS_TABLE . "
+ SET method = ''
+ WHERE method = 'notification.method.board'";
+ $this->sql_query($sql);
+ }
+
+ public function revert_module()
+ {
+ $sql = 'UPDATE ' . MODULES_TABLE . "
+ SET auth = ''
+ WHERE module_basename = 'ucp_notifications'
+ AND module_mode = 'notification_list'";
+ $this->sql_query($sql);
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/oauth_states.php b/phpBB/phpbb/db/migration/data/v320/oauth_states.php
new file mode 100644
index 0000000000..22ab2dabb3
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/oauth_states.php
@@ -0,0 +1,56 @@
+<?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\v320;
+
+class oauth_states extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\auth_provider_oauth');
+ }
+
+ public function effectively_installed()
+ {
+ return $this->db_tools->sql_table_exists($this->table_prefix . 'oauth_states');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'add_tables' => array(
+ $this->table_prefix . 'oauth_states' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'session_id' => array('CHAR:32', ''),
+ 'provider' => array('VCHAR', ''),
+ 'oauth_state' => array('VCHAR', ''),
+ ),
+ 'KEYS' => array(
+ 'user_id' => array('INDEX', 'user_id'),
+ 'provider' => array('INDEX', 'provider'),
+ ),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'oauth_states',
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/remote_upload_validation.php b/phpBB/phpbb/db/migration/data/v320/remote_upload_validation.php
new file mode 100644
index 0000000000..d61f6b96fd
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/remote_upload_validation.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\v320;
+
+class remote_upload_validation extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\v320a2',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('remote_upload_verify', '0')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php
new file mode 100644
index 0000000000..c14d31f1c0
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php
@@ -0,0 +1,90 @@
+<?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\v320;
+
+class remove_outdated_media extends \phpbb\db\migration\migration
+{
+ protected $cat_id = array(
+ ATTACHMENT_CATEGORY_WM,
+ ATTACHMENT_CATEGORY_RM,
+ ATTACHMENT_CATEGORY_QUICKTIME,
+ );
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'change_extension_group'))),
+ );
+ }
+
+ public function change_extension_group()
+ {
+ // select group ids of outdated media
+ $sql = 'SELECT group_id
+ FROM ' . EXTENSION_GROUPS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('cat_id', $this->cat_id);
+ $result = $this->db->sql_query($sql);
+
+ $group_ids = array();
+ while ($group_id = (int) $this->db->sql_fetchfield('group_id'))
+ {
+ $group_ids[] = $group_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ // nothing to do, admin has removed all the outdated media extension groups
+ if (empty($group_ids))
+ {
+ return true;
+ }
+
+ // get the group id of downloadable files
+ $sql = 'SELECT group_id
+ FROM ' . EXTENSION_GROUPS_TABLE . "
+ WHERE group_name = 'DOWNLOADABLE_FILES'";
+ $result = $this->db->sql_query($sql);
+ $download_id = (int) $this->db->sql_fetchfield('group_id');
+ $this->db->sql_freeresult($result);
+
+ if (empty($download_id))
+ {
+ $sql = 'UPDATE ' . EXTENSIONS_TABLE . '
+ SET group_id = 0
+ WHERE ' . $this->db->sql_in_set('group_id', $group_ids);
+ }
+ else
+ {
+ // move outdated media extensions to downloadable files
+ $sql = 'UPDATE ' . EXTENSIONS_TABLE . "
+ SET group_id = $download_id" . '
+ WHERE ' . $this->db->sql_in_set('group_id', $group_ids);
+ }
+
+ $result = $this->db->sql_query($sql);
+ $this->db->sql_freeresult($result);
+
+ // 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);
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php b/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php
new file mode 100644
index 0000000000..1cb9070bf9
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php
@@ -0,0 +1,152 @@
+<?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\v320;
+
+class remove_profilefield_wlm extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'pf_phpbb_wlm',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'profile_fields_data' => array(
+ 'pf_phpbb_wlm' => array('VCHAR', ''),
+ ),
+ ),
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'delete_custom_profile_field_data'))),
+ );
+ }
+
+ public function revert_data()
+ {
+ return array(
+ array('custom', array(array($this, 'create_custom_field'))),
+ );
+ }
+
+ public function delete_custom_profile_field_data()
+ {
+ $field_id = $this->get_custom_profile_field_id();
+
+ $sql = 'DELETE FROM ' . PROFILE_FIELDS_TABLE . '
+ WHERE field_id = ' . (int) $field_id;
+ $this->db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . '
+ WHERE field_id = ' . (int) $field_id;
+ $this->db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . '
+ WHERE field_id = ' . (int) $field_id;
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Get custom profile field id
+ * @return int custom profile filed id
+ */
+ public function get_custom_profile_field_id()
+ {
+ $sql = 'SELECT field_id
+ FROM ' . PROFILE_FIELDS_TABLE . "
+ WHERE field_name = 'phpbb_wlm'";
+ $result = $this->db->sql_query($sql);
+ $field_id = (int) $this->db->sql_fetchfield('field_id');
+ $this->db->sql_freeresult($result);
+
+ return $field_id;
+ }
+
+ public function create_custom_field()
+ {
+ $sql = 'SELECT MAX(field_order) as max_field_order
+ FROM ' . PROFILE_FIELDS_TABLE;
+ $result = $this->db->sql_query($sql);
+ $max_field_order = (int) $this->db->sql_fetchfield('max_field_order');
+ $this->db->sql_freeresult($result);
+
+ $sql_ary = array(
+ 'field_name' => 'phpbb_wlm',
+ 'field_type' => 'profilefields.type.string',
+ 'field_ident' => 'phpbb_wlm',
+ 'field_length' => '40',
+ 'field_minlen' => '5',
+ 'field_maxlen' => '255',
+ 'field_novalue' => '',
+ 'field_default_value' => '',
+ 'field_validation' => '.*',
+ 'field_required' => 0,
+ 'field_show_novalue' => 0,
+ 'field_show_on_reg' => 0,
+ 'field_show_on_pm' => 1,
+ 'field_show_on_vt' => 1,
+ 'field_show_on_ml' => 0,
+ 'field_show_profile' => 1,
+ 'field_hide' => 0,
+ 'field_no_view' => 0,
+ 'field_active' => 1,
+ 'field_is_contact' => 1,
+ 'field_contact_desc' => '',
+ 'field_contact_url' => '',
+ 'field_order' => $max_field_order + 1,
+ );
+
+ $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
+ $this->db->sql_query($sql);
+ $field_id = (int) $this->db->sql_nextid();
+
+ $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE);
+
+ $sql = 'SELECT lang_id
+ FROM ' . LANG_TABLE;
+ $result = $this->db->sql_query($sql);
+ $lang_name = 'WLM';
+ while ($lang_id = (int) $this->db->sql_fetchfield('lang_id'))
+ {
+ $insert_buffer->insert(array(
+ 'field_id' => (int) $field_id,
+ 'lang_id' => (int) $lang_id,
+ 'lang_name' => $lang_name,
+ 'lang_explain' => '',
+ 'lang_default_value' => '',
+ ));
+ }
+ $this->db->sql_freeresult($result);
+
+ $insert_buffer->flush();
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/report_id_auto_increment.php b/phpBB/phpbb/db/migration/data/v320/report_id_auto_increment.php
new file mode 100644
index 0000000000..6e81baefb9
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/report_id_auto_increment.php
@@ -0,0 +1,46 @@
+<?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\v320;
+
+class report_id_auto_increment extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\default_data_type_ids',
+ );
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'reports' => array(
+ 'report_id' => array('ULINT', null, 'auto_increment'),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'change_columns' => array(
+ $this->table_prefix . 'reports' => array(
+ 'report_id' => array('ULINT', 0),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/text_reparser.php b/phpBB/phpbb/db/migration/data/v320/text_reparser.php
new file mode 100644
index 0000000000..03c5d39fe4
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/text_reparser.php
@@ -0,0 +1,118 @@
+<?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\v320;
+
+use phpbb\textreparser\manager;
+use phpbb\textreparser\reparser_interface;
+
+class text_reparser extends \phpbb\db\migration\container_aware_migration
+{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v310\contact_admin_form',
+ '\phpbb\db\migration\data\v320\allowed_schemes_links',
+ );
+ }
+
+ public function effectively_installed()
+ {
+ return isset($this->config['reparse_lock']);
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('reparse_lock', 0, true)),
+ array('config.add', array('text_reparser.pm_text_cron_interval', 10)),
+ array('config.add', array('text_reparser.pm_text_last_cron', 0)),
+ array('config.add', array('text_reparser.poll_option_cron_interval', 10)),
+ array('config.add', array('text_reparser.poll_option_last_cron', 0)),
+ array('config.add', array('text_reparser.poll_title_cron_interval', 10)),
+ array('config.add', array('text_reparser.poll_title_last_cron', 0)),
+ array('config.add', array('text_reparser.post_text_cron_interval', 10)),
+ array('config.add', array('text_reparser.post_text_last_cron', 0)),
+ array('config.add', array('text_reparser.user_signature_cron_interval', 10)),
+ array('config.add', array('text_reparser.user_signature_last_cron', 0)),
+ array('custom', array(array($this, 'reparse'))),
+ );
+ }
+
+ public function reparse($resume_data)
+ {
+ /** @var manager $reparser_manager */
+ $reparser_manager = $this->container->get('text_reparser.manager');
+
+ /** @var reparser_interface[] $reparsers */
+ $reparsers = $this->container->get('text_reparser_collection');
+
+ // Initialize all reparsers
+ foreach ($reparsers as $name => $reparser)
+ {
+ $reparser_manager->update_resume_data($name, 1, $reparser->get_max_id(), 100);
+ }
+
+ // Sometimes a cron job is too much
+ $limit = 100;
+ $fast_reparsers = array(
+ 'text_reparser.contact_admin_info',
+ 'text_reparser.forum_description',
+ 'text_reparser.forum_rules',
+ 'text_reparser.group_description',
+ );
+
+ if (!is_array($resume_data))
+ {
+ $resume_data = array(
+ 'reparser' => 0,
+ 'current' => $this->container->get($fast_reparsers[0])->get_max_id(),
+ );
+ }
+
+ $fast_reparsers_size = count($fast_reparsers);
+ $processed_records = 0;
+ while ($processed_records < $limit && $resume_data['reparser'] < $fast_reparsers_size)
+ {
+ $reparser = $this->container->get($fast_reparsers[$resume_data['reparser']]);
+
+ // New reparser
+ if ($resume_data['current'] === 0)
+ {
+ $resume_data['current'] = $reparser->get_max_id();
+ }
+
+ $start = max(1, $resume_data['current'] + 1 - ($limit - $processed_records));
+ $end = max(1, $resume_data['current']);
+ $reparser->reparse_range($start, $end);
+
+ $processed_records += $end - $start + 1;
+ $resume_data['current'] = $start - 1;
+
+ if ($start === 1)
+ {
+ // Prevent CLI command from running these reparsers again
+ $reparser_manager->update_resume_data($fast_reparsers[$resume_data['reparser']], 1, 0, $limit);
+
+ $resume_data['reparser']++;
+ }
+ }
+
+ if ($resume_data['reparser'] === $fast_reparsers_size)
+ {
+ return true;
+ }
+
+ return $resume_data;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/v320a1.php b/phpBB/phpbb/db/migration/data/v320/v320a1.php
new file mode 100644
index 0000000000..d7ecb36f90
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/v320a1.php
@@ -0,0 +1,44 @@
+<?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\v320;
+
+class v320a1 extends \phpbb\db\migration\container_aware_migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-a1', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ '\phpbb\db\migration\data\v320\allowed_schemes_links',
+ '\phpbb\db\migration\data\v320\announce_global_permission',
+ '\phpbb\db\migration\data\v320\remove_profilefield_wlm',
+ '\phpbb\db\migration\data\v320\font_awesome_update',
+ '\phpbb\db\migration\data\v320\icons_alt',
+ '\phpbb\db\migration\data\v320\log_post_id',
+ '\phpbb\db\migration\data\v320\remove_outdated_media',
+ '\phpbb\db\migration\data\v320\notifications_board',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-dev')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/v320a2.php b/phpBB/phpbb/db/migration/data/v320/v320a2.php
new file mode 100644
index 0000000000..ae53a73210
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/v320a2.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\v320;
+
+class v320a2 extends \phpbb\db\migration\container_aware_migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-a2', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v317rc1',
+ '\phpbb\db\migration\data\v320\text_reparser',
+ '\phpbb\db\migration\data\v320\v320a1',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-a2')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/v320b1.php b/phpBB/phpbb/db/migration/data/v320/v320b1.php
new file mode 100644
index 0000000000..5c3a3797cd
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/v320b1.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\v320;
+
+class v320b1 extends \phpbb\db\migration\container_aware_migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-b1', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v317pl1',
+ '\phpbb\db\migration\data\v320\v320a2',
+ '\phpbb\db\migration\data\v31x\increase_size_of_dateformat',
+ '\phpbb\db\migration\data\v320\default_data_type_ids',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-b1')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/v320b2.php b/phpBB/phpbb/db/migration/data/v320/v320b2.php
new file mode 100644
index 0000000000..007f7588e6
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/v320b2.php
@@ -0,0 +1,40 @@
+<?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\v320;
+
+use phpbb\db\migration\migration;
+
+class v320b2 extends migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-b2', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v318',
+ '\phpbb\db\migration\data\v320\v320b1',
+ '\phpbb\db\migration\data\v320\remote_upload_validation',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-b2')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/v320rc1.php b/phpBB/phpbb/db/migration/data/v320/v320rc1.php
new file mode 100644
index 0000000000..a04a2abb19
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/v320rc1.php
@@ -0,0 +1,40 @@
+<?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\v320;
+
+use phpbb\db\migration\migration;
+
+class v320rc1 extends migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-RC1', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v319',
+ '\phpbb\db\migration\data\v320\report_id_auto_increment',
+ '\phpbb\db\migration\data\v320\v320b2',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-RC1')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/migration.php b/phpBB/phpbb/db/migration/migration.php
index 5f120333e1..4e218344f4 100644
--- a/phpBB/phpbb/db/migration/migration.php
+++ b/phpBB/phpbb/db/migration/migration.php
@@ -20,7 +20,7 @@ namespace phpbb\db\migration;
* in a subclass. This class provides various utility methods to simplify editing
* a phpBB.
*/
-abstract class migration
+abstract class migration implements migration_interface
{
/** @var \phpbb\config\config */
protected $config;
@@ -28,7 +28,7 @@ abstract class migration
/** @var \phpbb\db\driver\driver_interface */
protected $db;
- /** @var \phpbb\db\tools */
+ /** @var \phpbb\db\tools\tools_interface */
protected $db_tools;
/** @var string */
@@ -51,12 +51,12 @@ abstract class migration
*
* @param \phpbb\config\config $config
* @param \phpbb\db\driver\driver_interface $db
- * @param \phpbb\db\tools $db_tools
+ * @param \phpbb\db\tools\tools_interface $db_tools
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $table_prefix
*/
- public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
+ public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
{
$this->config = $config;
$this->db = $db;
@@ -70,9 +70,7 @@ abstract class migration
}
/**
- * Defines other migrations to be applied first
- *
- * @return array An array of migration class names
+ * {@inheritdoc}
*/
static public function depends_on()
{
@@ -80,14 +78,7 @@ abstract class migration
}
/**
- * Allows you to check if the migration is effectively installed (entirely optional)
- *
- * This is checked when a migration is installed. If true is returned, the migration will be set as
- * installed without performing the database changes.
- * This function is intended to help moving to migrations from a previous database updater, where some
- * migrations may have been installed already even though they are not yet listed in the migrations table.
- *
- * @return bool True if this migration is installed, False if this migration is not installed (checked on install)
+ * {@inheritdoc}
*/
public function effectively_installed()
{
@@ -95,9 +86,7 @@ abstract class migration
}
/**
- * Updates the database schema by providing a set of change instructions
- *
- * @return array Array of schema changes (compatible with db_tools->perform_schema_changes())
+ * {@inheritdoc}
*/
public function update_schema()
{
@@ -105,9 +94,7 @@ abstract class migration
}
/**
- * Reverts the database schema by providing a set of change instructions
- *
- * @return array Array of schema changes (compatible with db_tools->perform_schema_changes())
+ * {@inheritdoc}
*/
public function revert_schema()
{
@@ -115,9 +102,7 @@ abstract class migration
}
/**
- * Updates data by returning a list of instructions to be executed
- *
- * @return array Array of data update instructions
+ * {@inheritdoc}
*/
public function update_data()
{
@@ -125,12 +110,7 @@ abstract class migration
}
/**
- * Reverts data by returning a list of instructions to be executed
- *
- * @return array Array of data instructions that will be performed on revert
- * NOTE: calls to tools (such as config.add) are automatically reverted when
- * possible, so you should not attempt to revert those, this is mostly for
- * otherwise unrevertable calls (custom functions for example)
+ * {@inheritdoc}
*/
public function revert_data()
{
diff --git a/phpBB/phpbb/db/migration/migration_interface.php b/phpBB/phpbb/db/migration/migration_interface.php
new file mode 100644
index 0000000000..2aba5ec608
--- /dev/null
+++ b/phpBB/phpbb/db/migration/migration_interface.php
@@ -0,0 +1,70 @@
+<?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;
+
+/**
+ * Base class interface for database migrations
+ */
+interface migration_interface
+{
+ /**
+ * Defines other migrations to be applied first
+ *
+ * @return array An array of migration class names
+ */
+ static public function depends_on();
+
+ /**
+ * Allows you to check if the migration is effectively installed (entirely optional)
+ *
+ * This is checked when a migration is installed. If true is returned, the migration will be set as
+ * installed without performing the database changes.
+ * This function is intended to help moving to migrations from a previous database updater, where some
+ * migrations may have been installed already even though they are not yet listed in the migrations table.
+ *
+ * @return bool True if this migration is installed, False if this migration is not installed (checked on install)
+ */
+ public function effectively_installed();
+
+ /**
+ * Updates the database schema by providing a set of change instructions
+ *
+ * @return array Array of schema changes (compatible with db_tools->perform_schema_changes())
+ */
+ public function update_schema();
+
+ /**
+ * Reverts the database schema by providing a set of change instructions
+ *
+ * @return array Array of schema changes (compatible with db_tools->perform_schema_changes())
+ */
+ public function revert_schema();
+
+ /**
+ * Updates data by returning a list of instructions to be executed
+ *
+ * @return array Array of data update instructions
+ */
+ public function update_data();
+
+ /**
+ * Reverts data by returning a list of instructions to be executed
+ *
+ * @return array Array of data instructions that will be performed on revert
+ * NOTE: calls to tools (such as config.add) are automatically reverted when
+ * possible, so you should not attempt to revert those, this is mostly for
+ * otherwise unrevertable calls (custom functions for example)
+ */
+ public function revert_data();
+}
diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php
index da1a38e2fa..3f26a4998c 100644
--- a/phpBB/phpbb/db/migration/profilefield_base_migration.php
+++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php
@@ -237,6 +237,7 @@ abstract class profilefield_base_migration extends container_aware_migration
if ($profile_row === null)
{
+ /* @var $manager \phpbb\profilefields\manager */
$manager = $this->container->get('profilefields.manager');
$profile_row = $manager->build_insert_sql_array(array());
}
diff --git a/phpBB/phpbb/db/migration/schema_generator.php b/phpBB/phpbb/db/migration/schema_generator.php
index 91d8307d91..c579e25824 100644
--- a/phpBB/phpbb/db/migration/schema_generator.php
+++ b/phpBB/phpbb/db/migration/schema_generator.php
@@ -24,7 +24,7 @@ class schema_generator
/** @var \phpbb\db\driver\driver_interface */
protected $db;
- /** @var \phpbb\db\tools */
+ /** @var \phpbb\db\tools\tools_interface */
protected $db_tools;
/** @var array */
@@ -48,7 +48,7 @@ class schema_generator
/**
* Constructor
*/
- public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
+ public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
{
$this->config = $config;
$this->db = $db;
@@ -77,8 +77,15 @@ class schema_generator
$check_dependencies = true;
while (!empty($migrations))
{
- foreach ($migrations as $migration_class)
+ foreach ($migrations as $key => $migration_class)
{
+ // Unset classes that are not a valid migration
+ if (\phpbb\db\migrator::is_migration($migration_class) === false)
+ {
+ unset($migrations[$key]);
+ continue;
+ }
+
$open_dependencies = array_diff($migration_class::depends_on(), $tree);
if (empty($open_dependencies))
diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php
index 7ea7d1dac1..b47c426110 100644
--- a/phpBB/phpbb/db/migration/tool/module.php
+++ b/phpBB/phpbb/db/migration/tool/module.php
@@ -13,6 +13,8 @@
namespace phpbb\db\migration\tool;
+use phpbb\module\exception\module_exception;
+
/**
* Migration module management tool
*/
@@ -27,6 +29,9 @@ class module implements \phpbb\db\migration\tool\tool_interface
/** @var \phpbb\user */
protected $user;
+ /** @var \phpbb\module\module_manager */
+ protected $module_manager;
+
/** @var string */
protected $phpbb_root_path;
@@ -45,15 +50,17 @@ class module implements \phpbb\db\migration\tool\tool_interface
* @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\cache\service $cache
* @param \phpbb\user $user
+ * @param \phpbb\module\module_manager $module_manager
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $modules_table
*/
- public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, $phpbb_root_path, $php_ext, $modules_table)
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, \phpbb\module\module_manager $module_manager, $phpbb_root_path, $php_ext, $modules_table)
{
$this->db = $db;
$this->cache = $cache;
$this->user = $user;
+ $this->module_manager = $module_manager;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->modules_table = $modules_table;
@@ -157,6 +164,8 @@ class module implements \phpbb\db\migration\tool\tool_interface
*/
public function add($class, $parent = 0, $data = array())
{
+ global $user, $phpbb_log;
+
// allow sending the name as a string in $data to create a category
if (!is_array($data))
{
@@ -171,7 +180,6 @@ class module implements \phpbb\db\migration\tool\tool_interface
$basename = (isset($data['module_basename'])) ? $data['module_basename'] : '';
$module = $this->get_module_info($class, $basename);
- $result = '';
foreach ($module['modes'] as $mode => $module_info)
{
if (!isset($data['modes']) || in_array($mode, $data['modes']))
@@ -205,13 +213,6 @@ class module implements \phpbb\db\migration\tool\tool_interface
throw new \phpbb\db\migration\exception('MODULE_EXISTS', $data['module_langname']);
}
- if (!class_exists('acp_modules'))
- {
- include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
- $this->user->add_lang('acp/modules');
- }
- $acp_modules = new \acp_modules();
-
$module_data = array(
'module_enabled' => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1,
'module_display' => (isset($data['module_display'])) ? $data['module_display'] : 1,
@@ -222,19 +223,14 @@ class module implements \phpbb\db\migration\tool\tool_interface
'module_mode' => (isset($data['module_mode'])) ? $data['module_mode'] : '',
'module_auth' => (isset($data['module_auth'])) ? $data['module_auth'] : '',
);
- $result = $acp_modules->update_module_data($module_data, true);
- // update_module_data can either return a string or an empty array...
- if (is_string($result))
- {
- // Error
- throw new \phpbb\db\migration\exception('MODULE_ERROR', $result);
- }
- else
+ try
{
+ $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']);
- add_log('admin', 'LOG_MODULE_ADD', $module_log_name);
+ $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'])
@@ -284,6 +280,11 @@ class module implements \phpbb\db\migration\tool\tool_interface
$this->db->sql_query($sql);
}
}
+ catch (module_exception $e)
+ {
+ // Error
+ throw new \phpbb\db\migration\exception('MODULE_ERROR', $e->getMessage());
+ }
// Clear the Modules Cache
$this->cache->destroy("_modules_$class");
@@ -365,21 +366,9 @@ class module implements \phpbb\db\migration\tool\tool_interface
$module_ids[] = (int) $module;
}
- if (!class_exists('acp_modules'))
- {
- include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
- $this->user->add_lang('acp/modules');
- }
- $acp_modules = new \acp_modules();
- $acp_modules->module_class = $class;
-
foreach ($module_ids as $module_id)
{
- $result = $acp_modules->delete_module($module_id);
- if (!empty($result))
- {
- return;
- }
+ $this->module_manager->delete_module($module_id, $class);
}
$this->cache->destroy("_modules_$class");
@@ -427,13 +416,7 @@ class module implements \phpbb\db\migration\tool\tool_interface
*/
protected function get_module_info($class, $basename)
{
- if (!class_exists('acp_modules'))
- {
- include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
- $this->user->add_lang('acp/modules');
- }
- $acp_modules = new \acp_modules();
- $module = $acp_modules->get_module_infos($basename, $class, true);
+ $module = $this->module_manager->get_module_infos($class, $basename, true);
if (empty($module))
{
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index 45a333ac94..d7d7f18d2b 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -13,6 +13,8 @@
namespace phpbb\db;
+use phpbb\db\output_handler\migrator_output_handler_interface;
+use phpbb\db\output_handler\null_migrator_output_handler;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -32,7 +34,7 @@ class migrator
/** @var \phpbb\db\driver\driver_interface */
protected $db;
- /** @var \phpbb\db\tools */
+ /** @var \phpbb\db\tools\tools_interface */
protected $db_tools;
/** @var \phpbb\db\migration\helper */
@@ -92,7 +94,7 @@ class migrator
/**
* Constructor of the database migrator
*/
- public function __construct(ContainerInterface $container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper)
+ public function __construct(ContainerInterface $container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools\tools_interface $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper)
{
$this->container = $container;
$this->config = $config;
@@ -122,7 +124,7 @@ class migrator
/**
* Set the output handler.
*
- * @param migrator_output_handler $handler The output handler
+ * @param migrator_output_handler_interface $handler The output handler
*/
public function set_output_handler(migrator_output_handler_interface $handler)
{
@@ -182,10 +184,50 @@ class migrator
*/
public function set_migrations($class_names)
{
+ foreach ($class_names as $key => $class)
+ {
+ if (!self::is_migration($class))
+ {
+ unset($class_names[$key]);
+ }
+ }
+
$this->migrations = $class_names;
}
/**
+ * Get the list of available migration class names
+ *
+ * @return array Array of all migrations available to be run
+ */
+ public function get_migrations()
+ {
+ return $this->migrations;
+ }
+
+ /**
+ * Get the list of available and not installed migration class names
+ *
+ * @return array
+ */
+ public function get_installable_migrations()
+ {
+ $unfinished_migrations = array();
+
+ foreach ($this->migrations as $name)
+ {
+ if (!isset($this->migration_state[$name]) ||
+ !$this->migration_state[$name]['migration_schema_done'] ||
+ !$this->migration_state[$name]['migration_data_done'])
+ {
+ $unfinished_migrations[] = $name;
+ }
+ }
+
+ return $unfinished_migrations;
+ }
+
+ /**
* Runs a single update step from the next migration to be applied.
*
* The update step can either be a schema or a (partial) data update. To
@@ -497,19 +539,60 @@ class migrator
if ($state['migration_data_done'])
{
+ $verbosity = empty($state['migration_data_state']) ?
+ migrator_output_handler_interface::VERBOSITY_VERBOSE : migrator_output_handler_interface::VERBOSITY_DEBUG;
+ $this->output_handler->write(array('MIGRATION_REVERT_DATA_RUNNING', $name), $verbosity);
+
+ $total_time = (is_array($state['migration_data_state']) && isset($state['migration_data_state']['_total_time'])) ?
+ $state['migration_data_state']['_total_time'] : 0.0;
+ $elapsed_time = microtime(true);
+
$steps = array_merge($this->helper->reverse_update_data($migration->update_data()), $migration->revert_data());
$result = $this->process_data_step($steps, $state['migration_data_state']);
+ $elapsed_time = microtime(true) - $elapsed_time;
+ $total_time += $elapsed_time;
+
+ if (is_array($result))
+ {
+ $result['_total_time'] = $total_time;
+ }
+
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_data_done'] = ($result === true) ? false : true;
$this->set_migration_state($name, $state);
+
+ if (!$state['migration_data_done'])
+ {
+ $this->output_handler->write(array('MIGRATION_REVERT_DATA_DONE', $name, $total_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ }
+ else
+ {
+ $this->output_handler->write(array('MIGRATION_REVERT_DATA_IN_PROGRESS', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_VERY_VERBOSE);
+ }
}
else if ($state['migration_schema_done'])
{
+ $verbosity = empty($state['migration_data_state']) ?
+ migrator_output_handler_interface::VERBOSITY_VERBOSE : migrator_output_handler_interface::VERBOSITY_DEBUG;
+ $this->output_handler->write(array('MIGRATION_REVERT_SCHEMA_RUNNING', $name), $verbosity);
+
+ $total_time = (is_array($state['migration_data_state']) && isset($state['migration_data_state']['_total_time'])) ?
+ $state['migration_data_state']['_total_time'] : 0.0;
+ $elapsed_time = microtime(true);
+
$steps = $this->helper->get_schema_steps($migration->revert_schema());
$result = $this->process_data_step($steps, $state['migration_data_state']);
+ $elapsed_time = microtime(true) - $elapsed_time;
+ $total_time += $elapsed_time;
+
+ if (is_array($result))
+ {
+ $result['_total_time'] = $total_time;
+ }
+
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_schema_done'] = ($result === true) ? false : true;
@@ -521,10 +604,14 @@ class migrator
$this->last_run_migration = false;
unset($this->migration_state[$name]);
+
+ $this->output_handler->write(array('MIGRATION_REVERT_SCHEMA_DONE', $name, $total_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
}
else
{
$this->set_migration_state($name, $state);
+
+ $this->output_handler->write(array('MIGRATION_REVERT_SCHEMA_IN_PROGRESS', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_VERY_VERBOSE);
}
}
@@ -921,4 +1008,27 @@ class migrator
));
}
}
+
+ /**
+ * Check if a class is a migration.
+ *
+ * @param string $migration A migration class name
+ * @return bool Return true if class is a migration, false otherwise
+ */
+ static public function is_migration($migration)
+ {
+ if (class_exists($migration))
+ {
+ // Migration classes should extend the abstract class
+ // phpbb\db\migration\migration (which implements the
+ // migration_interface) and be instantiable.
+ $reflector = new \ReflectionClass($migration);
+ if ($reflector->implementsInterface('\phpbb\db\migration\migration_interface') && $reflector->isInstantiable())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/phpBB/phpbb/db/migrator_output_handler_interface.php b/phpBB/phpbb/db/migrator_output_handler_interface.php
deleted file mode 100644
index 9947b51dcc..0000000000
--- a/phpBB/phpbb/db/migrator_output_handler_interface.php
+++ /dev/null
@@ -1,31 +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\db;
-
-interface migrator_output_handler_interface
-{
- const VERBOSITY_QUIET = 16;
- const VERBOSITY_NORMAL = 32;
- const VERBOSITY_VERBOSE = 64;
- const VERBOSITY_VERY_VERBOSE = 128;
- const VERBOSITY_DEBUG = 256;
-
- /**
- * Write output using the configured closure.
- *
- * @param string|array $message The message to write or an array containing the language key and all of its parameters.
- * @param int $verbosity The verbosity of the message.
- */
- public function write($message, $verbosity);
-}
diff --git a/phpBB/phpbb/db/null_migrator_output_handler.php b/phpBB/phpbb/db/null_migrator_output_handler.php
deleted file mode 100644
index 0e8cfbb049..0000000000
--- a/phpBB/phpbb/db/null_migrator_output_handler.php
+++ /dev/null
@@ -1,24 +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\db;
-
-class null_migrator_output_handler implements migrator_output_handler_interface
-{
- /**
- * {@inheritdoc}
- */
- public function write($message, $verbosity)
- {
- }
-}
diff --git a/phpBB/phpbb/db/output_handler/html_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/html_migrator_output_handler.php
new file mode 100644
index 0000000000..67309649c9
--- /dev/null
+++ b/phpBB/phpbb/db/output_handler/html_migrator_output_handler.php
@@ -0,0 +1,46 @@
+<?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\output_handler;
+
+class html_migrator_output_handler implements migrator_output_handler_interface
+{
+ /**
+ * Language object.
+ *
+ * @var \phpbb\language\language
+ */
+ private $language;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\language\language $language Language object
+ */
+ public function __construct(\phpbb\language\language $language)
+ {
+ $this->language = $language;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write($message, $verbosity)
+ {
+ if ($verbosity <= migrator_output_handler_interface::VERBOSITY_VERBOSE)
+ {
+ $final_message = $this->language->lang_array(array_shift($message), $message);
+ echo $final_message . "<br />\n";
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php
new file mode 100644
index 0000000000..56d5cf49a1
--- /dev/null
+++ b/phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php
@@ -0,0 +1,46 @@
+<?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\output_handler;
+
+use phpbb\install\helper\iohandler\iohandler_interface;
+
+class installer_migrator_output_handler implements migrator_output_handler_interface
+{
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param iohandler_interface $iohandler Installer's IO-handler
+ */
+ public function __construct(iohandler_interface $iohandler)
+ {
+ $this->iohandler = $iohandler;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write($message, $verbosity)
+ {
+ if ($verbosity <= migrator_output_handler_interface::VERBOSITY_VERBOSE)
+ {
+ $this->iohandler->add_log_message($message);
+ $this->iohandler->send_response();
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php
new file mode 100644
index 0000000000..20991746ac
--- /dev/null
+++ b/phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php
@@ -0,0 +1,101 @@
+<?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\output_handler;
+
+class log_wrapper_migrator_output_handler implements migrator_output_handler_interface
+{
+ /**
+ * Language object.
+ *
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * A migrator output handler
+ *
+ * @var migrator_output_handler_interface
+ */
+ protected $migrator;
+
+ /**
+ * Log file handle
+ * @var resource
+ */
+ protected $file_handle = false;
+
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\language\language $language Language object
+ * @param migrator_output_handler_interface $migrator Migrator output handler
+ * @param string $log_file File to log to
+ * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB filesystem object
+ */
+ public function __construct(\phpbb\language\language $language, migrator_output_handler_interface $migrator, $log_file, \phpbb\filesystem\filesystem_interface $filesystem)
+ {
+ $this->language = $language;
+ $this->migrator = $migrator;
+ $this->filesystem = $filesystem;
+ $this->file_open($log_file);
+ }
+
+ /**
+ * Open file for logging
+ *
+ * @param string $file File to open
+ */
+ protected function file_open($file)
+ {
+ if ($this->filesystem->is_writable(dirname($file)))
+ {
+ $this->file_handle = fopen($file, 'w');
+ }
+ else
+ {
+ throw new \RuntimeException('Unable to write to migrator log file');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write($message, $verbosity)
+ {
+ $this->migrator->write($message, $verbosity);
+
+ if ($this->file_handle !== false)
+ {
+
+ $translated_message = $this->language->lang_array(array_shift($message), $message);
+
+ if ($verbosity <= migrator_output_handler_interface::VERBOSITY_NORMAL)
+ {
+ $translated_message = '[INFO] ' . $translated_message;
+ }
+ else
+ {
+ $translated_message = '[DEBUG] ' . $translated_message;
+ }
+
+ fwrite($this->file_handle, $translated_message);
+ fflush($this->file_handle);
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/output_handler/migrator_output_handler_interface.php b/phpBB/phpbb/db/output_handler/migrator_output_handler_interface.php
new file mode 100644
index 0000000000..455d8aabbb
--- /dev/null
+++ b/phpBB/phpbb/db/output_handler/migrator_output_handler_interface.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\output_handler;
+
+interface migrator_output_handler_interface
+{
+ const VERBOSITY_QUIET = 16;
+ const VERBOSITY_NORMAL = 32;
+ const VERBOSITY_VERBOSE = 64;
+ const VERBOSITY_VERY_VERBOSE = 128;
+ const VERBOSITY_DEBUG = 256;
+
+ /**
+ * Write output using the configured closure.
+ *
+ * @param string|array $message The message to write or an array containing the language key and all of its parameters.
+ * @param int $verbosity The verbosity of the message.
+ */
+ public function write($message, $verbosity);
+}
diff --git a/phpBB/phpbb/db/output_handler/null_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/null_migrator_output_handler.php
new file mode 100644
index 0000000000..5fc2a52577
--- /dev/null
+++ b/phpBB/phpbb/db/output_handler/null_migrator_output_handler.php
@@ -0,0 +1,24 @@
+<?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\output_handler;
+
+class null_migrator_output_handler implements migrator_output_handler_interface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function write($message, $verbosity)
+ {
+ }
+}
diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php
deleted file mode 100644
index 832a0c510c..0000000000
--- a/phpBB/phpbb/db/tools.php
+++ /dev/null
@@ -1,2840 +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\db;
-
-/**
-* Database Tools for handling cross-db actions such as altering columns, etc.
-* Currently not supported is returning SQL for creating tables.
-*/
-class tools
-{
- /**
- * Current sql layer
- */
- var $sql_layer = '';
-
- /**
- * @var object DB object
- */
- var $db = null;
-
- /**
- * The Column types for every database we support
- * @var array
- */
- var $dbms_type_map = array();
-
- /**
- * Is the used MS SQL Server a SQL Server 2000?
- * @var bool
- */
- protected $is_sql_server_2000;
-
- /**
- * Get the column types for every database we support
- *
- * @return array
- */
- public static function get_dbms_type_map()
- {
- return array(
- 'mysql_41' => array(
- 'INT:' => 'int(%d)',
- 'BINT' => 'bigint(20)',
- 'UINT' => 'mediumint(8) UNSIGNED',
- 'UINT:' => 'int(%d) UNSIGNED',
- 'TINT:' => 'tinyint(%d)',
- 'USINT' => 'smallint(4) UNSIGNED',
- 'BOOL' => 'tinyint(1) UNSIGNED',
- 'VCHAR' => 'varchar(255)',
- 'VCHAR:' => 'varchar(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'text',
- 'XSTEXT_UNI'=> 'varchar(100)',
- 'STEXT' => 'text',
- 'STEXT_UNI' => 'varchar(255)',
- 'TEXT' => 'text',
- 'TEXT_UNI' => 'text',
- 'MTEXT' => 'mediumtext',
- 'MTEXT_UNI' => 'mediumtext',
- 'TIMESTAMP' => 'int(11) UNSIGNED',
- 'DECIMAL' => 'decimal(5,2)',
- 'DECIMAL:' => 'decimal(%d,2)',
- 'PDECIMAL' => 'decimal(6,3)',
- 'PDECIMAL:' => 'decimal(%d,3)',
- 'VCHAR_UNI' => 'varchar(255)',
- 'VCHAR_UNI:'=> 'varchar(%d)',
- 'VCHAR_CI' => 'varchar(255)',
- 'VARBINARY' => 'varbinary(255)',
- ),
-
- 'mysql_40' => array(
- 'INT:' => 'int(%d)',
- 'BINT' => 'bigint(20)',
- 'UINT' => 'mediumint(8) UNSIGNED',
- 'UINT:' => 'int(%d) UNSIGNED',
- 'TINT:' => 'tinyint(%d)',
- 'USINT' => 'smallint(4) UNSIGNED',
- 'BOOL' => 'tinyint(1) UNSIGNED',
- 'VCHAR' => 'varbinary(255)',
- 'VCHAR:' => 'varbinary(%d)',
- 'CHAR:' => 'binary(%d)',
- 'XSTEXT' => 'blob',
- 'XSTEXT_UNI'=> 'blob',
- 'STEXT' => 'blob',
- 'STEXT_UNI' => 'blob',
- 'TEXT' => 'blob',
- 'TEXT_UNI' => 'blob',
- 'MTEXT' => 'mediumblob',
- 'MTEXT_UNI' => 'mediumblob',
- 'TIMESTAMP' => 'int(11) UNSIGNED',
- 'DECIMAL' => 'decimal(5,2)',
- 'DECIMAL:' => 'decimal(%d,2)',
- 'PDECIMAL' => 'decimal(6,3)',
- 'PDECIMAL:' => 'decimal(%d,3)',
- 'VCHAR_UNI' => 'blob',
- 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')),
- 'VCHAR_CI' => 'blob',
- 'VARBINARY' => 'varbinary(255)',
- ),
-
- 'mssql' => array(
- 'INT:' => '[int]',
- 'BINT' => '[float]',
- 'UINT' => '[int]',
- 'UINT:' => '[int]',
- 'TINT:' => '[int]',
- 'USINT' => '[int]',
- 'BOOL' => '[int]',
- 'VCHAR' => '[varchar] (255)',
- 'VCHAR:' => '[varchar] (%d)',
- 'CHAR:' => '[char] (%d)',
- 'XSTEXT' => '[varchar] (1000)',
- 'STEXT' => '[varchar] (3000)',
- 'TEXT' => '[varchar] (8000)',
- 'MTEXT' => '[text]',
- 'XSTEXT_UNI'=> '[varchar] (100)',
- 'STEXT_UNI' => '[varchar] (255)',
- 'TEXT_UNI' => '[varchar] (4000)',
- 'MTEXT_UNI' => '[text]',
- 'TIMESTAMP' => '[int]',
- 'DECIMAL' => '[float]',
- 'DECIMAL:' => '[float]',
- 'PDECIMAL' => '[float]',
- 'PDECIMAL:' => '[float]',
- 'VCHAR_UNI' => '[varchar] (255)',
- 'VCHAR_UNI:'=> '[varchar] (%d)',
- 'VCHAR_CI' => '[varchar] (255)',
- 'VARBINARY' => '[varchar] (255)',
- ),
-
- 'mssqlnative' => array(
- 'INT:' => '[int]',
- 'BINT' => '[float]',
- 'UINT' => '[int]',
- 'UINT:' => '[int]',
- 'TINT:' => '[int]',
- 'USINT' => '[int]',
- 'BOOL' => '[int]',
- 'VCHAR' => '[varchar] (255)',
- 'VCHAR:' => '[varchar] (%d)',
- 'CHAR:' => '[char] (%d)',
- 'XSTEXT' => '[varchar] (1000)',
- 'STEXT' => '[varchar] (3000)',
- 'TEXT' => '[varchar] (8000)',
- 'MTEXT' => '[text]',
- 'XSTEXT_UNI'=> '[varchar] (100)',
- 'STEXT_UNI' => '[varchar] (255)',
- 'TEXT_UNI' => '[varchar] (4000)',
- 'MTEXT_UNI' => '[text]',
- 'TIMESTAMP' => '[int]',
- 'DECIMAL' => '[float]',
- 'DECIMAL:' => '[float]',
- 'PDECIMAL' => '[float]',
- 'PDECIMAL:' => '[float]',
- 'VCHAR_UNI' => '[varchar] (255)',
- 'VCHAR_UNI:'=> '[varchar] (%d)',
- 'VCHAR_CI' => '[varchar] (255)',
- 'VARBINARY' => '[varchar] (255)',
- ),
-
- 'oracle' => array(
- 'INT:' => 'number(%d)',
- 'BINT' => 'number(20)',
- 'UINT' => 'number(8)',
- 'UINT:' => 'number(%d)',
- 'TINT:' => 'number(%d)',
- 'USINT' => 'number(4)',
- 'BOOL' => 'number(1)',
- 'VCHAR' => 'varchar2(255)',
- 'VCHAR:' => 'varchar2(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'varchar2(1000)',
- 'STEXT' => 'varchar2(3000)',
- 'TEXT' => 'clob',
- 'MTEXT' => 'clob',
- 'XSTEXT_UNI'=> 'varchar2(300)',
- 'STEXT_UNI' => 'varchar2(765)',
- 'TEXT_UNI' => 'clob',
- 'MTEXT_UNI' => 'clob',
- 'TIMESTAMP' => 'number(11)',
- 'DECIMAL' => 'number(5, 2)',
- 'DECIMAL:' => 'number(%d, 2)',
- 'PDECIMAL' => 'number(6, 3)',
- 'PDECIMAL:' => 'number(%d, 3)',
- 'VCHAR_UNI' => 'varchar2(765)',
- 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
- 'VCHAR_CI' => 'varchar2(255)',
- 'VARBINARY' => 'raw(255)',
- ),
-
- 'sqlite' => array(
- 'INT:' => 'int(%d)',
- 'BINT' => 'bigint(20)',
- 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED',
- 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED',
- 'TINT:' => 'tinyint(%d)',
- 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED',
- 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED',
- 'VCHAR' => 'varchar(255)',
- 'VCHAR:' => 'varchar(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'text(65535)',
- 'STEXT' => 'text(65535)',
- 'TEXT' => 'text(65535)',
- 'MTEXT' => 'mediumtext(16777215)',
- 'XSTEXT_UNI'=> 'text(65535)',
- 'STEXT_UNI' => 'text(65535)',
- 'TEXT_UNI' => 'text(65535)',
- 'MTEXT_UNI' => 'mediumtext(16777215)',
- 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
- 'DECIMAL' => 'decimal(5,2)',
- 'DECIMAL:' => 'decimal(%d,2)',
- 'PDECIMAL' => 'decimal(6,3)',
- 'PDECIMAL:' => 'decimal(%d,3)',
- 'VCHAR_UNI' => 'varchar(255)',
- 'VCHAR_UNI:'=> 'varchar(%d)',
- 'VCHAR_CI' => 'varchar(255)',
- 'VARBINARY' => 'blob',
- ),
-
- 'sqlite3' => array(
- 'INT:' => 'INT(%d)',
- 'BINT' => 'BIGINT(20)',
- 'UINT' => 'INTEGER UNSIGNED',
- 'UINT:' => 'INTEGER UNSIGNED',
- 'TINT:' => 'TINYINT(%d)',
- 'USINT' => 'INTEGER UNSIGNED',
- 'BOOL' => 'INTEGER UNSIGNED',
- 'VCHAR' => 'VARCHAR(255)',
- 'VCHAR:' => 'VARCHAR(%d)',
- 'CHAR:' => 'CHAR(%d)',
- 'XSTEXT' => 'TEXT(65535)',
- 'STEXT' => 'TEXT(65535)',
- 'TEXT' => 'TEXT(65535)',
- 'MTEXT' => 'MEDIUMTEXT(16777215)',
- 'XSTEXT_UNI'=> 'TEXT(65535)',
- 'STEXT_UNI' => 'TEXT(65535)',
- 'TEXT_UNI' => 'TEXT(65535)',
- 'MTEXT_UNI' => 'MEDIUMTEXT(16777215)',
- 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
- 'DECIMAL' => 'DECIMAL(5,2)',
- 'DECIMAL:' => 'DECIMAL(%d,2)',
- 'PDECIMAL' => 'DECIMAL(6,3)',
- 'PDECIMAL:' => 'DECIMAL(%d,3)',
- 'VCHAR_UNI' => 'VARCHAR(255)',
- 'VCHAR_UNI:'=> 'VARCHAR(%d)',
- 'VCHAR_CI' => 'VARCHAR(255)',
- 'VARBINARY' => 'BLOB',
- ),
-
- 'postgres' => array(
- 'INT:' => 'INT4',
- 'BINT' => 'INT8',
- 'UINT' => 'INT4', // unsigned
- 'UINT:' => 'INT4', // unsigned
- 'USINT' => 'INT2', // unsigned
- 'BOOL' => 'INT2', // unsigned
- 'TINT:' => 'INT2',
- 'VCHAR' => 'varchar(255)',
- 'VCHAR:' => 'varchar(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'varchar(1000)',
- 'STEXT' => 'varchar(3000)',
- 'TEXT' => 'varchar(8000)',
- 'MTEXT' => 'TEXT',
- 'XSTEXT_UNI'=> 'varchar(100)',
- 'STEXT_UNI' => 'varchar(255)',
- 'TEXT_UNI' => 'varchar(4000)',
- 'MTEXT_UNI' => 'TEXT',
- 'TIMESTAMP' => 'INT4', // unsigned
- 'DECIMAL' => 'decimal(5,2)',
- 'DECIMAL:' => 'decimal(%d,2)',
- 'PDECIMAL' => 'decimal(6,3)',
- 'PDECIMAL:' => 'decimal(%d,3)',
- 'VCHAR_UNI' => 'varchar(255)',
- 'VCHAR_UNI:'=> 'varchar(%d)',
- 'VCHAR_CI' => 'varchar_ci',
- 'VARBINARY' => 'bytea',
- ),
- );
- }
-
- /**
- * A list of types being unsigned for better reference in some db's
- * @var array
- */
- var $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
-
- /**
- * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules.
- * @var array
- */
- var $supported_dbms = array('mssql', 'mssqlnative', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite', 'sqlite3');
-
- /**
- * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array).
- * This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command.
- */
- var $return_statements = false;
-
- /**
- * Constructor. Set DB Object and set {@link $return_statements return_statements}.
- *
- * @param \phpbb\db\driver\driver_interface $db Database connection
- * @param bool $return_statements True if only statements should be returned and no SQL being executed
- */
- public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
- {
- $this->db = $db;
- $this->return_statements = $return_statements;
-
- $this->dbms_type_map = self::get_dbms_type_map();
-
- // Determine mapping database type
- switch ($this->db->get_sql_layer())
- {
- case 'mysql':
- $this->sql_layer = 'mysql_40';
- break;
-
- case 'mysql4':
- if (version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
- {
- $this->sql_layer = 'mysql_41';
- }
- else
- {
- $this->sql_layer = 'mysql_40';
- }
- break;
-
- case 'mysqli':
- $this->sql_layer = 'mysql_41';
- break;
-
- case 'mssql':
- case 'mssql_odbc':
- $this->sql_layer = 'mssql';
- break;
-
- case 'mssqlnative':
- $this->sql_layer = 'mssqlnative';
- break;
-
- default:
- $this->sql_layer = $this->db->get_sql_layer();
- break;
- }
- }
-
- /**
- * Setter for {@link $return_statements return_statements}.
- *
- * @param bool $return_statements True if SQL should not be executed but returned as strings
- * @return null
- */
- public function set_return_statements($return_statements)
- {
- $this->return_statements = $return_statements;
- }
-
- /**
- * Gets a list of tables in the database.
- *
- * @return array Array of table names (all lower case)
- */
- function sql_list_tables()
- {
- switch ($this->db->get_sql_layer())
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $sql = 'SHOW TABLES';
- break;
-
- case 'sqlite':
- $sql = 'SELECT name
- FROM sqlite_master
- WHERE type = "table"';
- break;
-
- case 'sqlite3':
- $sql = 'SELECT name
- FROM sqlite_master
- WHERE type = "table"
- AND name <> "sqlite_sequence"';
- break;
-
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $sql = "SELECT name
- FROM sysobjects
- WHERE type='U'";
- break;
-
- case 'postgres':
- $sql = 'SELECT relname
- FROM pg_stat_user_tables';
- break;
-
- case 'oracle':
- $sql = 'SELECT table_name
- FROM USER_TABLES';
- break;
- }
-
- $result = $this->db->sql_query($sql);
-
- $tables = array();
- while ($row = $this->db->sql_fetchrow($result))
- {
- $name = current($row);
- $tables[$name] = $name;
- }
- $this->db->sql_freeresult($result);
-
- return $tables;
- }
-
- /**
- * Check if table exists
- *
- *
- * @param string $table_name The table name to check for
- * @return bool true if table exists, else false
- */
- function sql_table_exists($table_name)
- {
- $this->db->sql_return_on_error(true);
- $result = $this->db->sql_query_limit('SELECT * FROM ' . $table_name, 1);
- $this->db->sql_return_on_error(false);
-
- if ($result)
- {
- $this->db->sql_freeresult($result);
- return true;
- }
-
- return false;
- }
-
- /**
- * Create SQL Table
- *
- * @param string $table_name The table name to create
- * @param array $table_data Array containing table data.
- * @return array Statements if $return_statements is true.
- */
- function sql_create_table($table_name, $table_data)
- {
- // holds the DDL for a column
- $columns = $statements = array();
-
- if ($this->sql_table_exists($table_name))
- {
- return $this->_sql_run_sql($statements);
- }
-
- // Begin transaction
- $statements[] = 'begin';
-
- // Determine if we have created a PRIMARY KEY in the earliest
- $primary_key_gen = false;
-
- // Determine if the table requires a sequence
- $create_sequence = false;
-
- // Begin table sql statement
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n";
- break;
-
- default:
- $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
- break;
- }
-
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- if (!isset($table_data['PRIMARY_KEY']))
- {
- $table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment');
- $table_data['PRIMARY_KEY'] = 'mssqlindex';
- }
- }
-
- // Iterate through the columns to create a table
- foreach ($table_data['COLUMNS'] as $column_name => $column_data)
- {
- // here lies an array, filled with information compiled on the column's data
- $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
-
- if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
- {
- trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
- }
-
- // here we add the definition of the new column to the list of columns
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default'];
- break;
-
- default:
- $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
- break;
- }
-
- // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
- if (!$primary_key_gen)
- {
- $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
- }
-
- // create sequence DDL based off of the existance of auto incrementing columns
- if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
- {
- $create_sequence = $column_name;
- }
- }
-
- // this makes up all the columns in the create table statement
- $table_sql .= implode(",\n", $columns);
-
- // Close the table for two DBMS and add to the statements
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $table_sql .= "\n);";
- $statements[] = $table_sql;
- break;
- }
-
- // we have yet to create a primary key for this table,
- // this means that we can add the one we really wanted instead
- if (!$primary_key_gen)
- {
- // Write primary key
- if (isset($table_data['PRIMARY_KEY']))
- {
- if (!is_array($table_data['PRIMARY_KEY']))
- {
- $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
- }
-
- switch ($this->sql_layer)
- {
- case 'mysql_40':
- case 'mysql_41':
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']);
- foreach ($primary_key_stmts as $pk_stmt)
- {
- $statements[] = $pk_stmt;
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
- case 'oracle':
- $table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
- break;
- }
- }
- }
-
- // close the table
- switch ($this->sql_layer)
- {
- case 'mysql_41':
- // make sure the table is in UTF-8 mode
- $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;";
- $statements[] = $table_sql;
- break;
-
- case 'mysql_40':
- case 'sqlite':
- case 'sqlite3':
- $table_sql .= "\n);";
- $statements[] = $table_sql;
- break;
-
- case 'postgres':
- // do we need to add a sequence for auto incrementing columns?
- if ($create_sequence)
- {
- $statements[] = "CREATE SEQUENCE {$table_name}_seq;";
- }
-
- $table_sql .= "\n);";
- $statements[] = $table_sql;
- break;
-
- case 'oracle':
- $table_sql .= "\n)";
- $statements[] = $table_sql;
-
- // do we need to add a sequence and a tigger for auto incrementing columns?
- if ($create_sequence)
- {
- // create the actual sequence
- $statements[] = "CREATE SEQUENCE {$table_name}_seq";
-
- // the trigger is the mechanism by which we increment the counter
- $trigger = "CREATE OR REPLACE TRIGGER t_{$table_name}\n";
- $trigger .= "BEFORE INSERT ON {$table_name}\n";
- $trigger .= "FOR EACH ROW WHEN (\n";
- $trigger .= "\tnew.{$create_sequence} IS NULL OR new.{$create_sequence} = 0\n";
- $trigger .= ")\n";
- $trigger .= "BEGIN\n";
- $trigger .= "\tSELECT {$table_name}_seq.nextval\n";
- $trigger .= "\tINTO :new.{$create_sequence}\n";
- $trigger .= "\tFROM dual;\n";
- $trigger .= "END;";
-
- $statements[] = $trigger;
- }
- break;
- }
-
- // Write Keys
- if (isset($table_data['KEYS']))
- {
- foreach ($table_data['KEYS'] as $key_name => $key_data)
- {
- if (!is_array($key_data[1]))
- {
- $key_data[1] = array($key_data[1]);
- }
-
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
-
- foreach ($key_stmts as $key_stmt)
- {
- $statements[] = $key_stmt;
- }
-
- $this->return_statements = $old_return_statements;
- }
- }
-
- // Commit Transaction
- $statements[] = 'commit';
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Handle passed database update array.
- * Expected structure...
- * Key being one of the following
- * drop_tables: Drop tables
- * add_tables: Add tables
- * change_columns: Column changes (only type, not name)
- * add_columns: Add columns to a table
- * drop_keys: Dropping keys
- * drop_columns: Removing/Dropping columns
- * add_primary_keys: adding primary keys
- * add_unique_index: adding an unique index
- * add_index: adding an index (can be column:index_size if you need to provide size)
- *
- * The values are in this format:
- * {TABLE NAME} => array(
- * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}),
- * {KEY/INDEX NAME} => array({COLUMN NAMES}),
- * )
- *
- * For more information have a look at /develop/create_schema_files.php (only available through SVN)
- */
- function perform_schema_changes($schema_changes)
- {
- if (empty($schema_changes))
- {
- return;
- }
-
- $statements = array();
- $sqlite = false;
-
- // For SQLite we need to perform the schema changes in a much more different way
- if (($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3') && $this->return_statements)
- {
- $sqlite_data = array();
- $sqlite = true;
- }
-
- // Drop tables?
- if (!empty($schema_changes['drop_tables']))
- {
- foreach ($schema_changes['drop_tables'] as $table)
- {
- // only drop table if it exists
- if ($this->sql_table_exists($table))
- {
- $result = $this->sql_table_drop($table);
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Add tables?
- if (!empty($schema_changes['add_tables']))
- {
- foreach ($schema_changes['add_tables'] as $table => $table_data)
- {
- $result = $this->sql_create_table($table, $table_data);
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
-
- // Change columns?
- if (!empty($schema_changes['change_columns']))
- {
- foreach ($schema_changes['change_columns'] as $table => $columns)
- {
- foreach ($columns as $column_name => $column_data)
- {
- // If the column exists we change it, else we add it ;)
- if ($column_exists = $this->sql_column_exists($table, $column_name))
- {
- $result = $this->sql_column_change($table, $column_name, $column_data, true);
- }
- else
- {
- $result = $this->sql_column_add($table, $column_name, $column_data, true);
- }
-
- if ($sqlite)
- {
- if ($column_exists)
- {
- $sqlite_data[$table]['change_columns'][] = $result;
- }
- else
- {
- $sqlite_data[$table]['add_columns'][] = $result;
- }
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Add columns?
- if (!empty($schema_changes['add_columns']))
- {
- foreach ($schema_changes['add_columns'] as $table => $columns)
- {
- foreach ($columns as $column_name => $column_data)
- {
- // Only add the column if it does not exist yet
- if ($column_exists = $this->sql_column_exists($table, $column_name))
- {
- continue;
- // This is commented out here because it can take tremendous time on updates
-// $result = $this->sql_column_change($table, $column_name, $column_data, true);
- }
- else
- {
- $result = $this->sql_column_add($table, $column_name, $column_data, true);
- }
-
- if ($sqlite)
- {
- if ($column_exists)
- {
- continue;
-// $sqlite_data[$table]['change_columns'][] = $result;
- }
- else
- {
- $sqlite_data[$table]['add_columns'][] = $result;
- }
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Remove keys?
- if (!empty($schema_changes['drop_keys']))
- {
- foreach ($schema_changes['drop_keys'] as $table => $indexes)
- {
- foreach ($indexes as $index_name)
- {
- if (!$this->sql_index_exists($table, $index_name))
- {
- continue;
- }
-
- $result = $this->sql_index_drop($table, $index_name);
-
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Drop columns?
- if (!empty($schema_changes['drop_columns']))
- {
- foreach ($schema_changes['drop_columns'] as $table => $columns)
- {
- foreach ($columns as $column)
- {
- // Only remove the column if it exists...
- if ($this->sql_column_exists($table, $column))
- {
- $result = $this->sql_column_remove($table, $column, true);
-
- if ($sqlite)
- {
- $sqlite_data[$table]['drop_columns'][] = $result;
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
- }
-
- // Add primary keys?
- if (!empty($schema_changes['add_primary_keys']))
- {
- foreach ($schema_changes['add_primary_keys'] as $table => $columns)
- {
- $result = $this->sql_create_primary_key($table, $columns, true);
-
- if ($sqlite)
- {
- $sqlite_data[$table]['primary_key'] = $result;
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
-
- // Add unique indexes?
- if (!empty($schema_changes['add_unique_index']))
- {
- foreach ($schema_changes['add_unique_index'] as $table => $index_array)
- {
- foreach ($index_array as $index_name => $column)
- {
- if ($this->sql_unique_index_exists($table, $index_name))
- {
- continue;
- }
-
- $result = $this->sql_create_unique_index($table, $index_name, $column);
-
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Add indexes?
- if (!empty($schema_changes['add_index']))
- {
- foreach ($schema_changes['add_index'] as $table => $index_array)
- {
- foreach ($index_array as $index_name => $column)
- {
- if ($this->sql_index_exists($table, $index_name))
- {
- continue;
- }
-
- $result = $this->sql_create_index($table, $index_name, $column);
-
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- if ($sqlite)
- {
- foreach ($sqlite_data as $table_name => $sql_schema_changes)
- {
- // Create temporary table with original data
- $statements[] = 'begin';
-
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'table'
- AND name = '{$table_name}'
- ORDER BY type DESC, name;";
- $result = $this->db->sql_query($sql);
-
- if (!$result)
- {
- continue;
- }
-
- $row = $this->db->sql_fetchrow($result);
- $this->db->sql_freeresult($result);
-
- // Create a backup table and populate it, destroy the existing one
- $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']);
- $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
- $statements[] = 'DROP TABLE ' . $table_name;
-
- // Get the columns...
- preg_match('#\((.*)\)#s', $row['sql'], $matches);
-
- $plain_table_cols = trim($matches[1]);
- $new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols);
- $column_list = array();
-
- foreach ($new_table_cols as $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- continue;
- }
- $column_list[] = $entities[0];
- }
-
- // note down the primary key notation because sqlite only supports adding it to the end for the new table
- $primary_key = false;
- $_new_cols = array();
-
- foreach ($new_table_cols as $key => $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- $primary_key = $declaration;
- continue;
- }
- $_new_cols[] = $declaration;
- }
-
- $new_table_cols = $_new_cols;
-
- // First of all... change columns
- if (!empty($sql_schema_changes['change_columns']))
- {
- foreach ($sql_schema_changes['change_columns'] as $column_sql)
- {
- foreach ($new_table_cols as $key => $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if (strpos($column_sql, $entities[0] . ' ') === 0)
- {
- $new_table_cols[$key] = $column_sql;
- }
- }
- }
- }
-
- if (!empty($sql_schema_changes['add_columns']))
- {
- foreach ($sql_schema_changes['add_columns'] as $column_sql)
- {
- $new_table_cols[] = $column_sql;
- }
- }
-
- // Now drop them...
- if (!empty($sql_schema_changes['drop_columns']))
- {
- foreach ($sql_schema_changes['drop_columns'] as $column_name)
- {
- // Remove from column list...
- $new_column_list = array();
- foreach ($column_list as $key => $value)
- {
- if ($value === $column_name)
- {
- continue;
- }
-
- $new_column_list[] = $value;
- }
-
- $column_list = $new_column_list;
-
- // Remove from table...
- $_new_cols = array();
- foreach ($new_table_cols as $key => $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if (strpos($column_name . ' ', $entities[0] . ' ') === 0)
- {
- continue;
- }
- $_new_cols[] = $declaration;
- }
- $new_table_cols = $_new_cols;
- }
- }
-
- // Primary key...
- if (!empty($sql_schema_changes['primary_key']))
- {
- $new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')';
- }
- // Add a new one or the old primary key
- else if ($primary_key !== false)
- {
- $new_table_cols[] = $primary_key;
- }
-
- $columns = implode(',', $column_list);
-
- // create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');';
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
- }
- }
-
- if ($this->return_statements)
- {
- return $statements;
- }
- }
-
- /**
- * Gets a list of columns of a table.
- *
- * @param string $table Table name
- *
- * @return array Array of column names (all lower case)
- */
- function sql_list_columns($table)
- {
- $columns = array();
-
- switch ($this->sql_layer)
- {
- case 'mysql_40':
- case 'mysql_41':
- $sql = "SHOW COLUMNS FROM $table";
- break;
-
- // PostgreSQL has a way of doing this in a much simpler way but would
- // not allow us to support all versions of PostgreSQL
- case 'postgres':
- $sql = "SELECT a.attname
- FROM pg_class c, pg_attribute a
- WHERE c.relname = '{$table}'
- AND a.attnum > 0
- AND a.attrelid = c.oid";
- break;
-
- // same deal with PostgreSQL, we must perform more complex operations than
- // we technically could
- case 'mssql':
- case 'mssqlnative':
- $sql = "SELECT c.name
- FROM syscolumns c
- LEFT JOIN sysobjects o ON c.id = o.id
- WHERE o.name = '{$table}'";
- break;
-
- case 'oracle':
- $sql = "SELECT column_name
- FROM user_tab_columns
- WHERE LOWER(table_name) = '" . strtolower($table) . "'";
- break;
-
- case 'sqlite':
- case 'sqlite3':
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'table'
- AND name = '{$table}'";
-
- $result = $this->db->sql_query($sql);
-
- if (!$result)
- {
- return false;
- }
-
- $row = $this->db->sql_fetchrow($result);
- $this->db->sql_freeresult($result);
-
- preg_match('#\((.*)\)#s', $row['sql'], $matches);
-
- $cols = trim($matches[1]);
- $col_array = preg_split('/,(?![\s\w]+\))/m', $cols);
-
- foreach ($col_array as $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- continue;
- }
-
- $column = strtolower($entities[0]);
- $columns[$column] = $column;
- }
-
- return $columns;
- break;
- }
-
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- $column = strtolower(current($row));
- $columns[$column] = $column;
- }
- $this->db->sql_freeresult($result);
-
- return $columns;
- }
-
- /**
- * Check whether a specified column exist in a table
- *
- * @param string $table Table to check
- * @param string $column_name Column to check
- *
- * @return bool True if column exists, false otherwise
- */
- function sql_column_exists($table, $column_name)
- {
- $columns = $this->sql_list_columns($table);
-
- return isset($columns[$column_name]);
- }
-
- /**
- * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes.
- *
- * @param string $table_name Table to check the index at
- * @param string $index_name The index name to check
- *
- * @return bool True if index exists, else false
- */
- function sql_index_exists($table_name, $index_name)
- {
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- if ($row['TYPE'] == 3)
- {
- if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- }
- $this->db->sql_freeresult($result);
-
- return false;
- }
-
- switch ($this->sql_layer)
- {
- case 'postgres':
- $sql = "SELECT ic.relname as index_name
- FROM pg_class bc, pg_class ic, pg_index i
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (bc.relname = '" . $table_name . "')
- AND (i.indisunique != 't')
- AND (i.indisprimary != 't')";
- $col = 'index_name';
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $sql = 'SHOW KEYS
- FROM ' . $table_name;
- $col = 'Key_name';
- break;
-
- case 'oracle':
- $sql = "SELECT index_name
- FROM user_indexes
- WHERE table_name = '" . strtoupper($table_name) . "'
- AND generated = 'N'
- AND uniqueness = 'NONUNIQUE'";
- $col = 'index_name';
- break;
-
- case 'sqlite':
- case 'sqlite3':
- $sql = "PRAGMA index_list('" . $table_name . "');";
- $col = 'name';
- break;
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique'])
- {
- continue;
- }
-
- // These DBMS prefix index name with the table name
- switch ($this->sql_layer)
- {
- case 'oracle':
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- $row[$col] = substr($row[$col], strlen($table_name) + 1);
- break;
- }
-
- if (strtolower($row[$col]) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- $this->db->sql_freeresult($result);
-
- return false;
- }
-
- /**
- * Check if a specified index exists in table. Does not return PRIMARY KEY indexes.
- *
- * @param string $table_name Table to check the index at
- * @param string $index_name The index name to check
- *
- * @return bool True if index exists, else false
- */
- function sql_unique_index_exists($table_name, $index_name)
- {
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- // Usually NON_UNIQUE is the column we want to check, but we allow for both
- if ($row['TYPE'] == 3)
- {
- if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- }
- $this->db->sql_freeresult($result);
- return false;
- }
-
- switch ($this->sql_layer)
- {
- case 'postgres':
- $sql = "SELECT ic.relname as index_name, i.indisunique
- FROM pg_class bc, pg_class ic, pg_index i
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (bc.relname = '" . $table_name . "')
- AND (i.indisprimary != 't')";
- $col = 'index_name';
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $sql = 'SHOW KEYS
- FROM ' . $table_name;
- $col = 'Key_name';
- break;
-
- case 'oracle':
- $sql = "SELECT index_name, table_owner
- FROM user_indexes
- WHERE table_name = '" . strtoupper($table_name) . "'
- AND generated = 'N'
- AND uniqueness = 'UNIQUE'";
- $col = 'index_name';
- break;
-
- case 'sqlite':
- case 'sqlite3':
- $sql = "PRAGMA index_list('" . $table_name . "');";
- $col = 'name';
- break;
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && ($row['Non_unique'] || $row[$col] == 'PRIMARY'))
- {
- continue;
- }
-
- if (($this->sql_layer == 'sqlite' || $this->sql_layer == 'sqlite3') && !$row['unique'])
- {
- continue;
- }
-
- if ($this->sql_layer == 'postgres' && $row['indisunique'] != 't')
- {
- continue;
- }
-
- // These DBMS prefix index name with the table name
- switch ($this->sql_layer)
- {
- case 'oracle':
- // Two cases here... prefixed with U_[table_owner] and not prefixed with table_name
- if (strpos($row[$col], 'U_') === 0)
- {
- $row[$col] = substr($row[$col], strlen('U_' . $row['table_owner']) + 1);
- }
- else if (strpos($row[$col], strtoupper($table_name)) === 0)
- {
- $row[$col] = substr($row[$col], strlen($table_name) + 1);
- }
- break;
-
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- $row[$col] = substr($row[$col], strlen($table_name) + 1);
- break;
- }
-
- if (strtolower($row[$col]) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- $this->db->sql_freeresult($result);
-
- return false;
- }
-
- /**
- * Private method for performing sql statements (either execute them or return them)
- * @access private
- */
- function _sql_run_sql($statements)
- {
- if ($this->return_statements)
- {
- return $statements;
- }
-
- // We could add error handling here...
- foreach ($statements as $sql)
- {
- if ($sql === 'begin')
- {
- $this->db->sql_transaction('begin');
- }
- else if ($sql === 'commit')
- {
- $this->db->sql_transaction('commit');
- }
- else
- {
- $this->db->sql_query($sql);
- }
- }
-
- return true;
- }
-
- /**
- * Function to prepare some column information for better usage
- * @access private
- */
- function sql_prepare_column_data($table_name, $column_name, $column_data)
- {
- if (strlen($column_name) > 30)
- {
- trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
- }
-
- // Get type
- list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]);
-
- // Adjust default value if db-dependent specified
- if (is_array($column_data[1]))
- {
- $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
- }
-
- $sql = '';
-
- $return_array = array();
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $sql .= " {$column_type} ";
- $sql_default = " {$column_type} ";
-
- // For adding columns we need the default definition
- if (!is_null($column_data[1]))
- {
- // For hexadecimal values do not use single quotes
- if (strpos($column_data[1], '0x') === 0)
- {
- $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') ';
- $sql_default .= $return_array['default'];
- }
- else
- {
- $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
- $sql_default .= $return_array['default'];
- }
- }
-
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
-// $sql .= 'IDENTITY (1, 1) ';
- $sql_default .= 'IDENTITY (1, 1) ';
- }
-
- $return_array['textimage'] = $column_type === '[text]';
-
- if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
- {
- $sql .= 'NOT NULL';
- $sql_default .= 'NOT NULL';
- }
- else
- {
- $sql .= 'NULL';
- $sql_default .= 'NULL';
- }
-
- $return_array['column_type_sql_default'] = $sql_default;
-
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $sql .= " {$column_type} ";
-
- // For hexadecimal values do not use single quotes
- if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob')
- {
- $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
- }
-
- if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
- {
- $sql .= 'NOT NULL';
- }
- else
- {
- $sql .= 'NULL';
- }
-
- if (isset($column_data[2]))
- {
- if ($column_data[2] == 'auto_increment')
- {
- $sql .= ' auto_increment';
- }
- else if ($this->sql_layer === 'mysql_41' && $column_data[2] == 'true_sort')
- {
- $sql .= ' COLLATE utf8_unicode_ci';
- }
- }
-
- if (isset($column_data['after']))
- {
- $return_array['after'] = $column_data['after'];
- }
-
- break;
-
- case 'oracle':
- $sql .= " {$column_type} ";
- $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
-
- // In Oracle empty strings ('') are treated as NULL.
- // Therefore in oracle we allow NULL's for all DEFAULT '' entries
- // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields)
- if (!preg_match('/number/i', $column_type))
- {
- $sql .= ($column_data[1] === '' || $column_data[1] === null) ? '' : 'NOT NULL';
- }
-
- $return_array['auto_increment'] = false;
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
- $return_array['auto_increment'] = true;
- }
-
- break;
-
- case 'postgres':
- $return_array['column_type'] = $column_type;
-
- $sql .= " {$column_type} ";
-
- $return_array['auto_increment'] = false;
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
- $default_val = "nextval('{$table_name}_seq')";
- $return_array['auto_increment'] = true;
- }
- else if (!is_null($column_data[1]))
- {
- $default_val = "'" . $column_data[1] . "'";
- $return_array['null'] = 'NOT NULL';
- $sql .= 'NOT NULL ';
- }
- else
- {
- // Integers need to have 0 instead of empty string as default
- if (strpos($column_type, 'INT') === 0)
- {
- $default_val = '0';
- }
- else
- {
- $default_val = "'" . $column_data[1] . "'";
- }
- $return_array['null'] = 'NULL';
- $sql .= 'NULL ';
- }
-
- $return_array['default'] = $default_val;
-
- $sql .= "DEFAULT {$default_val}";
-
- // Unsigned? Then add a CHECK contraint
- if (in_array($orig_column_type, $this->unsigned_types))
- {
- $return_array['constraint'] = "CHECK ({$column_name} >= 0)";
- $sql .= " CHECK ({$column_name} >= 0)";
- }
-
- break;
-
- case 'sqlite':
- case 'sqlite3':
- $return_array['primary_key_set'] = false;
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
- $sql .= ' INTEGER PRIMARY KEY';
- $return_array['primary_key_set'] = true;
-
- if ($this->sql_layer === 'sqlite3')
- {
- $sql .= ' AUTOINCREMENT';
- }
- }
- else
- {
- $sql .= ' ' . $column_type;
- }
-
- if (!is_null($column_data[1]))
- {
- $sql .= ' NOT NULL ';
- $sql .= "DEFAULT '{$column_data[1]}'";
- }
-
- break;
- }
-
- $return_array['column_type_sql'] = $sql;
-
- return $return_array;
- }
-
- /**
- * Get the column's database type from the type map
- *
- * @param string $column_map_type
- * @return array column type for this database
- * and map type without length
- */
- function get_column_type($column_map_type)
- {
- if (strpos($column_map_type, ':') !== false)
- {
- list($orig_column_type, $column_length) = explode(':', $column_map_type);
- if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']))
- {
- $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length);
- }
- else
- {
- if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule']))
- {
- switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0])
- {
- case 'div':
- $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1];
- $column_length = ceil($column_length);
- $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
- break;
- }
- }
-
- if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit']))
- {
- switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0])
- {
- case 'mult':
- $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1];
- if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2])
- {
- $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3];
- }
- else
- {
- $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
- }
- break;
- }
- }
- }
- $orig_column_type .= ':';
- }
- else
- {
- $orig_column_type = $column_map_type;
- $column_type = $this->dbms_type_map[$this->sql_layer][$column_map_type];
- }
-
- return array($column_type, $orig_column_type);
- }
-
- /**
- * Add new column
- */
- function sql_column_add($table_name, $column_name, $column_data, $inline = false)
- {
- $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- // Does not support AFTER, only through temporary table
- $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $after = (!empty($column_data['after'])) ? ' AFTER ' . $column_data['after'] : '';
- $statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'] . $after;
- break;
-
- case 'oracle':
- // Does not support AFTER, only through temporary table
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
- break;
-
- case 'postgres':
- // Does not support AFTER, only through temporary table
- if (version_compare($this->db->sql_server_info(true), '8.0', '>='))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
- }
- else
- {
- // old versions cannot add columns with default and null information
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint'];
-
- if (isset($column_data['null']))
- {
- if ($column_data['null'] == 'NOT NULL')
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL';
- }
- }
-
- if (isset($column_data['default']))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
- }
- }
-
- break;
-
- case 'sqlite':
- if ($inline && $this->return_statements)
- {
- return $column_name . ' ' . $column_data['column_type_sql'];
- }
-
- $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name);
- if (empty($recreate_queries))
- {
- break;
- }
-
- $statements[] = 'begin';
-
- $sql_create_table = array_shift($recreate_queries);
-
- // Create a backup table and populate it, destroy the existing one
- $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
- $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
- $statements[] = 'DROP TABLE ' . $table_name;
-
- preg_match('#\((.*)\)#s', $sql_create_table, $matches);
-
- $new_table_cols = trim($matches[1]);
- $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
- $column_list = array();
-
- foreach ($old_table_cols as $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- continue;
- }
- $column_list[] = $entities[0];
- }
-
- $columns = implode(',', $column_list);
-
- $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols;
-
- // create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');';
- $statements = array_merge($statements, $recreate_queries);
-
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
- break;
-
- case 'sqlite3':
- if ($inline && $this->return_statements)
- {
- return $column_name . ' ' . $column_data['column_type_sql'];
- }
-
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Drop column
- */
- function sql_column_remove($table_name, $column_name, $inline = false)
- {
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $indexes = $this->get_existing_indexes($table_name, $column_name);
- $indexes = array_merge($indexes, $this->get_existing_indexes($table_name, $column_name, true));
-
- // Drop any indexes
- $recreate_indexes = array();
- if (!empty($indexes))
- {
- foreach ($indexes as $index_name => $index_data)
- {
- $result = $this->sql_index_drop($table_name, $index_name);
- $statements = array_merge($statements, $result);
- if (sizeof($index_data) > 1)
- {
- // Remove this column from the index and recreate it
- $recreate_indexes[$index_name] = array_diff($index_data, array($column_name));
- }
- }
- }
-
- // Drop default value constraint
- $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
- $statements = array_merge($statements, $result);
-
- // Remove the column
- $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
-
- if (!empty($recreate_indexes))
- {
- // Recreate indexes after we removed the column
- foreach ($recreate_indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_index($table_name, $index_name, $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';
- break;
-
- case 'oracle':
- $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
- break;
-
- case 'postgres':
- $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
- break;
-
- case 'sqlite':
- case 'sqlite3':
-
- if ($inline && $this->return_statements)
- {
- return $column_name;
- }
-
- $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name, $column_name);
- if (empty($recreate_queries))
- {
- break;
- }
-
- $statements[] = 'begin';
-
- $sql_create_table = array_shift($recreate_queries);
-
- // Create a backup table and populate it, destroy the existing one
- $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
- $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
- $statements[] = 'DROP TABLE ' . $table_name;
-
- preg_match('#\((.*)\)#s', $sql_create_table, $matches);
-
- $new_table_cols = trim($matches[1]);
- $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
- $column_list = array();
-
- foreach ($old_table_cols as $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name)
- {
- continue;
- }
- $column_list[] = $entities[0];
- }
-
- $columns = implode(',', $column_list);
-
- $new_table_cols = trim(preg_replace('/' . $column_name . '\b[^,]+(?:,|$)/m', '', $new_table_cols));
- if (substr($new_table_cols, -1) === ',')
- {
- // Remove the comma from the last entry again
- $new_table_cols = substr($new_table_cols, 0, -1);
- }
-
- // create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');';
- $statements = array_merge($statements, $recreate_queries);
-
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Drop Index
- */
- function sql_index_drop($table_name, $index_name)
- {
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name;
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
- break;
-
- case 'oracle':
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Drop Table
- */
- function sql_table_drop($table_name)
- {
- $statements = array();
-
- if (!$this->sql_table_exists($table_name))
- {
- return $this->_sql_run_sql($statements);
- }
-
- // the most basic operation, get rid of the table
- $statements[] = 'DROP TABLE ' . $table_name;
-
- switch ($this->sql_layer)
- {
- case 'oracle':
- $sql = 'SELECT A.REFERENCED_NAME
- FROM USER_DEPENDENCIES A, USER_TRIGGERS B
- WHERE A.REFERENCED_TYPE = \'SEQUENCE\'
- AND A.NAME = B.TRIGGER_NAME
- AND B.TABLE_NAME = \'' . strtoupper($table_name) . "'";
- $result = $this->db->sql_query($sql);
-
- // any sequences ref'd to this table's triggers?
- while ($row = $this->db->sql_fetchrow($result))
- {
- $statements[] = "DROP SEQUENCE {$row['referenced_name']}";
- }
- $this->db->sql_freeresult($result);
- break;
-
- case 'postgres':
- // PGSQL does not "tightly" bind sequences and tables, we must guess...
- $sql = "SELECT relname
- FROM pg_class
- WHERE relkind = 'S'
- AND relname = '{$table_name}_seq'";
- $result = $this->db->sql_query($sql);
-
- // We don't even care about storing the results. We already know the answer if we get rows back.
- if ($this->db->sql_fetchrow($result))
- {
- $statements[] = "DROP SEQUENCE {$table_name}_seq;\n";
- }
- $this->db->sql_freeresult($result);
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Add primary key
- */
- function sql_create_primary_key($table_name, $column, $inline = false)
- {
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'postgres':
- case 'mysql_40':
- case 'mysql_41':
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
- $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
- $sql .= '[' . implode("],\n\t\t[", $column) . ']';
- $sql .= ')';
-
- $statements[] = $sql;
- break;
-
- case 'oracle':
- $statements[] = 'ALTER TABLE ' . $table_name . ' add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
- break;
-
- case 'sqlite':
- case 'sqlite3':
-
- if ($inline && $this->return_statements)
- {
- return $column;
- }
-
- $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name);
- if (empty($recreate_queries))
- {
- break;
- }
-
- $statements[] = 'begin';
-
- $sql_create_table = array_shift($recreate_queries);
-
- // Create a backup table and populate it, destroy the existing one
- $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
- $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
- $statements[] = 'DROP TABLE ' . $table_name;
-
- preg_match('#\((.*)\)#s', $sql_create_table, $matches);
-
- $new_table_cols = trim($matches[1]);
- $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
- $column_list = array();
-
- foreach ($old_table_cols as $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- continue;
- }
- $column_list[] = $entities[0];
- }
-
- $columns = implode(',', $column_list);
-
- // create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));';
- $statements = array_merge($statements, $recreate_queries);
-
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Add unique index
- */
- function sql_create_unique_index($table_name, $index_name, $column)
- {
- $statements = array();
-
- $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
- if (strlen($table_name . '_' . $index_name) - strlen($table_prefix) > 24)
- {
- $max_length = strlen($table_prefix) + 24;
- trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
- }
-
- switch ($this->sql_layer)
- {
- case 'postgres':
- case 'oracle':
- case 'sqlite':
- case 'sqlite3':
- $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Add index
- */
- function sql_create_index($table_name, $index_name, $column)
- {
- $statements = array();
-
- $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
- if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
- {
- $max_length = strlen($table_prefix) + 24;
- trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
- }
-
- // remove index length unless MySQL4
- if ('mysql_40' != $this->sql_layer)
- {
- $column = preg_replace('#:.*$#', '', $column);
- }
-
- switch ($this->sql_layer)
- {
- case 'postgres':
- case 'oracle':
- case 'sqlite':
- case 'sqlite3':
- $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
- break;
-
- case 'mysql_40':
- // add index size to definition as required by MySQL4
- foreach ($column as $i => $col)
- {
- if (false !== strpos($col, ':'))
- {
- list($col, $index_size) = explode(':', $col);
- $column[$i] = "$col($index_size)";
- }
- }
- // no break
- case 'mysql_41':
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * List all of the indices that belong to a table,
- * does not count:
- * * UNIQUE indices
- * * PRIMARY keys
- */
- function sql_list_index($table_name)
- {
- $index_array = array();
-
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if ($row['TYPE'] == 3)
- {
- $index_array[] = $row['INDEX_NAME'];
- }
- }
- $this->db->sql_freeresult($result);
- }
- else
- {
- switch ($this->sql_layer)
- {
- case 'postgres':
- $sql = "SELECT ic.relname as index_name
- FROM pg_class bc, pg_class ic, pg_index i
- WHERE (bc.oid = i.indrelid)
- AND (ic.oid = i.indexrelid)
- AND (bc.relname = '" . $table_name . "')
- AND (i.indisunique != 't')
- AND (i.indisprimary != 't')";
- $col = 'index_name';
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $sql = 'SHOW KEYS
- FROM ' . $table_name;
- $col = 'Key_name';
- break;
-
- case 'oracle':
- $sql = "SELECT index_name
- FROM user_indexes
- WHERE table_name = '" . strtoupper($table_name) . "'
- AND generated = 'N'
- AND uniqueness = 'NONUNIQUE'";
- $col = 'index_name';
- break;
-
- case 'sqlite':
- case 'sqlite3':
- $sql = "PRAGMA index_info('" . $table_name . "');";
- $col = 'name';
- break;
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique'])
- {
- continue;
- }
-
- switch ($this->sql_layer)
- {
- case 'oracle':
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- $row[$col] = substr($row[$col], strlen($table_name) + 1);
- break;
- }
-
- $index_array[] = $row[$col];
- }
- $this->db->sql_freeresult($result);
- }
-
- return array_map('strtolower', $index_array);
- }
-
- /**
- * Removes table_name from the index_name if it is at the beginning
- *
- * @param $table_name
- * @param $index_name
- * @return string
- */
- protected function strip_table_name_from_index_name($table_name, $index_name)
- {
- return (strpos(strtoupper($index_name), strtoupper($table_name)) === 0) ? substr($index_name, strlen($table_name) + 1) : $index_name;
- }
-
- /**
- * Change column type (not name!)
- */
- function sql_column_change($table_name, $column_name, $column_data, $inline = false)
- {
- $original_column_data = $column_data;
- $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $indexes = $this->get_existing_indexes($table_name, $column_name);
- $unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
-
- // Drop any indexes
- if (!empty($indexes) || !empty($unique_indexes))
- {
- $drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
- foreach ($drop_indexes as $index_name)
- {
- $result = $this->sql_index_drop($table_name, $index_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);
-
- // Change the column
- $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
-
- if (!empty($column_data['default']))
- {
- // Add new default value constraint
- $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $column_data['default'] . ' FOR [' . $column_name . ']';
- }
-
- if (!empty($indexes))
- {
- // Recreate indexes after we changed the column
- foreach ($indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_index($table_name, $index_name, $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- if (!empty($unique_indexes))
- {
- // Recreate unique indexes after we changed the column
- foreach ($unique_indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_unique_index($table_name, $index_name, $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
- break;
-
- case 'oracle':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- // Get list of existing indexes
- $indexes = $this->get_existing_indexes($table_name, $column_name);
- $unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
-
- // Drop any indexes
- if (!empty($indexes) || !empty($unique_indexes))
- {
- $drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
- foreach ($drop_indexes as $index_name)
- {
- $result = $this->sql_index_drop($table_name, $this->strip_table_name_from_index_name($table_name, $index_name));
- $statements = array_merge($statements, $result);
- }
- }
-
- $temp_column_name = 'temp_' . substr(md5($column_name), 0, 25);
- // Add a temporary table with the new type
- $result = $this->sql_column_add($table_name, $temp_column_name, $original_column_data);
- $statements = array_merge($statements, $result);
-
- // Copy the data to the new column
- $statements[] = 'UPDATE ' . $table_name . ' SET ' . $temp_column_name . ' = ' . $column_name;
-
- // Drop the original column
- $result = $this->sql_column_remove($table_name, $column_name);
- $statements = array_merge($statements, $result);
-
- // Recreate the original column with the new type
- $result = $this->sql_column_add($table_name, $column_name, $original_column_data);
- $statements = array_merge($statements, $result);
-
- if (!empty($indexes))
- {
- // Recreate indexes after we changed the column
- foreach ($indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_index($table_name, $this->strip_table_name_from_index_name($table_name, $index_name), $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- if (!empty($unique_indexes))
- {
- // Recreate unique indexes after we changed the column
- foreach ($unique_indexes as $index_name => $index_data)
- {
- $result = $this->sql_create_unique_index($table_name, $this->strip_table_name_from_index_name($table_name, $index_name), $index_data);
- $statements = array_merge($statements, $result);
- }
- }
-
- // Copy the data to the original column
- $statements[] = 'UPDATE ' . $table_name . ' SET ' . $column_name . ' = ' . $temp_column_name;
-
- // Drop the temporary column again
- $result = $this->sql_column_remove($table_name, $temp_column_name);
- $statements = array_merge($statements, $result);
-
- $this->return_statements = $old_return_statements;
- break;
-
- case 'postgres':
- $sql = 'ALTER TABLE ' . $table_name . ' ';
-
- $sql_array = array();
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
-
- if (isset($column_data['null']))
- {
- if ($column_data['null'] == 'NOT NULL')
- {
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
- }
- else if ($column_data['null'] == 'NULL')
- {
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
- }
- }
-
- if (isset($column_data['default']))
- {
- $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
- }
-
- // we don't want to double up on constraints if we change different number data types
- if (isset($column_data['constraint']))
- {
- $constraint_sql = "SELECT consrc as constraint_data
- FROM pg_constraint, pg_class bc
- WHERE conrelid = bc.oid
- AND bc.relname = '{$table_name}'
- AND NOT EXISTS (
- SELECT *
- FROM pg_constraint as c, pg_inherits as i
- WHERE i.inhrelid = pg_constraint.conrelid
- AND c.conname = pg_constraint.conname
- AND c.consrc = pg_constraint.consrc
- AND c.conrelid = i.inhparent
- )";
-
- $constraint_exists = false;
-
- $result = $this->db->sql_query($constraint_sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if (trim($row['constraint_data']) == trim($column_data['constraint']))
- {
- $constraint_exists = true;
- break;
- }
- }
- $this->db->sql_freeresult($result);
-
- if (!$constraint_exists)
- {
- $sql_array[] = 'ADD ' . $column_data['constraint'];
- }
- }
-
- $sql .= implode(', ', $sql_array);
-
- $statements[] = $sql;
- break;
-
- case 'sqlite':
- case 'sqlite3':
-
- if ($inline && $this->return_statements)
- {
- return $column_name . ' ' . $column_data['column_type_sql'];
- }
-
- $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name);
- if (empty($recreate_queries))
- {
- break;
- }
-
- $statements[] = 'begin';
-
- $sql_create_table = array_shift($recreate_queries);
-
- // Create a temp table and populate it, destroy the existing one
- $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
- $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
- $statements[] = 'DROP TABLE ' . $table_name;
-
- preg_match('#\((.*)\)#s', $sql_create_table, $matches);
-
- $new_table_cols = trim($matches[1]);
- $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
- $column_list = array();
-
- foreach ($old_table_cols as $key => $declaration)
- {
- $declaration = trim($declaration);
-
- // Check for the beginning of the constraint section and stop
- if (preg_match('/[^\(]*\s*PRIMARY KEY\s+\(/', $declaration) ||
- preg_match('/[^\(]*\s*UNIQUE\s+\(/', $declaration) ||
- preg_match('/[^\(]*\s*FOREIGN KEY\s+\(/', $declaration) ||
- preg_match('/[^\(]*\s*CHECK\s+\(/', $declaration))
- {
- break;
- }
-
- $entities = preg_split('#\s+#', $declaration);
- $column_list[] = $entities[0];
- if ($entities[0] == $column_name)
- {
- $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql'];
- }
- }
-
- $columns = implode(',', $column_list);
-
- // Create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');';
- $statements = array_merge($statements, $recreate_queries);
-
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
-
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Get queries to drop the default constraints of a column
- *
- * We need to drop the default constraints of a column,
- * before being able to change their type or deleting them.
- *
- * @param string $table_name
- * @param string $column_name
- * @return array Array with SQL statements
- */
- protected function mssql_get_drop_default_constraints_queries($table_name, $column_name)
- {
- $statements = array();
- if ($this->mssql_is_sql_server_2000())
- {
- // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
- // Deprecated in SQL Server 2005
- $sql = "SELECT so.name AS def_name
- FROM sysobjects so
- JOIN sysconstraints sc ON so.id = sc.constid
- WHERE object_name(so.parent_obj) = '{$table_name}'
- AND so.xtype = 'D'
- AND sc.colid = (SELECT colid FROM syscolumns
- WHERE id = object_id('{$table_name}')
- AND name = '{$column_name}')";
- }
- else
- {
- $sql = "SELECT dobj.name AS def_name
- FROM sys.columns col
- LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D')
- WHERE col.object_id = object_id('{$table_name}')
- AND col.name = '{$column_name}'
- AND dobj.name IS NOT NULL";
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']';
- }
- $this->db->sql_freeresult($result);
-
- return $statements;
- }
-
- /**
- * Get a list with existing indexes for the column
- *
- * @param string $table_name
- * @param string $column_name
- * @param bool $unique Should we get unique indexes or normal ones
- * @return array Array with Index name => columns
- */
- public function get_existing_indexes($table_name, $column_name, $unique = false)
- {
- switch ($this->sql_layer)
- {
- case 'mysql_40':
- case 'mysql_41':
- case 'postgres':
- case 'sqlite':
- case 'sqlite3':
- // Not supported
- throw new \Exception('DBMS is not supported');
- break;
- }
-
- $sql = '';
- $existing_indexes = array();
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- if ($this->mssql_is_sql_server_2000())
- {
- // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
- // Deprecated in SQL Server 2005
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
- FROM sysindexes ix
- INNER JOIN sysindexkeys ixc
- ON ixc.id = ix.id
- AND ixc.indid = ix.indid
- INNER JOIN syscolumns cols
- ON cols.colid = ixc.colid
- AND cols.id = ix.id
- WHERE ix.id = object_id('{$table_name}')
- AND cols.name = '{$column_name}'
- AND INDEXPROPERTY(ix.id, ix.name, 'IsUnique') = " . ($unique ? '1' : '0');
- }
- else
- {
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
- FROM sys.indexes ix
- INNER JOIN sys.index_columns ixc
- ON ixc.object_id = ix.object_id
- AND ixc.index_id = ix.index_id
- INNER JOIN sys.columns cols
- ON cols.column_id = ixc.column_id
- AND cols.object_id = ix.object_id
- WHERE ix.object_id = object_id('{$table_name}')
- AND cols.name = '{$column_name}'
- AND ix.is_unique = " . ($unique ? '1' : '0');
- }
- break;
-
- case 'oracle':
- $sql = "SELECT ix.index_name AS phpbb_index_name, ix.uniqueness AS is_unique
- FROM all_ind_columns ixc, all_indexes ix
- WHERE ix.index_name = ixc.index_name
- AND ixc.table_name = '" . strtoupper($table_name) . "'
- AND ixc.column_name = '" . strtoupper($column_name) . "'";
- break;
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- if (!isset($row['is_unique']) || ($unique && $row['is_unique'] == 'UNIQUE') || (!$unique && $row['is_unique'] == 'NONUNIQUE'))
- {
- $existing_indexes[$row['phpbb_index_name']] = array();
- }
- }
- $this->db->sql_freeresult($result);
-
- if (empty($existing_indexes))
- {
- return array();
- }
-
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- if ($this->mssql_is_sql_server_2000())
- {
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
- FROM sysindexes ix
- INNER JOIN sysindexkeys ixc
- ON ixc.id = ix.id
- AND ixc.indid = ix.indid
- INNER JOIN syscolumns cols
- ON cols.colid = ixc.colid
- AND cols.id = ix.id
- WHERE ix.id = object_id('{$table_name}')
- AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
- }
- else
- {
- $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
- FROM sys.indexes ix
- INNER JOIN sys.index_columns ixc
- ON ixc.object_id = ix.object_id
- AND ixc.index_id = ix.index_id
- INNER JOIN sys.columns cols
- ON cols.column_id = ixc.column_id
- AND cols.object_id = ix.object_id
- WHERE ix.object_id = object_id('{$table_name}')
- AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
- }
- break;
-
- case 'oracle':
- $sql = "SELECT index_name AS phpbb_index_name, column_name AS phpbb_column_name
- FROM all_ind_columns
- WHERE table_name = '" . strtoupper($table_name) . "'
- AND " . $this->db->sql_in_set('index_name', array_keys($existing_indexes));
- break;
- }
-
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name'];
- }
- $this->db->sql_freeresult($result);
-
- return $existing_indexes;
- }
-
- /**
- * Is the used MS SQL Server a SQL Server 2000?
- *
- * @return bool
- */
- protected function mssql_is_sql_server_2000()
- {
- if ($this->is_sql_server_2000 === null)
- {
- $sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version";
- $result = $this->db->sql_query($sql);
- $properties = $this->db->sql_fetchrow($result);
- $this->db->sql_freeresult($result);
- $this->is_sql_server_2000 = $properties['mssql_version'][0] == '8';
- }
-
- return $this->is_sql_server_2000;
- }
-
- /**
- * Returns the Queries which are required to recreate a table including indexes
- *
- * @param string $table_name
- * @param string $remove_column When we drop a column, we remove the column
- * from all indexes. If the index has no other
- * column, we drop it completly.
- * @return array
- */
- protected function sqlite_get_recreate_table_queries($table_name, $remove_column = '')
- {
- $queries = array();
-
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'table'
- AND name = '{$table_name}'";
- $result = $this->db->sql_query($sql);
- $sql_create_table = $this->db->sql_fetchfield('sql');
- $this->db->sql_freeresult($result);
-
- if (!$sql_create_table)
- {
- return array();
- }
- $queries[] = $sql_create_table;
-
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'index'
- AND tbl_name = '{$table_name}'";
- $result = $this->db->sql_query($sql);
- while ($sql_create_index = $this->db->sql_fetchfield('sql'))
- {
- if ($remove_column)
- {
- $match = array();
- preg_match('#(?:[\w ]+)\((.*)\)#', $sql_create_index, $match);
- if (!isset($match[1]))
- {
- continue;
- }
-
- // Find and remove $remove_column from the index
- $columns = explode(', ', $match[1]);
- $found_column = array_search($remove_column, $columns);
- if ($found_column !== false)
- {
- unset($columns[$found_column]);
-
- // If the column list is not empty add the index to the list
- if (!empty($columns))
- {
- $queries[] = str_replace($match[1], implode(', ', $columns), $sql_create_index);
- }
- }
- else
- {
- $queries[] = $sql_create_index;
- }
- }
- else
- {
- $queries[] = $sql_create_index;
- }
- }
- $this->db->sql_freeresult($result);
-
- return $queries;
- }
-}
diff --git a/phpBB/phpbb/db/tools/factory.php b/phpBB/phpbb/db/tools/factory.php
new file mode 100644
index 0000000000..96471c3408
--- /dev/null
+++ b/phpBB/phpbb/db/tools/factory.php
@@ -0,0 +1,43 @@
+<?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\tools;
+
+/**
+ * A factory which serves the suitable tools instance for the given dbal
+ */
+class factory
+{
+ /**
+ * @param mixed $db_driver
+ * @param bool $return_statements
+ * @return \phpbb\db\tools\tools_interface
+ */
+ public function get($db_driver, $return_statements = false)
+ {
+ if ($db_driver instanceof \phpbb\db\driver\mssql_base)
+ {
+ return new \phpbb\db\tools\mssql($db_driver, $return_statements);
+ }
+ else if ($db_driver instanceof \phpbb\db\driver\postgres)
+ {
+ return new \phpbb\db\tools\postgres($db_driver, $return_statements);
+ }
+ else if ($db_driver instanceof \phpbb\db\driver\driver_interface)
+ {
+ return new \phpbb\db\tools\tools($db_driver, $return_statements);
+ }
+
+ throw new \InvalidArgumentException('Invalid database driver given');
+ }
+}
diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php
new file mode 100644
index 0000000000..a132832005
--- /dev/null
+++ b/phpBB/phpbb/db/tools/mssql.php
@@ -0,0 +1,794 @@
+<?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\tools;
+
+/**
+ * Database Tools for handling cross-db actions such as altering columns, etc.
+ * Currently not supported is returning SQL for creating tables.
+ */
+class mssql extends tools
+{
+ /**
+ * Is the used MS SQL Server a SQL Server 2000?
+ * @var bool
+ */
+ protected $is_sql_server_2000;
+
+ /**
+ * Get the column types for mssql based databases
+ *
+ * @return array
+ */
+ public static function get_dbms_type_map()
+ {
+ return array(
+ 'mssql' => array(
+ 'INT:' => '[int]',
+ 'BINT' => '[float]',
+ 'ULINT' => '[int]',
+ 'UINT' => '[int]',
+ 'UINT:' => '[int]',
+ 'TINT:' => '[int]',
+ 'USINT' => '[int]',
+ 'BOOL' => '[int]',
+ 'VCHAR' => '[varchar] (255)',
+ 'VCHAR:' => '[varchar] (%d)',
+ 'CHAR:' => '[char] (%d)',
+ 'XSTEXT' => '[varchar] (1000)',
+ 'STEXT' => '[varchar] (3000)',
+ 'TEXT' => '[varchar] (8000)',
+ 'MTEXT' => '[text]',
+ 'XSTEXT_UNI'=> '[varchar] (100)',
+ 'STEXT_UNI' => '[varchar] (255)',
+ 'TEXT_UNI' => '[varchar] (4000)',
+ 'MTEXT_UNI' => '[text]',
+ 'TIMESTAMP' => '[int]',
+ 'DECIMAL' => '[float]',
+ 'DECIMAL:' => '[float]',
+ 'PDECIMAL' => '[float]',
+ 'PDECIMAL:' => '[float]',
+ 'VCHAR_UNI' => '[varchar] (255)',
+ 'VCHAR_UNI:'=> '[varchar] (%d)',
+ 'VCHAR_CI' => '[varchar] (255)',
+ 'VARBINARY' => '[varchar] (255)',
+ ),
+
+ 'mssqlnative' => array(
+ 'INT:' => '[int]',
+ 'BINT' => '[float]',
+ 'ULINT' => '[int]',
+ 'UINT' => '[int]',
+ 'UINT:' => '[int]',
+ 'TINT:' => '[int]',
+ 'USINT' => '[int]',
+ 'BOOL' => '[int]',
+ 'VCHAR' => '[varchar] (255)',
+ 'VCHAR:' => '[varchar] (%d)',
+ 'CHAR:' => '[char] (%d)',
+ 'XSTEXT' => '[varchar] (1000)',
+ 'STEXT' => '[varchar] (3000)',
+ 'TEXT' => '[varchar] (8000)',
+ 'MTEXT' => '[text]',
+ 'XSTEXT_UNI'=> '[varchar] (100)',
+ 'STEXT_UNI' => '[varchar] (255)',
+ 'TEXT_UNI' => '[varchar] (4000)',
+ 'MTEXT_UNI' => '[text]',
+ 'TIMESTAMP' => '[int]',
+ 'DECIMAL' => '[float]',
+ 'DECIMAL:' => '[float]',
+ 'PDECIMAL' => '[float]',
+ 'PDECIMAL:' => '[float]',
+ 'VCHAR_UNI' => '[varchar] (255)',
+ 'VCHAR_UNI:'=> '[varchar] (%d)',
+ 'VCHAR_CI' => '[varchar] (255)',
+ 'VARBINARY' => '[varchar] (255)',
+ ),
+ );
+ }
+
+ /**
+ * Constructor. Set DB Object and set {@link $return_statements return_statements}.
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param bool $return_statements True if only statements should be returned and no SQL being executed
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
+ {
+ parent::__construct($db, $return_statements);
+
+ // Determine mapping database type
+ switch ($this->db->get_sql_layer())
+ {
+ case 'mssql_odbc':
+ $this->sql_layer = 'mssql';
+ break;
+
+ case 'mssqlnative':
+ $this->sql_layer = 'mssqlnative';
+ break;
+ }
+
+ $this->dbms_type_map = self::get_dbms_type_map();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_tables()
+ {
+ $sql = "SELECT name
+ FROM sysobjects
+ WHERE type='U'";
+ $result = $this->db->sql_query($sql);
+
+ $tables = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $name = current($row);
+ $tables[$name] = $name;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $tables;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_table($table_name, $table_data)
+ {
+ // holds the DDL for a column
+ $columns = $statements = array();
+
+ if ($this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // Begin transaction
+ $statements[] = 'begin';
+
+ // Determine if we have created a PRIMARY KEY in the earliest
+ $primary_key_gen = false;
+
+ // Determine if the table requires a sequence
+ $create_sequence = false;
+
+ // Begin table sql statement
+ $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n";
+
+ if (!isset($table_data['PRIMARY_KEY']))
+ {
+ $table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment');
+ $table_data['PRIMARY_KEY'] = 'mssqlindex';
+ }
+
+ // Iterate through the columns to create a table
+ foreach ($table_data['COLUMNS'] as $column_name => $column_data)
+ {
+ // here lies an array, filled with information compiled on the column's data
+ $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+
+ if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
+ {
+ trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
+ }
+
+ // here we add the definition of the new column to the list of columns
+ $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default'];
+
+ // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
+ if (!$primary_key_gen)
+ {
+ $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
+ }
+
+ // create sequence DDL based off of the existance of auto incrementing columns
+ if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
+ {
+ $create_sequence = $column_name;
+ }
+ }
+
+ // this makes up all the columns in the create table statement
+ $table_sql .= implode(",\n", $columns);
+
+ // Close the table for two DBMS and add to the statements
+ $table_sql .= "\n);";
+ $statements[] = $table_sql;
+
+ // we have yet to create a primary key for this table,
+ // this means that we can add the one we really wanted instead
+ if (!$primary_key_gen)
+ {
+ // Write primary key
+ if (isset($table_data['PRIMARY_KEY']))
+ {
+ if (!is_array($table_data['PRIMARY_KEY']))
+ {
+ $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
+ }
+
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']);
+ foreach ($primary_key_stmts as $pk_stmt)
+ {
+ $statements[] = $pk_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Write Keys
+ if (isset($table_data['KEYS']))
+ {
+ foreach ($table_data['KEYS'] as $key_name => $key_data)
+ {
+ if (!is_array($key_data[1]))
+ {
+ $key_data[1] = array($key_data[1]);
+ }
+
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
+
+ foreach ($key_stmts as $key_stmt)
+ {
+ $statements[] = $key_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Commit Transaction
+ $statements[] = 'commit';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_columns($table_name)
+ {
+ $columns = array();
+
+ $sql = "SELECT c.name
+ FROM syscolumns c
+ LEFT JOIN sysobjects o ON c.id = o.id
+ WHERE o.name = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $column = strtolower(current($row));
+ $columns[$column] = $column;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $columns;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_exists($table_name, $index_name)
+ {
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['TYPE'] == 3)
+ {
+ if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_unique_index_exists($table_name, $index_name)
+ {
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // Usually NON_UNIQUE is the column we want to check, but we allow for both
+ if ($row['TYPE'] == 3)
+ {
+ if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_prepare_column_data($table_name, $column_name, $column_data)
+ {
+ if (strlen($column_name) > 30)
+ {
+ trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
+ }
+
+ // Get type
+ list($column_type, ) = $this->get_column_type($column_data[0]);
+
+ // Adjust default value if db-dependent specified
+ if (is_array($column_data[1]))
+ {
+ $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
+ }
+
+ $sql = '';
+
+ $return_array = array();
+
+ $sql .= " {$column_type} ";
+ $sql_default = " {$column_type} ";
+
+ // For adding columns we need the default definition
+ if (!is_null($column_data[1]))
+ {
+ // For hexadecimal values do not use single quotes
+ if (strpos($column_data[1], '0x') === 0)
+ {
+ $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') ';
+ $sql_default .= $return_array['default'];
+ }
+ else
+ {
+ $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
+ $sql_default .= $return_array['default'];
+ }
+ }
+
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ // $sql .= 'IDENTITY (1, 1) ';
+ $sql_default .= 'IDENTITY (1, 1) ';
+ }
+
+ $return_array['textimage'] = $column_type === '[text]';
+
+ if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
+ {
+ $sql .= 'NOT NULL';
+ $sql_default .= 'NOT NULL';
+ }
+ else
+ {
+ $sql .= 'NULL';
+ $sql_default .= 'NULL';
+ }
+
+ $return_array['column_type_sql_default'] = $sql_default;
+
+ $return_array['column_type_sql'] = $sql;
+
+ return $return_array;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_add($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ // Does not support AFTER, only through temporary table
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_remove($table_name, $column_name, $inline = false)
+ {
+ $statements = array();
+
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $indexes = $this->get_existing_indexes($table_name, $column_name);
+ $indexes = array_merge($indexes, $this->get_existing_indexes($table_name, $column_name, true));
+
+ // Drop any indexes
+ $recreate_indexes = array();
+ if (!empty($indexes))
+ {
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_index_drop($table_name, $index_name);
+ $statements = array_merge($statements, $result);
+ if (sizeof($index_data) > 1)
+ {
+ // Remove this column from the index and recreate it
+ $recreate_indexes[$index_name] = array_diff($index_data, array($column_name));
+ }
+ }
+ }
+
+ // Drop default value constraint
+ $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
+ $statements = array_merge($statements, $result);
+
+ // Remove the column
+ $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
+
+ if (!empty($recreate_indexes))
+ {
+ // Recreate indexes after we removed the column
+ foreach ($recreate_indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $this->return_statements = $old_return_statements;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_drop($table_name, $index_name)
+ {
+ $statements = array();
+
+ $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_table_drop($table_name)
+ {
+ $statements = array();
+
+ if (!$this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // the most basic operation, get rid of the table
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_primary_key($table_name, $column, $inline = false)
+ {
+ $statements = array();
+
+ $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
+ $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
+ $sql .= '[' . implode("],\n\t\t[", $column) . ']';
+ $sql .= ')';
+
+ $statements[] = $sql;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_unique_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ $statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ // remove index length
+ $column = preg_replace('#:.*$#', '', $column);
+
+ $statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_index($table_name)
+ {
+ $index_array = array();
+ $sql = "EXEC sp_statistics '$table_name'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['TYPE'] == 3)
+ {
+ $index_array[] = strtolower($row['INDEX_NAME']);
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return $index_array;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_change($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $indexes = $this->get_existing_indexes($table_name, $column_name);
+ $unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
+
+ // Drop any indexes
+ if (!empty($indexes) || !empty($unique_indexes))
+ {
+ $drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
+ foreach ($drop_indexes as $index_name)
+ {
+ $result = $this->sql_index_drop($table_name, $index_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);
+
+ // Change the column
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
+
+ if (!empty($column_data['default']))
+ {
+ // Add new default value constraint
+ $statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $column_data['default'] . ' FOR [' . $column_name . ']';
+ }
+
+ if (!empty($indexes))
+ {
+ // Recreate indexes after we changed the column
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ if (!empty($unique_indexes))
+ {
+ // Recreate unique indexes after we changed the column
+ foreach ($unique_indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_unique_index($table_name, $index_name, $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $this->return_statements = $old_return_statements;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * Get queries to drop the default constraints of a column
+ *
+ * We need to drop the default constraints of a column,
+ * before being able to change their type or deleting them.
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @return array Array with SQL statements
+ */
+ protected function mssql_get_drop_default_constraints_queries($table_name, $column_name)
+ {
+ $statements = array();
+ if ($this->mssql_is_sql_server_2000())
+ {
+ // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
+ // Deprecated in SQL Server 2005
+ $sql = "SELECT so.name AS def_name
+ FROM sysobjects so
+ JOIN sysconstraints sc ON so.id = sc.constid
+ WHERE object_name(so.parent_obj) = '{$table_name}'
+ AND so.xtype = 'D'
+ AND sc.colid = (SELECT colid FROM syscolumns
+ WHERE id = object_id('{$table_name}')
+ AND name = '{$column_name}')";
+ }
+ else
+ {
+ $sql = "SELECT dobj.name AS def_name
+ FROM sys.columns col
+ LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D')
+ WHERE col.object_id = object_id('{$table_name}')
+ AND col.name = '{$column_name}'
+ AND dobj.name IS NOT NULL";
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']';
+ }
+ $this->db->sql_freeresult($result);
+
+ return $statements;
+ }
+
+ /**
+ * Get a list with existing indexes for the column
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @param bool $unique Should we get unique indexes or normal ones
+ * @return array Array with Index name => columns
+ */
+ public function get_existing_indexes($table_name, $column_name, $unique = false)
+ {
+ $existing_indexes = array();
+ if ($this->mssql_is_sql_server_2000())
+ {
+ // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
+ // Deprecated in SQL Server 2005
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
+ FROM sysindexes ix
+ INNER JOIN sysindexkeys ixc
+ ON ixc.id = ix.id
+ AND ixc.indid = ix.indid
+ INNER JOIN syscolumns cols
+ ON cols.colid = ixc.colid
+ AND cols.id = ix.id
+ WHERE ix.id = object_id('{$table_name}')
+ AND cols.name = '{$column_name}'
+ AND INDEXPROPERTY(ix.id, ix.name, 'IsUnique') = " . ($unique ? '1' : '0');
+ }
+ else
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name
+ FROM sys.indexes ix
+ INNER JOIN sys.index_columns ixc
+ ON ixc.object_id = ix.object_id
+ AND ixc.index_id = ix.index_id
+ INNER JOIN sys.columns cols
+ ON cols.column_id = ixc.column_id
+ AND cols.object_id = ix.object_id
+ WHERE ix.object_id = object_id('{$table_name}')
+ AND cols.name = '{$column_name}'
+ AND ix.is_unique = " . ($unique ? '1' : '0');
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!isset($row['is_unique']) || ($unique && $row['is_unique'] == 'UNIQUE') || (!$unique && $row['is_unique'] == 'NONUNIQUE'))
+ {
+ $existing_indexes[$row['phpbb_index_name']] = array();
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($existing_indexes))
+ {
+ return array();
+ }
+
+ if ($this->mssql_is_sql_server_2000())
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
+ FROM sysindexes ix
+ INNER JOIN sysindexkeys ixc
+ ON ixc.id = ix.id
+ AND ixc.indid = ix.indid
+ INNER JOIN syscolumns cols
+ ON cols.colid = ixc.colid
+ AND cols.id = ix.id
+ WHERE ix.id = object_id('{$table_name}')
+ AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
+ }
+ else
+ {
+ $sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
+ FROM sys.indexes ix
+ INNER JOIN sys.index_columns ixc
+ ON ixc.object_id = ix.object_id
+ AND ixc.index_id = ix.index_id
+ INNER JOIN sys.columns cols
+ ON cols.column_id = ixc.column_id
+ AND cols.object_id = ix.object_id
+ WHERE ix.object_id = object_id('{$table_name}')
+ AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $existing_indexes;
+ }
+
+ /**
+ * Is the used MS SQL Server a SQL Server 2000?
+ *
+ * @return bool
+ */
+ protected function mssql_is_sql_server_2000()
+ {
+ if ($this->is_sql_server_2000 === null)
+ {
+ $sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version";
+ $result = $this->db->sql_query($sql);
+ $properties = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ $this->is_sql_server_2000 = $properties['mssql_version'][0] == '8';
+ }
+
+ return $this->is_sql_server_2000;
+ }
+
+}
diff --git a/phpBB/phpbb/db/tools/postgres.php b/phpBB/phpbb/db/tools/postgres.php
new file mode 100644
index 0000000000..e2a4e668a6
--- /dev/null
+++ b/phpBB/phpbb/db/tools/postgres.php
@@ -0,0 +1,614 @@
+<?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\tools;
+
+/**
+ * Database Tools for handling cross-db actions such as altering columns, etc.
+ * Currently not supported is returning SQL for creating tables.
+ */
+class postgres extends tools
+{
+ /**
+ * Get the column types for postgres only
+ *
+ * @return array
+ */
+ public static function get_dbms_type_map()
+ {
+ return array(
+ 'postgres' => array(
+ 'INT:' => 'INT4',
+ 'BINT' => 'INT8',
+ 'ULINT' => 'INT4', // unsigned
+ 'UINT' => 'INT4', // unsigned
+ 'UINT:' => 'INT4', // unsigned
+ 'USINT' => 'INT2', // unsigned
+ 'BOOL' => 'INT2', // unsigned
+ 'TINT:' => 'INT2',
+ 'VCHAR' => 'varchar(255)',
+ 'VCHAR:' => 'varchar(%d)',
+ 'CHAR:' => 'char(%d)',
+ 'XSTEXT' => 'varchar(1000)',
+ 'STEXT' => 'varchar(3000)',
+ 'TEXT' => 'varchar(8000)',
+ 'MTEXT' => 'TEXT',
+ 'XSTEXT_UNI'=> 'varchar(100)',
+ 'STEXT_UNI' => 'varchar(255)',
+ 'TEXT_UNI' => 'varchar(4000)',
+ 'MTEXT_UNI' => 'TEXT',
+ 'TIMESTAMP' => 'INT4', // unsigned
+ 'DECIMAL' => 'decimal(5,2)',
+ 'DECIMAL:' => 'decimal(%d,2)',
+ 'PDECIMAL' => 'decimal(6,3)',
+ 'PDECIMAL:' => 'decimal(%d,3)',
+ 'VCHAR_UNI' => 'varchar(255)',
+ 'VCHAR_UNI:'=> 'varchar(%d)',
+ 'VCHAR_CI' => 'varchar_ci',
+ 'VARBINARY' => 'bytea',
+ ),
+ );
+ }
+
+ /**
+ * Constructor. Set DB Object and set {@link $return_statements return_statements}.
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param bool $return_statements True if only statements should be returned and no SQL being executed
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
+ {
+ parent::__construct($db, $return_statements);
+
+ // Determine mapping database type
+ $this->sql_layer = 'postgres';
+
+ $this->dbms_type_map = self::get_dbms_type_map();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_tables()
+ {
+ $sql = 'SELECT relname
+ FROM pg_stat_user_tables';
+ $result = $this->db->sql_query($sql);
+
+ $tables = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $name = current($row);
+ $tables[$name] = $name;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $tables;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_table($table_name, $table_data)
+ {
+ // holds the DDL for a column
+ $columns = $statements = array();
+
+ if ($this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // Begin transaction
+ $statements[] = 'begin';
+
+ // Determine if we have created a PRIMARY KEY in the earliest
+ $primary_key_gen = false;
+
+ // Determine if the table requires a sequence
+ $create_sequence = false;
+
+ // Begin table sql statement
+ $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
+
+ // Iterate through the columns to create a table
+ foreach ($table_data['COLUMNS'] as $column_name => $column_data)
+ {
+ // here lies an array, filled with information compiled on the column's data
+ $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+
+ if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
+ {
+ trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
+ }
+
+ // here we add the definition of the new column to the list of columns
+ $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
+
+ // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
+ if (!$primary_key_gen)
+ {
+ $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
+ }
+
+ // create sequence DDL based off of the existance of auto incrementing columns
+ if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
+ {
+ $create_sequence = $column_name;
+ }
+ }
+
+ // this makes up all the columns in the create table statement
+ $table_sql .= implode(",\n", $columns);
+
+ // we have yet to create a primary key for this table,
+ // this means that we can add the one we really wanted instead
+ if (!$primary_key_gen)
+ {
+ // Write primary key
+ if (isset($table_data['PRIMARY_KEY']))
+ {
+ if (!is_array($table_data['PRIMARY_KEY']))
+ {
+ $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
+ }
+
+ $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
+ }
+ }
+
+ // do we need to add a sequence for auto incrementing columns?
+ if ($create_sequence)
+ {
+ $statements[] = "CREATE SEQUENCE {$table_name}_seq;";
+ }
+
+ // close the table
+ $table_sql .= "\n);";
+ $statements[] = $table_sql;
+
+ // Write Keys
+ if (isset($table_data['KEYS']))
+ {
+ foreach ($table_data['KEYS'] as $key_name => $key_data)
+ {
+ if (!is_array($key_data[1]))
+ {
+ $key_data[1] = array($key_data[1]);
+ }
+
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
+
+ foreach ($key_stmts as $key_stmt)
+ {
+ $statements[] = $key_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Commit Transaction
+ $statements[] = 'commit';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_columns($table_name)
+ {
+ $columns = array();
+
+ $sql = "SELECT a.attname
+ FROM pg_class c, pg_attribute a
+ WHERE c.relname = '{$table_name}'
+ AND a.attnum > 0
+ AND a.attrelid = c.oid";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $column = strtolower(current($row));
+ $columns[$column] = $column;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $columns;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_exists($table_name, $index_name)
+ {
+ $sql = "SELECT ic.relname as index_name
+ FROM pg_class bc, pg_class ic, pg_index i
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (bc.relname = '" . $table_name . "')
+ AND (i.indisunique != 't')
+ AND (i.indisprimary != 't')";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // This DBMS prefixes index names with the table name
+ $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
+
+ if (strtolower($row['index_name']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_unique_index_exists($table_name, $index_name)
+ {
+ $sql = "SELECT ic.relname as index_name, i.indisunique
+ FROM pg_class bc, pg_class ic, pg_index i
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (bc.relname = '" . $table_name . "')
+ AND (i.indisprimary != 't')";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if ($row['indisunique'] != 't')
+ {
+ continue;
+ }
+
+ // This DBMS prefixes index names with the table name
+ $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
+
+ if (strtolower($row['index_name']) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * Function to prepare some column information for better usage
+ * @access private
+ */
+ function sql_prepare_column_data($table_name, $column_name, $column_data)
+ {
+ if (strlen($column_name) > 30)
+ {
+ trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
+ }
+
+ // Get type
+ list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]);
+
+ // Adjust default value if db-dependent specified
+ if (is_array($column_data[1]))
+ {
+ $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
+ }
+
+ $sql = " {$column_type} ";
+
+ $return_array = array(
+ 'column_type' => $column_type,
+ 'auto_increment' => false,
+ );
+
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ $default_val = "nextval('{$table_name}_seq')";
+ $return_array['auto_increment'] = true;
+ }
+ else if (!is_null($column_data[1]))
+ {
+ $default_val = "'" . $column_data[1] . "'";
+ $return_array['null'] = 'NOT NULL';
+ $sql .= 'NOT NULL ';
+ }
+ else
+ {
+ // Integers need to have 0 instead of empty string as default
+ if (strpos($column_type, 'INT') === 0)
+ {
+ $default_val = '0';
+ }
+ else
+ {
+ $default_val = "'" . $column_data[1] . "'";
+ }
+ $return_array['null'] = 'NULL';
+ $sql .= 'NULL ';
+ }
+
+ $return_array['default'] = $default_val;
+
+ $sql .= "DEFAULT {$default_val}";
+
+ // Unsigned? Then add a CHECK contraint
+ if (in_array($orig_column_type, $this->unsigned_types))
+ {
+ $return_array['constraint'] = "CHECK ({$column_name} >= 0)";
+ $sql .= " CHECK ({$column_name} >= 0)";
+ }
+
+ $return_array['column_type_sql'] = $sql;
+
+ return $return_array;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_add($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ // Does not support AFTER, only through temporary table
+ if (version_compare($this->db->sql_server_info(true), '8.0', '>='))
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
+ }
+ else
+ {
+ // old versions cannot add columns with default and null information
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint'];
+
+ if (isset($column_data['null']))
+ {
+ if ($column_data['null'] == 'NOT NULL')
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL';
+ }
+ }
+
+ if (isset($column_data['default']))
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
+ }
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_remove($table_name, $column_name, $inline = false)
+ {
+ $statements = array();
+
+ $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_drop($table_name, $index_name)
+ {
+ $statements = array();
+
+ $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_table_drop($table_name)
+ {
+ $statements = array();
+
+ if (!$this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // the most basic operation, get rid of the table
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ // PGSQL does not "tightly" bind sequences and tables, we must guess...
+ $sql = "SELECT relname
+ FROM pg_class
+ WHERE relkind = 'S'
+ AND relname = '{$table_name}_seq'";
+ $result = $this->db->sql_query($sql);
+
+ // We don't even care about storing the results. We already know the answer if we get rows back.
+ if ($this->db->sql_fetchrow($result))
+ {
+ $statements[] = "DROP SEQUENCE {$table_name}_seq;\n";
+ }
+ $this->db->sql_freeresult($result);
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_primary_key($table_name, $column, $inline = false)
+ {
+ $statements = array();
+
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_unique_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ // remove index length
+ $column = preg_replace('#:.*$#', '', $column);
+
+ $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_index($table_name)
+ {
+ $index_array = array();
+
+ $sql = "SELECT ic.relname as index_name
+ FROM pg_class bc, pg_class ic, pg_index i
+ WHERE (bc.oid = i.indrelid)
+ AND (ic.oid = i.indexrelid)
+ AND (bc.relname = '" . $table_name . "')
+ AND (i.indisunique != 't')
+ AND (i.indisprimary != 't')";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
+
+ $index_array[] = $row['index_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return array_map('strtolower', $index_array);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_change($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ $sql = 'ALTER TABLE ' . $table_name . ' ';
+
+ $sql_array = array();
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
+
+ if (isset($column_data['null']))
+ {
+ if ($column_data['null'] == 'NOT NULL')
+ {
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
+ }
+ else if ($column_data['null'] == 'NULL')
+ {
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
+ }
+ }
+
+ if (isset($column_data['default']))
+ {
+ $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
+ }
+
+ // we don't want to double up on constraints if we change different number data types
+ if (isset($column_data['constraint']))
+ {
+ $constraint_sql = "SELECT consrc as constraint_data
+ FROM pg_constraint, pg_class bc
+ WHERE conrelid = bc.oid
+ AND bc.relname = '{$table_name}'
+ AND NOT EXISTS (
+ SELECT *
+ FROM pg_constraint as c, pg_inherits as i
+ WHERE i.inhrelid = pg_constraint.conrelid
+ AND c.conname = pg_constraint.conname
+ AND c.consrc = pg_constraint.consrc
+ AND c.conrelid = i.inhparent
+ )";
+
+ $constraint_exists = false;
+
+ $result = $this->db->sql_query($constraint_sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (trim($row['constraint_data']) == trim($column_data['constraint']))
+ {
+ $constraint_exists = true;
+ break;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (!$constraint_exists)
+ {
+ $sql_array[] = 'ADD ' . $column_data['constraint'];
+ }
+ }
+
+ $sql .= implode(', ', $sql_array);
+
+ $statements[] = $sql;
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * Get a list with existing indexes for the column
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @param bool $unique Should we get unique indexes or normal ones
+ * @return array Array with Index name => columns
+ */
+ public function get_existing_indexes($table_name, $column_name, $unique = false)
+ {
+ // Not supported
+ throw new \Exception('DBMS is not supported');
+ }
+}
diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php
new file mode 100644
index 0000000000..9273d69cd6
--- /dev/null
+++ b/phpBB/phpbb/db/tools/tools.php
@@ -0,0 +1,1918 @@
+<?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\tools;
+
+/**
+* Database Tools for handling cross-db actions such as altering columns, etc.
+* Currently not supported is returning SQL for creating tables.
+*/
+class tools implements tools_interface
+{
+ /**
+ * Current sql layer
+ */
+ var $sql_layer = '';
+
+ /**
+ * @var object DB object
+ */
+ var $db = null;
+
+ /**
+ * The Column types for every database we support
+ * @var array
+ */
+ var $dbms_type_map = array();
+
+ /**
+ * Get the column types for every database we support
+ *
+ * @return array
+ */
+ static public function get_dbms_type_map()
+ {
+ return array(
+ 'mysql_41' => array(
+ 'INT:' => 'int(%d)',
+ 'BINT' => 'bigint(20)',
+ 'ULINT' => 'INT(10) UNSIGNED',
+ 'UINT' => 'mediumint(8) UNSIGNED',
+ 'UINT:' => 'int(%d) UNSIGNED',
+ 'TINT:' => 'tinyint(%d)',
+ 'USINT' => 'smallint(4) UNSIGNED',
+ 'BOOL' => 'tinyint(1) UNSIGNED',
+ 'VCHAR' => 'varchar(255)',
+ 'VCHAR:' => 'varchar(%d)',
+ 'CHAR:' => 'char(%d)',
+ 'XSTEXT' => 'text',
+ 'XSTEXT_UNI'=> 'varchar(100)',
+ 'STEXT' => 'text',
+ 'STEXT_UNI' => 'varchar(255)',
+ 'TEXT' => 'text',
+ 'TEXT_UNI' => 'text',
+ 'MTEXT' => 'mediumtext',
+ 'MTEXT_UNI' => 'mediumtext',
+ 'TIMESTAMP' => 'int(11) UNSIGNED',
+ 'DECIMAL' => 'decimal(5,2)',
+ 'DECIMAL:' => 'decimal(%d,2)',
+ 'PDECIMAL' => 'decimal(6,3)',
+ 'PDECIMAL:' => 'decimal(%d,3)',
+ 'VCHAR_UNI' => 'varchar(255)',
+ 'VCHAR_UNI:'=> 'varchar(%d)',
+ 'VCHAR_CI' => 'varchar(255)',
+ 'VARBINARY' => 'varbinary(255)',
+ ),
+
+ 'mysql_40' => array(
+ 'INT:' => 'int(%d)',
+ 'BINT' => 'bigint(20)',
+ 'ULINT' => 'INT(10) UNSIGNED',
+ 'UINT' => 'mediumint(8) UNSIGNED',
+ 'UINT:' => 'int(%d) UNSIGNED',
+ 'TINT:' => 'tinyint(%d)',
+ 'USINT' => 'smallint(4) UNSIGNED',
+ 'BOOL' => 'tinyint(1) UNSIGNED',
+ 'VCHAR' => 'varbinary(255)',
+ 'VCHAR:' => 'varbinary(%d)',
+ 'CHAR:' => 'binary(%d)',
+ 'XSTEXT' => 'blob',
+ 'XSTEXT_UNI'=> 'blob',
+ 'STEXT' => 'blob',
+ 'STEXT_UNI' => 'blob',
+ 'TEXT' => 'blob',
+ 'TEXT_UNI' => 'blob',
+ 'MTEXT' => 'mediumblob',
+ 'MTEXT_UNI' => 'mediumblob',
+ 'TIMESTAMP' => 'int(11) UNSIGNED',
+ 'DECIMAL' => 'decimal(5,2)',
+ 'DECIMAL:' => 'decimal(%d,2)',
+ 'PDECIMAL' => 'decimal(6,3)',
+ 'PDECIMAL:' => 'decimal(%d,3)',
+ 'VCHAR_UNI' => 'blob',
+ 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')),
+ 'VCHAR_CI' => 'blob',
+ 'VARBINARY' => 'varbinary(255)',
+ ),
+
+ 'oracle' => array(
+ 'INT:' => 'number(%d)',
+ 'BINT' => 'number(20)',
+ 'ULINT' => 'number(10)',
+ 'UINT' => 'number(8)',
+ 'UINT:' => 'number(%d)',
+ 'TINT:' => 'number(%d)',
+ 'USINT' => 'number(4)',
+ 'BOOL' => 'number(1)',
+ 'VCHAR' => 'varchar2(255)',
+ 'VCHAR:' => 'varchar2(%d)',
+ 'CHAR:' => 'char(%d)',
+ 'XSTEXT' => 'varchar2(1000)',
+ 'STEXT' => 'varchar2(3000)',
+ 'TEXT' => 'clob',
+ 'MTEXT' => 'clob',
+ 'XSTEXT_UNI'=> 'varchar2(300)',
+ 'STEXT_UNI' => 'varchar2(765)',
+ 'TEXT_UNI' => 'clob',
+ 'MTEXT_UNI' => 'clob',
+ 'TIMESTAMP' => 'number(11)',
+ 'DECIMAL' => 'number(5, 2)',
+ 'DECIMAL:' => 'number(%d, 2)',
+ 'PDECIMAL' => 'number(6, 3)',
+ 'PDECIMAL:' => 'number(%d, 3)',
+ 'VCHAR_UNI' => 'varchar2(765)',
+ 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
+ 'VCHAR_CI' => 'varchar2(255)',
+ 'VARBINARY' => 'raw(255)',
+ ),
+
+ 'sqlite3' => array(
+ 'INT:' => 'INT(%d)',
+ 'BINT' => 'BIGINT(20)',
+ 'ULINT' => 'INTEGER UNSIGNED',
+ 'UINT' => 'INTEGER UNSIGNED',
+ 'UINT:' => 'INTEGER UNSIGNED',
+ 'TINT:' => 'TINYINT(%d)',
+ 'USINT' => 'INTEGER UNSIGNED',
+ 'BOOL' => 'INTEGER UNSIGNED',
+ 'VCHAR' => 'VARCHAR(255)',
+ 'VCHAR:' => 'VARCHAR(%d)',
+ 'CHAR:' => 'CHAR(%d)',
+ 'XSTEXT' => 'TEXT(65535)',
+ 'STEXT' => 'TEXT(65535)',
+ 'TEXT' => 'TEXT(65535)',
+ 'MTEXT' => 'MEDIUMTEXT(16777215)',
+ 'XSTEXT_UNI'=> 'TEXT(65535)',
+ 'STEXT_UNI' => 'TEXT(65535)',
+ 'TEXT_UNI' => 'TEXT(65535)',
+ 'MTEXT_UNI' => 'MEDIUMTEXT(16777215)',
+ 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
+ 'DECIMAL' => 'DECIMAL(5,2)',
+ 'DECIMAL:' => 'DECIMAL(%d,2)',
+ 'PDECIMAL' => 'DECIMAL(6,3)',
+ 'PDECIMAL:' => 'DECIMAL(%d,3)',
+ 'VCHAR_UNI' => 'VARCHAR(255)',
+ 'VCHAR_UNI:'=> 'VARCHAR(%d)',
+ 'VCHAR_CI' => 'VARCHAR(255)',
+ 'VARBINARY' => 'BLOB',
+ ),
+ );
+ }
+
+ /**
+ * A list of types being unsigned for better reference in some db's
+ * @var array
+ */
+ var $unsigned_types = array('ULINT', 'UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
+
+ /**
+ * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array).
+ * This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command.
+ */
+ var $return_statements = false;
+
+ /**
+ * Constructor. Set DB Object and set {@link $return_statements return_statements}.
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param bool $return_statements True if only statements should be returned and no SQL being executed
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
+ {
+ $this->db = $db;
+ $this->return_statements = $return_statements;
+
+ $this->dbms_type_map = self::get_dbms_type_map();
+
+ // Determine mapping database type
+ switch ($this->db->get_sql_layer())
+ {
+ case 'mysql':
+ $this->sql_layer = 'mysql_40';
+ break;
+
+ case 'mysql4':
+ if (version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
+ {
+ $this->sql_layer = 'mysql_41';
+ }
+ else
+ {
+ $this->sql_layer = 'mysql_40';
+ }
+ break;
+
+ case 'mysqli':
+ $this->sql_layer = 'mysql_41';
+ break;
+
+ default:
+ $this->sql_layer = $this->db->get_sql_layer();
+ break;
+ }
+ }
+
+ /**
+ * Setter for {@link $return_statements return_statements}.
+ *
+ * @param bool $return_statements True if SQL should not be executed but returned as strings
+ * @return null
+ */
+ public function set_return_statements($return_statements)
+ {
+ $this->return_statements = $return_statements;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_tables()
+ {
+ switch ($this->db->get_sql_layer())
+ {
+ case 'mysql':
+ case 'mysql4':
+ case 'mysqli':
+ $sql = 'SHOW TABLES';
+ break;
+
+ case 'sqlite3':
+ $sql = 'SELECT name
+ FROM sqlite_master
+ WHERE type = "table"
+ AND name <> "sqlite_sequence"';
+ break;
+
+ case 'oracle':
+ $sql = 'SELECT table_name
+ FROM USER_TABLES';
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+
+ $tables = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $name = current($row);
+ $tables[$name] = $name;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $tables;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_table_exists($table_name)
+ {
+ $this->db->sql_return_on_error(true);
+ $result = $this->db->sql_query_limit('SELECT * FROM ' . $table_name, 1);
+ $this->db->sql_return_on_error(false);
+
+ if ($result)
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_table($table_name, $table_data)
+ {
+ // holds the DDL for a column
+ $columns = $statements = array();
+
+ if ($this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // Begin transaction
+ $statements[] = 'begin';
+
+ // Determine if we have created a PRIMARY KEY in the earliest
+ $primary_key_gen = false;
+
+ // Determine if the table requires a sequence
+ $create_sequence = false;
+
+ // Begin table sql statement
+ $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
+
+ // Iterate through the columns to create a table
+ foreach ($table_data['COLUMNS'] as $column_name => $column_data)
+ {
+ // here lies an array, filled with information compiled on the column's data
+ $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+
+ if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
+ {
+ trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
+ }
+
+ // here we add the definition of the new column to the list of columns
+ $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
+
+ // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
+ if (!$primary_key_gen)
+ {
+ $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
+ }
+
+ // create sequence DDL based off of the existance of auto incrementing columns
+ if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
+ {
+ $create_sequence = $column_name;
+ }
+ }
+
+ // this makes up all the columns in the create table statement
+ $table_sql .= implode(",\n", $columns);
+
+ // we have yet to create a primary key for this table,
+ // this means that we can add the one we really wanted instead
+ if (!$primary_key_gen)
+ {
+ // Write primary key
+ if (isset($table_data['PRIMARY_KEY']))
+ {
+ if (!is_array($table_data['PRIMARY_KEY']))
+ {
+ $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
+ }
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ case 'sqlite3':
+ $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
+ break;
+
+ case 'oracle':
+ $table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
+ break;
+ }
+ }
+ }
+
+ // close the table
+ switch ($this->sql_layer)
+ {
+ case 'mysql_41':
+ // make sure the table is in UTF-8 mode
+ $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;";
+ $statements[] = $table_sql;
+ break;
+
+ case 'mysql_40':
+ case 'sqlite3':
+ $table_sql .= "\n);";
+ $statements[] = $table_sql;
+ break;
+
+ case 'oracle':
+ $table_sql .= "\n)";
+ $statements[] = $table_sql;
+
+ // do we need to add a sequence and a tigger for auto incrementing columns?
+ if ($create_sequence)
+ {
+ // create the actual sequence
+ $statements[] = "CREATE SEQUENCE {$table_name}_seq";
+
+ // the trigger is the mechanism by which we increment the counter
+ $trigger = "CREATE OR REPLACE TRIGGER t_{$table_name}\n";
+ $trigger .= "BEFORE INSERT ON {$table_name}\n";
+ $trigger .= "FOR EACH ROW WHEN (\n";
+ $trigger .= "\tnew.{$create_sequence} IS NULL OR new.{$create_sequence} = 0\n";
+ $trigger .= ")\n";
+ $trigger .= "BEGIN\n";
+ $trigger .= "\tSELECT {$table_name}_seq.nextval\n";
+ $trigger .= "\tINTO :new.{$create_sequence}\n";
+ $trigger .= "\tFROM dual;\n";
+ $trigger .= "END;";
+
+ $statements[] = $trigger;
+ }
+ break;
+ }
+
+ // Write Keys
+ if (isset($table_data['KEYS']))
+ {
+ foreach ($table_data['KEYS'] as $key_name => $key_data)
+ {
+ if (!is_array($key_data[1]))
+ {
+ $key_data[1] = array($key_data[1]);
+ }
+
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
+
+ foreach ($key_stmts as $key_stmt)
+ {
+ $statements[] = $key_stmt;
+ }
+
+ $this->return_statements = $old_return_statements;
+ }
+ }
+
+ // Commit Transaction
+ $statements[] = 'commit';
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function perform_schema_changes($schema_changes)
+ {
+ if (empty($schema_changes))
+ {
+ return;
+ }
+
+ $statements = array();
+ $sqlite = false;
+
+ // For SQLite we need to perform the schema changes in a much more different way
+ if ($this->db->get_sql_layer() == 'sqlite3' && $this->return_statements)
+ {
+ $sqlite_data = array();
+ $sqlite = true;
+ }
+
+ // Drop tables?
+ if (!empty($schema_changes['drop_tables']))
+ {
+ foreach ($schema_changes['drop_tables'] as $table)
+ {
+ // only drop table if it exists
+ if ($this->sql_table_exists($table))
+ {
+ $result = $this->sql_table_drop($table);
+ if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
+ // Add tables?
+ if (!empty($schema_changes['add_tables']))
+ {
+ foreach ($schema_changes['add_tables'] as $table => $table_data)
+ {
+ $result = $this->sql_create_table($table, $table_data);
+ if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+
+ // Change columns?
+ if (!empty($schema_changes['change_columns']))
+ {
+ foreach ($schema_changes['change_columns'] as $table => $columns)
+ {
+ foreach ($columns as $column_name => $column_data)
+ {
+ // If the column exists we change it, else we add it ;)
+ if ($column_exists = $this->sql_column_exists($table, $column_name))
+ {
+ $result = $this->sql_column_change($table, $column_name, $column_data, true);
+ }
+ else
+ {
+ $result = $this->sql_column_add($table, $column_name, $column_data, true);
+ }
+
+ if ($sqlite)
+ {
+ if ($column_exists)
+ {
+ $sqlite_data[$table]['change_columns'][] = $result;
+ }
+ else
+ {
+ $sqlite_data[$table]['add_columns'][] = $result;
+ }
+ }
+ else if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
+ // Add columns?
+ if (!empty($schema_changes['add_columns']))
+ {
+ foreach ($schema_changes['add_columns'] as $table => $columns)
+ {
+ foreach ($columns as $column_name => $column_data)
+ {
+ // Only add the column if it does not exist yet
+ if ($column_exists = $this->sql_column_exists($table, $column_name))
+ {
+ continue;
+ // This is commented out here because it can take tremendous time on updates
+// $result = $this->sql_column_change($table, $column_name, $column_data, true);
+ }
+ else
+ {
+ $result = $this->sql_column_add($table, $column_name, $column_data, true);
+ }
+
+ if ($sqlite)
+ {
+ if ($column_exists)
+ {
+ continue;
+// $sqlite_data[$table]['change_columns'][] = $result;
+ }
+ else
+ {
+ $sqlite_data[$table]['add_columns'][] = $result;
+ }
+ }
+ else if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
+ // Remove keys?
+ if (!empty($schema_changes['drop_keys']))
+ {
+ foreach ($schema_changes['drop_keys'] as $table => $indexes)
+ {
+ foreach ($indexes as $index_name)
+ {
+ if (!$this->sql_index_exists($table, $index_name))
+ {
+ continue;
+ }
+
+ $result = $this->sql_index_drop($table, $index_name);
+
+ if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
+ // Drop columns?
+ if (!empty($schema_changes['drop_columns']))
+ {
+ foreach ($schema_changes['drop_columns'] as $table => $columns)
+ {
+ foreach ($columns as $column)
+ {
+ // Only remove the column if it exists...
+ if ($this->sql_column_exists($table, $column))
+ {
+ $result = $this->sql_column_remove($table, $column, true);
+
+ if ($sqlite)
+ {
+ $sqlite_data[$table]['drop_columns'][] = $result;
+ }
+ else if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+ }
+
+ // Add primary keys?
+ if (!empty($schema_changes['add_primary_keys']))
+ {
+ foreach ($schema_changes['add_primary_keys'] as $table => $columns)
+ {
+ $result = $this->sql_create_primary_key($table, $columns, true);
+
+ if ($sqlite)
+ {
+ $sqlite_data[$table]['primary_key'] = $result;
+ }
+ else if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+
+ // Add unique indexes?
+ if (!empty($schema_changes['add_unique_index']))
+ {
+ foreach ($schema_changes['add_unique_index'] as $table => $index_array)
+ {
+ foreach ($index_array as $index_name => $column)
+ {
+ if ($this->sql_unique_index_exists($table, $index_name))
+ {
+ continue;
+ }
+
+ $result = $this->sql_create_unique_index($table, $index_name, $column);
+
+ if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
+ // Add indexes?
+ if (!empty($schema_changes['add_index']))
+ {
+ foreach ($schema_changes['add_index'] as $table => $index_array)
+ {
+ foreach ($index_array as $index_name => $column)
+ {
+ if ($this->sql_index_exists($table, $index_name))
+ {
+ continue;
+ }
+
+ $result = $this->sql_create_index($table, $index_name, $column);
+
+ if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
+ if ($sqlite)
+ {
+ foreach ($sqlite_data as $table_name => $sql_schema_changes)
+ {
+ // Create temporary table with original data
+ $statements[] = 'begin';
+
+ $sql = "SELECT sql
+ FROM sqlite_master
+ WHERE type = 'table'
+ AND name = '{$table_name}'
+ ORDER BY type DESC, name;";
+ $result = $this->db->sql_query($sql);
+
+ if (!$result)
+ {
+ continue;
+ }
+
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ // Create a backup table and populate it, destroy the existing one
+ $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']);
+ $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ // Get the columns...
+ preg_match('#\((.*)\)#s', $row['sql'], $matches);
+
+ $plain_table_cols = trim($matches[1]);
+ $new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols);
+ $column_list = array();
+
+ foreach ($new_table_cols as $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY')
+ {
+ continue;
+ }
+ $column_list[] = $entities[0];
+ }
+
+ // note down the primary key notation because sqlite only supports adding it to the end for the new table
+ $primary_key = false;
+ $_new_cols = array();
+
+ foreach ($new_table_cols as $key => $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY')
+ {
+ $primary_key = $declaration;
+ continue;
+ }
+ $_new_cols[] = $declaration;
+ }
+
+ $new_table_cols = $_new_cols;
+
+ // First of all... change columns
+ if (!empty($sql_schema_changes['change_columns']))
+ {
+ foreach ($sql_schema_changes['change_columns'] as $column_sql)
+ {
+ foreach ($new_table_cols as $key => $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if (strpos($column_sql, $entities[0] . ' ') === 0)
+ {
+ $new_table_cols[$key] = $column_sql;
+ }
+ }
+ }
+ }
+
+ if (!empty($sql_schema_changes['add_columns']))
+ {
+ foreach ($sql_schema_changes['add_columns'] as $column_sql)
+ {
+ $new_table_cols[] = $column_sql;
+ }
+ }
+
+ // Now drop them...
+ if (!empty($sql_schema_changes['drop_columns']))
+ {
+ foreach ($sql_schema_changes['drop_columns'] as $column_name)
+ {
+ // Remove from column list...
+ $new_column_list = array();
+ foreach ($column_list as $key => $value)
+ {
+ if ($value === $column_name)
+ {
+ continue;
+ }
+
+ $new_column_list[] = $value;
+ }
+
+ $column_list = $new_column_list;
+
+ // Remove from table...
+ $_new_cols = array();
+ foreach ($new_table_cols as $key => $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if (strpos($column_name . ' ', $entities[0] . ' ') === 0)
+ {
+ continue;
+ }
+ $_new_cols[] = $declaration;
+ }
+ $new_table_cols = $_new_cols;
+ }
+ }
+
+ // Primary key...
+ if (!empty($sql_schema_changes['primary_key']))
+ {
+ $new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')';
+ }
+ // Add a new one or the old primary key
+ else if ($primary_key !== false)
+ {
+ $new_table_cols[] = $primary_key;
+ }
+
+ $columns = implode(',', $column_list);
+
+ // create a new table and fill it up. destroy the temp one
+ $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');';
+ $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
+ $statements[] = 'DROP TABLE ' . $table_name . '_temp';
+
+ $statements[] = 'commit';
+ }
+ }
+
+ if ($this->return_statements)
+ {
+ return $statements;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_columns($table_name)
+ {
+ $columns = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $sql = "SHOW COLUMNS FROM $table_name";
+ break;
+
+ case 'oracle':
+ $sql = "SELECT column_name
+ FROM user_tab_columns
+ WHERE LOWER(table_name) = '" . strtolower($table_name) . "'";
+ break;
+
+ case 'sqlite3':
+ $sql = "SELECT sql
+ FROM sqlite_master
+ WHERE type = 'table'
+ AND name = '{$table_name}'";
+
+ $result = $this->db->sql_query($sql);
+
+ if (!$result)
+ {
+ return false;
+ }
+
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ preg_match('#\((.*)\)#s', $row['sql'], $matches);
+
+ $cols = trim($matches[1]);
+ $col_array = preg_split('/,(?![\s\w]+\))/m', $cols);
+
+ foreach ($col_array as $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY')
+ {
+ continue;
+ }
+
+ $column = strtolower($entities[0]);
+ $columns[$column] = $column;
+ }
+
+ return $columns;
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $column = strtolower(current($row));
+ $columns[$column] = $column;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $columns;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_exists($table_name, $column_name)
+ {
+ $columns = $this->sql_list_columns($table_name);
+
+ return isset($columns[$column_name]);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_exists($table_name, $index_name)
+ {
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $sql = 'SHOW KEYS
+ FROM ' . $table_name;
+ $col = 'Key_name';
+ break;
+
+ case 'oracle':
+ $sql = "SELECT index_name
+ FROM user_indexes
+ WHERE table_name = '" . strtoupper($table_name) . "'
+ AND generated = 'N'
+ AND uniqueness = 'NONUNIQUE'";
+ $col = 'index_name';
+ break;
+
+ case 'sqlite3':
+ $sql = "PRAGMA index_list('" . $table_name . "');";
+ $col = 'name';
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique'])
+ {
+ continue;
+ }
+
+ // These DBMS prefix index name with the table name
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ case 'sqlite3':
+ $row[$col] = substr($row[$col], strlen($table_name) + 1);
+ break;
+ }
+
+ if (strtolower($row[$col]) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_unique_index_exists($table_name, $index_name)
+ {
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $sql = 'SHOW KEYS
+ FROM ' . $table_name;
+ $col = 'Key_name';
+ break;
+
+ case 'oracle':
+ $sql = "SELECT index_name, table_owner
+ FROM user_indexes
+ WHERE table_name = '" . strtoupper($table_name) . "'
+ AND generated = 'N'
+ AND uniqueness = 'UNIQUE'";
+ $col = 'index_name';
+ break;
+
+ case 'sqlite3':
+ $sql = "PRAGMA index_list('" . $table_name . "');";
+ $col = 'name';
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && ($row['Non_unique'] || $row[$col] == 'PRIMARY'))
+ {
+ continue;
+ }
+
+ if ($this->sql_layer == 'sqlite3' && !$row['unique'])
+ {
+ continue;
+ }
+
+ // These DBMS prefix index name with the table name
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ // Two cases here... prefixed with U_[table_owner] and not prefixed with table_name
+ if (strpos($row[$col], 'U_') === 0)
+ {
+ $row[$col] = substr($row[$col], strlen('U_' . $row['table_owner']) + 1);
+ }
+ else if (strpos($row[$col], strtoupper($table_name)) === 0)
+ {
+ $row[$col] = substr($row[$col], strlen($table_name) + 1);
+ }
+ break;
+
+ case 'sqlite3':
+ $row[$col] = substr($row[$col], strlen($table_name) + 1);
+ break;
+ }
+
+ if (strtolower($row[$col]) == strtolower($index_name))
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return false;
+ }
+
+ /**
+ * Private method for performing sql statements (either execute them or return them)
+ * @access private
+ */
+ function _sql_run_sql($statements)
+ {
+ if ($this->return_statements)
+ {
+ return $statements;
+ }
+
+ // We could add error handling here...
+ foreach ($statements as $sql)
+ {
+ if ($sql === 'begin')
+ {
+ $this->db->sql_transaction('begin');
+ }
+ else if ($sql === 'commit')
+ {
+ $this->db->sql_transaction('commit');
+ }
+ else
+ {
+ $this->db->sql_query($sql);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Function to prepare some column information for better usage
+ * @access private
+ */
+ function sql_prepare_column_data($table_name, $column_name, $column_data)
+ {
+ if (strlen($column_name) > 30)
+ {
+ trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
+ }
+
+ // Get type
+ list($column_type) = $this->get_column_type($column_data[0]);
+
+ // Adjust default value if db-dependent specified
+ if (is_array($column_data[1]))
+ {
+ $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
+ }
+
+ $sql = '';
+
+ $return_array = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $sql .= " {$column_type} ";
+
+ // For hexadecimal values do not use single quotes
+ if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob')
+ {
+ $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
+ }
+
+ if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
+ {
+ $sql .= 'NOT NULL';
+ }
+ else
+ {
+ $sql .= 'NULL';
+ }
+
+ if (isset($column_data[2]))
+ {
+ if ($column_data[2] == 'auto_increment')
+ {
+ $sql .= ' auto_increment';
+ }
+ else if ($this->sql_layer === 'mysql_41' && $column_data[2] == 'true_sort')
+ {
+ $sql .= ' COLLATE utf8_unicode_ci';
+ }
+ }
+
+ if (isset($column_data['after']))
+ {
+ $return_array['after'] = $column_data['after'];
+ }
+
+ break;
+
+ case 'oracle':
+ $sql .= " {$column_type} ";
+ $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
+
+ // In Oracle empty strings ('') are treated as NULL.
+ // Therefore in oracle we allow NULL's for all DEFAULT '' entries
+ // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields)
+ if (!preg_match('/number/i', $column_type))
+ {
+ $sql .= ($column_data[1] === '' || $column_data[1] === null) ? '' : 'NOT NULL';
+ }
+
+ $return_array['auto_increment'] = false;
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ $return_array['auto_increment'] = true;
+ }
+
+ break;
+
+ case 'sqlite3':
+ $return_array['primary_key_set'] = false;
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ $sql .= ' INTEGER PRIMARY KEY AUTOINCREMENT';
+ $return_array['primary_key_set'] = true;
+ }
+ else
+ {
+ $sql .= ' ' . $column_type;
+ }
+
+ if (!is_null($column_data[1]))
+ {
+ $sql .= ' NOT NULL ';
+ $sql .= "DEFAULT '{$column_data[1]}'";
+ }
+
+ break;
+ }
+
+ $return_array['column_type_sql'] = $sql;
+
+ return $return_array;
+ }
+
+ /**
+ * Get the column's database type from the type map
+ *
+ * @param string $column_map_type
+ * @return array column type for this database
+ * and map type without length
+ */
+ function get_column_type($column_map_type)
+ {
+ $column_type = '';
+ if (strpos($column_map_type, ':') !== false)
+ {
+ list($orig_column_type, $column_length) = explode(':', $column_map_type);
+ if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']))
+ {
+ $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length);
+ }
+ else
+ {
+ if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule']))
+ {
+ switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0])
+ {
+ case 'div':
+ $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1];
+ $column_length = ceil($column_length);
+ $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
+ break;
+ }
+ }
+
+ if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit']))
+ {
+ switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0])
+ {
+ case 'mult':
+ $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1];
+ if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2])
+ {
+ $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3];
+ }
+ else
+ {
+ $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length);
+ }
+ break;
+ }
+ }
+ }
+ $orig_column_type .= ':';
+ }
+ else
+ {
+ $orig_column_type = $column_map_type;
+ $column_type = $this->dbms_type_map[$this->sql_layer][$column_map_type];
+ }
+
+ return array($column_type, $orig_column_type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_add($table_name, $column_name, $column_data, $inline = false)
+ {
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $after = (!empty($column_data['after'])) ? ' AFTER ' . $column_data['after'] : '';
+ $statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'] . $after;
+ break;
+
+ case 'oracle':
+ // Does not support AFTER, only through temporary table
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
+ break;
+
+ case 'sqlite3':
+ if ($inline && $this->return_statements)
+ {
+ return $column_name . ' ' . $column_data['column_type_sql'];
+ }
+
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_remove($table_name, $column_name, $inline = false)
+ {
+ $statements = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';
+ break;
+
+ case 'oracle':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
+ break;
+
+ case 'sqlite3':
+
+ if ($inline && $this->return_statements)
+ {
+ return $column_name;
+ }
+
+ $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name, $column_name);
+ if (empty($recreate_queries))
+ {
+ break;
+ }
+
+ $statements[] = 'begin';
+
+ $sql_create_table = array_shift($recreate_queries);
+
+ // Create a backup table and populate it, destroy the existing one
+ $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
+ $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ preg_match('#\((.*)\)#s', $sql_create_table, $matches);
+
+ $new_table_cols = trim($matches[1]);
+ $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
+ $column_list = array();
+
+ foreach ($old_table_cols as $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name)
+ {
+ continue;
+ }
+ $column_list[] = $entities[0];
+ }
+
+ $columns = implode(',', $column_list);
+
+ $new_table_cols = trim(preg_replace('/' . $column_name . '\b[^,]+(?:,|$)/m', '', $new_table_cols));
+ if (substr($new_table_cols, -1) === ',')
+ {
+ // Remove the comma from the last entry again
+ $new_table_cols = substr($new_table_cols, 0, -1);
+ }
+
+ // create a new table and fill it up. destroy the temp one
+ $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');';
+ $statements = array_merge($statements, $recreate_queries);
+
+ $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
+ $statements[] = 'DROP TABLE ' . $table_name . '_temp';
+
+ $statements[] = 'commit';
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_index_drop($table_name, $index_name)
+ {
+ $statements = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
+ break;
+
+ case 'oracle':
+ case 'sqlite3':
+ $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_table_drop($table_name)
+ {
+ $statements = array();
+
+ if (!$this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
+ // the most basic operation, get rid of the table
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ $sql = 'SELECT A.REFERENCED_NAME
+ FROM USER_DEPENDENCIES A, USER_TRIGGERS B
+ WHERE A.REFERENCED_TYPE = \'SEQUENCE\'
+ AND A.NAME = B.TRIGGER_NAME
+ AND B.TABLE_NAME = \'' . strtoupper($table_name) . "'";
+ $result = $this->db->sql_query($sql);
+
+ // any sequences ref'd to this table's triggers?
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $statements[] = "DROP SEQUENCE {$row['referenced_name']}";
+ }
+ $this->db->sql_freeresult($result);
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_primary_key($table_name, $column, $inline = false)
+ {
+ $statements = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
+ break;
+
+ case 'oracle':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
+ break;
+
+ case 'sqlite3':
+
+ if ($inline && $this->return_statements)
+ {
+ return $column;
+ }
+
+ $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name);
+ if (empty($recreate_queries))
+ {
+ break;
+ }
+
+ $statements[] = 'begin';
+
+ $sql_create_table = array_shift($recreate_queries);
+
+ // Create a backup table and populate it, destroy the existing one
+ $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
+ $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ preg_match('#\((.*)\)#s', $sql_create_table, $matches);
+
+ $new_table_cols = trim($matches[1]);
+ $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
+ $column_list = array();
+
+ foreach ($old_table_cols as $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY')
+ {
+ continue;
+ }
+ $column_list[] = $entities[0];
+ }
+
+ $columns = implode(',', $column_list);
+
+ // create a new table and fill it up. destroy the temp one
+ $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));';
+ $statements = array_merge($statements, $recreate_queries);
+
+ $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
+ $statements[] = 'DROP TABLE ' . $table_name . '_temp';
+
+ $statements[] = 'commit';
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_unique_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ case 'sqlite3':
+ $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
+ break;
+
+ case 'mysql_40':
+ case 'mysql_41':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')';
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_create_index($table_name, $index_name, $column)
+ {
+ $statements = array();
+
+ $this->check_index_name_length($table_name, $index_name);
+
+ // remove index length unless MySQL4
+ if ('mysql_40' != $this->sql_layer)
+ {
+ $column = preg_replace('#:.*$#', '', $column);
+ }
+
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ case 'sqlite3':
+ $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
+ break;
+
+ case 'mysql_40':
+ // add index size to definition as required by MySQL4
+ foreach ($column as $i => $col)
+ {
+ if (false !== strpos($col, ':'))
+ {
+ list($col, $index_size) = explode(':', $col);
+ $column[$i] = "$col($index_size)";
+ }
+ }
+ // no break
+ case 'mysql_41':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')';
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * Check whether the index name is too long
+ *
+ * @param string $table_name
+ * @param string $index_name
+ */
+ protected function check_index_name_length($table_name, $index_name)
+ {
+ $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
+ if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
+ {
+ $max_length = strlen($table_prefix) + 24;
+ trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_list_index($table_name)
+ {
+ $index_array = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $sql = 'SHOW KEYS
+ FROM ' . $table_name;
+ $col = 'Key_name';
+ break;
+
+ case 'oracle':
+ $sql = "SELECT index_name
+ FROM user_indexes
+ WHERE table_name = '" . strtoupper($table_name) . "'
+ AND generated = 'N'
+ AND uniqueness = 'NONUNIQUE'";
+ $col = 'index_name';
+ break;
+
+ case 'sqlite3':
+ $sql = "PRAGMA index_info('" . $table_name . "');";
+ $col = 'name';
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique'])
+ {
+ continue;
+ }
+
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ case 'sqlite3':
+ $row[$col] = substr($row[$col], strlen($table_name) + 1);
+ break;
+ }
+
+ $index_array[] = $row[$col];
+ }
+ $this->db->sql_freeresult($result);
+
+ return array_map('strtolower', $index_array);
+ }
+
+ /**
+ * Removes table_name from the index_name if it is at the beginning
+ *
+ * @param $table_name
+ * @param $index_name
+ * @return string
+ */
+ protected function strip_table_name_from_index_name($table_name, $index_name)
+ {
+ return (strpos(strtoupper($index_name), strtoupper($table_name)) === 0) ? substr($index_name, strlen($table_name) + 1) : $index_name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ function sql_column_change($table_name, $column_name, $column_data, $inline = false)
+ {
+ $original_column_data = $column_data;
+ $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
+ $statements = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ $statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
+ break;
+
+ case 'oracle':
+ // We need the data here
+ $old_return_statements = $this->return_statements;
+ $this->return_statements = true;
+
+ // Get list of existing indexes
+ $indexes = $this->get_existing_indexes($table_name, $column_name);
+ $unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
+
+ // Drop any indexes
+ if (!empty($indexes) || !empty($unique_indexes))
+ {
+ $drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
+ foreach ($drop_indexes as $index_name)
+ {
+ $result = $this->sql_index_drop($table_name, $this->strip_table_name_from_index_name($table_name, $index_name));
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ $temp_column_name = 'temp_' . substr(md5($column_name), 0, 25);
+ // Add a temporary table with the new type
+ $result = $this->sql_column_add($table_name, $temp_column_name, $original_column_data);
+ $statements = array_merge($statements, $result);
+
+ // Copy the data to the new column
+ $statements[] = 'UPDATE ' . $table_name . ' SET ' . $temp_column_name . ' = ' . $column_name;
+
+ // Drop the original column
+ $result = $this->sql_column_remove($table_name, $column_name);
+ $statements = array_merge($statements, $result);
+
+ // Recreate the original column with the new type
+ $result = $this->sql_column_add($table_name, $column_name, $original_column_data);
+ $statements = array_merge($statements, $result);
+
+ if (!empty($indexes))
+ {
+ // Recreate indexes after we changed the column
+ foreach ($indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_index($table_name, $this->strip_table_name_from_index_name($table_name, $index_name), $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ if (!empty($unique_indexes))
+ {
+ // Recreate unique indexes after we changed the column
+ foreach ($unique_indexes as $index_name => $index_data)
+ {
+ $result = $this->sql_create_unique_index($table_name, $this->strip_table_name_from_index_name($table_name, $index_name), $index_data);
+ $statements = array_merge($statements, $result);
+ }
+ }
+
+ // Copy the data to the original column
+ $statements[] = 'UPDATE ' . $table_name . ' SET ' . $column_name . ' = ' . $temp_column_name;
+
+ // Drop the temporary column again
+ $result = $this->sql_column_remove($table_name, $temp_column_name);
+ $statements = array_merge($statements, $result);
+
+ $this->return_statements = $old_return_statements;
+ break;
+
+ case 'sqlite3':
+
+ if ($inline && $this->return_statements)
+ {
+ return $column_name . ' ' . $column_data['column_type_sql'];
+ }
+
+ $recreate_queries = $this->sqlite_get_recreate_table_queries($table_name);
+ if (empty($recreate_queries))
+ {
+ break;
+ }
+
+ $statements[] = 'begin';
+
+ $sql_create_table = array_shift($recreate_queries);
+
+ // Create a temp table and populate it, destroy the existing one
+ $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $sql_create_table);
+ $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ preg_match('#\((.*)\)#s', $sql_create_table, $matches);
+
+ $new_table_cols = trim($matches[1]);
+ $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
+ $column_list = array();
+
+ foreach ($old_table_cols as $key => $declaration)
+ {
+ $declaration = trim($declaration);
+
+ // Check for the beginning of the constraint section and stop
+ if (preg_match('/[^\(]*\s*PRIMARY KEY\s+\(/', $declaration) ||
+ preg_match('/[^\(]*\s*UNIQUE\s+\(/', $declaration) ||
+ preg_match('/[^\(]*\s*FOREIGN KEY\s+\(/', $declaration) ||
+ preg_match('/[^\(]*\s*CHECK\s+\(/', $declaration))
+ {
+ break;
+ }
+
+ $entities = preg_split('#\s+#', $declaration);
+ $column_list[] = $entities[0];
+ if ($entities[0] == $column_name)
+ {
+ $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql'];
+ }
+ }
+
+ $columns = implode(',', $column_list);
+
+ // Create a new table and fill it up. destroy the temp one
+ $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');';
+ $statements = array_merge($statements, $recreate_queries);
+
+ $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
+ $statements[] = 'DROP TABLE ' . $table_name . '_temp';
+
+ $statements[] = 'commit';
+
+ break;
+ }
+
+ return $this->_sql_run_sql($statements);
+ }
+
+ /**
+ * Get a list with existing indexes for the column
+ *
+ * @param string $table_name
+ * @param string $column_name
+ * @param bool $unique Should we get unique indexes or normal ones
+ * @return array Array with Index name => columns
+ */
+ public function get_existing_indexes($table_name, $column_name, $unique = false)
+ {
+ switch ($this->sql_layer)
+ {
+ case 'mysql_40':
+ case 'mysql_41':
+ case 'sqlite3':
+ // Not supported
+ throw new \Exception('DBMS is not supported');
+ break;
+ }
+
+ $sql = '';
+ $existing_indexes = array();
+
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ $sql = "SELECT ix.index_name AS phpbb_index_name, ix.uniqueness AS is_unique
+ FROM all_ind_columns ixc, all_indexes ix
+ WHERE ix.index_name = ixc.index_name
+ AND ixc.table_name = '" . strtoupper($table_name) . "'
+ AND ixc.column_name = '" . strtoupper($column_name) . "'";
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!isset($row['is_unique']) || ($unique && $row['is_unique'] == 'UNIQUE') || (!$unique && $row['is_unique'] == 'NONUNIQUE'))
+ {
+ $existing_indexes[$row['phpbb_index_name']] = array();
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($existing_indexes))
+ {
+ return array();
+ }
+
+ switch ($this->sql_layer)
+ {
+ case 'oracle':
+ $sql = "SELECT index_name AS phpbb_index_name, column_name AS phpbb_column_name
+ FROM all_ind_columns
+ WHERE table_name = '" . strtoupper($table_name) . "'
+ AND " . $this->db->sql_in_set('index_name', array_keys($existing_indexes));
+ break;
+ }
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name'];
+ }
+ $this->db->sql_freeresult($result);
+
+ return $existing_indexes;
+ }
+
+ /**
+ * Returns the Queries which are required to recreate a table including indexes
+ *
+ * @param string $table_name
+ * @param string $remove_column When we drop a column, we remove the column
+ * from all indexes. If the index has no other
+ * column, we drop it completly.
+ * @return array
+ */
+ protected function sqlite_get_recreate_table_queries($table_name, $remove_column = '')
+ {
+ $queries = array();
+
+ $sql = "SELECT sql
+ FROM sqlite_master
+ WHERE type = 'table'
+ AND name = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+ $sql_create_table = $this->db->sql_fetchfield('sql');
+ $this->db->sql_freeresult($result);
+
+ if (!$sql_create_table)
+ {
+ return array();
+ }
+ $queries[] = $sql_create_table;
+
+ $sql = "SELECT sql
+ FROM sqlite_master
+ WHERE type = 'index'
+ AND tbl_name = '{$table_name}'";
+ $result = $this->db->sql_query($sql);
+ while ($sql_create_index = $this->db->sql_fetchfield('sql'))
+ {
+ if ($remove_column)
+ {
+ $match = array();
+ preg_match('#(?:[\w ]+)\((.*)\)#', $sql_create_index, $match);
+ if (!isset($match[1]))
+ {
+ continue;
+ }
+
+ // Find and remove $remove_column from the index
+ $columns = explode(', ', $match[1]);
+ $found_column = array_search($remove_column, $columns);
+ if ($found_column !== false)
+ {
+ unset($columns[$found_column]);
+
+ // If the column list is not empty add the index to the list
+ if (!empty($columns))
+ {
+ $queries[] = str_replace($match[1], implode(', ', $columns), $sql_create_index);
+ }
+ }
+ else
+ {
+ $queries[] = $sql_create_index;
+ }
+ }
+ else
+ {
+ $queries[] = $sql_create_index;
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ return $queries;
+ }
+}
diff --git a/phpBB/phpbb/db/tools/tools_interface.php b/phpBB/phpbb/db/tools/tools_interface.php
new file mode 100644
index 0000000000..f153f73a54
--- /dev/null
+++ b/phpBB/phpbb/db/tools/tools_interface.php
@@ -0,0 +1,202 @@
+<?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\tools;
+
+/**
+ * Interface for a Database Tools for handling cross-db actions such as altering columns, etc.
+ */
+interface tools_interface
+{
+ /**
+ * Handle passed database update array.
+ * Expected structure...
+ * Key being one of the following
+ * drop_tables: Drop tables
+ * add_tables: Add tables
+ * change_columns: Column changes (only type, not name)
+ * add_columns: Add columns to a table
+ * drop_keys: Dropping keys
+ * drop_columns: Removing/Dropping columns
+ * add_primary_keys: adding primary keys
+ * add_unique_index: adding an unique index
+ * add_index: adding an index (can be column:index_size if you need to provide size)
+ *
+ * The values are in this format:
+ * {TABLE NAME} => array(
+ * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}),
+ * {KEY/INDEX NAME} => array({COLUMN NAMES}),
+ * )
+ *
+ *
+ * @param array $schema_changes
+ * @return null
+ */
+ public function perform_schema_changes($schema_changes);
+
+ /**
+ * Gets a list of tables in the database.
+ *
+ * @return array Array of table names (all lower case)
+ */
+ public function sql_list_tables();
+
+ /**
+ * Check if table exists
+ *
+ * @param string $table_name The table name to check for
+ * @return bool true if table exists, else false
+ */
+ public function sql_table_exists($table_name);
+
+ /**
+ * Create SQL Table
+ *
+ * @param string $table_name The table name to create
+ * @param array $table_data Array containing table data.
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_create_table($table_name, $table_data);
+
+ /**
+ * Drop Table
+ *
+ * @param string $table_name The table name to drop
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_table_drop($table_name);
+
+ /**
+ * Gets a list of columns of a table.
+ *
+ * @param string $table_name Table name
+ * @return array Array of column names (all lower case)
+ */
+ public function sql_list_columns($table_name);
+
+ /**
+ * Check whether a specified column exist in a table
+ *
+ * @param string $table_name Table to check
+ * @param string $column_name Column to check
+ * @return bool True if column exists, false otherwise
+ */
+ public function sql_column_exists($table_name, $column_name);
+
+ /**
+ * Add new column
+ *
+ * @param string $table_name Table to modify
+ * @param string $column_name Name of the column to add
+ * @param array $column_data Column data
+ * @param bool $inline Whether the query should actually be run,
+ * or return a string for adding the column
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_column_add($table_name, $column_name, $column_data, $inline = false);
+
+ /**
+ * Change column type (not name!)
+ *
+ * @param string $table_name Table to modify
+ * @param string $column_name Name of the column to modify
+ * @param array $column_data Column data
+ * @param bool $inline Whether the query should actually be run,
+ * or return a string for modifying the column
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_column_change($table_name, $column_name, $column_data, $inline = false);
+
+ /**
+ * Drop column
+ *
+ * @param string $table_name Table to modify
+ * @param string $column_name Name of the column to drop
+ * @param bool $inline Whether the query should actually be run,
+ * or return a string for deleting the column
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_column_remove($table_name, $column_name, $inline = false);
+
+ /**
+ * List all of the indices that belong to a table
+ *
+ * NOTE: does not list
+ * - UNIQUE indices
+ * - PRIMARY keys
+ *
+ * @param string $table_name Table to check
+ * @return array Array with index names
+ */
+ public function sql_list_index($table_name);
+
+ /**
+ * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes.
+ *
+ * @param string $table_name Table to check the index at
+ * @param string $index_name The index name to check
+ * @return bool True if index exists, else false
+ */
+ public function sql_index_exists($table_name, $index_name);
+
+ /**
+ * Add index
+ *
+ * @param string $table_name Table to modify
+ * @param string $index_name Name of the index to create
+ * @param string|array $column Either a string with a column name, or an array with columns
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_create_index($table_name, $index_name, $column);
+
+ /**
+ * Drop Index
+ *
+ * @param string $table_name Table to modify
+ * @param string $index_name Name of the index to delete
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_index_drop($table_name, $index_name);
+
+ /**
+ * Check if a specified index exists in table.
+ *
+ * NOTE: Does not return normal and PRIMARY KEY indexes
+ *
+ * @param string $table_name Table to check the index at
+ * @param string $index_name The index name to check
+ * @return bool True if index exists, else false
+ */
+ public function sql_unique_index_exists($table_name, $index_name);
+
+ /**
+ * Add unique index
+ *
+ * @param string $table_name Table to modify
+ * @param string $index_name Name of the unique index to create
+ * @param string|array $column Either a string with a column name, or an array with columns
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_create_unique_index($table_name, $index_name, $column);
+
+ /**
+ * Add primary key
+ *
+ * @param string $table_name Table to modify
+ * @param string|array $column Either a string with a column name, or an array with columns
+ * @param bool $inline Whether the query should actually be run,
+ * or return a string for creating the key
+ * @return array|true Statements to run, or true if the statements have been executed
+ */
+ public function sql_create_primary_key($table_name, $column, $inline = false);
+}
diff --git a/phpBB/phpbb/debug/debug.php b/phpBB/phpbb/debug/debug.php
new file mode 100644
index 0000000000..c5ffada2e5
--- /dev/null
+++ b/phpBB/phpbb/debug/debug.php
@@ -0,0 +1,80 @@
+<?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\debug;
+
+use Symfony\Component\Debug\BufferingLogger;
+use Symfony\Component\Debug\DebugClassLoader;
+use Symfony\Component\Debug\ExceptionHandler;
+
+/**
+ * Registers all the debug tools.
+
+ * @see Symfony\Component\Debug\Debug
+ */
+class debug
+{
+ private static $enabled = false;
+
+ /**
+ * Enables the debug tools.
+ *
+ * This method registers an error handler and an exception handler.
+ *
+ * If the Symfony ClassLoader component is available, a special
+ * class loader is also registered.
+ *
+ * @param int $errorReportingLevel The level of error reporting you want
+ * @param bool $displayErrors Whether to display errors (for development) or just log them (for production)
+ */
+ public static function enable($errorReportingLevel = null, $displayErrors = true)
+ {
+ if (static::$enabled)
+ {
+ return;
+ }
+
+ static::$enabled = true;
+
+ if ($errorReportingLevel !== null)
+ {
+ error_reporting($errorReportingLevel);
+ }
+ else
+ {
+ error_reporting(-1);
+ }
+
+ if ('cli' !== php_sapi_name())
+ {
+ ini_set('display_errors', 0);
+ ExceptionHandler::register();
+ }
+ else if ($displayErrors && (!ini_get('log_errors') || ini_get('error_log')))
+ {
+ // CLI - display errors only if they're not already logged to STDERR
+ ini_set('display_errors', 1);
+ }
+
+ if ($displayErrors)
+ {
+ error_handler::register(new error_handler(new BufferingLogger()));
+ }
+ else
+ {
+ error_handler::register()->throwAt(0, true);
+ }
+
+ DebugClassLoader::enable();
+ }
+}
diff --git a/phpBB/phpbb/debug/error_handler.php b/phpBB/phpbb/debug/error_handler.php
new file mode 100644
index 0000000000..246e724f56
--- /dev/null
+++ b/phpBB/phpbb/debug/error_handler.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\debug;
+
+use Symfony\Component\Debug\ErrorHandler;
+
+class error_handler extends ErrorHandler
+{
+ public function handleError($type, $message, $file, $line, array $context, array $backtrace = null)
+ {
+ if ($type === E_USER_WARNING || $type === E_USER_NOTICE)
+ {
+ $handler = defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler';
+
+ $handler($type, $message, $file, $line);
+ }
+
+ return parent::handleError($type, $message, $file, $line, $context, $backtrace);
+ }
+}
diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php
index a214356ac3..b6854673c2 100644
--- a/phpBB/phpbb/di/container_builder.php
+++ b/phpBB/phpbb/di/container_builder.php
@@ -13,392 +13,617 @@
namespace phpbb\di;
+use phpbb\filesystem\filesystem;
+use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
+use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
+use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
-use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
+use Symfony\Component\Filesystem\Exception\IOException;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
class container_builder
{
- /** @var string phpBB Root Path */
- protected $phpbb_root_path;
-
- /** @var string php file extension */
- protected $php_ext;
-
/**
- * The container under construction
- *
- * @var ContainerBuilder
- */
- protected $container;
+ * @var string The environment to use.
+ */
+ protected $environment;
/**
- * @var \phpbb\db\driver\driver_interface
- */
- protected $dbal_connection = null;
+ * @var string phpBB Root Path
+ */
+ protected $phpbb_root_path;
/**
- * @var array the installed extensions
- */
- protected $installed_exts = null;
+ * @var string php file extension
+ */
+ protected $php_ext;
/**
- * Indicates whether the php config file should be injected into the container (default to true).
- *
- * @var bool
- */
- protected $inject_config = true;
+ * The container under construction
+ *
+ * @var ContainerBuilder
+ */
+ protected $container;
/**
- * Indicates whether extensions should be used (default to true).
- *
- * @var bool
- */
+ * Indicates whether extensions should be used (default to true).
+ *
+ * @var bool
+ */
protected $use_extensions = true;
/**
- * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config')
- *
- * @var string
- */
+ * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config')
+ *
+ * @var string
+ */
protected $config_path = null;
/**
- * Indicates whether the phpBB compile pass should be used (default to true).
- *
- * @var bool
- */
- protected $use_custom_pass = true;
+ * Indicates whether the container should be dumped to the filesystem (default to true).
+ *
+ * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
+ *
+ * @var bool
+ */
+ protected $use_cache = true;
/**
- * Indicates whether the kernel compile pass should be used (default to true).
- *
- * @var bool
- */
- protected $use_kernel_pass = true;
+ * Indicates if the container should be compiled automatically (default to true).
+ *
+ * @var bool
+ */
+ protected $compile_container = true;
/**
- * Indicates whether the container should be dumped to the filesystem (default to true).
- *
- * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
- *
- * @var bool
- */
- protected $dump_container = true;
+ * Custom parameters to inject into the container.
+ *
+ * Default to:
+ * array(
+ * 'core.root_path', $this->phpbb_root_path,
+ * 'core.php_ext', $this->php_ext,
+ * );
+ *
+ * @var array
+ */
+ protected $custom_parameters = [];
/**
- * Indicates if the container should be compiled automatically (default to true).
- *
- * @var bool
- */
- protected $compile_container = true;
+ * @var \phpbb\config_php_file
+ */
+ protected $config_php_file;
/**
- * Custom parameters to inject into the container.
- *
- * Default to true:
- * array(
- * 'core.root_path', $this->phpbb_root_path,
- * 'core.php_ext', $this->php_ext,
- * );
- *
- * @var array
- */
- protected $custom_parameters = null;
+ * @var string
+ */
+ protected $cache_dir;
/**
- * @var \phpbb\config_php_file
- */
- protected $config_php_file;
+ * @var array
+ */
+ private $container_extensions;
+
+ /** @var \Exception */
+ private $build_exception;
/**
- * Constructor
- *
- * @param \phpbb\config_php_file $config_php_file
- * @param string $phpbb_root_path Path to the phpbb includes directory.
- * @param string $php_ext php file extension
- */
- function __construct(\phpbb\config_php_file $config_php_file, $phpbb_root_path, $php_ext)
+ * Constructor
+ *
+ * @param string $phpbb_root_path Path to the phpbb includes directory.
+ * @param string $php_ext php file extension
+ */
+ public function __construct($phpbb_root_path, $php_ext)
{
- $this->config_php_file = $config_php_file;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
}
/**
- * Build and return a new Container respecting the current configuration
- *
- * @return \phpbb_cache_container|ContainerBuilder
- */
+ * Build and return a new Container respecting the current configuration
+ *
+ * @return \phpbb_cache_container|ContainerBuilder
+ */
public function get_container()
{
- $container_filename = $this->get_container_filename();
- if (!defined('DEBUG_CONTAINER') && $this->dump_container && file_exists($container_filename))
+ try
{
- require($container_filename);
- $this->container = new \phpbb_cache_container();
- }
- else
- {
- if ($this->config_path === null)
+ $container_filename = $this->get_container_filename();
+ $config_cache = new ConfigCache($container_filename, defined('DEBUG'));
+ if ($this->use_cache && $config_cache->isFresh())
{
- $this->config_path = $this->phpbb_root_path . 'config';
- }
- $container_extensions = array(new \phpbb\di\extension\core($this->config_path));
+ if ($this->use_extensions)
+ {
+ require($this->get_autoload_filename());
+ }
- if ($this->use_extensions)
- {
- $installed_exts = $this->get_installed_extensions();
- $container_extensions[] = new \phpbb\di\extension\ext($installed_exts);
+ require($config_cache->getPath());
+ $this->container = new \phpbb_cache_container();
}
-
- if ($this->inject_config)
+ else
{
- $container_extensions[] = new \phpbb\di\extension\config($this->config_php_file);
- }
+ $this->container_extensions = array(new extension\core($this->get_config_path()));
- $this->container = $this->create_container($container_extensions);
+ if ($this->use_extensions)
+ {
+ $this->load_extensions();
+ }
- if ($this->use_custom_pass)
- {
- // Symfony Kernel Listeners
- $this->container->addCompilerPass(new \phpbb\di\pass\collection_pass());
+ // Inject the config
+ if ($this->config_php_file)
+ {
+ $this->container_extensions[] = new extension\config($this->config_php_file);
+ }
+
+ $this->container = $this->create_container($this->container_extensions);
+
+ // Easy collections through tags
+ $this->container->addCompilerPass(new pass\collection_pass());
+
+ // Event listeners "phpBB style"
$this->container->addCompilerPass(new RegisterListenersPass('dispatcher', 'event.listener_listener', 'event.listener'));
- if ($this->use_kernel_pass)
+ // Event listeners "Symfony style"
+ $this->container->addCompilerPass(new RegisterListenersPass('dispatcher'));
+
+ if ($this->use_extensions)
+ {
+ $this->register_ext_compiler_pass();
+ }
+
+ $filesystem = new filesystem();
+ $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path())));
+ $loader->load($this->container->getParameter('core.environment') . '/config.yml');
+
+ $this->inject_custom_parameters();
+
+ if ($this->compile_container)
{
- $this->container->addCompilerPass(new RegisterListenersPass('dispatcher'));
+ $this->container->compile();
+
+ if ($this->use_cache)
+ {
+ $this->dump_container($config_cache);
+ }
}
}
- $this->inject_custom_parameters();
+ if ($this->compile_container && $this->config_php_file)
+ {
+ $this->container->set('config.php', $this->config_php_file);
+ }
- if ($this->compile_container)
+ return $this->container;
+ }
+ catch (\Exception $e)
+ {
+ // Don't try to recover if we are in the development environment
+ if ($this->get_environment() === 'development')
{
- $this->container->compile();
+ throw $e;
}
- if ($this->dump_container && !defined('DEBUG_CONTAINER'))
+ if ($this->build_exception === null)
+ {
+ $this->build_exception = $e;
+
+ return $this
+ ->without_extensions()
+ ->without_cache()
+ ->with_custom_parameters(array_merge($this->custom_parameters, [
+ 'container_exception' => $e,
+ ]))
+ ->get_container();
+ }
+ else
{
- $this->dump_container($container_filename);
+ // Rethrow the original exception if it's still failing
+ throw $this->build_exception;
}
}
+ }
- $this->container->set('config.php', $this->config_php_file);
+ /**
+ * Enable the extensions.
+ *
+ * @param string $environment The environment to use
+ * @return $this
+ */
+ public function with_environment($environment)
+ {
+ $this->environment = $environment;
- if ($this->compile_container)
- {
- $this->inject_dbal();
- }
+ return $this;
+ }
+
+ /**
+ * Enable the extensions.
+ *
+ * @return $this
+ */
+ public function with_extensions()
+ {
+ $this->use_extensions = true;
- return $this->container;
+ return $this;
}
/**
- * Set if the extensions should be used.
- *
- * @param bool $use_extensions
- */
- public function set_use_extensions($use_extensions)
+ * Disable the extensions.
+ *
+ * @return $this
+ */
+ public function without_extensions()
{
- $this->use_extensions = $use_extensions;
+ $this->use_extensions = false;
+
+ return $this;
}
/**
- * Set if the phpBB compile pass have to be used.
- *
- * @param bool $use_custom_pass
- */
- public function set_use_custom_pass($use_custom_pass)
+ * Enable the caching of the container.
+ *
+ * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
+ *
+ * @return $this
+ */
+ public function with_cache()
{
- $this->use_custom_pass = $use_custom_pass;
+ $this->use_cache = true;
+
+ return $this;
}
/**
- * Set if the kernel compile pass have to be used.
- *
- * @param bool $use_kernel_pass
- */
- public function set_use_kernel_pass($use_kernel_pass)
+ * Disable the caching of the container.
+ *
+ * @return $this
+ */
+ public function without_cache()
{
- $this->use_kernel_pass = $use_kernel_pass;
+ $this->use_cache = false;
+
+ return $this;
}
/**
- * Set if the php config file should be injecting into the container.
- *
- * @param bool $inject_config
- */
- public function set_inject_config($inject_config)
+ * Set the cache directory.
+ *
+ * @param string $cache_dir The cache directory.
+ * @return $this
+ */
+ public function with_cache_dir($cache_dir)
{
- $this->inject_config = $inject_config;
+ $this->cache_dir = $cache_dir;
+
+ return $this;
}
/**
- * Set if a dump container should be used.
- *
- * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
- *
- * @var bool $dump_container
- */
- public function set_dump_container($dump_container)
+ * Enable the compilation of the container.
+ *
+ * @return $this
+ */
+ public function with_compiled_container()
{
- $this->dump_container = $dump_container;
+ $this->compile_container = true;
+
+ return $this;
}
/**
- * Set if the container should be compiled automatically (default to true).
- *
- * @var bool $dump_container
- */
- public function set_compile_container($compile_container)
+ * Disable the compilation of the container.
+ *
+ * @return $this
+ */
+ public function without_compiled_container()
{
- $this->compile_container = $compile_container;
+ $this->compile_container = false;
+
+ return $this;
}
/**
- * Set a custom path to find the configuration of the container
- *
- * @param string $config_path
- */
- public function set_config_path($config_path)
+ * Set a custom path to find the configuration of the container.
+ *
+ * @param string $config_path
+ * @return $this
+ */
+ public function with_config_path($config_path)
{
$this->config_path = $config_path;
+
+ return $this;
}
/**
- * Set custom parameters to inject into the container.
- *
- * @param array $custom_parameters
- */
- public function set_custom_parameters($custom_parameters)
+ * Set custom parameters to inject into the container.
+ *
+ * @param array $custom_parameters
+ * @return $this
+ */
+ public function with_custom_parameters($custom_parameters)
{
$this->custom_parameters = $custom_parameters;
+
+ return $this;
}
/**
- * Dump the container to the disk.
- *
- * @param string $container_filename The name of the file.
- */
- protected function dump_container($container_filename)
+ * Set custom parameters to inject into the container.
+ *
+ * @param \phpbb\config_php_file $config_php_file
+ * @return $this
+ */
+ public function with_config(\phpbb\config_php_file $config_php_file)
{
- $dumper = new PhpDumper($this->container);
- $cached_container_dump = $dumper->dump(array(
- 'class' => 'phpbb_cache_container',
- 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder',
- ));
+ $this->config_php_file = $config_php_file;
- file_put_contents($container_filename, $cached_container_dump);
+ return $this;
}
/**
- * Inject the connection into the container if one was opened.
- */
- protected function inject_dbal()
+ * Returns the path to the container configuration (default: root_path/config)
+ *
+ * @return string
+ */
+ protected function get_config_path()
{
- if ($this->dbal_connection !== null)
- {
- $this->container->get('dbal.conn')->set_driver($this->dbal_connection);
- }
+ return $this->config_path ?: $this->phpbb_root_path . 'config';
}
/**
- * Get DB connection.
- *
- * @return \phpbb\db\driver\driver_interface
- */
- protected function get_dbal_connection()
+ * Returns the path to the cache directory (default: root_path/cache/environment).
+ *
+ * @return string Path to the cache directory.
+ */
+ protected function get_cache_dir()
{
- if ($this->dbal_connection === null)
- {
- $dbal_driver_class = $this->config_php_file->convert_30_dbms_to_31($this->config_php_file->get('dbms'));
- $this->dbal_connection = new $dbal_driver_class();
- $this->dbal_connection->sql_connect(
- $this->config_php_file->get('dbhost'),
- $this->config_php_file->get('dbuser'),
- $this->config_php_file->get('dbpasswd'),
- $this->config_php_file->get('dbname'),
- $this->config_php_file->get('dbport'),
- defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK
- );
- }
-
- return $this->dbal_connection;
+ return $this->cache_dir ?: $this->phpbb_root_path . 'cache/' . $this->get_environment() . '/';
}
/**
- * Get enabled extensions.
- *
- * @return array enabled extensions
- */
- protected function get_installed_extensions()
+ * Load the enabled extensions.
+ */
+ protected function load_extensions()
{
- $db = $this->get_dbal_connection();
- $extension_table = $this->config_php_file->get('table_prefix') . 'ext';
+ if ($this->config_php_file !== null)
+ {
+ // Build an intermediate container to load the ext list from the database
+ $container_builder = new container_builder($this->phpbb_root_path, $this->php_ext);
+ $ext_container = $container_builder
+ ->without_cache()
+ ->without_extensions()
+ ->with_config($this->config_php_file)
+ ->with_config_path($this->get_config_path())
+ ->with_environment('production')
+ ->without_compiled_container()
+ ->get_container()
+ ;
+
+ $ext_container->register('cache.driver', '\\phpbb\\cache\\driver\\dummy');
+ $ext_container->compile();
+
+ $extensions = $ext_container->get('ext.manager')->all_enabled();
+
+ // Load each extension found
+ $autoloaders = '<?php
+/**
+ * Loads all extensions custom auto-loaders.
+ *
+ * This file has been auto-generated
+ * by phpBB while loading the extensions.
+ */
+
+';
+ foreach ($extensions as $ext_name => $path)
+ {
+ $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\\extension';
- $sql = 'SELECT *
- FROM ' . $extension_table . '
- WHERE ext_active = 1';
+ if (!class_exists($extension_class))
+ {
+ $extension_class = '\\phpbb\\extension\\di\\extension_base';
+ }
+
+ $this->container_extensions[] = new $extension_class($ext_name, $path);
+
+ // Load extension autoloader
+ $filename = $path . 'vendor/autoload.php';
+ if (file_exists($filename))
+ {
+ $autoloaders .= "require('{$filename}');\n";
+ }
+ }
- $result = $db->sql_query($sql);
- $rows = $db->sql_fetchrowset($result);
- $db->sql_freeresult($result);
+ $configCache = new ConfigCache($this->get_autoload_filename(), false);
+ $configCache->write($autoloaders);
- $exts = array();
- foreach ($rows as $row)
+ require($this->get_autoload_filename());
+ }
+ else
{
- $exts[$row['ext_name']] = $this->phpbb_root_path . 'ext/' . $row['ext_name'] . '/';
+ // To load the extensions we need the database credentials.
+ // Automatically disable the extensions if we don't have them.
+ $this->use_extensions = false;
}
+ }
+
+ /**
+ * Dump the container to the disk.
+ *
+ * @param ConfigCache $cache The config cache
+ */
+ protected function dump_container($cache)
+ {
+ try
+ {
+ $dumper = new PhpDumper($this->container);
+ $proxy_dumper = new ProxyDumper();
+ $dumper->setProxyDumper($proxy_dumper);
- return $exts;
+ $cached_container_dump = $dumper->dump(array(
+ 'class' => 'phpbb_cache_container',
+ 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder',
+ ));
+
+ $cache->write($cached_container_dump, $this->container->getResources());
+ }
+ catch (IOException $e)
+ {
+ // Don't fail if the cache isn't writeable
+ }
}
/**
- * Create the ContainerBuilder object
- *
- * @param array $extensions Array of Container extension objects
- * @return ContainerBuilder object
- */
+ * Create the ContainerBuilder object
+ *
+ * @param array $extensions Array of Container extension objects
+ * @return ContainerBuilder object
+ */
protected function create_container(array $extensions)
{
- $container = new ContainerBuilder();
+ $container = new ContainerBuilder(new ParameterBag($this->get_core_parameters()));
+ $container->setProxyInstantiator(new RuntimeInstantiator());
+
+ $extensions_alias = array();
foreach ($extensions as $extension)
{
$container->registerExtension($extension);
- $container->loadFromExtension($extension->getAlias());
+ $extensions_alias[] = $extension->getAlias();
}
+ $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions_alias));
+
return $container;
}
/**
- * Inject the customs parameters into the container
- */
+ * Inject the customs parameters into the container
+ */
protected function inject_custom_parameters()
{
- if ($this->custom_parameters === null)
+ foreach ($this->custom_parameters as $key => $value)
{
- $this->custom_parameters = array(
- 'core.root_path' => $this->phpbb_root_path,
- 'core.php_ext' => $this->php_ext,
- );
+ $this->container->setParameter($key, $value);
}
- foreach ($this->custom_parameters as $key => $value)
+ }
+
+ /**
+ * Returns the core parameters.
+ *
+ * @return array An array of core parameters
+ */
+ protected function get_core_parameters()
+ {
+ return array_merge(
+ array(
+ 'core.root_path' => $this->phpbb_root_path,
+ 'core.php_ext' => $this->php_ext,
+ 'core.environment' => $this->get_environment(),
+ 'core.debug' => defined('DEBUG') ? DEBUG : false,
+ 'core.cache_dir' => $this->get_cache_dir(),
+ ),
+ $this->get_env_parameters()
+ );
+ }
+
+ /**
+ * Gets the environment parameters.
+ *
+ * Only the parameters starting with "PHPBB__" are considered.
+ *
+ * @return array An array of parameters
+ */
+ protected function get_env_parameters()
+ {
+ $parameters = array();
+ foreach ($_SERVER as $key => $value)
{
- $this->container->setParameter($key, $value);
+ if (0 === strpos($key, 'PHPBB__'))
+ {
+ $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
+ }
}
+
+ return $parameters;
}
/**
- * Get the filename under which the dumped container will be stored.
- *
- * @return string Path for dumped container
- */
+ * Get the filename under which the dumped container will be stored.
+ *
+ * @return string Path for dumped container
+ */
protected function get_container_filename()
{
- return $this->phpbb_root_path . 'cache/container_' . md5($this->phpbb_root_path) . '.' . $this->php_ext;
+ $container_params = [
+ 'phpbb_root_path' => $this->phpbb_root_path,
+ 'use_extensions' => $this->use_extensions,
+ 'config_path' => $this->config_path,
+ ];
+
+ return $this->get_cache_dir() . 'container_' . md5(implode(',', $container_params)) . '.' . $this->php_ext;
+ }
+
+ /**
+ * Get the filename under which the dumped extensions autoloader will be stored.
+ *
+ * @return string Path for dumped extensions autoloader
+ */
+ protected function get_autoload_filename()
+ {
+ $container_params = [
+ 'phpbb_root_path' => $this->phpbb_root_path,
+ 'use_extensions' => $this->use_extensions,
+ 'config_path' => $this->config_path,
+ ];
+
+ return $this->get_cache_dir() . 'autoload_' . md5(implode(',', $container_params)) . '.' . $this->php_ext;
+ }
+
+ /**
+ * Return the name of the current environment.
+ *
+ * @return string
+ */
+ protected function get_environment()
+ {
+ return $this->environment ?: PHPBB_ENVIRONMENT;
+ }
+
+ private function register_ext_compiler_pass()
+ {
+ $finder = new Finder();
+ $finder
+ ->name('*_pass.php')
+ ->path('di/pass')
+ ->files()
+ ->ignoreDotFiles(true)
+ ->ignoreUnreadableDirs(true)
+ ->ignoreVCS(true)
+ ->followLinks()
+ ->in($this->phpbb_root_path . 'ext')
+ ;
+
+ /** @var \SplFileInfo $pass */
+ foreach ($finder as $pass)
+ {
+ $filename = $pass->getPathname();
+ $filename = substr($filename, 0, -strlen('.' . $pass->getExtension()));
+ $filename = str_replace(DIRECTORY_SEPARATOR, '/', $filename);
+ $className = preg_replace('#^.*ext/#', '', $filename);
+ $className = '\\' . str_replace('/', '\\', $className);
+
+ if (class_exists($className) && in_array('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface', class_implements($className), true))
+ {
+ $this->container->addCompilerPass(new $className());
+ }
+ }
}
}
diff --git a/phpBB/phpbb/di/extension/container_configuration.php b/phpBB/phpbb/di/extension/container_configuration.php
new file mode 100644
index 0000000000..4585d6509e
--- /dev/null
+++ b/phpBB/phpbb/di/extension/container_configuration.php
@@ -0,0 +1,52 @@
+<?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\di\extension;
+
+use Symfony\Component\Config\Definition\Builder\TreeBuilder;
+use Symfony\Component\Config\Definition\ConfigurationInterface;
+
+class container_configuration implements ConfigurationInterface
+{
+
+ /**
+ * Generates the configuration tree builder.
+ *
+ * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
+ */
+ public function getConfigTreeBuilder()
+ {
+ $treeBuilder = new TreeBuilder();
+ $rootNode = $treeBuilder->root('core');
+ $rootNode
+ ->children()
+ ->booleanNode('require_dev_dependencies')->defaultValue(false)->end()
+ ->arrayNode('debug')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->booleanNode('exceptions')->defaultValue(false)->end()
+ ->end()
+ ->end()
+ ->arrayNode('twig')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->booleanNode('debug')->defaultValue(null)->end()
+ ->booleanNode('auto_reload')->defaultValue(null)->end()
+ ->booleanNode('enable_debug_extension')->defaultValue(false)->end()
+ ->end()
+ ->end()
+ ->end()
+ ;
+ return $treeBuilder;
+ }
+}
diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php
index ca4fa5c082..29c0b0e44e 100644
--- a/phpBB/phpbb/di/extension/core.php
+++ b/phpBB/phpbb/di/extension/core.php
@@ -13,53 +13,110 @@
namespace phpbb\di\extension;
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
-use Symfony\Component\Config\FileLocator;
+use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* Container core extension
*/
class core extends Extension
{
+ const TWIG_OPTIONS_POSITION = 6;
+
/**
- * Config path
- * @var string
- */
+ * Config path
+ * @var string
+ */
protected $config_path;
/**
- * Constructor
- *
- * @param string $config_path Config path
- */
+ * Constructor
+ *
+ * @param string $config_path Config path
+ */
public function __construct($config_path)
{
$this->config_path = $config_path;
}
/**
- * Loads a specific configuration.
- *
- * @param array $config An array of configuration values
- * @param ContainerBuilder $container A ContainerBuilder instance
- *
- * @throws \InvalidArgumentException When provided tag is not defined in this extension
- */
- public function load(array $config, ContainerBuilder $container)
+ * Loads a specific configuration.
+ *
+ * @param array $configs An array of configuration values
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ *
+ * @throws \InvalidArgumentException When provided tag is not defined in this extension
+ */
+ public function load(array $configs, ContainerBuilder $container)
+ {
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($this->config_path)));
+ $loader->load($container->getParameter('core.environment') . '/container/environment.yml');
+
+ $config = $this->getConfiguration($configs, $container);
+ $config = $this->processConfiguration($config, $configs);
+
+ if ($config['require_dev_dependencies'])
+ {
+ if (!class_exists('Goutte\Client', true))
+ {
+ trigger_error(
+ 'Composer development dependencies have not been set up for the ' . $container->getParameter('core.environment') . ' environment yet, run ' .
+ "'php ../composer.phar install --dev' from the phpBB directory to do so.",
+ E_USER_ERROR
+ );
+ }
+ }
+
+ // Set the Twig options if defined in the environment
+ $definition = $container->getDefinition('template.twig.environment');
+ $twig_environment_options = $definition->getArgument(static::TWIG_OPTIONS_POSITION);
+ if ($config['twig']['debug'])
+ {
+ $twig_environment_options['debug'] = true;
+ }
+ if ($config['twig']['auto_reload'])
+ {
+ $twig_environment_options['auto_reload'] = true;
+ }
+
+ // Replace the 7th argument, the options passed to the environment
+ $definition->replaceArgument(static::TWIG_OPTIONS_POSITION, $twig_environment_options);
+
+ if ($config['twig']['enable_debug_extension'])
+ {
+ $definition = $container->getDefinition('template.twig.extensions.debug');
+ $definition->addTag('twig.extension');
+ }
+
+ // Set the debug options
+ foreach ($config['debug'] as $name => $value)
+ {
+ $container->setParameter('debug.' . $name, $value);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration(array $config, ContainerBuilder $container)
{
- $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path)));
- $loader->load('services.yml');
+ $r = new \ReflectionClass('\phpbb\di\extension\container_configuration');
+ $container->addResource(new FileResource($r->getFileName()));
+
+ return new container_configuration();
}
/**
- * Returns the recommended alias to use in XML.
- *
- * This alias is also the mandatory prefix to use when using YAML.
- *
- * @return string The alias
- */
+ * Returns the recommended alias to use in XML.
+ *
+ * This alias is also the mandatory prefix to use when using YAML.
+ *
+ * @return string The alias
+ */
public function getAlias()
{
return 'core';
diff --git a/phpBB/phpbb/di/extension/ext.php b/phpBB/phpbb/di/extension/ext.php
deleted file mode 100644
index 718c992d2e..0000000000
--- a/phpBB/phpbb/di/extension/ext.php
+++ /dev/null
@@ -1,67 +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\di\extension;
-
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\HttpKernel\DependencyInjection\Extension;
-use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
-use Symfony\Component\Config\FileLocator;
-
-/**
-* Container ext extension
-*/
-class ext extends Extension
-{
- protected $paths = array();
-
- public function __construct($enabled_extensions)
- {
- foreach ($enabled_extensions as $ext => $path)
- {
- $this->paths[] = $path;
- }
- }
-
- /**
- * Loads a specific configuration.
- *
- * @param array $config An array of configuration values
- * @param ContainerBuilder $container A ContainerBuilder instance
- *
- * @throws \InvalidArgumentException When provided tag is not defined in this extension
- */
- public function load(array $config, ContainerBuilder $container)
- {
- foreach ($this->paths as $path)
- {
- if (file_exists($path . '/config/services.yml'))
- {
- $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($path . '/config')));
- $loader->load('services.yml');
- }
- }
- }
-
- /**
- * Returns the recommended alias to use in XML.
- *
- * This alias is also the mandatory prefix to use when using YAML.
- *
- * @return string The alias
- */
- public function getAlias()
- {
- return 'ext';
- }
-}
diff --git a/phpBB/phpbb/di/ordered_service_collection.php b/phpBB/phpbb/di/ordered_service_collection.php
new file mode 100644
index 0000000000..046012ae5b
--- /dev/null
+++ b/phpBB/phpbb/di/ordered_service_collection.php
@@ -0,0 +1,117 @@
+<?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\di;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Collection of services in a specified order
+ */
+class ordered_service_collection extends service_collection
+{
+ /**
+ * @var bool
+ */
+ protected $is_ordered;
+
+ /**
+ * @var array
+ */
+ protected $service_ids;
+
+ /**
+ * Constructor
+ *
+ * @param ContainerInterface $container Container object
+ */
+ public function __construct(ContainerInterface $container)
+ {
+ $this->is_ordered = false;
+ $this->service_ids = array();
+
+ parent::__construct($container);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIterator()
+ {
+ if (!$this->is_ordered)
+ {
+ $this->sort_services();
+ }
+
+ return new service_collection_iterator($this);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($index)
+ {
+ if (!$this->is_ordered)
+ {
+ $this->sort_services();
+ }
+
+ return parent::offsetExists($index);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($index)
+ {
+ if (!$this->is_ordered)
+ {
+ $this->sort_services();
+ }
+
+ return parent::offsetGet($index);
+ }
+
+ /**
+ * Adds a service ID to the collection
+ *
+ * @param string $service_id
+ * @param int $order
+ */
+ public function add($service_id, $order = 0)
+ {
+ $order = (int) $order;
+ $this->service_ids[$order][] = $service_id;
+ $this->is_ordered = false;
+ }
+
+ protected function sort_services()
+ {
+ if ($this->is_ordered)
+ {
+ return;
+ }
+
+ $this->exchangeArray(array());
+ ksort($this->service_ids);
+ foreach ($this->service_ids as $service_order_group)
+ {
+ foreach ($service_order_group as $service_id)
+ {
+ $this->offsetSet($service_id, null);
+ }
+ }
+
+ $this->is_ordered = true;
+ }
+}
diff --git a/phpBB/phpbb/di/pass/collection_pass.php b/phpBB/phpbb/di/pass/collection_pass.php
index a5c054674e..341f88518d 100644
--- a/phpBB/phpbb/di/pass/collection_pass.php
+++ b/phpBB/phpbb/di/pass/collection_pass.php
@@ -34,10 +34,30 @@ class collection_pass implements CompilerPassInterface
foreach ($container->findTaggedServiceIds('service_collection') as $id => $data)
{
$definition = $container->getDefinition($id);
+ $is_ordered_collection = (substr($definition->getClass(), -strlen('ordered_service_collection')) === 'ordered_service_collection');
+ $is_class_name_aware = (isset($data[0]['class_name_aware']) && $data[0]['class_name_aware']);
foreach ($container->findTaggedServiceIds($data[0]['tag']) as $service_id => $service_data)
{
- $definition->addMethodCall('add', array($service_id));
+ if ($is_ordered_collection)
+ {
+ $arguments = array($service_id, $service_data[0]['order']);
+ }
+ else
+ {
+ $arguments = array($service_id);
+ }
+
+ if ($is_class_name_aware)
+ {
+ $service_definition = $container->getDefinition($service_id);
+ $definition->addMethodCall('add_service_class', array(
+ $service_id,
+ $service_definition->getClass()
+ ));
+ }
+
+ $definition->addMethodCall('add', $arguments);
}
}
}
diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection.php
index 82ca9bf679..8e9175e204 100644
--- a/phpBB/phpbb/di/service_collection.php
+++ b/phpBB/phpbb/di/service_collection.php
@@ -26,6 +26,11 @@ class service_collection extends \ArrayObject
protected $container;
/**
+ * @var array
+ */
+ protected $service_classes;
+
+ /**
* Constructor
*
* @param ContainerInterface $container Container object
@@ -33,6 +38,7 @@ class service_collection extends \ArrayObject
public function __construct(ContainerInterface $container)
{
$this->container = $container;
+ $this->service_classes = array();
}
/**
@@ -76,4 +82,25 @@ class service_collection extends \ArrayObject
{
$this->offsetSet($name, null);
}
+
+ /**
+ * Add a service's class to the collection
+ *
+ * @param string $service_id
+ * @param string $class
+ */
+ public function add_service_class($service_id, $class)
+ {
+ $this->service_classes[$service_id] = $class;
+ }
+
+ /**
+ * Get services' classes
+ *
+ * @return array
+ */
+ public function get_service_classes()
+ {
+ return $this->service_classes;
+ }
}
diff --git a/phpBB/phpbb/di/service_collection_iterator.php b/phpBB/phpbb/di/service_collection_iterator.php
index 0d031ab52d..31bc156e99 100644
--- a/phpBB/phpbb/di/service_collection_iterator.php
+++ b/phpBB/phpbb/di/service_collection_iterator.php
@@ -32,7 +32,7 @@ class service_collection_iterator extends \ArrayIterator
*/
public function __construct(service_collection $collection, $flags = 0)
{
- parent::__construct($collection, $flags);
+ parent::__construct($collection->getArrayCopy(), $flags);
$this->collection = $collection;
}
diff --git a/phpBB/phpbb/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php
index 9d15f9370e..3c7375dadf 100644
--- a/phpBB/phpbb/event/kernel_exception_subscriber.php
+++ b/phpBB/phpbb/event/kernel_exception_subscriber.php
@@ -24,15 +24,17 @@ class kernel_exception_subscriber implements EventSubscriberInterface
{
/**
* Template object
+ *
* @var \phpbb\template\template
*/
protected $template;
/**
- * User object
- * @var \phpbb\user
+ * Language object
+ *
+ * @var \phpbb\language\language
*/
- protected $user;
+ protected $language;
/** @var \phpbb\request\type_cast_helper */
protected $type_caster;
@@ -40,13 +42,13 @@ class kernel_exception_subscriber implements EventSubscriberInterface
/**
* Construct method
*
- * @param \phpbb\template\template $template Template object
- * @param \phpbb\user $user User object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\language\language $language Language object
*/
- public function __construct(\phpbb\template\template $template, \phpbb\user $user)
+ public function __construct(\phpbb\template\template $template, \phpbb\language\language $language)
{
$this->template = $template;
- $this->user = $user;
+ $this->language = $language;
$this->type_caster = new \phpbb\request\type_cast_helper();
}
@@ -65,7 +67,7 @@ class kernel_exception_subscriber implements EventSubscriberInterface
if ($exception instanceof \phpbb\exception\exception_interface)
{
- $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($message), $exception->get_parameters()));
+ $message = $this->language->lang_array($message, $exception->get_parameters());
}
// Show <strong> text in bold
@@ -73,10 +75,10 @@ class kernel_exception_subscriber implements EventSubscriberInterface
if (!$event->getRequest()->isXmlHttpRequest())
{
- page_header($this->user->lang('INFORMATION'));
+ page_header($this->language->lang('INFORMATION'));
$this->template->assign_vars(array(
- 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'),
+ 'MESSAGE_TITLE' => $this->language->lang('INFORMATION'),
'MESSAGE_TEXT' => $message,
));
@@ -114,7 +116,7 @@ class kernel_exception_subscriber implements EventSubscriberInterface
$event->setResponse($response);
}
- public static function getSubscribedEvents()
+ static public function getSubscribedEvents()
{
return array(
KernelEvents::EXCEPTION => 'on_kernel_exception',
diff --git a/phpBB/phpbb/event/kernel_request_subscriber.php b/phpBB/phpbb/event/kernel_request_subscriber.php
deleted file mode 100644
index ee9f29a59d..0000000000
--- a/phpBB/phpbb/event/kernel_request_subscriber.php
+++ /dev/null
@@ -1,82 +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\event;
-
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\EventListener\RouterListener;
-use Symfony\Component\Routing\RequestContext;
-
-class kernel_request_subscriber implements EventSubscriberInterface
-{
- /**
- * Extension manager object
- * @var \phpbb\extension\manager
- */
- protected $manager;
-
- /**
- * PHP file extension
- * @var string
- */
- protected $php_ext;
-
- /**
- * Root path
- * @var string
- */
- protected $root_path;
-
- /**
- * Construct method
- *
- * @param \phpbb\extension\manager $manager Extension manager object
- * @param string $root_path Root path
- * @param string $php_ext PHP file extension
- */
- public function __construct(\phpbb\extension\manager $manager, $root_path, $php_ext)
- {
- $this->root_path = $root_path;
- $this->php_ext = $php_ext;
- $this->manager = $manager;
- }
-
- /**
- * This listener is run when the KernelEvents::REQUEST event is triggered
- *
- * This is responsible for setting up the routing information
- *
- * @param GetResponseEvent $event
- * @throws \BadMethodCallException
- * @return null
- */
- public function on_kernel_request(GetResponseEvent $event)
- {
- $request = $event->getRequest();
- $context = new RequestContext();
- $context->fromRequest($request);
-
- $matcher = phpbb_get_url_matcher($this->manager, $context, $this->root_path, $this->php_ext);
- $router_listener = new RouterListener($matcher, $context);
- $router_listener->onKernelRequest($event);
- }
-
- public static function getSubscribedEvents()
- {
- return array(
- KernelEvents::REQUEST => 'on_kernel_request',
- );
- }
-}
diff --git a/phpBB/phpbb/event/kernel_terminate_subscriber.php b/phpBB/phpbb/event/kernel_terminate_subscriber.php
index 3a709f73fd..f0d0a2f595 100644
--- a/phpBB/phpbb/event/kernel_terminate_subscriber.php
+++ b/phpBB/phpbb/event/kernel_terminate_subscriber.php
@@ -32,7 +32,7 @@ class kernel_terminate_subscriber implements EventSubscriberInterface
exit_handler();
}
- public static function getSubscribedEvents()
+ static public function getSubscribedEvents()
{
return array(
KernelEvents::TERMINATE => array('on_kernel_terminate', ~PHP_INT_MAX),
diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php
index 02c2a1b9d6..e042d0a5d1 100644
--- a/phpBB/phpbb/event/md_exporter.php
+++ b/phpBB/phpbb/event/md_exporter.php
@@ -99,7 +99,7 @@ class md_exporter
{
$this->crawl_eventsmd($md_file, 'styles');
- $styles = array('prosilver', 'subsilver2');
+ $styles = array('prosilver');
foreach ($styles as $style)
{
$file_list = $this->get_recursive_file_list(
@@ -266,7 +266,7 @@ class md_exporter
$wiki_page = '= Template Events =' . "\n";
}
$wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";
- $wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Subsilver Placement (If applicable) !! Added in Release !! Explanation' . "\n";
+ $wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Added in Release !! Explanation' . "\n";
}
foreach ($this->events as $event_name => $event)
@@ -280,7 +280,7 @@ class md_exporter
}
else
{
- $wiki_page .= implode(', ', $event['files']['prosilver']) . ' || ' . implode(', ', $event['files']['subsilver2']);
+ $wiki_page .= implode(', ', $event['files']['prosilver']);
}
$wiki_page .= " || {$event['since']} || " . str_replace("\n", ' ', $event['description']) . "\n";
@@ -371,7 +371,6 @@ class md_exporter
{
$files_list = array(
'prosilver' => array(),
- 'subsilver2' => array(),
'adm' => array(),
);
@@ -391,10 +390,6 @@ class md_exporter
{
$files_list['prosilver'][] = substr($file, strlen('styles/prosilver/template/'));
}
- else if (($this->filter !== 'adm') && strpos($file, 'styles/subsilver2/template/') === 0)
- {
- $files_list['subsilver2'][] = substr($file, strlen('styles/subsilver2/template/'));
- }
else if (($this->filter === 'adm') && strpos($file, 'adm/style/') === 0)
{
$files_list['adm'][] = substr($file, strlen('adm/style/'));
diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php
index 5bb530bad4..c7778cfed1 100644
--- a/phpBB/phpbb/extension/base.php
+++ b/phpBB/phpbb/extension/base.php
@@ -24,7 +24,7 @@ class base implements \phpbb\extension\extension_interface
protected $container;
/** @var \phpbb\finder */
- protected $finder;
+ protected $extension_finder;
/** @var \phpbb\db\migrator */
protected $migrator;
@@ -73,9 +73,7 @@ class base implements \phpbb\extension\extension_interface
*/
public function enable_step($old_state)
{
- $migrations = $this->get_migration_file_list();
-
- $this->migrator->set_migrations($migrations);
+ $this->get_migration_file_list();
$this->migrator->update();
@@ -103,8 +101,6 @@ class base implements \phpbb\extension\extension_interface
{
$migrations = $this->get_migration_file_list();
- $this->migrator->set_migrations($migrations);
-
foreach ($migrations as $migration)
{
while ($this->migrator->migration_state($migration) !== false)
@@ -137,6 +133,10 @@ class base implements \phpbb\extension\extension_interface
$migrations = $this->extension_finder->get_classes_from_files($migrations);
+ $this->migrator->set_migrations($migrations);
+
+ $migrations = $this->migrator->get_migrations();
+
return $migrations;
}
}
diff --git a/phpBB/phpbb/extension/di/extension_base.php b/phpBB/phpbb/extension/di/extension_base.php
new file mode 100644
index 0000000000..ba74615e70
--- /dev/null
+++ b/phpBB/phpbb/extension/di/extension_base.php
@@ -0,0 +1,138 @@
+<?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\extension\di;
+
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+
+/**
+ * Container core extension
+ */
+class extension_base extends Extension
+{
+ /**
+ * Name of the extension (vendor/name)
+ *
+ * @var string
+ */
+ protected $extension_name;
+
+ /**
+ * Path to the extension.
+ *
+ * @var string
+ */
+ protected $ext_path;
+
+ /**
+ * Constructor
+ *
+ * @param string $extension_name Name of the extension (vendor/name)
+ * @param string $ext_path Path to the extension
+ */
+ public function __construct($extension_name, $ext_path)
+ {
+ $this->extension_name = $extension_name;
+ $this->ext_path = $ext_path;
+ }
+
+ /**
+ * Loads a specific configuration.
+ *
+ * @param array $configs An array of configuration values
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ *
+ * @throws \InvalidArgumentException When provided tag is not defined in this extension
+ */
+ public function load(array $configs, ContainerBuilder $container)
+ {
+ $this->load_services($container);
+ }
+
+ /**
+ * Loads the services.yml file.
+ *
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ */
+ protected function load_services(ContainerBuilder $container)
+ {
+ $services_directory = false;
+ $services_file = false;
+
+ if (file_exists($this->ext_path . 'config/' . $container->getParameter('core.environment') . '/container/environment.yml'))
+ {
+ $services_directory = $this->ext_path . 'config/' . $container->getParameter('core.environment') . '/container/';
+ $services_file = 'environment.yml';
+ }
+ else if (!is_dir($this->ext_path . 'config/' . $container->getParameter('core.environment')))
+ {
+ if (file_exists($this->ext_path . 'config/default/container/environment.yml'))
+ {
+ $services_directory = $this->ext_path . 'config/default/container/';
+ $services_file = 'environment.yml';
+ }
+ else if (!is_dir($this->ext_path . 'config/default') && file_exists($this->ext_path . '/config/services.yml'))
+ {
+ $services_directory = $this->ext_path . 'config';
+ $services_file = 'services.yml';
+ }
+ }
+
+ if ($services_directory && $services_file)
+ {
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($services_directory)));
+ $loader->load($services_file);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration(array $config, ContainerBuilder $container)
+ {
+ $reflected = new \ReflectionClass($this);
+ $namespace = $reflected->getNamespaceName();
+
+ $class = $namespace . '\\di\configuration';
+ if (class_exists($class))
+ {
+ $r = new \ReflectionClass($class);
+ $container->addResource(new FileResource($r->getFileName()));
+
+ if (!method_exists($class, '__construct'))
+ {
+ $configuration = new $class();
+
+ return $configuration;
+ }
+ }
+
+ }
+
+ /**
+ * Returns the recommended alias to use in XML.
+ *
+ * This alias is also the mandatory prefix to use when using YAML.
+ *
+ * @return string The alias
+ */
+ public function getAlias()
+ {
+ return str_replace('/', '_', $this->extension_name);
+ }
+}
diff --git a/phpBB/phpbb/extension/exception.php b/phpBB/phpbb/extension/exception.php
index 3f7d251a4e..9050449bf1 100644
--- a/phpBB/phpbb/extension/exception.php
+++ b/phpBB/phpbb/extension/exception.php
@@ -16,10 +16,6 @@ namespace phpbb\extension;
/**
* Exception class for metadata
*/
-class exception extends \UnexpectedValueException
+class exception extends \phpbb\exception\runtime_exception
{
- public function __toString()
- {
- return $this->getMessage();
- }
}
diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php
index 76f0e3558e..98d2d27278 100644
--- a/phpBB/phpbb/extension/manager.php
+++ b/phpBB/phpbb/extension/manager.php
@@ -26,7 +26,6 @@ class manager
protected $db;
protected $config;
protected $cache;
- protected $user;
protected $php_ext;
protected $extensions;
protected $extension_table;
@@ -39,15 +38,14 @@ class manager
* @param ContainerInterface $container A container
* @param \phpbb\db\driver\driver_interface $db A database connection
* @param \phpbb\config\config $config Config object
- * @param \phpbb\filesystem $filesystem
- * @param \phpbb\user $user User object
+ * @param \phpbb\filesystem\filesystem_interface $filesystem
* @param string $extension_table The name of the table holding extensions
* @param string $phpbb_root_path Path to the phpbb includes directory.
* @param string $php_ext php file extension, defaults to php
* @param \phpbb\cache\driver\driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext
*/
- public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext')
+ public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext')
{
$this->cache = $cache;
$this->cache_name = $cache_name;
@@ -58,7 +56,6 @@ class manager
$this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
- $this->user = $user;
$this->extensions = ($this->cache) ? $this->cache->get($this->cache_name) : false;
@@ -154,7 +151,7 @@ class manager
*/
public function create_extension_metadata_manager($name, \phpbb\template\template $template)
{
- return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->user, $this->phpbb_root_path);
+ return new \phpbb\extension\metadata_manager($name, $this->config, $this, $template, $this->phpbb_root_path);
}
/**
@@ -464,15 +461,17 @@ class manager
* All enabled and disabled extensions are considered configured. A purged
* extension that is no longer in the database is not configured.
*
+ * @param bool $phpbb_relative Whether the path should be relative to phpbb root
+ *
* @return array An array with extension names as keys and and the
* database stored extension information as values
*/
- public function all_configured()
+ public function all_configured($phpbb_relative = true)
{
$configured = array();
foreach ($this->extensions as $name => $data)
{
- $data['ext_path'] = $this->phpbb_root_path . $data['ext_path'];
+ $data['ext_path'] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path'];
$configured[$name] = $data;
}
return $configured;
@@ -480,18 +479,19 @@ class manager
/**
* Retrieves all enabled extensions.
+ * @param bool $phpbb_relative Whether the path should be relative to phpbb root
*
* @return array An array with extension names as keys and and the
* database stored extension information as values
*/
- public function all_enabled()
+ public function all_enabled($phpbb_relative = true)
{
$enabled = array();
foreach ($this->extensions as $name => $data)
{
if ($data['ext_active'])
{
- $enabled[$name] = $this->phpbb_root_path . $data['ext_path'];
+ $enabled[$name] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path'];
}
}
return $enabled;
@@ -500,17 +500,19 @@ class manager
/**
* Retrieves all disabled extensions.
*
+ * @param bool $phpbb_relative Whether the path should be relative to phpbb root
+ *
* @return array An array with extension names as keys and and the
* database stored extension information as values
*/
- public function all_disabled()
+ public function all_disabled($phpbb_relative = true)
{
$disabled = array();
foreach ($this->extensions as $name => $data)
{
if (!$data['ext_active'])
{
- $disabled[$name] = $this->phpbb_root_path . $data['ext_path'];
+ $disabled[$name] = ($phpbb_relative ? $this->phpbb_root_path : '') . $data['ext_path'];
}
}
return $disabled;
diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php
index a64d88fe39..4f080647c8 100644
--- a/phpBB/phpbb/extension/metadata_manager.php
+++ b/phpBB/phpbb/extension/metadata_manager.php
@@ -37,12 +37,6 @@ class metadata_manager
protected $template;
/**
- * phpBB User instance
- * @var \phpbb\user
- */
- protected $user;
-
- /**
* phpBB root path
* @var string
*/
@@ -73,15 +67,13 @@ class metadata_manager
* @param \phpbb\config\config $config phpBB Config instance
* @param \phpbb\extension\manager $extension_manager An instance of the phpBB extension manager
* @param \phpbb\template\template $template phpBB Template instance
- * @param \phpbb\user $user User instance
* @param string $phpbb_root_path Path to the phpbb includes directory.
*/
- public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, \phpbb\template\template $template, \phpbb\user $user, $phpbb_root_path)
+ public function __construct($ext_name, \phpbb\config\config $config, \phpbb\extension\manager $extension_manager, \phpbb\template\template $template, $phpbb_root_path)
{
$this->config = $config;
$this->extension_manager = $extension_manager;
$this->template = $template;
- $this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
$this->ext_name = $ext_name;
@@ -149,7 +141,7 @@ class metadata_manager
if (!file_exists($this->metadata_file))
{
- throw new \phpbb\extension\exception($this->user->lang('FILE_NOT_FOUND', $this->metadata_file));
+ throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file));
}
}
@@ -163,18 +155,18 @@ class metadata_manager
{
if (!file_exists($this->metadata_file))
{
- throw new \phpbb\extension\exception($this->user->lang('FILE_NOT_FOUND', $this->metadata_file));
+ throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file));
}
else
{
if (!($file_contents = file_get_contents($this->metadata_file)))
{
- throw new \phpbb\extension\exception($this->user->lang('FILE_CONTENT_ERR', $this->metadata_file));
+ throw new \phpbb\extension\exception('FILE_CONTENT_ERR', array($this->metadata_file));
}
if (($metadata = json_decode($file_contents, true)) === null)
{
- throw new \phpbb\extension\exception($this->user->lang('FILE_JSON_DECODE_ERR', $this->metadata_file));
+ throw new \phpbb\extension\exception('FILE_JSON_DECODE_ERR', array($this->metadata_file));
}
array_walk_recursive($metadata, array($this, 'sanitize_json'));
@@ -246,12 +238,12 @@ class metadata_manager
{
if (!isset($this->metadata[$name]))
{
- throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', $name));
+ throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array($name));
}
if (!preg_match($fields[$name], $this->metadata[$name]))
{
- throw new \phpbb\extension\exception($this->user->lang('META_FIELD_INVALID', $name));
+ throw new \phpbb\extension\exception('META_FIELD_INVALID', array($name));
}
}
break;
@@ -270,14 +262,14 @@ class metadata_manager
{
if (empty($this->metadata['authors']))
{
- throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'authors'));
+ throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('authors'));
}
foreach ($this->metadata['authors'] as $author)
{
if (!isset($author['name']))
{
- throw new \phpbb\extension\exception($this->user->lang('META_FIELD_NOT_SET', 'author name'));
+ throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('author name'));
}
}
diff --git a/phpBB/phpbb/feed/attachments_base.php b/phpBB/phpbb/feed/attachments_base.php
index 04812f1570..b14dafe15a 100644
--- a/phpBB/phpbb/feed/attachments_base.php
+++ b/phpBB/phpbb/feed/attachments_base.php
@@ -16,7 +16,7 @@ namespace phpbb\feed;
/**
* Abstract class for feeds displaying attachments
*/
-abstract class attachments_base extends \phpbb\feed\base
+abstract class attachments_base extends base
{
/**
* Attachments that may be displayed
diff --git a/phpBB/phpbb/feed/base.php b/phpBB/phpbb/feed/base.php
index eeea0a55df..d4be0dc592 100644
--- a/phpBB/phpbb/feed/base.php
+++ b/phpBB/phpbb/feed/base.php
@@ -1,27 +1,27 @@
<?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.
-*
-*/
+ *
+ * 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;
/**
-* Base class with some generic functions and settings.
-*/
-abstract class base
+ * Base class with some generic functions and settings.
+ */
+abstract class base implements feed_interface
{
/**
- * Feed helper object
- * @var \phpbb\feed\helper
- */
+ * Feed helper object
+ * @var \phpbb\feed\helper
+ */
protected $helper;
/** @var \phpbb\config\config */
@@ -49,47 +49,47 @@ abstract class base
protected $phpEx;
/**
- * SQL Query to be executed to get feed items
- */
- var $sql = array();
+ * SQL Query to be executed to get feed items
+ */
+ protected $sql = array();
/**
- * Keys specified for retrieval of title, content, etc.
- */
- var $keys = array();
+ * Keys specified for retrieval of title, content, etc.
+ */
+ protected $keys = array();
/**
- * Number of items to fetch. Usually overwritten by $config['feed_something']
- */
- var $num_items = 15;
+ * Number of items to fetch. Usually overwritten by $config['feed_something']
+ */
+ protected $num_items = 15;
/**
- * Separator for title elements to separate items (for example forum / topic)
- */
- var $separator = "\xE2\x80\xA2"; // &bull;
+ * Separator for title elements to separate items (for example forum / topic)
+ */
+ protected $separator = "\xE2\x80\xA2"; // &bull;
/**
- * Separator for the statistics row (Posted by, post date, replies, etc.)
- */
- var $separator_stats = "\xE2\x80\x94"; // &mdash;
+ * Separator for the statistics row (Posted by, post date, replies, etc.)
+ */
+ protected $separator_stats = "\xE2\x80\x94"; // &mdash;
/** @var mixed Query result handle */
protected $result;
/**
- * Constructor
- *
- * @param \phpbb\feed\helper $helper Feed helper
- * @param \phpbb\config\config $config Config object
- * @param \phpbb\db\driver\driver_interface $db Database connection
- * @param \phpbb\cache\driver\driver_interface $cache Cache object
- * @param \phpbb\user $user User object
- * @param \phpbb\auth\auth $auth Auth object
- * @param \phpbb\content_visibility $content_visibility Content visibility object
- * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
- * @param string $phpEx php file extension
- */
- function __construct(
+ * Constructor
+ *
+ * @param \phpbb\feed\helper $helper Feed helper
+ * @param \phpbb\config\config $config Config object
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param \phpbb\cache\driver\driver_interface $cache Cache object
+ * @param \phpbb\user $user User object
+ * @param \phpbb\auth\auth $auth Auth object
+ * @param \phpbb\content_visibility $content_visibility Auth object
+ * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
+ * @param string $phpEx php file extension
+ */
+ public function __construct(
\phpbb\feed\helper $helper,
\phpbb\config\config $config,
\phpbb\db\driver\driver_interface $db,
@@ -127,23 +127,23 @@ abstract class base
}
/**
- * Set keys.
- */
- function set_keys()
+ * {@inheritdoc}
+ */
+ public function set_keys()
{
}
/**
- * Open feed
- */
- function open()
+ * {@inheritdoc}
+ */
+ public function open()
{
}
/**
- * Close feed
- */
- function close()
+ * {@inheritdoc}
+ */
+ public function close()
{
if (!empty($this->result))
{
@@ -152,28 +152,62 @@ abstract class base
}
/**
- * Set key
- *
- * @param string $key Key
- * @param mixed $value Value
- */
- function set($key, $value)
+ * {@inheritdoc}
+ */
+ public function set($key, $value)
{
$this->keys[$key] = $value;
}
/**
- * Get key
- *
- * @param string $key Key
- * @return mixed
- */
- function get($key)
+ * {@inheritdoc}
+ */
+ public function get($key)
{
return (isset($this->keys[$key])) ? $this->keys[$key] : null;
}
- function get_readable_forums()
+ /**
+ * {@inheritdoc}
+ */
+ public function get_item()
+ {
+ if (!isset($this->result))
+ {
+ if (!$this->get_sql())
+ {
+ return false;
+ }
+
+ $sql_ary = $this->sql;
+
+ /**
+ * Event to modify the feed item sql
+ *
+ * @event core.feed_base_modify_item_sql
+ * @var array sql_ary The SQL array to get the feed item data
+ *
+ * @since 3.1.10-RC1
+ */
+ $vars = array('sql_ary');
+ extract($this->phpbb_dispatcher->trigger_event('core.feed_base_modify_item_sql', compact($vars)));
+ $this->sql = $sql_ary;
+ unset($sql_ary);
+
+ // Query database
+ $sql = $this->db->sql_build_query('SELECT', $this->sql);
+ $this->result = $this->db->sql_query_limit($sql, $this->num_items);
+ }
+
+ return $this->db->sql_fetchrow($this->result);
+ }
+
+ /**
+ * Returns the ids of the forums readable by the current user.
+ *
+ * @return int[]
+ */
+ protected function get_readable_forums()
{
static $forum_ids;
@@ -185,7 +219,12 @@ abstract class base
return $forum_ids;
}
- function get_moderator_approve_forums()
+ /**
+ * Returns the ids of the forum for which the current user can approve the post in the moderation queue.
+ *
+ * @return int[]
+ */
+ protected function get_moderator_approve_forums()
{
static $forum_ids;
@@ -197,7 +236,13 @@ abstract class base
return $forum_ids;
}
- function is_moderator_approve_forum($forum_id)
+ /**
+ * Returns true if the current user can approve the post of the given forum
+ *
+ * @param int $forum_id Forum id to check
+ * @return bool
+ */
+ protected function is_moderator_approve_forum($forum_id)
{
static $forum_ids;
@@ -209,7 +254,12 @@ abstract class base
return (isset($forum_ids[$forum_id])) ? true : false;
}
- function get_excluded_forums()
+ /**
+ * Returns the ids of the forum excluded from the feeds
+ *
+ * @return int[]
+ */
+ protected function get_excluded_forums()
{
static $forum_ids;
@@ -236,51 +286,35 @@ abstract class base
return $forum_ids;
}
- function is_excluded_forum($forum_id)
+ /**
+ * Returns true if the given id is in the excluded forums list.
+ *
+ * @param int $forum_id Id to check
+ * @return bool
+ */
+ protected function is_excluded_forum($forum_id)
{
$forum_ids = $this->get_excluded_forums();
return isset($forum_ids[$forum_id]) ? true : false;
}
- function get_passworded_forums()
+ /**
+ * Returns all password protected forum ids the current user is currently NOT authenticated for.
+ *
+ * @return array Array of forum ids
+ */
+ protected function get_passworded_forums()
{
return $this->user->get_passworded_forums();
}
- function get_item()
- {
- if (!isset($this->result))
- {
- if (!$this->get_sql())
- {
- return false;
- }
-
- $sql_ary = $this->sql;
-
- /**
- * Event to modify the feed item sql
- *
- * @event core.feed_base_modify_item_sql
- * @var array sql_ary The SQL array to get the feed item data
- *
- * @since 3.1.10-RC1
- */
- $vars = array('sql_ary');
- extract($this->phpbb_dispatcher->trigger_event('core.feed_base_modify_item_sql', compact($vars)));
- $this->sql = $sql_ary;
- unset($sql_ary);
-
- // Query database
- $sql = $this->db->sql_build_query('SELECT', $this->sql);
- $this->result = $this->db->sql_query_limit($sql, $this->num_items);
- }
-
- return $this->db->sql_fetchrow($this->result);
- }
-
- function user_viewprofile($row)
+ /**
+ * Returns the link to the user profile.
+ *
+ * @return string
+ */
+ protected function user_viewprofile($row)
{
$author_id = (int) $row[$this->get('author_id')];
@@ -293,4 +327,11 @@ abstract class base
return '<a href="' . $this->helper->append_sid('memberlist.' . $this->phpEx, 'mode=viewprofile&amp;u=' . $author_id) . '">' . $row[$this->get('creator')] . '</a>';
}
+
+ /**
+ * Returns the SQL query used to retrieve the posts of the feed.
+ *
+ * @return string SQL SELECT query
+ */
+ protected abstract function get_sql();
}
diff --git a/phpBB/phpbb/feed/controller/feed.php b/phpBB/phpbb/feed/controller/feed.php
new file mode 100644
index 0000000000..c0d7bc72ec
--- /dev/null
+++ b/phpBB/phpbb/feed/controller/feed.php
@@ -0,0 +1,411 @@
+<?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\controller;
+
+use phpbb\auth\auth;
+use phpbb\config\config;
+use phpbb\db\driver\driver_interface;
+use \phpbb\event\dispatcher_interface;
+use phpbb\exception\http_exception;
+use phpbb\feed\feed_interface;
+use phpbb\feed\exception\feed_unavailable_exception;
+use phpbb\feed\exception\unauthorized_exception;
+use phpbb\feed\helper as feed_helper;
+use phpbb\controller\helper as controller_helper;
+use phpbb\symfony_request;
+use phpbb\user;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+
+class feed
+{
+ /**
+ * @var \Twig_Environment
+ */
+ protected $template;
+
+ /**
+ * @var symfony_request
+ */
+ protected $request;
+
+ /**
+ * @var controller_helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var config
+ */
+ protected $config;
+
+ /**
+ * @var driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * @var feed_helper
+ */
+ protected $feed_helper;
+
+ /**
+ * @var user
+ */
+ protected $user;
+
+ /**
+ * @var auth
+ */
+ protected $auth;
+
+ /**
+ * @var dispatcher_interface
+ */
+ protected $phpbb_dispatcher;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \Twig_Environment $twig
+ * @param symfony_request $request
+ * @param controller_helper $controller_helper
+ * @param config $config
+ * @param driver_interface $db
+ * @param ContainerInterface $container
+ * @param feed_helper $feed_helper
+ * @param user $user
+ * @param auth $auth
+ * @param dispatcher_interface $phpbb_dispatcher
+ * @param string $php_ext
+ */
+ public function __construct(\Twig_Environment $twig, symfony_request $request, controller_helper $controller_helper, config $config, driver_interface $db, ContainerInterface $container, feed_helper $feed_helper, user $user, auth $auth, dispatcher_interface $phpbb_dispatcher, $php_ext)
+ {
+ $this->request = $request;
+ $this->controller_helper = $controller_helper;
+ $this->config = $config;
+ $this->db = $db;
+ $this->container = $container;
+ $this->feed_helper = $feed_helper;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->php_ext = $php_ext;
+ $this->template = $twig;
+ $this->phpbb_dispatcher = $phpbb_dispatcher;
+ }
+
+ /**
+ * Controller for /feed/forums route
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function forums()
+ {
+ if (!$this->config['feed_overall_forums'])
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.forums'));
+ }
+
+ /**
+ * Controller for /feed/news route
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function news()
+ {
+ // Get at least one news forum
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $this->db->sql_query_limit($sql, 1, 0, 600);
+ $s_feed_news = (int) $this->db->sql_fetchfield('forum_id');
+ $this->db->sql_freeresult($result);
+
+ if (!$s_feed_news)
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.news'));
+ }
+
+ /**
+ * Controller for /feed/topics route
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function topics()
+ {
+ if (!$this->config['feed_topics_new'])
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.topics'));
+ }
+
+ /**
+ * Controller for /feed/topics_new route
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function topics_new()
+ {
+ return $this->topics();
+ }
+
+ /**
+ * Controller for /feed/topics_active route
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function topics_active()
+ {
+ if (!$this->config['feed_topics_active'])
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.topics_active'));
+ }
+
+ /**
+ * Controller for /feed/forum/{forum_id} route
+ *
+ * @param int $forum_id
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function forum($forum_id)
+ {
+ if (!$this->config['feed_forum'])
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.forum')->set_forum_id($forum_id));
+ }
+
+ /**
+ * Controller for /feed/topic/{topic_id} route
+ *
+ * @param int $topic_id
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function topic($topic_id)
+ {
+ if (!$this->config['feed_topic'])
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.topic')->set_topic_id($topic_id));
+ }
+
+ /**
+ * Controller for /feed/{mode] route
+ *
+ * @return Response
+ *
+ * @throws http_exception when the feed is disabled
+ */
+ public function overall()
+ {
+ if (!$this->config['feed_overall'])
+ {
+ $this->send_unavailable();
+ }
+
+ return $this->send_feed($this->container->get('feed.overall'));
+ }
+
+ /**
+ * Display a given feed
+ *
+ * @param feed_interface $feed
+ *
+ * @return Response
+ */
+ protected function send_feed(feed_interface $feed)
+ {
+ try
+ {
+ return $this->send_feed_do($feed);
+ }
+ catch (feed_unavailable_exception $e)
+ {
+ throw new http_exception(Response::HTTP_NOT_FOUND, $e->getMessage(), $e->get_parameters(), $e);
+ }
+ catch (unauthorized_exception $e)
+ {
+ throw new http_exception(Response::HTTP_FORBIDDEN, $e->getMessage(), $e->get_parameters(), $e);
+ }
+ }
+
+ /**
+ * Really send the feed
+ *
+ * @param feed_interface $feed
+ *
+ * @return Response
+ *
+ * @throw exception\feed_exception
+ */
+ protected function send_feed_do(feed_interface $feed)
+ {
+ $feed_updated_time = 0;
+ $item_vars = array();
+
+ $board_url = $this->feed_helper->get_board_url();
+
+ // Open Feed
+ $feed->open();
+
+ // Iterate through items
+ while ($row = $feed->get_item())
+ {
+ /**
+ * Event to modify the feed row
+ *
+ * @event core.feed_modify_feed_row
+ * @var int forum_id Forum ID
+ * @var string mode Feeds mode (forums|topics|topics_new|topics_active|news)
+ * @var array row Array with feed data
+ * @var int topic_id Topic ID
+ *
+ * @since 3.1.10-RC1
+ */
+ $vars = array('forum_id', 'mode', 'row', 'topic_id');
+ extract($this->phpbb_dispatcher->trigger_event('core.feed_modify_feed_row', compact($vars)));
+
+ // BBCode options to correctly disable urls, smilies, bbcode...
+ if ($feed->get('options') === null)
+ {
+ // Allow all combinations
+ $options = 7;
+
+ if ($feed->get('enable_bbcode') !== null && $feed->get('enable_smilies') !== null && $feed->get('enable_magic_url') !== null)
+ {
+ $options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0);
+ }
+ }
+ else
+ {
+ $options = $row[$feed->get('options')];
+ }
+
+ $title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : '');
+
+ $published = ($feed->get('published') !== null) ? (int) $row[$feed->get('published')] : 0;
+ $updated = ($feed->get('updated') !== null) ? (int) $row[$feed->get('updated')] : 0;
+
+ $display_attachments = ($this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment']) ? true : false;
+
+ $item_row = array(
+ 'author' => ($feed->get('creator') !== null) ? $row[$feed->get('creator')] : '',
+ 'published' => ($published > 0) ? $this->feed_helper->format_date($published) : '',
+ 'updated' => ($updated > 0) ? $this->feed_helper->format_date($updated) : '',
+ 'link' => '',
+ 'title' => censor_text($title),
+ 'category' => ($this->config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $this->php_ext . '?f=' . $row['forum_id'] : '',
+ 'category_name' => ($this->config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '',
+ 'description' => censor_text($this->feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], ($display_attachments ? $feed->get_attachments($row['post_id']) : array()))),
+ 'statistics' => '',
+ );
+
+ // Adjust items, fill link, etc.
+ $feed->adjust_item($item_row, $row);
+
+ $item_vars[] = $item_row;
+
+ $feed_updated_time = max($feed_updated_time, $published, $updated);
+ }
+
+ // If we do not have any items at all, sending the current time is better than sending no time.
+ if (!$feed_updated_time)
+ {
+ $feed_updated_time = time();
+ }
+
+ $feed->close();
+
+ $content = $this->template->render('feed.xml.twig', array(
+ // Some default assignments
+ // FEED_IMAGE is not used (atom)
+ 'FEED_IMAGE' => '',
+ 'SELF_LINK' => $this->controller_helper->route($this->request->attributes->get('_route'), $this->request->attributes->get('_route_params'), true, '', UrlGeneratorInterface::ABSOLUTE_URL),
+ 'FEED_LINK' => $board_url . '/index.' . $this->php_ext,
+ 'FEED_TITLE' => $this->config['sitename'],
+ 'FEED_SUBTITLE' => $this->config['site_desc'],
+ 'FEED_UPDATED' => $this->feed_helper->format_date($feed_updated_time),
+ 'FEED_LANG' => $this->user->lang['USER_LANG'],
+ 'FEED_AUTHOR' => $this->config['sitename'],
+
+ // Feed entries
+ 'FEED_ROWS' => $item_vars,
+ ));
+
+ $response = new Response($content);
+ $response->headers->set('Content-Type', 'application/atom+xml');
+ $response->setCharset('UTF-8');
+ $response->setLastModified(new \DateTime('@' . $feed_updated_time));
+
+ if (!empty($this->user->data['is_bot']))
+ {
+ // Let reverse proxies know we detected a bot.
+ $response->headers->set('X-PHPBB-IS-BOT', 'yes');
+ }
+
+ return $response;
+ }
+
+ /**
+ * Throw and exception saying that the feed isn't available
+ *
+ * @throw http_exception
+ */
+ protected function send_unavailable()
+ {
+ throw new http_exception(404, 'FEATURE_NOT_AVAILABLE');
+ }
+}
diff --git a/phpBB/phpbb/feed/exception/feed_exception.php b/phpBB/phpbb/feed/exception/feed_exception.php
new file mode 100644
index 0000000000..c9c888211e
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/feed_exception.php
@@ -0,0 +1,21 @@
+<?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\exception;
+
+use phpbb\exception\runtime_exception;
+
+abstract class feed_exception extends runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/feed/exception/feed_unavailable_exception.php b/phpBB/phpbb/feed/exception/feed_unavailable_exception.php
new file mode 100644
index 0000000000..4b6605b47d
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/feed_unavailable_exception.php
@@ -0,0 +1,19 @@
+<?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\exception;
+
+abstract class feed_unavailable_exception extends feed_exception
+{
+
+}
diff --git a/phpBB/phpbb/feed/exception/no_feed_exception.php b/phpBB/phpbb/feed/exception/no_feed_exception.php
new file mode 100644
index 0000000000..af6357b74c
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/no_feed_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+class no_feed_exception extends feed_unavailable_exception
+{
+ public function __construct(\Exception $previous = null, $code = 0)
+ {
+ parent::__construct('NO_FEED', array(), $previous, $code);
+ }
+}
diff --git a/phpBB/phpbb/feed/exception/no_forum_exception.php b/phpBB/phpbb/feed/exception/no_forum_exception.php
new file mode 100644
index 0000000000..a60832957a
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/no_forum_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+class no_forum_exception extends feed_unavailable_exception
+{
+ public function __construct($forum_id, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct('NO_FORUM', array($forum_id), $previous, $code);
+ }
+}
diff --git a/phpBB/phpbb/feed/exception/no_topic_exception.php b/phpBB/phpbb/feed/exception/no_topic_exception.php
new file mode 100644
index 0000000000..b961a65d1c
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/no_topic_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+class no_topic_exception extends feed_unavailable_exception
+{
+ public function __construct($topic_id, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct('NO_TOPIC', array($topic_id), $previous, $code);
+ }
+}
diff --git a/phpBB/phpbb/feed/exception/unauthorized_exception.php b/phpBB/phpbb/feed/exception/unauthorized_exception.php
new file mode 100644
index 0000000000..7868975779
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/unauthorized_exception.php
@@ -0,0 +1,19 @@
+<?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\exception;
+
+abstract class unauthorized_exception extends feed_exception
+{
+
+}
diff --git a/phpBB/phpbb/feed/exception/unauthorized_forum_exception.php b/phpBB/phpbb/feed/exception/unauthorized_forum_exception.php
new file mode 100644
index 0000000000..4384c7b39b
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/unauthorized_forum_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+class unauthorized_forum_exception extends unauthorized_exception
+{
+ public function __construct($forum_id, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct('SORRY_AUTH_READ', array($forum_id), $previous, $code);
+ }
+}
diff --git a/phpBB/phpbb/feed/exception/unauthorized_topic_exception.php b/phpBB/phpbb/feed/exception/unauthorized_topic_exception.php
new file mode 100644
index 0000000000..f49f0a0476
--- /dev/null
+++ b/phpBB/phpbb/feed/exception/unauthorized_topic_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+class unauthorized_topic_exception extends unauthorized_exception
+{
+ public function __construct($topic_id, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct('SORRY_AUTH_READ_TOPIC', array($topic_id), $previous, $code);
+ }
+}
diff --git a/phpBB/phpbb/feed/factory.php b/phpBB/phpbb/feed/factory.php
deleted file mode 100644
index f364f06d03..0000000000
--- a/phpBB/phpbb/feed/factory.php
+++ /dev/null
@@ -1,127 +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\feed;
-
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
-* Factory class to return correct object
-*/
-class factory
-{
- /**
- * Service container object
- * @var ContainerInterface
- */
- protected $container;
-
- /** @var \phpbb\config\config */
- protected $config;
-
- /** @var \phpbb\db\driver\driver_interface */
- protected $db;
-
- /**
- * Constructor
- *
- * @param ContainerInterface $container Container object
- * @param \phpbb\config\config $config Config object
- * @param \phpbb\db\driver\driver_interface $db Database connection
- */
- public function __construct(ContainerInterface $container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db)
- {
- $this->container = $container;
- $this->config = $config;
- $this->db = $db;
- }
-
- /**
- * Return correct object for specified mode
- *
- * @param string $mode The feeds mode.
- * @param int $forum_id Forum id specified by the script if forum feed provided.
- * @param int $topic_id Topic id specified by the script if topic feed provided.
- *
- * @return object Returns correct feeds object for specified mode.
- */
- function get_feed($mode, $forum_id, $topic_id)
- {
- switch ($mode)
- {
- case 'forums':
- if (!$this->config['feed_overall_forums'])
- {
- return false;
- }
-
- return $this->container->get('feed.forums');
- break;
-
- case 'topics':
- case 'topics_new':
- if (!$this->config['feed_topics_new'])
- {
- return false;
- }
-
- return $this->container->get('feed.topics');
- break;
-
- case 'topics_active':
- if (!$this->config['feed_topics_active'])
- {
- return false;
- }
-
- return $this->container->get('feed.topics_active');
- break;
-
- case 'news':
- // Get at least one news forum
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TABLE . '
- WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
- $result = $this->db->sql_query_limit($sql, 1, 0, 600);
- $s_feed_news = (int) $this->db->sql_fetchfield('forum_id');
- $this->db->sql_freeresult($result);
-
- if (!$s_feed_news)
- {
- return false;
- }
-
- return $this->container->get('feed.news');
- break;
-
- default:
- if ($topic_id && $this->config['feed_topic'])
- {
- return $this->container->get('feed.topic')
- ->set_topic_id($topic_id);
- }
- else if ($forum_id && $this->config['feed_forum'])
- {
- return $this->container->get('feed.forum')
- ->set_forum_id($forum_id);
- }
- else if ($this->config['feed_overall'])
- {
- return $this->container->get('feed.overall');
- }
-
- return false;
- break;
- }
- }
-}
diff --git a/phpBB/phpbb/feed/feed_interface.php b/phpBB/phpbb/feed/feed_interface.php
new file mode 100644
index 0000000000..c185cd249c
--- /dev/null
+++ b/phpBB/phpbb/feed/feed_interface.php
@@ -0,0 +1,67 @@
+<?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;
+
+/**
+ * Interface implemented by all feeds types
+ */
+interface feed_interface
+{
+ /**
+ * Set keys.
+ */
+ public function set_keys();
+
+ /**
+ * Open feed
+ */
+ public function open();
+
+ /**
+ * Close feed
+ */
+ public function close();
+
+ /**
+ * Set key
+ *
+ * @param string $key Key
+ * @param mixed $value Value
+ */
+ public function set($key, $value);
+
+ /**
+ * Get key
+ *
+ * @param string $key Key
+ * @return mixed
+ */
+ public function get($key);
+
+ /**
+ * Get the next post in the feed
+ *
+ * @return array
+ */
+ public function get_item();
+
+ /**
+ * Adjust a feed entry
+ *
+ * @param $item_row
+ * @param $row
+ * @return array
+ */
+ public function adjust_item(&$item_row, &$row);
+}
diff --git a/phpBB/phpbb/feed/forum.php b/phpBB/phpbb/feed/forum.php
index 7a2087c1cd..f522e91169 100644
--- a/phpBB/phpbb/feed/forum.php
+++ b/phpBB/phpbb/feed/forum.php
@@ -1,35 +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.
-*
-*/
+ *
+ * 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;
+use phpbb\feed\exception\no_feed_exception;
+use phpbb\feed\exception\no_forum_exception;
+use phpbb\feed\exception\unauthorized_forum_exception;
+
/**
-* Forum feed
-*
-* This will give you the last {$this->num_items} posts made
-* within a specific forum.
-*/
-class forum extends \phpbb\feed\post_base
+ * Forum feed
+ *
+ * This will give you the last {$this->num_items} posts made
+ * within a specific forum.
+ */
+class forum extends post_base
{
- var $forum_id = 0;
- var $forum_data = array();
+ protected $forum_id = 0;
+ protected $forum_data = array();
/**
- * Set the Forum ID
- *
- * @param int $forum_id Forum ID
- * @return \phpbb\feed\forum
- */
+ * Set the Forum ID
+ *
+ * @param int $forum_id Forum ID
+ * @return \phpbb\feed\forum
+ */
public function set_forum_id($forum_id)
{
$this->forum_id = (int) $forum_id;
@@ -37,7 +41,10 @@ class forum extends \phpbb\feed\post_base
return $this;
}
- function open()
+ /**
+ * {@inheritdoc}
+ */
+ public function open()
{
// Check if forum exists
$sql = 'SELECT forum_id, forum_name, forum_password, forum_type, forum_options
@@ -49,25 +56,33 @@ class forum extends \phpbb\feed\post_base
if (empty($this->forum_data))
{
- trigger_error('NO_FORUM');
+ throw new no_forum_exception($this->forum_id);
}
// Forum needs to be postable
if ($this->forum_data['forum_type'] != FORUM_POST)
{
- trigger_error('NO_FEED');
+ throw new no_feed_exception();
}
// Make sure forum is not excluded from feed
if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->forum_data['forum_options']))
{
- trigger_error('NO_FEED');
+ throw new no_feed_exception();
}
// Make sure we can read this forum
if (!$this->auth->acl_get('f_read', $this->forum_id))
{
- trigger_error('SORRY_AUTH_READ');
+ if ($this->user->data['user_id'] != ANONYMOUS)
+ {
+ send_status_line(403, 'Forbidden');
+ }
+ else
+ {
+ send_status_line(401, 'Unauthorized');
+ }
+ throw new unauthorized_forum_exception($this->forum_id);
}
// Make sure forum is not passworded or user is authed
@@ -77,7 +92,15 @@ class forum extends \phpbb\feed\post_base
if (isset($forum_ids_passworded[$this->forum_id]))
{
- trigger_error('SORRY_AUTH_READ');
+ if ($this->user->data['user_id'] != ANONYMOUS)
+ {
+ send_status_line(403, 'Forbidden');
+ }
+ else
+ {
+ send_status_line(401, 'Unauthorized');
+ }
+ throw new unauthorized_forum_exception($this->forum_id);
}
unset($forum_ids_passworded);
@@ -86,7 +109,10 @@ class forum extends \phpbb\feed\post_base
parent::open();
}
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_sql()
{
// Determine topics with recent activity
$sql = 'SELECT topic_id, topic_last_post_time
@@ -114,7 +140,7 @@ class forum extends \phpbb\feed\post_base
$this->sql = array(
'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
- 'u.username, u.user_id',
+ 'u.username, u.user_id',
'FROM' => array(
POSTS_TABLE => 'p',
USERS_TABLE => 'u',
@@ -129,7 +155,10 @@ class forum extends \phpbb\feed\post_base
return true;
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
parent::adjust_item($item_row, $row);
@@ -137,7 +166,10 @@ class forum extends \phpbb\feed\post_base
$item_row['forum_id'] = $this->forum_id;
}
- function get_item()
+ /**
+ * {@inheritdoc}
+ */
+ public function get_item()
{
return ($row = parent::get_item()) ? array_merge($this->forum_data, $row) : $row;
}
diff --git a/phpBB/phpbb/feed/forums.php b/phpBB/phpbb/feed/forums.php
index ee14a5bc76..92f2b2dd4d 100644
--- a/phpBB/phpbb/feed/forums.php
+++ b/phpBB/phpbb/feed/forums.php
@@ -1,29 +1,32 @@
<?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.
-*
-*/
+ *
+ * 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;
/**
-* 'All Forums' feed
-*
-* This will give you a list of all postable forums where feeds are enabled
-* including forum description, topic stats and post stats
-*/
-class forums extends \phpbb\feed\base
+ * 'All Forums' feed
+ *
+ * This will give you a list of all postable forums where feeds are enabled
+ * including forum description, topic stats and post stats
+ */
+class forums extends base
{
- var $num_items = 0;
+ protected $num_items = 0;
- function set_keys()
+ /**
+ * {@inheritdoc}
+ */
+ public function set_keys()
{
$this->set('title', 'forum_name');
$this->set('text', 'forum_desc');
@@ -33,7 +36,10 @@ class forums extends \phpbb\feed\base
$this->set('options', 'forum_desc_options');
}
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ public function get_sql()
{
$in_fid_ary = array_diff($this->get_readable_forums(), $this->get_excluded_forums());
if (empty($in_fid_ary))
@@ -55,7 +61,10 @@ class forums extends \phpbb\feed\base
return true;
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
$item_row['link'] = $this->helper->append_sid('viewforum.' . $this->phpEx, 'f=' . $row['forum_id']);
diff --git a/phpBB/phpbb/feed/helper.php b/phpBB/phpbb/feed/helper.php
index f2030f5ced..e15d1e131e 100644
--- a/phpBB/phpbb/feed/helper.php
+++ b/phpBB/phpbb/feed/helper.php
@@ -1,21 +1,21 @@
<?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.
-*
-*/
+ *
+ * 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;
/**
-* Class with some helpful functions used in feeds
-*/
+ * Class with some helpful functions used in feeds
+ */
class helper
{
/** @var \phpbb\config\config */
@@ -31,13 +31,13 @@ class helper
protected $phpEx;
/**
- * 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
- */
+ * 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
+ */
public function __construct(\phpbb\config\config $config, \phpbb\user $user, $phpbb_root_path, $phpEx)
{
$this->config = $config;
@@ -47,8 +47,8 @@ class helper
}
/**
- * Run links through append_sid(), prepend generate_board_url() and remove session id
- */
+ * Run links through append_sid(), prepend generate_board_url() and remove session id
+ */
public function get_board_url()
{
static $board_url;
@@ -62,16 +62,16 @@ class helper
}
/**
- * Run links through append_sid(), prepend generate_board_url() and remove session id
- */
+ * Run links through append_sid(), prepend generate_board_url() and remove session id
+ */
public function append_sid($url, $params)
{
return append_sid($this->get_board_url() . '/' . $url, $params, true, '');
}
/**
- * Generate ISO 8601 date string (RFC 3339)
- */
+ * Generate ISO 8601 date string (RFC 3339)
+ */
public function format_date($time)
{
static $zone_offset;
@@ -87,16 +87,16 @@ class helper
}
/**
- * Generate text content
- *
- * @param string $content is feed text content
- * @param string $uid is bbcode_uid
- * @param string $bitfield is bbcode bitfield
- * @param int $options bbcode flag options
- * @param int $forum_id is the forum id
- * @param array $post_attachments is an array containing the attachments and their respective info
- * @return string the html content to be printed for the feed
- */
+ * Generate text content
+ *
+ * @param string $content is feed text content
+ * @param string $uid is bbcode_uid
+ * @param string $bitfield is bbcode bitfield
+ * @param int $options bbcode flag options
+ * @param int $forum_id is the forum id
+ * @param array $post_attachments is an array containing the attachments and their respective info
+ * @return string the html content to be printed for the feed
+ */
public function generate_content($content, $uid, $bitfield, $options, $forum_id, $post_attachments)
{
if (empty($content))
@@ -122,16 +122,16 @@ class helper
// Firefox does not support CSS for feeds, though
// Remove font sizes
- // $content = preg_replace('#<span style="font-size: [0-9]+%; line-height: [0-9]+%;">([^>]+)</span>#iU', '\1', $content);
+ // $content = preg_replace('#<span style="font-size: [0-9]+%; line-height: [0-9]+%;">([^>]+)</span>#iU', '\1', $content);
// Make text strong :P
- // $content = preg_replace('#<span style="font-weight: bold?">(.*?)</span>#iU', '<strong>\1</strong>', $content);
+ // $content = preg_replace('#<span style="font-weight: bold?">(.*?)</span>#iU', '<strong>\1</strong>', $content);
// Italic
- // $content = preg_replace('#<span style="font-style: italic?">([^<]+)</span>#iU', '<em>\1</em>', $content);
+ // $content = preg_replace('#<span style="font-style: italic?">([^<]+)</span>#iU', '<em>\1</em>', $content);
// Underline
- // $content = preg_replace('#<span style="text-decoration: underline?">([^<]+)</span>#iU', '<u>\1</u>', $content);
+ // $content = preg_replace('#<span style="text-decoration: underline?">([^<]+)</span>#iU', '<u>\1</u>', $content);
// Remove embed Windows Media Streams
$content = preg_replace( '#<\!--\[if \!IE\]>-->([^[]+)<\!--<!\[endif\]-->#si', '', $content);
diff --git a/phpBB/phpbb/feed/news.php b/phpBB/phpbb/feed/news.php
index a02c199d85..fb6fa09278 100644
--- a/phpBB/phpbb/feed/news.php
+++ b/phpBB/phpbb/feed/news.php
@@ -1,27 +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.
-*
-*/
+ *
+ * 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;
/**
-* News feed
-*
-* This will give you {$this->num_items} first posts
-* of all topics in the selected news forums.
-*/
-class news extends \phpbb\feed\topic_base
+ * News feed
+ *
+ * This will give you {$this->num_items} first posts
+ * of all topics in the selected news forums.
+ */
+class news extends topic_base
{
- function get_news_forums()
+ /**
+ * Returns the ids of the 'news forums'
+ * @return int[]
+ */
+ private function get_news_forums()
{
static $forum_ids;
@@ -48,7 +52,10 @@ class news extends \phpbb\feed\topic_base
return $forum_ids;
}
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_sql()
{
// Determine forum ids
$in_fid_ary = array_intersect($this->get_news_forums(), $this->get_readable_forums());
diff --git a/phpBB/phpbb/feed/overall.php b/phpBB/phpbb/feed/overall.php
index ab452f5386..40cf94ace0 100644
--- a/phpBB/phpbb/feed/overall.php
+++ b/phpBB/phpbb/feed/overall.php
@@ -1,27 +1,30 @@
<?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.
-*
-*/
+ *
+ * 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;
/**
-* Board wide feed (aka overall feed)
-*
-* This will give you the newest {$this->num_items} posts
-* from the whole board.
-*/
-class overall extends \phpbb\feed\post_base
+ * Board wide feed (aka overall feed)
+ *
+ * This will give you the newest {$this->num_items} posts
+ * from the whole board.
+ */
+class overall extends post_base
{
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_sql()
{
$forum_ids = array_diff($this->get_readable_forums(), $this->get_excluded_forums(), $this->get_passworded_forums());
if (empty($forum_ids))
@@ -55,8 +58,8 @@ class overall extends \phpbb\feed\post_base
// Get the actual data
$this->sql = array(
'SELECT' => 'f.forum_id, f.forum_name, ' .
- 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
- 'u.username, u.user_id',
+ 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
+ 'u.username, u.user_id',
'FROM' => array(
USERS_TABLE => 'u',
POSTS_TABLE => 'p',
@@ -77,7 +80,10 @@ class overall extends \phpbb\feed\post_base
return true;
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
parent::adjust_item($item_row, $row);
diff --git a/phpBB/phpbb/feed/post_base.php b/phpBB/phpbb/feed/post_base.php
index 011775b6af..f6dc39cbec 100644
--- a/phpBB/phpbb/feed/post_base.php
+++ b/phpBB/phpbb/feed/post_base.php
@@ -1,27 +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.
-*
-*/
+ *
+ * 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;
/**
-* Abstract class for post based feeds
-*/
-abstract class post_base extends \phpbb\feed\attachments_base
+ * Abstract class for post based feeds
+ */
+abstract class post_base extends attachments_base
{
- var $num_items = 'feed_limit_post';
- var $attachments = array();
+ protected $num_items = 'feed_limit_post';
- function set_keys()
+ /**
+ * {@inheritdoc}
+ */
+ public function set_keys()
{
$this->set('title', 'post_subject');
$this->set('title2', 'topic_title');
@@ -40,7 +42,10 @@ abstract class post_base extends \phpbb\feed\attachments_base
$this->set('enable_magic_url', 'enable_magic_url');
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
$item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, "t={$row['topic_id']}&amp;p={$row['post_id']}#p{$row['post_id']}");
diff --git a/phpBB/phpbb/feed/topic.php b/phpBB/phpbb/feed/topic.php
index 66c49e55cf..e5f2c41468 100644
--- a/phpBB/phpbb/feed/topic.php
+++ b/phpBB/phpbb/feed/topic.php
@@ -1,35 +1,40 @@
<?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.
-*
-*/
+ *
+ * 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;
+use phpbb\feed\exception\no_feed_exception;
+use phpbb\feed\exception\no_topic_exception;
+use phpbb\feed\exception\unauthorized_forum_exception;
+use phpbb\feed\exception\unauthorized_topic_exception;
+
/**
-* Topic feed for a specific topic
-*
-* This will give you the last {$this->num_items} posts made within this topic.
-*/
-class topic extends \phpbb\feed\post_base
+ * Topic feed for a specific topic
+ *
+ * This will give you the last {$this->num_items} posts made within this topic.
+ */
+class topic extends post_base
{
- var $topic_id = 0;
- var $forum_id = 0;
- var $topic_data = array();
+ protected $topic_id = 0;
+ protected $forum_id = 0;
+ protected $topic_data = array();
/**
- * Set the Topic ID
- *
- * @param int $topic_id Topic ID
- * @return \phpbb\feed\topic
- */
+ * Set the Topic ID
+ *
+ * @param int $topic_id Topic ID
+ * @return \phpbb\feed\topic
+ */
public function set_topic_id($topic_id)
{
$this->topic_id = (int) $topic_id;
@@ -37,7 +42,10 @@ class topic extends \phpbb\feed\post_base
return $this;
}
- function open()
+ /**
+ * {@inheritdoc}
+ */
+ public function open()
{
$sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_visibility, t.topic_title, t.topic_time, t.topic_views, t.topic_posts_approved, t.topic_type
FROM ' . TOPICS_TABLE . ' t
@@ -50,7 +58,7 @@ class topic extends \phpbb\feed\post_base
if (empty($this->topic_data))
{
- trigger_error('NO_TOPIC');
+ throw new no_topic_exception($this->topic_id);
}
$this->forum_id = (int) $this->topic_data['forum_id'];
@@ -58,19 +66,35 @@ class topic extends \phpbb\feed\post_base
// Make sure topic is either approved or user authed
if ($this->topic_data['topic_visibility'] != ITEM_APPROVED && !$this->auth->acl_get('m_approve', $this->forum_id))
{
- trigger_error('SORRY_AUTH_READ');
+ if ($this->user->data['user_id'] != ANONYMOUS)
+ {
+ send_status_line(403, 'Forbidden');
+ }
+ else
+ {
+ send_status_line(401, 'Unauthorized');
+ }
+ throw new unauthorized_topic_exception($this->topic_id);
}
// Make sure forum is not excluded from feed
if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->topic_data['forum_options']))
{
- trigger_error('NO_FEED');
+ throw new no_feed_exception();
}
// Make sure we can read this forum
if (!$this->auth->acl_get('f_read', $this->forum_id))
{
- trigger_error('SORRY_AUTH_READ');
+ if ($this->user->data['user_id'] != ANONYMOUS)
+ {
+ send_status_line(403, 'Forbidden');
+ }
+ else
+ {
+ send_status_line(401, 'Unauthorized');
+ }
+ throw new unauthorized_forum_exception($this->forum_id);
}
// Make sure forum is not passworded or user is authed
@@ -80,7 +104,15 @@ class topic extends \phpbb\feed\post_base
if (isset($forum_ids_passworded[$this->forum_id]))
{
- trigger_error('SORRY_AUTH_READ');
+ if ($this->user->data['user_id'] != ANONYMOUS)
+ {
+ send_status_line(403, 'Forbidden');
+ }
+ else
+ {
+ send_status_line(401, 'Unauthorized');
+ }
+ throw new unauthorized_forum_exception($this->forum_id);
}
unset($forum_ids_passworded);
@@ -89,11 +121,14 @@ class topic extends \phpbb\feed\post_base
parent::open();
}
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_sql()
{
$this->sql = array(
'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.post_attachment, ' .
- 'u.username, u.user_id',
+ 'u.username, u.user_id',
'FROM' => array(
POSTS_TABLE => 'p',
USERS_TABLE => 'u',
@@ -107,14 +142,20 @@ class topic extends \phpbb\feed\post_base
return true;
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
parent::adjust_item($item_row, $row);
$item_row['forum_id'] = $this->forum_id;
}
- function get_item()
+ /**
+ * {@inheritdoc}
+ */
+ public function get_item()
{
return ($row = parent::get_item()) ? array_merge($this->topic_data, $row) : $row;
}
diff --git a/phpBB/phpbb/feed/topic_base.php b/phpBB/phpbb/feed/topic_base.php
index f9ff368cba..0f1a9ccb70 100644
--- a/phpBB/phpbb/feed/topic_base.php
+++ b/phpBB/phpbb/feed/topic_base.php
@@ -1,26 +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.
-*
-*/
+ *
+ * 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;
/**
-* Abstract class for topic based feeds
-*/
-abstract class topic_base extends \phpbb\feed\attachments_base
+ * Abstract class for topic based feeds
+ */
+abstract class topic_base extends attachments_base
{
- var $num_items = 'feed_limit_topic';
+ protected $num_items = 'feed_limit_topic';
- function set_keys()
+ /**
+ * {@inheritdoc}
+ */
+ public function set_keys()
{
$this->set('title', 'topic_title');
$this->set('title2', 'forum_name');
@@ -39,7 +42,10 @@ abstract class topic_base extends \phpbb\feed\attachments_base
$this->set('enable_magic_url', 'enable_magic_url');
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
$item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, 't=' . $row['topic_id'] . '&amp;p=' . $row['post_id'] . '#p' . $row['post_id']);
diff --git a/phpBB/phpbb/feed/topics.php b/phpBB/phpbb/feed/topics.php
index 2b9cb3501a..cf4a2e579e 100644
--- a/phpBB/phpbb/feed/topics.php
+++ b/phpBB/phpbb/feed/topics.php
@@ -1,27 +1,30 @@
<?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.
-*
-*/
+ *
+ * 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;
/**
-* New Topics feed
-*
-* This will give you the last {$this->num_items} created topics
-* including the first post.
-*/
-class topics extends \phpbb\feed\topic_base
+ * New Topics feed
+ *
+ * This will give you the last {$this->num_items} created topics
+ * including the first post.
+ */
+class topics extends topic_base
{
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_sql()
{
$forum_ids_read = $this->get_readable_forums();
if (empty($forum_ids_read))
@@ -77,7 +80,10 @@ class topics extends \phpbb\feed\topic_base
return true;
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
parent::adjust_item($item_row, $row);
diff --git a/phpBB/phpbb/feed/topics_active.php b/phpBB/phpbb/feed/topics_active.php
index 6d5eddfc16..52340dc2d5 100644
--- a/phpBB/phpbb/feed/topics_active.php
+++ b/phpBB/phpbb/feed/topics_active.php
@@ -1,30 +1,33 @@
<?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.
-*
-*/
+ *
+ * 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;
/**
-* Active Topics feed
-*
-* This will give you the last {$this->num_items} topics
-* with replies made withing the last {$this->sort_days} days
-* including the last post.
-*/
-class topics_active extends \phpbb\feed\topic_base
+ * Active Topics feed
+ *
+ * This will give you the last {$this->num_items} topics
+ * with replies made withing the last {$this->sort_days} days
+ * including the last post.
+ */
+class topics_active extends topic_base
{
- var $sort_days = 7;
+ protected $sort_days = 7;
- function set_keys()
+ /**
+ * {@inheritdoc}
+ */
+ public function set_keys()
{
parent::set_keys();
@@ -32,7 +35,10 @@ class topics_active extends \phpbb\feed\topic_base
$this->set('creator', 'topic_last_poster_name');
}
- function get_sql()
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_sql()
{
$forum_ids_read = $this->get_readable_forums();
if (empty($forum_ids_read))
@@ -94,7 +100,12 @@ class topics_active extends \phpbb\feed\topic_base
return true;
}
- function get_forum_ids()
+ /**
+ * Returns the ids of the forums not excluded from the active list
+ *
+ * @return int[]
+ */
+ private function get_forum_ids()
{
static $forum_ids;
@@ -122,7 +133,10 @@ class topics_active extends \phpbb\feed\topic_base
return $forum_ids;
}
- function adjust_item(&$item_row, &$row)
+ /**
+ * {@inheritdoc}
+ */
+ public function adjust_item(&$item_row, &$row)
{
parent::adjust_item($item_row, $row);
diff --git a/phpBB/phpbb/files/factory.php b/phpBB/phpbb/files/factory.php
new file mode 100644
index 0000000000..84b7cc9449
--- /dev/null
+++ b/phpBB/phpbb/files/factory.php
@@ -0,0 +1,58 @@
+<?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\files;
+
+class factory
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ private $container;
+
+ /**
+ * Constructor
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+ */
+ public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * Get files service
+ *
+ * @param string $name Service name
+ *
+ * @return object|bool Requested service or false if service could not be
+ * found by the container
+ */
+ public function get($name)
+ {
+ $service = false;
+
+ $name = (strpos($name, '.') === false) ? 'files.' . $name : $name;
+
+ try
+ {
+ $service = $this->container->get($name);
+ }
+ catch (\Exception $e)
+ {
+ // do nothing
+ }
+
+ return $service;
+ }
+}
diff --git a/phpBB/phpbb/files/filespec.php b/phpBB/phpbb/files/filespec.php
new file mode 100644
index 0000000000..2ff2a92c83
--- /dev/null
+++ b/phpBB/phpbb/files/filespec.php
@@ -0,0 +1,584 @@
+<?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\files;
+
+use phpbb\language\language;
+
+/**
+ * Responsible for holding all file relevant information, as well as doing file-specific operations.
+ * The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
+ */
+class filespec
+{
+ /** @var string File name */
+ protected $filename = '';
+
+ /** @var string Real name of file */
+ protected $realname = '';
+
+ /** @var string Upload name of file */
+ protected $uploadname = '';
+
+ /** @var string Mimetype of file */
+ protected $mimetype = '';
+
+ /** @var string File extension */
+ protected $extension = '';
+
+ /** @var int File size */
+ protected $filesize = 0;
+
+ /** @var int Width of file */
+ protected $width = 0;
+
+ /** @var int Height of file */
+ protected $height = 0;
+
+ /** @var array Image info including type and size */
+ protected $image_info = array();
+
+ /** @var string Destination file name */
+ protected $destination_file = '';
+
+ /** @var string Destination file path */
+ protected $destination_path = '';
+
+ /** @var bool Whether file was moved */
+ protected $file_moved = false;
+
+ /** @var bool Whether file is local */
+ protected $local = false;
+
+ /** @var bool Class initialization flag */
+ protected $class_initialized = false;
+
+ /** @var array Error array */
+ public $error = array();
+
+ /** @var upload Instance of upload class */
+ public $upload;
+
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper class */
+ protected $php_ini;
+
+ /** @var \FastImageSize\FastImageSize */
+ protected $imagesize;
+
+ /** @var language Language class */
+ protected $language;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ /** @var \phpbb\plupload\plupload The plupload object */
+ protected $plupload;
+
+ /** @var \phpbb\mimetype\guesser phpBB Mimetype guesser */
+ protected $mimetype_guesser;
+
+ /**
+ * File upload class
+ *
+ * @param \phpbb\filesystem\filesystem_interface $phpbb_filesystem Filesystem
+ * @param language $language Language
+ * @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper
+ * @param \FastImageSize\FastImageSize $imagesize Imagesize class
+ * @param string $phpbb_root_path phpBB root path
+ * @param \phpbb\mimetype\guesser $mimetype_guesser Mime type guesser
+ * @param \phpbb\plupload\plupload $plupload Plupload
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $phpbb_filesystem, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \FastImageSize\FastImageSize $imagesize, $phpbb_root_path, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
+ {
+ $this->filesystem = $phpbb_filesystem;
+ $this->language = $language;
+ $this->php_ini = $php_ini;
+ $this->imagesize = $imagesize;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->plupload = $plupload;
+ $this->mimetype_guesser = $mimetype_guesser;
+ }
+
+ /**
+ * Set upload ary
+ *
+ * @param array $upload_ary Upload ary
+ *
+ * @return filespec This instance of the filespec class
+ */
+ public function set_upload_ary($upload_ary)
+ {
+ if (!isset($upload_ary) || !sizeof($upload_ary))
+ {
+ return $this;
+ }
+
+ $this->class_initialized = true;
+ $this->filename = $upload_ary['tmp_name'];
+ $this->filesize = $upload_ary['size'];
+ $name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name'];
+ $name = trim(utf8_basename($name));
+ $this->realname = $this->uploadname = $name;
+ $this->mimetype = $upload_ary['type'];
+
+ // Opera adds the name to the mime type
+ $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype;
+
+ if (!$this->mimetype)
+ {
+ $this->mimetype = 'application/octet-stream';
+ }
+
+ $this->extension = strtolower(self::get_extension($this->realname));
+
+ // Try to get real filesize from temporary folder (not always working) ;)
+ $this->filesize = ($this->get_filesize($this->filename)) ?: $this->filesize;
+
+ $this->width = $this->height = 0;
+ $this->file_moved = false;
+
+ $this->local = (isset($upload_ary['local_mode'])) ? true : false;
+
+ return $this;
+ }
+
+ /**
+ * Set the upload namespace
+ *
+ * @param upload $namespace Instance of upload class
+ *
+ * @return filespec This instance of the filespec class
+ */
+ public function set_upload_namespace($namespace)
+ {
+ $this->upload = $namespace;
+
+ return $this;
+ }
+
+ /**
+ * Check if class members were not properly initialised yet
+ *
+ * @return bool True if there was an init error, false if not
+ */
+ public function init_error()
+ {
+ return !$this->class_initialized;
+ }
+
+ /**
+ * Set error in error array
+ *
+ * @param mixed $error Content for error array
+ *
+ * @return \phpbb\files\filespec This instance of the filespec class
+ */
+ public function set_error($error)
+ {
+ $this->error[] = $error;
+
+ return $this;
+ }
+
+ /**
+ * Cleans destination filename
+ *
+ * @param string $mode Either real, unique, or unique_ext. Real creates a
+ * realname, filtering some characters, lowering every
+ * character. Unique creates a unique filename.
+ * @param string $prefix Prefix applied to filename
+ * @param string $user_id The user_id is only needed for when cleaning a user's avatar
+ */
+ public function clean_filename($mode = 'unique', $prefix = '', $user_id = '')
+ {
+ if ($this->init_error())
+ {
+ return;
+ }
+
+ switch ($mode)
+ {
+ case 'real':
+ // Remove every extension from filename (to not let the mime bug being exposed)
+ if (strpos($this->realname, '.') !== false)
+ {
+ $this->realname = substr($this->realname, 0, strpos($this->realname, '.'));
+ }
+
+ // Replace any chars which may cause us problems with _
+ $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
+
+ $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname)));
+ $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname);
+
+ $this->realname = $prefix . $this->realname . '.' . $this->extension;
+ break;
+
+ case 'unique':
+ $this->realname = $prefix . md5(unique_id());
+ break;
+
+ case 'avatar':
+ $this->extension = strtolower($this->extension);
+ $this->realname = $prefix . $user_id . '.' . $this->extension;
+
+ break;
+
+ case 'unique_ext':
+ default:
+ $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension;
+ }
+ }
+
+ /**
+ * Get property from file object
+ *
+ * @param string $property Name of property
+ *
+ * @return mixed Content of property
+ */
+ public function get($property)
+ {
+ if ($this->init_error() || !isset($this->$property))
+ {
+ return false;
+ }
+
+ return $this->$property;
+ }
+
+ /**
+ * Check if file is an image (mime type)
+ *
+ * @return bool true if it is an image, false if not
+ */
+ public function is_image()
+ {
+ return (strpos($this->mimetype, 'image/') === 0);
+ }
+
+ /**
+ * Check if the file got correctly uploaded
+ *
+ * @return bool true if it is a valid upload, false if not
+ */
+ public function is_uploaded()
+ {
+ $is_plupload = $this->plupload && $this->plupload->is_active();
+
+ if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename))
+ {
+ return false;
+ }
+
+ if (($this->local || $is_plupload) && !file_exists($this->filename))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Remove file
+ */
+ public function remove()
+ {
+ if ($this->file_moved)
+ {
+ @unlink($this->destination_file);
+ }
+ }
+
+ /**
+ * Get file extension
+ *
+ * @param string $filename Filename that needs to be checked
+ *
+ * @return string Extension of the supplied filename
+ */
+ static public function get_extension($filename)
+ {
+ $filename = utf8_basename($filename);
+
+ if (strpos($filename, '.') === false)
+ {
+ return '';
+ }
+
+ $filename = explode('.', $filename);
+ return array_pop($filename);
+ }
+
+ /**
+ * Get mime type
+ *
+ * @param string $filename Filename that needs to be checked
+ * @return string Mime type of supplied filename
+ */
+ public function get_mimetype($filename)
+ {
+ if ($this->mimetype_guesser !== null)
+ {
+ $mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname);
+
+ if ($mimetype !== 'application/octet-stream')
+ {
+ $this->mimetype = $mimetype;
+ }
+ }
+
+ return $this->mimetype;
+ }
+
+ /**
+ * Get file size
+ *
+ * @param string $filename File name of file to check
+ *
+ * @return int File size
+ */
+ public function get_filesize($filename)
+ {
+ return @filesize($filename);
+ }
+
+
+ /**
+ * Check the first 256 bytes for forbidden content
+ *
+ * @param array $disallowed_content Array containg disallowed content
+ *
+ * @return bool False if disallowed content found, true if not
+ */
+ public function check_content($disallowed_content)
+ {
+ if (empty($disallowed_content))
+ {
+ return true;
+ }
+
+ $fp = @fopen($this->filename, 'rb');
+
+ if ($fp !== false)
+ {
+ $ie_mime_relevant = fread($fp, 256);
+ fclose($fp);
+ foreach ($disallowed_content as $forbidden)
+ {
+ if (stripos($ie_mime_relevant, '<' . $forbidden) !== false)
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Move file to destination folder
+ * The phpbb_root_path variable will be applied to the destination path
+ *
+ * @param string $destination Destination path, for example $config['avatar_path']
+ * @param bool $overwrite If set to true, an already existing file will be overwritten
+ * @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped
+ * @param string|bool $chmod Permission mask for chmodding the file after a successful move.
+ * The mode entered here reflects the mode defined by {@link phpbb_chmod()}
+ *
+ * @return bool True if file was moved, false if not
+ * @access public
+ */
+ public function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false)
+ {
+ if (sizeof($this->error))
+ {
+ return false;
+ }
+
+ $chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod;
+
+ // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
+ $this->destination_path = $this->phpbb_root_path . $destination;
+
+ // Check if the destination path exist...
+ if (!file_exists($this->destination_path))
+ {
+ @unlink($this->filename);
+ return false;
+ }
+
+ $upload_mode = ($this->php_ini->getBool('open_basedir') || $this->php_ini->getBool('safe_mode')) ? 'move' : 'copy';
+ $upload_mode = ($this->local) ? 'local' : $upload_mode;
+ $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
+
+ // Check if the file already exist, else there is something wrong...
+ if (file_exists($this->destination_file) && !$overwrite)
+ {
+ @unlink($this->filename);
+ $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
+ $this->file_moved = false;
+ return false;
+ }
+ else
+ {
+ if (file_exists($this->destination_file))
+ {
+ @unlink($this->destination_file);
+ }
+
+ switch ($upload_mode)
+ {
+ case 'copy':
+
+ if (!@copy($this->filename, $this->destination_file))
+ {
+ if (!@move_uploaded_file($this->filename, $this->destination_file))
+ {
+ $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
+ }
+ }
+
+ break;
+
+ case 'move':
+
+ if (!@move_uploaded_file($this->filename, $this->destination_file))
+ {
+ if (!@copy($this->filename, $this->destination_file))
+ {
+ $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
+ }
+ }
+
+ break;
+
+ case 'local':
+
+ if (!@copy($this->filename, $this->destination_file))
+ {
+ $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
+ }
+
+ break;
+ }
+
+ // Remove temporary filename
+ @unlink($this->filename);
+
+ if (sizeof($this->error))
+ {
+ return false;
+ }
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($this->destination_file, $chmod);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ }
+
+ // Try to get real filesize from destination folder
+ $this->filesize = ($this->get_filesize($this->destination_file)) ?: $this->filesize;
+
+ // Get mimetype of supplied file
+ $this->mimetype = $this->get_mimetype($this->destination_file);
+
+ if ($this->is_image() && !$skip_image_check)
+ {
+ $this->width = $this->height = 0;
+
+ $this->image_info = $this->imagesize->getImageSize($this->destination_file, $this->mimetype);
+
+ if ($this->image_info !== false)
+ {
+ $this->width = $this->image_info['width'];
+ $this->height = $this->image_info['height'];
+
+ // Check image type
+ $types = upload::image_types();
+
+ if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']]))
+ {
+ if (!isset($types[$this->image_info['type']]))
+ {
+ $this->error[] = $this->language->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype);
+ }
+ else
+ {
+ $this->error[] = $this->language->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension);
+ }
+ }
+
+ // Make sure the dimensions match a valid image
+ if (empty($this->width) || empty($this->height))
+ {
+ $this->error[] = $this->language->lang('ATTACHED_IMAGE_NOT_IMAGE');
+ }
+ }
+ else
+ {
+ $this->error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE');
+ }
+ }
+
+ $this->file_moved = true;
+ $this->additional_checks();
+ unset($this->upload);
+
+ return true;
+ }
+
+ /**
+ * Performing additional checks
+ *
+ * @return bool False if issue was found, true if not
+ */
+ public function additional_checks()
+ {
+ if (!$this->file_moved)
+ {
+ return false;
+ }
+
+ // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
+ if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
+ {
+ $max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
+
+ $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
+
+ return false;
+ }
+
+ if (!$this->upload->valid_dimensions($this))
+ {
+ $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_SIZE',
+ $this->language->lang('PIXELS', (int) $this->upload->min_width),
+ $this->language->lang('PIXELS', (int) $this->upload->min_height),
+ $this->language->lang('PIXELS', (int) $this->upload->max_width),
+ $this->language->lang('PIXELS', (int) $this->upload->max_height),
+ $this->language->lang('PIXELS', (int) $this->width),
+ $this->language->lang('PIXELS', (int) $this->height));
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/phpBB/phpbb/files/types/base.php b/phpBB/phpbb/files/types/base.php
new file mode 100644
index 0000000000..3313ad040b
--- /dev/null
+++ b/phpBB/phpbb/files/types/base.php
@@ -0,0 +1,65 @@
+<?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\files\types;
+
+abstract class base implements type_interface
+{
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\files\upload */
+ protected $upload;
+
+ /**
+ * Check if upload exceeds maximum file size
+ *
+ * @param \phpbb\files\filespec $file Filespec object
+ *
+ * @return \phpbb\files\filespec Returns same filespec instance
+ */
+ public function check_upload_size($file)
+ {
+ // PHP Upload filesize exceeded
+ if ($file->get('filename') == 'none')
+ {
+ $max_filesize = $this->php_ini->getString('upload_max_filesize');
+ $unit = 'MB';
+
+ if (!empty($max_filesize))
+ {
+ $unit = strtolower(substr($max_filesize, -1, 1));
+ $max_filesize = (int) $max_filesize;
+
+ $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
+ }
+
+ $file->error[] = (empty($max_filesize)) ? $this->language->lang($this->upload->error_prefix . 'PHP_SIZE_NA') : $this->language->lang($this->upload->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, $this->language->lang($unit));
+ }
+
+ return $file;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_upload(\phpbb\files\upload $upload)
+ {
+ $this->upload = $upload;
+
+ return $this;
+ }
+}
diff --git a/phpBB/phpbb/files/types/form.php b/phpBB/phpbb/files/types/form.php
new file mode 100644
index 0000000000..832f090c47
--- /dev/null
+++ b/phpBB/phpbb/files/types/form.php
@@ -0,0 +1,138 @@
+<?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\files\types;
+
+use bantu\IniGetWrapper\IniGetWrapper;
+use phpbb\files\factory;
+use phpbb\files\filespec;
+use phpbb\language\language;
+use phpbb\plupload\plupload;
+use phpbb\request\request_interface;
+
+class form extends base
+{
+ /** @var factory Files factory */
+ protected $factory;
+
+ /** @var language */
+ protected $language;
+
+ /** @var IniGetWrapper */
+ protected $php_ini;
+
+ /** @var plupload */
+ protected $plupload;
+
+ /** @var request_interface */
+ protected $request;
+
+ /** @var \phpbb\files\upload */
+ protected $upload;
+
+ /**
+ * Construct a form upload type
+ *
+ * @param factory $factory Files factory
+ * @param language $language Language class
+ * @param IniGetWrapper $php_ini ini_get() wrapper
+ * @param plupload $plupload Plupload
+ * @param request_interface $request Request object
+ */
+ public function __construct(factory $factory, language $language, IniGetWrapper $php_ini, plupload $plupload, request_interface $request)
+ {
+ $this->factory = $factory;
+ $this->language = $language;
+ $this->php_ini = $php_ini;
+ $this->plupload = $plupload;
+ $this->request = $request;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function upload()
+ {
+ $args = func_get_args();
+ return $this->form_upload($args[0]);
+ }
+
+ /**
+ * Form upload method
+ * Upload file from users harddisk
+ *
+ * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified)
+ *
+ * @return filespec $file Object "filespec" is returned, all further operations can be done with this object
+ * @access public
+ */
+ protected function form_upload($form_name)
+ {
+ $upload = $this->request->file($form_name);
+ unset($upload['local_mode']);
+
+ $result = $this->plupload->handle_upload($form_name);
+ if (is_array($result))
+ {
+ $upload = array_merge($upload, $result);
+ }
+
+ /** @var filespec $file */
+ $file = $this->factory->get('filespec')
+ ->set_upload_ary($upload)
+ ->set_upload_namespace($this->upload);
+
+ if ($file->init_error())
+ {
+ $file->error[] = '';
+ return $file;
+ }
+
+ // Error array filled?
+ if (isset($upload['error']))
+ {
+ $error = $this->upload->assign_internal_error($upload['error']);
+
+ if ($error !== false)
+ {
+ $file->error[] = $error;
+ return $file;
+ }
+ }
+
+ // Check if empty file got uploaded (not catched by is_uploaded_file)
+ if (isset($upload['size']) && $upload['size'] == 0)
+ {
+ $file->error[] = $this->language->lang($this->upload->error_prefix . 'EMPTY_FILEUPLOAD');
+ return $file;
+ }
+
+ // PHP Upload file size check
+ $file = $this->check_upload_size($file);
+ if (sizeof($file->error))
+ {
+ return $file;
+ }
+
+ // Not correctly uploaded
+ if (!$file->is_uploaded())
+ {
+ $file->error[] = $this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED');
+ return $file;
+ }
+
+ $this->upload->common_checks($file);
+
+ return $file;
+ }
+}
diff --git a/phpBB/phpbb/files/types/local.php b/phpBB/phpbb/files/types/local.php
new file mode 100644
index 0000000000..7e9210b196
--- /dev/null
+++ b/phpBB/phpbb/files/types/local.php
@@ -0,0 +1,136 @@
+<?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\files\types;
+
+use bantu\IniGetWrapper\IniGetWrapper;
+use phpbb\files\factory;
+use phpbb\files\filespec;
+use phpbb\language\language;
+use phpbb\request\request_interface;
+
+class local extends base
+{
+ /** @var factory Files factory */
+ protected $factory;
+
+ /** @var language */
+ protected $language;
+
+ /** @var IniGetWrapper */
+ protected $php_ini;
+
+ /** @var request_interface */
+ protected $request;
+
+ /** @var \phpbb\files\upload */
+ protected $upload;
+
+ /**
+ * Construct a form upload type
+ *
+ * @param factory $factory Files factory
+ * @param language $language Language class
+ * @param IniGetWrapper $php_ini ini_get() wrapper
+ * @param request_interface $request Request object
+ */
+ public function __construct(factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request)
+ {
+ $this->factory = $factory;
+ $this->language = $language;
+ $this->php_ini = $php_ini;
+ $this->request = $request;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function upload()
+ {
+ $args = func_get_args();
+ return $this->local_upload($args[0], isset($args[1]) ? $args[1] : false);
+ }
+
+ /**
+ * Move file from another location to phpBB
+ *
+ * @param string $source_file Filename of source file
+ * @param array|bool $filedata Array with filedata or false
+ *
+ * @return filespec Object "filespec" is returned, all further operations can be done with this object
+ */
+ protected function local_upload($source_file, $filedata = false)
+ {
+ $upload = $this->get_upload_ary($source_file, $filedata);
+
+ /** @var filespec $file */
+ $file = $this->factory->get('filespec')
+ ->set_upload_ary($upload)
+ ->set_upload_namespace($this->upload);
+
+ if ($file->init_error())
+ {
+ $file->error[] = '';
+ return $file;
+ }
+
+ // PHP Upload file size check
+ $file = $this->check_upload_size($file);
+ if (sizeof($file->error))
+ {
+ return $file;
+ }
+
+ // Not correctly uploaded
+ if (!$file->is_uploaded())
+ {
+ $file->error[] = $this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED');
+ return $file;
+ }
+
+ $this->upload->common_checks($file);
+ $this->request->overwrite('local', $upload, request_interface::FILES);
+
+ return $file;
+ }
+
+ /**
+ * Retrieve upload array
+ *
+ * @param string $source_file Source file name
+ * @param array $filedata File data array
+ *
+ * @return array Upload array
+ */
+ protected function get_upload_ary($source_file, $filedata)
+ {
+ $upload = array();
+
+ $upload['local_mode'] = true;
+ $upload['tmp_name'] = $source_file;
+
+ if ($filedata === false)
+ {
+ $upload['name'] = utf8_basename($source_file);
+ $upload['size'] = 0;
+ }
+ else
+ {
+ $upload['name'] = $filedata['realname'];
+ $upload['size'] = $filedata['size'];
+ $upload['type'] = $filedata['type'];
+ }
+
+ return $upload;
+ }
+}
diff --git a/phpBB/phpbb/files/types/remote.php b/phpBB/phpbb/files/types/remote.php
new file mode 100644
index 0000000000..1fdba0ca32
--- /dev/null
+++ b/phpBB/phpbb/files/types/remote.php
@@ -0,0 +1,207 @@
+<?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\files\types;
+
+use bantu\IniGetWrapper\IniGetWrapper;
+use phpbb\config\config;
+use phpbb\files\factory;
+use phpbb\files\filespec;
+use phpbb\language\language;
+use phpbb\request\request_interface;
+
+class remote extends base
+{
+ /** @var config phpBB config */
+ protected $config;
+
+ /** @var factory Files factory */
+ protected $factory;
+
+ /** @var language */
+ protected $language;
+
+ /** @var IniGetWrapper */
+ protected $php_ini;
+
+ /** @var request_interface */
+ protected $request;
+
+ /** @var \phpbb\files\upload */
+ protected $upload;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ /**
+ * Construct a form upload type
+ *
+ * @param config $config phpBB config
+ * @param factory $factory Files factory
+ * @param language $language Language class
+ * @param IniGetWrapper $php_ini ini_get() wrapper
+ * @param request_interface $request Request object
+ * @param string $phpbb_root_path phpBB root path
+ */
+ public function __construct(config $config, factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path)
+ {
+ $this->config = $config;
+ $this->factory = $factory;
+ $this->language = $language;
+ $this->php_ini = $php_ini;
+ $this->request = $request;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function upload()
+ {
+ $args = func_get_args();
+ return $this->remote_upload($args[0]);
+ }
+
+ /**
+ * Remote upload method
+ * Uploads file from given url
+ *
+ * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif
+ * @return filespec $file Object "filespec" is returned, all further operations can be done with this object
+ * @access public
+ */
+ protected function remote_upload($upload_url)
+ {
+ $upload_ary = array();
+ $upload_ary['local_mode'] = true;
+
+ if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->upload->allowed_extensions) . ')$#i', $upload_url, $match))
+ {
+ return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'URL_INVALID'));
+ }
+
+ $url = parse_url($upload_url);
+
+ $upload_ary['type'] = 'application/octet-stream';
+
+ $url['path'] = explode('.', $url['path']);
+ $ext = array_pop($url['path']);
+
+ $url['path'] = implode('', $url['path']);
+ $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
+
+ $remote_max_filesize = $this->get_max_file_size();
+
+ $guzzle_options = [
+ 'timeout' => $this->upload->upload_timeout,
+ 'connect_timeout' => $this->upload->upload_timeout,
+ 'verify' => !empty($this->config['remote_upload_verify']) ? (bool) $this->config['remote_upload_verify'] : false,
+ ];
+ $client = new \GuzzleHttp\Client($guzzle_options);
+
+ try
+ {
+ $response = $client->get($upload_url, $guzzle_options);
+ }
+ catch (\GuzzleHttp\Exception\ClientException $clientException)
+ {
+ return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'URL_NOT_FOUND');
+ }
+ catch (\GuzzleHttp\Exception\RequestException $requestException)
+ {
+ if (strpos($requestException->getMessage(), 'cURL error 28') !== false || preg_match('/408|504/', $requestException->getCode()))
+ {
+ return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'REMOTE_UPLOAD_TIMEOUT');
+ }
+ else
+ {
+ return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED'));
+ }
+ }
+ catch (\Exception $e)
+ {
+ return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED'));
+ }
+
+ $content_length = $response->getBody()->getSize();
+ if ($remote_max_filesize && $content_length > $remote_max_filesize)
+ {
+ $max_filesize = get_formatted_filesize($remote_max_filesize, false);
+
+ return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']));
+ }
+
+ if ($content_length == 0)
+ {
+ return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'EMPTY_REMOTE_DATA');
+ }
+
+ $data = $response->getBody();
+
+ $filename = tempnam(sys_get_temp_dir(), unique_id() . '-');
+
+ if (!($fp = @fopen($filename, 'wb')))
+ {
+ return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'NOT_UPLOADED');
+ }
+
+ $upload_ary['size'] = fwrite($fp, $data);
+ fclose($fp);
+ unset($data);
+
+ $upload_ary['tmp_name'] = $filename;
+
+ /** @var filespec $file */
+ $file = $this->factory->get('filespec')
+ ->set_upload_ary($upload_ary)
+ ->set_upload_namespace($this->upload);
+ $this->upload->common_checks($file);
+
+ return $file;
+ }
+
+ /**
+ * Get maximum file size for remote uploads
+ *
+ * @return int Maximum file size
+ */
+ protected function get_max_file_size()
+ {
+ $max_file_size = $this->upload->max_filesize;
+ if (!$max_file_size)
+ {
+ $max_file_size = $this->php_ini->getString('upload_max_filesize');
+
+ if (!empty($max_file_size))
+ {
+ $unit = strtolower(substr($max_file_size, -1, 1));
+ $max_file_size = (int) $max_file_size;
+
+ switch ($unit)
+ {
+ case 'g':
+ $max_file_size *= 1024;
+ // no break
+ case 'm':
+ $max_file_size *= 1024;
+ // no break
+ case 'k':
+ $max_file_size *= 1024;
+ // no break
+ }
+ }
+ }
+
+ return $max_file_size;
+ }
+}
diff --git a/phpBB/phpbb/files/types/type_interface.php b/phpBB/phpbb/files/types/type_interface.php
new file mode 100644
index 0000000000..e07078349a
--- /dev/null
+++ b/phpBB/phpbb/files/types/type_interface.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\files\types;
+
+use phpbb\files\upload;
+
+interface type_interface
+{
+ /**
+ * Handle upload for upload types. Arguments passed to this method will be
+ * handled by the upload type classes themselves.
+ *
+ * @return \phpbb\files\filespec|bool Filespec instance if upload is
+ * successful or false if not
+ */
+ public function upload();
+
+ /**
+ * Set upload instance
+ * Needs to be executed before every upload.
+ *
+ * @param upload $upload Upload instance
+ *
+ * @return type_interface Returns itself
+ */
+ public function set_upload(upload $upload);
+}
diff --git a/phpBB/phpbb/files/upload.php b/phpBB/phpbb/files/upload.php
new file mode 100644
index 0000000000..a9bf74094d
--- /dev/null
+++ b/phpBB/phpbb/files/upload.php
@@ -0,0 +1,390 @@
+<?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\files;
+
+use phpbb\filesystem\filesystem_interface;
+use phpbb\language\language;
+use phpbb\request\request_interface;
+
+/**
+ * File upload class
+ * Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads
+ */
+class upload
+{
+ /** @var array Allowed file extensions */
+ public $allowed_extensions = array();
+
+ /** @var array Disallowed content */
+ protected $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title');
+
+ /** @var int Maximum filesize */
+ public $max_filesize = 0;
+
+ /** @var int Minimum width of images */
+ public $min_width = 0;
+
+ /** @var int Minimum height of images */
+ public $min_height = 0;
+
+ /** @var int Maximum width of images */
+ public $max_width = 0;
+
+ /** @var int Maximum height of images */
+ public $max_height = 0;
+
+ /** @var string Prefix for language variables of errors */
+ public $error_prefix = '';
+
+ /** @var int Timeout for remote upload */
+ public $upload_timeout = 6;
+
+ /** @var filesystem_interface */
+ protected $filesystem;
+
+ /** @var \phpbb\files\factory Files factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language Language class */
+ protected $language;
+
+ /** @var request_interface Request class */
+ protected $request;
+
+ /**
+ * Init file upload class.
+ *
+ * @param filesystem_interface $filesystem
+ * @param factory $factory Files factory
+ * @param language $language Language class
+ * @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper
+ * @param request_interface $request Request class
+ */
+ public function __construct(filesystem_interface $filesystem, factory $factory, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, request_interface $request)
+ {
+ $this->filesystem = $filesystem;
+ $this->factory = $factory;
+ $this->language = $language;
+ $this->php_ini = $php_ini;
+ $this->request = $request;
+ }
+
+ /**
+ * Reset vars
+ */
+ public function reset_vars()
+ {
+ $this->max_filesize = 0;
+ $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0;
+ $this->error_prefix = '';
+ $this->allowed_extensions = array();
+ $this->disallowed_content = array();
+ }
+
+ /**
+ * Set allowed extensions
+ *
+ * @param array $allowed_extensions Allowed file extensions
+ *
+ * @return \phpbb\files\upload This instance of upload
+ */
+ public function set_allowed_extensions($allowed_extensions)
+ {
+ if ($allowed_extensions !== false && is_array($allowed_extensions))
+ {
+ $this->allowed_extensions = $allowed_extensions;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set allowed dimensions
+ *
+ * @param int $min_width Minimum image width
+ * @param int $min_height Minimum image height
+ * @param int $max_width Maximum image width
+ * @param int $max_height Maximum image height
+ *
+ * @return \phpbb\files\upload This instance of upload
+ */
+ public function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height)
+ {
+ $this->min_width = (int) $min_width;
+ $this->min_height = (int) $min_height;
+ $this->max_width = (int) $max_width;
+ $this->max_height = (int) $max_height;
+
+ return $this;
+ }
+
+ /**
+ * Set maximum allowed file size
+ *
+ * @param int $max_filesize Maximum file size
+ *
+ * @return \phpbb\files\upload This instance of upload
+ */
+ public function set_max_filesize($max_filesize)
+ {
+ if ($max_filesize !== false && (int) $max_filesize)
+ {
+ $this->max_filesize = (int) $max_filesize;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set disallowed strings
+ *
+ * @param array $disallowed_content Disallowed content
+ *
+ * @return \phpbb\files\upload This instance of upload
+ */
+ public function set_disallowed_content($disallowed_content)
+ {
+ if ($disallowed_content !== false && is_array($disallowed_content))
+ {
+ $this->disallowed_content = array_diff($disallowed_content, array(''));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set error prefix
+ *
+ * @param string $error_prefix Prefix for language variables of errors
+ *
+ * @return \phpbb\files\upload This instance of upload
+ */
+ public function set_error_prefix($error_prefix)
+ {
+ $this->error_prefix = $error_prefix;
+
+ return $this;
+ }
+
+ /**
+ * Handle upload based on type
+ *
+ * @param string $type Upload type
+ *
+ * @return \phpbb\files\filespec|bool A filespec instance if upload was
+ * successful, false if there were issues or the type is not supported
+ */
+ public function handle_upload($type)
+ {
+ $args = func_get_args();
+ array_shift($args);
+ $type_class = $this->factory->get($type)
+ ->set_upload($this);
+
+ return (is_object($type_class)) ? call_user_func_array(array($type_class, 'upload'), $args) : false;
+ }
+
+ /**
+ * Assign internal error
+ *
+ * @param string $errorcode Error code to assign
+ *
+ * @return string Error string
+ * @access public
+ */
+ public function assign_internal_error($errorcode)
+ {
+ switch ($errorcode)
+ {
+ case UPLOAD_ERR_INI_SIZE:
+ $max_filesize = $this->php_ini->getString('upload_max_filesize');
+ $unit = 'MB';
+
+ if (!empty($max_filesize))
+ {
+ $unit = strtolower(substr($max_filesize, -1, 1));
+ $max_filesize = (int) $max_filesize;
+
+ $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
+ }
+
+ $error = (empty($max_filesize)) ? $this->language->lang($this->error_prefix . 'PHP_SIZE_NA') : $this->language->lang($this->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, $this->language->lang($unit));
+ break;
+
+ case UPLOAD_ERR_FORM_SIZE:
+ $max_filesize = get_formatted_filesize($this->max_filesize, false);
+
+ $error = $this->language->lang($this->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
+ break;
+
+ case UPLOAD_ERR_PARTIAL:
+ $error = $this->language->lang($this->error_prefix . 'PARTIAL_UPLOAD');
+ break;
+
+ case UPLOAD_ERR_NO_FILE:
+ $error = $this->language->lang($this->error_prefix . 'NOT_UPLOADED');
+ break;
+
+ case UPLOAD_ERR_NO_TMP_DIR:
+ case UPLOAD_ERR_CANT_WRITE:
+ $error = $this->language->lang($this->error_prefix . 'NO_TEMP_DIR');
+ break;
+
+ case UPLOAD_ERR_EXTENSION:
+ $error = $this->language->lang($this->error_prefix . 'PHP_UPLOAD_STOPPED');
+ break;
+
+ default:
+ $error = false;
+ break;
+ }
+
+ return $error;
+ }
+
+ /**
+ * Perform common file checks
+ *
+ * @param filespec $file Instance of filespec class
+ */
+ 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))
+ {
+ $max_filesize = get_formatted_filesize($this->max_filesize, false);
+
+ $file->error[] = $this->language->lang($this->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
+ }
+
+ // check Filename
+ if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname')))
+ {
+ $file->error[] = $this->language->lang($this->error_prefix . 'INVALID_FILENAME', $file->get('realname'));
+ }
+
+ // Invalid Extension
+ if (!$this->valid_extension($file))
+ {
+ $file->error[] = $this->language->lang($this->error_prefix . 'DISALLOWED_EXTENSION', $file->get('extension'));
+ }
+
+ // MIME Sniffing
+ if (!$this->valid_content($file))
+ {
+ $file->error[] = $this->language->lang($this->error_prefix . 'DISALLOWED_CONTENT');
+ }
+ }
+
+ /**
+ * Check for allowed extension
+ *
+ * @param filespec $file Instance of filespec class
+ *
+ * @return bool True if extension is allowed, false if not
+ */
+ public function valid_extension(&$file)
+ {
+ return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false;
+ }
+
+ /**
+ * Check for allowed dimension
+ *
+ * @param filespec $file Instance of filespec class
+ *
+ * @return bool True if dimensions are valid or no constraints set, false
+ * if not
+ */
+ public function valid_dimensions(&$file)
+ {
+ if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height)
+ {
+ return true;
+ }
+
+ if (($file->get('width') > $this->max_width && $this->max_width) ||
+ ($file->get('height') > $this->max_height && $this->max_height) ||
+ ($file->get('width') < $this->min_width && $this->min_width) ||
+ ($file->get('height') < $this->min_height && $this->min_height))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if form upload is valid
+ *
+ * @param string $form_name Name of form
+ *
+ * @return bool True if form upload is valid, false if not
+ */
+ public function is_valid($form_name)
+ {
+ $upload = $this->request->file($form_name);
+
+ return (!empty($upload) && $upload['name'] !== 'none');
+ }
+
+
+ /**
+ * Check for bad content (IE mime-sniffing)
+ *
+ * @param filespec $file Instance of filespec class
+ *
+ * @return bool True if content is valid, false if not
+ */
+ public function valid_content(&$file)
+ {
+ return ($file->check_content($this->disallowed_content));
+ }
+
+ /**
+ * Get image type/extension mapping
+ *
+ * @return array Array containing the image types and their extensions
+ */
+ static public function image_types()
+ {
+ $result = array(
+ IMAGETYPE_GIF => array('gif'),
+ IMAGETYPE_JPEG => array('jpg', 'jpeg'),
+ IMAGETYPE_PNG => array('png'),
+ IMAGETYPE_SWF => array('swf'),
+ IMAGETYPE_PSD => array('psd'),
+ IMAGETYPE_BMP => array('bmp'),
+ IMAGETYPE_TIFF_II => array('tif', 'tiff'),
+ IMAGETYPE_TIFF_MM => array('tif', 'tiff'),
+ IMAGETYPE_JPC => array('jpg', 'jpeg'),
+ IMAGETYPE_JP2 => array('jpg', 'jpeg'),
+ IMAGETYPE_JPX => array('jpg', 'jpeg'),
+ IMAGETYPE_JB2 => array('jpg', 'jpeg'),
+ IMAGETYPE_IFF => array('iff'),
+ IMAGETYPE_WBMP => array('wbmp'),
+ IMAGETYPE_XBM => array('xbm'),
+ );
+
+ if (defined('IMAGETYPE_SWC'))
+ {
+ $result[IMAGETYPE_SWC] = array('swc');
+ }
+
+ return $result;
+ }
+}
diff --git a/phpBB/phpbb/filesystem.php b/phpBB/phpbb/filesystem.php
index 77517082e5..af56d78845 100644
--- a/phpBB/phpbb/filesystem.php
+++ b/phpBB/phpbb/filesystem.php
@@ -14,37 +14,8 @@
namespace phpbb;
/**
-* A class with various functions that are related to paths, files and the filesystem
-*/
-class filesystem
+ * @deprecated 3.2.0-dev (To be removed 3.3.0) use \phpbb\filesystem\filesystem instead
+ */
+class filesystem extends \phpbb\filesystem\filesystem
{
- /**
- * Eliminates useless . and .. components from specified path.
- *
- * @param string $path Path to clean
- * @return string Cleaned path
- */
- public function clean_path($path)
- {
- $exploded = explode('/', $path);
- $filtered = array();
- foreach ($exploded as $part)
- {
- if ($part === '.' && !empty($filtered))
- {
- continue;
- }
-
- if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..')
- {
- array_pop($filtered);
- }
- else
- {
- $filtered[] = $part;
- }
- }
- $path = implode('/', $filtered);
- return $path;
- }
}
diff --git a/phpBB/phpbb/filesystem/exception/filesystem_exception.php b/phpBB/phpbb/filesystem/exception/filesystem_exception.php
new file mode 100644
index 0000000000..d68fa9adf3
--- /dev/null
+++ b/phpBB/phpbb/filesystem/exception/filesystem_exception.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\filesystem\exception;
+
+class filesystem_exception extends \phpbb\exception\runtime_exception
+{
+ /**
+ * Constructor
+ *
+ * @param string $message The Exception message to throw (must be a language variable).
+ * @param string $filename The file that caused the error.
+ * @param array $parameters The parameters to use with the language var.
+ * @param \Exception $previous The previous runtime_exception used for the runtime_exception chaining.
+ * @param integer $code The Exception code.
+ */
+ public function __construct($message = "", $filename = '', $parameters = array(), \Exception $previous = null, $code = 0)
+ {
+ parent::__construct($message, array_merge(array('filename' => $filename), $parameters), $previous, $code);
+ }
+
+ /**
+ * Returns the filename that triggered the error
+ *
+ * @return string
+ */
+ public function get_filename()
+ {
+ $parameters = parent::get_parameters();
+ return $parameters['filename'];
+ }
+}
diff --git a/phpBB/phpbb/filesystem/filesystem.php b/phpBB/phpbb/filesystem/filesystem.php
new file mode 100644
index 0000000000..2112882d1d
--- /dev/null
+++ b/phpBB/phpbb/filesystem/filesystem.php
@@ -0,0 +1,916 @@
+<?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\filesystem;
+
+use phpbb\filesystem\exception\filesystem_exception;
+
+/**
+ * A class with various functions that are related to paths, files and the filesystem
+ */
+class filesystem implements filesystem_interface
+{
+ /**
+ * Store some information about file ownership for phpBB's chmod function
+ *
+ * @var array
+ */
+ protected $chmod_info;
+
+ /**
+ * Stores current working directory
+ *
+ * @var string|bool current working directory or false if it cannot be recovered
+ */
+ protected $working_directory;
+
+ /**
+ * Symfony's Filesystem component
+ *
+ * @var \Symfony\Component\Filesystem\Filesystem
+ */
+ protected $symfony_filesystem;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->chmod_info = array();
+ $this->symfony_filesystem = new \Symfony\Component\Filesystem\Filesystem();
+ $this->working_directory = null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function chgrp($files, $group, $recursive = false)
+ {
+ try
+ {
+ $this->symfony_filesystem->chgrp($files, $group, $recursive);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ // Try to recover filename
+ // By the time this is written that is at the end of the message
+ $error = trim($e->getMessage());
+ $file = substr($error, strrpos($error, ' '));
+
+ throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false)
+ {
+ if (is_null($perms))
+ {
+ // Default to read permission for compatibility reasons
+ $perms = self::CHMOD_READ;
+ }
+
+ // Check if we got a permission flag
+ if ($perms > self::CHMOD_ALL)
+ {
+ $file_perm = $perms;
+
+ // Extract permissions
+ //$owner = ($file_perm >> 6) & 7; // This will be ignored
+ $group = ($file_perm >> 3) & 7;
+ $other = ($file_perm >> 0) & 7;
+
+ // Does any permissions provided? if so we add execute bit for directories
+ $group = ($group !== 0) ? ($group | self::CHMOD_EXECUTE) : $group;
+ $other = ($other !== 0) ? ($other | self::CHMOD_EXECUTE) : $other;
+
+ // Compute directory permissions
+ $dir_perm = (self::CHMOD_ALL << 6) + ($group << 3) + ($other << 3);
+ }
+ else
+ {
+ // Add execute bit to owner if execute bit is among perms
+ $owner_perm = (self::CHMOD_READ | self::CHMOD_WRITE) | ($perms & self::CHMOD_EXECUTE);
+ $file_perm = ($owner_perm << 6) + ($perms << 3) + ($perms << 0);
+
+ // Compute directory permissions
+ $perm = ($perms !== 0) ? ($perms | self::CHMOD_EXECUTE) : $perms;
+ $dir_perm = (($owner_perm | self::CHMOD_EXECUTE) << 6) + ($perm << 3) + ($perm << 0);
+ }
+
+ // Symfony's filesystem component does not support extra execution flags on directories
+ // so we need to implement it again
+ foreach ($this->to_iterator($files) as $file)
+ {
+ if ($recursive && is_dir($file) && !is_link($file))
+ {
+ $this->chmod(new \FilesystemIterator($file), $perms, true);
+ }
+
+ // Don't chmod links as mostly those require 0777 and that cannot be changed
+ if (is_dir($file) || (is_link($file) && $force_chmod_link))
+ {
+ if (true !== @chmod($file, $dir_perm))
+ {
+ throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file, array());
+ }
+ }
+ else if (is_file($file))
+ {
+ if (true !== @chmod($file, $file_perm))
+ {
+ throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file, array());
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function chown($files, $user, $recursive = false)
+ {
+ try
+ {
+ $this->symfony_filesystem->chown($files, $user, $recursive);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ // Try to recover filename
+ // By the time this is written that is at the end of the message
+ $error = trim($e->getMessage());
+ $file = substr($error, strrpos($error, ' '));
+
+ throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clean_path($path)
+ {
+ $exploded = explode('/', $path);
+ $filtered = array();
+ foreach ($exploded as $part)
+ {
+ if ($part === '.' && !empty($filtered))
+ {
+ continue;
+ }
+
+ if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..')
+ {
+ array_pop($filtered);
+ }
+ else
+ {
+ $filtered[] = $part;
+ }
+ }
+ $path = implode('/', $filtered);
+ return $path;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function copy($origin_file, $target_file, $override = false)
+ {
+ try
+ {
+ $this->symfony_filesystem->copy($origin_file, $target_file, $override);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ throw new filesystem_exception('CANNOT_COPY_FILES', '', array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dump_file($filename, $content)
+ {
+ try
+ {
+ $this->symfony_filesystem->dumpFile($filename, $content);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ throw new filesystem_exception('CANNOT_DUMP_FILE', $filename, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function exists($files)
+ {
+ return $this->symfony_filesystem->exists($files);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_absolute_path($path)
+ {
+ return (isset($path[0]) && $path[0] === '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_readable($files, $recursive = false)
+ {
+ foreach ($this->to_iterator($files) as $file)
+ {
+ if ($recursive && is_dir($file) && !is_link($file))
+ {
+ if (!$this->is_readable(new \FilesystemIterator($file), true))
+ {
+ return false;
+ }
+ }
+
+ if (!is_readable($file))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_writable($files, $recursive = false)
+ {
+ if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('is_writable'))
+ {
+ foreach ($this->to_iterator($files) as $file)
+ {
+ if ($recursive && is_dir($file) && !is_link($file))
+ {
+ if (!$this->is_writable(new \FilesystemIterator($file), true))
+ {
+ return false;
+ }
+ }
+
+ if (!$this->phpbb_is_writable($file))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // use built in is_writable
+ foreach ($this->to_iterator($files) as $file)
+ {
+ if ($recursive && is_dir($file) && !is_link($file))
+ {
+ if (!$this->is_writable(new \FilesystemIterator($file), true))
+ {
+ return false;
+ }
+ }
+
+ if (!is_writable($file))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function make_path_relative($end_path, $start_path)
+ {
+ return $this->symfony_filesystem->makePathRelative($end_path, $start_path);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array())
+ {
+ try
+ {
+ $this->symfony_filesystem->mirror($origin_dir, $target_dir, $iterator, $options);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ $msg = $e->getMessage();
+ $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"'));
+
+ throw new filesystem_exception('CANNOT_MIRROR_DIRECTORY', $filename, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mkdir($dirs, $mode = 0777)
+ {
+ try
+ {
+ $this->symfony_filesystem->mkdir($dirs, $mode);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ $msg = $e->getMessage();
+ $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"'));
+
+ throw new filesystem_exception('CANNOT_CREATE_DIRECTORY', $filename, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function phpbb_chmod($files, $perms = null, $recursive = false, $force_chmod_link = false)
+ {
+ if (is_null($perms))
+ {
+ // Default to read permission for compatibility reasons
+ $perms = self::CHMOD_READ;
+ }
+
+ if (empty($this->chmod_info))
+ {
+ if (!function_exists('fileowner') || !function_exists('filegroup'))
+ {
+ $this->chmod_info['process'] = false;
+ }
+ else
+ {
+ $common_php_owner = @fileowner(__FILE__);
+ $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_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
+ if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group)
+ {
+ $this->chmod_info['process'] = false;
+ }
+ else
+ {
+ $this->chmod_info = array(
+ 'process' => true,
+ 'common_owner' => $common_php_owner,
+ 'common_group' => $common_php_group,
+ 'php_uid' => $php_uid,
+ 'php_gids' => $php_gids,
+ );
+ }
+ }
+ }
+
+ if ($this->chmod_info['process'])
+ {
+ try
+ {
+ foreach ($this->to_iterator($files) as $file)
+ {
+ $file_uid = @fileowner($file);
+ $file_gid = @filegroup($file);
+
+ // Change owner
+ if ($file_uid !== $this->chmod_info['common_owner'])
+ {
+ $this->chown($file, $this->chmod_info['common_owner'], $recursive);
+ }
+
+ // Change group
+ if ($file_gid !== $this->chmod_info['common_group'])
+ {
+ $this->chgrp($file, $this->chmod_info['common_group'], $recursive);
+ }
+
+ clearstatcache();
+ $file_uid = @fileowner($file);
+ $file_gid = @filegroup($file);
+ }
+ }
+ catch (filesystem_exception $e)
+ {
+ $this->chmod_info['process'] = false;
+ }
+ }
+
+ // Still able to process?
+ if ($this->chmod_info['process'])
+ {
+ if ($file_uid === $this->chmod_info['php_uid'])
+ {
+ $php = 'owner';
+ }
+ else if (in_array($file_gid, $this->chmod_info['php_gids']))
+ {
+ $php = 'group';
+ }
+ else
+ {
+ // Since we are setting the everyone bit anyway, no need to do expensive operations
+ $this->chmod_info['process'] = false;
+ }
+ }
+
+ // We are not able to determine or change something
+ if (!$this->chmod_info['process'])
+ {
+ $php = 'other';
+ }
+
+ switch ($php)
+ {
+ case 'owner':
+ try
+ {
+ $this->chmod($files, $perms, $recursive, $force_chmod_link);
+ clearstatcache();
+ if ($this->is_readable($files) && $this->is_writable($files))
+ {
+ break;
+ }
+ }
+ catch (filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ case 'group':
+ try
+ {
+ $this->chmod($files, $perms, $recursive, $force_chmod_link);
+ clearstatcache();
+ if ((!($perms & self::CHMOD_READ) || $this->is_readable($files, $recursive)) && (!($perms & self::CHMOD_WRITE) || $this->is_writable($files, $recursive)))
+ {
+ break;
+ }
+ }
+ catch (filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ case 'other':
+ default:
+ $this->chmod($files, $perms, $recursive, $force_chmod_link);
+ break;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function realpath($path)
+ {
+ if (!function_exists('realpath'))
+ {
+ return $this->phpbb_own_realpath($path);
+ }
+
+ $realpath = realpath($path);
+
+ // Strangely there are provider not disabling realpath but returning strange values. :o
+ // We at least try to cope with them.
+ if ((!$this->is_absolute_path($path) && $realpath === $path) || $realpath === false)
+ {
+ return $this->phpbb_own_realpath($path);
+ }
+
+ // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
+ if (substr($realpath, -1) === DIRECTORY_SEPARATOR)
+ {
+ $realpath = substr($realpath, 0, -1);
+ }
+
+ return $realpath;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function remove($files)
+ {
+ try
+ {
+ $this->symfony_filesystem->remove($files);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ // Try to recover filename
+ // By the time this is written that is at the end of the message
+ $error = trim($e->getMessage());
+ $file = substr($error, strrpos($error, ' '));
+
+ throw new filesystem_exception('CANNOT_DELETE_FILES', $file, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rename($origin, $target, $overwrite = false)
+ {
+ try
+ {
+ $this->symfony_filesystem->rename($origin, $target, $overwrite);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ $msg = $e->getMessage();
+ $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"'));
+
+ throw new filesystem_exception('CANNOT_RENAME_FILE', $filename, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function symlink($origin_dir, $target_dir, $copy_on_windows = false)
+ {
+ try
+ {
+ $this->symfony_filesystem->symlink($origin_dir, $target_dir, $copy_on_windows);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ throw new filesystem_exception('CANNOT_CREATE_SYMLINK', $origin_dir, array(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function touch($files, $time = null, $access_time = null)
+ {
+ try
+ {
+ $this->symfony_filesystem->touch($files, $time, $access_time);
+ }
+ catch (\Symfony\Component\Filesystem\Exception\IOException $e)
+ {
+ // Try to recover filename
+ // By the time this is written that is at the end of the message
+ $error = trim($e->getMessage());
+ $file = substr($error, strrpos($error, ' '));
+
+ throw new filesystem_exception('CANNOT_TOUCH_FILES', $file, array(), $e);
+ }
+ }
+
+ /**
+ * phpBB's implementation of is_writable
+ *
+ * @todo Investigate if is_writable is still buggy
+ *
+ * @param string $file file/directory to check if writable
+ *
+ * @return bool true if the given path is writable
+ */
+ protected function phpbb_is_writable($file)
+ {
+ if (file_exists($file))
+ {
+ // Canonicalise path to absolute path
+ $file = $this->realpath($file);
+
+ if (is_dir($file))
+ {
+ // Test directory by creating a file inside the directory
+ $result = @tempnam($file, 'i_w');
+
+ if (is_string($result) && file_exists($result))
+ {
+ unlink($result);
+
+ // Ensure the file is actually in the directory (returned realpathed)
+ return (strpos($result, $file) === 0) ? true : false;
+ }
+ }
+ else
+ {
+ $handle = @fopen($file, 'c');
+
+ if (is_resource($handle))
+ {
+ fclose($handle);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // file does not exist test if we can write to the directory
+ $dir = dirname($file);
+
+ if (file_exists($dir) && is_dir($dir) && $this->phpbb_is_writable($dir))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Try to resolve real path when PHP's realpath failes to do so
+ *
+ * @param string $path
+ * @return bool|string
+ */
+ protected function phpbb_own_realpath($path)
+ {
+ // Replace all directory separators with '/'
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+
+ $is_absolute_path = false;
+ $path_prefix = '';
+
+ if ($this->is_absolute_path($path))
+ {
+ $is_absolute_path = true;
+ }
+ else
+ {
+ // Resolve working directory and store it
+ if (is_null($this->working_directory))
+ {
+ if (function_exists('getcwd'))
+ {
+ $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', getcwd());
+ }
+
+ //
+ // From this point on we really just guessing
+ // If chdir were called we screwed
+ //
+ 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']));
+ }
+ else
+ {
+ //
+ // Assuming that the working directory is phpBB root
+ // we could use this as a fallback, when phpBB will use controllers
+ // everywhere this will be a safe assumption
+ //
+ //$dir_parts = explode(DIRECTORY_SEPARATOR, __DIR__);
+ //$namespace_parts = explode('\\', trim(__NAMESPACE__, '\\'));
+
+ //$namespace_part_count = sizeof($namespace_parts);
+
+ // Check if we still loading from root
+ //if (array_slice($dir_parts, -$namespace_part_count) === $namespace_parts)
+ //{
+ // $this->working_directory = implode('/', array_slice($dir_parts, 0, -$namespace_part_count));
+ //}
+ //else
+ //{
+ // $this->working_directory = false;
+ //}
+
+ $this->working_directory = false;
+ }
+ }
+
+ if ($this->working_directory !== false)
+ {
+ $is_absolute_path = true;
+ $path = $this->working_directory . '/' . $path;
+ }
+ }
+
+ if ($is_absolute_path)
+ {
+ if (defined('PHP_WINDOWS_VERSION_MAJOR'))
+ {
+ $path_prefix = $path[0] . ':';
+ $path = substr($path, 2);
+ }
+ else
+ {
+ $path_prefix = '';
+ }
+ }
+
+ $resolved_path = $this->resolve_path($path, $path_prefix, $is_absolute_path);
+ if ($resolved_path === false)
+ {
+ return false;
+ }
+
+ if (!@file_exists($resolved_path) || (!@is_dir($resolved_path . '/') && !is_file($resolved_path)))
+ {
+ return false;
+ }
+
+ // Return OS specific directory separators
+ $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved_path);
+
+ // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
+ if (substr($resolved, -1) === DIRECTORY_SEPARATOR)
+ {
+ return substr($resolved, 0, -1);
+ }
+
+ return $resolved;
+ }
+
+ /**
+ * Convert file(s) to \Traversable object
+ *
+ * This is the same function as Symfony's toIterator, but that is private
+ * so we cannot use it.
+ *
+ * @param string|array|\Traversable $files filename/list of filenames
+ * @return \Traversable
+ */
+ protected function to_iterator($files)
+ {
+ if (!$files instanceof \Traversable)
+ {
+ $files = new \ArrayObject(is_array($files) ? $files : array($files));
+ }
+
+ return $files;
+ }
+
+ /**
+ * Try to resolve symlinks in path
+ *
+ * @param string $path The path to resolve
+ * @param string $prefix The path prefix (on windows the drive letter)
+ * @param bool $absolute Whether or not the path is absolute
+ * @param bool $return_array Whether or not to return path parts
+ *
+ * @return string|array|bool returns the resolved path or an array of parts of the path if $return_array is true
+ * or false if path cannot be resolved
+ */
+ protected function resolve_path($path, $prefix = '', $absolute = false, $return_array = false)
+ {
+ if ($return_array)
+ {
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+ }
+
+ trim ($path, '/');
+ $path_parts = explode('/', $path);
+ $resolved = array();
+ $resolved_path = $prefix;
+ $file_found = false;
+
+ foreach ($path_parts as $path_part)
+ {
+ if ($file_found)
+ {
+ return false;
+ }
+
+ if (empty($path_part) || ($path_part === '.' && ($absolute || !empty($resolved))))
+ {
+ continue;
+ }
+ else if ($absolute && $path_part === '..')
+ {
+ if (empty($resolved))
+ {
+ // No directories above root
+ return false;
+ }
+
+ array_pop($resolved);
+ $resolved_path = false;
+ }
+ else if ($path_part === '..' && !empty($resolved) && !in_array($resolved[sizeof($resolved) - 1], array('.', '..')))
+ {
+ array_pop($resolved);
+ $resolved_path = false;
+ }
+ else
+ {
+ if ($resolved_path === false)
+ {
+ if (empty($resolved))
+ {
+ $resolved_path = ($absolute) ? $prefix . '/' . $path_part : $path_part;
+ }
+ else
+ {
+ $tmp_array = $resolved;
+ if ($absolute)
+ {
+ array_unshift($tmp_array, $prefix);
+ }
+
+ $resolved_path = implode('/', $tmp_array);
+ }
+ }
+
+ $current_path = $resolved_path . '/' . $path_part;
+
+ // Resolve symlinks
+ if (is_link($current_path))
+ {
+ if (!function_exists('readlink'))
+ {
+ return false;
+ }
+
+ $link = readlink($current_path);
+
+ // Is link has an absolute path in it?
+ if ($this->is_absolute_path($link))
+ {
+ if (defined('PHP_WINDOWS_VERSION_MAJOR'))
+ {
+ $prefix = $link[0] . ':';
+ $link = substr($link, 2);
+ }
+ else
+ {
+ $prefix = '';
+ }
+
+ $resolved = $this->resolve_path($link, $prefix, true, true);
+ $absolute = true;
+ }
+ else
+ {
+ $resolved = $this->resolve_path($resolved_path . '/' . $link, $prefix, $absolute, true);
+ }
+
+ if (!$resolved)
+ {
+ return false;
+ }
+
+ $resolved_path = false;
+ }
+ else if (is_dir($current_path . '/'))
+ {
+ $resolved[] = $path_part;
+ $resolved_path = $current_path;
+ }
+ else if (is_file($current_path))
+ {
+ $resolved[] = $path_part;
+ $resolved_path = $current_path;
+ $file_found = true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ // If at the end of the path there were a .. or .
+ // we need to build the path again.
+ // Only doing this when a string is expected in return
+ if ($resolved_path === false && $return_array === false)
+ {
+ if (empty($resolved))
+ {
+ $resolved_path = ($absolute) ? $prefix . '/' : './';
+ }
+ else
+ {
+ $tmp_array = $resolved;
+ if ($absolute)
+ {
+ array_unshift($tmp_array, $prefix);
+ }
+
+ $resolved_path = implode('/', $tmp_array);
+ }
+ }
+
+ return ($return_array) ? $resolved : $resolved_path;
+ }
+}
diff --git a/phpBB/phpbb/filesystem/filesystem_interface.php b/phpBB/phpbb/filesystem/filesystem_interface.php
new file mode 100644
index 0000000000..1093be2499
--- /dev/null
+++ b/phpBB/phpbb/filesystem/filesystem_interface.php
@@ -0,0 +1,284 @@
+<?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\filesystem;
+
+/**
+ * Interface for phpBB's filesystem service
+ */
+interface filesystem_interface
+{
+ /**
+ * chmod all permissions flag
+ *
+ * @var int
+ */
+ const CHMOD_ALL = 7;
+
+ /**
+ * chmod read permissions flag
+ *
+ * @var int
+ */
+ const CHMOD_READ = 4;
+
+ /**
+ * chmod write permissions flag
+ *
+ * @var int
+ */
+ const CHMOD_WRITE = 2;
+
+ /**
+ * chmod execute permissions flag
+ *
+ * @var int
+ */
+ const CHMOD_EXECUTE = 1;
+
+ /**
+ * Change owner group of files/directories
+ *
+ * @param string|array|\Traversable $files The file(s)/directorie(s) to change group
+ * @param string $group The group that should own the files/directories
+ * @param bool $recursive If the group should be changed recursively
+ * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function chgrp($files, $group, $recursive = false);
+
+ /**
+ * Global function for chmodding directories and files for internal use
+ *
+ * The function accepts filesystem_interface::CHMOD_ flags in the permission argument
+ * or the user can specify octal values (or any integer if it makes sense). All directories will have
+ * an execution bit appended, if the user group (owner, group or other) has any bit specified.
+ *
+ * @param string|array|\Traversable $files The file/directory to be chmodded
+ * @param int $perms Permissions to set
+ * @param bool $recursive If the permissions should be changed recursively
+ * @param bool $force_chmod_link Try to apply permissions to symlinks as well
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false);
+
+ /**
+ * Change owner group of files/directories
+ *
+ * @param string|array|\Traversable $files The file(s)/directorie(s) to change group
+ * @param string $user The owner user name
+ * @param bool $recursive Whether change the owner recursively or not
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function chown($files, $user, $recursive = false);
+
+ /**
+ * Eliminates useless . and .. components from specified path.
+ *
+ * @param string $path Path to clean
+ *
+ * @return string Cleaned path
+ */
+ public function clean_path($path);
+
+ /**
+ * Copies a file.
+ *
+ * This method only copies the file if the origin file is newer than the target file.
+ *
+ * By default, if the target already exists, it is not overridden.
+ *
+ * @param string $origin_file The original filename
+ * @param string $target_file The target filename
+ * @param bool $override Whether to override an existing file or not
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be copied
+ */
+ public function copy($origin_file, $target_file, $override = false);
+
+ /**
+ * Atomically dumps content into a file.
+ *
+ * @param string $filename The file to be written to.
+ * @param string $content The data to write into the file.
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be written
+ */
+ public function dump_file($filename, $content);
+
+ /**
+ * Checks the existence of files or directories.
+ *
+ * @param string|array|\Traversable $files files/directories to check
+ *
+ * @return bool Returns true if all files/directories exist, false otherwise
+ */
+ public function exists($files);
+
+ /**
+ * Checks if a path is absolute or not
+ *
+ * @param string $path Path to check
+ *
+ * @return bool true if the path is absolute, false otherwise
+ */
+ public function is_absolute_path($path);
+
+ /**
+ * Checks if files/directories are readable
+ *
+ * @param string|array|\Traversable $files files/directories to check
+ * @param bool $recursive Whether or not directories should be checked recursively
+ *
+ * @return bool True when the files/directories are readable, otherwise false.
+ */
+ public function is_readable($files, $recursive = false);
+
+ /**
+ * Test if a file/directory is writable
+ *
+ * @param string|array|\Traversable $files files/directories to perform write test on
+ * @param bool $recursive Whether or not directories should be checked recursively
+ *
+ * @return bool True when the files/directories are writable, otherwise false.
+ */
+ public function is_writable($files, $recursive = false);
+
+ /**
+ * Given an existing path, convert it to a path relative to a given starting path
+ *
+ * @param string $end_path Absolute path of target
+ * @param string $start_path Absolute path where traversal begins
+ *
+ * @return string Path of target relative to starting path
+ */
+ public function make_path_relative($end_path, $start_path);
+
+ /**
+ * Mirrors a directory to another.
+ *
+ * @param string $origin_dir The origin directory
+ * @param string $target_dir The target directory
+ * @param \Traversable $iterator A Traversable instance
+ * @param array $options An array of boolean options
+ * Valid options are:
+ * - $options['override'] Whether to override an existing file on copy or not (see copy())
+ * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
+ * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be copied.
+ * The filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array());
+
+ /**
+ * Creates a directory recursively.
+ *
+ * @param string|array|\Traversable $dirs The directory path
+ * @param int $mode The directory mode
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception On any directory creation failure
+ * The filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function mkdir($dirs, $mode = 0777);
+
+ /**
+ * Global function for chmodding directories and files for internal use
+ *
+ * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
+ * The function determines owner and group from common.php file and sets the same to the provided file.
+ * The function uses bit fields to build the permissions.
+ * The function sets the appropiate execute bit on directories.
+ *
+ * Supported constants representing bit fields are:
+ *
+ * filesystem_interface::CHMOD_ALL - all permissions (7)
+ * filesystem_interface::CHMOD_READ - read permission (4)
+ * filesystem_interface::CHMOD_WRITE - write permission (2)
+ * filesystem_interface::CHMOD_EXECUTE - execute permission (1)
+ *
+ * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions.
+ *
+ * @param string|array|\Traversable $file The file/directory to be chmodded
+ * @param int $perms Permissions to set
+ * @param bool $recursive If the permissions should be changed recursively
+ * @param bool $force_chmod_link Try to apply permissions to symlinks as well
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function phpbb_chmod($file, $perms = null, $recursive = false, $force_chmod_link = false);
+
+ /**
+ * A wrapper for PHP's realpath
+ *
+ * Try to resolve realpath when PHP's realpath is not available, or
+ * known to be buggy.
+ *
+ * @param string $path Path to resolve
+ *
+ * @return string Resolved path
+ */
+ public function realpath($path);
+
+ /**
+ * Removes files or directories.
+ *
+ * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When removal fails.
+ * The filename which triggered the error can be
+ * retrieved by filesystem_exception::get_filename()
+ */
+ public function remove($files);
+
+ /**
+ * Renames a file or a directory.
+ *
+ * @param string $origin The origin filename or directory
+ * @param string $target The new filename or directory
+ * @param bool $overwrite Whether to overwrite the target if it already exists
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When target file or directory already exists,
+ * or origin cannot be renamed.
+ */
+ public function rename($origin, $target, $overwrite = false);
+
+ /**
+ * Creates a symbolic link or copy a directory.
+ *
+ * @param string $origin_dir The origin directory path
+ * @param string $target_dir The symbolic link name
+ * @param bool $copy_on_windows Whether to copy files if on Windows
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When symlink fails
+ */
+ public function symlink($origin_dir, $target_dir, $copy_on_windows = false);
+
+ /**
+ * Sets access and modification time of file.
+ *
+ * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
+ * @param int $time The touch time as a Unix timestamp
+ * @param int $access_time The access time as a Unix timestamp
+ *
+ * @throws \phpbb\filesystem\exception\filesystem_exception When touch fails
+ */
+ public function touch($files, $time = null, $access_time = null);
+}
diff --git a/phpBB/phpbb/finder.php b/phpBB/phpbb/finder.php
index 28f28825ba..58bc27084e 100644
--- a/phpBB/phpbb/finder.php
+++ b/phpBB/phpbb/finder.php
@@ -48,14 +48,14 @@ class finder
/**
* Creates a new finder instance with its dependencies
*
- * @param \phpbb\filesystem $filesystem Filesystem instance
+ * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem instance
* @param string $phpbb_root_path Path to the phpbb root directory
* @param \phpbb\cache\driver\driver_interface $cache A cache instance or null
* @param string $php_ext php file extension
* @param string $cache_name The name of the cache variable, defaults to
* _ext_finder
*/
- public function __construct(\phpbb\filesystem $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder')
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder')
{
$this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path;
diff --git a/phpBB/phpbb/group/helper.php b/phpBB/phpbb/group/helper.php
new file mode 100644
index 0000000000..5befddfc53
--- /dev/null
+++ b/phpBB/phpbb/group/helper.php
@@ -0,0 +1,40 @@
+<?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\group;
+
+class helper
+{
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\language\language $language Language object
+ */
+ public function __construct(\phpbb\language\language $language)
+ {
+ $this->language = $language;
+ }
+
+ /**
+ * @param $group_name string The stored group name
+ *
+ * @return string Group name or translated group name if it exists
+ */
+ public function get_name($group_name)
+ {
+ return $this->language->is_set('G_' . utf8_strtoupper($group_name)) ? $this->language->lang('G_' . utf8_strtoupper($group_name)) : $group_name;
+ }
+}
diff --git a/phpBB/phpbb/help/controller/bbcode.php b/phpBB/phpbb/help/controller/bbcode.php
new file mode 100644
index 0000000000..e16f99023d
--- /dev/null
+++ b/phpBB/phpbb/help/controller/bbcode.php
@@ -0,0 +1,85 @@
+<?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\help\controller;
+
+/**
+ * BBCode help page
+ */
+class bbcode extends controller
+{
+ /**
+ * @return string The title of the page
+ */
+ public function display()
+ {
+ $this->language->add_lang('help/bbcode');
+
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_INTRO',
+ false,
+ array(
+ 'HELP_BBCODE_INTRO_BBCODE_QUESTION' => 'HELP_BBCODE_INTRO_BBCODE_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_TEXT',
+ false,
+ array(
+ 'HELP_BBCODE_TEXT_BASIC_QUESTION' => 'HELP_BBCODE_TEXT_BASIC_ANSWER',
+ 'HELP_BBCODE_TEXT_COLOR_QUESTION' => 'HELP_BBCODE_TEXT_COLOR_ANSWER',
+ 'HELP_BBCODE_TEXT_COMBINE_QUESTION' => 'HELP_BBCODE_TEXT_COMBINE_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_QUOTES',
+ false,
+ array(
+ 'HELP_BBCODE_QUOTES_TEXT_QUESTION' => 'HELP_BBCODE_QUOTES_TEXT_ANSWER',
+ 'HELP_BBCODE_QUOTES_CODE_QUESTION' => 'HELP_BBCODE_QUOTES_CODE_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_LISTS',
+ false,
+ array(
+ 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => 'HELP_BBCODE_LISTS_UNORDERER_ANSWER',
+ 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => 'HELP_BBCODE_LISTS_ORDERER_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_LINKS',
+ true,
+ array(
+ 'HELP_BBCODE_LINKS_BASIC_QUESTION' => 'HELP_BBCODE_LINKS_BASIC_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_IMAGES',
+ false,
+ array(
+ 'HELP_BBCODE_IMAGES_BASIC_QUESTION' => 'HELP_BBCODE_IMAGES_BASIC_ANSWER',
+ 'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => 'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_BBCODE_BLOCK_OTHERS',
+ false,
+ array(
+ 'HELP_BBCODE_OTHERS_CUSTOM_QUESTION' => 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER',
+ )
+ );
+
+ return $this->language->lang('BBCODE_GUIDE');
+ }
+}
diff --git a/phpBB/phpbb/help/controller/controller.php b/phpBB/phpbb/help/controller/controller.php
new file mode 100644
index 0000000000..29494205a9
--- /dev/null
+++ b/phpBB/phpbb/help/controller/controller.php
@@ -0,0 +1,76 @@
+<?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\help\controller;
+
+/**
+ * BBCode help page
+ */
+abstract class controller
+{
+ /** @var \phpbb\controller\helper */
+ protected $helper;
+
+ /** @var \phpbb\help\manager */
+ protected $manager;
+
+ /** @var \phpbb\template\template */
+ protected $template;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var string */
+ protected $root_path;
+
+ /** @var string */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\controller\helper $helper
+ * @param \phpbb\help\manager $manager
+ * @param \phpbb\template\template $template
+ * @param \phpbb\language\language $language
+ * @param string $root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\controller\helper $helper, \phpbb\help\manager $manager, \phpbb\template\template $template, \phpbb\language\language $language, $root_path, $php_ext)
+ {
+ $this->helper = $helper;
+ $this->manager = $manager;
+ $this->template = $template;
+ $this->language = $language;
+ $this->root_path = $root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * @return string
+ */
+ abstract protected function display();
+
+ public function handle()
+ {
+ $title = $this->display();
+
+ $this->template->assign_vars(array(
+ 'L_FAQ_TITLE' => $title,
+ 'S_IN_FAQ' => true,
+ ));
+
+ make_jumpbox(append_sid("{$this->root_path}viewforum.{$this->php_ext}"));
+ return $this->helper->render('faq_body.html', $title);
+ }
+}
diff --git a/phpBB/phpbb/help/controller/faq.php b/phpBB/phpbb/help/controller/faq.php
new file mode 100644
index 0000000000..5e45cfe667
--- /dev/null
+++ b/phpBB/phpbb/help/controller/faq.php
@@ -0,0 +1,165 @@
+<?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\help\controller;
+
+/**
+ * FAQ help page
+ */
+class faq extends controller
+{
+ /**
+ * @return string The title of the page
+ */
+ public function display()
+ {
+ $this->language->add_lang('help/faq');
+
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_LOGIN',
+ false,
+ array(
+ 'HELP_FAQ_LOGIN_REGISTER_QUESTION' => 'HELP_FAQ_LOGIN_REGISTER_ANSWER',
+ 'HELP_FAQ_LOGIN_COPPA_QUESTION' => 'HELP_FAQ_LOGIN_COPPA_ANSWER',
+ 'HELP_FAQ_LOGIN_CANNOT_REGISTER_QUESTION' => 'HELP_FAQ_LOGIN_CANNOT_REGISTER_ANSWER',
+ 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_QUESTION' => 'HELP_FAQ_LOGIN_REGISTER_CONFIRM_ANSWER',
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_QUESTION' => 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANSWER',
+ 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_QUESTION' => 'HELP_FAQ_LOGIN_CANNOT_LOGIN_ANYMORE_ANSWER',
+ 'HELP_FAQ_LOGIN_LOST_PASSWORD_QUESTION' => 'HELP_FAQ_LOGIN_LOST_PASSWORD_ANSWER',
+ 'HELP_FAQ_LOGIN_AUTO_LOGOUT_QUESTION' => 'HELP_FAQ_LOGIN_AUTO_LOGOUT_ANSWER',
+ 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_USERSETTINGS',
+ false,
+ array(
+ 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_QUESTION' => 'HELP_FAQ_USERSETTINGS_CHANGE_SETTINGS_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_QUESTION' => 'HELP_FAQ_USERSETTINGS_HIDE_ONLINE_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_TIMEZONE_QUESTION' => 'HELP_FAQ_USERSETTINGS_TIMEZONE_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_SERVERTIME_QUESTION' => 'HELP_FAQ_USERSETTINGS_SERVERTIME_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_LANGUAGE_QUESTION' => 'HELP_FAQ_USERSETTINGS_LANGUAGE_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_AVATAR_QUESTION' => 'HELP_FAQ_USERSETTINGS_AVATAR_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_QUESTION' => 'HELP_FAQ_USERSETTINGS_AVATAR_DISPLAY_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_RANK_QUESTION' => 'HELP_FAQ_USERSETTINGS_RANK_ANSWER',
+ 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_QUESTION' => 'HELP_FAQ_USERSETTINGS_EMAIL_LOGIN_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_POSTING',
+ false,
+ array(
+ 'HELP_FAQ_POSTING_CREATE_QUESTION' => 'HELP_FAQ_POSTING_CREATE_ANSWER',
+ 'HELP_FAQ_POSTING_EDIT_DELETE_QUESTION' => 'HELP_FAQ_POSTING_EDIT_DELETE_ANSWER',
+ 'HELP_FAQ_POSTING_SIGNATURE_QUESTION' => 'HELP_FAQ_POSTING_SIGNATURE_ANSWER',
+ 'HELP_FAQ_POSTING_POLL_CREATE_QUESTION' => 'HELP_FAQ_POSTING_POLL_CREATE_ANSWER',
+ 'HELP_FAQ_POSTING_POLL_ADD_QUESTION' => 'HELP_FAQ_POSTING_POLL_ADD_ANSWER',
+ 'HELP_FAQ_POSTING_POLL_EDIT_QUESTION' => 'HELP_FAQ_POSTING_POLL_EDIT_ANSWER',
+ 'HELP_FAQ_POSTING_FORUM_RESTRICTED_QUESTION' => 'HELP_FAQ_POSTING_FORUM_RESTRICTED_ANSWER',
+ 'HELP_FAQ_POSTING_NO_ATTACHMENTS_QUESTION' => 'HELP_FAQ_POSTING_NO_ATTACHMENTS_ANSWER',
+ 'HELP_FAQ_POSTING_WARNING_QUESTION' => 'HELP_FAQ_POSTING_WARNING_ANSWER',
+ 'HELP_FAQ_POSTING_REPORT_QUESTION' => 'HELP_FAQ_POSTING_REPORT_ANSWER',
+ 'HELP_FAQ_POSTING_DRAFT_QUESTION' => 'HELP_FAQ_POSTING_DRAFT_ANSWER',
+ 'HELP_FAQ_POSTING_QUEUE_QUESTION' => 'HELP_FAQ_POSTING_QUEUE_ANSWER',
+ 'HELP_FAQ_POSTING_BUMP_QUESTION' => 'HELP_FAQ_POSTING_BUMP_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_FORMATTING',
+ false,
+ array(
+ 'HELP_FAQ_FORMATTING_BBOCDE_QUESTION' => 'HELP_FAQ_FORMATTING_BBOCDE_ANSWER',
+ 'HELP_FAQ_FORMATTING_HTML_QUESTION' => 'HELP_FAQ_FORMATTING_HTML_ANSWER',
+ 'HELP_FAQ_FORMATTING_SMILIES_QUESTION' => 'HELP_FAQ_FORMATTING_SMILIES_ANSWER',
+ 'HELP_FAQ_FORMATTING_IMAGES_QUESTION' => 'HELP_FAQ_FORMATTING_IMAGES_ANSWER',
+ 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_QUESTION' => 'HELP_FAQ_FORMATTING_GLOBAL_ANNOUNCE_ANSWER',
+ 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_QUESTION' => 'HELP_FAQ_FORMATTING_ANNOUNCEMENT_ANSWER',
+ 'HELP_FAQ_FORMATTING_STICKIES_QUESTION' => 'HELP_FAQ_FORMATTING_STICKIES_ANSWER',
+ 'HELP_FAQ_FORMATTING_LOCKED_QUESTION' => 'HELP_FAQ_FORMATTING_LOCKED_ANSWER',
+ 'HELP_FAQ_FORMATTING_ICONS_QUESTION' => 'HELP_FAQ_FORMATTING_ICONS_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_GROUPS',
+ true,
+ array(
+ 'HELP_FAQ_GROUPS_ADMINISTRATORS_QUESTION' => 'HELP_FAQ_GROUPS_ADMINISTRATORS_ANSWER',
+ 'HELP_FAQ_GROUPS_MODERATORS_QUESTION' => 'HELP_FAQ_GROUPS_MODERATORS_ANSWER',
+ 'HELP_FAQ_GROUPS_USERGROUPS_QUESTION' => 'HELP_FAQ_GROUPS_USERGROUPS_ANSWER',
+ 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_QUESTION' => 'HELP_FAQ_GROUPS_USERGROUPS_JOIN_ANSWER',
+ 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_QUESTION' => 'HELP_FAQ_GROUPS_USERGROUPS_LEAD_ANSWER',
+ 'HELP_FAQ_GROUPS_COLORS_QUESTION' => 'HELP_FAQ_GROUPS_COLORS_ANSWER',
+ 'HELP_FAQ_GROUPS_DEFAULT_QUESTION' => 'HELP_FAQ_GROUPS_DEFAULT_ANSWER',
+ 'HELP_FAQ_GROUPS_TEAM_QUESTION' => 'HELP_FAQ_GROUPS_TEAM_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_PMS',
+ false,
+ array(
+ 'HELP_FAQ_PMS_CANNOT_SEND_QUESTION' => 'HELP_FAQ_PMS_CANNOT_SEND_ANSWER',
+ 'HELP_FAQ_PMS_UNWANTED_QUESTION' => 'HELP_FAQ_PMS_UNWANTED_ANSWER',
+ 'HELP_FAQ_PMS_SPAM_QUESTION' => 'HELP_FAQ_PMS_SPAM_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_FRIENDS',
+ false,
+ array(
+ 'HELP_FAQ_FRIENDS_BASIC_QUESTION' => 'HELP_FAQ_FRIENDS_BASIC_ANSWER',
+ 'HELP_FAQ_FRIENDS_MANAGE_QUESTION' => 'HELP_FAQ_FRIENDS_MANAGE_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_SEARCH',
+ false,
+ array(
+ 'HELP_FAQ_SEARCH_FORUM_QUESTION' => 'HELP_FAQ_SEARCH_FORUM_ANSWER',
+ 'HELP_FAQ_SEARCH_NO_RESULT_QUESTION' => 'HELP_FAQ_SEARCH_NO_RESULT_ANSWER',
+ 'HELP_FAQ_SEARCH_BLANK_QUESTION' => 'HELP_FAQ_SEARCH_BLANK_ANSWER',
+ 'HELP_FAQ_SEARCH_MEMBERS_QUESTION' => 'HELP_FAQ_SEARCH_MEMBERS_ANSWER',
+ 'HELP_FAQ_SEARCH_OWN_QUESTION' => 'HELP_FAQ_SEARCH_OWN_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_BOOKMARKS',
+ false,
+ array(
+ 'HELP_FAQ_BOOKMARKS_DIFFERENCE_QUESTION' => 'HELP_FAQ_BOOKMARKS_DIFFERENCE_ANSWER',
+ 'HELP_FAQ_BOOKMARKS_TOPIC_QUESTION' => 'HELP_FAQ_BOOKMARKS_TOPIC_ANSWER',
+ 'HELP_FAQ_BOOKMARKS_FORUM_QUESTION' => 'HELP_FAQ_BOOKMARKS_FORUM_ANSWER',
+ 'HELP_FAQ_BOOKMARKS_REMOVE_QUESTION' => 'HELP_FAQ_BOOKMARKS_REMOVE_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_ATTACHMENTS',
+ false,
+ array(
+ 'HELP_FAQ_ATTACHMENTS_ALLOWED_QUESTION' => 'HELP_FAQ_ATTACHMENTS_ALLOWED_ANSWER',
+ 'HELP_FAQ_ATTACHMENTS_OWN_QUESTION' => 'HELP_FAQ_ATTACHMENTS_OWN_ANSWER',
+ )
+ );
+ $this->manager->add_block(
+ 'HELP_FAQ_BLOCK_ISSUES',
+ false,
+ array(
+ 'HELP_FAQ_ISSUES_WHOIS_PHPBB_QUESTION' => 'HELP_FAQ_ISSUES_WHOIS_PHPBB_ANSWER',
+ 'HELP_FAQ_ISSUES_FEATURE_QUESTION' => 'HELP_FAQ_ISSUES_FEATURE_ANSWER',
+ 'HELP_FAQ_ISSUES_LEGAL_QUESTION' => 'HELP_FAQ_ISSUES_LEGAL_ANSWER',
+ 'HELP_FAQ_ISSUES_ADMIN_QUESTION' => 'HELP_FAQ_ISSUES_ADMIN_ANSWER',
+ )
+ );
+
+ return $this->language->lang('FAQ_EXPLAIN');
+ }
+}
diff --git a/phpBB/phpbb/help/controller/help.php b/phpBB/phpbb/help/controller/help.php
new file mode 100644
index 0000000000..9cc3b0c8b4
--- /dev/null
+++ b/phpBB/phpbb/help/controller/help.php
@@ -0,0 +1,160 @@
+<?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\help\controller;
+
+use phpbb\exception\http_exception;
+
+class help
+{
+ /** @var \phpbb\controller\helper */
+ protected $helper;
+
+ /** @var \phpbb\event\dispatcher_interface */
+ protected $dispatcher;
+
+ /** @var \phpbb\template\template */
+ protected $template;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var string */
+ protected $root_path;
+
+ /** @var string */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\controller\helper $helper
+ * @param \phpbb\event\dispatcher_interface $dispatcher
+ * @param \phpbb\template\template $template
+ * @param \phpbb\user $user
+ * @param string $root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\controller\helper $helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\template\template $template, \phpbb\user $user, $root_path, $php_ext)
+ {
+ $this->helper = $helper;
+ $this->dispatcher = $dispatcher;
+ $this->template = $template;
+ $this->user = $user;
+ $this->root_path = $root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Controller for /help/{mode} routes
+ *
+ * @param string $mode
+ * @return \Symfony\Component\HttpFoundation\Response A Symfony Response object
+ * @throws http_exception when the $mode is not known by any extension
+ */
+ public function handle($mode)
+ {
+ switch ($mode)
+ {
+ case 'faq':
+ case 'bbcode':
+ $page_title = ($mode === 'faq') ? $this->user->lang['FAQ_EXPLAIN'] : $this->user->lang['BBCODE_GUIDE'];
+ $this->user->add_lang($mode, false, true);
+ break;
+
+ default:
+ $page_title = $this->user->lang['FAQ_EXPLAIN'];
+ $ext_name = $lang_file = '';
+
+ /**
+ * You can use this event display a custom help page
+ *
+ * @event core.faq_mode_validation
+ * @var string page_title Title of the page
+ * @var string mode FAQ that is going to be displayed
+ * @var string lang_file Language file containing the help data
+ * @var string ext_name Vendor and extension name where the help
+ * language file can be loaded from
+ * @since 3.1.4-RC1
+ */
+ $vars = array(
+ 'page_title',
+ 'mode',
+ 'lang_file',
+ 'ext_name',
+ );
+ extract($this->dispatcher->trigger_event('core.faq_mode_validation', compact($vars)));
+
+ if ($ext_name === '' || $lang_file === '')
+ {
+ throw new http_exception(404, 'Not Found');
+ }
+
+ $this->user->add_lang($lang_file, false, true, $ext_name);
+ break;
+
+ }
+
+ $this->template->assign_vars(array(
+ 'L_FAQ_TITLE' => $page_title,
+ 'S_IN_FAQ' => true,
+ ));
+
+ $this->assign_to_template($this->user->help);
+
+ make_jumpbox(append_sid("{$this->root_path}viewforum.{$this->php_ext}"));
+ return $this->helper->render('faq_body.html', $page_title);
+ }
+
+ /**
+ * Assigns the help data to the template blocks
+ *
+ * @param array $help_data
+ * @return null
+ */
+ protected function assign_to_template(array $help_data)
+ {
+ // Pull the array data from the lang pack
+ $switch_column = $found_switch = false;
+ foreach ($help_data as $help_ary)
+ {
+ if ($help_ary[0] == '--')
+ {
+ if ($help_ary[1] == '--')
+ {
+ $switch_column = true;
+ $found_switch = true;
+ continue;
+ }
+
+ $this->template->assign_block_vars('faq_block', array(
+ 'BLOCK_TITLE' => $help_ary[1],
+ 'SWITCH_COLUMN' => $switch_column,
+ ));
+
+ if ($switch_column)
+ {
+ $switch_column = false;
+ }
+ continue;
+ }
+
+ $this->template->assign_block_vars('faq_block.faq_row', array(
+ 'FAQ_QUESTION' => $help_ary[0],
+ 'FAQ_ANSWER' => $help_ary[1],
+ ));
+ }
+
+ $this->template->assign_var('SWITCH_COLUMN_MANUALLY', !$found_switch);
+ }
+}
diff --git a/phpBB/phpbb/help/manager.php b/phpBB/phpbb/help/manager.php
new file mode 100644
index 0000000000..39f52d343b
--- /dev/null
+++ b/phpBB/phpbb/help/manager.php
@@ -0,0 +1,137 @@
+<?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\help;
+
+/**
+ * Class help page manager
+ */
+class manager
+{
+ /** @var \phpbb\event\dispatcher */
+ protected $dispatcher;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\template\template */
+ protected $template;
+
+ /** @var bool */
+ protected $switched_column;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\event\dispatcher $dispatcher
+ * @param \phpbb\language\language $language
+ * @param \phpbb\template\template $template
+ */
+ public function __construct(\phpbb\event\dispatcher $dispatcher, \phpbb\language\language $language, \phpbb\template\template $template)
+ {
+ $this->dispatcher = $dispatcher;
+ $this->language = $language;
+ $this->template = $template;
+ }
+
+ /**
+ * Add a new faq block
+ *
+ * @param string $block_name Name or language key with the name of the block
+ * @param bool $switch_column Switch the column of the menu
+ * @param array $questions Array of frequently asked questions
+ */
+ public function add_block($block_name, $switch_column = false, $questions = array())
+ {
+ /**
+ * You can use this event to add a block before the current one.
+ *
+ * @event core.help_manager_add_block_before
+ * @var string block_name Language key of the block headline
+ * @var bool switch_column Should we switch the menu column before this headline
+ * @var array questions Array with questions
+ * @since 3.2.0-a1
+ */
+ $vars = array('block_name', 'switch_column', 'questions');
+ extract($this->dispatcher->trigger_event('core.help_manager_add_block_before', compact($vars)));
+
+ $this->template->assign_block_vars('faq_block', array(
+ 'BLOCK_TITLE' => $this->language->lang($block_name),
+ 'SWITCH_COLUMN' => !$this->switched_column && $switch_column,
+ ));
+
+ foreach ($questions as $question => $answer)
+ {
+ $this->add_question($question, $answer);
+ }
+
+ $this->switched_column = $this->switched_column || $switch_column;
+
+ /**
+ * You can use this event to add a block after the current one.
+ *
+ * @event core.help_manager_add_block_after
+ * @var string block_name Language key of the block headline
+ * @var bool switch_column Should we switch the menu column before this headline
+ * @var array questions Array with questions
+ * @since 3.2.0-a1
+ */
+ $vars = array('block_name', 'switch_column', 'questions');
+ extract($this->dispatcher->trigger_event('core.help_manager_add_block_after', compact($vars)));
+ }
+
+ /**
+ * Add a new faq question
+ *
+ * @param string $question Question or language key with the question of the block
+ * @param string $answer Answer or language key with the answer of the block
+ */
+ public function add_question($question, $answer)
+ {
+ /**
+ * You can use this event to add a question before the current one.
+ *
+ * @event core.help_manager_add_question_before
+ * @var string question Language key of the question
+ * @var string answer Language key of the answer
+ * @since 3.2.0-a1
+ */
+ $vars = array('question', 'answer');
+ extract($this->dispatcher->trigger_event('core.help_manager_add_question_before', compact($vars)));
+
+ $this->template->assign_block_vars('faq_block.faq_row', array(
+ 'FAQ_QUESTION' => $this->language->lang($question),
+ 'FAQ_ANSWER' => $this->language->lang($answer),
+ ));
+
+ /**
+ * You can use this event to add a question after the current one.
+ *
+ * @event core.help_manager_add_question_after
+ * @var string question Language key of the question
+ * @var string answer Language key of the answer
+ * @since 3.2.0-a1
+ */
+ $vars = array('question', 'answer');
+ extract($this->dispatcher->trigger_event('core.help_manager_add_question_after', compact($vars)));
+ }
+
+ /**
+ * Returns whether the block titles switched side
+ * @return bool
+ */
+ public function switched_column()
+ {
+ return $this->switched_column;
+ }
+}
diff --git a/phpBB/phpbb/hook/finder.php b/phpBB/phpbb/hook/finder.php
index a3d02d3aa0..f5a68a1370 100644
--- a/phpBB/phpbb/hook/finder.php
+++ b/phpBB/phpbb/hook/finder.php
@@ -18,8 +18,19 @@ namespace phpbb\hook;
*/
class finder
{
- protected $phpbb_root_path;
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
protected $cache;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
protected $php_ext;
/**
diff --git a/phpBB/phpbb/install/console/command/install/config/show.php b/phpBB/phpbb/install/console/command/install/config/show.php
new file mode 100644
index 0000000000..b6c11956fe
--- /dev/null
+++ b/phpBB/phpbb/install/console/command/install/config/show.php
@@ -0,0 +1,123 @@
+<?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\console\command\install\config;
+
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\installer_configuration;
+use phpbb\language\language;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Yaml;
+
+class show extends \phpbb\console\command\command
+{
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param language $language
+ * @param factory $factory
+ */
+ public function __construct(language $language, factory $factory)
+ {
+ $this->iohandler_factory = $factory;
+ $this->language = $language;
+
+ parent::__construct(new \phpbb\user($language, 'datetime'));
+ }
+
+ /**
+ *
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('install:config:show')
+ ->addArgument(
+ 'config-file',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_CONFIG_FILE'))
+ ->setDescription($this->language->lang('CLI_INSTALL_SHOW_CONFIG'))
+ ;
+ }
+
+ /**
+ * Show the validated configuration
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return null
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->iohandler_factory->set_environment('cli');
+
+ /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $style = new SymfonyStyle($input, $output);
+ $iohandler->set_style($style, $output);
+
+ $config_file = $input->getArgument('config-file');
+
+ if (!is_file($config_file))
+ {
+ $iohandler->add_error_message(array('MISSING_FILE', $config_file));
+
+ return;
+ }
+
+ try
+ {
+ $config = Yaml::parse(file_get_contents($config_file), true, false);
+ }
+ catch (ParseException $e)
+ {
+ $iohandler->add_error_message('INVALID_YAML_FILE');
+
+ return;
+ }
+
+ $processor = new Processor();
+ $configuration = new installer_configuration();
+
+ try
+ {
+ $config = $processor->processConfiguration($configuration, $config);
+ }
+ catch (Exception $e)
+ {
+ $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage());
+
+ return;
+ }
+
+ $style->block(Yaml::dump(array('installer' => $config), 10, 4, true, false));
+ }
+}
diff --git a/phpBB/phpbb/install/console/command/install/config/validate.php b/phpBB/phpbb/install/console/command/install/config/validate.php
new file mode 100644
index 0000000000..b48a1acbd4
--- /dev/null
+++ b/phpBB/phpbb/install/console/command/install/config/validate.php
@@ -0,0 +1,124 @@
+<?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\console\command\install\config;
+
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\installer_configuration;
+use phpbb\language\language;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Yaml;
+
+class validate extends \phpbb\console\command\command
+{
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param language $language
+ * @param factory $factory
+ */
+ public function __construct(language $language, factory $factory)
+ {
+ $this->iohandler_factory = $factory;
+ $this->language = $language;
+
+ parent::__construct(new \phpbb\user($language, 'datetime'));
+ }
+
+ /**
+ *
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('install:config:validate')
+ ->addArgument(
+ 'config-file',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_CONFIG_FILE'))
+ ->setDescription($this->language->lang('CLI_INSTALL_VALIDATE_CONFIG'))
+ ;
+ }
+
+ /**
+ * Validate the configuration file
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return null
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->iohandler_factory->set_environment('cli');
+
+ /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $style = new SymfonyStyle($input, $output);
+ $iohandler->set_style($style, $output);
+
+ $config_file = $input->getArgument('config-file');
+
+ if (!is_file($config_file))
+ {
+ $iohandler->add_error_message(array('MISSING_FILE', array($config_file)));
+
+ return 1;
+ }
+
+ try
+ {
+ $config = Yaml::parse(file_get_contents($config_file), true, false);
+ }
+ catch (ParseException $e)
+ {
+ $iohandler->add_error_message('INVALID_YAML_FILE');
+
+ return 1;
+ }
+
+ $processor = new Processor();
+ $configuration = new installer_configuration();
+
+ try
+ {
+ $processor->processConfiguration($configuration, $config);
+ }
+ catch (Exception $e)
+ {
+ $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage());
+
+ return 1;
+ }
+
+ $iohandler->add_success_message('CONFIGURATION_VALID');
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php
new file mode 100644
index 0000000000..de3a2e2d61
--- /dev/null
+++ b/phpBB/phpbb/install/console/command/install/install.php
@@ -0,0 +1,207 @@
+<?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\console\command\install;
+
+use phpbb\install\exception\installer_exception;
+use phpbb\install\helper\install_helper;
+use phpbb\install\helper\iohandler\cli_iohandler;
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\installer;
+use phpbb\install\installer_configuration;
+use phpbb\language\language;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Yaml;
+
+class install extends \phpbb\console\command\command
+{
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var installer
+ */
+ protected $installer;
+
+ /**
+ * @var install_helper
+ */
+ protected $install_helper;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param language $language
+ * @param factory $factory
+ * @param installer $installer
+ * @param install_helper $install_helper
+ */
+ public function __construct(language $language, factory $factory, installer $installer, install_helper $install_helper)
+ {
+ $this->iohandler_factory = $factory;
+ $this->installer = $installer;
+ $this->language = $language;
+ $this->install_helper = $install_helper;
+
+ parent::__construct(new \phpbb\user($language, 'datetime'));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('install')
+ ->addArgument(
+ 'config-file',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_CONFIG_FILE'))
+ ->setDescription($this->language->lang('CLI_INSTALL_BOARD'))
+ ;
+ }
+
+ /**
+ * Executes the command install.
+ *
+ * Install the board
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return null
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->iohandler_factory->set_environment('cli');
+
+ /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $style = new SymfonyStyle($input, $output);
+ $iohandler->set_style($style, $output);
+
+ $this->installer->set_iohandler($iohandler);
+
+ $config_file = $input->getArgument('config-file');
+
+ if ($this->install_helper->is_phpbb_installed())
+ {
+ $iohandler->add_error_message('INSTALL_PHPBB_INSTALLED');
+
+ return 1;
+ }
+
+ if (!is_file($config_file))
+ {
+ $iohandler->add_error_message(array('MISSING_FILE', $config_file));
+
+ return 1;
+ }
+
+ try
+ {
+ $config = Yaml::parse(file_get_contents($config_file), true, false);
+ }
+ catch (ParseException $e)
+ {
+ $iohandler->add_error_message(array('INVALID_YAML_FILE', $config_file));
+
+ return 1;
+ }
+
+ $processor = new Processor();
+ $configuration = new installer_configuration();
+
+ try
+ {
+ $config = $processor->processConfiguration($configuration, $config);
+ }
+ catch (Exception $e)
+ {
+ $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage());
+
+ return 1;
+ }
+
+ $this->register_configuration($iohandler, $config);
+
+ try
+ {
+ $this->installer->run();
+ }
+ catch (installer_exception $e)
+ {
+ $iohandler->add_error_message($e->getMessage());
+ return 1;
+ }
+ }
+
+ /**
+ * Register the configuration to simulate the forms.
+ *
+ * @param cli_iohandler $iohandler
+ * @param array $config
+ */
+ private function register_configuration(cli_iohandler $iohandler, $config)
+ {
+ $iohandler->set_input('admin_name', $config['admin']['name']);
+ $iohandler->set_input('admin_pass1', $config['admin']['password']);
+ $iohandler->set_input('admin_pass2', $config['admin']['password']);
+ $iohandler->set_input('board_email', $config['admin']['email']);
+ $iohandler->set_input('submit_admin', 'submit');
+
+ $iohandler->set_input('default_lang', $config['board']['lang']);
+ $iohandler->set_input('board_name', $config['board']['name']);
+ $iohandler->set_input('board_description', $config['board']['description']);
+ $iohandler->set_input('submit_board', 'submit');
+
+ $iohandler->set_input('dbms', $config['database']['dbms']);
+ $iohandler->set_input('dbhost', $config['database']['dbhost']);
+ $iohandler->set_input('dbport', $config['database']['dbport']);
+ $iohandler->set_input('dbuser', $config['database']['dbuser']);
+ $iohandler->set_input('dbpasswd', $config['database']['dbpasswd']);
+ $iohandler->set_input('dbname', $config['database']['dbname']);
+ $iohandler->set_input('table_prefix', $config['database']['table_prefix']);
+ $iohandler->set_input('submit_database', 'submit');
+
+ $iohandler->set_input('email_enable', $config['email']['enabled']);
+ $iohandler->set_input('smtp_delivery', $config['email']['smtp_delivery']);
+ $iohandler->set_input('smtp_host', $config['email']['smtp_host']);
+ $iohandler->set_input('smtp_port', $config['email']['smtp_port']);
+ $iohandler->set_input('smtp_auth', $config['email']['smtp_auth']);
+ $iohandler->set_input('smtp_user', $config['email']['smtp_user']);
+ $iohandler->set_input('smtp_pass', $config['email']['smtp_pass']);
+ $iohandler->set_input('submit_email', 'submit');
+
+ $iohandler->set_input('cookie_secure', $config['server']['cookie_secure']);
+ $iohandler->set_input('server_protocol', $config['server']['server_protocol']);
+ $iohandler->set_input('force_server_vars', $config['server']['force_server_vars']);
+ $iohandler->set_input('server_name', $config['server']['server_name']);
+ $iohandler->set_input('server_port', $config['server']['server_port']);
+ $iohandler->set_input('script_path', $config['server']['script_path']);
+ $iohandler->set_input('submit_server', 'submit');
+ }
+}
diff --git a/phpBB/phpbb/install/console/command/update/config/show.php b/phpBB/phpbb/install/console/command/update/config/show.php
new file mode 100644
index 0000000000..e462763b5d
--- /dev/null
+++ b/phpBB/phpbb/install/console/command/update/config/show.php
@@ -0,0 +1,123 @@
+<?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\console\command\update\config;
+
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\updater_configuration;
+use phpbb\language\language;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Yaml;
+
+class show extends \phpbb\console\command\command
+{
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param language $language
+ * @param factory $factory
+ */
+ public function __construct(language $language, factory $factory)
+ {
+ $this->iohandler_factory = $factory;
+ $this->language = $language;
+
+ parent::__construct(new \phpbb\user($language, 'datetime'));
+ }
+
+ /**
+ *
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('update:config:show')
+ ->addArgument(
+ 'config-file',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_CONFIG_FILE'))
+ ->setDescription($this->language->lang('CLI_INSTALL_SHOW_CONFIG'))
+ ;
+ }
+
+ /**
+ * Show the validated configuration
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return null
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->iohandler_factory->set_environment('cli');
+
+ /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $style = new SymfonyStyle($input, $output);
+ $iohandler->set_style($style, $output);
+
+ $config_file = $input->getArgument('config-file');
+
+ if (!is_file($config_file))
+ {
+ $iohandler->add_error_message(array('MISSING_FILE', $config_file));
+
+ return;
+ }
+
+ try
+ {
+ $config = Yaml::parse(file_get_contents($config_file), true, false);
+ }
+ catch (ParseException $e)
+ {
+ $iohandler->add_error_message('INVALID_YAML_FILE');
+
+ return;
+ }
+
+ $processor = new Processor();
+ $configuration = new updater_configuration();
+
+ try
+ {
+ $config = $processor->processConfiguration($configuration, $config);
+ }
+ catch (Exception $e)
+ {
+ $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage());
+
+ return;
+ }
+
+ $style->block(Yaml::dump(array('updater' => $config), 10, 4, true, false));
+ }
+}
diff --git a/phpBB/phpbb/install/console/command/update/config/validate.php b/phpBB/phpbb/install/console/command/update/config/validate.php
new file mode 100644
index 0000000000..18de5eab46
--- /dev/null
+++ b/phpBB/phpbb/install/console/command/update/config/validate.php
@@ -0,0 +1,124 @@
+<?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\console\command\update\config;
+
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\updater_configuration;
+use phpbb\language\language;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Yaml;
+
+class validate extends \phpbb\console\command\command
+{
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param language $language
+ * @param factory $factory
+ */
+ public function __construct(language $language, factory $factory)
+ {
+ $this->iohandler_factory = $factory;
+ $this->language = $language;
+
+ parent::__construct(new \phpbb\user($language, 'datetime'));
+ }
+
+ /**
+ *
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('update:config:validate')
+ ->addArgument(
+ 'config-file',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_CONFIG_FILE'))
+ ->setDescription($this->language->lang('CLI_INSTALL_VALIDATE_CONFIG'))
+ ;
+ }
+
+ /**
+ * Validate the configuration file
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return null
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->iohandler_factory->set_environment('cli');
+
+ /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $style = new SymfonyStyle($input, $output);
+ $iohandler->set_style($style, $output);
+
+ $config_file = $input->getArgument('config-file');
+
+ if (!is_file($config_file))
+ {
+ $iohandler->add_error_message(array('MISSING_FILE', array($config_file)));
+
+ return 1;
+ }
+
+ try
+ {
+ $config = Yaml::parse(file_get_contents($config_file), true, false);
+ }
+ catch (ParseException $e)
+ {
+ $iohandler->add_error_message('INVALID_YAML_FILE');
+
+ return 1;
+ }
+
+ $processor = new Processor();
+ $configuration = new updater_configuration();
+
+ try
+ {
+ $processor->processConfiguration($configuration, $config);
+ }
+ catch (Exception $e)
+ {
+ $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage());
+
+ return 1;
+ }
+
+ $iohandler->add_success_message('CONFIGURATION_VALID');
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/console/command/update/update.php b/phpBB/phpbb/install/console/command/update/update.php
new file mode 100644
index 0000000000..116f42f758
--- /dev/null
+++ b/phpBB/phpbb/install/console/command/update/update.php
@@ -0,0 +1,179 @@
+<?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\console\command\update;
+
+use phpbb\install\exception\installer_exception;
+use phpbb\install\helper\install_helper;
+use phpbb\install\helper\iohandler\cli_iohandler;
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\installer;
+use phpbb\install\updater_configuration;
+use phpbb\language\language;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Yaml;
+
+class update extends \phpbb\console\command\command
+{
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var installer
+ */
+ protected $installer;
+
+ /**
+ * @var install_helper
+ */
+ protected $install_helper;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ *
+ * @param language $language
+ * @param factory $factory
+ * @param installer $installer
+ * @param install_helper $install_helper
+ */
+ public function __construct(language $language, factory $factory, installer $installer, install_helper $install_helper)
+ {
+ $this->iohandler_factory = $factory;
+ $this->installer = $installer;
+ $this->language = $language;
+ $this->install_helper = $install_helper;
+
+ parent::__construct(new \phpbb\user($language, 'datetime'));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('update')
+ ->addArgument(
+ 'config-file',
+ InputArgument::REQUIRED,
+ $this->language->lang('CLI_CONFIG_FILE'))
+ ->setDescription($this->language->lang('CLI_UPDATE_BOARD'))
+ ;
+ }
+
+ /**
+ * Executes the command update.
+ *
+ * Update the board
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return int
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->iohandler_factory->set_environment('cli');
+
+ /** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $style = new SymfonyStyle($input, $output);
+ $iohandler->set_style($style, $output);
+
+ $this->installer->set_iohandler($iohandler);
+
+ $config_file = $input->getArgument('config-file');
+
+ if (!$this->install_helper->is_phpbb_installed())
+ {
+ $iohandler->add_error_message('INSTALL_PHPBB_NOT_INSTALLED');
+
+ return 1;
+ }
+
+ if (!is_file($config_file))
+ {
+ $iohandler->add_error_message(array('MISSING_FILE', $config_file));
+
+ return 1;
+ }
+
+ try
+ {
+ $config = Yaml::parse(file_get_contents($config_file), true, false);
+ }
+ catch (ParseException $e)
+ {
+ $iohandler->add_error_message(array('INVALID_YAML_FILE', $config_file));
+
+ return 1;
+ }
+
+ $processor = new Processor();
+ $configuration = new updater_configuration();
+
+ try
+ {
+ $config = $processor->processConfiguration($configuration, $config);
+ }
+ catch (Exception $e)
+ {
+ $iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage());
+
+ return 1;
+ }
+
+ $this->register_configuration($iohandler, $config);
+
+ try
+ {
+ $this->installer->run();
+ }
+ catch (installer_exception $e)
+ {
+ $iohandler->add_error_message($e->getMessage());
+ return 1;
+ }
+ }
+
+ /**
+ * Register the configuration to simulate the forms.
+ *
+ * @param cli_iohandler $iohandler
+ * @param array $config
+ */
+ private function register_configuration(cli_iohandler $iohandler, $config)
+ {
+ $iohandler->set_input('update_type', $config['type']);
+ $iohandler->set_input('submit_update', 'submit');
+
+ $iohandler->set_input('compression_method', '.tar');
+ $iohandler->set_input('method', 'direct_file');
+ $iohandler->set_input('submit_update_file', 'submit');
+
+ $iohandler->set_input('submit_continue_file_update', 'submit');
+ }
+}
diff --git a/phpBB/phpbb/install/controller/archive_download.php b/phpBB/phpbb/install/controller/archive_download.php
new file mode 100644
index 0000000000..eabc0a9976
--- /dev/null
+++ b/phpBB/phpbb/install/controller/archive_download.php
@@ -0,0 +1,93 @@
+<?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\controller;
+
+use phpbb\exception\http_exception;
+use phpbb\install\helper\config;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+use Symfony\Component\HttpFoundation\ResponseHeaderBag;
+
+class archive_download
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ */
+ public function __construct(config $config)
+ {
+ $this->installer_config = $config;
+ $this->installer_config->load_config();
+ }
+
+ /**
+ * Sends response with the merge conflict archive
+ *
+ * Merge conflicts always have to be resolved manually,
+ * so we use a different archive for that.
+ *
+ * @return BinaryFileResponse
+ */
+ public function conflict_archive()
+ {
+ $filename = $this->installer_config->get('update_file_conflict_archive', '');
+
+ if (empty($filename))
+ {
+ throw new http_exception(404, 'URL_NOT_FOUND');
+ }
+
+ return $this->send_response($filename);
+ }
+
+ /**
+ * Sends response with the updated files' archive
+ *
+ * @return BinaryFileResponse
+ */
+ public function update_archive()
+ {
+ $filename = $this->installer_config->get('update_file_archive', '');
+
+ if (empty($filename))
+ {
+ throw new http_exception(404, 'URL_NOT_FOUND');
+ }
+
+ return $this->send_response($filename);
+ }
+
+ /**
+ * Generates a download response
+ *
+ * @param string $filename Path to the file to download
+ *
+ * @return BinaryFileResponse Response object
+ */
+ private function send_response($filename)
+ {
+ $response = new BinaryFileResponse($filename);
+ $response->setContentDisposition(
+ ResponseHeaderBag::DISPOSITION_ATTACHMENT,
+ basename($filename)
+ );
+
+ return $response;
+ }
+}
diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php
new file mode 100644
index 0000000000..ff7e691224
--- /dev/null
+++ b/phpBB/phpbb/install/controller/helper.php
@@ -0,0 +1,413 @@
+<?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\controller;
+
+use phpbb\install\helper\config;
+use phpbb\install\helper\navigation\navigation_provider;
+use phpbb\language\language;
+use phpbb\language\language_file_helper;
+use phpbb\path_helper;
+use phpbb\request\request;
+use phpbb\request\request_interface;
+use phpbb\routing\router;
+use phpbb\symfony_request;
+use phpbb\template\template;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\Cookie;
+
+/**
+ * A duplicate of \phpbb\controller\helper
+ *
+ * This class is necessary because of controller\helper's legacy function calls
+ * to page_header() page_footer() functions which has unavailable dependencies.
+ */
+class helper
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var bool|string
+ */
+ protected $language_cookie;
+
+ /**
+ * @var \phpbb\language\language_file_helper
+ */
+ protected $lang_helper;
+
+ /**
+ * @var \phpbb\install\helper\navigation\navigation_provider
+ */
+ protected $navigation_provider;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * @var \phpbb\path_helper
+ */
+ protected $path_helper;
+
+ /**
+ * @var \phpbb\request\request
+ */
+ protected $phpbb_request;
+
+ /**
+ * @var \phpbb\symfony_request
+ */
+ protected $request;
+
+ /**
+ * @var \phpbb\routing\router
+ */
+ protected $router;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_admin_path;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ * @param language $language
+ * @param language_file_helper $lang_helper
+ * @param navigation_provider $nav
+ * @param template $template
+ * @param path_helper $path_helper
+ * @param request $phpbb_request
+ * @param symfony_request $request
+ * @param router $router
+ * @param string $phpbb_root_path
+ */
+ public function __construct(config $config, language $language, language_file_helper $lang_helper, navigation_provider $nav, template $template, path_helper $path_helper, request $phpbb_request, symfony_request $request, router $router, $phpbb_root_path)
+ {
+ $this->installer_config = $config;
+ $this->language = $language;
+ $this->language_cookie = false;
+ $this->lang_helper = $lang_helper;
+ $this->navigation_provider = $nav;
+ $this->template = $template;
+ $this->path_helper = $path_helper;
+ $this->phpbb_request = $phpbb_request;
+ $this->request = $request;
+ $this->router = $router;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->phpbb_admin_path = $phpbb_root_path . 'adm/';
+ }
+
+ /**
+ * Automate setting up the page and creating the response object.
+ *
+ * @param string $template_file The template handle to render
+ * @param string $page_title The title of the page to output
+ * @param bool $selected_language True to enable language selector it, false otherwise
+ * @param int $status_code The status code to be sent to the page header
+ *
+ * @return Response object containing rendered page
+ */
+ public function render($template_file, $page_title = '', $selected_language = false, $status_code = 200)
+ {
+ $this->page_header($page_title, $selected_language);
+
+ $this->template->set_filenames(array(
+ 'body' => $template_file,
+ ));
+
+ $response = new Response($this->template->assign_display('body'), $status_code);
+
+ // Set language cookie
+ if ($this->language_cookie !== false)
+ {
+ $cookie = new Cookie('lang', $this->language_cookie, time() + 3600);
+ $response->headers->setCookie($cookie);
+
+ $this->language_cookie = false;
+ }
+
+ return $response;
+ }
+
+ /**
+ * Returns path from route name
+ *
+ * @param string $route_name
+ * @param array $parameters
+ *
+ * @return string
+ */
+ public function route($route_name, $parameters = array())
+ {
+ $url = $this->router->generate($route_name, $parameters);
+
+ return $url;
+ }
+
+ /**
+ * Handles language selector form
+ */
+ public function handle_language_select()
+ {
+ $lang = null;
+
+ // Check if language form has been submited
+ $submit = $this->phpbb_request->variable('change_lang', '');
+ if (!empty($submit))
+ {
+ $lang = $this->phpbb_request->variable('language', '');
+ }
+
+ // Retrieve language from cookie
+ $lang_cookie = $this->phpbb_request->variable('lang', '', false, request_interface::COOKIE);
+ if (empty($lang) && !empty($lang_cookie))
+ {
+ $lang = $lang_cookie;
+ }
+
+ $lang = (!empty($lang) && strpos($lang, '/') === false) ? $lang : null;
+ $this->language_cookie = $lang;
+
+ $this->render_language_select($lang);
+
+ if ($lang !== null)
+ {
+ $this->language->set_user_language($lang, true);
+ $this->installer_config->set('user_language', $lang);
+ }
+ }
+
+ /**
+ * Process navigation data to reflect active/completed stages
+ *
+ * @param \phpbb\install\helper\iohandler\iohandler_interface|null $iohandler
+ */
+ public function handle_navigation($iohandler = null)
+ {
+ $nav_data = $this->installer_config->get_navigation_data();
+
+ // Set active navigation stage
+ if (isset($nav_data['active']) && is_array($nav_data['active']))
+ {
+ if ($iohandler !== null)
+ {
+ $iohandler->set_active_stage_menu($nav_data['active']);
+ }
+
+ $this->navigation_provider->set_nav_property($nav_data['active'], array(
+ 'selected' => true,
+ 'completed' => false,
+ ));
+ }
+
+ // Set finished navigation stages
+ if (isset($nav_data['finished']) && is_array($nav_data['finished']))
+ {
+ foreach ($nav_data['finished'] as $finished_stage)
+ {
+ if ($iohandler !== null)
+ {
+ $iohandler->set_finished_stage_menu($finished_stage);
+ }
+
+ $this->navigation_provider->set_nav_property($finished_stage, array(
+ 'selected' => false,
+ 'completed' => true,
+ ));
+ }
+ }
+ }
+
+ /**
+ * Set default template variables
+ *
+ * @param string $page_title Title of the page
+ * @param bool $selected_language True to enable language selector it, false otherwise
+ */
+ protected function page_header($page_title, $selected_language = false)
+ {
+ // Path to templates
+ $paths = array($this->phpbb_root_path . 'install/update/new/adm/', $this->phpbb_admin_path);
+ $paths = array_filter($paths, 'is_dir');
+ $path = array_shift($paths);
+ $path = substr($path, strlen($this->phpbb_root_path));
+
+ $this->template->assign_vars(array(
+ 'L_CHANGE' => $this->language->lang('CHANGE'),
+ 'L_COLON' => $this->language->lang('COLON'),
+ 'L_INSTALL_PANEL' => $this->language->lang('INSTALL_PANEL'),
+ 'L_SELECT_LANG' => $this->language->lang('SELECT_LANG'),
+ 'L_SKIP' => $this->language->lang('SKIP'),
+ 'PAGE_TITLE' => $this->language->lang($page_title),
+ 'T_IMAGE_PATH' => $this->path_helper->get_web_root_path() . $path . 'images',
+ 'T_JQUERY_LINK' => $this->path_helper->get_web_root_path() . $path . '../assets/javascript/jquery.min.js',
+ 'T_TEMPLATE_PATH' => $this->path_helper->get_web_root_path() . $path . 'style',
+ 'T_ASSETS_PATH' => $this->path_helper->get_web_root_path() . $path . '../assets',
+
+ 'S_CONTENT_DIRECTION' => $this->language->lang('DIRECTION'),
+ 'S_CONTENT_FLOW_BEGIN' => ($this->language->lang('DIRECTION') === 'ltr') ? 'left' : 'right',
+ 'S_CONTENT_FLOW_END' => ($this->language->lang('DIRECTION') === 'ltr') ? 'right' : 'left',
+ 'S_CONTENT_ENCODING' => 'UTF-8',
+ 'S_LANG_SELECT' => $selected_language,
+
+ 'S_USER_LANG' => $this->language->lang('USER_LANG'),
+ ));
+
+ $this->render_navigation();
+ }
+
+ /**
+ * Render navigation
+ */
+ protected function render_navigation()
+ {
+ // Get navigation items
+ $nav_array = $this->navigation_provider->get();
+ $nav_array = $this->sort_navigation_level($nav_array);
+
+ $active_main_menu = $this->get_active_main_menu($nav_array);
+
+ // Pass navigation to template
+ foreach ($nav_array as $key => $entry)
+ {
+ $this->template->assign_block_vars('t_block1', array(
+ 'L_TITLE' => $this->language->lang($entry['label']),
+ 'S_SELECTED' => ($active_main_menu === $key),
+ 'U_TITLE' => $this->route($entry['route']),
+ ));
+
+ if (is_array($entry[0]) && $active_main_menu === $key)
+ {
+ $entry[0] = $this->sort_navigation_level($entry[0]);
+
+ foreach ($entry[0] as $name => $sub_entry)
+ {
+ if (isset($sub_entry['stage']) && $sub_entry['stage'] === true)
+ {
+ $this->template->assign_block_vars('l_block2', array(
+ 'L_TITLE' => $this->language->lang($sub_entry['label']),
+ 'S_SELECTED' => (isset($sub_entry['selected']) && $sub_entry['selected'] === true),
+ 'S_COMPLETE' => (isset($sub_entry['completed']) && $sub_entry['completed'] === true),
+ 'STAGE_NAME' => $name,
+ ));
+ }
+ else
+ {
+ $this->template->assign_block_vars('l_block1', array(
+ 'L_TITLE' => $this->language->lang($sub_entry['label']),
+ 'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')),
+ 'U_TITLE' => $this->route($sub_entry['route']),
+ ));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Render language select form
+ *
+ * @param string $selected_language
+ */
+ protected function render_language_select($selected_language = null)
+ {
+ $langs = $this->lang_helper->get_available_languages();
+ foreach ($langs as $lang)
+ {
+ $this->template->assign_block_vars('language_select_item', array(
+ 'VALUE' => $lang['iso'],
+ 'NAME' => $lang['local_name'],
+ 'SELECTED' => ($lang['iso'] === $selected_language),
+ ));
+ }
+ }
+
+ /**
+ * Returns the name of the active main menu item
+ *
+ * @param array $nav_array
+ *
+ * @return string|bool Returns the name of the active main menu element, if the element not found, returns false
+ */
+ protected function get_active_main_menu($nav_array)
+ {
+ $active_route = $this->request->get('_route');
+
+ foreach ($nav_array as $nav_name => $nav_options)
+ {
+ $current_menu = $nav_name;
+
+ if (isset($nav_options['route']) && $nav_options['route'] === $active_route)
+ {
+ return $nav_name;
+ }
+
+ if (is_array($nav_options[0]))
+ {
+ foreach ($nav_options[0] as $sub_menus)
+ {
+ if (isset($sub_menus['route']) && $sub_menus['route'] === $active_route)
+ {
+ return $current_menu;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Sorts the top level of navigation array
+ *
+ * @param array $nav_array Navigation array
+ *
+ * @return array
+ */
+ protected function sort_navigation_level($nav_array)
+ {
+ $sorted = array();
+ foreach ($nav_array as $key => $nav)
+ {
+ $order = (isset($nav['order'])) ? $nav['order'] : 0;
+ $sorted[$order][$key] = $nav;
+ }
+
+ // Linearization of navigation array
+ $nav_array = array();
+ ksort($sorted);
+ foreach ($sorted as $nav)
+ {
+ $nav_array = array_merge($nav_array, $nav);
+ }
+
+ return $nav_array;
+ }
+}
diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php
new file mode 100644
index 0000000000..92506872a3
--- /dev/null
+++ b/phpBB/phpbb/install/controller/install.php
@@ -0,0 +1,172 @@
+<?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\controller;
+
+use phpbb\exception\http_exception;
+use phpbb\install\helper\install_helper;
+use phpbb\install\helper\navigation\navigation_provider;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpFoundation\Response;
+use phpbb\install\helper\iohandler\factory;
+use phpbb\template\template;
+use phpbb\request\request_interface;
+use phpbb\install\installer;
+use phpbb\language\language;
+
+/**
+ * Controller for installing phpBB
+ */
+class install
+{
+ /**
+ * @var helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var navigation_provider
+ */
+ protected $menu_provider;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var template
+ */
+ protected $template;
+
+ /**
+ * @var request_interface
+ */
+ protected $request;
+
+ /**
+ * @var installer
+ */
+ protected $installer;
+
+ /**
+ * @var install_helper
+ */
+ protected $install_helper;
+
+ /**
+ * Constructor
+ *
+ * @param helper $helper
+ * @param factory $factory
+ * @param navigation_provider $nav_provider
+ * @param language $language
+ * @param template $template
+ * @param request_interface $request
+ * @param installer $installer
+ * @param install_helper $install_helper
+ */
+ public function __construct(helper $helper, factory $factory, navigation_provider $nav_provider, language $language, template $template, request_interface $request, installer $installer, install_helper $install_helper)
+ {
+ $this->controller_helper = $helper;
+ $this->iohandler_factory = $factory;
+ $this->menu_provider = $nav_provider;
+ $this->language = $language;
+ $this->template = $template;
+ $this->request = $request;
+ $this->installer = $installer;
+ $this->install_helper = $install_helper;
+ }
+
+ /**
+ * Controller logic
+ *
+ * @return Response|StreamedResponse
+ *
+ * @throws http_exception When phpBB is already installed
+ */
+ public function handle()
+ {
+ if ($this->install_helper->is_phpbb_installed())
+ {
+ throw new http_exception(403, 'INSTALL_PHPBB_INSTALLED');
+ }
+
+ $this->template->assign_vars(array(
+ 'U_ACTION' => $this->controller_helper->route('phpbb_installer_install'),
+ ));
+
+ // Set up input-output handler
+ if ($this->request->is_ajax())
+ {
+ $this->iohandler_factory->set_environment('ajax');
+ }
+ else
+ {
+ $this->iohandler_factory->set_environment('nojs');
+ }
+
+ // Set the appropriate input-output handler
+ $this->installer->set_iohandler($this->iohandler_factory->get());
+ $this->controller_helper->handle_language_select();
+
+ if ($this->request->is_ajax())
+ {
+ $installer = $this->installer;
+ $response = new StreamedResponse();
+ $response->setCallback(function() use ($installer) {
+ $installer->run();
+ });
+
+ // Try to bypass any server output buffers
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+ return $response;
+ }
+ else
+ {
+ // Determine whether the installation was started or not
+ if (true)
+ {
+ // Set active stage
+ $this->menu_provider->set_nav_property(
+ array('install', 0, 'introduction'),
+ array(
+ 'selected' => true,
+ 'completed' => false,
+ )
+ );
+
+ // If not, let's render the welcome page
+ $this->template->assign_vars(array(
+ 'SHOW_INSTALL_START_FORM' => true,
+ 'TITLE' => $this->language->lang('INSTALL_INTRO'),
+ 'CONTENT' => $this->language->lang('INSTALL_INTRO_BODY'),
+ ));
+
+ /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $this->controller_helper->handle_navigation($iohandler);
+
+ return $this->controller_helper->render('installer_install.html', 'INSTALL', true);
+ }
+
+ // @todo: implement no js controller logic
+ }
+ }
+}
diff --git a/phpBB/phpbb/install/controller/installer_index.php b/phpBB/phpbb/install/controller/installer_index.php
new file mode 100644
index 0000000000..c2d9572284
--- /dev/null
+++ b/phpBB/phpbb/install/controller/installer_index.php
@@ -0,0 +1,81 @@
+<?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\controller;
+
+class installer_index
+{
+ /**
+ * @var helper
+ */
+ protected $helper;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param helper $helper
+ * @param \phpbb\language\language $language
+ * @param \phpbb\template\template $template
+ * @param string $phpbb_root_path
+ */
+ public function __construct(helper $helper, \phpbb\language\language $language, \phpbb\template\template $template, $phpbb_root_path)
+ {
+ $this->helper = $helper;
+ $this->language = $language;
+ $this->template = $template;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function handle($mode)
+ {
+ $this->helper->handle_language_select();
+
+ switch ($mode)
+ {
+ case "intro":
+ $title = $this->language->lang('INTRODUCTION_TITLE');
+ $body = $this->language->lang('INTRODUCTION_BODY');
+ break;
+ case "support":
+ $title = $this->language->lang('SUPPORT_TITLE');
+ $body = $this->language->lang('SUPPORT_BODY');
+ break;
+ case "license":
+ $title = $this->language->lang('LICENSE_TITLE');
+ $body = implode("<br/>\n", file($this->phpbb_root_path . 'docs/LICENSE.txt'));
+ break;
+ }
+
+ $this->template->assign_vars(array(
+ 'TITLE' => $title,
+ 'BODY' => $body,
+ ));
+
+ return $this->helper->render('installer_main.html', $title, true);
+ }
+}
diff --git a/phpBB/phpbb/install/controller/timeout_check.php b/phpBB/phpbb/install/controller/timeout_check.php
new file mode 100644
index 0000000000..1c90e3caf3
--- /dev/null
+++ b/phpBB/phpbb/install/controller/timeout_check.php
@@ -0,0 +1,80 @@
+<?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\controller;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+class timeout_check
+{
+ /**
+ * @var helper
+ */
+ protected $helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param helper $helper
+ * @param string $phpbb_root_path
+ */
+ public function __construct(helper $helper, $phpbb_root_path)
+ {
+ $this->helper = $helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Controller for querying installer status
+ */
+ public function status()
+ {
+ $lock_file = $this->phpbb_root_path . 'store/io_lock.lock';
+ $response = new JsonResponse();
+
+ if (!file_exists($lock_file))
+ {
+ $response->setData(array(
+ 'status' => 'fail',
+ ));
+ }
+ else
+ {
+ $fp = @fopen($lock_file, 'r');
+
+ if ($fp && flock($fp, LOCK_EX | LOCK_NB))
+ {
+ $status = (filesize($lock_file) >= 2 && fread($fp, 2) === 'ok') ? 'continue' : 'fail';
+
+ $response->setData(array(
+ 'status' => $status,
+ ));
+ flock($fp, LOCK_UN);
+ fclose($fp);
+ }
+ else
+ {
+ $response->setData(array(
+ 'status' => 'running',
+ ));
+ }
+ }
+
+ return $response;
+ }
+}
diff --git a/phpBB/phpbb/install/controller/update.php b/phpBB/phpbb/install/controller/update.php
new file mode 100644
index 0000000000..6b88827940
--- /dev/null
+++ b/phpBB/phpbb/install/controller/update.php
@@ -0,0 +1,166 @@
+<?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\controller;
+
+use phpbb\exception\http_exception;
+use phpbb\install\helper\install_helper;
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\helper\navigation\navigation_provider;
+use phpbb\install\installer;
+use phpbb\language\language;
+use phpbb\request\request_interface;
+use phpbb\template\template;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+
+/**
+ * Updater controller
+ */
+class update
+{
+ /**
+ * @var helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var installer
+ */
+ protected $installer;
+
+ /**
+ * @var install_helper
+ */
+ protected $install_helper;
+
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var navigation_provider
+ */
+ protected $menu_provider;
+
+ /**
+ * @var request_interface
+ */
+ protected $request;
+
+ /**
+ * @var template
+ */
+ protected $template;
+
+ /**
+ * Constructor
+ *
+ * @param helper $controller_helper
+ * @param installer $installer
+ * @param install_helper $install_helper
+ * @param factory $iohandler
+ * @param language $language
+ * @param navigation_provider $menu_provider
+ * @param request_interface $request
+ * @param template $template
+ */
+ public function __construct(helper $controller_helper, installer $installer, install_helper $install_helper, factory $iohandler, language $language, navigation_provider $menu_provider, request_interface $request, template $template)
+ {
+ $this->controller_helper = $controller_helper;
+ $this->installer = $installer;
+ $this->install_helper = $install_helper;
+ $this->iohandler_factory = $iohandler;
+ $this->language = $language;
+ $this->menu_provider = $menu_provider;
+ $this->request = $request;
+ $this->template = $template;
+ }
+
+ /**
+ * Controller entry point
+ *
+ * @return Response|StreamedResponse
+ *
+ * @throws http_exception When phpBB is not installed
+ */
+ public function handle()
+ {
+ if (!$this->install_helper->is_phpbb_installed())
+ {
+ throw new http_exception(403, 'INSTALL_PHPBB_NOT_INSTALLED');
+ }
+
+ $this->template->assign_vars(array(
+ 'U_ACTION' => $this->controller_helper->route('phpbb_installer_update'),
+ ));
+
+ // Set up input-output handler
+ if ($this->request->is_ajax())
+ {
+ $this->iohandler_factory->set_environment('ajax');
+ }
+ else
+ {
+ $this->iohandler_factory->set_environment('nojs');
+ }
+
+ // Set the appropriate input-output handler
+ $this->installer->set_iohandler($this->iohandler_factory->get());
+ $this->controller_helper->handle_language_select();
+
+ // Render the intro page
+ if ($this->request->is_ajax())
+ {
+ $installer = $this->installer;
+ $response = new StreamedResponse();
+ $response->setCallback(function() use ($installer) {
+ $installer->run();
+ });
+
+ // Try to bypass any server output buffers
+ $response->headers->set('X-Accel-Buffering', 'no');
+ $response->headers->set('Content-type', 'application/json');
+
+ return $response;
+ }
+ else
+ {
+ // Set active stage
+ $this->menu_provider->set_nav_property(
+ array('update', 0, 'introduction'),
+ array(
+ 'selected' => true,
+ 'completed' => false,
+ )
+ );
+
+ $this->template->assign_vars(array(
+ 'SHOW_INSTALL_START_FORM' => true,
+ 'TITLE' => $this->language->lang('UPDATE_INSTALLATION'),
+ 'CONTENT' => $this->language->lang('UPDATE_INSTALLATION_EXPLAIN'),
+ ));
+
+ /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $this->controller_helper->handle_navigation($iohandler);
+
+ return $this->controller_helper->render('installer_update.html', 'UPDATE_INSTALLATION', true);
+ }
+ }
+}
diff --git a/phpBB/phpbb/install/event/kernel_exception_subscriber.php b/phpBB/phpbb/install/event/kernel_exception_subscriber.php
new file mode 100644
index 0000000000..60b7d9a400
--- /dev/null
+++ b/phpBB/phpbb/install/event/kernel_exception_subscriber.php
@@ -0,0 +1,126 @@
+<?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\event;
+
+use phpbb\exception\exception_interface;
+use phpbb\install\controller\helper;
+use phpbb\language\language;
+use phpbb\template\template;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+/**
+ * Exception handler for the installer
+ */
+class kernel_exception_subscriber implements EventSubscriberInterface
+{
+ /**
+ * @var helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var template
+ */
+ protected $template;
+
+ /**
+ * Constructor
+ *
+ * @param helper $controller_helper
+ * @param language $language
+ * @param template $template
+ */
+ public function __construct(helper $controller_helper, language $language, template $template)
+ {
+ $this->controller_helper = $controller_helper;
+ $this->language = $language;
+ $this->template = $template;
+ }
+
+ /**
+ * This listener is run when the KernelEvents::EXCEPTION event is triggered
+ *
+ * @param GetResponseForExceptionEvent $event
+ */
+ public function on_kernel_exception(GetResponseForExceptionEvent $event)
+ {
+ $exception = $event->getException();
+ $message = $exception->getMessage();
+
+ if ($exception instanceof exception_interface)
+ {
+ $message = $this->language->lang_array($message, $exception->get_parameters());
+ }
+
+ if (!$event->getRequest()->isXmlHttpRequest())
+ {
+ $this->template->assign_vars(array(
+ 'TITLE' => $this->language->lang('INFORMATION'),
+ 'BODY' => $message,
+ ));
+
+ $response = $this->controller_helper->render(
+ 'installer_main.html',
+ $this->language->lang('INFORMATION'),
+ false,
+ 500
+ );
+ }
+ else
+ {
+ $data = array();
+
+ if (!empty($message))
+ {
+ $data['message'] = $message;
+ }
+
+ if (defined('DEBUG'))
+ {
+ $data['trace'] = $exception->getTrace();
+ }
+
+ $response = new JsonResponse($data, 500);
+ }
+
+ if ($exception instanceof HttpExceptionInterface)
+ {
+ $response->setStatusCode($exception->getStatusCode());
+ $response->headers->add($exception->getHeaders());
+ }
+
+ $event->setResponse($response);
+ }
+
+ /**
+ * Returns an array of events the object is subscribed to
+ *
+ * @return array Array of events the object is subscribed to
+ */
+ static public function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::EXCEPTION => 'on_kernel_exception',
+ );
+ }
+}
diff --git a/phpBB/phpbb/install/exception/cannot_build_container_exception.php b/phpBB/phpbb/install/exception/cannot_build_container_exception.php
new file mode 100644
index 0000000000..6cf12b008b
--- /dev/null
+++ b/phpBB/phpbb/install/exception/cannot_build_container_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * Thrown when the container cannot be built
+ */
+class cannot_build_container_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/file_updater_failure_exception.php b/phpBB/phpbb/install/exception/file_updater_failure_exception.php
new file mode 100644
index 0000000000..46ba2ed32d
--- /dev/null
+++ b/phpBB/phpbb/install/exception/file_updater_failure_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * Thrown when the file updater fails
+ */
+class file_updater_failure_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php b/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php
new file mode 100644
index 0000000000..51864c5dca
--- /dev/null
+++ b/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * Thrown when installer config is not writable to disk
+ */
+class installer_config_not_writable_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/installer_exception.php b/phpBB/phpbb/install/exception/installer_exception.php
new file mode 100644
index 0000000000..f17dca8f17
--- /dev/null
+++ b/phpBB/phpbb/install/exception/installer_exception.php
@@ -0,0 +1,24 @@
+<?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\exception;
+
+use phpbb\exception\runtime_exception;
+
+/**
+ * Installer's base exception
+ */
+class installer_exception extends runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/invalid_dbms_exception.php b/phpBB/phpbb/install/exception/invalid_dbms_exception.php
new file mode 100644
index 0000000000..38de5f613a
--- /dev/null
+++ b/phpBB/phpbb/install/exception/invalid_dbms_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * Thrown when an unavailable DBMS has been selected
+ */
+class invalid_dbms_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/jump_to_restart_point_exception.php b/phpBB/phpbb/install/exception/jump_to_restart_point_exception.php
new file mode 100644
index 0000000000..b628c4fbe3
--- /dev/null
+++ b/phpBB/phpbb/install/exception/jump_to_restart_point_exception.php
@@ -0,0 +1,44 @@
+<?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\exception;
+
+class jump_to_restart_point_exception extends installer_exception
+{
+ /**
+ * @var string
+ */
+ protected $restart_point_name;
+
+ /**
+ * Constructor
+ *
+ * @param string $restart_point_name
+ */
+ public function __construct($restart_point_name)
+ {
+ $this->restart_point_name = $restart_point_name;
+
+ parent::__construct();
+ }
+
+ /**
+ * Returns the restart point's name
+ *
+ * @return string
+ */
+ public function get_restart_point_name()
+ {
+ return $this->restart_point_name;
+ }
+}
diff --git a/phpBB/phpbb/install/exception/resource_limit_reached_exception.php b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php
new file mode 100644
index 0000000000..025e09fbd3
--- /dev/null
+++ b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * Thrown when the installer is out of memory or time
+ */
+class resource_limit_reached_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/user_interaction_required_exception.php b/phpBB/phpbb/install/exception/user_interaction_required_exception.php
new file mode 100644
index 0000000000..d65a448841
--- /dev/null
+++ b/phpBB/phpbb/install/exception/user_interaction_required_exception.php
@@ -0,0 +1,25 @@
+<?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\exception;
+
+/**
+ * This exception should be thrown when user interaction is inevitable
+ *
+ * Note: Please note that the output should already be setup for the user
+ * when you use throw this exception
+ */
+class user_interaction_required_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php
new file mode 100644
index 0000000000..fad6749019
--- /dev/null
+++ b/phpBB/phpbb/install/helper/config.php
@@ -0,0 +1,450 @@
+<?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\helper;
+
+use phpbb\install\exception\installer_config_not_writable_exception;
+
+/**
+ * Stores common settings and installation status
+ */
+class config
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * Array which contains config settings for the installer
+ *
+ * The array will also store all the user input, as well as any
+ * data that is passed to other tasks by a task.
+ *
+ * @var array
+ */
+ protected $installer_config;
+
+ /**
+ * @var string
+ */
+ protected $install_config_file;
+
+ /**
+ * @var \bantu\IniGetWrapper\IniGetWrapper
+ */
+ protected $php_ini;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Array containing progress information
+ *
+ * @var array
+ */
+ protected $progress_data;
+
+ /**
+ * Array containing system information
+ *
+ * The array contains run time and memory limitations.
+ *
+ * @var array
+ */
+ protected $system_data;
+
+ /**
+ * Array containing navigation bar information
+ *
+ * @var array
+ */
+ protected $navigation_data;
+
+ /**
+ * Flag indicating that config file should be cleaned up
+ *
+ * @var bool
+ */
+ protected $do_clean_up;
+
+ /**
+ * Constructor
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \bantu\IniGetWrapper\IniGetWrapper $php_ini, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->php_ini = $php_ini;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->do_clean_up = false;
+
+ // Set up data arrays
+ $this->navigation_data = array();
+ $this->installer_config = array();
+ $this->system_data = array();
+ $this->progress_data = array(
+ 'last_task_module_name' => '', // Stores the service name of the latest finished module
+ 'last_task_module_index' => 0, // Stores the index of the latest finished module
+ 'last_task_index' => 0, // Stores the index of the latest finished task
+ 'max_task_progress' => 0,
+ 'current_task_progress' => 0,
+ '_restart_points' => array(),
+ 'use_restart_point' => false,
+ );
+
+ $this->install_config_file = $this->phpbb_root_path . 'store/install_config.php';
+
+ $this->setup_system_data();
+ }
+
+ /**
+ * Returns data for a specified parameter
+ *
+ * @param string $param_name Name of the parameter to return
+ * @param mixed $default Default value to return when the specified data
+ * does not exist.
+ *
+ * @return mixed value of the specified parameter or the default value if the data
+ * cannot be recovered.
+ */
+ public function get($param_name, $default = false)
+ {
+ return (isset($this->installer_config[$param_name])) ? $this->installer_config[$param_name] : $default;
+ }
+
+ /**
+ * Sets a parameter in installer_config
+ *
+ * @param string $param_name Name of the parameter
+ * @param mixed $value Values to set the parameter
+ */
+ public function set($param_name, $value)
+ {
+ $this->installer_config = array_merge($this->installer_config, array(
+ $param_name => $value,
+ ));
+ }
+
+ /**
+ * Returns system parameter
+ *
+ * @param string $param_name Name of the parameter
+ *
+ * @return mixed Returns system parameter if it is defined, false otherwise
+ */
+ public function system_get($param_name)
+ {
+ return (isset($this->system_data[$param_name])) ? $this->system_data[$param_name] : false;
+ }
+
+ /**
+ * Returns remaining time until the run time limit
+ *
+ * @return int Remaining time until the run time limit in seconds
+ */
+ public function get_time_remaining()
+ {
+ if ($this->system_data['max_execution_time'] <= 0)
+ {
+ return PHP_INT_MAX;
+ }
+
+ return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - microtime(true);
+ }
+
+ /**
+ * Returns remaining memory available for PHP
+ *
+ * @return int Remaining memory until reaching the limit
+ */
+ public function get_memory_remaining()
+ {
+ if ($this->system_data['memory_limit'] <= 0)
+ {
+ return 1;
+ }
+
+ if (function_exists('memory_get_usage'))
+ {
+ return ($this->system_data['memory_limit'] - memory_get_usage());
+ }
+
+ // If we cannot get the information then just return a positive number (and cross fingers)
+ return 1;
+ }
+
+ /**
+ * Saves the latest executed task
+ *
+ * @param int $task_service_index Index of the installer task service in the module
+ */
+ public function set_finished_task($task_service_index)
+ {
+ $this->progress_data['last_task_index'] = $task_service_index;
+ }
+
+ /**
+ * Set active module
+ *
+ * @param string $module_service_name Name of the installer module service
+ * @param int $module_service_index Index of the installer module service
+ */
+ public function set_active_module($module_service_name, $module_service_index)
+ {
+ $this->progress_data['last_task_module_name'] = $module_service_name;
+ $this->progress_data['last_task_module_index'] = $module_service_index;
+ }
+
+ /**
+ * Getter for progress data
+ *
+ * @return array
+ */
+ public function get_progress_data()
+ {
+ return $this->progress_data;
+ }
+
+ /**
+ * Recovers install configuration from file
+ */
+ public function load_config()
+ {
+ if (!$this->filesystem->exists($this->install_config_file))
+ {
+ return;
+ }
+
+ $file_content = @file_get_contents($this->install_config_file);
+ $serialized_data = trim(substr($file_content, 8));
+
+ $installer_config = array();
+ $progress_data = array();
+ $navigation_data = array();
+
+ if (!empty($serialized_data))
+ {
+ $unserialized_data = json_decode($serialized_data, true);
+
+ $installer_config = (is_array($unserialized_data['installer_config'])) ? $unserialized_data['installer_config'] : array();
+ $progress_data = (is_array($unserialized_data['progress_data'])) ? $unserialized_data['progress_data'] : array();
+ $navigation_data = (is_array($unserialized_data['navigation_data'])) ? $unserialized_data['navigation_data'] : array();
+ }
+
+ $this->installer_config = array_merge($this->installer_config, $installer_config);
+ $this->progress_data = array_merge($this->progress_data, $progress_data);
+ $this->navigation_data = array_merge($this->navigation_data, $navigation_data);
+ }
+
+ /**
+ * Creates a progress restart point
+ *
+ * Restart points can be used to repeat certain tasks periodically.
+ * You need to call this method from the first task you want to repeat.
+ *
+ * @param string $name Name of the restart point
+ */
+ public function create_progress_restart_point($name)
+ {
+ $tmp_progress_data = $this->progress_data;
+ unset($tmp_progress_data['_restart_points']);
+
+ $this->progress_data['_restart_points'][$name] = $tmp_progress_data;
+ }
+
+ /**
+ * Set restart point to continue from
+ *
+ * @param string $name Name of the restart point
+ *
+ * @return bool Returns false if the restart point name does not exist, otherwise true
+ */
+ public function jump_to_restart_point($name)
+ {
+ if (!isset($this->progress_data['_restart_points'][$name]) || empty($this->progress_data['_restart_points'][$name]))
+ {
+ return false;
+ }
+
+ foreach ($this->progress_data['_restart_points'][$name] as $key => $value)
+ {
+ $this->progress_data[$key] = $value;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns whether a restart point with a given name exists or not
+ *
+ * @param string $name Name of the restart point
+ *
+ * @return bool
+ */
+ public function has_restart_point($name)
+ {
+ return isset($this->progress_data['_restart_points'][$name]);
+ }
+
+ /**
+ * Dumps install configuration to disk
+ */
+ public function save_config()
+ {
+ if ($this->do_clean_up)
+ {
+ @unlink($this->install_config_file);
+ return;
+ }
+
+ // Create array to save
+ $save_array = array(
+ 'installer_config' => $this->installer_config,
+ 'progress_data' => $this->progress_data,
+ 'navigation_data' => $this->navigation_data,
+ );
+
+ // Create file content
+ $file_content = '<?php // ';
+ $file_content .= json_encode($save_array);
+ $file_content .= "\n";
+
+ // Dump file_content to disk
+ $fp = @fopen($this->install_config_file, 'w');
+ if (!$fp)
+ {
+ throw new installer_config_not_writable_exception();
+ }
+
+ fwrite($fp, $file_content);
+ fclose($fp);
+ }
+
+ /**
+ * Increments the task progress
+ *
+ * @param int $increment_by The amount to increment by
+ */
+ public function increment_current_task_progress($increment_by = 1)
+ {
+ $this->progress_data['current_task_progress'] += $increment_by;
+
+ if ($this->progress_data['current_task_progress'] > $this->progress_data['max_task_progress'])
+ {
+ $this->progress_data['current_task_progress'] = $this->progress_data['max_task_progress'];
+ }
+ }
+
+ /**
+ * Sets the task progress to a specific number
+ *
+ * @param int $task_progress The task progress number to be set
+ */
+ public function set_current_task_progress($task_progress)
+ {
+ $this->progress_data['current_task_progress'] = $task_progress;
+ }
+
+ /**
+ * Sets the number of tasks belonging to the installer in the current mode.
+ *
+ * @param int $task_progress_count Number of tasks
+ */
+ public function set_task_progress_count($task_progress_count)
+ {
+ $this->progress_data['max_task_progress'] = $task_progress_count;
+ }
+
+ /**
+ * Returns the number of the current task being executed
+ *
+ * @return int
+ */
+ public function get_current_task_progress()
+ {
+ return $this->progress_data['current_task_progress'];
+ }
+
+ /**
+ * Returns the number of tasks belonging to the installer in the current mode.
+ *
+ * @return int
+ */
+ public function get_task_progress_count()
+ {
+ return $this->progress_data['max_task_progress'];
+ }
+
+ /**
+ * Marks stage as completed in the navigation bar
+ *
+ * @param array $nav_path Array to the navigation elem
+ */
+ public function set_finished_navigation_stage($nav_path)
+ {
+ if (isset($this->navigation_data['finished']) && in_array($nav_path, $this->navigation_data['finished']))
+ {
+ return;
+ }
+
+ $this->navigation_data['finished'][] = $nav_path;
+ }
+
+ /**
+ * Marks stage as active in the navigation bar
+ *
+ * @param array $nav_path Array to the navigation elem
+ */
+ public function set_active_navigation_stage($nav_path)
+ {
+ $this->navigation_data['active'] = $nav_path;
+ }
+
+ /**
+ * Returns navigation data
+ *
+ * @return array
+ */
+ public function get_navigation_data()
+ {
+ return $this->navigation_data;
+ }
+
+ /**
+ * Removes install config file
+ */
+ public function clean_up_config_file()
+ {
+ $this->do_clean_up = true;
+ @unlink($this->install_config_file);
+ }
+
+ /**
+ * Filling up system_data array
+ */
+ protected function setup_system_data()
+ {
+ // Query maximum runtime from php.ini
+ $execution_time = $this->php_ini->getNumeric('max_execution_time');
+ $execution_time = min(15, $execution_time / 2);
+ $this->system_data['max_execution_time'] = $execution_time;
+
+ // Set start time
+ $this->system_data['start_time'] = microtime(true);
+
+ // Get memory limit
+ $this->system_data['memory_limit'] = $this->php_ini->getBytes('memory_limit');
+ }
+}
diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php
new file mode 100644
index 0000000000..9e372fecde
--- /dev/null
+++ b/phpBB/phpbb/install/helper/container_factory.php
@@ -0,0 +1,191 @@
+<?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\helper;
+
+use phpbb\install\exception\cannot_build_container_exception;
+use phpbb\language\language;
+use phpbb\request\request;
+
+class container_factory
+{
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * The full phpBB container
+ *
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * Constructor
+ *
+ * @param language $language Language service
+ * @param request $request Request interface
+ * @param update_helper $update_helper Update helper
+ * @param string $phpbb_root_path Path to phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct(language $language, request $request, update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->language = $language;
+ $this->request = $request;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->container = null;
+ }
+
+ /**
+ * Container getter
+ *
+ * @param null|string $service_name Name of the service to return
+ *
+ * @return \Symfony\Component\DependencyInjection\ContainerInterface|Object phpBB's dependency injection container
+ * or the service specified in $service_name
+ *
+ * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built
+ * @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException If the service is not defined
+ * @throws \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException When a circular reference is detected
+ * @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException When the service is not defined
+ */
+ public function get($service_name = null)
+ {
+ // Check if container was built, if not try to build it
+ if ($this->container === null)
+ {
+ $this->build_container();
+ }
+
+ return ($service_name === null) ? $this->container : $this->container->get($service_name);
+ }
+
+ /**
+ * Returns the specified parameter from the container
+ *
+ * @param string $param_name
+ *
+ * @return mixed
+ *
+ * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built
+ */
+ public function get_parameter($param_name)
+ {
+ // Check if container was built, if not try to build it
+ if ($this->container === null)
+ {
+ $this->build_container();
+ }
+
+ return $this->container->getParameter($param_name);
+ }
+
+ /**
+ * Build dependency injection container
+ *
+ * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built
+ */
+ protected function build_container()
+ {
+ // If the container has been already built just return.
+ // Although this should never happen
+ if ($this->container instanceof \Symfony\Component\DependencyInjection\ContainerInterface)
+ {
+ return;
+ }
+
+ // Check whether container can be built
+ // We need config.php for that so let's check if it has been set up yet
+ if (!filesize($this->phpbb_root_path . 'config.' . $this->php_ext))
+ {
+ throw new cannot_build_container_exception();
+ }
+
+ $phpbb_config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext);
+ $phpbb_container_builder = new \phpbb\di\container_builder($this->phpbb_root_path, $this->php_ext);
+
+ // For BC with functions that we need during install
+ global $phpbb_container, $table_prefix;
+
+ $disable_super_globals = $this->request->super_globals_disabled();
+
+ // This is needed because container_builder::get_env_parameters() uses $_SERVER
+ if ($disable_super_globals)
+ {
+ $this->request->enable_super_globals();
+ }
+
+ $other_config_path = $this->phpbb_root_path . 'install/update/new/config';
+ $config_path = (is_dir($other_config_path)) ? $other_config_path : $this->phpbb_root_path . 'config';
+
+ $this->container = $phpbb_container_builder
+ ->with_environment('production')
+ ->with_config($phpbb_config_php_file)
+ ->with_config_path($config_path)
+ ->without_compiled_container()
+ ->get_container();
+
+ // Setting request is required for the compatibility globals as those are generated from
+ // this container
+ if (!$this->container->isFrozen())
+ {
+ $this->container->register('request')->setSynthetic(true);
+ $this->container->register('language')->setSynthetic(true);
+ }
+
+ $this->container->set('request', $this->request);
+ $this->container->set('language', $this->language);
+
+ $this->container->compile();
+
+ $phpbb_container = $this->container;
+ $table_prefix = $phpbb_config_php_file->get('table_prefix');
+
+ // Restore super globals to previous state
+ if ($disable_super_globals)
+ {
+ $this->request->disable_super_globals();
+ }
+
+ // Get compatibilty globals and constants
+ $this->update_helper->include_file('includes/compatibility_globals.' . $this->php_ext);
+
+ register_compatibility_globals();
+
+ $this->update_helper->include_file('includes/constants.' . $this->php_ext);
+ }
+}
diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php
new file mode 100644
index 0000000000..192f0a3654
--- /dev/null
+++ b/phpBB/phpbb/install/helper/database.php
@@ -0,0 +1,430 @@
+<?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\helper;
+
+use phpbb\install\exception\invalid_dbms_exception;
+
+/**
+ * Database related general functionality for installer
+ */
+class database
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var array
+ */
+ protected $supported_dbms = array(
+ // Note: php 5.5 alpha 2 deprecated mysql.
+ // Keep mysqli before mysql in this list.
+ 'mysqli' => array(
+ 'LABEL' => 'MySQL with MySQLi Extension',
+ 'SCHEMA' => 'mysql_41',
+ 'MODULE' => 'mysqli',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\mysqli',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mysql' => array(
+ 'LABEL' => 'MySQL',
+ 'SCHEMA' => 'mysql',
+ 'MODULE' => 'mysql',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\mysql',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mssql_odbc'=> array(
+ 'LABEL' => 'MS SQL Server [ ODBC ]',
+ 'SCHEMA' => 'mssql',
+ 'MODULE' => 'odbc',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\mssql_odbc',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mssqlnative' => array(
+ 'LABEL' => 'MS SQL Server 2005+ [ Native ]',
+ 'SCHEMA' => 'mssql',
+ 'MODULE' => 'sqlsrv',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\mssqlnative',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ 'oracle' => array(
+ 'LABEL' => 'Oracle',
+ 'SCHEMA' => 'oracle',
+ 'MODULE' => 'oci8',
+ 'DELIM' => '/',
+ 'DRIVER' => 'phpbb\db\driver\oracle',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ 'postgres' => array(
+ 'LABEL' => 'PostgreSQL 8.3+',
+ 'SCHEMA' => 'postgres',
+ 'MODULE' => 'pgsql',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\postgres',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'sqlite3' => array(
+ 'LABEL' => 'SQLite3',
+ 'SCHEMA' => 'sqlite',
+ 'MODULE' => 'sqlite3',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\sqlite3',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ );
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem interface
+ * @param string $phpbb_root_path Path to phpBB's root
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Returns an array of available DBMS supported by phpBB
+ *
+ * If a DBMS is specified it will only return data for that DBMS
+ * and will load its extension if necessary.
+ *
+ * @param mixed $dbms name of the DBMS that's info is required or false for all DBMS info
+ * @param bool $return_unavailable set it to true if you expect unavailable but supported DBMS
+ * returned as well
+ * @param bool $only_20x_options set it to true if you only want to recover 2.0.x options
+ *
+ * @return array Array of available and supported DBMS
+ */
+ public function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
+ {
+ $available_dbms = $this->supported_dbms;
+
+ if ($dbms)
+ {
+ if (isset($this->supported_dbms[$dbms]))
+ {
+ $available_dbms = array($dbms => $this->supported_dbms[$dbms]);
+ }
+ else
+ {
+ return array();
+ }
+ }
+
+ $any_dbms_available = false;
+ foreach ($available_dbms as $db_name => $db_array)
+ {
+ if ($only_20x_options && !$db_array['2.0.x'])
+ {
+ if ($return_unavailable)
+ {
+ $available_dbms[$db_name]['AVAILABLE'] = false;
+ }
+ else
+ {
+ unset($available_dbms[$db_name]);
+ }
+
+ continue;
+ }
+
+ $dll = $db_array['MODULE'];
+ if (!@extension_loaded($dll))
+ {
+ if ($return_unavailable)
+ {
+ $available_dbms[$db_name]['AVAILABLE'] = false;
+ }
+ else
+ {
+ unset($available_dbms[$db_name]);
+ }
+
+ continue;
+ }
+
+ $any_dbms_available = true;
+ }
+
+ if ($return_unavailable)
+ {
+ $available_dbms['ANY_DB_SUPPORT'] = $any_dbms_available;
+ }
+
+ return $available_dbms;
+ }
+
+ /**
+ * Removes "/* style" as well as "# style" comments from $input.
+ *
+ * @param string $sql_query Input string
+ *
+ * @return string Input string with comments removed
+ */
+ public function remove_comments($sql_query)
+ {
+ // Remove /* */ comments (http://ostermiller.org/findcomment.html)
+ $sql_query = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql_query);
+
+ // Remove # style comments
+ $sql_query = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql_query));
+
+ return $sql_query;
+ }
+
+ /**
+ * split_sql_file() will split an uploaded sql file into single sql statements.
+ *
+ * Note: expects trim() to have already been run on $sql.
+ *
+ * @param string $sql SQL statements
+ * @param string $delimiter Delimiter between sql statements
+ *
+ * @return array Array of sql statements
+ */
+ public function split_sql_file($sql, $delimiter)
+ {
+ $sql = str_replace("\r" , '', $sql);
+ $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
+
+ $data = array_map('trim', $data);
+
+ // The empty case
+ $end_data = end($data);
+
+ if (empty($end_data))
+ {
+ unset($data[key($data)]);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Validates table prefix
+ *
+ * @param string $dbms The selected dbms
+ * @param string $table_prefix The table prefix to validate
+ *
+ * @return bool|array true if table prefix is valid, array of errors otherwise
+ *
+ * @throws \phpbb\install\exception\invalid_dbms_exception When $dbms is not a valid
+ */
+ public function validate_table_prefix($dbms, $table_prefix)
+ {
+ $errors = array();
+
+ if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $table_prefix))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_INVALID_PREFIX',
+ );
+ }
+
+ // Do dbms specific checks
+ $dbms_info = $this->get_available_dbms($dbms);
+ switch ($dbms_info[$dbms]['SCHEMA'])
+ {
+ case 'mysql':
+ case 'mysql_41':
+ $prefix_length = 36;
+ break;
+ case 'mssql':
+ $prefix_length = 90;
+ break;
+ case 'oracle':
+ $prefix_length = 6;
+ break;
+ case 'postgres':
+ $prefix_length = 36;
+ break;
+ case 'sqlite':
+ $prefix_length = 200;
+ break;
+ default:
+ throw new invalid_dbms_exception();
+ break;
+ }
+
+ // Check the prefix length to ensure that index names are not too long
+ if (strlen($table_prefix) > $prefix_length)
+ {
+ $errors[] = array(
+ 'title' => array('INST_ERR_PREFIX_TOO_LONG', $prefix_length),
+ );
+ }
+
+ return (empty($errors)) ? true : $errors;
+ }
+
+ /**
+ * Check if the user provided database parameters are correct
+ *
+ * This function checks the database connection data and also checks for
+ * any other problems that could cause an error during the installation
+ * such as if there is any database table names conflicting.
+ *
+ * Note: The function assumes that $table_prefix has been already validated
+ * with validate_table_prefix().
+ *
+ * @param string $dbms Selected database type
+ * @param string $dbhost Database host address
+ * @param int $dbport Database port number
+ * @param string $dbuser Database username
+ * @param string $dbpass Database password
+ * @param string $dbname Database name
+ * @param string $table_prefix Database table prefix
+ *
+ * @return array|bool Returns true if test is successful, array of errors otherwise
+ */
+ public function check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix)
+ {
+ $dbms_info = $this->get_available_dbms($dbms);
+ $dbms_info = $dbms_info[$dbms];
+ $errors = array();
+
+ // Instantiate it and set return on error true
+ /** @var \phpbb\db\driver\driver_interface $db */
+ $db = new $dbms_info['DRIVER'];
+ $db->sql_return_on_error(true);
+
+ // Check that we actually have a database name before going any further
+ if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle'), true) && $dbname === '')
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_NAME',
+ );
+ }
+
+ // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
+ if ($dbms_info['SCHEMA'] === 'sqlite'
+ && stripos($this->filesystem->realpath($dbhost), $this->filesystem->realpath($this->phpbb_root_path) === 0))
+ {
+ $errors[] = array(
+ 'title' =>'INST_ERR_DB_FORUM_PATH',
+ );
+ }
+
+ // Try to connect to db
+ if (is_array($db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, false, true)))
+ {
+ $db_error = $db->sql_error();
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_CONNECT',
+ 'description' => ($db_error['message']) ? utf8_convert_message($db_error['message']) : 'INST_ERR_DB_NO_ERROR',
+ );
+ }
+ else
+ {
+ // Check if there is any table name collisions
+ $temp_prefix = strtolower($table_prefix);
+ $table_ary = array(
+ $temp_prefix . 'attachments',
+ $temp_prefix . 'config',
+ $temp_prefix . 'sessions',
+ $temp_prefix . 'topics',
+ $temp_prefix . 'users',
+ );
+
+ $db_tools_factory = new \phpbb\db\tools\factory();
+ $db_tools = $db_tools_factory->get($db);
+ $tables = $db_tools->sql_list_tables();
+ $tables = array_map('strtolower', $tables);
+ $table_intersect = array_intersect($tables, $table_ary);
+
+ if (sizeof($table_intersect))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_PREFIX',
+ );
+ }
+
+ // Check if database version is supported
+ switch ($dbms)
+ {
+ case 'mysqli':
+ if (version_compare($db->sql_server_info(true), '4.1.3', '<'))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_MYSQLI',
+ );
+ }
+ break;
+ case 'sqlite3':
+ if (version_compare($db->sql_server_info(true), '3.6.15', '<'))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_SQLITE3',
+ );
+ }
+ break;
+ case 'oracle':
+ $sql = "SELECT *
+ FROM NLS_DATABASE_PARAMETERS
+ WHERE PARAMETER = 'NLS_RDBMS_VERSION'
+ OR PARAMETER = 'NLS_CHARACTERSET'";
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $stats[$row['parameter']] = $row['value'];
+ }
+ $db->sql_freeresult($result);
+
+ if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_ORACLE',
+ );
+ }
+ break;
+ case 'postgres':
+ $sql = "SHOW server_encoding;";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_POSTGRES',
+ );
+ }
+ break;
+ }
+ }
+
+ return (empty($errors)) ? true : $errors;
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/compression_file_updater.php b/phpBB/phpbb/install/helper/file_updater/compression_file_updater.php
new file mode 100644
index 0000000000..ede992fb6e
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/compression_file_updater.php
@@ -0,0 +1,133 @@
+<?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\helper\file_updater;
+
+use phpbb\install\helper\update_helper;
+
+/**
+ * File updater for generating archive with updated files
+ */
+class compression_file_updater implements file_updater_interface
+{
+ /**
+ * @var \compress
+ */
+ protected $compress;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->compress = null;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Set the compression method
+ *
+ * @param string $method Compression method's file extension
+ *
+ * @return string Archive's filename
+ */
+ public function init($method)
+ {
+ $this->update_helper->include_file('includes/functions_compress.' . $this->php_ext);
+
+ $archive_filename = 'update_archive_' . time() . '_' . uniqid();
+ $path = $this->phpbb_root_path . 'store/' . $archive_filename . '' . $method;
+
+ if ($method === '.zip')
+ {
+ $this->compress = new \compress_zip('w', $path);
+ }
+ else
+ {
+ $this->compress = new \compress_tar('w', $path, $method);
+ }
+
+ return $path;
+ }
+
+ /**
+ * Close archive writing process
+ */
+ public function close()
+ {
+ $this->compress->close();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete_file($path_to_file)
+ {
+ // We do absolutely nothing here, as this function is called when a file should be
+ // removed from the filesystem, but since this is an archive generator, it clearly
+ // cannot do that.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false)
+ {
+ if ($create_from_content)
+ {
+ $this->compress->add_data($source, $path_to_file_to_create);
+ }
+ else
+ {
+ $this->compress->add_custom_file($source, $path_to_file_to_create);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false)
+ {
+ // Both functions are identical here
+ $this->create_new_file($path_to_file_to_update, $source, $create_from_content);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_method_name()
+ {
+ return 'compression';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/factory.php b/phpBB/phpbb/install/helper/file_updater/factory.php
new file mode 100644
index 0000000000..d3a2f22782
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/factory.php
@@ -0,0 +1,69 @@
+<?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\helper\file_updater;
+
+use phpbb\di\service_collection;
+use phpbb\install\exception\file_updater_failure_exception;
+
+/**
+ * File updater factory
+ */
+class factory
+{
+ /**
+ * @var array
+ */
+ protected $file_updaters;
+
+ /**
+ * Constructor
+ *
+ * @param service_collection $collection File updater service collection
+ */
+ public function __construct(service_collection $collection)
+ {
+ foreach ($collection as $service)
+ {
+ $this->register($service);
+ }
+ }
+
+ /**
+ * Register updater object
+ *
+ * @param file_updater_interface $updater Updater object
+ */
+ public function register(file_updater_interface $updater)
+ {
+ $name = $updater->get_method_name();
+ $this->file_updaters[$name] = $updater;
+ }
+
+ /**
+ * Returns file updater object
+ *
+ * @param string $name Name of the updater method
+ *
+ * @throws file_updater_failure_exception When the specified file updater does not exist
+ */
+ public function get($name)
+ {
+ if (!isset($this->file_updaters[$name]))
+ {
+ throw new file_updater_failure_exception();
+ }
+
+ return $this->file_updaters[$name];
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/file_updater.php b/phpBB/phpbb/install/helper/file_updater/file_updater.php
new file mode 100644
index 0000000000..cc0f5c6b5f
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/file_updater.php
@@ -0,0 +1,202 @@
+<?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\helper\file_updater;
+
+use phpbb\filesystem\exception\filesystem_exception;
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\file_updater_failure_exception;
+
+/**
+ * File updater for direct filesystem access
+ */
+class file_updater implements file_updater_interface
+{
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param filesystem $filesystem
+ * @param string $phpbb_root_path
+ */
+ public function __construct(filesystem $filesystem, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ * @throws filesystem_exception When the filesystem class fails
+ */
+ public function delete_file($path_to_file)
+ {
+ $this->filesystem->remove($this->phpbb_root_path . $path_to_file);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ * @throws filesystem_exception When the filesystem class fails
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false)
+ {
+ $path_to_file_to_create = $this->phpbb_root_path . $path_to_file_to_create;
+
+ $dir = dirname($path_to_file_to_create);
+ if (!$this->filesystem->exists($dir))
+ {
+ $this->make_dir($dir);
+ }
+
+ $original_dir_perms = false;
+
+ if (!$this->filesystem->is_writable($dir))
+ {
+ // Extract last 9 bits we actually need
+ $original_dir_perms = @fileperms($dir) & 511;
+ $this->filesystem->phpbb_chmod($dir, filesystem::CHMOD_ALL);
+ }
+
+ if (!$create_from_content)
+ {
+ try
+ {
+ $this->filesystem->copy($source, $path_to_file_to_create);
+ }
+ catch (filesystem_exception $e)
+ {
+ $this->write_file($path_to_file_to_create, $source, $create_from_content);
+ }
+ }
+ else
+ {
+ $this->write_file($path_to_file_to_create, $source, $create_from_content);
+ }
+
+ if ($original_dir_perms !== false)
+ {
+ $this->filesystem->phpbb_chmod($dir, $original_dir_perms);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ * @throws filesystem_exception When the filesystem class fails
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false)
+ {
+ $path_to_file_to_update = $this->phpbb_root_path . $path_to_file_to_update;
+ $original_file_perms = false;
+
+ // Maybe necessary for binary files
+ $dir = dirname($path_to_file_to_update);
+ if (!$this->filesystem->exists($dir))
+ {
+ $this->make_dir($dir);
+ }
+
+ if (!$this->filesystem->is_writable($path_to_file_to_update))
+ {
+ // Extract last 9 bits we actually need
+ $original_file_perms = @fileperms($path_to_file_to_update) & 511;
+ $this->filesystem->phpbb_chmod($path_to_file_to_update, filesystem::CHMOD_WRITE);
+ }
+
+ if (!$create_from_content)
+ {
+ try
+ {
+ $this->filesystem->copy($source, $path_to_file_to_update, true);
+ }
+ catch (filesystem_exception $e)
+ {
+ $this->write_file($path_to_file_to_update, $source, $create_from_content);
+ }
+ }
+ else
+ {
+ $this->write_file($path_to_file_to_update, $source, $create_from_content);
+ }
+
+ if ($original_file_perms !== false)
+ {
+ $this->filesystem->phpbb_chmod($path_to_file_to_update, $original_file_perms);
+ }
+ }
+
+ /**
+ * Creates directory structure
+ *
+ * @param string $path Path to the directory where the file should be placed (and non-existent)
+ */
+ private function make_dir($path)
+ {
+ if (is_dir($path))
+ {
+ return;
+ }
+
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+ $this->filesystem->mkdir($path, 493); // 493 === 0755
+ }
+
+ /**
+ * Fallback function for file writing
+ *
+ * @param string $path_to_file Path to the file's location
+ * @param string $source Path to file to copy or string with the new file's content
+ * @param bool|false $create_from_content Whether or not to use $source as the content, false by default
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ */
+ private function write_file($path_to_file, $source, $create_from_content = false)
+ {
+ if (!$create_from_content)
+ {
+ $source = @file_get_contents($source);
+ }
+
+ $file_pointer = @fopen($path_to_file, 'w');
+
+ if (!is_resource($file_pointer))
+ {
+ throw new file_updater_failure_exception();
+ }
+
+ @fwrite($file_pointer, $source);
+ @fclose($file_pointer);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_method_name()
+ {
+ return 'direct_file';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/file_updater_interface.php b/phpBB/phpbb/install/helper/file_updater/file_updater_interface.php
new file mode 100644
index 0000000000..b13d7c9fe1
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/file_updater_interface.php
@@ -0,0 +1,49 @@
+<?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\helper\file_updater;
+
+interface file_updater_interface
+{
+ /**
+ * Deletes a file
+ *
+ * @param string $path_to_file Path to the file to delete
+ */
+ public function delete_file($path_to_file);
+
+ /**
+ * Creates a new file
+ *
+ * @param string $path_to_file_to_create Path to the new file's location
+ * @param string $source Path to file to copy or string with the new file's content
+ * @param bool $create_from_content Whether or not to use $source as the content, false by default
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false);
+
+ /**
+ * Update file
+ *
+ * @param string $path_to_file_to_update Path to the file's location
+ * @param string $source Path to file to copy or string with the new file's content
+ * @param bool $create_from_content Whether or not to use $source as the content, false by default
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false);
+
+ /**
+ * Returns the name of the file updater method
+ *
+ * @return string
+ */
+ public function get_method_name();
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php
new file mode 100644
index 0000000000..258a035768
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php
@@ -0,0 +1,136 @@
+<?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\helper\file_updater;
+
+use phpbb\install\helper\update_helper;
+
+/**
+ * File updater for FTP updates
+ */
+class ftp_file_updater implements file_updater_interface
+{
+ /**
+ * @var \transfer
+ */
+ protected $transfer;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __constructor(update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->transfer = null;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Initialize FTP connection
+ *
+ * @param string $method
+ * @param string $host
+ * @param string $user
+ * @param string $pass
+ * @param string $path
+ * @param int $port
+ * @param int $timeout
+ */
+ public function init($method, $host, $user, $pass, $path, $port, $timeout)
+ {
+ $this->update_helper->include_file('includes/functions_transfer.' . $this->php_ext);
+ $this->transfer = new $method($host, $user, $pass, $path, $port, $timeout);
+ $this->transfer->open_session();
+ }
+
+ /**
+ * Close FTP session
+ */
+ public function close()
+ {
+ $this->transfer->close_session();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete_file($path_to_file)
+ {
+ $this->transfer->delete_file($path_to_file);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false)
+ {
+ $dirname = dirname($path_to_file_to_create);
+
+ if ($dirname && !file_exists($this->phpbb_root_path . $dirname))
+ {
+ $this->transfer->make_dir($dirname);
+ }
+
+ if ($create_from_content)
+ {
+ $this->transfer->write_file($path_to_file_to_create, $source);
+ }
+ else
+ {
+ $this->transfer->copy_file($path_to_file_to_create, $source);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false)
+ {
+ if ($create_from_content)
+ {
+ $this->transfer->write_file($path_to_file_to_update, $source);
+ }
+ else
+ {
+ $this->transfer->copy_file($path_to_file_to_update, $source);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_method_name()
+ {
+ return 'ftp';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/install_helper.php b/phpBB/phpbb/install/helper/install_helper.php
new file mode 100644
index 0000000000..ffe36cd645
--- /dev/null
+++ b/phpBB/phpbb/install/helper/install_helper.php
@@ -0,0 +1,60 @@
+<?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\helper;
+
+/**
+ * General helper functionality for the installer
+ */
+class install_helper
+{
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param string $phpbb_root_path path to phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct($phpbb_root_path, $php_ext)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Check whether phpBB is installed.
+ *
+ * @return bool
+ */
+ public function is_phpbb_installed()
+ {
+ $config_path = $this->phpbb_root_path . 'config.' . $this->php_ext;
+ $install_lock_path = $this->phpbb_root_path . 'cache/install_lock';
+
+ if (file_exists($config_path) && !file_exists($install_lock_path) && filesize($config_path))
+ {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php
new file mode 100644
index 0000000000..c168d26425
--- /dev/null
+++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php
@@ -0,0 +1,489 @@
+<?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\helper\iohandler;
+
+use phpbb\path_helper;
+use phpbb\routing\router;
+
+/**
+ * Input-Output handler for the AJAX frontend
+ */
+class ajax_iohandler extends iohandler_base
+{
+ /**
+ * @var path_helper
+ */
+ protected $path_helper;
+
+ /**
+ * @var \phpbb\request\request_interface
+ */
+ protected $request;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * @var router
+ */
+ protected $router;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $file_status;
+
+ /**
+ * @var string
+ */
+ protected $form;
+
+ /**
+ * @var bool
+ */
+ protected $request_client_refresh;
+
+ /**
+ * @var array
+ */
+ protected $nav_data;
+
+ /**
+ * @var array
+ */
+ protected $cookies;
+
+ /**
+ * @var array
+ */
+ protected $download;
+
+ /**
+ * @var array
+ */
+ protected $redirect_url;
+
+ /**
+ * @var resource
+ */
+ protected $file_lock_pointer;
+
+ /**
+ * Constructor
+ *
+ * @param path_helper $path_helper
+ * @param \phpbb\request\request_interface $request HTTP request interface
+ * @param \phpbb\template\template $template Template engine
+ * @param router $router Router
+ * @param string $root_path Path to phpBB's root
+ */
+ public function __construct(path_helper $path_helper, \phpbb\request\request_interface $request, \phpbb\template\template $template, router $router, $root_path)
+ {
+ $this->path_helper = $path_helper;
+ $this->request = $request;
+ $this->router = $router;
+ $this->template = $template;
+ $this->form = '';
+ $this->nav_data = array();
+ $this->cookies = array();
+ $this->download = array();
+ $this->redirect_url = array();
+ $this->file_status = '';
+ $this->phpbb_root_path = $root_path;
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_input($name, $default, $multibyte = false)
+ {
+ return $this->request->variable($name, $default, $multibyte);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_server_variable($name, $default = '')
+ {
+ return $this->request->server($name, $default);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_header_variable($name, $default = '')
+ {
+ return $this->request->header($name, $default);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_secure()
+ {
+ return $this->request->is_secure();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_user_form_group($title, $form)
+ {
+ $this->form = $this->generate_form_render_data($title, $form);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function generate_form_render_data($title, $form)
+ {
+ $this->template->assign_block_vars('options', array(
+ 'LEGEND' => $this->language->lang($title),
+ 'S_LEGEND' => true,
+ ));
+
+ $not_button_form = false;
+
+ foreach ($form as $input_name => $input_options)
+ {
+ if (!isset($input_options['type']))
+ {
+ continue;
+ }
+
+ $tpl_ary = array();
+ $not_button_form = ($input_options['type'] !== 'submit' || $not_button_form);
+
+ $tpl_ary['TYPE'] = $input_options['type'];
+ $tpl_ary['TITLE'] = $this->language->lang($input_options['label']);
+ $tpl_ary['KEY'] = $input_name;
+ $tpl_ary['S_EXPLAIN'] = false;
+
+ if (isset($input_options['default']))
+ {
+ $default = $input_options['default'];
+ $default = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $default);
+ $tpl_ary['DEFAULT'] = $default;
+ }
+
+ if (isset($input_options['description']))
+ {
+ $tpl_ary['TITLE_EXPLAIN'] = $this->language->lang($input_options['description']);
+ $tpl_ary['S_EXPLAIN'] = true;
+ }
+
+ if (in_array($input_options['type'], array('select', 'radio'), true))
+ {
+ for ($i = 0, $total = sizeof($input_options['options']); $i < $total; $i++)
+ {
+ if (isset($input_options['options'][$i]['label']))
+ {
+ $input_options['options'][$i]['label'] = $this->language->lang($input_options['options'][$i]['label']);
+ }
+ }
+
+ $tpl_ary['OPTIONS'] = $input_options['options'];
+ }
+
+ $block_name = ($input_options['type'] === 'submit') ? 'submit_buttons' : 'options';
+ $this->template->assign_block_vars($block_name, $tpl_ary);
+ }
+
+ $this->template->assign_var('S_NOT_ONLY_BUTTON_FORM', $not_button_form);
+
+ $this->template->set_filenames(array(
+ 'form_install' => 'installer_form.html',
+ ));
+
+ return $this->template->assign_display('form_install');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function send_response($no_more_output = false)
+ {
+ $json_data_array = $this->prepare_json_array($no_more_output);
+
+ if (empty($json_data_array))
+ {
+ return;
+ }
+
+ $json_data = json_encode($json_data_array);
+
+ // Try to push content to the browser
+ print(str_pad(' ', 4096) . "\n");
+ print($json_data . "\n\n");
+ flush();
+ }
+
+ /**
+ * Prepares iohandler's data to be sent out to the client.
+ *
+ * @param bool $no_more_output Whether or not there will be more output in this response
+ *
+ * @return array
+ */
+ protected function prepare_json_array($no_more_output = false)
+ {
+ $json_array = array();
+
+ if (!empty($this->errors))
+ {
+ $json_array['errors'] = $this->errors;
+ $this->errors = array();
+ }
+
+ if (!empty($this->warnings))
+ {
+ $json_array['warnings'] = $this->warnings;
+ $this->warnings = array();
+ }
+
+ if (!empty($this->logs))
+ {
+ $json_array['logs'] = $this->logs;
+ $this->logs = array();
+ }
+
+ if (!empty($this->success))
+ {
+ $json_array['success'] = $this->success;
+ $this->success = array();
+ }
+
+ if (!empty($this->download))
+ {
+ $json_array['download'] = $this->download;
+ $this->download = array();
+ }
+
+ if (!empty($this->form))
+ {
+ $json_array['form'] = $this->form;
+ $this->form = '';
+ }
+
+ if (!empty($this->file_status))
+ {
+ $json_array['file_status'] = $this->file_status;
+ $this->file_status = '';
+ }
+
+ // If current task name is set, we push progress message to the client side
+ if (!empty($this->current_task_name))
+ {
+ $json_array['progress'] = array(
+ 'task_name' => $this->current_task_name,
+ 'task_num' => $this->current_task_progress,
+ 'task_count' => $this->task_progress_count,
+ );
+
+ if ($this->restart_progress_bar)
+ {
+ $json_array['progress']['restart'] = 1;
+ $this->restart_progress_bar = false;
+ }
+ }
+
+ if (!empty($this->nav_data))
+ {
+ $json_array['nav'] = $this->nav_data;
+ $this->nav_data = array();
+ }
+
+ if ($this->request_client_refresh)
+ {
+ $json_array['refresh'] = true;
+ $this->request_client_refresh = false;
+ }
+
+ if (!empty($this->cookies))
+ {
+ $json_array['cookies'] = $this->cookies;
+ $this->cookies = array();
+ }
+
+ if (!empty($this->redirect_url))
+ {
+ $json_array['redirect'] = $this->redirect_url;
+ $this->redirect_url = array();
+ }
+
+ if ($no_more_output)
+ {
+ $json_array['over'] = true;
+ }
+
+ return $json_array;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_progress($task_lang_key, $task_number)
+ {
+ parent::set_progress($task_lang_key, $task_number);
+ $this->send_response();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function request_refresh()
+ {
+ $this->request_client_refresh = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_active_stage_menu($menu_path)
+ {
+ $this->nav_data['active'] = $menu_path[sizeof($menu_path) - 1];
+ $this->send_response();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_finished_stage_menu($menu_path)
+ {
+ $this->nav_data['finished'][] = $menu_path[sizeof($menu_path) - 1];
+ $this->send_response();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_cookie($cookie_name, $cookie_value)
+ {
+ $this->cookies[] = array(
+ 'name' => $cookie_name,
+ 'value' => $cookie_value
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_download_link($route, $title, $msg = null)
+ {
+ $link_properties = array(
+ 'href' => $this->router->generate($route),
+ 'title' => $this->language->lang($title),
+ 'download' => $this->language->lang('DOWNLOAD'),
+ );
+
+ if ($msg !== null)
+ {
+ $link_properties['msg'] = htmlspecialchars_decode($this->language->lang($msg));
+ }
+
+ $this->download[] = $link_properties;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render_update_file_status($status_array)
+ {
+ $this->template->assign_vars(array(
+ 'T_IMAGE_PATH' => $this->path_helper->get_web_root_path() . 'adm/images/',
+ ));
+
+ foreach ($status_array as $block => $list)
+ {
+ foreach ($list as $filename)
+ {
+ $dirname = dirname($filename);
+
+ $this->template->assign_block_vars($block, array(
+ 'STATUS' => $block,
+ 'FILENAME' => $filename,
+ 'DIR_PART' => (!empty($dirname) && $dirname !== '.') ? dirname($filename) . '/' : false,
+ 'FILE_PART' => basename($filename),
+ ));
+ }
+ }
+
+ $this->template->set_filenames(array(
+ 'file_status' => 'installer_update_file_status.html',
+ ));
+
+ $this->file_status = $this->template->assign_display('file_status');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function redirect($url, $use_ajax = false)
+ {
+ $this->redirect_url = array('url' => $url, 'use_ajax' => $use_ajax);
+ $this->send_response(true);
+ }
+
+ /**
+ * Acquires a file lock
+ */
+ public function acquire_lock()
+ {
+ $lock_file = $this->phpbb_root_path . 'store/io_lock.lock';
+ $this->file_lock_pointer = @fopen($lock_file, 'w+');
+
+ if ($this->file_lock_pointer)
+ {
+ flock($this->file_lock_pointer, LOCK_EX);
+ }
+ }
+
+ /**
+ * Release file lock
+ */
+ public function release_lock()
+ {
+ if ($this->file_lock_pointer)
+ {
+ fwrite($this->file_lock_pointer, 'ok');
+ flock($this->file_lock_pointer, LOCK_UN);
+ fclose($this->file_lock_pointer);
+ }
+ }
+
+ /**
+ * Callback function for language replacing
+ *
+ * @param array $matches
+ * @return string
+ */
+ public function lang_replace_callback($matches)
+ {
+ if (!empty($matches[1]))
+ {
+ return $this->language->lang($matches[1]);
+ }
+
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php
new file mode 100644
index 0000000000..196cdcdaab
--- /dev/null
+++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php
@@ -0,0 +1,309 @@
+<?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\helper\iohandler;
+
+use phpbb\install\exception\installer_exception;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\OutputStyle;
+
+/**
+ * Input-Output handler for the CLI frontend
+ */
+class cli_iohandler extends iohandler_base
+{
+ /**
+ * @var OutputInterface
+ */
+ protected $output;
+
+ /**
+ * @var OutputStyle
+ */
+ protected $io;
+
+ /**
+ * @var array
+ */
+ protected $input_values = array();
+
+ /**
+ * @var \Symfony\Component\Console\Helper\ProgressBar
+ */
+ protected $progress_bar;
+
+ /**
+ * Set the style and output used to display feedback;
+ *
+ * @param OutputStyle $style
+ * @param OutputInterface $output
+ */
+ public function set_style(OutputStyle $style, OutputInterface $output)
+ {
+ $this->io = $style;
+ $this->output = $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_input($name, $default, $multibyte = false)
+ {
+ $result = $default;
+
+ if (isset($this->input_values[$name]))
+ {
+ $result = $this->input_values[$name];
+ }
+
+ if ($multibyte)
+ {
+ return utf8_normalize_nfc($result);
+ }
+
+ return $result;
+ }
+
+ public function set_input($name, $value)
+ {
+ $this->input_values[$name] = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_server_variable($name, $default = '')
+ {
+ return $default;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_header_variable($name, $default = '')
+ {
+ return $default;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_secure()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_user_form_group($title, $form)
+ {
+ throw new installer_exception('MISSING_DATA');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function send_response($no_more_output = false)
+ {
+ }
+
+ /**
+ * {@inheritdoc
+ */
+ public function add_error_message($error_title, $error_description = false)
+ {
+ $this->io->newLine();
+ $message = $this->translate_message($error_title, $error_description);
+ $message_string = $message['title'] . (!empty($message['description']) ? "\n" . $message['description'] : '');
+
+ if (strpos($message_string, '<br />') !== false)
+ {
+ $message_string = strip_tags(str_replace('<br />', "\n", $message_string));
+ }
+
+ $this->io->error($message_string);
+
+ if ($this->progress_bar !== null)
+ {
+ $this->io->newLine(2);
+ $this->progress_bar->display();
+ }
+ }
+
+ /**
+ * {@inheritdoc
+ */
+ public function add_warning_message($warning_title, $warning_description = false)
+ {
+ $this->io->newLine();
+
+ $message = $this->translate_message($warning_title, $warning_description);
+ $message_string = $message['title'] . (!empty($message['description']) ? "\n" . $message['description'] : '');
+ $this->io->warning($message_string);
+
+ if ($this->progress_bar !== null)
+ {
+ $this->io->newLine(2);
+ $this->progress_bar->display();
+ }
+ }
+
+ /**
+ * {@inheritdoc
+ */
+ public function add_log_message($log_title, $log_description = false)
+ {
+ if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL)
+ {
+ $message = $this->translate_message($log_title, $log_description);
+ $this->output->writeln(sprintf('[%3d/%-3d] ---- %s', $this->current_task_progress, $this->task_progress_count, $message['title']));
+ }
+ }
+
+ /**
+ * {@inheritdoc
+ */
+ public function add_success_message($error_title, $error_description = false)
+ {
+ $this->io->newLine();
+
+ $message = $this->translate_message($error_title, $error_description);
+ $message_string = $message['title'] . (!empty($message['description']) ? "\n" . $message['description'] : '');
+ $this->io->success($message_string);
+
+ if ($this->progress_bar !== null)
+ {
+ $this->io->newLine(2);
+ $this->progress_bar->display();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_task_count($task_count, $restart = false)
+ {
+ parent::set_task_count($task_count, $restart);
+
+ if ($this->output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL)
+ {
+ if ($this->progress_bar !== null)
+ {
+ // Symfony's ProgressBar is immutable regarding task_count, so delete the old and create a new one.
+ $this->progress_bar->clear();
+ }
+ else
+ {
+ $this->io->newLine(2);
+ }
+
+ $this->progress_bar = $this->io->createProgressBar($task_count);
+ $this->progress_bar->setFormat(
+ " %current:3s%/%max:-3s% %bar% %percent:3s%%\n" .
+ " %message%\n");
+ $this->progress_bar->setBarWidth(60);
+
+ if (!defined('PHP_WINDOWS_VERSION_BUILD'))
+ {
+ $this->progress_bar->setEmptyBarCharacter('â–‘'); // light shade character \u2591
+ $this->progress_bar->setProgressCharacter('');
+ $this->progress_bar->setBarCharacter('â–“'); // dark shade character \u2593
+ }
+
+ $this->progress_bar->setMessage('');
+ $this->progress_bar->start();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_progress($task_lang_key, $task_number)
+ {
+ parent::set_progress($task_lang_key, $task_number);
+
+ if ($this->progress_bar !== null)
+ {
+ $this->progress_bar->setProgress($this->current_task_progress);
+ $this->progress_bar->setMessage($this->current_task_name);
+ }
+ else
+ {
+ $this->output->writeln(sprintf('[%3d/%-3d] %s', $this->current_task_progress, $this->task_progress_count, $this->current_task_name));
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function finish_progress($message_lang_key)
+ {
+ parent::finish_progress($message_lang_key);
+
+ if ($this->progress_bar !== null)
+ {
+ $this->progress_bar->finish();
+ $this->progress_bar = null;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function request_refresh()
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_active_stage_menu($menu_path)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_finished_stage_menu($menu_path)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_cookie($cookie_name, $cookie_value)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_download_link($route, $title, $msg = null)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render_update_file_status($status_array)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function redirect($url, $use_ajax = false)
+ {
+ }
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php b/phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php
new file mode 100644
index 0000000000..f2ddeda6f7
--- /dev/null
+++ b/phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php
@@ -0,0 +1,19 @@
+<?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\helper\iohandler\exception;
+
+class iohandler_not_implemented_exception extends \Exception
+{
+
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/factory.php b/phpBB/phpbb/install/helper/iohandler/factory.php
new file mode 100644
index 0000000000..1e8395760a
--- /dev/null
+++ b/phpBB/phpbb/install/helper/iohandler/factory.php
@@ -0,0 +1,79 @@
+<?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\helper\iohandler;
+
+use phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception;
+
+/**
+ * Input-output handler factory
+ */
+class factory
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * @var string
+ */
+ protected $environment;
+
+ /**
+ * Constructor
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container
+ */
+ public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container)
+ {
+ $this->container = $container;
+ $this->environment = null;
+ }
+
+ /**
+ * @param string $environment The name of the input-output handler to use
+ */
+ public function set_environment($environment)
+ {
+ $this->environment = $environment;
+ }
+
+ /**
+ * Factory getter for iohandler
+ *
+ * @return \phpbb\install\helper\iohandler\iohandler_interface
+ *
+ * @throws \phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception
+ * When the specified iohandler_interface does not exists
+ */
+ public function get()
+ {
+ switch ($this->environment)
+ {
+ case 'ajax':
+ return $this->container->get('installer.helper.iohandler_ajax');
+ break;
+ case 'nojs':
+ // @todo replace this
+ return $this->container->get('installer.helper.iohandler_ajax');
+ break;
+ case 'cli':
+ return $this->container->get('installer.helper.iohandler_cli');
+ break;
+ default:
+ throw new iohandler_not_implemented_exception();
+ break;
+ }
+ }
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php
new file mode 100644
index 0000000000..fed4bc101f
--- /dev/null
+++ b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php
@@ -0,0 +1,204 @@
+<?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\helper\iohandler;
+
+/**
+ * Base class for installer input-output handlers
+ */
+abstract class iohandler_base implements iohandler_interface
+{
+ /**
+ * Array of errors
+ *
+ * Errors should be added, when the installation cannot continue without
+ * user interaction. If the aim is to notify the user about something, please
+ * use a warning instead.
+ *
+ * @var array
+ */
+ protected $errors;
+
+ /**
+ * Array of warnings
+ *
+ * @var array
+ */
+ protected $warnings;
+
+ /**
+ * Array of logs
+ *
+ * @var array
+ */
+ protected $logs;
+
+ /**
+ * Array of success messages
+ *
+ * @var array
+ */
+ protected $success;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var int
+ */
+ protected $task_progress_count;
+
+ /**
+ * @var int
+ */
+ protected $current_task_progress;
+
+ /**
+ * @var string
+ */
+ protected $current_task_name;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->errors = array();
+ $this->warnings = array();
+ $this->logs = array();
+ $this->success = array();
+
+ $this->restart_progress_bar = false;
+ $this->task_progress_count = 0;
+ $this->current_task_progress = 0;
+ $this->current_task_name = '';
+ }
+
+ /**
+ * Set language service
+ *
+ * @param \phpbb\language\language $language
+ */
+ public function set_language(\phpbb\language\language $language)
+ {
+ $this->language = $language;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_error_message($error_title, $error_description = false)
+ {
+ if (!is_array($error_title) && strpos($error_title, '<br />') !== false)
+ {
+ $error_title = strip_tags(htmlspecialchars_decode($error_title));
+ }
+ $this->errors[] = $this->translate_message($error_title, $error_description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_warning_message($warning_title, $warning_description = false)
+ {
+ $this->warnings[] = $this->translate_message($warning_title, $warning_description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_log_message($log_title, $log_description = false)
+ {
+ $this->logs[] = $this->translate_message($log_title, $log_description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_success_message($success_title, $success_description = false)
+ {
+ $this->success[] = $this->translate_message($success_title, $success_description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_task_count($task_count, $restart = false)
+ {
+ $this->task_progress_count = $task_count;
+ $this->restart_progress_bar = $restart;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_progress($task_lang_key, $task_number)
+ {
+ $this->current_task_name = '';
+
+ if (!empty($task_lang_key))
+ {
+ $this->current_task_name = $this->language->lang($task_lang_key);
+ }
+
+ $this->current_task_progress = $task_number;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function finish_progress($message_lang_key)
+ {
+ if (!empty($message_lang_key))
+ {
+ $this->current_task_name = $this->language->lang($message_lang_key);
+ }
+
+ $this->current_task_progress = $this->task_progress_count;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function generate_form_render_data($title, $form)
+ {
+ return '';
+ }
+
+ /**
+ * Localize message.
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param array|string $title Title of the message
+ * @param array|string|bool $description Description of the message
+ *
+ * @return array Localized message in an array
+ */
+ protected function translate_message($title, $description)
+ {
+ $message_array = array();
+
+ $message_array['title'] = call_user_func_array(array($this->language, 'lang'), (array) $title);
+
+ if ($description !== false)
+ {
+ $message_array['description'] = call_user_func_array(array($this->language, 'lang'), (array) $description);
+ }
+
+ return $message_array;
+ }
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php
new file mode 100644
index 0000000000..f22f33d9cb
--- /dev/null
+++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php
@@ -0,0 +1,211 @@
+<?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\helper\iohandler;
+
+/**
+ * Input-Output handler interface for the installer
+ */
+interface iohandler_interface
+{
+ /**
+ * Renders or returns response message
+ *
+ * @param bool $no_more_output Whether or not there will be more output in this output unit
+ */
+ public function send_response($no_more_output = false);
+
+ /**
+ * Returns input variable
+ *
+ * @param string $name Name of the input variable to obtain
+ * @param mixed $default A default value that is returned if the variable was not set.
+ * This function will always return a value of the same type as the default.
+ * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters
+ * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks
+ *
+ * @return mixed Value of the input variable
+ */
+ public function get_input($name, $default, $multibyte = false);
+
+ /**
+ * Returns server variable
+ *
+ * This function should work the same as request_interterface::server().
+ *
+ * @param string $name Name of the server variable
+ * @param mixed $default Default value to return when the requested variable does not exist
+ *
+ * @return mixed Value of the server variable
+ */
+ public function get_server_variable($name, $default = '');
+
+ /**
+ * Wrapper function for request_interterface::header()
+ *
+ * @param string $name Name of the request header variable
+ * @param mixed $default Default value to return when the requested variable does not exist
+ *
+ * @return mixed
+ */
+ public function get_header_variable($name, $default = '');
+
+ /**
+ * Returns true if the connection is encrypted
+ *
+ * @return bool
+ */
+ public function is_secure();
+
+ /**
+ * Adds an error message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $error_title Title of the error message.
+ * @param string|bool|array $error_description Description of the error (and possibly guidelines to resolve it),
+ * or false if the error description is not available.
+ */
+ public function add_error_message($error_title, $error_description = false);
+
+ /**
+ * Adds a warning message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $warning_title Title of the warning message
+ * @param string|bool|array $warning_description Description of the warning (and possibly guidelines to resolve it),
+ * or false if the warning description is not available
+ */
+ public function add_warning_message($warning_title, $warning_description = false);
+
+ /**
+ * Adds a log message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $log_title Title of the log message
+ * @param string|bool|array $log_description Description of the log,
+ * or false if the log description is not available
+ */
+ public function add_log_message($log_title, $log_description = false);
+
+ /**
+ * Adds a success message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $success_title Title of the success message
+ * @param string|bool|array $success_description Description of the success,
+ * or false if the success description is not available
+ *
+ * @return null
+ */
+ public function add_success_message($success_title, $success_description = false);
+
+ /**
+ * Adds a requested data group to the rendering queue
+ *
+ * @param string $title Language variable with the title of the form
+ * @param array $form An array describing the required data (options etc)
+ */
+ public function add_user_form_group($title, $form);
+
+ /**
+ * Returns the rendering information for the form
+ *
+ * @param string $title Language variable with the title of the form
+ * @param array $form An array describing the required data (options etc)
+ *
+ * @return string Information to render the form
+ */
+ public function generate_form_render_data($title, $form);
+
+ /**
+ * Sets the number of tasks belonging to the installer in the current mode.
+ *
+ * @param int $task_count Number of tasks
+ * @param bool $restart Whether or not to restart the progress bar, false by default
+ */
+ public function set_task_count($task_count, $restart = false);
+
+ /**
+ * Sets the progress information
+ *
+ * @param string $task_lang_key Language key for the name of the task
+ * @param int $task_number Position of the current task in the task queue
+ */
+ public function set_progress($task_lang_key, $task_number);
+
+ /**
+ * Sends refresh request to the client
+ */
+ public function request_refresh();
+
+ /**
+ * Marks stage as active in the navigation bar
+ *
+ * @param array $menu_path Array to the navigation elem
+ */
+ public function set_active_stage_menu($menu_path);
+
+ /**
+ * Marks stage as completed in the navigation bar
+ *
+ * @param array $menu_path Array to the navigation elem
+ */
+ public function set_finished_stage_menu($menu_path);
+
+ /**
+ * Finish the progress bar
+ *
+ * @param string $message_lang_key Language key for the message
+ */
+ public function finish_progress($message_lang_key);
+
+ /**
+ * Adds a download link
+ *
+ * @param string $route Route for the link
+ * @param string $title Language key for the title
+ * @param string|null|array $msg Language key for the message
+ */
+ public function add_download_link($route, $title, $msg = null);
+
+ /**
+ * Redirects the user to a new page
+ *
+ * @param string $url URL to redirect to
+ * @param bool $use_ajax Whether or not to use AJAX redirect
+ */
+ public function redirect($url, $use_ajax = false);
+
+ /**
+ * Renders the status of update files
+ *
+ * @param array $status_array Array containing files in groups to render
+ */
+ public function render_update_file_status($status_array);
+
+ /**
+ * Sends and sets cookies
+ *
+ * @param string $cookie_name Name of the cookie to set
+ * @param string $cookie_value Value of the cookie to set
+ */
+ public function set_cookie($cookie_name, $cookie_value);
+}
diff --git a/phpBB/phpbb/install/helper/navigation/convertor_navigation.php b/phpBB/phpbb/install/helper/navigation/convertor_navigation.php
new file mode 100644
index 0000000000..54cab83b1d
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/convertor_navigation.php
@@ -0,0 +1,78 @@
+<?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\helper\navigation;
+
+use phpbb\install\helper\install_helper;
+
+class convertor_navigation implements navigation_interface
+{
+ /**
+ * @var install_helper
+ */
+ private $install_helper;
+
+ /**
+ * Constructor
+ *
+ * @param install_helper $install_helper
+ */
+ public function __construct(install_helper $install_helper)
+ {
+ $this->install_helper = $install_helper;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get()
+ {
+ if (!$this->install_helper->is_phpbb_installed())
+ {
+ return array();
+ }
+
+ return array(
+ 'convert' => array(
+ 'label' => 'CONVERT',
+ 'route' => 'phpbb_convert_intro',
+ 'order' => 3,
+ array(
+ 'intro' => array(
+ 'label' => 'SUB_INTRO',
+ 'stage' => true,
+ 'order' => 0,
+ ),
+ 'settings' => array(
+ 'label' => 'STAGE_SETTINGS',
+ 'stage' => true,
+ 'route' => 'phpbb_convert_settings',
+ 'order' => 1,
+ ),
+ 'convert' => array(
+ 'label' => 'STAGE_IN_PROGRESS',
+ 'stage' => true,
+ 'route' => 'phpbb_convert_convert',
+ 'order' => 2,
+ ),
+ 'finish' => array(
+ 'label' => 'CONVERT_COMPLETE',
+ 'stage' => true,
+ 'route' => 'phpbb_convert_finish',
+ 'order' => 3,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/install/helper/navigation/install_navigation.php b/phpBB/phpbb/install/helper/navigation/install_navigation.php
new file mode 100644
index 0000000000..f690f8de76
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/install_navigation.php
@@ -0,0 +1,75 @@
+<?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\helper\navigation;
+
+use phpbb\install\helper\install_helper;
+
+class install_navigation implements navigation_interface
+{
+ /**
+ * @var install_helper
+ */
+ private $install_helper;
+
+ /**
+ * Constructor
+ *
+ * @param install_helper $install_helper
+ */
+ public function __construct(install_helper $install_helper)
+ {
+ $this->install_helper = $install_helper;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get()
+ {
+ if ($this->install_helper->is_phpbb_installed())
+ {
+ return array();
+ }
+
+ return array(
+ 'install' => array(
+ 'label' => 'INSTALL',
+ 'route' => 'phpbb_installer_install',
+ 'order' => 1,
+ array(
+ 'introduction' => array(
+ 'label' => 'INTRODUCTION_TITLE',
+ 'stage' => true,
+ 'order' => 0,
+ ),
+ 'requirements' => array(
+ 'label' => 'STAGE_REQUIREMENTS',
+ 'stage' => true,
+ 'order' => 1,
+ ),
+ 'obtain_data' => array(
+ 'label' => 'STAGE_OBTAIN_DATA',
+ 'stage' => true,
+ 'order' => 2,
+ ),
+ 'install' => array(
+ 'label' => 'STAGE_INSTALL',
+ 'stage' => true,
+ 'order' => 3,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/install/helper/navigation/main_navigation.php b/phpBB/phpbb/install/helper/navigation/main_navigation.php
new file mode 100644
index 0000000000..214bb04963
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/main_navigation.php
@@ -0,0 +1,48 @@
+<?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\helper\navigation;
+
+class main_navigation implements navigation_interface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get()
+ {
+ return array(
+ 'overview' => array(
+ 'label' => 'MENU_OVERVIEW',
+ 'route' => 'phpbb_installer_index',
+ 'order' => 0,
+ array(
+ 'introduction' => array(
+ 'label' => 'MENU_INTRO',
+ 'route' => 'phpbb_installer_index',
+ 'order' => 0,
+ ),
+ 'support' => array(
+ 'label' => 'MENU_SUPPORT',
+ 'route' => 'phpbb_installer_support',
+ 'order' => 1,
+ ),
+ 'license' => array(
+ 'label' => 'MENU_LICENSE',
+ 'route' => 'phpbb_installer_license',
+ 'order' => 2,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/install/helper/navigation/navigation_interface.php b/phpBB/phpbb/install/helper/navigation/navigation_interface.php
new file mode 100644
index 0000000000..eebdbe923f
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/navigation_interface.php
@@ -0,0 +1,43 @@
+<?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\helper\navigation;
+
+/**
+ * Interface for installer's navigation defining services
+ */
+interface navigation_interface
+{
+ /**
+ * Returns an array with the navigation items
+ *
+ * The returned array should have the following format:
+ * <code>
+ * array(
+ * 'parent_nav_name' => array(
+ * 'nav_name' => array(
+ * 'label' => 'MY_MENU',
+ * 'route' => 'phpbb_route_name',
+ * )
+ * )
+ * )
+ * </code>
+ *
+ * Navigation item setting options:
+ * - label: The language variable name
+ * - route: Name of the route which it is belongs to
+ *
+ * @return array
+ */
+ public function get();
+}
diff --git a/phpBB/phpbb/install/helper/navigation/navigation_provider.php b/phpBB/phpbb/install/helper/navigation/navigation_provider.php
new file mode 100644
index 0000000000..d52aec8999
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/navigation_provider.php
@@ -0,0 +1,121 @@
+<?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\helper\navigation;
+
+use phpbb\di\service_collection;
+
+/**
+ * Installers navigation provider
+ */
+class navigation_provider
+{
+ /**
+ * @var array
+ */
+ private $menu_collection;
+
+ /**
+ * Constructor
+ *
+ * @param service_collection $plugins
+ */
+ public function __construct(service_collection $plugins)
+ {
+ $this->menu_collection = array();
+
+ foreach ($plugins as $plugin => $plugin_instance)
+ {
+ $this->register($plugin_instance);
+ }
+ }
+
+ /**
+ * Returns navigation array
+ *
+ * @return array
+ */
+ public function get()
+ {
+ return $this->menu_collection;
+ }
+
+ /**
+ * Registers a navigation provider's navigation items
+ *
+ * @param navigation_interface $navigation
+ */
+ public function register(navigation_interface $navigation)
+ {
+ $nav_arry = $navigation->get();
+ $this->menu_collection = $this->merge($nav_arry, $this->menu_collection);
+ }
+
+ /**
+ * Set a property in the navigation array
+ *
+ * @param array $nav_element Array to the navigation elem
+ * @param array $property_array Array with the properties to set
+ */
+ public function set_nav_property($nav_element, $property_array)
+ {
+ $array_pointer = array();
+ $array_root_pointer = &$array_pointer;
+ foreach ($nav_element as $array_path)
+ {
+ $array_pointer[$array_path] = array();
+ $array_pointer = &$array_pointer[$array_path];
+ }
+
+ $array_pointer = $property_array;
+
+ $this->menu_collection = $this->merge($array_root_pointer, $this->menu_collection);
+ }
+
+ /**
+ * Recursive array merge
+ *
+ * This function is necessary to be able to replace the options of
+ * already set navigation items.
+ *
+ * @param array $array_to_merge
+ * @param array $array_to_merge_into
+ *
+ * @return array Merged array
+ */
+ private function merge($array_to_merge, $array_to_merge_into)
+ {
+ $merged_array = $array_to_merge_into;
+
+ foreach ($array_to_merge as $key => $value)
+ {
+ if (isset($array_to_merge_into[$key]))
+ {
+ if (is_array($array_to_merge_into[$key]) && is_array($value))
+ {
+ $merged_array[$key] = $this->merge($value, $array_to_merge_into[$key]);
+ }
+ else
+ {
+ $merged_array[$key] = $value;
+ }
+ }
+ else
+ {
+ $merged_array[$key] = $value;
+ }
+ }
+
+ return $merged_array;
+ }
+}
diff --git a/phpBB/phpbb/install/helper/navigation/update_navigation.php b/phpBB/phpbb/install/helper/navigation/update_navigation.php
new file mode 100644
index 0000000000..3d239c3451
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/update_navigation.php
@@ -0,0 +1,80 @@
+<?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\helper\navigation;
+
+use phpbb\install\helper\install_helper;
+
+class update_navigation implements navigation_interface
+{
+ /**
+ * @var install_helper
+ */
+ private $install_helper;
+
+ /**
+ * Constructor
+ *
+ * @param install_helper $install_helper
+ */
+ public function __construct(install_helper $install_helper)
+ {
+ $this->install_helper = $install_helper;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get()
+ {
+ if (!$this->install_helper->is_phpbb_installed())
+ {
+ return array();
+ }
+
+ return array(
+ 'update' => array(
+ 'label' => 'UPDATE',
+ 'route' => 'phpbb_installer_update',
+ 'order' => 1,
+ array(
+ 'introduction' => array(
+ 'label' => 'INTRODUCTION_TITLE',
+ 'stage' => true,
+ 'order' => 0,
+ ),
+ 'requirements' => array(
+ 'label' => 'STAGE_REQUIREMENTS',
+ 'stage' => true,
+ 'order' => 1,
+ ),
+ 'obtain_data' => array(
+ 'label' => 'STAGE_OBTAIN_DATA',
+ 'stage' => true,
+ 'order' => 2,
+ ),
+ 'update_files' => array(
+ 'label' => 'STAGE_UPDATE_FILES',
+ 'stage' => true,
+ 'order' => 3,
+ ),
+ 'update_database' => array(
+ 'label' => 'STAGE_UPDATE_DATABASE',
+ 'stage' => true,
+ 'order' => 4,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/install/helper/update_helper.php b/phpBB/phpbb/install/helper/update_helper.php
new file mode 100644
index 0000000000..a00731d317
--- /dev/null
+++ b/phpBB/phpbb/install/helper/update_helper.php
@@ -0,0 +1,113 @@
+<?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\helper;
+
+/**
+ * General helper functionality for the updater
+ */
+class update_helper
+{
+ /**
+ * @var string
+ */
+ protected $path_to_new_files;
+
+ /**
+ * @var string
+ */
+ protected $path_to_old_files;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param string $phpbb_root_path
+ */
+ public function __construct($phpbb_root_path)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->path_to_new_files = $phpbb_root_path . 'install/update/new/';
+ $this->path_to_old_files = $phpbb_root_path . 'install/update/old/';
+ }
+
+ /**
+ * Returns path to new update files
+ *
+ * @return string
+ */
+ public function get_path_to_new_update_files()
+ {
+ return $this->path_to_new_files;
+ }
+
+ /**
+ * Returns path to new update files
+ *
+ * @return string
+ */
+ public function get_path_to_old_update_files()
+ {
+ return $this->path_to_old_files;
+ }
+
+ /**
+ * Includes the updated file if available
+ *
+ * @param string $filename Path to the file relative to phpBB root path
+ */
+ public function include_file($filename)
+ {
+ if (is_file($this->path_to_new_files . $filename))
+ {
+ include_once($this->path_to_new_files . $filename);
+ }
+ else if (is_file($this->phpbb_root_path . $filename))
+ {
+ include_once($this->phpbb_root_path . $filename);
+ }
+ }
+
+ /**
+ * Customized version_compare()
+ *
+ * @param string $version_number1
+ * @param string $version_number2
+ * @param string|null $operator
+ * @return int|bool The returned value is identical to the PHP build-in function version_compare()
+ */
+ public function phpbb_version_compare($version_number1, $version_number2, $operator = null)
+ {
+ if ($operator === null)
+ {
+ $result = version_compare(
+ str_replace('rc', 'RC', strtolower($version_number1)),
+ str_replace('rc', 'RC', strtolower($version_number2))
+ );
+ }
+ else
+ {
+ $result = version_compare(
+ str_replace('rc', 'RC', strtolower($version_number1)),
+ str_replace('rc', 'RC', strtolower($version_number2)),
+ $operator
+ );
+ }
+
+ return $result;
+ }
+}
diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php
new file mode 100644
index 0000000000..240423ae78
--- /dev/null
+++ b/phpBB/phpbb/install/installer.php
@@ -0,0 +1,337 @@
+<?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;
+
+use phpbb\cache\driver\driver_interface;
+use phpbb\di\ordered_service_collection;
+use phpbb\install\exception\cannot_build_container_exception;
+use phpbb\install\exception\installer_config_not_writable_exception;
+use phpbb\install\exception\jump_to_restart_point_exception;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\iohandler\ajax_iohandler;
+use phpbb\install\helper\iohandler\cli_iohandler;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\path_helper;
+
+class installer
+{
+ /**
+ * @var driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var container_factory
+ */
+ protected $container_factory;
+
+ /**
+ * @var config
+ */
+ protected $install_config;
+
+ /**
+ * @var ordered_service_collection
+ */
+ protected $installer_modules;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $web_root;
+
+ /**
+ * Stores the number of steps that a given module has
+ *
+ * @var array
+ */
+ protected $module_step_count;
+
+ /**
+ * @var bool
+ */
+ protected $purge_cache_before;
+
+ /**
+ * Constructor
+ *
+ * @param driver_interface $cache Cache service
+ * @param config $config Installer config handler
+ * @param path_helper $path_helper Path helper
+ * @param container_factory $container Container
+ */
+ public function __construct(driver_interface $cache, config $config, path_helper $path_helper, container_factory $container)
+ {
+ $this->cache = $cache;
+ $this->install_config = $config;
+ $this->container_factory = $container;
+ $this->installer_modules = null;
+ $this->web_root = $path_helper->get_web_root_path();
+ $this->purge_cache_before = false;
+ }
+
+ /**
+ * Sets modules to execute
+ *
+ * Note: The installer will run modules in the order they are set in
+ * the array.
+ *
+ * @param ordered_service_collection $modules Service collection of module service names
+ */
+ public function set_modules(ordered_service_collection $modules)
+ {
+ $this->installer_modules = $modules;
+ }
+
+ /**
+ * Sets input-output handler objects
+ *
+ * @param iohandler_interface $iohandler
+ */
+ public function set_iohandler(iohandler_interface $iohandler)
+ {
+ $this->iohandler = $iohandler;
+ }
+
+ /**
+ * Sets whether to purge cache before the installation process
+ *
+ * @param bool $purge_cache_before
+ */
+ public function set_purge_cache_before($purge_cache_before)
+ {
+ $this->purge_cache_before = $purge_cache_before;
+ }
+
+ /**
+ * Run phpBB installer
+ */
+ public function run()
+ {
+ if ($this->iohandler instanceof ajax_iohandler)
+ {
+ $this->iohandler->acquire_lock();
+ }
+
+ // Load install progress
+ $this->install_config->load_config();
+
+ if (!$this->install_config->get('cache_purged_before', false) && $this->purge_cache_before)
+ {
+ /** @var \phpbb\cache\driver\driver_interface $cache */
+ $cache = $this->container_factory->get('cache.driver');
+ $cache->purge();
+ $this->install_config->set('cache_purged_before', true);
+ }
+
+ // Recover install progress
+ $module_index = $this->recover_progress();
+
+ // Variable used to check if the install process have been finished
+ $install_finished = false;
+ $fail_cleanup = false;
+ $send_refresh = false;
+
+ // We are installing something, so the introduction stage can go now...
+ $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction'));
+ $this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction'));
+
+ if ($this->install_config->get_task_progress_count() === 0)
+ {
+ // Count all tasks in the current installer modules
+ $step_count = 0;
+
+ /** @var \phpbb\install\module_interface $module */
+ foreach ($this->installer_modules as $name => $module)
+ {
+ $module_step_count = $module->get_step_count();
+ $step_count += $module_step_count;
+ $this->module_step_count[$name] = $module_step_count;
+ }
+
+ // Set task count
+ $this->install_config->set_task_progress_count($step_count);
+ }
+
+ // Set up progress information
+ $this->iohandler->set_task_count(
+ $this->install_config->get_task_progress_count()
+ );
+
+ try
+ {
+ $iterator = $this->installer_modules->getIterator();
+
+ if ($module_index < $iterator->count())
+ {
+ $iterator->seek($module_index);
+ }
+ else
+ {
+ $iterator->seek($module_index - 1);
+ $iterator->next();
+ }
+
+ while ($iterator->valid())
+ {
+ $module = $iterator->current();
+ $name = $iterator->key();
+
+ // Check if module should be executed
+ if (!$module->is_essential() && !$module->check_requirements())
+ {
+ $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path());
+ $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path());
+
+ $this->iohandler->add_log_message(array(
+ 'SKIP_MODULE',
+ $name,
+ ));
+ $this->install_config->increment_current_task_progress($this->module_step_count[$name]);
+ }
+ else
+ {
+ // Set the correct stage in the navigation bar
+ $this->install_config->set_active_navigation_stage($module->get_navigation_stage_path());
+ $this->iohandler->set_active_stage_menu($module->get_navigation_stage_path());
+
+ $this->iohandler->send_response();
+
+ $module->run();
+
+ $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path());
+ $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path());
+ }
+
+ $module_index++;
+ $iterator->next();
+
+ // Save progress
+ $this->install_config->set_active_module($name, $module_index);
+
+ if ($iterator->valid() && ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0))
+ {
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ // Installation finished
+ $install_finished = true;
+
+ if ($this->iohandler instanceof cli_iohandler)
+ {
+ $this->iohandler->add_success_message('INSTALLER_FINISHED');
+ }
+ else
+ {
+ global $SID;
+ $acp_url = $this->web_root . 'adm/index.php' . $SID;
+ $this->iohandler->add_success_message('INSTALLER_FINISHED', array(
+ 'ACP_LINK',
+ $acp_url,
+ ));
+ }
+ }
+ catch (user_interaction_required_exception $e)
+ {
+ $this->iohandler->send_response(true);
+ }
+ catch (resource_limit_reached_exception $e)
+ {
+ $send_refresh = true;
+ }
+ catch (jump_to_restart_point_exception $e)
+ {
+ $this->install_config->jump_to_restart_point($e->get_restart_point_name());
+ $send_refresh = true;
+ }
+ catch (\Exception $e)
+ {
+ $this->iohandler->add_error_message($e->getMessage());
+ $this->iohandler->send_response(true);
+ $fail_cleanup = true;
+ }
+
+ if ($this->iohandler instanceof ajax_iohandler)
+ {
+ $this->iohandler->release_lock();
+ }
+
+ if ($install_finished)
+ {
+ // Send install finished message
+ $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count());
+ $this->iohandler->send_response(true);
+ }
+ else if ($send_refresh)
+ {
+ $this->iohandler->request_refresh();
+ $this->iohandler->send_response(true);
+ }
+
+ // Save install progress
+ try
+ {
+ if ($install_finished || $fail_cleanup)
+ {
+ $this->install_config->clean_up_config_file();
+ $this->cache->purge();
+
+ try
+ {
+ /** @var \phpbb\cache\driver\driver_interface $cache */
+ $cache = $this->container_factory->get('cache.driver');
+ $cache->purge();
+ }
+ catch (cannot_build_container_exception $e)
+ {
+ // Do not do anything, this just means there is no config.php yet
+ }
+ }
+ else
+ {
+ $this->install_config->save_config();
+ }
+ }
+ catch (installer_config_not_writable_exception $e)
+ {
+ // It is allowed to fail this test during requirements testing
+ $progress_data = $this->install_config->get_progress_data();
+
+ if ($progress_data['last_task_module_name'] !== 'installer.module.requirements_install')
+ {
+ $this->iohandler->add_error_message('INSTALLER_CONFIG_NOT_WRITABLE');
+ }
+ }
+ }
+
+ /**
+ * Recover install progress
+ *
+ * @return string Index of the next installer module to execute
+ */
+ protected function recover_progress()
+ {
+ $progress_array = $this->install_config->get_progress_data();
+ return $progress_array['last_task_module_index'];
+ }
+}
diff --git a/phpBB/phpbb/install/installer_configuration.php b/phpBB/phpbb/install/installer_configuration.php
new file mode 100644
index 0000000000..c660c99d0f
--- /dev/null
+++ b/phpBB/phpbb/install/installer_configuration.php
@@ -0,0 +1,143 @@
+<?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;
+
+use Symfony\Component\Config\Definition\Builder\TreeBuilder;
+use Symfony\Component\Config\Definition\ConfigurationInterface;
+
+class installer_configuration implements ConfigurationInterface
+{
+
+ /**
+ * Generates the configuration tree builder.
+ *
+ * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
+ */
+ public function getConfigTreeBuilder()
+ {
+ $treeBuilder = new TreeBuilder();
+ $rootNode = $treeBuilder->root('installer');
+ $rootNode
+ ->children()
+ ->arrayNode('admin')
+ ->children()
+ ->scalarNode('name')->defaultValue('admin')->cannotBeEmpty()->end()
+ ->scalarNode('password')->defaultValue('adminadmin')->cannotBeEmpty()->end()
+ ->scalarNode('email')->defaultValue('admin@example.org')->cannotBeEmpty()->end()
+ ->end()
+ ->end()
+ ->arrayNode('board')
+ ->children()
+ ->scalarNode('lang')
+ ->defaultValue('en')
+ ->cannotBeEmpty()
+ ->end()
+ ->scalarNode('name')
+ ->defaultValue('My Board')
+ ->cannotBeEmpty()
+ ->end()
+ ->scalarNode('description')
+ ->defaultValue('My amazing new phpBB board')
+ ->cannotBeEmpty()
+ ->end()
+ ->end()
+ ->end()
+ ->arrayNode('database')
+ ->children()
+ ->scalarNode('dbms')
+ ->defaultValue('sqlite3')
+ ->cannotBeEmpty()
+ ->isRequired()
+ ->end()
+ ->scalarNode('dbhost')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('dbport')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('dbuser')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('dbpasswd')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('dbname')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('table_prefix')
+ ->defaultValue('phpbb_')
+ ->cannotBeEmpty()
+ ->isRequired()
+ ->end()
+ ->end()
+ ->end()
+ ->arrayNode('email')
+ ->canBeEnabled()
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->booleanNode('smtp_delivery')
+ ->defaultValue(false)
+ ->treatNullLike(false)
+ ->end()
+ ->scalarNode('smtp_host')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('smtp_port')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('smtp_auth')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('smtp_user')
+ ->defaultValue(null)
+ ->end()
+ ->scalarNode('smtp_pass')
+ ->defaultValue(null)
+ ->end()
+ ->end()
+ ->end()
+ ->arrayNode('server')
+ ->children()
+ ->booleanNode('cookie_secure')
+ ->defaultValue(false)
+ ->treatNullLike(false)
+ ->end()
+ ->scalarNode('server_protocol')
+ ->defaultValue('http://')
+ ->cannotBeEmpty()
+ ->end()
+ ->booleanNode('force_server_vars')
+ ->defaultValue(false)
+ ->treatNullLike(false)
+ ->end()
+ ->scalarNode('server_name')
+ ->defaultValue('localhost')
+ ->cannotBeEmpty()
+ ->end()
+ ->integerNode('server_port')
+ ->defaultValue(80)
+ ->min(1)
+ ->cannotBeEmpty()
+ ->end()
+ ->scalarNode('script_path')
+ ->defaultValue('/')
+ ->cannotBeEmpty()
+ ->end()
+ ->end()
+ ->end()
+ ->end()
+ ;
+ return $treeBuilder;
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_data/module.php b/phpBB/phpbb/install/module/install_data/module.php
new file mode 100644
index 0000000000..77f1f73f1f
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_data/module.php
@@ -0,0 +1,28 @@
+<?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\install_data;
+
+/**
+ * Installer module for recovering and installing default data installation
+ */
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'install');
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_data/task/add_bots.php b/phpBB/phpbb/install/module/install_data/task/add_bots.php
new file mode 100644
index 0000000000..1f1cecceb2
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_data/task/add_bots.php
@@ -0,0 +1,263 @@
+<?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\install_data\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+
+class add_bots extends \phpbb\install\task_base
+{
+ /**
+ * A list of the web-crawlers/bots we recognise by default
+ *
+ * Candidates but not included:
+ * 'Accoona [Bot]' 'Accoona-AI-Agent/'
+ * 'ASPseek [Crawler]' 'ASPseek/'
+ * 'Boitho [Crawler]' 'boitho.com-dc/'
+ * 'Bunnybot [Bot]' 'powered by www.buncat.de'
+ * 'Cosmix [Bot]' 'cfetch/'
+ * 'Crawler Search [Crawler]' '.Crawler-Search.de'
+ * 'Findexa [Crawler]' 'Findexa Crawler ('
+ * 'GBSpider [Spider]' 'GBSpider v'
+ * 'genie [Bot]' 'genieBot ('
+ * 'Hogsearch [Bot]' 'oegp v. 1.3.0'
+ * 'Insuranco [Bot]' 'InsurancoBot'
+ * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler'
+ * 'ISC Systems [Bot]' 'ISC Systems iRc Search'
+ * 'Jyxobot [Bot]' 'Jyxobot/'
+ * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/'
+ * 'LinkWalker' 'LinkWalker'
+ * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html'
+ * 'Naver [Bot]' 'nhnbot@naver.com)'
+ * 'NetResearchServer' 'NetResearchServer/'
+ * 'Nimble [Crawler]' 'NimbleCrawler'
+ * 'Ocelli [Bot]' 'Ocelli/'
+ * 'Onsearch [Bot]' 'onCHECK-Robot'
+ * 'Orange [Spider]' 'OrangeSpider'
+ * 'Sproose [Bot]' 'http://www.sproose.com/bot'
+ * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)'
+ * 'Tbot [Bot]' 'Tbot/'
+ * 'Thumbshots [Capture]' 'thumbshots-de-Bot'
+ * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/'
+ * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)'
+ * 'WissenOnline [Bot]' 'WissenOnline-Bot'
+ * 'WWWeasel [Bot]' 'WWWeasel Robot v'
+ * 'Xaldon [Spider]' 'Xaldon WebSpider'
+ *
+ * @var array
+ */
+ protected $bot_list = array(
+ 'AdsBot [Google]' => array('AdsBot-Google', ''),
+ 'Alexa [Bot]' => array('ia_archiver', ''),
+ 'Alta Vista [Bot]' => array('Scooter/', ''),
+ 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
+ 'Baidu [Spider]' => array('Baiduspider', ''),
+ 'Bing [Bot]' => array('bingbot/', ''),
+ 'Exabot [Bot]' => array('Exabot', ''),
+ 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
+ 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
+ 'Francis [Bot]' => array('http://www.neomo.de/', ''),
+ 'Gigabot [Bot]' => array('Gigabot/', ''),
+ 'Google Adsense [Bot]' => array('Mediapartners-Google', ''),
+ 'Google Desktop' => array('Google Desktop', ''),
+ 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
+ 'Google [Bot]' => array('Googlebot', ''),
+ 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
+ 'Heritrix [Crawler]' => array('heritrix/1.', ''),
+ 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
+ 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
+ 'ichiro [Crawler]' => array('ichiro/', ''),
+ 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
+ 'Metager [Bot]' => array('MetagerBot/', ''),
+ 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
+ 'MSN [Bot]' => array('msnbot/', ''),
+ 'MSNbot Media' => array('msnbot-media/', ''),
+ 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
+ 'Online link [Validator]' => array('online link validator', ''),
+ 'psbot [Picsearch]' => array('psbot/0', ''),
+ 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
+ 'SEO Crawler' => array('SEO search Crawler/', ''),
+ 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
+ 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
+ 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
+ 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
+ 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
+ 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
+ 'Voyager [Bot]' => array('voyager/', ''),
+ 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
+ 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
+ 'W3C [Validator]' => array('W3C_Validator', ''),
+ 'YaCy [Bot]' => array('yacybot', ''),
+ 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
+ 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
+ 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
+ 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
+ );
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $io_handler;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $install_config Installer's config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Input-output handler for the installer
+ * @param \phpbb\install\helper\container_factory $container Installer's DI container
+ * @param \phpbb\language\language $language Language provider
+ * @param string $phpbb_root_path Relative path to phpBB root
+ * @param string $php_ext PHP extension
+ */
+ public function __construct(\phpbb\install\helper\config $install_config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ \phpbb\install\helper\container_factory $container,
+ \phpbb\language\language $language,
+ $phpbb_root_path,
+ $php_ext)
+ {
+ parent::__construct(true);
+
+ $this->db = $container->get('dbal.conn');
+ $this->install_config = $install_config;
+ $this->io_handler = $iohandler;
+ $this->language = $language;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = 'BOTS'";
+ $result = $this->db->sql_query($sql);
+ $group_id = (int) $this->db->sql_fetchfield('group_id');
+ $this->db->sql_freeresult($result);
+
+ if (!$group_id)
+ {
+ // If we reach this point then something has gone very wrong
+ $this->io_handler->add_error_message('NO_GROUP');
+ }
+
+ $i = $this->install_config->get('add_bot_index', 0);
+ $bot_list = array_slice($this->bot_list, $i);
+
+ foreach ($bot_list as $bot_name => $bot_ary)
+ {
+ $user_row = array(
+ 'user_type' => USER_IGNORE,
+ 'group_id' => $group_id,
+ 'username' => $bot_name,
+ 'user_regdate' => time(),
+ 'user_password' => '',
+ 'user_colour' => '9E8DA7',
+ 'user_email' => '',
+ 'user_lang' => $this->install_config->get('default_lang'),
+ 'user_style' => 1,
+ 'user_timezone' => 'UTC',
+ 'user_dateformat' => $this->language->lang('default_dateformat'),
+ 'user_allow_massemail' => 0,
+ 'user_allow_pm' => 0,
+ );
+
+ if (!function_exists('user_add'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
+ $user_id = user_add($user_row);
+
+ if (!$user_id)
+ {
+ // If we can't insert this user then continue to the next one to avoid inconsistent data
+ $this->io_handler->add_error_message('CONV_ERROR_INSERT_BOT');
+
+ $i++;
+ continue;
+ }
+
+ $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', array(
+ 'bot_active' => 1,
+ 'bot_name' => (string) $bot_name,
+ 'user_id' => (int) $user_id,
+ 'bot_agent' => (string) $bot_ary[0],
+ 'bot_ip' => (string) $bot_ary[1],
+ ));
+
+ $this->db->sql_query($sql);
+
+ $i++;
+
+ // Stop execution if resource limit is reached
+ if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)
+ {
+ break;
+ }
+ }
+
+ $this->install_config->set('add_bot_index', $i);
+
+ if ($i < sizeof($this->bot_list))
+ {
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_ADD_BOTS';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_data/task/add_languages.php b/phpBB/phpbb/install/module/install_data/task/add_languages.php
new file mode 100644
index 0000000000..7ffdf4f276
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_data/task/add_languages.php
@@ -0,0 +1,121 @@
+<?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\install_data\task;
+
+class add_languages extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\language\language_file_helper
+ */
+ protected $language_helper;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ * @param \phpbb\install\helper\container_factory $container Installer's DI container
+ * @param \phpbb\language\language_file_helper $language_helper Language file helper service
+ */
+ public function __construct(\phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ \phpbb\install\helper\container_factory $container,
+ \phpbb\language\language_file_helper $language_helper)
+ {
+ $this->db = $container->get('dbal.conn');
+ $this->iohandler = $iohandler;
+ $this->language_helper = $language_helper;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $languages = $this->language_helper->get_available_languages();
+ $installed_languages = array();
+
+ foreach ($languages as $lang_info)
+ {
+ $lang_pack = array(
+ 'lang_iso' => $lang_info['iso'],
+ 'lang_dir' => $lang_info['iso'],
+ 'lang_english_name' => htmlspecialchars($lang_info['name']),
+ 'lang_local_name' => htmlspecialchars($lang_info['local_name'], ENT_COMPAT, 'UTF-8'),
+ 'lang_author' => htmlspecialchars($lang_info['author'], ENT_COMPAT, 'UTF-8'),
+ );
+
+ $this->db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $this->db->sql_build_array('INSERT', $lang_pack));
+
+ $installed_languages[] = (int) $this->db->sql_nextid();
+ if ($this->db->get_sql_error_triggered())
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message($error['message']);
+ }
+ }
+
+ $sql = 'SELECT * FROM ' . PROFILE_FIELDS_TABLE;
+ $result = $this->db->sql_query($sql);
+
+ $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ foreach ($installed_languages as $lang_id)
+ {
+ $insert_buffer->insert(array(
+ 'field_id' => $row['field_id'],
+ 'lang_id' => $lang_id,
+
+ // Remove phpbb_ from field name
+ 'lang_name' => strtoupper(substr($row['field_name'], 6)),
+ 'lang_explain' => '',
+ 'lang_default_value' => '',
+ ));
+ }
+ }
+
+ $this->db->sql_freeresult($result);
+
+ $insert_buffer->flush();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_ADD_LANGUAGES';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_data/task/add_modules.php b/phpBB/phpbb/install/module/install_data/task/add_modules.php
new file mode 100644
index 0000000000..d21a5be823
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_data/task/add_modules.php
@@ -0,0 +1,568 @@
+<?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\install_data\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+
+class add_modules extends \phpbb\install\task_base
+{
+ /**
+ * @var config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\extension\manager
+ */
+ protected $extension_manager;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\module\module_manager
+ */
+ protected $module_manager;
+
+ /**
+ * Define the module structure so that we can populate the database without
+ * needing to hard-code module_id values
+ *
+ * @var array
+ */
+ protected $module_categories = array(
+ 'acp' => array(
+ 'ACP_CAT_GENERAL' => array(
+ 'ACP_QUICK_ACCESS',
+ 'ACP_BOARD_CONFIGURATION',
+ 'ACP_CLIENT_COMMUNICATION',
+ 'ACP_SERVER_CONFIGURATION',
+ ),
+ 'ACP_CAT_FORUMS' => array(
+ 'ACP_MANAGE_FORUMS',
+ 'ACP_FORUM_BASED_PERMISSIONS',
+ ),
+ 'ACP_CAT_POSTING' => array(
+ 'ACP_MESSAGES',
+ 'ACP_ATTACHMENTS',
+ ),
+ 'ACP_CAT_USERGROUP' => array(
+ 'ACP_CAT_USERS',
+ 'ACP_GROUPS',
+ 'ACP_USER_SECURITY',
+ ),
+ 'ACP_CAT_PERMISSIONS' => array(
+ 'ACP_GLOBAL_PERMISSIONS',
+ 'ACP_FORUM_BASED_PERMISSIONS',
+ 'ACP_PERMISSION_ROLES',
+ 'ACP_PERMISSION_MASKS',
+ ),
+ 'ACP_CAT_CUSTOMISE' => array(
+ 'ACP_STYLE_MANAGEMENT',
+ 'ACP_EXTENSION_MANAGEMENT',
+ 'ACP_LANGUAGE',
+ ),
+ 'ACP_CAT_MAINTENANCE' => array(
+ 'ACP_FORUM_LOGS',
+ 'ACP_CAT_DATABASE',
+ ),
+ 'ACP_CAT_SYSTEM' => array(
+ 'ACP_AUTOMATION',
+ 'ACP_GENERAL_TASKS',
+ 'ACP_MODULE_MANAGEMENT',
+ ),
+ 'ACP_CAT_DOT_MODS' => null,
+ ),
+ 'mcp' => array(
+ 'MCP_MAIN' => null,
+ 'MCP_QUEUE' => null,
+ 'MCP_REPORTS' => null,
+ 'MCP_NOTES' => null,
+ 'MCP_WARN' => null,
+ 'MCP_LOGS' => null,
+ 'MCP_BAN' => null,
+ ),
+ 'ucp' => array(
+ 'UCP_MAIN' => null,
+ 'UCP_PROFILE' => null,
+ 'UCP_PREFS' => null,
+ 'UCP_PM' => null,
+ 'UCP_USERGROUPS' => null,
+ 'UCP_ZEBRA' => null,
+ ),
+ );
+
+ /**
+ * @var array
+ */
+ protected $module_categories_basenames = array(
+ 'UCP_PM' => 'ucp_pm',
+ );
+
+ /**
+ * @var array
+ */
+ protected $module_extras = array(
+ 'acp' => array(
+ 'ACP_QUICK_ACCESS' => array(
+ 'ACP_MANAGE_USERS',
+ 'ACP_GROUPS_MANAGE',
+ 'ACP_MANAGE_FORUMS',
+ 'ACP_MOD_LOGS',
+ 'ACP_BOTS',
+ 'ACP_PHP_INFO',
+ ),
+ 'ACP_FORUM_BASED_PERMISSIONS' => array(
+ 'ACP_FORUM_PERMISSIONS',
+ 'ACP_FORUM_PERMISSIONS_COPY',
+ 'ACP_FORUM_MODERATORS',
+ 'ACP_USERS_FORUM_PERMISSIONS',
+ 'ACP_GROUPS_FORUM_PERMISSIONS',
+ ),
+ ),
+ );
+
+ /**
+ * Constructor
+ *
+ * @parma config $config Installer's config
+ * @param iohandler_interface $iohandler Installer's input-output handler
+ * @param container_factory $container Installer's DI container
+ */
+ public function __construct(config $config, iohandler_interface $iohandler, container_factory $container)
+ {
+ $this->config = $config;
+ $this->db = $container->get('dbal.conn');
+ $this->extension_manager = $container->get('ext.manager');
+ $this->iohandler = $iohandler;
+ $this->module_manager = $container->get('module.manager');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $module_classes = array('acp', 'mcp', 'ucp');
+ $total = sizeof($module_classes);
+ $i = $this->config->get('module_class_index', 0);
+ $module_classes = array_slice($module_classes, $i);
+
+ foreach ($module_classes as $module_class)
+ {
+ $categories = $this->config->get('module_categories_array', array());
+
+ $k = $this->config->get('module_categories_index', 0);
+ $module_categories = array_slice($this->module_categories[$module_class], $k);
+ $timed_out = false;
+
+ foreach ($module_categories as $cat_name => $subs)
+ {
+ // Check if this sub-category has a basename. If it has, use it.
+ $basename = (isset($this->module_categories_basenames[$cat_name])) ? $this->module_categories_basenames[$cat_name] : '';
+
+ $module_data = array(
+ 'module_basename' => $basename,
+ 'module_enabled' => 1,
+ 'module_display' => 1,
+ 'parent_id' => 0,
+ 'module_class' => $module_class,
+ 'module_langname' => $cat_name,
+ 'module_mode' => '',
+ 'module_auth' => '',
+ );
+
+ $this->module_manager->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($this->db->get_sql_error_triggered())
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+
+ $categories[$cat_name]['id'] = (int) $module_data['module_id'];
+ $categories[$cat_name]['parent_id'] = 0;
+
+ if (is_array($subs))
+ {
+ foreach ($subs as $level2_name)
+ {
+ // Check if this sub-category has a basename. If it has, use it.
+ $basename = (isset($this->module_categories_basenames[$level2_name])) ? $this->module_categories_basenames[$level2_name] : '';
+
+ $module_data = array(
+ 'module_basename' => $basename,
+ 'module_enabled' => 1,
+ 'module_display' => 1,
+ 'parent_id' => (int) $categories[$cat_name]['id'],
+ 'module_class' => $module_class,
+ 'module_langname' => $level2_name,
+ 'module_mode' => '',
+ 'module_auth' => '',
+ );
+
+ $this->module_manager->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($this->db->get_sql_error_triggered())
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+
+ $categories[$level2_name]['id'] = (int) $module_data['module_id'];
+ $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id'];
+ }
+ }
+
+ $k++;
+
+ // Stop execution if resource limit is reached
+ if ($this->config->get_time_remaining() <= 0 || $this->config->get_memory_remaining() <= 0)
+ {
+ $timed_out = true;
+ break;
+ }
+ }
+
+ $this->config->set('module_categories_array', $categories);
+ $this->config->set('module_categories_index', $k);
+
+ if ($timed_out)
+ {
+ throw new resource_limit_reached_exception();
+ }
+
+ // Get the modules we want to add... returned sorted by name
+ $module_info = $this->module_manager->get_module_infos($module_class);
+
+ $k = $this->config->get('module_info_index', 0);
+ $module_info = array_slice($module_info, $k);
+
+ foreach ($module_info as $module_basename => $fileinfo)
+ {
+ foreach ($fileinfo['modes'] as $module_mode => $row)
+ {
+ foreach ($row['cat'] as $cat_name)
+ {
+ if (!isset($categories[$cat_name]))
+ {
+ continue;
+ }
+
+ $module_data = array(
+ 'module_basename' => $module_basename,
+ 'module_enabled' => 1,
+ 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1,
+ 'parent_id' => (int) $categories[$cat_name]['id'],
+ 'module_class' => $module_class,
+ 'module_langname' => $row['title'],
+ 'module_mode' => $module_mode,
+ 'module_auth' => $row['auth'],
+ );
+
+ $this->module_manager->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($this->db->get_sql_error_triggered())
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+ }
+ }
+
+ $k++;
+
+ // Stop execution if resource limit is reached
+ if ($this->config->get_time_remaining() <= 0 || $this->config->get_memory_remaining() <= 0)
+ {
+ $timed_out = true;
+ break;
+ }
+ }
+
+ $this->config->set('module_info_index', $k);
+
+ // Stop execution if resource limit is reached
+ if ($timed_out)
+ {
+ throw new resource_limit_reached_exception();
+ }
+
+ // Move some of the modules around since the code above will put them in the wrong place
+ if (!$this->config->get('modules_ordered', false))
+ {
+ $this->order_modules($module_class);
+ $this->config->set('modules_ordered', true);
+
+ // Stop execution if resource limit is reached
+ if ($this->config->get_time_remaining() <= 0 || $this->config->get_memory_remaining() <= 0)
+ {
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ // And now for the special ones
+ // (these are modules which appear in multiple categories and thus get added manually
+ // to some for more control)
+ if (isset($this->module_extras[$module_class]))
+ {
+ $this->add_module_extras($module_class);
+ }
+
+ $this->module_manager->remove_cache_file($module_class);
+
+ $i++;
+
+ $this->config->set('module_class_index', $i);
+ $this->config->set('module_categories_index', 0);
+ $this->config->set('module_info_index', 0);
+ $this->config->set('added_extra_modules', false);
+ $this->config->set('modules_ordered', false);
+ $this->config->set('module_categories_array', array());
+
+ // Stop execution if resource limit is reached
+ if ($this->config->get_time_remaining() <= 0 || $this->config->get_memory_remaining() <= 0)
+ {
+ break;
+ }
+ }
+
+ if ($i < $total)
+ {
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ /**
+ * Move modules to their correct place
+ *
+ * @param string $module_class
+ */
+ protected function order_modules($module_class)
+ {
+ if ($module_class == 'acp')
+ {
+ // Move main module 4 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'acp_main'
+ AND module_class = 'acp'
+ AND module_mode = 'main'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'acp', 'move_up', 4);
+
+ // Move permissions intro screen module 4 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'acp_permissions'
+ AND module_class = 'acp'
+ AND module_mode = 'intro'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'acp', 'move_up', 4);
+
+ // Move manage users screen module 5 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'acp_users'
+ AND module_class = 'acp'
+ AND module_mode = 'overview'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'acp', 'move_up', 5);
+
+ // Move extension management module 1 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT'
+ AND module_class = 'acp'
+ AND module_mode = ''
+ AND module_basename = ''";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'acp', 'move_up', 1);
+ }
+
+ if ($module_class == 'mcp')
+ {
+ // Move pm report details module 3 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'mcp_pm_reports'
+ AND module_class = 'mcp'
+ AND module_mode = 'pm_report_details'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'mcp', 'move_down', 3);
+
+ // Move closed pm reports module 3 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'mcp_pm_reports'
+ AND module_class = 'mcp'
+ AND module_mode = 'pm_reports_closed'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'mcp', 'move_down', 3);
+
+ // Move open pm reports module 3 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'mcp_pm_reports'
+ AND module_class = 'mcp'
+ AND module_mode = 'pm_reports'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'mcp', 'move_down', 3);
+ }
+
+ if ($module_class == 'ucp')
+ {
+ // Move attachment module 4 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'ucp_attachments'
+ AND module_class = 'ucp'
+ AND module_mode = 'attachments'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'ucp', 'move_down', 4);
+
+ // Move notification options module 4 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'ucp_notifications'
+ AND module_class = 'ucp'
+ AND module_mode = 'notification_options'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'ucp', 'move_down', 4);
+
+ // Move OAuth module 5 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'ucp_auth_link'
+ AND module_class = 'ucp'
+ AND module_mode = 'auth_link'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->module_manager->move_module_by($row, 'ucp', 'move_down', 5);
+ }
+ }
+
+ /**
+ * Add extra modules
+ *
+ * @param string $module_class
+ */
+ protected function add_module_extras($module_class)
+ {
+ foreach ($this->module_extras[$module_class] as $cat_name => $mods)
+ {
+ $sql = 'SELECT module_id, left_id, right_id
+ FROM ' . MODULES_TABLE . "
+ WHERE module_langname = '" . $this->db->sql_escape($cat_name) . "'
+ AND module_class = '" . $this->db->sql_escape($module_class) . "'";
+ $result = $this->db->sql_query_limit($sql, 1);
+ $row2 = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ foreach ($mods as $mod_name)
+ {
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_langname = '" . $this->db->sql_escape($mod_name) . "'
+ AND module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND module_basename <> ''";
+ $result = $this->db->sql_query_limit($sql, 1);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $module_data = array(
+ 'module_basename' => $row['module_basename'],
+ 'module_enabled' => (int) $row['module_enabled'],
+ 'module_display' => (int) $row['module_display'],
+ 'parent_id' => (int) $row2['module_id'],
+ 'module_class' => $row['module_class'],
+ 'module_langname' => $row['module_langname'],
+ 'module_mode' => $row['module_mode'],
+ 'module_auth' => $row['module_auth'],
+ );
+
+ $this->module_manager->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($this->db->get_sql_error_triggered())
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_ADD_MODULES';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_database/module.php b/phpBB/phpbb/install/module/install_database/module.php
new file mode 100644
index 0000000000..0d8b33087f
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/module.php
@@ -0,0 +1,28 @@
+<?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\install_database;
+
+/**
+ * Installer module for database installation
+ */
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'install');
+ }
+}
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
new file mode 100644
index 0000000000..8002e3ed97
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php
@@ -0,0 +1,372 @@
+<?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\install_database\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+
+/**
+ * Create database schema
+ */
+class add_config_settings extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var \phpbb\passwords\manager
+ */
+ protected $password_manager;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $config_table;
+
+ /**
+ * @var string
+ */
+ protected $user_table;
+
+ /**
+ * @var string
+ */
+ protected $topics_table;
+
+ /**
+ * @var string
+ */
+ protected $forums_table;
+
+ /**
+ * @var string
+ */
+ protected $posts_table;
+
+ /**
+ * @var string
+ */
+ protected $moderator_cache_table;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem service
+ * @param \phpbb\install\helper\config $install_config Installer's config helper
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ * @param \phpbb\install\helper\container_factory $container Installer's DI container
+ * @param \phpbb\language\language $language Language service
+ * @param string $phpbb_root_path Path to phpBB's root
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem,
+ \phpbb\install\helper\config $install_config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ \phpbb\install\helper\container_factory $container,
+ \phpbb\language\language $language,
+ $phpbb_root_path)
+ {
+ $this->db = $container->get('dbal.conn');
+ $this->filesystem = $filesystem;
+ $this->install_config = $install_config;
+ $this->iohandler = $iohandler;
+ $this->language = $language;
+ $this->password_manager = $container->get('passwords.manager');
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ // Table names
+ $this->config_table = $container->get_parameter('tables.config');
+ $this->forums_table = $container->get_parameter('tables.forums');
+ $this->topics_table = $container->get_parameter('tables.topics');
+ $this->user_table = $container->get_parameter('tables.users');
+ $this->moderator_cache_table = $container->get_parameter('tables.moderator_cache');
+ $this->posts_table = $container->get_parameter('tables.posts');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $server_name = $this->install_config->get('server_name');
+ $current_time = time();
+ $user_ip = phpbb_ip_normalise($this->iohandler->get_server_variable('REMOTE_ADDR'));
+ $user_ip = ($user_ip === false) ? '' : $user_ip;
+ $referer = $this->iohandler->get_server_variable('REFERER');
+
+ // Calculate cookie domain
+ $cookie_domain = $server_name;
+
+ if (strpos($cookie_domain, 'www.') === 0)
+ {
+ $cookie_domain = substr($cookie_domain, 3);
+ }
+
+ // Set default config and post data, this applies to all DB's
+ $sql_ary = array(
+ 'INSERT INTO ' . $this->config_table . " (config_name, config_value)
+ VALUES ('board_startdate', '$current_time')",
+
+ 'INSERT INTO ' . $this->config_table . " (config_name, config_value)
+ 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'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_port')) . "'
+ WHERE config_name = 'server_port'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_email')) . "'
+ WHERE config_name = 'board_email'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_email')) . "'
+ WHERE config_name = 'board_contact'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($cookie_domain) . "'
+ WHERE config_name = 'cookie_domain'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "'
+ WHERE config_name = 'default_dateformat'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('email_enable')) . "'
+ WHERE config_name = 'email_enable'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_delivery')) . "'
+ WHERE config_name = 'smtp_delivery'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_host')) . "'
+ WHERE config_name = 'smtp_host'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_port')) . "'
+ WHERE config_name = 'smtp_port'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_auth')) . "'
+ WHERE config_name = 'smtp_auth_method'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_user')) . "'
+ WHERE config_name = 'smtp_username'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_pass')) . "'
+ WHERE config_name = 'smtp_password'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('cookie_secure')) . "'
+ WHERE config_name = 'cookie_secure'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('force_server_vars')) . "'
+ WHERE config_name = 'force_server_vars'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('script_path')) . "'
+ WHERE config_name = 'script_path'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_protocol')) . "'
+ WHERE config_name = 'server_protocol'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "'
+ WHERE config_name = 'newest_username'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . md5(mt_rand()) . "'
+ WHERE config_name = 'avatar_salt'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . md5(mt_rand()) . "'
+ WHERE config_name = 'plupload_salt'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_name')) . "'
+ WHERE config_name = 'sitename'",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_description')) . "'
+ WHERE config_name = 'site_desc'",
+
+ 'UPDATE ' . $this->user_table . "
+ SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "',
+ user_password='" . $this->password_manager->hash($this->install_config->get('admin_passwd')) . "',
+ user_ip = '" . $this->db->sql_escape($user_ip) . "',
+ user_lang = '" . $this->db->sql_escape($this->install_config->get('user_language', 'en')) . "',
+ user_email='" . $this->db->sql_escape($this->install_config->get('board_email')) . "',
+ user_dateformat='" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "',
+ user_email_hash = " . $this->db->sql_escape(phpbb_email_hash($this->install_config->get('board_email'))) . ",
+ username_clean = '" . $this->db->sql_escape(utf8_clean_string($this->install_config->get('admin_name'))) . "'
+ WHERE username = 'Admin'",
+
+ 'UPDATE ' . $this->moderator_cache_table . "
+ SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "'
+ WHERE username = 'Admin'",
+
+ 'UPDATE ' . $this->forums_table . "
+ SET forum_last_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "'
+ WHERE forum_last_poster_name = 'Admin'",
+
+ 'UPDATE ' . $this->topics_table . "
+ SET topic_first_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "',
+ topic_last_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "'
+ WHERE topic_first_poster_name = 'Admin'
+ OR topic_last_poster_name = 'Admin'",
+
+ 'UPDATE ' . $this->user_table . "
+ SET user_regdate = $current_time",
+
+ 'UPDATE ' . $this->posts_table . "
+ SET post_time = $current_time, poster_ip = '" . $this->db->sql_escape($user_ip) . "'",
+
+ 'UPDATE ' . $this->topics_table . "
+ SET topic_time = $current_time, topic_last_post_time = $current_time",
+
+ 'UPDATE ' . $this->forums_table . "
+ SET forum_last_post_time = $current_time",
+
+ 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($this->db->sql_server_info(true)) . "'
+ WHERE config_name = 'dbms_version'",
+ );
+
+ if (@extension_loaded('gd'))
+ {
+ $sql_ary[] = 'UPDATE ' . $this->config_table . "
+ SET config_value = 'core.captcha.plugins.gd'
+ WHERE config_name = 'captcha_plugin'";
+
+ $sql_ary[] = 'UPDATE ' . $this->config_table . "
+ SET config_value = '1'
+ WHERE config_name = 'captcha_gd'";
+ }
+
+ $ref = substr($referer, strpos($referer, '://') + 3);
+ if (!(stripos($ref, $server_name) === 0))
+ {
+ $sql_ary[] = 'UPDATE ' . $this->config_table . "
+ SET config_value = '0'
+ WHERE config_name = 'referer_validation'";
+ }
+
+ // We set a (semi-)unique cookie name to bypass login issues related to the cookie name.
+ $cookie_name = 'phpbb3_';
+ $rand_str = md5(mt_rand());
+ $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35));
+ $rand_str = substr($rand_str, 0, 5);
+ $cookie_name .= strtolower($rand_str);
+
+ $sql_ary[] = 'UPDATE ' . $this->config_table . "
+ SET config_value = '" . $this->db->sql_escape($cookie_name) . "'
+ WHERE config_name = 'cookie_name'";
+
+ // Disable avatars if upload directory is not writable
+ if (!$this->filesystem->is_writable($this->phpbb_root_path . 'images/avatars/upload/'))
+ {
+ $sql_ary[] = 'UPDATE ' . $this->config_table . "
+ SET config_value = '0'
+ WHERE config_name = 'allow_avatar'";
+
+ $sql_ary[] = 'UPDATE ' . $this->config_table . "
+ SET config_value = '0'
+ WHERE config_name = 'allow_avatar_upload'";
+ }
+
+ $i = $this->install_config->get('add_config_settings_index', 0);
+ $total = sizeof($sql_ary);
+ $sql_ary = array_slice($sql_ary, $i);
+
+ foreach ($sql_ary as $sql)
+ {
+ if (!$this->db->sql_query($sql))
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+
+ $i++;
+
+ // Stop execution if resource limit is reached
+ if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)
+ {
+ break;
+ }
+ }
+
+ if ($i < $total)
+ {
+ $this->install_config->set('add_config_settings_index', $i);
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_ADD_CONFIG_SETTINGS';
+ }
+}
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
new file mode 100644
index 0000000000..e32101a3f7
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/task/add_default_data.php
@@ -0,0 +1,184 @@
+<?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\install_database\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+
+/**
+ * Create database schema
+ */
+class add_default_data extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\install\helper\database
+ */
+ protected $database_helper;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\database $db_helper Installer's database helper
+ * @param \phpbb\install\helper\config $config Installer config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ * @param \phpbb\install\helper\container_factory $container Installer's DI container
+ * @param \phpbb\language\language $language Language service
+ * @param string $root_path Root path of phpBB
+ */
+ public function __construct(\phpbb\install\helper\database $db_helper,
+ \phpbb\install\helper\config $config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ \phpbb\install\helper\container_factory $container,
+ \phpbb\language\language $language,
+ $root_path)
+ {
+ $this->db = $container->get('dbal.conn.driver');
+ $this->database_helper = $db_helper;
+ $this->config = $config;
+ $this->iohandler = $iohandler;
+ $this->language = $language;
+ $this->phpbb_root_path = $root_path;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $table_prefix = $this->config->get('table_prefix');
+ $dbms = $this->config->get('dbms');
+ $dbms_info = $this->database_helper->get_available_dbms($dbms);
+
+ // Get schema data from file
+ $sql_query = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema_data.sql');
+
+ // Clean up SQL
+ $sql_query = $this->replace_dbms_specific_sql($sql_query);
+ $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $table_prefix . '\1 ', $sql_query);
+ $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $sql_query);
+ $sql_query = $this->database_helper->remove_comments($sql_query);
+ $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);
+ $sql_query = array_slice($sql_query, $i);
+
+ foreach ($sql_query as $sql)
+ {
+ if (!$this->db->sql_query($sql))
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+
+ $i++;
+
+ // Stop execution if resource limit is reached
+ if ($this->config->get_time_remaining() <= 0 || $this->config->get_memory_remaining() <= 0)
+ {
+ break;
+ }
+ }
+
+ $this->config->set('add_default_data_index', $i);
+
+ if ($i < $total)
+ {
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ /**
+ * Process DB specific SQL
+ *
+ * @return string
+ */
+ protected function replace_dbms_specific_sql($query)
+ {
+ if ($this->db instanceof \phpbb\db\driver\mssql_base)
+ {
+ $query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $query);
+ }
+ else if ($this->db instanceof \phpbb\db\driver\postgres)
+ {
+ $query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $query);
+ }
+ else if ($this->db instanceof \phpbb\db\driver\mysql_base)
+ {
+ $query = str_replace('\\', '\\\\', $query);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Callback function for language replacing
+ *
+ * @param array $matches
+ * @return string
+ */
+ public function lang_replace_callback($matches)
+ {
+ if (!empty($matches[1]))
+ {
+ return $this->db->sql_escape($this->language->lang($matches[1]));
+ }
+
+ return '';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_ADD_DEFAULT_DATA';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_database/task/add_tables.php b/phpBB/phpbb/install/module/install_database/task/add_tables.php
new file mode 100644
index 0000000000..f344f91582
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/task/add_tables.php
@@ -0,0 +1,151 @@
+<?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\install_database\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+
+/**
+ * Create tables
+ */
+class add_tables extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\db\tools\tools_interface
+ */
+ protected $db_tools;
+
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var string
+ */
+ protected $schema_file_path;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config
+ * @param \phpbb\install\helper\database $db_helper
+ * @param \phpbb\filesystem\filesystem_interface $filesystem
+ * @param string $phpbb_root_path
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\database $db_helper,
+ \phpbb\filesystem\filesystem_interface $filesystem,
+ $phpbb_root_path)
+ {
+ $dbms = $db_helper->get_available_dbms($config->get('dbms'));
+ $dbms = $dbms[$config->get('dbms')]['DRIVER'];
+ $factory = new \phpbb\db\tools\factory();
+
+ $this->db = new $dbms();
+ $this->db->sql_connect(
+ $config->get('dbhost'),
+ $config->get('dbuser'),
+ $config->get('dbpasswd'),
+ $config->get('dbname'),
+ $config->get('dbport'),
+ false,
+ false
+ );
+
+ $this->config = $config;
+ $this->db_tools = $factory->get($this->db);
+ $this->filesystem = $filesystem;
+ $this->schema_file_path = $phpbb_root_path . 'store/schema.json';
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $table_prefix = $this->config->get('table_prefix');
+ $change_prefix = $this->config->get('change_table_prefix', true);
+
+ if (!defined('CONFIG_TABLE'))
+ {
+ // CONFIG_TABLE is required by sql_create_index() to check the
+ // length of index names. However table_prefix is not defined
+ // here yet, so we need to create the constant ourselves.
+ define('CONFIG_TABLE', $table_prefix . 'config');
+ }
+
+ $db_table_schema = @file_get_contents($this->schema_file_path);
+ $db_table_schema = json_decode($db_table_schema, true);
+ $total = sizeof($db_table_schema);
+ $i = $this->config->get('add_table_index', 0);
+ $db_table_schema = array_slice($db_table_schema, $i);
+
+ foreach ($db_table_schema as $table_name => $table_data)
+ {
+ $i++;
+
+ $this->db_tools->sql_create_table(
+ ( ($change_prefix) ? ($table_prefix . substr($table_name, 6)) : $table_name ),
+ $table_data
+ );
+
+ // Stop execution if resource limit is reached
+ if ($this->config->get_time_remaining() <= 0 || $this->config->get_memory_remaining() <= 0)
+ {
+ break;
+ }
+ }
+
+ $this->config->set('add_table_index', $i);
+
+ if ($i < $total)
+ {
+ throw new resource_limit_reached_exception();
+ }
+ else
+ {
+ @unlink($this->schema_file_path);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_CREATE_TABLES';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php
new file mode 100644
index 0000000000..a5635d5dbe
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php
@@ -0,0 +1,234 @@
+<?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\install_database\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+
+/**
+ * Create database schema
+ */
+class create_schema extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\db\tools\tools_interface
+ */
+ protected $db_tools;
+
+ /**
+ * @var \phpbb\install\helper\database
+ */
+ protected $database_helper;
+
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config Installer's config provider
+ * @param \phpbb\install\helper\database $db_helper Installer's database helper
+ * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem service
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ * @param string $phpbb_root_path Path phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\database $db_helper,
+ \phpbb\filesystem\filesystem_interface $filesystem,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ $phpbb_root_path,
+ $php_ext)
+ {
+ $dbms = $db_helper->get_available_dbms($config->get('dbms'));
+ $dbms = $dbms[$config->get('dbms')]['DRIVER'];
+ $factory = new \phpbb\db\tools\factory();
+
+ $this->db = new $dbms();
+ $this->db->sql_connect(
+ $config->get('dbhost'),
+ $config->get('dbuser'),
+ $config->get('dbpasswd'),
+ $config->get('dbname'),
+ $config->get('dbport'),
+ false,
+ false
+ );
+
+ $this->config = $config;
+ $this->db_tools = $factory->get($this->db);
+ $this->database_helper = $db_helper;
+ $this->filesystem = $filesystem;
+ $this->iohandler = $iohandler;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // As this task may take a large amount of time to complete refreshing the page might be necessary for some
+ // server configurations with limited resources
+ if (!$this->config->get('pre_schema_forced_refresh'))
+ {
+ if ($this->config->get_time_remaining() < 5)
+ {
+ $this->config->set('pre_schema_forced_refresh', true);
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ $this->db->sql_return_on_error(true);
+
+ $dbms = $this->config->get('dbms');
+ $dbms_info = $this->database_helper->get_available_dbms($dbms);
+ $schema_name = $dbms_info[$dbms]['SCHEMA'];
+ $delimiter = $dbms_info[$dbms]['DELIM'];
+ $table_prefix = $this->config->get('table_prefix');
+
+ if ($dbms === 'mysql')
+ {
+ if (version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
+ {
+ $schema_name .= '_41';
+ }
+ else
+ {
+ $schema_name .= '_40';
+ }
+ }
+
+ $db_schema_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql';
+
+ // Load database vendor specific code if there is any
+ if ($this->filesystem->exists($db_schema_path))
+ {
+ $sql_query = @file_get_contents($db_schema_path);
+ $sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);
+ $sql_query = $this->database_helper->remove_comments($sql_query);
+ $sql_query = $this->database_helper->split_sql_file($sql_query, $delimiter);
+
+ foreach ($sql_query as $sql)
+ {
+ if (!$this->db->sql_query($sql))
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+ }
+
+ unset($sql_query);
+ }
+
+ $change_prefix = false;
+
+ // Generate database schema
+ if ($this->filesystem->exists($this->phpbb_root_path . 'install/schemas/schema.json'))
+ {
+ $db_table_schema = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema.json');
+ $db_table_schema = json_decode($db_table_schema, true);
+ $change_prefix = true;
+ }
+ else
+ {
+ global $table_prefix;
+
+ $table_prefix = $this->config->get('table_prefix');
+
+ if (!defined('CONFIG_TABLE'))
+ {
+ // We need to include the constants file for the table constants
+ // when we generate the schema from the migration files.
+ include ($this->phpbb_root_path . 'includes/constants.' . $this->php_ext);
+ }
+
+ $finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, null, $this->php_ext);
+ $migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes();
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($this->db, true);
+ $schema_generator = new \phpbb\db\migration\schema_generator(
+ $migrator_classes,
+ new \phpbb\config\config(array()),
+ $this->db,
+ $db_tools,
+ $this->phpbb_root_path,
+ $this->php_ext,
+ $table_prefix
+ );
+ $db_table_schema = $schema_generator->get_schema();
+ }
+
+ if (!defined('CONFIG_TABLE'))
+ {
+ // CONFIG_TABLE is required by sql_create_index() to check the
+ // length of index names. However table_prefix is not defined
+ // here yet, so we need to create the constant ourselves.
+ define('CONFIG_TABLE', $table_prefix . 'config');
+ }
+
+ foreach ($db_table_schema as $table_name => $table_data)
+ {
+ $this->db_tools->sql_create_table(
+ ( ($change_prefix) ? ($table_prefix . substr($table_name, 6)) : $table_name ),
+ $table_data
+ );
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_CREATE_DATABASE_SCHEMA';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema_file.php b/phpBB/phpbb/install/module/install_database/task/create_schema_file.php
new file mode 100644
index 0000000000..b6d6ece17f
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/task/create_schema_file.php
@@ -0,0 +1,164 @@
+<?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\install_database\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+
+/**
+ * Create database schema
+ */
+class create_schema_file extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config Installer's config provider
+ * @param \phpbb\install\helper\database $db_helper Installer's database helper
+ * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem service
+ * @param string $phpbb_root_path Path phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\database $db_helper,
+ \phpbb\filesystem\filesystem_interface $filesystem,
+ $phpbb_root_path,
+ $php_ext)
+ {
+ $dbms = $db_helper->get_available_dbms($config->get('dbms'));
+ $dbms = $dbms[$config->get('dbms')]['DRIVER'];
+
+ $this->db = new $dbms();
+ $this->db->sql_connect(
+ $config->get('dbhost'),
+ $config->get('dbuser'),
+ $config->get('dbpasswd'),
+ $config->get('dbname'),
+ $config->get('dbport'),
+ false,
+ false
+ );
+
+ $this->config = $config;
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Generate database schema
+ if ($this->filesystem->exists($this->phpbb_root_path . 'install/schemas/schema.json'))
+ {
+ $db_table_schema = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema.json');
+ $this->config->set('change_table_prefix', true);
+ }
+ else
+ {
+ global $table_prefix;
+
+ // As this task may take a large amount of time to complete refreshing the page might be necessary for some
+ // server configurations with limited resources
+ if (!$this->config->get('pre_schema_forced_refresh', false))
+ {
+ if ($this->config->get_time_remaining() < 5)
+ {
+ $this->config->set('pre_schema_forced_refresh', true);
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ $table_prefix = $this->config->get('table_prefix');
+
+ if (!defined('CONFIG_TABLE'))
+ {
+ // We need to include the constants file for the table constants
+ // when we generate the schema from the migration files.
+ include ($this->phpbb_root_path . 'includes/constants.' . $this->php_ext);
+ }
+
+ $finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, null, $this->php_ext);
+ $migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes();
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($this->db, true);
+ $schema_generator = new \phpbb\db\migration\schema_generator(
+ $migrator_classes,
+ new \phpbb\config\config(array()),
+ $this->db,
+ $db_tools,
+ $this->phpbb_root_path,
+ $this->php_ext,
+ $table_prefix
+ );
+ $db_table_schema = $schema_generator->get_schema();
+ $db_table_schema = json_encode($db_table_schema, JSON_PRETTY_PRINT);
+
+ $this->config->set('change_table_prefix', false);
+ }
+
+ $fp = @fopen($this->phpbb_root_path . 'store/schema.json', 'wb');
+ if (!$fp)
+ {
+ throw new \Exception('INST_SCHEMA_FILE_NOT_WRITABLE');
+ }
+
+ fwrite($fp, $db_table_schema);
+ fclose($fp);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_CREATE_DATABASE_SCHEMA_FILE';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_database/task/set_up_database.php b/phpBB/phpbb/install/module/install_database/task/set_up_database.php
new file mode 100644
index 0000000000..49c8ea23ad
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_database/task/set_up_database.php
@@ -0,0 +1,164 @@
+<?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\install_database\task;
+
+/**
+ * Set up database for table generation
+ */
+class set_up_database extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\install\helper\database
+ */
+ protected $database_helper;
+
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $schema_file_path;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config
+ * @param \phpbb\install\helper\database $db_helper
+ * @param \phpbb\filesystem\filesystem_interface $filesystem
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
+ * @param string $phpbb_root_path
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\database $db_helper,
+ \phpbb\filesystem\filesystem_interface $filesystem,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ $phpbb_root_path)
+ {
+ $dbms = $db_helper->get_available_dbms($config->get('dbms'));
+ $dbms = $dbms[$config->get('dbms')]['DRIVER'];
+
+ $this->db = new $dbms();
+ $this->db->sql_connect(
+ $config->get('dbhost'),
+ $config->get('dbuser'),
+ $config->get('dbpasswd'),
+ $config->get('dbname'),
+ $config->get('dbport'),
+ false,
+ false
+ );
+
+ $this->config = $config;
+ $this->database_helper = $db_helper;
+ $this->filesystem = $filesystem;
+ $this->iohandler = $iohandler;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ $dbms = $this->config->get('dbms');
+ $dbms_info = $this->database_helper->get_available_dbms($dbms);
+ $schema_name = $dbms_info[$dbms]['SCHEMA'];
+
+ if ($dbms === 'mysql')
+ {
+ if (version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
+ {
+ $schema_name .= '_41';
+ }
+ else
+ {
+ $schema_name .= '_40';
+ }
+ }
+
+ $this->schema_file_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql';
+
+ return $this->filesystem->exists($this->schema_file_path);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->db->sql_return_on_error(true);
+
+ $dbms = $this->config->get('dbms');
+ $dbms_info = $this->database_helper->get_available_dbms($dbms);
+ $delimiter = $dbms_info[$dbms]['DELIM'];
+ $table_prefix = $this->config->get('table_prefix');
+
+ $sql_query = @file_get_contents($this->schema_file_path);
+ $sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);
+ $sql_query = $this->database_helper->remove_comments($sql_query);
+ $sql_query = $this->database_helper->split_sql_file($sql_query, $delimiter);
+
+ foreach ($sql_query as $sql)
+ {
+ if (!$this->db->sql_query($sql))
+ {
+ $error = $this->db->sql_error($this->db->get_sql_error_sql());
+ $this->iohandler->add_error_message('INST_ERR_DB', $error['message']);
+ }
+ }
+
+ unset($sql_query);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_SETUP_DATABASE';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_filesystem/module.php b/phpBB/phpbb/install/module/install_filesystem/module.php
new file mode 100644
index 0000000000..7215449664
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_filesystem/module.php
@@ -0,0 +1,28 @@
+<?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\install_filesystem;
+
+/**
+ * Installer module for filesystem installation
+ */
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'install');
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php
new file mode 100644
index 0000000000..5bc425b929
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php
@@ -0,0 +1,244 @@
+<?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\install_filesystem\task;
+
+use phpbb\install\exception\user_interaction_required_exception;
+
+/**
+ * Dumps config file
+ */
+class create_config_file extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\install\helper\database
+ */
+ protected $db_helper;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var array
+ */
+ protected $options;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\filesystem\filesystem_interface $filesystem
+ * @param \phpbb\install\helper\config $install_config
+ * @param \phpbb\install\helper\database $db_helper
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ * @param array $options
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem,
+ \phpbb\install\helper\config $install_config,
+ \phpbb\install\helper\database $db_helper,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ $phpbb_root_path,
+ $php_ext,
+ $options = array())
+ {
+ $this->install_config = $install_config;
+ $this->db_helper = $db_helper;
+ $this->filesystem = $filesystem;
+ $this->iohandler = $iohandler;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->options = array_merge(array(
+ 'debug' => false,
+ 'debug_container' => false,
+ 'environment' => null,
+ ), $options);
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $config_written = true;
+
+ // Create config.php
+ $path_to_config = $this->phpbb_root_path . 'config.' . $this->php_ext;
+
+ $fp = @fopen($path_to_config, 'w');
+ if (!$fp)
+ {
+ $config_written = false;
+ }
+
+ $config_content = $this->get_config_data($this->options['debug'], $this->options['debug_container'], $this->options['environment']);
+
+ if (!@fwrite($fp, $config_content))
+ {
+ $config_written = false;
+ }
+
+ @fclose($fp);
+
+ // chmod config.php to be only readable
+ if ($config_written)
+ {
+ try
+ {
+ $this->filesystem->phpbb_chmod($path_to_config, \phpbb\filesystem\filesystem_interface::CHMOD_READ);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing, the user will get a notice later
+ }
+ }
+ else
+ {
+ $this->iohandler->add_error_message('UNABLE_TO_WRITE_CONFIG_FILE');
+ throw new user_interaction_required_exception();
+ }
+
+ // Create a lock file to indicate that there is an install in progress
+ $fp = @fopen($this->phpbb_root_path . 'cache/install_lock', 'wb');
+ if ($fp === false)
+ {
+ // We were unable to create the lock file - abort
+ $this->iohandler->add_error_message('UNABLE_TO_WRITE_LOCK');
+ throw new user_interaction_required_exception();
+ }
+ @fclose($fp);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($this->phpbb_root_path . 'cache/install_lock', 0777);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing, the user will get a notice later
+ }
+ }
+
+ /**
+ * Returns the content which should be dumped to config.php
+ *
+ * @param bool $debug If the debug constants should be enabled by default or not
+ * @param bool $debug_container If the container should be compiled on
+ * every page load or not
+ * @param string $environment The environment to use
+ *
+ * @return string content to be written to the config file
+ */
+ protected function get_config_data($debug = false, $debug_container = false, $environment = null)
+ {
+ $config_content = "<?php\n";
+ $config_content .= "// phpBB 3.2.x auto-generated configuration file\n// Do not change anything in this file!\n";
+
+ $dbms = $this->install_config->get('dbms');
+ $db_driver = $this->db_helper->get_available_dbms($dbms);
+ $db_driver = $db_driver[$dbms]['DRIVER'];
+
+ $config_data_array = array(
+ 'dbms' => $db_driver,
+ 'dbhost' => $this->install_config->get('dbhost'),
+ 'dbport' => $this->install_config->get('dbport'),
+ 'dbname' => $this->install_config->get('dbname'),
+ 'dbuser' => $this->install_config->get('dbuser'),
+ 'dbpasswd' => $this->install_config->get('dbpasswd'),
+ 'table_prefix' => $this->install_config->get('table_prefix'),
+
+ 'phpbb_adm_relative_path' => 'adm/',
+
+ 'acm_type' => 'phpbb\cache\driver\file',
+ );
+
+ foreach ($config_data_array as $key => $value)
+ {
+ $config_content .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n";
+ }
+
+ $config_content .= "\n@define('PHPBB_INSTALLED', true);\n";
+ $config_content .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n";
+
+ if ($environment)
+ {
+ $config_content .= "@define('PHPBB_ENVIRONMENT', 'test');\n";
+ }
+ else if ($debug)
+ {
+ $config_content .= "@define('PHPBB_ENVIRONMENT', 'development');\n";
+ }
+ else
+ {
+ $config_content .= "@define('PHPBB_ENVIRONMENT', 'production');\n";
+ }
+
+ if ($debug_container)
+ {
+ $config_content .= "@define('DEBUG_CONTAINER', true);\n";
+ }
+ else
+ {
+ $config_content .= "// @define('DEBUG_CONTAINER', true);\n";
+ }
+
+ if ($environment === 'test')
+ {
+ $config_content .= "@define('DEBUG_TEST', true);\n";
+
+ // Mandatory for the functional tests, will be removed by PHPBB3-12623
+ $config_content .= "@define('DEBUG', true);\n";
+ }
+
+ return $config_content;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_CREATE_CONFIG_FILE';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_finish/module.php b/phpBB/phpbb/install/module/install_finish/module.php
new file mode 100644
index 0000000000..3a7544b84f
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_finish/module.php
@@ -0,0 +1,28 @@
+<?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\install_finish;
+
+/**
+ * Installer module for filesystem installation
+ */
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'install');
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php
new file mode 100644
index 0000000000..292be57f5f
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php
@@ -0,0 +1,174 @@
+<?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\install_finish\task;
+
+use phpbb\config\db;
+
+/**
+ * Logs installation and sends an email to the admin
+ */
+class notify_user extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\auth\auth
+ */
+ protected $auth;
+
+ /**
+ * @var \phpbb\config\db
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var \phpbb\log\log_interface
+ */
+ protected $log;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\container_factory $container
+ * @param \phpbb\install\helper\config $install_config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\install\helper\container_factory $container, \phpbb\install\helper\config $install_config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, $phpbb_root_path, $php_ext)
+ {
+ $this->install_config = $install_config;
+ $this->iohandler = $iohandler;
+
+ $this->auth = $container->get('auth');
+ $this->language = $container->get('language');
+ $this->log = $container->get('log');
+ $this->user = $container->get('user');
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ // We need to reload config for cases when it doesn't have all values
+ /** @var \phpbb\cache\driver\driver_interface $cache */
+ $cache = $container->get('cache.driver');
+ $cache->destroy('config');
+
+ $this->config = new db(
+ $container->get('dbal.conn'),
+ $cache,
+ $container->get_parameter('tables.config')
+ );
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->user->session_begin();
+ $this->user->setup('common');
+
+ if ($this->config['email_enable'])
+ {
+ include ($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
+
+ // functions_messenger.php uses config to determine language paths
+ // Remove when able
+ global $config;
+ $config = $this->config;
+
+ $messenger = new \messenger(false);
+ $messenger->template('installed', $this->install_config->get('user_language', 'en'));
+ $messenger->to($this->config['board_email'], $this->install_config->get('admin_name'));
+ $messenger->anti_abuse_headers($this->config, $this->user);
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($this->install_config->get('admin_name')),
+ 'PASSWORD' => htmlspecialchars_decode($this->install_config->get('admin_passwd')))
+ );
+ $messenger->send(NOTIFY_EMAIL);
+ }
+
+ // Login admin
+ // Ugly but works
+ $this->auth->login(
+ $this->install_config->get('admin_name'),
+ $this->install_config->get('admin_passwd'),
+ false,
+ true,
+ true
+ );
+
+ $this->iohandler->set_cookie($this->config['cookie_name'] . '_sid', $this->user->session_id);
+ $this->iohandler->set_cookie($this->config['cookie_name'] . '_u', $this->user->cookie_data['u']);
+ $this->iohandler->set_cookie($this->config['cookie_name'] . '_k', $this->user->cookie_data['k']);
+
+ // Create log
+ $this->log->add(
+ 'admin',
+ $this->user->data['user_id'],
+ $this->user->ip,
+ 'LOG_INSTALL_INSTALLED',
+ false,
+ array($this->config['version'])
+ );
+
+ // Remove install_lock
+ @unlink($this->phpbb_root_path . 'cache/install_lock');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_NOTIFY_USER';
+ }
+}
diff --git a/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php
new file mode 100644
index 0000000000..34541c361e
--- /dev/null
+++ b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php
@@ -0,0 +1,92 @@
+<?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\install_finish\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+
+/**
+ * Populates migrations
+ */
+class populate_migrations extends \phpbb\install\task_base
+{
+ /**
+ * @var config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\extension\manager
+ */
+ protected $extension_manager;
+
+ /**
+ * @var \phpbb\db\migrator
+ */
+ protected $migrator;
+
+ /**
+ * Constructor
+ *
+ * @param config $config Installer's config
+ * @param container_factory $container phpBB's DI contianer
+ */
+ public function __construct(config $config, container_factory $container)
+ {
+ $this->config = $config;
+ $this->extension_manager = $container->get('ext.manager');
+ $this->migrator = $container->get('migrator');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if (!$this->config->get('populate_migration_refresh_before', false))
+ {
+ if ($this->config->get_time_remaining() < 1)
+ {
+ $this->config->set('populate_migration_refresh_before', true);
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ $finder = $this->extension_manager->get_finder();
+
+ $migrations = $finder
+ ->core_path('phpbb/db/migration/data/')
+ ->get_classes();
+ $this->migrator->populate_migrations($migrations);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return 'TASK_POPULATE_MIGRATIONS';
+ }
+}
diff --git a/phpBB/phpbb/install/module/obtain_data/install_module.php b/phpBB/phpbb/install/module/obtain_data/install_module.php
new file mode 100644
index 0000000000..deb4be90d8
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/install_module.php
@@ -0,0 +1,33 @@
+<?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;
+
+class install_module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'obtain_data');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
new file mode 100644
index 0000000000..d1f1af6b83
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
@@ -0,0 +1,218 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+
+/**
+ * This class requests and validates admin account data from the user
+ */
+class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\install\task_interface
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $io_handler;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $install_config Installer's config helper
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ */
+ public function __construct(\phpbb\install\helper\config $install_config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler)
+ {
+ $this->install_config = $install_config;
+ $this->io_handler = $iohandler;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->io_handler->get_input('submit_admin', false))
+ {
+ $this->process_form();
+ }
+ else
+ {
+ $this->request_form_data();
+ }
+ }
+
+ /**
+ * Process form data
+ */
+ protected function process_form()
+ {
+ // Admin data
+ $admin_name = $this->io_handler->get_input('admin_name', '', true);
+ $admin_pass1 = $this->io_handler->get_input('admin_pass1', '', true);
+ $admin_pass2 = $this->io_handler->get_input('admin_pass2', '', true);
+ $board_email = $this->io_handler->get_input('board_email', '', true);
+
+ $admin_data_valid = $this->check_admin_data($admin_name, $admin_pass1, $admin_pass2, $board_email);
+
+ if ($admin_data_valid)
+ {
+ $this->install_config->set('admin_name', $admin_name);
+ $this->install_config->set('admin_passwd', $admin_pass1);
+ $this->install_config->set('board_email', $board_email);
+ }
+ else
+ {
+ $this->request_form_data(true);
+ }
+ }
+
+ /**
+ * Request data from the user
+ *
+ * @param bool $use_request_data Whether to use submited data
+ *
+ * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data
+ */
+ protected function request_form_data($use_request_data = false)
+ {
+ if ($use_request_data)
+ {
+ $admin_username = $this->io_handler->get_input('admin_name', '', true);
+ $admin_email = $this->io_handler->get_input('board_email', '', true);
+ }
+ else
+ {
+ $admin_username = '';
+ $admin_email = '';
+ }
+
+ $admin_form = array(
+ 'admin_name' => array(
+ 'label' => 'ADMIN_USERNAME',
+ 'description' => 'ADMIN_USERNAME_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $admin_username,
+ ),
+ 'board_email' => array(
+ 'label' => 'CONTACT_EMAIL',
+ 'type' => 'email',
+ 'default' => $admin_email,
+ ),
+ 'admin_pass1' => array(
+ 'label' => 'ADMIN_PASSWORD',
+ 'description' => 'ADMIN_PASSWORD_EXPLAIN',
+ 'type' => 'password',
+ ),
+ 'admin_pass2' => array(
+ 'label' => 'ADMIN_PASSWORD_CONFIRM',
+ 'type' => 'password',
+ ),
+ 'submit_admin' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ );
+
+ $this->io_handler->add_user_form_group('ADMIN_CONFIG', $admin_form);
+
+ // Require user interaction
+ throw new user_interaction_required_exception();
+ }
+
+ /**
+ * Check admin data
+ *
+ * @param string $username Admin username
+ * @param string $pass1 Admin password
+ * @param string $pass2 Admin password confirmation
+ * @param string $email Admin e-mail address
+ *
+ * @return bool True if data is valid, false otherwise
+ */
+ protected function check_admin_data($username, $pass1, $pass2, $email)
+ {
+ $data_valid = true;
+
+ // Check if none of admin data is empty
+ if (in_array('', array($username, $pass1, $pass2, $email), true))
+ {
+ $this->io_handler->add_error_message('INST_ERR_MISSING_DATA');
+ $data_valid = false;
+ }
+
+ if (utf8_strlen($username) < 3)
+ {
+ $this->io_handler->add_error_message('INST_ERR_USER_TOO_SHORT');
+ $data_valid = false;
+ }
+
+ if (utf8_strlen($username) > 20)
+ {
+ $this->io_handler->add_error_message('INST_ERR_USER_TOO_LONG');
+ $data_valid = false;
+ }
+
+ if ($pass1 !== $pass2 && $pass1 !== '')
+ {
+ $this->io_handler->add_error_message('INST_ERR_PASSWORD_MISMATCH');
+ $data_valid = false;
+ }
+
+ // Test against the default password rules
+ if (utf8_strlen($pass1) < 6)
+ {
+ $this->io_handler->add_error_message('INST_ERR_PASSWORD_TOO_SHORT');
+ $data_valid = false;
+ }
+
+ if (utf8_strlen($pass1) > 30)
+ {
+ $this->io_handler->add_error_message('INST_ERR_PASSWORD_TOO_LONG');
+ $data_valid = false;
+ }
+
+ if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email))
+ {
+ $this->io_handler->add_error_message('INST_ERR_EMAIL_INVALID');
+ $data_valid = false;
+ }
+
+ return $data_valid;
+ }
+
+ /**
+ * {@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_board_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
new file mode 100644
index 0000000000..ff2a0a2f86
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
@@ -0,0 +1,185 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+
+/**
+ * This class obtains default data from the user related to board (Board name, Board descritpion, etc...)
+ */
+class obtain_board_data extends \phpbb\install\task_base implements \phpbb\install\task_interface
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $io_handler;
+
+ /**
+ * @var \phpbb\language\language_file_helper
+ */
+ protected $language_helper;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config Installer's config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ * @param \phpbb\language\language_file_helper $lang_helper Language file helper
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler,
+ \phpbb\language\language_file_helper $lang_helper)
+ {
+ $this->install_config = $config;
+ $this->io_handler = $iohandler;
+ $this->language_helper = $lang_helper;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->io_handler->get_input('submit_board', false))
+ {
+ $this->process_form();
+ }
+ else
+ {
+ $this->request_form_data();
+ }
+ }
+
+ /**
+ * Process form data
+ */
+ protected function process_form()
+ {
+ // Board data
+ $default_lang = $this->io_handler->get_input('default_lang', '');
+ $board_name = $this->io_handler->get_input('board_name', '', true);
+ $board_desc = $this->io_handler->get_input('board_description', '', true);
+
+ // Check default lang
+ $langs = $this->language_helper->get_available_languages();
+ $lang_valid = false;
+
+ foreach ($langs as $lang)
+ {
+ if ($lang['iso'] === $default_lang)
+ {
+ $lang_valid = true;
+ break;
+ }
+ }
+
+ $this->install_config->set('board_name', $board_name);
+ $this->install_config->set('board_description', $board_desc);
+
+ if ($lang_valid)
+ {
+ $this->install_config->set('default_lang', $default_lang);
+ }
+ else
+ {
+ $this->request_form_data(true);
+ }
+ }
+
+ /**
+ * Request data from the user
+ *
+ * @param bool $use_request_data Whether to use submited data
+ *
+ * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data
+ */
+ protected function request_form_data($use_request_data = false)
+ {
+ if ($use_request_data)
+ {
+ $board_name = $this->io_handler->get_input('board_name', '', true);
+ $board_desc = $this->io_handler->get_input('board_description', '', true);
+ }
+ else
+ {
+ $board_name = '{L_CONFIG_SITENAME}';
+ $board_desc = '{L_CONFIG_SITE_DESC}';
+ }
+
+ // Use language because we only check this to be valid
+ $default_lang = $this->install_config->get('user_language', 'en');
+
+ $langs = $this->language_helper->get_available_languages();
+ $lang_options = array();
+
+ foreach ($langs as $lang)
+ {
+ $lang_options[] = array(
+ 'value' => $lang['iso'],
+ 'label' => $lang['local_name'],
+ 'selected' => ($default_lang === $lang['iso']),
+ );
+ }
+
+ $board_form = array(
+ 'default_lang' => array(
+ 'label' => 'DEFAULT_LANGUAGE',
+ 'type' => 'select',
+ 'options' => $lang_options,
+ ),
+ 'board_name' => array(
+ 'label' => 'BOARD_NAME',
+ 'type' => 'text',
+ 'default' => $board_name,
+ ),
+ 'board_description' => array(
+ 'label' => 'BOARD_DESCRIPTION',
+ 'type' => 'text',
+ 'default' => $board_desc,
+ ),
+ 'submit_board' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ );
+
+ $this->io_handler->add_user_form_group('BOARD_CONFIG', $board_form);
+
+ throw new user_interaction_required_exception();
+ }
+
+ /**
+ * {@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_database_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php
new file mode 100644
index 0000000000..ce720dbf76
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php
@@ -0,0 +1,270 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+
+/**
+ * This class requests and validates database information from the user
+ */
+class obtain_database_data extends \phpbb\install\task_base implements \phpbb\install\task_interface
+{
+ /**
+ * @var \phpbb\install\helper\database
+ */
+ protected $database_helper;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $io_handler;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\database $database_helper Installer's database helper
+ * @param \phpbb\install\helper\config $install_config Installer's config helper
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ */
+ public function __construct(\phpbb\install\helper\database $database_helper,
+ \phpbb\install\helper\config $install_config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler)
+ {
+ $this->database_helper = $database_helper;
+ $this->install_config = $install_config;
+ $this->io_handler = $iohandler;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->io_handler->get_input('submit_database', false))
+ {
+ $this->process_form();
+ }
+ else
+ {
+ $this->request_form_data();
+ }
+ }
+
+ /**
+ * Process form data
+ */
+ protected function process_form()
+ {
+ // Collect database data
+ $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_input('dbpasswd', '', true);
+ $dbname = $this->io_handler->get_input('dbname', '');
+ $table_prefix = $this->io_handler->get_input('table_prefix', '');
+
+ // Check database data
+ $user_data_vaild = $this->check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpasswd, $dbname, $table_prefix);
+
+ // Save database data if it is correct
+ if ($user_data_vaild)
+ {
+ $this->install_config->set('dbms', $dbms);
+ $this->install_config->set('dbhost', $dbhost);
+ $this->install_config->set('dbport', $dbport);
+ $this->install_config->set('dbuser', $dbuser);
+ $this->install_config->set('dbpasswd', $dbpasswd);
+ $this->install_config->set('dbname', $dbname);
+ $this->install_config->set('table_prefix', $table_prefix);
+ }
+ else
+ {
+ $this->request_form_data(true);
+ }
+ }
+
+ /**
+ * Request data from the user
+ *
+ * @param bool $use_request_data Whether to use submited data
+ *
+ * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data
+ */
+ protected function request_form_data($use_request_data = false)
+ {
+ if ($use_request_data)
+ {
+ $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', '');
+ $dbname = $this->io_handler->get_input('dbname', '');
+ $table_prefix = $this->io_handler->get_input('table_prefix', 'phpbb_');
+ }
+ else
+ {
+ $dbms = '';
+ $dbhost = '';
+ $dbport = '';
+ $dbuser = '';
+ $dbname = '';
+ $table_prefix = 'phpbb_';
+ }
+
+ $dbms_select = array();
+ foreach ($this->database_helper->get_available_dbms() as $dbms_key => $dbms_array)
+ {
+ $dbms_select[] = array(
+ 'value' => $dbms_key,
+ 'label' => 'DB_OPTION_' . strtoupper($dbms_key),
+ 'selected' => ($dbms_key === $dbms),
+ );
+ }
+
+ $database_form = array(
+ 'dbms' => array(
+ 'label' => 'DBMS',
+ 'type' => 'select',
+ 'options' => $dbms_select,
+ ),
+ 'dbhost' => array(
+ 'label' => 'DB_HOST',
+ 'description' => 'DB_HOST_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $dbhost,
+ ),
+ 'dbport' => array(
+ 'label' => 'DB_PORT',
+ 'description' => 'DB_PORT_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $dbport,
+ ),
+ 'dbuser' => array(
+ 'label' => 'DB_USERNAME',
+ 'type' => 'text',
+ 'default' => $dbuser,
+ ),
+ 'dbpasswd' => array(
+ 'label' => 'DB_PASSWORD',
+ 'type' => 'password',
+ ),
+ 'dbname' => array(
+ 'label' => 'DB_NAME',
+ 'type' => 'text',
+ 'default' => $dbname,
+ ),
+ 'table_prefix' => array(
+ 'label' => 'TABLE_PREFIX',
+ 'description' => 'TABLE_PREFIX_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $table_prefix,
+ ),
+ 'submit_database' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ );
+
+ $this->io_handler->add_user_form_group('DB_CONFIG', $database_form);
+
+ // Require user interaction
+ throw new user_interaction_required_exception();
+ }
+
+ /**
+ * Check database data
+ *
+ * @param string $dbms Selected database type
+ * @param string $dbhost Database host address
+ * @param int $dbport Database port number
+ * @param string $dbuser Database username
+ * @param string $dbpass Database password
+ * @param string $dbname Database name
+ * @param string $table_prefix Database table prefix
+ *
+ * @return bool True if database data is correct, false otherwise
+ */
+ protected function check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix)
+ {
+ $available_dbms = $this->database_helper->get_available_dbms();
+ $data_valid = true;
+
+ // Check if PHP has the database extensions for the specified DBMS
+ if (!isset($available_dbms[$dbms]))
+ {
+ $this->io_handler->add_error_message('INST_ERR_NO_DB');
+ $data_valid = false;
+ }
+
+ // Validate table prefix
+ $prefix_valid = $this->database_helper->validate_table_prefix($dbms, $table_prefix);
+ if (is_array($prefix_valid))
+ {
+ foreach ($prefix_valid as $error)
+ {
+ $this->io_handler->add_error_message(
+ $error['title'],
+ (isset($error['description'])) ? $error['description'] : false
+ );
+ }
+
+ $data_valid = false;
+ }
+
+ // Try to connect to database if all provided data is valid
+ if ($data_valid)
+ {
+ $connect_test = $this->database_helper->check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix);
+ if (is_array($connect_test))
+ {
+ foreach ($connect_test as $error)
+ {
+ $this->io_handler->add_error_message(
+ $error['title'],
+ (isset($error['description'])) ? $error['description'] : false
+ );
+ }
+
+ $data_valid = false;
+ }
+ }
+
+ return $data_valid;
+ }
+
+ /**
+ * {@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_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php
new file mode 100644
index 0000000000..1cb4f04297
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php
@@ -0,0 +1,173 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+
+class obtain_email_data extends \phpbb\install\task_base implements \phpbb\install\task_interface
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $io_handler;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config Installer's config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler)
+ {
+ $this->install_config = $config;
+ $this->io_handler = $iohandler;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // 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_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', '');
+
+ $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP');
+
+ // Check if data is sent
+ if ($this->io_handler->get_input('submit_email', false))
+ {
+ $this->install_config->set('email_enable', $email_enable);
+ $this->install_config->set('smtp_delivery', $smtp_delivery);
+ $this->install_config->set('smtp_host', $smtp_host);
+ $this->install_config->set('smtp_port', $smtp_port);
+ $this->install_config->set('smtp_auth', $smtp_auth);
+ $this->install_config->set('smtp_user', $smtp_user);
+ $this->install_config->set('smtp_pass', $smtp_passwd);
+ }
+ else
+ {
+ $auth_options = array();
+ foreach ($auth_methods as $method)
+ {
+ $auth_options[] = array(
+ 'value' => $method,
+ 'label' => 'SMTP_' . str_replace('-', '_', $method),
+ 'selected' => false,
+ );
+ }
+
+ $email_form = array(
+ 'email_enable' => array(
+ 'label' => 'ENABLE_EMAIL',
+ 'description' => 'COOKIE_SECURE_EXPLAIN',
+ 'type' => 'radio',
+ 'options' => array(
+ array(
+ 'value' => 1,
+ 'label' => 'ENABLE',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 0,
+ 'label' => 'DISABLE',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'smtp_delivery' => array(
+ 'label' => 'USE_SMTP',
+ 'description' => 'USE_SMTP_EXPLAIN',
+ 'type' => 'radio',
+ 'options' => array(
+ array(
+ 'value' => 0,
+ 'label' => 'NO',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 1,
+ 'label' => 'YES',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'smtp_host' => array(
+ 'label' => 'SMTP_SERVER',
+ 'type' => 'text',
+ 'default' => $smtp_host,
+ ),
+ 'smtp_port' => array(
+ 'label' => 'SMTP_PORT',
+ 'type' => 'text',
+ 'default' => $smtp_port,
+ ),
+ 'smtp_auth' => array(
+ 'label' => 'SMTP_AUTH_METHOD',
+ 'description' => 'SMTP_AUTH_METHOD_EXPLAIN',
+ 'type' => 'select',
+ 'options' => $auth_options,
+ ),
+ 'smtp_user' => array(
+ 'label' => 'SMTP_USERNAME',
+ 'description' => 'SMTP_USERNAME_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $smtp_user,
+ ),
+ 'smtp_pass' => array(
+ 'label' => 'SMTP_PASSWORD',
+ 'description' => 'SMTP_PASSWORD_EXPLAIN',
+ 'type' => 'password',
+ ),
+ 'submit_email' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ );
+
+ $this->io_handler->add_user_form_group('EMAIL_CONFIG', $email_form);
+
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@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_file_updater_method.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php
new file mode 100644
index 0000000000..d5a8855c37
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php
@@ -0,0 +1,167 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class obtain_file_updater_method extends task_base
+{
+ /**
+ * @var array Supported compression methods
+ *
+ * Note: .tar is assumed to be supported, but not in the list
+ */
+ protected $available_methods;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param config $installer_config
+ * @param iohandler_interface $iohandler
+ */
+ public function __construct(config $installer_config, iohandler_interface $iohandler)
+ {
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+
+ $this->available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->iohandler->get_input('submit_update_file', false))
+ {
+ $supported_methods = array('compression', 'ftp', 'direct_file');
+ $method = $this->iohandler->get_input('method', 'compression');
+ $update_method = (in_array($method, $supported_methods, true)) ? $method : 'compression';
+ $this->installer_config->set('file_update_method', $update_method);
+
+ $compression = $this->iohandler->get_input('compression_method', '.zip');
+ $supported_methods = array_keys($this->available_methods);
+ $supported_methods[] = '.tar';
+ $compression = (in_array($compression, $supported_methods, true)) ? $compression : '.zip';
+ $this->installer_config->set('file_update_compression', $compression);
+ }
+ else
+ {
+ $this->iohandler->add_user_form_group('UPDATE_FILE_METHOD_TITLE', array(
+ 'method' => array(
+ 'label' => 'UPDATE_FILE_METHOD',
+ 'type' => 'select',
+ 'options' => array(
+ array(
+ 'value' => 'compression',
+ 'label' => 'UPDATE_FILE_METHOD_DOWNLOAD',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 'ftp',
+ 'label' => 'UPDATE_FILE_METHOD_FTP',
+ 'selected' => false,
+ ),
+ array(
+ 'value' => 'direct_file',
+ 'label' => 'UPDATE_FILE_METHOD_FILESYSTEM',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'compression_method' => array(
+ 'label' => 'SELECT_DOWNLOAD_FORMAT',
+ 'type' => 'select',
+ 'options' => $this->get_available_compression_methods(),
+ ),
+ 'submit_update_file' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ ));
+
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * Returns form elements in an array of available compression methods
+ *
+ * @return array
+ */
+ protected function get_available_compression_methods()
+ {
+ $methods[] = array(
+ 'value' => '.tar',
+ 'label' => '.tar',
+ 'selected' => true,
+ );
+
+ foreach ($this->available_methods as $type => $module)
+ {
+ if (!@extension_loaded($module))
+ {
+ continue;
+ }
+
+ $methods[] = array(
+ 'value' => $type,
+ 'label' => $type,
+ 'selected' => false,
+ );
+ }
+
+ return $methods;
+ }
+
+ /**
+ * {@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_imagick_path.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php
new file mode 100644
index 0000000000..377d96ed1a
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php
@@ -0,0 +1,89 @@
+<?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
new file mode 100644
index 0000000000..1ef70eae08
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php
@@ -0,0 +1,202 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+
+/**
+ * This class requests and saves some information about the server
+ */
+class obtain_server_data extends \phpbb\install\task_base implements \phpbb\install\task_interface
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $io_handler;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config Installer's config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler Installer's input-output handler
+ */
+ public function __construct(\phpbb\install\helper\config $config,
+ \phpbb\install\helper\iohandler\iohandler_interface $iohandler)
+ {
+ $this->install_config = $config;
+ $this->io_handler = $iohandler;
+
+ parent::__construct(true);
+ }
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $cookie_secure = $this->io_handler->is_secure();
+ $server_protocol = ($this->io_handler->is_secure()) ? 'https://' : 'http://';
+ $server_port = $this->io_handler->get_server_variable('SERVER_PORT', 0);
+
+ // HTTP_HOST is having the correct browser url in most cases...
+ $server_name = strtolower(htmlspecialchars_decode($this->io_handler->get_header_variable(
+ 'Host',
+ $this->io_handler->get_server_variable('SERVER_NAME')
+ )));
+
+ // HTTP HOST can carry a port number...
+ if (strpos($server_name, ':') !== false)
+ {
+ $server_name = substr($server_name, 0, strpos($server_name, ':'));
+ }
+
+ $script_path = htmlspecialchars_decode($this->io_handler->get_server_variable('PHP_SELF'));
+
+ if (!$script_path)
+ {
+ $script_path = htmlspecialchars_decode($this->io_handler->get_server_variable('REQUEST_URI'));
+ }
+
+ $script_path = str_replace(array('\\', '//'), '/', $script_path);
+ $script_path = trim(dirname(dirname(dirname($script_path)))); // Because we are in install/app.php/route_name
+
+ // Server data
+ $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_port = $this->io_handler->get_input('server_port', $server_port);
+ $script_path = $this->io_handler->get_input('script_path', $script_path);
+
+ // Clean up script path
+ if ($script_path !== '/')
+ {
+ // Adjust destination path (no trailing slash)
+ if (substr($script_path, -1) === '/')
+ {
+ $script_path = substr($script_path, 0, -1);
+ }
+
+ $script_path = str_replace(array('../', './'), '', $script_path);
+
+ if ($script_path[0] !== '/')
+ {
+ $script_path = '/' . $script_path;
+ }
+ }
+
+ // Check if data is sent
+ if ($this->io_handler->get_input('submit_server', false))
+ {
+ $this->install_config->set('cookie_secure', $cookie_secure);
+ $this->install_config->set('server_protocol', $server_protocol);
+ $this->install_config->set('force_server_vars', $force_server_vars);
+ $this->install_config->set('server_name', $server_name);
+ $this->install_config->set('server_port', $server_port);
+ $this->install_config->set('script_path', $script_path);
+ }
+ else
+ {
+ // Render form
+ $server_form = array(
+ 'cookie_secure' => array(
+ 'label' => 'COOKIE_SECURE',
+ 'description' => 'COOKIE_SECURE_EXPLAIN',
+ 'type' => 'radio',
+ 'options' => array(
+ array(
+ 'value' => 0,
+ 'label' => 'NO',
+ 'selected' => (!$cookie_secure),
+ ),
+ array(
+ 'value' => 1,
+ 'label' => 'YES',
+ 'selected' => ($cookie_secure),
+ ),
+ ),
+ ),
+ 'force_server_vars' => array(
+ 'label' => 'FORCE_SERVER_VARS',
+ 'description' => 'FORCE_SERVER_VARS_EXPLAIN',
+ 'type' => 'radio',
+ 'options' => array(
+ array(
+ 'value' => 0,
+ 'label' => 'NO',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 1,
+ 'label' => 'YES',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'server_protocol' => array(
+ 'label' => 'SERVER_PROTOCOL',
+ 'description' => 'SERVER_PROTOCOL_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $server_protocol,
+ ),
+ 'server_name' => array(
+ 'label' => 'SERVER_NAME',
+ 'description' => 'SERVER_NAME_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $server_name,
+ ),
+ 'server_port' => array(
+ 'label' => 'SERVER_PORT',
+ 'description' => 'SERVER_PORT_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $server_port,
+ ),
+ 'script_path' => array(
+ 'label' => 'SCRIPT_PATH',
+ 'description' => 'SCRIPT_PATH_EXPLAIN',
+ 'type' => 'text',
+ 'default' => $script_path,
+ ),
+ 'submit_server' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ )
+ );
+
+ $this->io_handler->add_user_form_group('SERVER_CONFIG', $server_form);
+
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@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_update_files.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php
new file mode 100644
index 0000000000..0cb809154e
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php
@@ -0,0 +1,113 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class obtain_update_files extends task_base
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(config $config, iohandler_interface $iohandler, $phpbb_root_path, $php_ext)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Load update info file
+ // The file should be checked in the requirements, so we assume that it exists
+ $update_info_file = $this->phpbb_root_path . 'install/update/index.' . $this->php_ext;
+ include($update_info_file);
+ $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
+
+ // If the file is invalid, abort mission
+ if (!$info)
+ {
+ $this->iohandler->add_error_message('WRONG_INFO_FILE_FORMAT');
+ throw new user_interaction_required_exception();
+ }
+
+ // Replace .php with $this->php_ext if needed
+ if ($this->php_ext !== 'php')
+ {
+ $custom_extension = '.' . $this->php_ext;
+ $info['files'] = preg_replace('#\.php$#i', $custom_extension, $info['files']);
+ }
+
+ // Save update info
+ $this->installer_config->set('update_info_unprocessed', $info);
+ }
+
+ /**
+ * {@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_update_ftp_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php
new file mode 100644
index 0000000000..f31472fc58
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php
@@ -0,0 +1,163 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+class obtain_update_ftp_data extends task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param config $installer_config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $php_ext
+ */
+ public function __construct(config $installer_config, iohandler_interface $iohandler, update_helper $update_helper, $php_ext)
+ {
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->php_ext = $php_ext;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return ($this->installer_config->get('do_update_files', false) &&
+ ($this->installer_config->get('file_update_method', '') === 'ftp')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if ($this->iohandler->get_input('submit_ftp', false))
+ {
+ $this->update_helper->include_file('includes/functions_transfer.' . $this->php_ext);
+
+ $method = 'ftp';
+ $methods = \transfer::methods();
+ if (!in_array($method, $methods, true))
+ {
+ $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_port = $this->iohandler->get_input('ftp_port', 21);
+ $ftp_time = $this->iohandler->get_input('ftp_timeout', 10);
+
+ $this->installer_config->set('ftp_host', $ftp_host);
+ $this->installer_config->set('ftp_user', $ftp_user);
+ $this->installer_config->set('ftp_pass', $ftp_pass);
+ $this->installer_config->set('ftp_path', $ftp_path);
+ $this->installer_config->set('ftp_port', (int) $ftp_port);
+ $this->installer_config->set('ftp_timeout', (int) $ftp_time);
+ $this->installer_config->set('ftp_method', $method);
+ }
+ else
+ {
+ $this->iohandler->add_user_form_group('FTP_SETTINGS', array(
+ 'ftp_host' => array(
+ 'label' => 'FTP_HOST',
+ 'description' => 'FTP_HOST_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'ftp_user' => array(
+ 'label' => 'FTP_USERNAME',
+ 'description' => 'FTP_USERNAME_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'ftp_pass' => array(
+ 'label' => 'FTP_PASSWORD',
+ 'description' => 'FTP_PASSWORD_EXPLAIN',
+ 'type' => 'password',
+ ),
+ 'ftp_path' => array(
+ 'label' => 'FTP_ROOT_PATH',
+ 'description' => 'FTP_ROOT_PATH_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'ftp_port' => array(
+ 'label' => 'FTP_PORT',
+ 'description' => 'FTP_PORT_EXPLAIN',
+ 'type' => 'text',
+ 'default' => 21,
+ ),
+ 'ftp_timeout' => array(
+ 'label' => 'FTP_TIMEOUT',
+ 'description' => 'FTP_TIMEOUT_EXPLAIN',
+ 'type' => 'text',
+ 'default' => 10,
+ ),
+ 'submit_ftp' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ ));
+
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@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_update_settings.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php
new file mode 100644
index 0000000000..3b24e8ba40
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php
@@ -0,0 +1,123 @@
+<?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;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class obtain_update_settings extends task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param config $installer_config
+ * @param iohandler_interface $iohandler
+ */
+ public function __construct(config $installer_config, iohandler_interface $iohandler)
+ {
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->iohandler->get_input('submit_update', false))
+ {
+ $update_files = $this->iohandler->get_input('update_type', 'all') === 'all';
+
+ if ($this->installer_config->get('disable_filesystem_update', false) && $update_files)
+ {
+ $this->iohandler->add_error_message('UPDATE_FILES_NOT_FOUND');
+
+ throw new user_interaction_required_exception();
+ }
+
+ $this->installer_config->set('do_update_files', $update_files);
+ }
+ else
+ {
+ if ($this->installer_config->get('disable_filesystem_update', false))
+ {
+ $options[] = array(
+ 'value' => 'db_only',
+ 'label' => 'UPDATE_TYPE_DB_ONLY',
+ 'selected' => true,
+ );
+ }
+ else
+ {
+ $options = array(
+ array(
+ 'value' => 'all',
+ 'label' => 'UPDATE_TYPE_ALL',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 'db_only',
+ 'label' => 'UPDATE_TYPE_DB_ONLY',
+ 'selected' => false,
+ ),
+ );
+ }
+
+ $this->iohandler->add_user_form_group('UPDATE_TYPE', array(
+ 'update_type' => array(
+ 'label' => 'UPDATE_TYPE',
+ 'type' => 'radio',
+ 'options' => $options,
+ ),
+ 'submit_update' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ ));
+
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@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/update_module.php b/phpBB/phpbb/install/module/obtain_data/update_module.php
new file mode 100644
index 0000000000..c2f9019d34
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/update_module.php
@@ -0,0 +1,33 @@
+<?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;
+
+class update_module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'obtain_data');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php b/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php
new file mode 100644
index 0000000000..121b4ff4e5
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php
@@ -0,0 +1,71 @@
+<?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\requirements;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\module_base;
+
+/**
+ * Base class for requirements installer module
+ */
+abstract class abstract_requirements_module extends module_base
+{
+ public function run()
+ {
+ $tests_passed = true;
+ foreach ($this->task_collection as $name => $task)
+ {
+ // Check if we can run the task
+ if (!$task->is_essential() && !$task->check_requirements())
+ {
+ continue;
+ }
+
+ if ($this->allow_progress_bar)
+ {
+ $this->install_config->increment_current_task_progress();
+ }
+
+ $test_result = $task->run();
+ $tests_passed = ($tests_passed) ? $test_result : false;
+ }
+
+ // Module finished, so clear task progress
+ $this->install_config->set_finished_task(0);
+
+ // Check if tests have failed
+ if (!$tests_passed)
+ {
+ // If requirements are not met, exit form installer
+ // Set up UI for retesting
+ $this->iohandler->add_user_form_group('', array(
+ 'install' => array(
+ 'label' => 'RETEST_REQUIREMENTS',
+ 'type' => 'submit',
+ ),
+ ));
+
+ // Send the response and quit
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/install_module.php b/phpBB/phpbb/install/module/requirements/install_module.php
new file mode 100644
index 0000000000..ed0c5fbd94
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/install_module.php
@@ -0,0 +1,25 @@
+<?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\requirements;
+
+class install_module extends abstract_requirements_module
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'requirements');
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/task/check_filesystem.php b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php
new file mode 100644
index 0000000000..868af39433
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php
@@ -0,0 +1,279 @@
+<?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\requirements\task;
+
+/**
+ * Checks filesystem requirements
+ */
+class check_filesystem extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var array
+ */
+ protected $files_to_check;
+
+ /**
+ * @var bool
+ */
+ protected $tests_passed;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $response;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\filesystem\filesystem_interface $filesystem filesystem handler
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $response response helper
+ * @param string $phpbb_root_path relative path to phpBB's root
+ * @param string $php_ext extension of php files
+ * @param bool $check_config_php Whether or not to check if config.php is writable
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \phpbb\install\helper\iohandler\iohandler_interface $response, $phpbb_root_path, $php_ext, $check_config_php = true)
+ {
+ parent::__construct(true);
+
+ $this->filesystem = $filesystem;
+ $this->response = $response;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ $this->tests_passed = false;
+
+ // Files/Directories to check
+ // All file/directory names must be relative to phpBB's root path
+ $this->files_to_check = array(
+ array(
+ 'path' => 'cache/',
+ 'failable' => false,
+ 'is_file' => false,
+ ),
+ array(
+ 'path' => 'store/',
+ 'failable' => false,
+ 'is_file' => false,
+ ),
+ array(
+ 'path' => 'files/',
+ 'failable' => false,
+ 'is_file' => false,
+ ),
+ array(
+ 'path' => 'images/avatars/upload/',
+ 'failable' => true,
+ 'is_file' => false,
+ ),
+ );
+
+ if ($check_config_php)
+ {
+ $this->files_to_check[] = array(
+ 'path' => "config.$php_ext",
+ 'failable' => false,
+ 'is_file' => true,
+ );
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->tests_passed = true;
+
+ // Check files/directories to be writable
+ foreach ($this->files_to_check as $file)
+ {
+ if ($file['is_file'])
+ {
+ $this->check_file($file['path'], $file['failable']);
+ }
+ else
+ {
+ $this->check_dir($file['path'], $file['failable']);
+ }
+ }
+
+ return $this->tests_passed;
+ }
+
+ /**
+ * Sets $this->tests_passed
+ *
+ * @param bool $is_passed
+ */
+ protected function set_test_passed($is_passed)
+ {
+ // If one test failed, tests_passed should be false
+ $this->tests_passed = (!$this->tests_passed) ? false : $is_passed;
+ }
+
+ /**
+ * Check if a file is readable and writable
+ *
+ * @param string $file Filename
+ * @param bool $failable Whether failing test should interrupt installation process
+ */
+ protected function check_file($file, $failable = false)
+ {
+ $path = $this->phpbb_root_path . $file;
+ $exists = $writable = true;
+
+ // Try to create file if it does not exists
+ if (!file_exists($path))
+ {
+ $fp = @fopen($path, 'w');
+ @fclose($fp);
+ try
+ {
+ $this->filesystem->phpbb_chmod($path,
+ \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE
+ );
+ $exists = true;
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ }
+
+ if (file_exists($path))
+ {
+ if (!$this->filesystem->is_writable($path))
+ {
+ $writable = false;
+ }
+ }
+ else
+ {
+ $exists = $writable = false;
+ }
+
+ $this->set_test_passed(($exists && $writable) || $failable);
+
+ if (!($exists && $writable))
+ {
+ $title = ($exists) ? 'FILE_NOT_WRITABLE' : 'FILE_NOT_EXISTS';
+ $lang_suffix = '_EXPLAIN';
+ $lang_suffix .= ($failable) ? '_OPTIONAL' : '';
+ $description = array($title . $lang_suffix, $file);
+
+ if ($failable)
+ {
+ $this->response->add_warning_message($title, $description);
+ }
+ else
+ {
+ $this->response->add_error_message($title, $description);
+ }
+ }
+ }
+
+ /**
+ * Check if a directory is readable and writable
+ *
+ * @param string $dir Filename
+ * @param bool $failable Whether failing test should abort the installation process
+ */
+ protected function check_dir($dir, $failable = false)
+ {
+ $path = $this->phpbb_root_path . $dir;
+ $exists = $writable = false;
+
+ // Try to create the directory if it does not exist
+ if (!file_exists($path))
+ {
+ try
+ {
+ $this->filesystem->mkdir($path, 0777);
+ $this->filesystem->phpbb_chmod($path,
+ \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE
+ );
+ $exists = true;
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ }
+
+ // Now really check
+ if (file_exists($path) && is_dir($path))
+ {
+ try
+ {
+ $exists = true;
+ $this->filesystem->phpbb_chmod($path,
+ \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE
+ );
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ }
+
+ if ($this->filesystem->is_writable($path))
+ {
+ $writable = true;
+ }
+
+ $this->set_test_passed(($exists && $writable) || $failable);
+
+ if (!($exists && $writable))
+ {
+ $title = ($exists) ? 'DIRECTORY_NOT_WRITABLE' : 'DIRECTORY_NOT_EXISTS';
+ $lang_suffix = '_EXPLAIN';
+ $lang_suffix .= ($failable) ? '_OPTIONAL' : '';
+ $description = array($title . $lang_suffix, $dir);
+
+ if ($failable)
+ {
+ $this->response->add_warning_message($title, $description);
+ }
+ else
+ {
+ $this->response->add_error_message($title, $description);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/task/check_server_environment.php b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php
new file mode 100644
index 0000000000..29f9777747
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php
@@ -0,0 +1,209 @@
+<?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\requirements\task;
+
+/**
+ * Installer task that checks if the server meats phpBB requirements
+ */
+class check_server_environment extends \phpbb\install\task_base
+{
+ /**
+ * @var \phpbb\install\helper\database
+ */
+ protected $database_helper;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $response_helper;
+
+ /**
+ * @var bool
+ */
+ protected $tests_passed;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\database $database_helper
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $response
+ */
+ public function __construct(\phpbb\install\helper\database $database_helper,
+ \phpbb\install\helper\iohandler\iohandler_interface $response)
+ {
+ $this->database_helper = $database_helper;
+ $this->response_helper = $response;
+ $this->tests_passed = true;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ //
+ // Check requirements
+ // The error messages should be set in the check_ functions
+ //
+
+ // Check PHP version
+ $this->check_php_version();
+
+ // Check for getimagesize()
+ $this->check_image_size();
+
+ // Check for PCRE support
+ $this->check_pcre();
+
+ // Check for JSON support
+ $this->check_json();
+
+ // XML extension support check
+ $this->check_xml();
+
+ // Check for dbms support
+ $this->check_available_dbms();
+
+ return $this->tests_passed;
+ }
+
+ /**
+ * Sets $this->tests_passed
+ *
+ * @param bool $is_passed
+ */
+ protected function set_test_passed($is_passed)
+ {
+ // If one test failed, tests_passed should be false
+ $this->tests_passed = (!$this->tests_passed) ? false : $is_passed;
+ }
+
+ /**
+ * Check if the requirements for PHP version is met
+ */
+ protected function check_php_version()
+ {
+ $php_version = PHP_VERSION;
+
+ if (version_compare($php_version, '5.4') < 0)
+ {
+ $this->response_helper->add_error_message('PHP_VERSION_REQD', 'PHP_VERSION_REQD_EXPLAIN');
+
+ $this->set_test_passed(false);
+ return;
+ }
+
+ $this->set_test_passed(true);
+ }
+
+ /**
+ * Checks if the installed PHP has getimagesize() available
+ */
+ protected function check_image_size()
+ {
+ if (!@function_exists('getimagesize'))
+ {
+ $this->response_helper->add_error_message('PHP_GETIMAGESIZE_SUPPORT', 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN');
+
+ $this->set_test_passed(false);
+ return;
+ }
+
+ $this->set_test_passed(true);
+ }
+
+ /**
+ * Checks if the installed PHP supports PCRE
+ */
+ protected function check_pcre()
+ {
+ if (@preg_match('//u', ''))
+ {
+ $this->set_test_passed(true);
+ return;
+ }
+
+ $this->response_helper->add_error_message('PCRE_UTF_SUPPORT', 'PCRE_UTF_SUPPORT_EXPLAIN');
+
+ $this->set_test_passed(false);
+ }
+
+ /**
+ * Checks whether PHP's JSON extension is available or not
+ */
+ protected function check_json()
+ {
+ if (@extension_loaded('json'))
+ {
+ $this->set_test_passed(true);
+ return;
+ }
+
+ $this->response_helper->add_error_message('PHP_JSON_SUPPORT', 'PHP_JSON_SUPPORT_EXPLAIN');
+
+ $this->set_test_passed(false);
+ }
+
+ /**
+ * Checks whether or not the XML PHP extension is available (Required by the text formatter)
+ */
+ protected function check_xml()
+ {
+ if (class_exists('DOMDocument'))
+ {
+ $this->set_test_passed(true);
+ return;
+ }
+
+ $this->response_helper->add_error_message('PHP_XML_SUPPORT', 'PHP_XML_SUPPORT_EXPLAIN');
+
+ $this->set_test_passed(false);
+ }
+
+ /**
+ * Check if any supported DBMS is available
+ */
+ protected function check_available_dbms()
+ {
+ $available_dbms = $this->database_helper->get_available_dbms(false, true);
+
+ if ($available_dbms['ANY_DB_SUPPORT'])
+ {
+ $this->set_test_passed(true);
+ return;
+ }
+
+ $this->response_helper->add_error_message('PHP_SUPPORTED_DB', 'PHP_SUPPORTED_DB_EXPLAIN');
+
+ $this->set_test_passed(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/task/check_update.php b/phpBB/phpbb/install/module/requirements/task/check_update.php
new file mode 100644
index 0000000000..cd66ffc8f9
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/task/check_update.php
@@ -0,0 +1,195 @@
+<?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\requirements\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * Check the availability of updater files and update version
+ */
+class check_update extends task_base
+{
+ /**
+ * @var \phpbb\config\db
+ */
+ protected $config;
+
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var \phpbb\version_helper
+ */
+ protected $version_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var bool
+ */
+ protected $tests_passed;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param filesystem $filesystem
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(container_factory $container, filesystem $filesystem, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->filesystem = $filesystem;
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->tests_passed = true;
+
+ $this->config = $container->get('config');
+ $this->version_helper = $container->get('version_helper');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * Sets $this->tests_passed
+ *
+ * @param bool $is_passed
+ */
+ protected function set_test_passed($is_passed)
+ {
+ // If one test failed, tests_passed should be false
+ $this->tests_passed = $this->tests_passed && $is_passed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Array of update files
+ $update_files = array(
+ $this->phpbb_root_path . 'install/update',
+ $this->phpbb_root_path . 'install/update/index.' . $this->php_ext,
+ );
+
+ // 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 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...
+ $this->installer_config->set('disable_filesystem_update', true);
+ return true;
+ }
+
+ // Recover version numbers
+ $update_info = array();
+ @include($this->phpbb_root_path . 'install/update/index.' . $this->php_ext);
+ $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
+ $update_version = false;
+
+ if ($info !== false)
+ {
+ $update_version = (!empty($info['version']['to'])) ? trim($info['version']['to']) : false;
+ }
+
+ // Get current and latest version
+ try
+ {
+ $latest_version = $this->version_helper->get_latest_on_current_branch(true);
+ }
+ catch (\RuntimeException $e)
+ {
+ $latest_version = $update_version;
+ }
+
+ $current_version = (!empty($this->config['version_update_from'])) ? $this->config['version_update_from'] : $this->config['version'];
+
+ // Check if the update package
+ if (!$this->update_helper->phpbb_version_compare($current_version, $update_version, '<'))
+ {
+ $this->iohandler->add_error_message('NO_UPDATE_FILES_UP_TO_DATE');
+ $this->tests_passed = false;
+ }
+
+ // Check if the update package works with the installed version
+ if (empty($info['version']['from']) || $info['version']['from'] !== $current_version)
+ {
+ $this->iohandler->add_error_message(array('INCOMPATIBLE_UPDATE_FILES', $current_version, $info['version']['from'], $update_version));
+ $this->tests_passed = false;
+ }
+
+ // check if this is the latest update package
+ if ($this->update_helper->phpbb_version_compare($update_version, $latest_version, '<'))
+ {
+ $this->iohandler->add_warning_message(array('OLD_UPDATE_FILES', $info['version']['from'], $update_version, $latest_version));
+ }
+
+ return $this->tests_passed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/update_module.php b/phpBB/phpbb/install/module/requirements/update_module.php
new file mode 100644
index 0000000000..223d12faf3
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/update_module.php
@@ -0,0 +1,25 @@
+<?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\requirements;
+
+class update_module extends abstract_requirements_module
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'requirements');
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_database/module.php b/phpBB/phpbb/install/module/update_database/module.php
new file mode 100644
index 0000000000..ee38afe17d
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_database/module.php
@@ -0,0 +1,33 @@
+<?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\update_database;
+
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'update_database');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_database/task/update.php b/phpBB/phpbb/install/module/update_database/task/update.php
new file mode 100644
index 0000000000..9d7ba2f919
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_database/task/update.php
@@ -0,0 +1,236 @@
+<?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\update_database\task;
+
+use phpbb\db\migration\exception;
+use phpbb\db\output_handler\installer_migrator_output_handler;
+use phpbb\db\output_handler\log_wrapper_migrator_output_handler;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\task_base;
+
+/**
+ * Database updater task
+ */
+class update extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\extension\manager
+ */
+ protected $extension_manager;
+
+ /**
+ * @var \phpbb\filesystem\filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var \phpbb\log\log
+ */
+ protected $log;
+
+ /**
+ * @var \phpbb\db\migrator
+ */
+ protected $migrator;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\container_factory $container
+ * @param \phpbb\filesystem\filesystem $filesystem
+ * @param \phpbb\install\helper\config $installer_config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
+ * @param \phpbb\language\language $language
+ * @param string $phpbb_root_path
+ */
+ public function __construct(\phpbb\install\helper\container_factory $container, \phpbb\filesystem\filesystem $filesystem, \phpbb\install\helper\config $installer_config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, \phpbb\language\language $language, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+ $this->language = $language;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ $this->cache = $container->get('cache.driver');
+ $this->config = $container->get('config');
+ $this->extension_manager = $container->get('ext.manager');
+ $this->log = $container->get('log');
+ $this->migrator = $container->get('migrator');
+ $this->user = $container->get('user');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->language->add_lang('migrator');
+
+ if (!isset($this->config['version_update_from']))
+ {
+ $this->config->set('version_update_from', $this->config['version']);
+ }
+
+ $original_version = $this->config['version_update_from'];
+
+ $this->migrator->set_output_handler(
+ new log_wrapper_migrator_output_handler(
+ $this->language,
+ new installer_migrator_output_handler($this->iohandler),
+ $this->phpbb_root_path . 'store/migrations_' . time() . '.log',
+ $this->filesystem
+ )
+ );
+
+ $this->migrator->create_migrations_table();
+
+ $migrations = $this->extension_manager
+ ->get_finder()
+ ->core_path('phpbb/db/migration/data/')
+ ->extension_directory('/migrations')
+ ->get_classes();
+
+ $this->migrator->set_migrations($migrations);
+
+ $migration_step_count = $this->installer_config->get('database_update_migration_steps', -1);
+ if ($migration_step_count < 0)
+ {
+ $migration_step_count = count($this->migrator->get_installable_migrations()) * 2;
+ $this->installer_config->set('database_update_migration_steps', $migration_step_count);
+ }
+
+ $progress_count = $this->installer_config->get('database_update_count', 0);
+ $restart_progress_bar = ($progress_count === 0); // Only "restart" when the update runs for the first time
+ $this->iohandler->set_task_count($migration_step_count, $restart_progress_bar);
+ $this->installer_config->set_task_progress_count($migration_step_count);
+
+ while (!$this->migrator->finished())
+ {
+ try
+ {
+ $this->migrator->update();
+ $progress_count++;
+
+ $last_run_migration = $this->migrator->get_last_run_migration();
+ if (isset($last_run_migration['effectively_installed']) && $last_run_migration['effectively_installed'])
+ {
+ // We skipped two step, so increment $progress_count by another one
+ $progress_count++;
+ }
+ else if (($last_run_migration['task'] === 'process_schema_step' && !$last_run_migration['state']['migration_schema_done']) ||
+ ($last_run_migration['task'] === 'process_data_step' && !$last_run_migration['state']['migration_data_done']))
+ {
+ // We just run a step that wasn't counted yet so make it count
+ $migration_step_count++;
+ }
+
+ $this->iohandler->set_task_count($migration_step_count);
+ $this->installer_config->set_task_progress_count($migration_step_count);
+ $this->iohandler->set_progress('STAGE_UPDATE_DATABASE', $progress_count);
+ }
+ catch (exception $e)
+ {
+ $msg = $e->getParameters();
+ array_unshift($msg, $e->getMessage());
+
+ $this->iohandler->add_error_message($msg);
+ throw new user_interaction_required_exception();
+ }
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ $this->installer_config->set('database_update_count', $progress_count);
+ $this->installer_config->set('database_update_migration_steps', $migration_step_count);
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ if ($original_version !== $this->config['version'])
+ {
+ $this->log->add(
+ 'admin',
+ (isset($this->user->data['user_id'])) ? $this->user->data['user_id'] : ANONYMOUS,
+ $this->user->ip,
+ 'LOG_UPDATE_DATABASE',
+ false,
+ array(
+ $original_version,
+ $this->config['version']
+ )
+ );
+ }
+
+ $this->iohandler->add_success_message('INLINE_UPDATE_SUCCESSFUL');
+
+ $this->config->delete('version_update_from');
+
+ $this->cache->purge();
+
+ $this->config->increment('assets_version', 1);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/module.php b/phpBB/phpbb/install/module/update_filesystem/module.php
new file mode 100644
index 0000000000..157c78a1ac
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/module.php
@@ -0,0 +1,33 @@
+<?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\update_filesystem;
+
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'update_files');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php
new file mode 100644
index 0000000000..e3e6db6263
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php
@@ -0,0 +1,205 @@
+<?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\update_filesystem\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * Merges user made changes into the files
+ */
+class diff_files extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $this->cache = $container->get('cache.driver');
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ $files_to_diff = $this->installer_config->get('update_files', array());
+ $files_to_diff = (isset($files_to_diff['update_with_diff'])) ? $files_to_diff['update_with_diff'] : array();
+
+ return $this->installer_config->get('do_update_files', false) && count($files_to_diff) > 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Include diff engine
+ $this->update_helper->include_file('includes/diff/diff.' . $this->php_ext);
+ $this->update_helper->include_file('includes/diff/engine.' . $this->php_ext);
+
+ // Set up basic vars
+ $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'];
+
+ // Set progress bar
+ $this->iohandler->set_task_count(count($files_to_diff), true);
+ $this->iohandler->set_progress('UPDATE_FILE_DIFF', 0);
+ $progress_count = $this->installer_config->get('file_diff_update_count', 0);
+
+ // Recover progress
+ $progress_key = $this->installer_config->get('differ_progress_key', -1);
+ $progress_recovered = ($progress_key === -1);
+ $merge_conflicts = $this->installer_config->get('merge_conflict_list', array());
+
+ foreach ($files_to_diff as $key => $filename)
+ {
+ if ($progress_recovered === false)
+ {
+ if ($progress_key === $key)
+ {
+ $progress_recovered = true;
+ }
+
+ continue;
+ }
+
+ // Read in files' content
+ $file_contents = array();
+
+ // Handle the special case when user created a file with the filename that is now new in the core
+ $file_contents[0] = (file_exists($old_path . $filename)) ? file_get_contents($old_path . $filename) : '';
+
+ $filenames = array(
+ $this->phpbb_root_path . $filename,
+ $new_path . $filename
+ );
+
+ foreach ($filenames as $file_to_diff)
+ {
+ $file_contents[] = file_get_contents($file_to_diff);
+
+ if ($file_contents[sizeof($file_contents) - 1] === false)
+ {
+ $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff));
+ unset($file_contents);
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]);
+ unset($file_contents);
+
+ // Handle conflicts
+ if ($diff->get_num_conflicts() !== 0)
+ {
+ $merge_conflicts[] = $filename;
+ }
+
+ // Save merged output
+ $this->cache->put(
+ '_file_' . md5($filename),
+ base64_encode(implode("\n", $diff->merged_output()))
+ );
+
+ unset($diff);
+
+ $progress_count++;
+ $this->iohandler->set_progress('UPDATE_FILE_DIFF', $progress_count);
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ // Save differ progress
+ $this->installer_config->set('differ_progress_key', $key);
+ $this->installer_config->set('merge_conflict_list', $merge_conflicts);
+ $this->installer_config->set('file_diff_update_count', $progress_count);
+
+ // Request refresh
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ $this->iohandler->finish_progress('ALL_FILES_DIFFED');
+ $this->installer_config->set('merge_conflict_list', $merge_conflicts);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
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
new file mode 100644
index 0000000000..f911b7ac62
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php
@@ -0,0 +1,123 @@
+<?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\update_filesystem\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\jump_to_restart_point_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class download_updated_files extends task_base
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param filesystem $filesystem
+ */
+ public function __construct(config $config, iohandler_interface $iohandler, filesystem $filesystem)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->filesystem = $filesystem;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false)
+ && $this->installer_config->get('file_update_method', '') === 'compression';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if ($this->iohandler->get_input('database_update_submit', false))
+ {
+ // Remove archive
+ $this->filesystem->remove(
+ $this->installer_config->get('update_file_archive', null)
+ );
+
+ $this->installer_config->set('update_file_archive', null);
+ }
+ else if ($this->iohandler->get_input('update_recheck_files_submit', false))
+ {
+ throw new jump_to_restart_point_exception('check_update_files');
+ }
+ else
+ {
+ // Render download box
+ $this->iohandler->add_download_link(
+ 'phpbb_installer_update_file_download',
+ 'DOWNLOAD_UPDATE_METHOD',
+ 'DOWNLOAD_UPDATE_METHOD_EXPLAIN'
+ );
+
+ // 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',
+ ),
+ 'database_update_submit' => array(
+ 'label' => 'UPDATE_CONTINUE_UPDATE_PROCESS',
+ 'type' => 'submit',
+ ),
+ ));
+
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php
new file mode 100644
index 0000000000..f4b3870148
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php
@@ -0,0 +1,187 @@
+<?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\update_filesystem\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * Updater task performing file checking
+ */
+class file_check extends task_base
+{
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Construct
+ *
+ * @param filesystem $filesystem
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ */
+ public function __construct(filesystem $filesystem, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if (!$this->installer_config->has_restart_point('check_update_files'))
+ {
+ $this->installer_config->create_progress_restart_point('check_update_files');
+ }
+
+ $old_path = $this->update_helper->get_path_to_old_update_files();
+ $new_path = $this->update_helper->get_path_to_new_update_files();
+
+ $update_info = $this->installer_config->get('update_info', array());
+ $file_update_info = $this->installer_config->get('update_files', array());
+
+ if (empty($update_info))
+ {
+ $root_path = $this->phpbb_root_path;
+
+ $update_info = $this->installer_config->get('update_info_unprocessed', array());
+
+ $file_update_info = array();
+ $file_update_info['update_without_diff'] = array_diff($update_info['binary'], $update_info['deleted']);
+
+ // Filter out files that are already deleted
+ $file_update_info['delete'] = array_filter(
+ $update_info['deleted'],
+ function ($filename) use ($root_path)
+ {
+ return file_exists($root_path . $filename);
+ }
+ );
+ }
+
+ $progress_count = $this->installer_config->get('file_check_progress_count', 0);
+ $task_count = count($update_info['files']);
+ $this->iohandler->set_task_count($task_count);
+ $this->iohandler->set_progress('UPDATE_CHECK_FILES', 0);
+
+ foreach ($update_info['files'] as $key => $filename)
+ {
+ $old_file = $old_path . $filename;
+ $new_file = $new_path . $filename;
+ $file = $this->phpbb_root_path . $filename;
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ // Save progress
+ $this->installer_config->set('update_info', $update_info);
+ $this->installer_config->set('file_check_progress_count', $progress_count);
+ $this->installer_config->set('update_files', $file_update_info);
+
+ // Request refresh
+ throw new resource_limit_reached_exception();
+ }
+
+ $progress_count++;
+ $this->iohandler->set_progress('UPDATE_CHECK_FILES', $progress_count);
+
+ if (!$this->filesystem->exists($file))
+ {
+ $file_update_info['new'][] = $filename;
+ }
+ else
+ {
+ $file_checksum = md5_file($file);
+
+ if ($file_checksum === md5_file($new_file))
+ {
+ // File already up to date
+ continue;
+ }
+ else if ($this->filesystem->exists($old_file) && $file_checksum === md5_file($old_file))
+ {
+ // No need to diff the file
+ $file_update_info['update_without_diff'][] = $filename;
+ }
+ else
+ {
+ $file_update_info['update_with_diff'][] = $filename;
+ }
+ }
+
+ unset($update_info['files'][$key]);
+ }
+
+ $this->installer_config->set('update_files', $file_update_info);
+ $this->installer_config->set('update_info', array());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
new file mode 100644
index 0000000000..7f18950cf6
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
@@ -0,0 +1,170 @@
+<?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\update_filesystem\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\file_updater\factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class show_file_status extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\install\helper\file_updater\compression_file_updater
+ */
+ protected $file_updater;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param filesystem $filesystem
+ * @param factory $file_updater_factory
+ */
+ public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, filesystem $filesystem, factory $file_updater_factory)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->filesystem = $filesystem;
+
+ $this->cache = $container->get('cache.driver');
+
+ // Initialize compression file updater
+ $this->file_updater = $file_updater_factory->get('compression');
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if (!$this->iohandler->get_input('submit_continue_file_update', false))
+ {
+ // Handle merge conflicts
+ $merge_conflicts = $this->installer_config->get('merge_conflict_list', array());
+
+ // Create archive for merge conflicts
+ if (!empty($merge_conflicts))
+ {
+ $compression_method = $this->installer_config->get('compression_method', '');
+ $conflict_archive = $this->file_updater->init($compression_method);
+ $this->installer_config->set('update_file_conflict_archive', $conflict_archive);
+
+ foreach ($merge_conflicts as $filename)
+ {
+ $this->file_updater->create_new_file(
+ $filename,
+ base64_decode($this->cache->get('_file_' . md5($filename))),
+ true
+ );
+ }
+
+ // Render download box
+ $this->iohandler->add_download_link(
+ 'phpbb_installer_update_conflict_download',
+ 'DOWNLOAD_CONFLICTS',
+ 'DOWNLOAD_CONFLICTS_EXPLAIN'
+ );
+
+ $this->file_updater->close();
+ }
+
+ // Render update file statuses
+ $file_update_info = $this->installer_config->get('update_files', array());
+ $file_status = array(
+ 'deleted' => (!isset($file_update_info['delete'])) ? array() : $file_update_info['delete'],
+ 'new' => (!isset($file_update_info['new'])) ? array() : $file_update_info['new'],
+ 'conflict' => $this->installer_config->get('merge_conflict_list', array()),
+ 'modified' => (!isset($file_update_info['update_with_diff'])) ? array() : $file_update_info['update_with_diff'],
+ 'not_modified' => (!isset($file_update_info['update_without_diff'])) ? array() : $file_update_info['update_without_diff'],
+ );
+
+ $this->iohandler->render_update_file_status($file_status);
+
+ // Add form to continue update
+ $this->iohandler->add_user_form_group('UPDATE_CONTINUE_FILE_UPDATE', array(
+ 'submit_continue_file_update' => array(
+ 'label' => 'UPDATE_CONTINUE_FILE_UPDATE',
+ 'type' => 'submit',
+ ),
+ ));
+
+ // Show results to the user
+ throw new user_interaction_required_exception();
+ }
+ else
+ {
+ $conflict_archive_path = $this->installer_config->get('update_file_conflict_archive', null);
+
+ // Remove archive
+ if ($conflict_archive_path !== null && $this->filesystem->exists($conflict_archive_path))
+ {
+ $this->filesystem->remove($conflict_archive_path);
+ }
+
+ $this->installer_config->set('update_file_conflict_archive', null);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/update_files.php b/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
new file mode 100644
index 0000000000..fbb465cc66
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
@@ -0,0 +1,294 @@
+<?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\update_filesystem\task;
+
+use phpbb\exception\runtime_exception;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\file_updater\factory;
+use phpbb\install\helper\file_updater\file_updater_interface;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * File updater task
+ */
+class update_files extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var factory
+ */
+ protected $factory;
+
+ /**
+ * @var file_updater_interface
+ */
+ protected $file_updater;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param factory $file_updater_factory
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ */
+ public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, factory $file_updater_factory, update_helper $update_helper, $phpbb_root_path)
+ {
+ $this->factory = $file_updater_factory;
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ $this->cache = $container->get('cache.driver');
+ $this->file_updater = null;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $new_path = $this->update_helper->get_path_to_new_update_files();
+
+ $file_update_info = $this->installer_config->get('update_files', array());
+
+ $update_type_progress = $this->installer_config->get('file_updater_type_progress', '');
+ $update_elem_progress = $this->installer_config->get('file_updater_elem_progress', '');
+ $type_progress_found = false;
+ $elem_progress_found = false;
+
+ // Progress bar
+ $task_count = 0;
+ foreach ($file_update_info as $sub_array)
+ {
+ $task_count += count($sub_array);
+ }
+
+ // Everything is up to date, so just continue
+ if ($task_count === 0)
+ {
+ return;
+ }
+
+ $progress_count = $this->installer_config->get('file_update_progress_count', 0);
+ $this->iohandler->set_task_count($task_count, true);
+ $this->iohandler->set_progress('UPDATE_UPDATING_FILES', 0);
+
+ $this->file_updater = $this->get_file_updater();
+
+ // File updater fallback logic
+ try
+ {
+ // Update files
+ foreach ($file_update_info as $type => $file_update_vector)
+ {
+ if (!$type_progress_found)
+ {
+ if ($type === $update_type_progress || empty($update_elem_progress))
+ {
+ $type_progress_found = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ foreach ($file_update_vector as $path)
+ {
+ if (!$elem_progress_found)
+ {
+ if ($path === $update_elem_progress || empty($update_elem_progress))
+ {
+ $elem_progress_found = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ switch ($type)
+ {
+ case 'delete':
+ $this->file_updater->delete_file($path);
+ break;
+ case 'new':
+ $this->file_updater->create_new_file($path, $new_path . $path);
+ break;
+ case 'update_without_diff':
+ $this->file_updater->update_file($path, $new_path . $path);
+ break;
+ case 'update_with_diff':
+ $this->file_updater->update_file(
+ $path,
+ base64_decode($this->cache->get('_file_' . md5($path))),
+ true
+ );
+ break;
+ }
+
+ // Save progress
+ $this->installer_config->set('file_updater_type_progress', $type);
+ $this->installer_config->set('file_updater_elem_progress', $path);
+ $progress_count++;
+ $this->iohandler->set_progress('UPDATE_UPDATING_FILES', $progress_count);
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ // Request refresh
+ throw new resource_limit_reached_exception();
+ }
+ }
+ }
+
+ $this->iohandler->finish_progress('UPDATE_UPDATING_FILES');
+ }
+ catch (runtime_exception $e)
+ {
+ if ($e instanceof resource_limit_reached_exception)
+ {
+ throw new resource_limit_reached_exception();
+ }
+
+ $current_method = $this->installer_config->get('file_update_method', '');
+
+ // File updater failed, try to fallback to download file update mode
+ if ($current_method !== 'compression')
+ {
+ $this->iohandler->add_warning_message(array(
+ 'UPDATE_FILE_UPDATER_HAS_FAILED',
+ $current_method,
+ 'compression'
+ ));
+ $this->installer_config->set('file_update_method', 'compression');
+
+ // We only want a simple refresh here
+ throw new resource_limit_reached_exception();
+ }
+ else
+ {
+ // Nowhere to fallback to :(
+ // Due to the way the installer handles fatal errors, we need to throw a low level exception
+ throw new runtime_exception('UPDATE_FILE_UPDATERS_HAVE_FAILED');
+ }
+ }
+
+ $file_updater_method = $this->installer_config->get('file_update_method', '');
+ if ($file_updater_method === 'compression' || $file_updater_method === 'ftp')
+ {
+ $this->file_updater->close();
+ }
+ }
+
+ /**
+ * Get file updater
+ *
+ * @param null|string $file_updater_method Name of the file updater to use
+ *
+ * @return file_updater_interface File updater
+ */
+ protected function get_file_updater($file_updater_method = null)
+ {
+ $file_updater_method = ($file_updater_method === null) ? $this->installer_config->get('file_update_method', '') : $file_updater_method;
+
+ if ($file_updater_method === 'compression')
+ {
+ $compression_method = $this->installer_config->get('file_update_compression', '');
+
+ /** @var \phpbb\install\helper\file_updater\compression_file_updater $file_updater */
+ $file_updater = $this->factory->get('compression');
+ $archive_path = $file_updater->init($compression_method);
+ $this->installer_config->set('update_file_archive', $archive_path);
+ }
+ else if ($file_updater_method === 'ftp')
+ {
+ /** @var \phpbb\install\helper\file_updater\ftp_file_updater $file_updater */
+ $file_updater = $this->factory->get('ftp');
+ $file_updater->init(
+ $this->installer_config->get('ftp_method', ''),
+ $this->installer_config->get('ftp_host', ''),
+ $this->installer_config->get('ftp_user', ''),
+ $this->installer_config->get('ftp_pass', ''),
+ $this->installer_config->get('ftp_path', ''),
+ $this->installer_config->get('ftp_port', 0),
+ $this->installer_config->get('ftp_timeout', 10)
+ );
+ }
+ else
+ {
+ /** @var file_updater_interface $file_updater */
+ $file_updater = $this->factory->get('direct_file');
+ }
+
+ return $file_updater;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php
new file mode 100644
index 0000000000..93c10bd656
--- /dev/null
+++ b/phpBB/phpbb/install/module_base.php
@@ -0,0 +1,213 @@
+<?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;
+
+use phpbb\di\ordered_service_collection;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+
+/**
+ * Base class for installer module
+ */
+abstract class module_base implements module_interface
+{
+ /**
+ * @var config
+ */
+ protected $install_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var bool
+ */
+ protected $is_essential;
+
+ /**
+ * Array of tasks for installer module
+ *
+ * @var ordered_service_collection
+ */
+ protected $task_collection;
+
+ /**
+ * @var array
+ */
+ protected $task_step_count;
+
+ /**
+ * @var bool
+ */
+ protected $allow_progress_bar;
+
+ /**
+ * Installer module constructor
+ *
+ * @param ordered_service_collection $tasks array of installer tasks for installer module
+ * @param bool $essential flag indicating whether the module is essential or not
+ * @param bool $allow_progress_bar flag indicating whether or not to send progress information from within the module
+ */
+ public function __construct(ordered_service_collection $tasks, $essential = true, $allow_progress_bar = true)
+ {
+ $this->task_collection = $tasks;
+ $this->is_essential = $essential;
+ $this->allow_progress_bar = $allow_progress_bar;
+ }
+
+ /**
+ * Dependency getter
+ *
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ */
+ public function setup(config $config, iohandler_interface $iohandler)
+ {
+ $this->install_config = $config;
+ $this->iohandler = $iohandler;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_essential()
+ {
+ return $this->is_essential;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Overwrite this method if your task is non-essential!
+ */
+ public function check_requirements()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Recover install progress
+ $task_index = $this->recover_progress();
+ $iterator = $this->task_collection->getIterator();
+
+ if ($task_index < $iterator->count())
+ {
+ $iterator->seek($task_index);
+ }
+ else
+ {
+ $this->install_config->set_finished_task(0);
+ return;
+ }
+
+ while ($iterator->valid())
+ {
+ $task = $iterator->current();
+ $name = $iterator->key();
+
+ // Check if we can run the task
+ if (!$task->is_essential() && !$task->check_requirements())
+ {
+ $this->iohandler->add_log_message(array(
+ 'SKIP_TASK',
+ $name,
+ ));
+
+ $this->install_config->increment_current_task_progress($this->task_step_count[$name]);
+ }
+ else
+ {
+ // Send progress information
+ if ($this->allow_progress_bar)
+ {
+ $this->iohandler->set_progress(
+ $task->get_task_lang_name(),
+ $this->install_config->get_current_task_progress()
+ );
+
+ $this->iohandler->send_response();
+ }
+
+ $task->run();
+
+ if ($this->allow_progress_bar)
+ {
+ // Only increment progress by one, as if a task has more than one steps
+ // then that should be incremented in the task itself
+ $this->install_config->increment_current_task_progress();
+ }
+ }
+
+ $task_index++;
+ $this->install_config->set_finished_task($task_index);
+ $iterator->next();
+
+ // Send progress information
+ if ($this->allow_progress_bar)
+ {
+ $this->iohandler->set_progress(
+ $task->get_task_lang_name(),
+ $this->install_config->get_current_task_progress()
+ );
+ }
+
+ $this->iohandler->send_response();
+
+ // Stop execution if resource limit is reached
+ if ($iterator->valid() && ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0))
+ {
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ // Module finished, so clear task progress
+ $this->install_config->set_finished_task(0);
+ }
+
+ /**
+ * Returns the next task's name
+ *
+ * @return string Index of the array element of the next task
+ */
+ protected function recover_progress()
+ {
+ $progress_array = $this->install_config->get_progress_data();
+ return $progress_array['last_task_index'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ $task_step_count = 0;
+ $task_class_names = $this->task_collection->get_service_classes();
+
+ foreach ($task_class_names as $name => $task_class)
+ {
+ $step_count = $task_class::get_step_count();
+ $task_step_count += $step_count;
+ $this->task_step_count[$name] = $step_count;
+ }
+
+ return $task_step_count;
+ }
+}
diff --git a/phpBB/phpbb/install/module_interface.php b/phpBB/phpbb/install/module_interface.php
new file mode 100644
index 0000000000..a2d61e3958
--- /dev/null
+++ b/phpBB/phpbb/install/module_interface.php
@@ -0,0 +1,63 @@
+<?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;
+
+/**
+ * Interface for installer modules
+ *
+ * An installer module is a task collection which executes installer tasks.
+ */
+interface module_interface
+{
+ /**
+ * Checks if the execution of the module is essential to install phpBB or it can be skipped
+ *
+ * Note: Please note that all the non-essential modules have to implement check_requirements()
+ * method.
+ *
+ * @return bool true if the module is essential, false otherwise
+ */
+ public function is_essential();
+
+ /**
+ * Checks requirements for the tasks
+ *
+ * Note: Only need to be implemented for non-essential tasks, as essential tasks
+ * requirements should be checked in the requirements install module.
+ *
+ * @return bool true if the task's requirements are met
+ */
+ public function check_requirements();
+
+ /**
+ * Executes the task
+ *
+ * @return null
+ */
+ public function run();
+
+ /**
+ * Returns the number of tasks in the module
+ *
+ * @return int
+ */
+ public function get_step_count();
+
+ /**
+ * Returns an array to the correct navigation stage
+ *
+ * @return array
+ */
+ public function get_navigation_stage_path();
+}
diff --git a/phpBB/phpbb/install/task_base.php b/phpBB/phpbb/install/task_base.php
new file mode 100644
index 0000000000..b5199be4af
--- /dev/null
+++ b/phpBB/phpbb/install/task_base.php
@@ -0,0 +1,53 @@
+<?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;
+
+/**
+ * Base class for installer task
+ */
+abstract class task_base implements task_interface
+{
+ /**
+ * @var bool
+ */
+ protected $is_essential;
+
+ /**
+ * Constructor
+ *
+ * @param bool $essential
+ */
+ public function __construct($essential = true)
+ {
+ $this->is_essential = $essential;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_essential()
+ {
+ return $this->is_essential;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Note: Overwrite this method if your task is non-essential!
+ */
+ public function check_requirements()
+ {
+ return true;
+ }
+}
diff --git a/phpBB/phpbb/install/task_interface.php b/phpBB/phpbb/install/task_interface.php
new file mode 100644
index 0000000000..794cb16482
--- /dev/null
+++ b/phpBB/phpbb/install/task_interface.php
@@ -0,0 +1,61 @@
+<?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;
+
+/**
+ * Interface for installer tasks
+ */
+interface task_interface
+{
+ /**
+ * Returns the number of steps the task contains
+ *
+ * This is a helper method to provide a better progress bar for the front-end.
+ *
+ * @return int The number of steps that the task contains
+ */
+ static public function get_step_count();
+
+ /**
+ * Checks if the task is essential to install phpBB or it can be skipped
+ *
+ * Note: Please note that all the non-essential modules have to implement check_requirements()
+ * method.
+ *
+ * @return bool true if the task is essential, false otherwise
+ */
+ public function is_essential();
+
+ /**
+ * Checks requirements for the tasks
+ *
+ * Note: Only need to be implemented for non-essential tasks, as essential tasks
+ * requirements should be checked in the requirements install module.
+ *
+ * @return bool true if the task's requirements are met
+ */
+ public function check_requirements();
+
+ /**
+ * Executes the task
+ */
+ public function run();
+
+ /**
+ * Returns the language key of the name of the task
+ *
+ * @return string
+ */
+ public function get_task_lang_name();
+}
diff --git a/phpBB/phpbb/install/updater_configuration.php b/phpBB/phpbb/install/updater_configuration.php
new file mode 100644
index 0000000000..e992356290
--- /dev/null
+++ b/phpBB/phpbb/install/updater_configuration.php
@@ -0,0 +1,40 @@
+<?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;
+
+use Symfony\Component\Config\Definition\Builder\TreeBuilder;
+use Symfony\Component\Config\Definition\ConfigurationInterface;
+
+class updater_configuration implements ConfigurationInterface
+{
+
+ /**
+ * Generates the configuration tree builder.
+ *
+ * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
+ */
+ public function getConfigTreeBuilder()
+ {
+ $treeBuilder = new TreeBuilder();
+ $rootNode = $treeBuilder->root('updater');
+ $rootNode
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->enumNode('type')->values(['all','db_only'])->defaultValue('all')->end()
+ ->end()
+ ;
+
+ return $treeBuilder;
+ }
+}
diff --git a/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php b/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php
new file mode 100644
index 0000000000..94e3466208
--- /dev/null
+++ b/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php
@@ -0,0 +1,22 @@
+<?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\language\exception;
+
+/**
+ * Thrown when nonexistent plural rule is specified
+ */
+class invalid_plural_rule_exception extends language_exception
+{
+
+}
diff --git a/phpBB/phpbb/language/exception/language_exception.php b/phpBB/phpbb/language/exception/language_exception.php
new file mode 100644
index 0000000000..b1258414aa
--- /dev/null
+++ b/phpBB/phpbb/language/exception/language_exception.php
@@ -0,0 +1,22 @@
+<?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\language\exception;
+
+/**
+ * Base exception class for language exceptions
+ */
+class language_exception extends \phpbb\exception\runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/language/exception/language_file_not_found.php b/phpBB/phpbb/language/exception/language_file_not_found.php
new file mode 100644
index 0000000000..89364267eb
--- /dev/null
+++ b/phpBB/phpbb/language/exception/language_file_not_found.php
@@ -0,0 +1,22 @@
+<?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\language\exception;
+
+/**
+ * This exception is thrown when the language file is not found
+ */
+class language_file_not_found extends language_exception
+{
+
+}
diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php
new file mode 100644
index 0000000000..42429c2c07
--- /dev/null
+++ b/phpBB/phpbb/language/language.php
@@ -0,0 +1,673 @@
+<?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\language;
+
+use phpbb\language\exception\invalid_plural_rule_exception;
+
+/**
+ * Wrapper class for loading translations
+ */
+class language
+{
+ /**
+ * Global fallback language
+ *
+ * ISO code of the language to fallback to when the specified language entries
+ * cannot be found.
+ *
+ * @var string
+ */
+ const FALLBACK_LANGUAGE = 'en';
+
+ /**
+ * @var array List of common language files
+ */
+ protected $common_language_files;
+
+ /**
+ * @var bool
+ */
+ protected $common_language_files_loaded;
+
+ /**
+ * @var string ISO code of the default board language
+ */
+ protected $default_language;
+
+ /**
+ * @var string ISO code of the User's language
+ */
+ protected $user_language;
+
+ /**
+ * @var array Language fallback array (the order is important)
+ */
+ protected $language_fallback;
+
+ /**
+ * @var array Array of language variables
+ */
+ protected $lang;
+
+ /**
+ * @var array Loaded language sets
+ */
+ protected $loaded_language_sets;
+
+ /**
+ * @var \phpbb\language\language_file_loader Language file loader
+ */
+ protected $loader;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\language\language_file_loader $loader Language file loader
+ * @param array|null $common_modules Array of common language modules to load (optional)
+ */
+ public function __construct(language_file_loader $loader, $common_modules = null)
+ {
+ $this->loader = $loader;
+
+ // Set up default information
+ $this->user_language = false;
+ $this->default_language = false;
+ $this->lang = array();
+ $this->loaded_language_sets = array(
+ 'core' => array(),
+ 'ext' => array(),
+ );
+
+ // Common language files
+ if (is_array($common_modules))
+ {
+ $this->common_language_files = $common_modules;
+ }
+ else
+ {
+ $this->common_language_files = array(
+ 'common',
+ );
+ }
+
+ $this->common_language_files_loaded = false;
+
+ $this->language_fallback = array(self::FALLBACK_LANGUAGE);
+ }
+
+ /**
+ * Function to set user's language to display.
+ *
+ * @param string $user_lang_iso ISO code of the User's language
+ * @param bool $reload Whether or not to reload language files
+ */
+ public function set_user_language($user_lang_iso, $reload = false)
+ {
+ $this->user_language = $user_lang_iso;
+
+ $this->set_fallback_array($reload);
+ }
+
+ /**
+ * Function to set the board's default language to display.
+ *
+ * @param string $default_lang_iso ISO code of the board's default language
+ * @param bool $reload Whether or not to reload language files
+ */
+ public function set_default_language($default_lang_iso, $reload = false)
+ {
+ $this->default_language = $default_lang_iso;
+
+ $this->set_fallback_array($reload);
+ }
+
+ /**
+ * Returns language array
+ *
+ * Note: This function is needed for the BC purposes, until \phpbb\user::lang[] is
+ * not removed.
+ *
+ * @return array Array of loaded language strings
+ */
+ public function get_lang_array()
+ {
+ // Load common language files if they not loaded yet
+ if (!$this->common_language_files_loaded)
+ {
+ $this->load_common_language_files();
+ }
+
+ return $this->lang;
+ }
+
+ /**
+ * Add Language Items
+ *
+ * Examples:
+ * <code>
+ * $component = array('posting');
+ * $component = array('posting', 'viewtopic')
+ * $component = 'posting'
+ * </code>
+ *
+ * @param string|array $component The name of the language component to load
+ * @param string|null $extension_name Name of the extension to load component from, or null for core file
+ */
+ public function add_lang($component, $extension_name = null)
+ {
+ // Load common language files if they not loaded yet
+ // This needs to be here to correctly merge language arrays
+ if (!$this->common_language_files_loaded)
+ {
+ $this->load_common_language_files();
+ }
+
+ if (!is_array($component))
+ {
+ if (!is_null($extension_name))
+ {
+ $this->load_extension($extension_name, $component);
+ }
+ else
+ {
+ $this->load_core_file($component);
+ }
+ }
+ else
+ {
+ foreach ($component as $lang_file)
+ {
+ $this->add_lang($lang_file, $extension_name);
+ }
+ }
+ }
+
+ /**
+ * @param $key array|string The language key we want to know more about. Can be string or array.
+ *
+ * @return bool Returns whether the language key is set.
+ */
+ public function is_set($key)
+ {
+ // Load common language files if they not loaded yet
+ if (!$this->common_language_files_loaded)
+ {
+ $this->load_common_language_files();
+ }
+
+ if (is_array($key))
+ {
+ $lang = &$this->lang[array_shift($key)];
+
+ foreach ($key as $_key)
+ {
+ $lang = &$lang[$_key];
+ }
+ }
+ else
+ {
+ $lang = &$this->lang[$key];
+ }
+
+ return isset($lang);
+ }
+
+ /**
+ * Advanced language substitution
+ *
+ * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms.
+ * Params are the language key and the parameters to be substituted.
+ * This function/functionality is inspired by SHS` and Ashe.
+ *
+ * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp>
+ *
+ * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry:
+ * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry.
+ *
+ * @return string Return localized string or the language key if the translation is not available
+ */
+ public function lang()
+ {
+ $args = func_get_args();
+ $key = array_shift($args);
+
+ return $this->lang_array($key, $args);
+ }
+
+ /**
+ * Returns the raw value associated to a language key or the language key no translation is available.
+ * No parameter substitution is performed, can be a string or an array.
+ *
+ * @param string|array $key Language key
+ *
+ * @return array|string
+ */
+ public function lang_raw($key)
+ {
+ // Load common language files if they not loaded yet
+ if (!$this->common_language_files_loaded)
+ {
+ $this->load_common_language_files();
+ }
+
+ if (is_array($key))
+ {
+ $lang = &$this->lang[array_shift($key)];
+
+ foreach ($key as $_key)
+ {
+ $lang = &$lang[$_key];
+ }
+ }
+ else
+ {
+ $lang = &$this->lang[$key];
+ }
+
+ // Return if language string does not exist
+ if (!isset($lang) || (!is_string($lang) && !is_array($lang)))
+ {
+ return $key;
+ }
+
+ return $lang;
+ }
+
+ /**
+ * Act like lang() but takes a key and an array of parameters instead of using variadic
+ *
+ * @param string|array $key Language key
+ * @param array $args Parameters
+ *
+ * @return string
+ */
+ public function lang_array($key, $args = array())
+ {
+ $lang = $this->lang_raw($key);
+
+ if ($lang === $key)
+ {
+ return $key;
+ }
+
+ // If the language entry is a string, we simply mimic sprintf() behaviour
+ if (is_string($lang))
+ {
+ if (count($args) === 0)
+ {
+ return $lang;
+ }
+
+ // Replace key with language entry and simply pass along...
+ return vsprintf($lang, $args);
+ }
+ else if (sizeof($lang) == 0)
+ {
+ // If the language entry is an empty array, we just return the language key
+ return $key;
+ }
+
+ // It is an array... now handle different nullar/singular/plural forms
+ $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++)
+ {
+ if (is_int($args[$i]) || is_float($args[$i]))
+ {
+ if ($args[$i] == 0 && isset($lang[0]))
+ {
+ // We allow each translation using plural forms to specify a version for the case of 0 things,
+ // so that "0 users" may be displayed as "No users".
+ $key_found = 0;
+ break;
+ }
+ else
+ {
+ $use_plural_form = $this->get_plural_form($args[$i]);
+ if (isset($lang[$use_plural_form]))
+ {
+ // The key we should use exists, so we use it.
+ $key_found = $use_plural_form;
+ }
+ else
+ {
+ // If the key we need to use does not exist, we fall back to the previous one.
+ $numbers = array_keys($lang);
+
+ foreach ($numbers as $num)
+ {
+ if ($num > $use_plural_form)
+ {
+ break;
+ }
+
+ $key_found = $num;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form)
+ if ($key_found === false)
+ {
+ $numbers = array_keys($lang);
+ $key_found = end($numbers);
+ }
+
+ // Use the language string we determined and pass it to sprintf()
+ return vsprintf($lang[$key_found], $args);
+ }
+
+ /**
+ * Loads common language files
+ */
+ protected function load_common_language_files()
+ {
+ if (!$this->common_language_files_loaded)
+ {
+ foreach ($this->common_language_files as $lang_file)
+ {
+ $this->load_core_file($lang_file);
+ }
+
+ $this->common_language_files_loaded = true;
+ }
+ }
+
+ /**
+ * Determine which plural form we should use.
+ *
+ * For some languages this is not as simple as for English.
+ *
+ * @param int|float $number The number we want to get the plural case for. Float numbers are floored.
+ * @param int|bool $force_rule False to use the plural rule of the language package
+ * or an integer to force a certain plural rule
+ *
+ * @return int The plural-case we need to use for the number plural-rule combination
+ *
+ * @throws \phpbb\language\exception\invalid_plural_rule_exception When $force_rule has an invalid value
+ */
+ public function get_plural_form($number, $force_rule = false)
+ {
+ $number = (int) $number;
+ $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1);
+
+ if ($plural_rule > 15 || $plural_rule < 0)
+ {
+ throw new invalid_plural_rule_exception('INVALID_PLURAL_RULE', array(
+ 'plural_rule' => $plural_rule,
+ ));
+ }
+
+ /**
+ * The following plural rules are based on a list published by the Mozilla Developer Network
+ * https://developer.mozilla.org/en/Localization_and_Plurals
+ */
+ switch ($plural_rule)
+ {
+ case 0:
+ /**
+ * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao
+ * 1 - everything: 0, 1, 2, ...
+ */
+ return 1;
+
+ case 1:
+ /**
+ * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan)
+ * 1 - 1
+ * 2 - everything else: 0, 2, 3, ...
+ */
+ return ($number === 1) ? 1 : 2;
+
+ case 2:
+ /**
+ * Families: Romanic (French, Brazilian Portuguese)
+ * 1 - 0, 1
+ * 2 - everything else: 2, 3, ...
+ */
+ return (($number === 0) || ($number === 1)) ? 1 : 2;
+
+ case 3:
+ /**
+ * Families: Baltic (Latvian)
+ * 1 - 0
+ * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ...
+ * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ...
+ */
+ return ($number === 0) ? 1 : ((($number % 10 === 1) && ($number % 100 != 11)) ? 2 : 3);
+
+ case 4:
+ /**
+ * Families: Celtic (Scottish Gaelic)
+ * 1 - is 1 or 11: 1, 11
+ * 2 - is 2 or 12: 2, 12
+ * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19
+ * 4 - everything else: 0, 20, 21, ...
+ */
+ return ($number === 1 || $number === 11) ? 1 : (($number === 2 || $number === 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4));
+
+ case 5:
+ /**
+ * Families: Romanic (Romanian)
+ * 1 - 1
+ * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ...
+ * 3 - everything else: 20, 21, ...
+ */
+ return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3);
+
+ case 6:
+ /**
+ * Families: Baltic (Lithuanian)
+ * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ...
+ * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ...
+ * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ...
+ */
+ return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3);
+
+ case 7:
+ /**
+ * Families: Slavic (Croatian, Serbian, Russian, Ukrainian)
+ * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ...
+ * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ...
+ * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ...
+ */
+ return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3);
+
+ case 8:
+ /**
+ * Families: Slavic (Slovak, Czech)
+ * 1 - 1
+ * 2 - 2, 3, 4
+ * 3 - everything else: 0, 5, 6, 7, ...
+ */
+ return ($number === 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3);
+
+ case 9:
+ /**
+ * Families: Slavic (Polish)
+ * 1 - 1
+ * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ...
+ * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ...
+ */
+ return ($number === 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3);
+
+ case 10:
+ /**
+ * Families: Slavic (Slovenian, Sorbian)
+ * 1 - ends in 01: 1, 101, 201, ...
+ * 2 - ends in 02: 2, 102, 202, ...
+ * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ...
+ * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ...
+ */
+ return ($number % 100 === 1) ? 1 : (($number % 100 === 2) ? 2 : ((($number % 100 === 3) || ($number % 100 === 4)) ? 3 : 4));
+
+ case 11:
+ /**
+ * Families: Celtic (Irish Gaeilge)
+ * 1 - 1
+ * 2 - 2
+ * 3 - is 3-6: 3, 4, 5, 6
+ * 4 - is 7-10: 7, 8, 9, 10
+ * 5 - everything else: 0, 11, 12, ...
+ */
+ return ($number === 1) ? 1 : (($number === 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5)));
+
+ case 12:
+ /**
+ * Families: Semitic (Arabic)
+ * 1 - 1
+ * 2 - 2
+ * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ...
+ * 4 - ends in 11-99: 11, ... 99, 111, 112, ...
+ * 5 - everything else: 100, 101, 102, 200, 201, 202, ...
+ * 6 - 0
+ */
+ return ($number === 1) ? 1 : (($number === 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6))));
+
+ case 13:
+ /**
+ * Families: Semitic (Maltese)
+ * 1 - 1
+ * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ...
+ * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ...
+ * 4 - everything else: 20, 21, ...
+ */
+ return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4));
+
+ case 14:
+ /**
+ * Families: Slavic (Macedonian)
+ * 1 - ends in 1: 1, 11, 21, ...
+ * 2 - ends in 2: 2, 12, 22, ...
+ * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ...
+ */
+ return ($number % 10 === 1) ? 1 : (($number % 10 === 2) ? 2 : 3);
+
+ case 15:
+ /**
+ * Families: Icelandic
+ * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ...
+ * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ...
+ */
+ return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : 2;
+ }
+ }
+
+ /**
+ * Returns the ISO code of the used language
+ *
+ * @return string The ISO code of the currently used language
+ */
+ public function get_used_language()
+ {
+ return $this->language_fallback[0];
+ }
+
+ /**
+ * Returns language fallback data
+ *
+ * @param bool $reload Whether or not to reload language files
+ *
+ * @return array
+ */
+ protected function set_fallback_array($reload = false)
+ {
+ $fallback_array = array();
+
+ if ($this->user_language)
+ {
+ $fallback_array[] = $this->user_language;
+ }
+
+ if ($this->default_language)
+ {
+ $fallback_array[] = $this->default_language;
+ }
+
+ $fallback_array[] = self::FALLBACK_LANGUAGE;
+
+ $this->language_fallback = $fallback_array;
+
+ if ($reload)
+ {
+ $this->reload_language_files();
+ }
+ }
+
+ /**
+ * Load core language file
+ *
+ * @param string $component Name of the component to load
+ */
+ protected function load_core_file($component)
+ {
+ // Check if the component is already loaded
+ if (isset($this->loaded_language_sets['core'][$component]))
+ {
+ return;
+ }
+
+ $this->loader->load($component, $this->language_fallback, $this->lang);
+ $this->loaded_language_sets['core'][$component] = true;
+ }
+
+ /**
+ * Load extension language file
+ *
+ * @param string $extension_name Name of the extension to load language from
+ * @param string $component Name of the component to load
+ */
+ protected function load_extension($extension_name, $component)
+ {
+ // Check if the component is already loaded
+ if (isset($this->loaded_language_sets['ext'][$extension_name][$component]))
+ {
+ return;
+ }
+
+ $this->loader->load_extension($extension_name, $component, $this->language_fallback, $this->lang);
+ $this->loaded_language_sets['ext'][$extension_name][$component] = true;
+ }
+
+ /**
+ * Reload language files
+ */
+ protected function reload_language_files()
+ {
+ $loaded_files = $this->loaded_language_sets;
+ $this->loaded_language_sets = array(
+ 'core' => array(),
+ 'ext' => array(),
+ );
+
+ // Reload core files
+ foreach ($loaded_files['core'] as $component => $value)
+ {
+ $this->load_core_file($component);
+ }
+
+ // Reload extension files
+ foreach ($loaded_files['ext'] as $ext_name => $ext_info)
+ {
+ foreach ($ext_info as $ext_component => $value)
+ {
+ $this->load_extension($ext_name, $ext_component);
+ }
+ }
+ }
+}
diff --git a/phpBB/phpbb/language/language_file_helper.php b/phpBB/phpbb/language/language_file_helper.php
new file mode 100644
index 0000000000..85de034fb8
--- /dev/null
+++ b/phpBB/phpbb/language/language_file_helper.php
@@ -0,0 +1,72 @@
+<?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\language;
+
+use Symfony\Component\Finder\Finder;
+
+/**
+ * Helper class for language file related functions
+ */
+class language_file_helper
+{
+ /**
+ * @var string Path to phpBB's root
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param string $phpbb_root_path Path to phpBB's root
+ */
+ public function __construct($phpbb_root_path)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Returns available languages
+ *
+ * @return array
+ */
+ public function get_available_languages()
+ {
+ // Find available language packages
+ $finder = new Finder();
+ $finder->files()
+ ->name('iso.txt')
+ ->depth('== 1')
+ ->followLinks()
+ ->in($this->phpbb_root_path . 'language');
+
+ $available_languages = array();
+ foreach ($finder as $file)
+ {
+ $path = $file->getRelativePath();
+ $info = explode("\n", $file->getContents());
+
+ $available_languages[] = array(
+ // Get the name of the directory containing iso.txt
+ 'iso' => $path,
+
+ // Recover data from file
+ 'name' => trim($info[0]),
+ 'local_name' => trim($info[1]),
+ 'author' => trim($info[2])
+ );
+ }
+
+ return $available_languages;
+ }
+}
diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php
new file mode 100644
index 0000000000..359202fd63
--- /dev/null
+++ b/phpBB/phpbb/language/language_file_loader.php
@@ -0,0 +1,206 @@
+<?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\language;
+
+use \phpbb\language\exception\language_file_not_found;
+
+/**
+ * Language file loader
+ */
+class language_file_loader
+{
+ /**
+ * @var string Path to phpBB's root
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string Extension of PHP files
+ */
+ protected $php_ext;
+
+ /**
+ * @var \phpbb\extension\manager Extension manager
+ */
+ protected $extension_manager;
+
+ /**
+ * Constructor
+ *
+ * @param string $phpbb_root_path Path to phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct($phpbb_root_path, $php_ext)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $this->extension_manager = null;
+ }
+
+ /**
+ * Extension manager setter
+ *
+ * @param \phpbb\extension\manager $extension_manager Extension manager
+ */
+ public function set_extension_manager(\phpbb\extension\manager $extension_manager)
+ {
+ $this->extension_manager = $extension_manager;
+ }
+
+ /**
+ * Loads language array for the given component
+ *
+ * @param string $component Name of the language component
+ * @param string|array $locale ISO code of the language to load, or array of ISO codes if you want to
+ * specify additional language fallback steps
+ * @param array $lang Array reference containing language strings
+ */
+ public function load($component, $locale, &$lang)
+ {
+ $locale = (array) $locale;
+
+ // Determine path to language directory
+ $path = $this->phpbb_root_path . 'language/';
+
+ $this->load_file($path, $component, $locale, $lang);
+ }
+
+ /**
+ * Loads language array for the given extension component
+ *
+ * @param string $extension Name of the extension
+ * @param string $component Name of the language component
+ * @param string|array $locale ISO code of the language to load, or array of ISO codes if you want to
+ * specify additional language fallback steps
+ * @param array $lang Array reference containing language strings
+ */
+ public function load_extension($extension, $component, $locale, &$lang)
+ {
+ // Check if extension manager was loaded
+ if ($this->extension_manager === null)
+ {
+ // If not, let's return
+ return;
+ }
+
+ $locale = (array) $locale;
+
+ // Determine path to language directory
+ $path = $this->extension_manager->get_extension_path($extension, true) . 'language/';
+
+ $this->load_file($path, $component, $locale, $lang);
+ }
+
+ /**
+ * Prepares language file loading
+ *
+ * @param string $path Path to search for file in
+ * @param string $component Name of the language component
+ * @param array $locale Array containing language fallback options
+ * @param array $lang Array reference of language strings
+ */
+ protected function load_file($path, $component, $locale, &$lang)
+ {
+ // This is BC stuff and not the best idea as it makes language fallback
+ // implementation quite hard like below.
+ if (strpos($this->phpbb_root_path . $component, $path) === 0)
+ {
+ // Filter out the path
+ $path_diff = str_replace($path, '', dirname($this->phpbb_root_path . $component));
+ $language_file = basename($component, '.' . $this->php_ext);
+ $component = '';
+
+ // This step is needed to resolve language/en/subdir style $component
+ // $path already points to the language base directory so we need to eliminate
+ // the first directory from the path (that should be the language directory)
+ $path_diff_parts = explode('/', $path_diff);
+
+ if (sizeof($path_diff_parts) > 1)
+ {
+ array_shift($path_diff_parts);
+ $component = implode('/', $path_diff_parts) . '/';
+ }
+
+ $component .= $language_file;
+ }
+
+ // Determine filename
+ $filename = $component . '.' . $this->php_ext;
+
+ // Determine path to file
+ $file_path = $this->get_language_file_path($path, $filename, $locale);
+
+ // Load language array
+ $this->load_language_file($file_path, $lang);
+ }
+
+ /**
+ * This function implements language fallback logic
+ *
+ * @param string $path Path to language directory
+ * @param string $filename Filename to load language strings from
+ *
+ * @return string Relative path to language file
+ *
+ * @throws language_file_not_found When the path to the file cannot be resolved
+ */
+ protected function get_language_file_path($path, $filename, $locales)
+ {
+ $language_file_path = $filename;
+
+ // Language fallback logic
+ foreach ($locales as $locale)
+ {
+ $language_file_path = $path . $locale . '/' . $filename;
+
+ // If we are in install, try to use the updated version, when available
+ if (defined('IN_INSTALL'))
+ {
+ $install_language_path = str_replace('language/', 'install/update/new/language/', $language_file_path);
+ if (file_exists($install_language_path))
+ {
+ return $install_language_path;
+ }
+ }
+
+ if (file_exists($language_file_path))
+ {
+ return $language_file_path;
+ }
+ }
+
+ // The language file is not exist
+ throw new language_file_not_found('Language file ' . $language_file_path . ' couldn\'t be opened.');
+ }
+
+ /**
+ * Loads language file
+ *
+ * @param string $path Path to language file to load
+ * @param array $lang Reference of the array of language strings
+ */
+ protected function load_language_file($path, &$lang)
+ {
+ // Do not suppress error if in DEBUG mode
+ if (defined('DEBUG'))
+ {
+ include $path;
+ }
+ else
+ {
+ @include $path;
+ }
+ }
+}
diff --git a/phpBB/phpbb/log/dummy.php b/phpBB/phpbb/log/dummy.php
new file mode 100644
index 0000000000..5c2d145e15
--- /dev/null
+++ b/phpBB/phpbb/log/dummy.php
@@ -0,0 +1,81 @@
+<?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\log;
+
+/**
+* Dummy logger
+*/
+class dummy implements log_interface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function is_enabled($type = '')
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable($type = '')
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable($type = '')
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array())
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($mode, $conditions = array())
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '')
+ {
+ return array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_log_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_valid_offset()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php
index 094ff78abe..2e20eebaac 100644
--- a/phpBB/phpbb/log/log.php
+++ b/phpBB/phpbb/log/log.php
@@ -27,7 +27,7 @@ class log implements \phpbb\log\log_interface
/**
* An array with the disabled log types. Logs of such types will not be
- * added when add_log() is called.
+ * added when add() is called.
* @var array
*/
protected $disabled_types;
@@ -223,7 +223,7 @@ class log implements \phpbb\log\log_interface
return false;
}
- if ($log_time == false)
+ if ($log_time === false)
{
$log_time = time();
}
@@ -249,10 +249,13 @@ class log implements \phpbb\log\log_interface
unset($additional_data['forum_id']);
$topic_id = isset($additional_data['topic_id']) ? (int) $additional_data['topic_id'] : 0;
unset($additional_data['topic_id']);
+ $post_id = isset($additional_data['post_id']) ? (int) $additional_data['post_id'] : 0;
+ unset($additional_data['post_id']);
$sql_ary += array(
'log_type' => LOG_MOD,
'forum_id' => $forum_id,
'topic_id' => $topic_id,
+ 'post_id' => $post_id,
'log_data' => (!empty($additional_data)) ? serialize($additional_data) : '',
);
break;
@@ -643,6 +646,7 @@ class log implements \phpbb\log\log_interface
'time' => (int) $row['log_time'],
'forum_id' => (int) $row['forum_id'],
'topic_id' => (int) $row['topic_id'],
+ 'post_id' => (int) $row['post_id'],
'viewforum' => ($row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false,
'action' => (isset($this->user->lang[$row['log_operation']])) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}',
@@ -743,6 +747,7 @@ class log implements \phpbb\log\log_interface
foreach ($log as $key => $row)
{
$log[$key]['viewtopic'] = (isset($topic_auth['f_read'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&amp;t=' . $row['topic_id']) : false;
+ $log[$key]['viewpost'] = (isset($topic_auth['f_read'][$row['topic_id']]) && $row['post_id']) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&amp;t=' . $row['topic_id'] . '&amp;p=' . $row['post_id']) : false;
$log[$key]['viewlogs'] = (isset($topic_auth['m_'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}mcp.{$this->php_ext}", 'i=logs&amp;mode=topic_logs&amp;t=' . $row['topic_id'], true, $this->user->session_id) : false;
}
}
diff --git a/phpBB/phpbb/log/log_interface.php b/phpBB/phpbb/log/log_interface.php
index 5932f722aa..86286e6f88 100644
--- a/phpBB/phpbb/log/log_interface.php
+++ b/phpBB/phpbb/log/log_interface.php
@@ -32,8 +32,8 @@ interface log_interface
* Disable log
*
* This function allows disabling the log system or parts of it, for this
- * page call. When add_log is called and the type is disabled,
- * the log will not be added to the database.
+ * page call. When add() is called and the type is disabled, the log will
+ * not be added to the database.
*
* @param mixed $type The log type we want to disable. Empty to
* disable all logs. Can also be an array of types.
@@ -57,12 +57,12 @@ interface log_interface
/**
* Adds a log entry to the database
*
- * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
- * @param int $user_id User ID of the user
- * @param string $log_ip IP address of the user
- * @param string $log_operation Name of the operation
- * @param int $log_time Timestamp when the log entry was added, if empty time() will be used
- * @param array $additional_data More arguments can be added, depending on the log_type
+ * @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
+ * @param int $user_id User ID of the user
+ * @param string $log_ip IP address of the user
+ * @param string $log_operation Name of the operation
+ * @param int|bool $log_time Timestamp when the log entry was added. If false, time() will be used
+ * @param array $additional_data More arguments can be added, depending on the log_type
*
* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise.
*/
diff --git a/phpBB/phpbb/log/null.php b/phpBB/phpbb/log/null.php
deleted file mode 100644
index baa78895ea..0000000000
--- a/phpBB/phpbb/log/null.php
+++ /dev/null
@@ -1,81 +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\log;
-
-/**
-* Null logger
-*/
-class null implements log_interface
-{
- /**
- * {@inheritdoc}
- */
- public function is_enabled($type = '')
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function disable($type = '')
- {
- }
-
- /**
- * {@inheritdoc}
- */
- public function enable($type = '')
- {
- }
-
- /**
- * {@inheritdoc}
- */
- public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array())
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function delete($mode, $conditions = array())
- {
- }
-
- /**
- * {@inheritdoc}
- */
- public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '')
- {
- return array();
- }
-
- /**
- * {@inheritdoc}
- */
- public function get_log_count()
- {
- return 0;
- }
-
- /**
- * {@inheritdoc}
- */
- public function get_valid_offset()
- {
- return 0;
- }
-}
diff --git a/phpBB/phpbb/message/topic_form.php b/phpBB/phpbb/message/topic_form.php
index 174643bb81..dbb883c142 100644
--- a/phpBB/phpbb/message/topic_form.php
+++ b/phpBB/phpbb/message/topic_form.php
@@ -71,6 +71,14 @@ class topic_form extends form
if (!$this->auth->acl_get('f_read', $this->topic_row['forum_id']))
{
+ if ($this->user->data['user_id'] != ANONYMOUS)
+ {
+ send_status_line(403, 'Forbidden');
+ }
+ else
+ {
+ send_status_line(401, 'Unauthorized');
+ }
return 'SORRY_AUTH_READ';
}
diff --git a/phpBB/phpbb/module/exception/module_exception.php b/phpBB/phpbb/module/exception/module_exception.php
new file mode 100644
index 0000000000..8ad75112bc
--- /dev/null
+++ b/phpBB/phpbb/module/exception/module_exception.php
@@ -0,0 +1,19 @@
+<?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\module\exception;
+
+class module_exception extends \phpbb\exception\runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/module/exception/module_not_found_exception.php b/phpBB/phpbb/module/exception/module_not_found_exception.php
new file mode 100644
index 0000000000..2d485e7b35
--- /dev/null
+++ b/phpBB/phpbb/module/exception/module_not_found_exception.php
@@ -0,0 +1,19 @@
+<?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\module\exception;
+
+class module_not_found_exception extends module_exception
+{
+
+}
diff --git a/phpBB/phpbb/module/module_manager.php b/phpBB/phpbb/module/module_manager.php
new file mode 100644
index 0000000000..7ae16cdb61
--- /dev/null
+++ b/phpBB/phpbb/module/module_manager.php
@@ -0,0 +1,564 @@
+<?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\module;
+
+use phpbb\module\exception\module_exception;
+use phpbb\module\exception\module_not_found_exception;
+
+class module_manager
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\extension\manager
+ */
+ protected $extension_manager;
+
+ /**
+ * @var string
+ */
+ protected $modules_table;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\cache\driver\driver_interface $cache Cache driver
+ * @param \phpbb\db\driver\driver_interface $db Database driver
+ * @param \phpbb\extension\manager $ext_manager Extension manager
+ * @param string $modules_table Module database table's name
+ * @param string $phpbb_root_path Path to phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct(\phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\extension\manager $ext_manager, $modules_table, $phpbb_root_path, $php_ext)
+ {
+ $this->cache = $cache;
+ $this->db = $db;
+ $this->extension_manager = $ext_manager;
+ $this->modules_table = $modules_table;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Get row for specified module
+ *
+ * @param int $module_id ID of the module
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ *
+ * @return array Array of data fetched from the database
+ *
+ * @throws \phpbb\module\exception\module_not_found_exception When there is no module with $module_id
+ */
+ public function get_module_row($module_id, $module_class)
+ {
+ $module_id = (int) $module_id;
+
+ $sql = 'SELECT *
+ FROM ' . $this->modules_table . "
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND module_id = $module_id";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ throw new module_not_found_exception('NO_MODULE');
+ }
+
+ return $row;
+ }
+
+ /**
+ * Get available module information from module files
+ *
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ * @param string $module ID of module
+ * @param bool $use_all_available Use all available instead of just all
+ * enabled extensions
+ *
+ * @return array Array with module information gathered from module info files.
+ */
+ public function get_module_infos($module_class, $module = '', $use_all_available = false)
+ {
+ $directory = $this->phpbb_root_path . 'includes/' . $module_class . '/info/';
+ $fileinfo = array();
+
+ $finder = $this->extension_manager->get_finder($use_all_available);
+
+ $modules = $finder
+ ->extension_suffix('_module')
+ ->extension_directory("/$module_class")
+ ->core_path("includes/$module_class/info/")
+ ->core_prefix($module_class . '_')
+ ->get_classes(true);
+
+ foreach ($modules as $cur_module)
+ {
+ // Skip entries we do not need if we know the module we are
+ // looking for
+ if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module)
+ {
+ continue;
+ }
+
+ $info_class = preg_replace('/_module$/', '_info', $cur_module);
+
+ // If the class does not exist it might be following the old
+ // format. phpbb_acp_info_acp_foo needs to be turned into
+ // acp_foo_info and the respective file has to be included
+ // manually because it does not support auto loading
+ $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module);
+ $old_info_class = $old_info_class_file . '_info';
+
+ if (class_exists($old_info_class))
+ {
+ $info_class = $old_info_class;
+ }
+ else if (!class_exists($info_class))
+ {
+ $info_class = $old_info_class;
+
+ // need to check class exists again because previous checks triggered autoloading
+ if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $this->php_ext))
+ {
+ include($directory . $old_info_class_file . '.' . $this->php_ext);
+ }
+ }
+
+ if (class_exists($info_class))
+ {
+ $info = new $info_class();
+ $module_info = $info->module();
+
+ $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module;
+
+ $fileinfo[$main_class] = $module_info;
+ }
+ }
+
+ ksort($fileinfo);
+
+ return $fileinfo;
+ }
+
+ /**
+ * Get module branch
+ *
+ * @param int $module_id ID of the module
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ * @param string $type Type of branch (Expected values: all, parents or children)
+ * @param bool $include_module Whether or not to include the specified module with $module_id
+ *
+ * @return array Returns an array containing the modules in the specified branch type.
+ */
+ public function get_module_branch($module_id, $module_class, $type = 'all', $include_module = true)
+ {
+ $module_id = (int) $module_id;
+
+ switch ($type)
+ {
+ case 'parents':
+ $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id';
+ break;
+
+ case 'children':
+ $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id';
+ break;
+
+ default:
+ $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id';
+ break;
+ }
+
+ $rows = array();
+
+ $sql = 'SELECT m2.*
+ FROM ' . $this->modules_table . ' m1
+ LEFT JOIN ' . $this->modules_table . " m2 ON ($condition)
+ WHERE m1.module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND m2.module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND m1.module_id = $module_id
+ ORDER BY m2.left_id DESC";
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!$include_module && $row['module_id'] == $module_id)
+ {
+ continue;
+ }
+
+ $rows[] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ /**
+ * Remove modules cache file
+ *
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ */
+ public function remove_cache_file($module_class)
+ {
+ // Sanitise for future path use, it's escaped as appropriate for queries
+ $cache_class = str_replace(array('.', '/', '\\'), '', basename($module_class));
+ $this->cache->destroy('_modules_' . $cache_class);
+ $this->cache->destroy('sql', $this->modules_table);
+ }
+
+ /**
+ * Update/Add module
+ *
+ * @param array &$module_data The module data
+ *
+ * @throws \phpbb\module\exception\module_not_found_exception When parent module or the category is not exist
+ */
+ public function update_module_data(&$module_data)
+ {
+ if (!isset($module_data['module_id']))
+ {
+ // no module_id means we're creating a new category/module
+ if ($module_data['parent_id'])
+ {
+ $sql = 'SELECT left_id, right_id
+ FROM ' . $this->modules_table . "
+ WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
+ AND module_id = " . (int) $module_data['parent_id'];
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ throw new module_not_found_exception('PARENT_NOT_EXIST');
+ }
+
+ // Workaround
+ $row['left_id'] = (int) $row['left_id'];
+ $row['right_id'] = (int) $row['right_id'];
+
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET left_id = left_id + 2, right_id = right_id + 2
+ WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
+ AND left_id > {$row['right_id']}";
+ $this->db->sql_query($sql);
+
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET right_id = right_id + 2
+ WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
+ AND {$row['left_id']} BETWEEN left_id AND right_id";
+ $this->db->sql_query($sql);
+
+ $module_data['left_id'] = (int) $row['right_id'];
+ $module_data['right_id'] = (int) $row['right_id'] + 1;
+ }
+ else
+ {
+ $sql = 'SELECT MAX(right_id) AS right_id
+ FROM ' . $this->modules_table . "
+ WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $module_data['left_id'] = (int) $row['right_id'] + 1;
+ $module_data['right_id'] = (int) $row['right_id'] + 2;
+ }
+
+ $sql = 'INSERT INTO ' . $this->modules_table . ' ' . $this->db->sql_build_array('INSERT', $module_data);
+ $this->db->sql_query($sql);
+
+ $module_data['module_id'] = $this->db->sql_nextid();
+ }
+ else
+ {
+ $row = $this->get_module_row($module_data['module_id'], $module_data['module_class']);
+
+ if ($module_data['module_basename'] && !$row['module_basename'])
+ {
+ // 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))
+ {
+ throw new module_not_found_exception('NO_CATEGORY_TO_MODULE');
+ }
+ }
+
+ if ($row['parent_id'] != $module_data['parent_id'])
+ {
+ $this->move_module($module_data['module_id'], $module_data['parent_id'], $module_data['module_class']);
+ }
+
+ $update_ary = $module_data;
+ unset($update_ary['module_id']);
+
+ $sql = 'UPDATE ' . $this->modules_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $update_ary) . "
+ WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
+ AND module_id = " . (int) $module_data['module_id'];
+ $this->db->sql_query($sql);
+ }
+ }
+
+ /**
+ * Move module around the tree
+ *
+ * @param int $from_module_id ID of the current parent module
+ * @param int $to_parent_id ID of the target parent module
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ *
+ * @throws \phpbb\module\exception\module_not_found_exception If the module specified to move modules from does not
+ * have any children.
+ */
+ public function move_module($from_module_id, $to_parent_id, $module_class)
+ {
+ $moved_modules = $this->get_module_branch($from_module_id, $module_class, 'children');
+
+ if (empty($moved_modules))
+ {
+ throw new module_not_found_exception();
+ }
+
+ $from_data = $moved_modules[0];
+ $diff = sizeof($moved_modules) * 2;
+
+ $moved_ids = array();
+ for ($i = 0, $size = sizeof($moved_modules); $i < $size; ++$i)
+ {
+ $moved_ids[] = $moved_modules[$i]['module_id'];
+ }
+
+ // Resync parents
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET right_id = right_id - $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND left_id < " . (int) $from_data['right_id'] . '
+ AND right_id > ' . (int) $from_data['right_id'];
+ $this->db->sql_query($sql);
+
+ // Resync righthand side of tree
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET left_id = left_id - $diff, right_id = right_id - $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND left_id > " . (int) $from_data['right_id'];
+ $this->db->sql_query($sql);
+
+ if ($to_parent_id > 0)
+ {
+ $to_data = $this->get_module_row($to_parent_id, $module_class);
+
+ // Resync new parents
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET right_id = right_id + $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id
+ AND ' . $this->db->sql_in_set('module_id', $moved_ids, true);
+ $this->db->sql_query($sql);
+
+ // Resync the righthand side of the tree
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET left_id = left_id + $diff, right_id = right_id + $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND left_id > " . (int) $to_data['right_id'] . '
+ AND ' . $this->db->sql_in_set('module_id', $moved_ids, true);
+ $this->db->sql_query($sql);
+
+ // Resync moved branch
+ $to_data['right_id'] += $diff;
+ if ($to_data['right_id'] > $from_data['right_id'])
+ {
+ $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1);
+ }
+ else
+ {
+ $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1);
+ }
+ }
+ else
+ {
+ $sql = 'SELECT MAX(right_id) AS right_id
+ FROM ' . $this->modules_table . "
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND " . $this->db->sql_in_set('module_id', $moved_ids, true);
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1);
+ }
+
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET left_id = left_id $diff, right_id = right_id $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND " . $this->db->sql_in_set('module_id', $moved_ids);
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Remove module from tree
+ *
+ * @param int $module_id ID of the module to delete
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ *
+ * @throws \phpbb\module\exception\module_exception When the specified module cannot be removed
+ */
+ public function delete_module($module_id, $module_class)
+ {
+ $module_id = (int) $module_id;
+
+ $row = $this->get_module_row($module_id, $module_class);
+
+ $branch = $this->get_module_branch($module_id, $module_class, 'children', false);
+
+ if (sizeof($branch))
+ {
+ throw new module_exception('CANNOT_REMOVE_MODULE');
+ }
+
+ // If not move
+ $diff = 2;
+ $sql = 'DELETE FROM ' . $this->modules_table . "
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND module_id = $module_id";
+ $this->db->sql_query($sql);
+
+ $row['right_id'] = (int) $row['right_id'];
+ $row['left_id'] = (int) $row['left_id'];
+
+ // Resync tree
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET right_id = right_id - $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}";
+ $this->db->sql_query($sql);
+
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET left_id = left_id - $diff, right_id = right_id - $diff
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND left_id > {$row['right_id']}";
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * Move module position by $steps up/down
+ *
+ * @param array $module_row Array of module data
+ * @param string $module_class Class of the module (acp, ucp, mcp etc...)
+ * @param string $action Direction of moving (valid values: move_up or move_down)
+ * @param int $steps Number of steps to move module
+ *
+ * @return string Returns the language name of the module
+ *
+ * @throws \phpbb\module\exception\module_not_found_exception When the specified module does not exists
+ */
+ public function move_module_by($module_row, $module_class, $action = 'move_up', $steps = 1)
+ {
+ /**
+ * Fetch all the siblings between the module's current spot
+ * and where we want to move it to. If there are less than $steps
+ * siblings between the current spot and the target then the
+ * module will move as far as possible
+ */
+ $sql = 'SELECT module_id, left_id, right_id, module_langname
+ FROM ' . $this->modules_table . "
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND parent_id = " . (int) $module_row['parent_id'] . '
+ AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC');
+ $result = $this->db->sql_query_limit($sql, $steps);
+
+ $target = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $target = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ if (!sizeof($target))
+ {
+ // The module is already on top or bottom
+ throw new module_not_found_exception();
+ }
+
+ /**
+ * $left_id and $right_id define the scope of the nodes that are affected by the move.
+ * $diff_up and $diff_down are the values to substract or add to each node's left_id
+ * and right_id in order to move them up or down.
+ * $move_up_left and $move_up_right define the scope of the nodes that are moving
+ * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down.
+ */
+ if ($action == 'move_up')
+ {
+ $left_id = (int) $target['left_id'];
+ $right_id = (int) $module_row['right_id'];
+
+ $diff_up = (int) ($module_row['left_id'] - $target['left_id']);
+ $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
+
+ $move_up_left = (int) $module_row['left_id'];
+ $move_up_right = (int) $module_row['right_id'];
+ }
+ else
+ {
+ $left_id = (int) $module_row['left_id'];
+ $right_id = (int) $target['right_id'];
+
+ $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
+ $diff_down = (int) ($target['right_id'] - $module_row['right_id']);
+
+ $move_up_left = (int) ($module_row['right_id'] + 1);
+ $move_up_right = (int) $target['right_id'];
+ }
+
+ // Now do the dirty job
+ $sql = 'UPDATE ' . $this->modules_table . "
+ SET left_id = left_id + CASE
+ WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
+ ELSE {$diff_down}
+ END,
+ right_id = right_id + CASE
+ WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
+ ELSE {$diff_down}
+ END
+ WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
+ AND left_id BETWEEN {$left_id} AND {$right_id}
+ AND right_id BETWEEN {$left_id} AND {$right_id}";
+ $this->db->sql_query($sql);
+
+ $this->remove_cache_file($module_class);
+
+ return $target['module_langname'];
+ }
+}
diff --git a/phpBB/phpbb/notification/exception.php b/phpBB/phpbb/notification/exception.php
index 83c4526df7..e416438061 100644
--- a/phpBB/phpbb/notification/exception.php
+++ b/phpBB/phpbb/notification/exception.php
@@ -17,10 +17,6 @@ namespace phpbb\notification;
* Notifications exception
*/
-class exception extends \Exception
+class exception extends \phpbb\exception\runtime_exception
{
- public function __toString()
- {
- return $this->getMessage();
- }
}
diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php
index f5663f4b34..6923d96392 100644
--- a/phpBB/phpbb/notification/manager.php
+++ b/phpBB/phpbb/notification/manager.php
@@ -26,7 +26,7 @@ class manager
/** @var array */
protected $subscription_types;
- /** @var array */
+ /** @var method\method_interface[] */
protected $notification_methods;
/** @var ContainerInterface */
@@ -35,9 +35,6 @@ class manager
/** @var \phpbb\user_loader */
protected $user_loader;
- /** @var \phpbb\config\config */
- protected $config;
-
/** @var \phpbb\event\dispatcher_interface */
protected $phpbb_dispatcher;
@@ -47,22 +44,16 @@ class manager
/** @var \phpbb\cache\service */
protected $cache;
+ /** @var \phpbb\language\language */
+ protected $language;
+
/** @var \phpbb\user */
protected $user;
/** @var string */
- protected $phpbb_root_path;
-
- /** @var string */
- protected $php_ext;
-
- /** @var string */
protected $notification_types_table;
/** @var string */
- protected $notifications_table;
-
- /** @var string */
protected $user_notifications_table;
/**
@@ -72,43 +63,37 @@ class manager
* @param array $notification_methods
* @param ContainerInterface $phpbb_container
* @param \phpbb\user_loader $user_loader
- * @param \phpbb\config\config $config
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher
* @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\cache\service $cache
+ * @param \phpbb\language\language $language
* @param \phpbb\user $user
- * @param string $phpbb_root_path
- * @param string $php_ext
* @param string $notification_types_table
- * @param string $notifications_table
* @param string $user_notifications_table
*
* @return \phpbb\notification\manager
*/
- public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\language\language $language, \phpbb\user $user, $notification_types_table, $user_notifications_table)
{
$this->notification_types = $notification_types;
$this->notification_methods = $notification_methods;
$this->phpbb_container = $phpbb_container;
$this->user_loader = $user_loader;
- $this->config = $config;
$this->phpbb_dispatcher = $phpbb_dispatcher;
$this->db = $db;
$this->cache = $cache;
+ $this->language = $language;
$this->user = $user;
- $this->phpbb_root_path = $phpbb_root_path;
- $this->php_ext = $php_ext;
-
$this->notification_types_table = $notification_types_table;
- $this->notifications_table = $notifications_table;
$this->user_notifications_table = $user_notifications_table;
}
/**
- * Load the user's notifications
+ * Load the user's notifications for a given method
*
+ * @param string $method_name
* @param array $options Optional options to control what notifications are loaded
* notification_id Notification id to load (or array of notification ids)
* user_id User id to load notifications for (Default: $user->data['user_id'])
@@ -123,27 +108,21 @@ class manager
* 'notifications' array of notification type objects
* 'unread_count' number of unread notifications the user has if count_unread is true in the options
* 'total_count' number of notifications the user has if count_total is true in the options
+ * @throws \phpbb\notification\exception when the method doesn't refer to a class extending \phpbb\notification\method\method_interface
*/
- public function load_notifications(array $options = array())
+ public function load_notifications($method_name, array $options = array())
{
- // Merge default options
- $options = array_merge(array(
- 'notification_id' => false,
- 'user_id' => $this->user->data['user_id'],
- 'order_by' => 'notification_time',
- 'order_dir' => 'DESC',
- 'limit' => 0,
- 'start' => 0,
- 'all_unread' => false,
- 'count_unread' => false,
- 'count_total' => false,
- ), $options);
-
- // If all_unread, count_unread must be true
- $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread'];
+ $method = $this->get_method_class($method_name);
- // Anonymous users and bots never receive notifications
- if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE))
+ if (! $method instanceof \phpbb\notification\method\method_interface)
+ {
+ throw new \phpbb\notification\exception($this->language->lang('NOTIFICATION_METHOD_INVALID', $method_name));
+ }
+ else if ($method->is_available())
+ {
+ return $method->load_notifications($options);
+ }
+ else
{
return array(
'notifications' => array(),
@@ -151,172 +130,112 @@ class manager
'total_count' => 0,
);
}
+ }
- $notifications = $user_ids = array();
- $load_special = array();
- $total_count = $unread_count = 0;
+ /**
+ * Mark notifications read or unread for all available methods
+ *
+ * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
+ * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ *
+ * @deprecated since 3.2
+ */
+ public function mark_notifications_read($notification_type_name, $item_id, $user_id, $time = false)
+ {
+ $this->mark_notifications($notification_type_name, $item_id, $user_id, $time);
+ }
- if ($options['count_unread'])
+ /**
+ * Mark notifications read or unread for all available methods
+ *
+ * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
+ * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True)
+ */
+ public function mark_notifications($notification_type_name, $item_id, $user_id, $time = false, $mark_read = true)
+ {
+ if (is_array($notification_type_name))
{
- // Get the total number of unread notifications
- $sql = 'SELECT COUNT(n.notification_id) AS unread_count
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.user_id = ' . (int) $options['user_id'] . '
- AND n.notification_read = 0
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- $unread_count = (int) $this->db->sql_fetchfield('unread_count');
- $this->db->sql_freeresult($result);
+ $notification_type_id = $this->get_notification_type_ids($notification_type_name);
}
-
- if ($options['count_total'])
+ else if ($notification_type_name !== false)
{
- // Get the total number of notifications
- $sql = 'SELECT COUNT(n.notification_id) AS total_count
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.user_id = ' . (int) $options['user_id'] . '
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- $total_count = (int) $this->db->sql_fetchfield('total_count');
- $this->db->sql_freeresult($result);
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
}
-
- if (!$options['count_total'] || $total_count)
+ else
{
- $rowset = array();
- $selected_unread_count = 0;
-
- // Get the main notifications
- $sql = 'SELECT n.*, nt.notification_type_name
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.user_id = ' . (int) $options['user_id'] .
- (($options['notification_id']) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : '') . '
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1
- ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
- $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- $rowset[$row['notification_id']] = $row;
- $selected_unread_count += (int) !$row['notification_read'];
- }
- $this->db->sql_freeresult($result);
-
- // Get all unread notifications
- if ($selected_unread_count < $unread_count && $options['all_unread'] && !empty($rowset))
- {
- $sql = 'SELECT n.*, nt.notification_type_name
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.user_id = ' . (int) $options['user_id'] . '
- AND n.notification_read = 0
- AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . '
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1
- ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
- $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- $rowset[$row['notification_id']] = $row;
- }
- $this->db->sql_freeresult($result);
- }
-
- foreach ($rowset as $row)
- {
- $notification = $this->get_item_type_class($row['notification_type_name'], $row);
-
- // Array of user_ids to query all at once
- $user_ids = array_merge($user_ids, $notification->users_to_query());
-
- // Some notification types also require querying additional tables themselves
- if (!isset($load_special[$row['notification_type_name']]))
- {
- $load_special[$row['notification_type_name']] = array();
- }
- $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special());
-
- $notifications[$row['notification_id']] = $notification;
- }
-
- $this->user_loader->load_users($user_ids);
-
- // Allow each type to load its own special items
- foreach ($load_special as $item_type => $data)
- {
- $item_class = $this->get_item_type_class($item_type);
-
- $item_class->load_special($data, $notifications);
- }
+ $notification_type_id = false;
}
- return array(
- 'notifications' => $notifications,
- 'unread_count' => $unread_count,
- 'total_count' => $total_count,
- );
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $method->mark_notifications($notification_type_id, $item_id, $user_id, $time, $mark_read);
+ }
}
/**
- * Mark notifications read
- *
- * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
- * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
- * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
- * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
- */
- public function mark_notifications_read($notification_type_name, $item_id, $user_id, $time = false)
+ * Mark notifications read or unread from a parent identifier for all available methods
+ *
+ * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ *
+ * @deprecated since 3.2
+ */
+ public function mark_notifications_read_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false)
{
- $time = ($time !== false) ? $time : time();
-
- $sql = 'UPDATE ' . $this->notifications_table . "
- SET notification_read = 1
- WHERE notification_time <= " . (int) $time .
- (($notification_type_name !== false) ? ' AND ' . $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : '') .
- (($user_id !== false) ? ' AND ' . $this->db->sql_in_set('user_id', $user_id) : '') .
- (($item_id !== false) ? ' AND ' . $this->db->sql_in_set('item_id', $item_id) : '');
- $this->db->sql_query($sql);
+ $this->mark_notifications_by_parent($notification_type_name, $item_parent_id, $user_id, $time);
}
/**
- * Mark notifications read from a parent identifier
+ * Mark notifications read or unread from a parent identifier for all available methods
*
* @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
* @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True)
*/
- public function mark_notifications_read_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false)
+ public function mark_notifications_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false, $mark_read = true)
{
- $time = ($time !== false) ? $time : time();
-
- $sql = 'UPDATE ' . $this->notifications_table . "
- SET notification_read = 1
- WHERE notification_time <= " . (int) $time .
- (($notification_type_name !== false) ? ' AND ' . $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : '') .
- (($item_parent_id !== false) ? ' AND ' . $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : '') .
- (($user_id !== false) ? ' AND ' . $this->db->sql_in_set('user_id', $user_id) : '');
- $this->db->sql_query($sql);
+ if (is_array($notification_type_name))
+ {
+ $notification_type_id = $this->get_notification_type_ids($notification_type_name);
+ }
+ else
+ {
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
+ }
+
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $method->mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time, $mark_read);
+ }
}
/**
- * Mark notifications read
+ * Mark notifications read or unread for a given method
*
+ * @param string $method_name
* @param int|array $notification_id Notification id or array of notification ids.
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True)
*/
- public function mark_notifications_read_by_id($notification_id, $time = false)
+ public function mark_notifications_by_id($method_name, $notification_id, $time = false, $mark_read = true)
{
- $time = ($time !== false) ? $time : time();
+ $method = $this->get_method_class($method_name);
- $sql = 'UPDATE ' . $this->notifications_table . "
- SET notification_read = 1
- WHERE notification_time <= " . (int) $time . '
- AND ' . $this->db->sql_in_set('notification_id', $notification_id);
- $this->db->sql_query($sql);
+ if ($method instanceof \phpbb\notification\method\method_interface && $method->is_available())
+ {
+ $method->mark_notifications_by_id($notification_id, $time, $mark_read);
+ }
}
/**
@@ -350,8 +269,6 @@ class manager
return $notified_users;
}
- $item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
-
// find out which users want to receive this type of notification
$notify_users = $this->get_item_type_class($notification_type_name)->find_users_for_notification($data, $options);
@@ -404,25 +321,23 @@ class manager
$item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
$user_ids = array();
- $notification_objects = $notification_methods = array();
+ $notification_methods = array();
// Never send notifications to the anonymous user!
unset($notify_users[ANONYMOUS]);
// Make sure not to send new notifications to users who've already been notified about this item
// This may happen when an item was added, but now new users are able to see the item
- $sql = 'SELECT n.user_id
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.notification_type_id = ' . (int) $notification_type_id . '
- AND n.item_id = ' . (int) $item_id . '
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
+ // We remove each user which was already notified by at least one method.
+ /** @var method\method_interface $method */
+ foreach ($this->get_subscription_methods_instances() as $method)
{
- unset($notify_users[$row['user_id']]);
+ $notified_users = $method->get_notified_users($notification_type_id, array('item_id' => $item_id));
+ foreach ($notified_users as $user => $notifications)
+ {
+ unset($notify_users[$user]);
+ }
}
- $this->db->sql_freeresult($result);
if (!sizeof($notify_users))
{
@@ -434,8 +349,6 @@ class manager
$pre_create_data = $notification->pre_create_insert_array($data, $notify_users);
unset($notification);
- $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table);
-
// Go through each user so we can insert a row in the DB and then notify them by their desired means
foreach ($notify_users as $user => $methods)
{
@@ -443,8 +356,8 @@ class manager
$notification->user_id = (int) $user;
- // Insert notification row using buffer.
- $insert_buffer->insert($notification->create_insert_array($data, $pre_create_data));
+ // Generate the insert_array
+ $notification->create_insert_array($data, $pre_create_data);
// Users are needed to send notifications
$user_ids = array_merge($user_ids, $notification->users_to_query());
@@ -452,20 +365,15 @@ class manager
foreach ($methods as $method)
{
// setup the notification methods and add the notification to the queue
- if ($method) // blank means we just insert it as a notification, but do not notify them by any other means
+ if (!isset($notification_methods[$method]))
{
- if (!isset($notification_methods[$method]))
- {
- $notification_methods[$method] = $this->get_method_class($method);
- }
-
- $notification_methods[$method]->add_to_queue($notification);
+ $notification_methods[$method] = $this->get_method_class($method);
}
+
+ $notification_methods[$method]->add_to_queue($notification);
}
}
- $insert_buffer->flush();
-
// We need to load all of the users to send notifications
$this->user_loader->load_users($user_ids);
@@ -477,12 +385,13 @@ class manager
}
/**
- * Update a notification
+ * Update notification
*
* @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param array $data Data specific for this type that will be updated
+ * @param array $options
*/
- public function update_notifications($notification_type_name, $data)
+ public function update_notifications($notification_type_name, array $data, array $options = array())
{
if (is_array($notification_type_name))
{
@@ -494,27 +403,28 @@ class manager
return;
}
- $notification = $this->get_item_type_class($notification_type_name);
+ $this->update_notification($this->get_item_type_class($notification_type_name), $data, $options);
+ }
- // Allow the notifications class to over-ride the update_notifications functionality
- if (method_exists($notification, 'update_notifications'))
+ /**
+ * Update a notification
+ *
+ * @param \phpbb\notification\type\type_interface $notification The notification
+ * @param array $data Data specific for this type that will be updated
+ * @param array $options
+ */
+ public function update_notification(\phpbb\notification\type\type_interface $notification, array $data, array $options = array())
+ {
+ if (empty($options))
{
- // Return False to over-ride the rest of the update
- if ($notification->update_notifications($data) === false)
- {
- return;
- }
+ $options['item_id'] = $notification->get_item_id($data);
}
- $notification_type_id = $this->get_notification_type_id($notification_type_name);
- $item_id = $notification->get_item_id($data);
- $update_array = $notification->create_update_array($data);
-
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $update_array) . '
- WHERE notification_type_id = ' . (int) $notification_type_id . '
- AND item_id = ' . (int) $item_id;
- $this->db->sql_query($sql);
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $method->update_notification($notification, $data, $options);
+ }
}
/**
@@ -523,14 +433,15 @@ class manager
* @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types)
* @param int|array $item_id Identifier within the type (or array of ids)
* @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked)
+ * @param mixed $user_id User id (Default: false; not checked)
*/
- public function delete_notifications($notification_type_name, $item_id, $parent_id = false)
+ public function delete_notifications($notification_type_name, $item_id, $parent_id = false, $user_id = false)
{
if (is_array($notification_type_name))
{
foreach ($notification_type_name as $type)
{
- $this->delete_notifications($type, $item_id, $parent_id);
+ $this->delete_notifications($type, $item_id, $parent_id, $user_id);
}
return;
@@ -538,11 +449,11 @@ class manager
$notification_type_id = $this->get_notification_type_id($notification_type_name);
- $sql = 'DELETE FROM ' . $this->notifications_table . '
- WHERE notification_type_id = ' . (int) $notification_type_id . '
- AND ' . $this->db->sql_in_set('item_id', $item_id) .
- (($parent_id !== false) ? ' AND ' . $this->db->sql_in_set('item_parent_id', $parent_id) : '');
- $this->db->sql_query($sql);
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $method->delete_notifications($notification_type_id, $item_id, $parent_id, $user_id);
+ }
}
/**
@@ -558,6 +469,7 @@ class manager
foreach ($this->notification_types as $type_name => $data)
{
+ /** @var type\base $type */
$type = $this->get_item_type_class($type_name);
if ($type instanceof \phpbb\notification\type\type_interface && $type->is_available())
@@ -593,16 +505,55 @@ class manager
{
$subscription_methods = array();
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method_name => $method)
+ {
+ $subscription_methods[$method_name] = array(
+ 'id' => $method->get_type(),
+ 'lang' => str_replace('.', '_', strtoupper($method->get_type())),
+ );
+ }
+
+ return $subscription_methods;
+ }
+
+ /**
+ * Get all of the subscription methods
+ *
+ * @return array Array of method's instances
+ */
+ private function get_subscription_methods_instances()
+ {
+ $subscription_methods = array();
+
foreach ($this->notification_methods as $method_name => $data)
{
$method = $this->get_method_class($method_name);
- if ($method instanceof \phpbb\notification\method\method_interface && $method->is_available())
+ if ($method instanceof \phpbb\notification\method\method_interface)
{
- $subscription_methods[$method_name] = array(
- 'id' => $method->get_type(),
- 'lang' => str_replace('.', '_', strtoupper($method->get_type())),
- );
+ $subscription_methods[$method_name] = $method;
+ }
+ }
+
+ return $subscription_methods;
+ }
+
+ /**
+ * Get all of the available subscription methods
+ *
+ * @return array Array of method's instances
+ */
+ private function get_available_subscription_methods()
+ {
+ $subscription_methods = array();
+
+ /** @var method\method_interface $method */
+ foreach ($this->get_subscription_methods_instances() as $method_name => $method)
+ {
+ if ($method->is_available())
+ {
+ $subscription_methods[$method_name] = $method;
}
}
@@ -646,9 +597,10 @@ class manager
*/
public function get_global_subscriptions($user_id = false)
{
- $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
+ $user_id = $user_id ?: $this->user->data['user_id'];
$subscriptions = array();
+ $default_methods = $this->get_default_methods();
$user_notifications = $this->get_user_notifications($user_id);
@@ -656,29 +608,32 @@ class manager
{
foreach ($types as $id => $type)
{
-
- if (empty($user_notifications[$id]))
- {
- // No rows at all, default to ''
- $subscriptions[$id] = array('');
- }
- else
+ $type_subscriptions = $default_methods;
+ if (!empty($user_notifications[$id]))
{
foreach ($user_notifications[$id] as $user_notification)
{
+ $key = array_search($user_notification['method'], $type_subscriptions, true);
if (!$user_notification['notify'])
{
+ if ($key !== false)
+ {
+ unset($type_subscriptions[$key]);
+ }
+
continue;
}
-
- if (!isset($subscriptions[$id]))
+ else if ($key === false)
{
- $subscriptions[$id] = array();
+ $type_subscriptions[] = $user_notification['method'];
}
-
- $subscriptions[$id][] = $user_notification['method'];
}
}
+
+ if (!empty($type_subscriptions))
+ {
+ $subscriptions[$id] = $type_subscriptions;
+ }
}
}
@@ -690,15 +645,20 @@ class manager
*
* @param string $item_type Type identifier of the subscription
* @param int $item_id The id of the item
- * @param string $method The method of the notification e.g. '', 'email', or 'jabber'
+ * @param string $method The method of the notification e.g. 'board', 'email', or 'jabber'
+ * (if null a subscription will be added for all the defaults methods)
* @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
*/
- public function add_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
+ public function add_subscription($item_type, $item_id = 0, $method = null, $user_id = false)
{
- if ($method !== '')
+ if ($method === null)
{
- // Make sure to subscribe them to the base subscription
- $this->add_subscription($item_type, $item_id, '', $user_id);
+ foreach ($this->get_default_methods() as $method_name)
+ {
+ $this->add_subscription($item_type, $item_id, $method_name, $user_id);
+ }
+
+ return;
}
$user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
@@ -742,33 +702,23 @@ class manager
*
* @param string $item_type Type identifier of the subscription
* @param int $item_id The id of the item
- * @param string $method The method of the notification e.g. '', 'email', or 'jabber'
+ * @param string $method The method of the notification e.g. 'board', 'email', or 'jabber'
* @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
*/
- public function delete_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
+ public function delete_subscription($item_type, $item_id = 0, $method = null, $user_id = false)
{
- $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
-
- // If no method, make sure that no other notification methods for this item are selected before deleting
- if ($method === '')
+ if ($method === null)
{
- $sql = 'SELECT COUNT(*) as num_notifications
- FROM ' . $this->user_notifications_table . "
- WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
- AND item_id = " . (int) $item_id . '
- AND user_id = ' .(int) $user_id . "
- AND method <> ''
- AND notify = 1";
- $this->db->sql_query($sql);
- $num_notifications = $this->db->sql_fetchfield('num_notifications');
- $this->db->sql_freeresult();
-
- if ($num_notifications)
+ foreach ($this->get_default_methods() as $method_name)
{
- return;
+ $this->delete_subscription($item_type, $item_id, $method_name, $user_id);
}
+
+ return;
}
+ $user_id = $user_id ?: $this->user->data['user_id'];
+
$sql = 'UPDATE ' . $this->user_notifications_table . "
SET notify = 0
WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
@@ -828,15 +778,12 @@ class manager
{
$notification_type_id = $this->get_notification_type_id($notification_type_name);
- $sql = 'DELETE FROM ' . $this->notifications_table . '
- WHERE notification_type_id = ' . (int) $notification_type_id;
- $this->db->sql_query($sql);
-
- $sql = 'DELETE FROM ' . $this->notification_types_table . '
- WHERE notification_type_id = ' . (int) $notification_type_id;
- $this->db->sql_query($sql);
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $method->purge_notifications($notification_type_id);
+ }
- $this->cache->destroy('notification_type_ids');
}
catch (\phpbb\notification\exception $e)
{
@@ -869,17 +816,40 @@ class manager
*/
public function prune_notifications($timestamp, $only_read = true)
{
- $sql = 'DELETE FROM ' . $this->notifications_table . '
- WHERE notification_time < ' . (int) $timestamp .
- (($only_read) ? ' AND notification_read = 1' : '');
- $this->db->sql_query($sql);
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $method->prune_notifications($timestamp, $only_read);
+ }
+ }
+
+ /**
+ * Helper to get the list of methods enabled by default
+ *
+ * @return method\method_interface[]
+ */
+ public function get_default_methods()
+ {
+ $default_methods = array();
- $this->config->set('read_notification_last_gc', time(), false);
+ foreach ($this->notification_methods as $method)
+ {
+ if ($method->is_enabled_by_default() && $method->is_available())
+ {
+ $default_methods[] = $method->get_type();
+ }
+ }
+
+ return $default_methods;
}
/**
- * Helper to get the notifications item type class and set it up
- */
+ * Helper to get the notifications item type class and set it up
+ *
+ * @param string $notification_type_name
+ * @param array $data
+ * @return type\type_interface
+ */
public function get_item_type_class($notification_type_name, $data = array())
{
$item = $this->load_object($notification_type_name);
@@ -890,16 +860,22 @@ class manager
}
/**
- * Helper to get the notifications method class and set it up
- */
+ * Helper to get the notifications method class and set it up
+ *
+ * @param string $method_name
+ * @return method\method_interface
+ */
public function get_method_class($method_name)
{
return $this->load_object($method_name);
}
/**
- * Helper to load objects (notification types/methods)
- */
+ * Helper to load objects (notification types/methods)
+ *
+ * @param string $object_name
+ * @return method\method_interface|type\type_interface
+ */
protected function load_object($object_name)
{
$object = $this->phpbb_container->get($object_name);
@@ -946,7 +922,8 @@ class manager
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($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name));
+
+ throw new \phpbb\notification\exception('NOTIFICATION_TYPE_NOT_EXIST', array($notification_type_name));
}
$sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array(
@@ -987,4 +964,26 @@ class manager
return $notification_type_ids;
}
+
+ /**
+ * Find the users which are already notified
+ *
+ * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to retrieve all item types
+ * @param array $options
+ * @return array The list of the notified users
+ */
+ public function get_notified_users($notification_type_name, array $options)
+ {
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
+
+ $notified_users = array();
+
+ /** @var method\method_interface $method */
+ foreach ($this->get_available_subscription_methods() as $method)
+ {
+ $notified_users = $notified_users + $method->get_notified_users($notification_type_id, $options);
+ }
+
+ return $notified_users;
+ }
}
diff --git a/phpBB/phpbb/notification/method/base.php b/phpBB/phpbb/notification/method/base.php
index 6ee1d2984a..4a183ca508 100644
--- a/phpBB/phpbb/notification/method/base.php
+++ b/phpBB/phpbb/notification/method/base.php
@@ -21,36 +21,6 @@ abstract class base implements \phpbb\notification\method\method_interface
/** @var \phpbb\notification\manager */
protected $notification_manager;
- /** @var \phpbb\user_loader */
- protected $user_loader;
-
- /** @var \phpbb\db\driver\driver_interface */
- protected $db;
-
- /** @var \phpbb\cache\driver\driver_interface */
- protected $cache;
-
- /** @var \phpbb\template\template */
- protected $template;
-
- /** @var \phpbb\extension\manager */
- protected $extension_manager;
-
- /** @var \phpbb\user */
- protected $user;
-
- /** @var \phpbb\auth\auth */
- protected $auth;
-
- /** @var \phpbb\config\config */
- protected $config;
-
- /** @var string */
- protected $phpbb_root_path;
-
- /** @var string */
- protected $php_ext;
-
/**
* Queue of messages to be sent
*
@@ -59,38 +29,43 @@ abstract class base implements \phpbb\notification\method\method_interface
protected $queue = array();
/**
- * Notification Method Base Constructor
+ * Set notification manager (required)
*
- * @param \phpbb\user_loader $user_loader
- * @param \phpbb\db\driver\driver_interface $db
- * @param \phpbb\cache\driver\driver_interface $cache
- * @param \phpbb\user $user
- * @param \phpbb\auth\auth $auth
- * @param \phpbb\config\config $config
- * @param string $phpbb_root_path
- * @param string $php_ext
- * @return \phpbb\notification\method\base
+ * @param \phpbb\notification\manager $notification_manager
*/
- public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext)
+ public function set_notification_manager(\phpbb\notification\manager $notification_manager)
{
- $this->user_loader = $user_loader;
- $this->db = $db;
- $this->cache = $cache;
- $this->user = $user;
- $this->auth = $auth;
- $this->config = $config;
- $this->phpbb_root_path = $phpbb_root_path;
- $this->php_ext = $php_ext;
+ $this->notification_manager = $notification_manager;
}
/**
- * Set notification manager (required)
+ * Is the method enable by default?
*
- * @param \phpbb\notification\manager $notification_manager
+ * @return bool
*/
- public function set_notification_manager(\phpbb\notification\manager $notification_manager)
+ public function is_enabled_by_default()
{
- $this->notification_manager = $notification_manager;
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_notified_users($notification_type_id, array $options)
+ {
+ return array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load_notifications(array $options = array())
+ {
+ return array(
+ 'notifications' => array(),
+ 'unread_count' => 0,
+ 'total_count' => 0,
+ );
}
/**
@@ -104,6 +79,55 @@ abstract class base implements \phpbb\notification\method\method_interface
}
/**
+ * {@inheritdoc}
+ */
+ public function update_notification($notification, array $data, array $options)
+ {
+ }
+
+ /**
+ * {@inheritdoc
+ */
+ public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune_notifications($timestamp, $only_read = true)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function purge_notifications($notification_type_id)
+ {
+ }
+
+ /**
* Empty the queue
*/
protected function empty_queue()
diff --git a/phpBB/phpbb/notification/method/board.php b/phpBB/phpbb/notification/method/board.php
new file mode 100644
index 0000000000..931b252daa
--- /dev/null
+++ b/phpBB/phpbb/notification/method/board.php
@@ -0,0 +1,399 @@
+<?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\notification\method;
+
+/**
+* In Board notification method class
+* This class handles in board notifications. This method is enabled by default.
+*
+* @package notifications
+*/
+class board extends \phpbb\notification\method\base
+{
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\cache\driver\driver_interface */
+ protected $cache;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var string */
+ protected $notification_types_table;
+
+ /** @var string */
+ protected $notifications_table;
+
+ /**
+ * Notification Method Board Constructor
+ *
+ * @param \phpbb\user_loader $user_loader
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\cache\driver\driver_interface $cache
+ * @param \phpbb\user $user
+ * @param \phpbb\config\config $config
+ * @param string $notification_types_table
+ * @param string $notifications_table
+ */
+ public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\config\config $config, $notification_types_table, $notifications_table)
+ {
+ $this->user_loader = $user_loader;
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->user = $user;
+ $this->config = $config;
+ $this->notification_types_table = $notification_types_table;
+ $this->notifications_table = $notifications_table;
+
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_to_queue(\phpbb\notification\type\type_interface $notification)
+ {
+ $this->queue[] = $notification;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_type()
+ {
+ return 'notification.method.board';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_available()
+ {
+ return $this->config['allow_board_notifications'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_enabled_by_default()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_notified_users($notification_type_id, array $options)
+ {
+ $notified_users = array();
+ $sql = 'SELECT n.*
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.notification_type_id = ' . (int) $notification_type_id .
+ (isset($options['item_id']) ? ' AND n.item_id = ' . (int) $options['item_id'] : '') .
+ (isset($options['item_parent_id']) ? ' AND n.item_parent_id = ' . (int) $options['item_parent_id'] : '') .
+ (isset($options['user_id']) ? ' AND n.user_id = ' . (int) $options['user_id'] : '') .
+ (isset($options['read']) ? ' AND n.notification_read = ' . (int) $options['read'] : '') .'
+ AND nt.notification_type_id = n.notification_type_id
+ AND nt.notification_type_enabled = 1';
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $notified_users[$row['user_id']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ return $notified_users;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load_notifications(array $options = array())
+ {
+ // Merge default options
+ $options = array_merge(array(
+ 'notification_id' => false,
+ 'user_id' => $this->user->data['user_id'],
+ 'order_by' => 'notification_time',
+ 'order_dir' => 'DESC',
+ 'limit' => 0,
+ 'start' => 0,
+ 'all_unread' => false,
+ 'count_unread' => false,
+ 'count_total' => false,
+ ), $options);
+
+ // If all_unread, count_unread must be true
+ $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread'];
+
+ // Anonymous users and bots never receive notifications
+ if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE))
+ {
+ return array(
+ 'notifications' => array(),
+ 'unread_count' => 0,
+ 'total_count' => 0,
+ );
+ }
+
+ $notifications = $user_ids = array();
+ $load_special = array();
+ $total_count = $unread_count = 0;
+
+ if ($options['count_unread'])
+ {
+ // Get the total number of unread notifications
+ $sql = 'SELECT COUNT(n.notification_id) AS unread_count
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.user_id = ' . (int) $options['user_id'] . '
+ AND n.notification_read = 0
+ AND nt.notification_type_id = n.notification_type_id
+ AND nt.notification_type_enabled = 1';
+ $result = $this->db->sql_query($sql);
+ $unread_count = (int) $this->db->sql_fetchfield('unread_count');
+ $this->db->sql_freeresult($result);
+ }
+
+ if ($options['count_total'])
+ {
+ // Get the total number of notifications
+ $sql = 'SELECT COUNT(n.notification_id) AS total_count
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.user_id = ' . (int) $options['user_id'] . '
+ AND nt.notification_type_id = n.notification_type_id
+ AND nt.notification_type_enabled = 1';
+ $result = $this->db->sql_query($sql);
+ $total_count = (int) $this->db->sql_fetchfield('total_count');
+ $this->db->sql_freeresult($result);
+ }
+
+ if (!$options['count_total'] || $total_count)
+ {
+ $rowset = array();
+
+ // Get the main notifications
+ $sql = 'SELECT n.*, nt.notification_type_name
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.user_id = ' . (int) $options['user_id'] .
+ (($options['notification_id']) ? ((is_array($options['notification_id'])) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : ' AND n.notification_id = ' . (int) $options['notification_id']) : '') . '
+ AND nt.notification_type_id = n.notification_type_id
+ AND nt.notification_type_enabled = 1
+ ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
+ $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $rowset[$row['notification_id']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+
+ // Get all unread notifications
+ if ($unread_count && $options['all_unread'] && !empty($rowset))
+ {
+ $sql = 'SELECT n.*, nt.notification_type_name
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.user_id = ' . (int) $options['user_id'] . '
+ AND n.notification_read = 0
+ AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . '
+ AND nt.notification_type_id = n.notification_type_id
+ AND nt.notification_type_enabled = 1
+ ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
+ $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $rowset[$row['notification_id']] = $row;
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ foreach ($rowset as $row)
+ {
+ $notification = $this->notification_manager->get_item_type_class($row['notification_type_name'], $row);
+
+ // Array of user_ids to query all at once
+ $user_ids = array_merge($user_ids, $notification->users_to_query());
+
+ // Some notification types also require querying additional tables themselves
+ if (!isset($load_special[$row['notification_type_name']]))
+ {
+ $load_special[$row['notification_type_name']] = array();
+ }
+ $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special());
+
+ $notifications[$row['notification_id']] = $notification;
+ }
+
+ $this->user_loader->load_users($user_ids);
+
+ // Allow each type to load its own special items
+ foreach ($load_special as $item_type => $data)
+ {
+ $item_class = $this->notification_manager->get_item_type_class($item_type);
+
+ $item_class->load_special($data, $notifications);
+ }
+ }
+
+ return array(
+ 'notifications' => $notifications,
+ 'unread_count' => $unread_count,
+ 'total_count' => $total_count,
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function notify()
+ {
+ $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table);
+
+ /** @var \phpbb\notification\type\type_interface $notification */
+ foreach ($this->queue as $notification)
+ {
+ $data = $notification->get_insert_array();
+ $insert_buffer->insert($data);
+ }
+
+ $insert_buffer->flush();
+
+ // We're done, empty the queue
+ $this->empty_queue();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_notification($notification, array $data, array $options)
+ {
+ // Allow the notifications class to over-ride the update_notifications functionality
+ if (method_exists($notification, 'update_notifications'))
+ {
+ // Return False to over-ride the rest of the update
+ if ($notification->update_notifications($data) === false)
+ {
+ return;
+ }
+ }
+
+ $notification_type_id = $this->notification_manager->get_notification_type_id($notification->get_type());
+ $update_array = $notification->create_update_array($data);
+
+ $sql = 'UPDATE ' . $this->notifications_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $update_array) . '
+ WHERE notification_type_id = ' . (int) $notification_type_id .
+ (isset($options['item_id']) ? ' AND item_id = ' . (int) $options['item_id'] : '') .
+ (isset($options['item_parent_id']) ? ' AND item_parent_id = ' . (int) $options['item_parent_id'] : '') .
+ (isset($options['user_id']) ? ' AND user_id = ' . (int) $options['user_id'] : '') .
+ (isset($options['read']) ? ' AND notification_read = ' . (int) $options['read'] : '');
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true)
+ {
+ $time = ($time !== false) ? $time : time();
+
+ $sql = 'UPDATE ' . $this->notifications_table . '
+ SET notification_read = ' . ($mark_read ? 1 : 0) . '
+ WHERE notification_time <= ' . (int) $time .
+ (($notification_type_id !== false) ? ' AND ' .
+ (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') .
+ (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') .
+ (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : '');
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true)
+ {
+ $time = ($time !== false) ? $time : time();
+
+ $sql = 'UPDATE ' . $this->notifications_table . '
+ SET notification_read = ' . ($mark_read ? 1 : 0) . '
+ WHERE notification_time <= ' . (int) $time .
+ (($notification_type_id !== false) ? ' AND ' .
+ (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') .
+ (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : 'item_parent_id = ' . (int) $item_parent_id) : '') .
+ (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '');
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true)
+ {
+ $time = ($time !== false) ? $time : time();
+
+ $sql = 'UPDATE ' . $this->notifications_table . '
+ SET notification_read = ' . ($mark_read ? 1 : 0) . '
+ WHERE notification_time <= ' . (int) $time . '
+ AND ' . ((is_array($notification_id)) ? $this->db->sql_in_set('notification_id', $notification_id) : 'notification_id = ' . (int) $notification_id);
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false)
+ {
+ $sql = 'DELETE FROM ' . $this->notifications_table . '
+ WHERE notification_type_id = ' . (int) $notification_type_id . '
+ AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) .
+ (($parent_id !== false) ? ' AND ' . ((is_array($parent_id) ? $this->db->sql_in_set('item_parent_id', $parent_id) : 'item_parent_id = ' . (int) $parent_id)) : '') .
+ (($user_id !== false) ? ' AND ' . ((is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id)) : '');
+ $this->db->sql_query($sql);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune_notifications($timestamp, $only_read = true)
+ {
+ $sql = 'DELETE FROM ' . $this->notifications_table . '
+ WHERE notification_time < ' . (int) $timestamp .
+ (($only_read) ? ' AND notification_read = 1' : '');
+ $this->db->sql_query($sql);
+
+ $this->config->set('read_notification_last_gc', time(), false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function purge_notifications($notification_type_id)
+ {
+ $sql = 'DELETE FROM ' . $this->notifications_table . '
+ WHERE notification_type_id = ' . (int) $notification_type_id;
+ $this->db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . $this->notification_types_table . '
+ WHERE notification_type_id = ' . (int) $notification_type_id;
+ $this->db->sql_query($sql);
+
+ $this->cache->destroy('notification_type_ids');
+ }
+}
diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php
index a4b93bc85c..21a6559012 100644
--- a/phpBB/phpbb/notification/method/email.php
+++ b/phpBB/phpbb/notification/method/email.php
@@ -20,6 +20,29 @@ namespace phpbb\notification\method;
class email extends \phpbb\notification\method\messenger_base
{
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /**
+ * Notification Method email Constructor
+ *
+ * @param \phpbb\user_loader $user_loader
+ * @param \phpbb\user $user
+ * @param \phpbb\config\config $config
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, $phpbb_root_path, $php_ext)
+ {
+ parent::__construct($user_loader, $phpbb_root_path, $php_ext);
+
+ $this->user = $user;
+ $this->config = $config;
+ }
+
/**
* Get notification method name
*
diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php
index 09f186e3ca..509c6b432c 100644
--- a/phpBB/phpbb/notification/method/jabber.php
+++ b/phpBB/phpbb/notification/method/jabber.php
@@ -20,6 +20,29 @@ namespace phpbb\notification\method;
class jabber extends \phpbb\notification\method\messenger_base
{
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /**
+ * Notification Method jabber Constructor
+ *
+ * @param \phpbb\user_loader $user_loader
+ * @param \phpbb\user $user
+ * @param \phpbb\config\config $config
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\user_loader $user_loader, \phpbb\user $user, \phpbb\config\config $config, $phpbb_root_path, $php_ext)
+ {
+ parent::__construct($user_loader, $phpbb_root_path, $php_ext);
+
+ $this->user = $user;
+ $this->config = $config;
+ }
+
/**
* Get notification method name
*
@@ -61,6 +84,6 @@ class jabber extends \phpbb\notification\method\messenger_base
return;
}
- return $this->notify_using_messenger(NOTIFY_IM, 'short/');
+ $this->notify_using_messenger(NOTIFY_IM, 'short/');
}
}
diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php
index 0bfbfd6b02..1f5525accc 100644
--- a/phpBB/phpbb/notification/method/messenger_base.php
+++ b/phpBB/phpbb/notification/method/messenger_base.php
@@ -19,6 +19,29 @@ namespace phpbb\notification\method;
*/
abstract class messenger_base extends \phpbb\notification\method\base
{
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ /** @var string */
+ protected $phpbb_root_path;
+
+ /** @var string */
+ protected $php_ext;
+
+ /**
+ * Notification Method Board Constructor
+ *
+ * @param \phpbb\user_loader $user_loader
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\user_loader $user_loader, $phpbb_root_path, $php_ext)
+ {
+ $this->user_loader = $user_loader;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
/**
* Notify using phpBB messenger
*
@@ -57,9 +80,9 @@ abstract class messenger_base extends \phpbb\notification\method\base
include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
}
$messenger = new \messenger();
- $board_url = generate_board_url();
// Time to go through the queue and send emails
+ /** @var \phpbb\notification\type\type_interface $notification */
foreach ($this->queue as $notification)
{
if ($notification->get_email_template() === false)
diff --git a/phpBB/phpbb/notification/method/method_interface.php b/phpBB/phpbb/notification/method/method_interface.php
index 76b0de179c..c2e4940485 100644
--- a/phpBB/phpbb/notification/method/method_interface.php
+++ b/phpBB/phpbb/notification/method/method_interface.php
@@ -26,12 +26,48 @@ interface method_interface
public function get_type();
/**
+ * Is the method enable by default?
+ *
+ * @return bool
+ */
+ public function is_enabled_by_default();
+
+ /**
* Is this method available for the user?
* This is checked on the notifications options
*/
public function is_available();
/**
+ * Return the list of the users already notified
+ *
+ * @param int $notification_type_id Type of the notification
+ * @param array $options
+ * @return array User
+ */
+ public function get_notified_users($notification_type_id, array $options);
+
+ /**
+ * Load the user's notifications
+ *
+ * @param array $options Optional options to control what notifications are loaded
+ * notification_id Notification id to load (or array of notification ids)
+ * user_id User id to load notifications for (Default: $user->data['user_id'])
+ * order_by Order by (Default: notification_time)
+ * order_dir Order direction (Default: DESC)
+ * limit Number of notifications to load (Default: 5)
+ * start Notifications offset (Default: 0)
+ * all_unread Load all unread notifications? If set to true, count_unread is set to true (Default: false)
+ * count_unread Count all unread notifications? (Default: false)
+ * count_total Count all notifications? (Default: false)
+ * @return array Array of information based on the request with keys:
+ * 'notifications' array of notification type objects
+ * 'unread_count' number of unread notifications the user has if count_unread is true in the options
+ * 'total_count' number of notifications the user has if count_total is true in the options
+ */
+ public function load_notifications(array $options = array());
+
+ /**
* Add a notification to the queue
*
* @param \phpbb\notification\type\type_interface $notification
@@ -42,4 +78,72 @@ interface method_interface
* Parse the queue and notify the users
*/
public function notify();
+
+ /**
+ * Update a notification
+ *
+ * @param \phpbb\notification\type\type_interface $notification Notification to update
+ * @param array $data Data specific for this type that will be updated
+ * @param array $options
+ */
+ public function update_notification($notification, array $data, array $options);
+
+ /**
+ * Mark notifications read or unread
+ *
+ * @param bool|string $notification_type_id Type identifier of item types. False to mark read for all item types
+ * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True)
+ */
+ public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true);
+
+ /**
+ * Mark notifications read or unread from a parent identifier
+ *
+ * @param string $notification_type_id Type identifier of item types
+ * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
+ * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True)
+ */
+ public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true);
+
+ /**
+ * Mark notifications read or unread
+ *
+ * @param int $notification_id Notification id of notification ids.
+ * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
+ * @param bool $mark_read Define if the notification as to be set to True or False. (Default: True)
+ */
+ public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true);
+
+ /**
+ * Delete a notification
+ *
+ * @param string $notification_type_id Type identifier of item types
+ * @param int|array $item_id Identifier within the type (or array of ids)
+ * @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked)
+ * @param mixed $user_id User id (Default: false; not checked)
+ */
+ public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false);
+
+ /**
+ * Delete all notifications older than a certain time
+ *
+ * @param int $timestamp Unix timestamp to delete all notifications that were created before
+ * @param bool $only_read True (default) to only prune read notifications
+ */
+ public function prune_notifications($timestamp, $only_read = true);
+
+ /**
+ * Purge all notifications of a certain type
+ *
+ * This should be called when an extension which has notification types
+ * is purged so that all those notifications are removed
+ *
+ * @param string $notification_type_id Type identifier of the subscription
+ */
+ public function purge_notifications($notification_type_id);
}
diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php
index 7c5c18aa47..9f2ae857ef 100644
--- a/phpBB/phpbb/notification/type/admin_activate_user.php
+++ b/phpBB/phpbb/notification/type/admin_activate_user.php
@@ -36,11 +36,27 @@ class admin_activate_user extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_ADMIN_ACTIVATE_USER',
'group' => 'NOTIFICATION_GROUP_ADMINISTRATION',
);
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ public function set_config(\phpbb\config\config $config)
+ {
+ $this->config = $config;
+ }
+
+ public function set_user_loader(\phpbb\user_loader $user_loader)
+ {
+ $this->user_loader = $user_loader;
+ }
+
/**
* {@inheritdoc}
*/
@@ -52,7 +68,7 @@ class admin_activate_user extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static function get_item_id($user)
+ static public function get_item_id($user)
{
return (int) $user['user_id'];
}
@@ -60,7 +76,7 @@ class admin_activate_user extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static function get_item_parent_id($post)
+ static public function get_item_parent_id($post)
{
return 0;
}
@@ -114,7 +130,7 @@ class admin_activate_user extends \phpbb\notification\type\base
{
$username = $this->user_loader->get_username($this->item_id, 'no_profile');
- return $this->user->lang($this->language_key, $username);
+ return $this->language->lang($this->language_key, $username);
}
/**
@@ -164,6 +180,6 @@ class admin_activate_user extends \phpbb\notification\type\base
$this->set_data('user_actkey', $user['user_actkey']);
$this->notification_time = $user['user_regdate'];
- return parent::create_insert_array($user, $pre_create_data);
+ parent::create_insert_array($user, $pre_create_data);
}
}
diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php
index 5760c12166..e4b111e4da 100644
--- a/phpBB/phpbb/notification/type/approve_post.php
+++ b/phpBB/phpbb/notification/type/approve_post.php
@@ -50,7 +50,7 @@ class approve_post extends \phpbb\notification\type\post
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
@@ -79,7 +79,7 @@ class approve_post extends \phpbb\notification\type\post
), $options);
$users = array();
- $users[$post['poster_id']] = array('');
+ $users[$post['poster_id']] = $this->notification_manager->get_default_methods();
return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array(
'item_type' => static::$notification_option['id'],
@@ -107,21 +107,24 @@ class approve_post extends \phpbb\notification\type\post
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('post_subject', $post['post_subject']);
- $data = parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php
index 26e51bf9cd..f8a3fdec6f 100644
--- a/phpBB/phpbb/notification/type/approve_topic.php
+++ b/phpBB/phpbb/notification/type/approve_topic.php
@@ -50,7 +50,7 @@ class approve_topic extends \phpbb\notification\type\topic
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
@@ -79,7 +79,7 @@ class approve_topic extends \phpbb\notification\type\topic
), $options);
$users = array();
- $users[$post['poster_id']] = array('');
+ $users[$post['poster_id']] = $this->notification_manager->get_default_methods();
return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array(
'item_type' => static::$notification_option['id'],
@@ -107,19 +107,23 @@ class approve_topic extends \phpbb\notification\type\topic
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
- $data = parent::create_insert_array($post, $pre_create_data);
- $this->notification_time = $data['notification_time'] = time();
+ parent::create_insert_array($post, $pre_create_data);
+
+ $this->notification_time = time();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php
index 4ead06071e..77ed7f2b09 100644
--- a/phpBB/phpbb/notification/type/base.php
+++ b/phpBB/phpbb/notification/type/base.php
@@ -21,17 +21,11 @@ abstract class base implements \phpbb\notification\type\type_interface
/** @var \phpbb\notification\manager */
protected $notification_manager;
- /** @var \phpbb\user_loader */
- protected $user_loader;
-
/** @var \phpbb\db\driver\driver_interface */
protected $db;
- /** @var \phpbb\cache\driver\driver_interface */
- protected $cache;
-
- /** @var \phpbb\template\template */
- protected $template;
+ /** @var \phpbb\language\language */
+ protected $language;
/** @var \phpbb\user */
protected $user;
@@ -39,9 +33,6 @@ abstract class base implements \phpbb\notification\type\type_interface
/** @var \phpbb\auth\auth */
protected $auth;
- /** @var \phpbb\config\config */
- protected $config;
-
/** @var string */
protected $phpbb_root_path;
@@ -49,12 +40,6 @@ abstract class base implements \phpbb\notification\type\type_interface
protected $php_ext;
/** @var string */
- protected $notification_types_table;
-
- /** @var string */
- protected $notifications_table;
-
- /** @var string */
protected $user_notifications_table;
/**
@@ -63,7 +48,7 @@ abstract class base implements \phpbb\notification\type\type_interface
* @var bool|array False if the service should use its default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = false;
+ static public $notification_option = false;
/**
* The notification_type_id, set upon creation of the class
@@ -74,7 +59,7 @@ abstract class base implements \phpbb\notification\type\type_interface
protected $notification_type_id;
/**
- * Indentification data
+ * Identification data
* notification_type_id - ID of the item type (auto generated, from notification types table)
* item_id - ID of the item (e.g. post_id, msg_id)
* item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
@@ -89,35 +74,26 @@ abstract class base implements \phpbb\notification\type\type_interface
private $data = array();
/**
- * Notification Type Base Constructor
- *
- * @param \phpbb\user_loader $user_loader
- * @param \phpbb\db\driver\driver_interface $db
- * @param \phpbb\cache\driver\driver_interface $cache
- * @param \phpbb\user $user
- * @param \phpbb\auth\auth $auth
- * @param \phpbb\config\config $config
- * @param string $phpbb_root_path
- * @param string $php_ext
- * @param string $notification_types_table
- * @param string $notifications_table
- * @param string $user_notifications_table
- * @return \phpbb\notification\type\base
- */
- public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, $user, \phpbb\auth\auth $auth, \phpbb\config\config $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ * Notification Type Base Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\language\language $language
+ * @param \phpbb\user $user
+ * @param \phpbb\auth\auth $auth
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ * @param string $user_notifications_table
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\language\language $language, \phpbb\user $user, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext, $user_notifications_table)
{
- $this->user_loader = $user_loader;
$this->db = $db;
- $this->cache = $cache;
+ $this->language = $language;
$this->user = $user;
$this->auth = $auth;
- $this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
- $this->notification_types_table = $notification_types_table;
- $this->notifications_table = $notifications_table;
$this->user_notifications_table = $user_notifications_table;
}
@@ -207,12 +183,7 @@ abstract class base implements \phpbb\notification\type\type_interface
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $type_data Data unique to this notification type
- * @param array $pre_create_data Data from pre_create_insert_array()
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($type_data, $pre_create_data = array())
{
@@ -225,9 +196,15 @@ abstract class base implements \phpbb\notification\type\type_interface
'notification_time' => time(),
'notification_read' => false,
- 'notification_data' => array(),
+ 'notification_data' => array(),
), $this->data);
+ }
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
$data = $this->data;
$data['notification_data'] = serialize($data['notification_data']);
@@ -244,7 +221,8 @@ abstract class base implements \phpbb\notification\type\type_interface
*/
public function create_update_array($type_data)
{
- $data = $this->create_insert_array($type_data);
+ $this->create_insert_array($type_data);
+ $data = $this->get_insert_array();
// Unset data unique to each row
unset(
@@ -330,6 +308,7 @@ abstract class base implements \phpbb\notification\type\type_interface
* URL to unsubscribe to this notification (fall back)
*
* @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item
+ * @return false
*/
public function get_unsubscribe_url($method = false)
{
@@ -397,8 +376,11 @@ abstract class base implements \phpbb\notification\type\type_interface
}
/**
- * Load the special items (fall back)
- */
+ * Load the special items (fall back)
+ *
+ * @param array $data
+ * @param array $notifications
+ */
public function load_special($data, $notifications)
{
return;
@@ -415,10 +397,12 @@ abstract class base implements \phpbb\notification\type\type_interface
}
/**
- * Pre create insert array function (fall back)
- *
- * @return array
- */
+ * Pre create insert array function (fall back)
+ *
+ * @param array $type_data
+ * @param array $notify_users
+ * @return array
+ */
public function pre_create_insert_array($type_data, $notify_users)
{
return array();
@@ -429,13 +413,13 @@ abstract class base implements \phpbb\notification\type\type_interface
*/
/**
- * Find the users who want to receive notifications (helper)
- *
- * @param array $user_ids User IDs to check if they want to receive notifications
- * (Bool False to check all users besides anonymous and bots (USER_IGNORE))
- *
- * @return array
- */
+ * Find the users who want to receive notifications (helper)
+ *
+ * @param array|bool $user_ids User IDs to check if they want to receive notifications
+ * (Bool False to check all users besides anonymous and bots (USER_IGNORE))
+ * @param array $options
+ * @return array
+ */
protected function check_user_notification_options($user_ids = false, $options = array())
{
$options = array_merge(array(
@@ -465,7 +449,7 @@ abstract class base implements \phpbb\notification\type\type_interface
return array();
}
- $rowset = $resulting_user_ids = array();
+ $rowset = $output = array();
$sql = 'SELECT user_id, method, notify
FROM ' . $this->user_notifications_table . '
@@ -476,9 +460,7 @@ abstract class base implements \phpbb\notification\type\type_interface
while ($row = $this->db->sql_fetchrow($result))
{
- $resulting_user_ids[] = $row['user_id'];
-
- if (!$row['notify'] || (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']])))
+ if (isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']]))
{
continue;
}
@@ -487,22 +469,47 @@ abstract class base implements \phpbb\notification\type\type_interface
{
$rowset[$row['user_id']] = array();
}
+ $rowset[$row['user_id']][$row['method']] = $row['notify'];
- $rowset[$row['user_id']][] = $row['method'];
+ if (!isset($output[$row['user_id']]))
+ {
+ $output[$row['user_id']] = array();
+ }
+ if ($row['notify'])
+ {
+ $output[$row['user_id']][] = $row['method'];
+ }
}
$this->db->sql_freeresult($result);
+ $default_methods = $this->notification_manager->get_default_methods();
+
foreach ($user_ids as $user_id)
{
- if (!in_array($user_id, $resulting_user_ids) && !isset($options['ignore_users'][$user_id]))
+ if (isset($options['ignore_users'][$user_id]))
+ {
+ continue;
+ }
+ if (!array_key_exists($user_id, $rowset))
+ {
+ // No rows at all for this user, use the default methods
+ $output[$user_id] = $default_methods;
+ }
+ else
{
- // No rows at all for this user, default to ''
- $rowset[$user_id] = array('');
+ foreach ($default_methods as $default_method)
+ {
+ if (!array_key_exists($default_method, $rowset[$user_id]))
+ {
+ // No user preference for this type recorded, but it should be enabled by default.
+ $output[$user_id][] = $default_method;
+ }
+ }
}
}
- return $rowset;
+ return $output;
}
/**
@@ -516,22 +523,23 @@ abstract class base implements \phpbb\notification\type\type_interface
{
$this->notification_read = (bool) !$unread;
- $where = array(
- 'notification_type_id = ' . (int) $this->notification_type_id,
- 'item_id = ' . (int) $this->item_id,
- 'user_id = ' . (int) $this->user_id,
- );
- $where = implode(' AND ', $where);
-
if ($return)
{
+ $where = array(
+ 'notification_type_id = ' . (int) $this->notification_type_id,
+ 'item_id = ' . (int) $this->item_id,
+ 'user_id = ' . (int) $this->user_id,
+ );
+
+ $where = implode(' AND ', $where);
return $where;
}
+ else
+ {
+ $this->notification_manager->mark_notifications($this->get_type(), (int) $this->item_id, (int) $this->user_id, false, $this->notification_read);
+ }
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET notification_read = ' . (int) $this->notification_read . '
- WHERE ' . $where;
- $this->db->sql_query($sql);
+ return null;
}
/**
diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php
index 1626add22c..ebbb961c57 100644
--- a/phpBB/phpbb/notification/type/bookmark.php
+++ b/phpBB/phpbb/notification/type/bookmark.php
@@ -43,7 +43,7 @@ class bookmark extends \phpbb\notification\type\post
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_BOOKMARK',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
@@ -91,31 +91,27 @@ class bookmark extends \phpbb\notification\type\post
}
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
- $update_notifications = array();
- $sql = 'SELECT n.*
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
- AND n.item_parent_id = ' . (int) static::get_item_parent_id($post) . '
- AND n.notification_read = 0
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
+ $notified_users = $this->notification_manager->get_notified_users($this->get_type(), array(
+ 'item_parent_id' => static::get_item_parent_id($post),
+ 'read' => 0,
+ ));
+
+ foreach ($notified_users as $user => $notification_data)
{
- // Do not create a new notification
- unset($notify_users[$row['user_id']]);
+ unset($notify_users[$user]);
- $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row);
+ /** @var bookmark $notification */
+ $notification = $this->notification_manager->get_item_type_class($this->get_type(), $notification_data);
$update_responders = $notification->add_responders($post);
if (!empty($update_responders))
{
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . '
- WHERE notification_id = ' . $row['notification_id'];
- $this->db->sql_query($sql);
+ $this->notification_manager->update_notification($notification, $update_responders, array(
+ 'item_parent_id' => self::get_item_parent_id($post),
+ 'read' => 0,
+ 'user_id' => $user,
+ ));
}
}
- $this->db->sql_freeresult($result);
return $notify_users;
}
diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php
index 6c7bcbcaee..2d908eb254 100644
--- a/phpBB/phpbb/notification/type/disapprove_post.php
+++ b/phpBB/phpbb/notification/type/disapprove_post.php
@@ -60,7 +60,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
@@ -73,7 +73,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
*/
public function get_title()
{
- return $this->user->lang($this->language_key);
+ return $this->language->lang($this->language_key);
}
/**
@@ -83,7 +83,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -96,7 +96,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
*/
public function get_reason()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('disapprove_reason')
);
@@ -125,21 +125,24 @@ class disapprove_post extends \phpbb\notification\type\approve_post
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('disapprove_reason', $post['disapprove_reason']);
- $data = parent::create_insert_array($post);
+ parent::create_insert_array($post, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php
index efa5eb7ecd..c2522fb562 100644
--- a/phpBB/phpbb/notification/type/disapprove_topic.php
+++ b/phpBB/phpbb/notification/type/disapprove_topic.php
@@ -60,7 +60,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'moderation_queue',
'lang' => 'NOTIFICATION_TYPE_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_POSTING',
@@ -73,7 +73,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
*/
public function get_title()
{
- return $this->user->lang($this->language_key);
+ return $this->language->lang($this->language_key);
}
/**
@@ -83,7 +83,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -96,7 +96,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
*/
public function get_reason()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('disapprove_reason')
);
@@ -125,21 +125,24 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('disapprove_reason', $post['disapprove_reason']);
- $data = parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php
index 96bfc86322..28a9e73bf9 100644
--- a/phpBB/phpbb/notification/type/group_request.php
+++ b/phpBB/phpbb/notification/type/group_request.php
@@ -26,10 +26,18 @@ class group_request extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_GROUP_REQUEST',
);
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ public function set_user_loader(\phpbb\user_loader $user_loader)
+ {
+ $this->user_loader = $user_loader;
+ }
+
/**
* {@inheritdoc}
*/
@@ -50,7 +58,7 @@ class group_request extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static function get_item_id($group)
+ static public function get_item_id($group)
{
return (int) $group['user_id'];
}
@@ -58,7 +66,7 @@ class group_request extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static function get_item_parent_id($group)
+ static public function get_item_parent_id($group)
{
// Group id is the parent
return (int) $group['group_id'];
@@ -106,7 +114,7 @@ class group_request extends \phpbb\notification\type\base
{
$username = $this->user_loader->get_username($this->item_id, 'no_profile');
- return $this->user->lang('NOTIFICATION_GROUP_REQUEST', $username, $this->get_data('group_name'));
+ return $this->language->lang('NOTIFICATION_GROUP_REQUEST', $username, $this->get_data('group_name'));
}
/**
@@ -156,6 +164,6 @@ class group_request extends \phpbb\notification\type\base
{
$this->set_data('group_name', $group['group_name']);
- return parent::create_insert_array($group, $pre_create_data);
+ parent::create_insert_array($group, $pre_create_data);
}
}
diff --git a/phpBB/phpbb/notification/type/group_request_approved.php b/phpBB/phpbb/notification/type/group_request_approved.php
index d284046ffa..f55d28bafd 100644
--- a/phpBB/phpbb/notification/type/group_request_approved.php
+++ b/phpBB/phpbb/notification/type/group_request_approved.php
@@ -34,7 +34,7 @@ class group_request_approved extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static function get_item_id($group)
+ static public function get_item_id($group)
{
return (int) $group['group_id'];
}
@@ -42,7 +42,7 @@ class group_request_approved extends \phpbb\notification\type\base
/**
* {@inheritdoc}
*/
- public static function get_item_parent_id($group)
+ static public function get_item_parent_id($group)
{
return 0;
}
@@ -58,7 +58,7 @@ class group_request_approved extends \phpbb\notification\type\base
foreach ($group['user_ids'] as $user_id)
{
- $users[$user_id] = array('');
+ $users[$user_id] = $this->notification_manager->get_default_methods();
}
return $users;
@@ -69,7 +69,7 @@ class group_request_approved extends \phpbb\notification\type\base
*/
public function get_title()
{
- return $this->user->lang('NOTIFICATION_GROUP_REQUEST_APPROVED', $this->get_data('group_name'));
+ return $this->language->lang('NOTIFICATION_GROUP_REQUEST_APPROVED', $this->get_data('group_name'));
}
/**
@@ -87,7 +87,7 @@ class group_request_approved extends \phpbb\notification\type\base
{
$this->set_data('group_name', $group['group_name']);
- return parent::create_insert_array($group, $pre_create_data);
+ parent::create_insert_array($group, $pre_create_data);
}
/**
diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php
index d2f34f95d0..8fb9172911 100644
--- a/phpBB/phpbb/notification/type/pm.php
+++ b/phpBB/phpbb/notification/type/pm.php
@@ -36,10 +36,26 @@ class pm extends \phpbb\notification\type\base
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_PM',
);
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ public function set_config(\phpbb\config\config $config)
+ {
+ $this->config = $config;
+ }
+
+ public function set_user_loader(\phpbb\user_loader $user_loader)
+ {
+ $this->user_loader = $user_loader;
+ }
+
/**
* Is available
*/
@@ -53,7 +69,7 @@ class pm extends \phpbb\notification\type\base
*
* @param array $pm The data from the private message
*/
- public static function get_item_id($pm)
+ static public function get_item_id($pm)
{
return (int) $pm['msg_id'];
}
@@ -63,7 +79,7 @@ class pm extends \phpbb\notification\type\base
*
* @param array $pm The data from the pm
*/
- public static function get_item_parent_id($pm)
+ static public function get_item_parent_id($pm)
{
// No parent
return 0;
@@ -112,7 +128,7 @@ class pm extends \phpbb\notification\type\base
{
$username = $this->user_loader->get_username($this->get_data('from_user_id'), 'no_profile');
- return $this->user->lang('NOTIFICATION_PM', $username);
+ return $this->language->lang('NOTIFICATION_PM', $username);
}
/**
@@ -122,7 +138,7 @@ class pm extends \phpbb\notification\type\base
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
$this->get_data('message_subject')
);
@@ -176,13 +192,7 @@ class pm extends \phpbb\notification\type\base
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $pm Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($pm, $pre_create_data = array())
{
@@ -190,6 +200,6 @@ class pm extends \phpbb\notification\type\base
$this->set_data('message_subject', $pm['message_subject']);
- return parent::create_insert_array($pm, $pre_create_data);
+ parent::create_insert_array($pm, $pre_create_data);
}
}
diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php
index 2969da550d..b9afc6d70a 100644
--- a/phpBB/phpbb/notification/type/post.php
+++ b/phpBB/phpbb/notification/type/post.php
@@ -50,11 +50,27 @@ class post extends \phpbb\notification\type\base
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_POST',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ public function set_config(\phpbb\config\config $config)
+ {
+ $this->config = $config;
+ }
+
+ public function set_user_loader(\phpbb\user_loader $user_loader)
+ {
+ $this->user_loader = $user_loader;
+ }
+
/**
* Is available
*/
@@ -67,8 +83,9 @@ class post extends \phpbb\notification\type\base
* Get the id of the item
*
* @param array $post The data from the post
+ * @return int The post id
*/
- public static function get_item_id($post)
+ static public function get_item_id($post)
{
return (int) $post['post_id'];
}
@@ -77,8 +94,9 @@ class post extends \phpbb\notification\type\base
* Get the id of the parent
*
* @param array $post The data from the post
+ * @return int The topic id
*/
- public static function get_item_parent_id($post)
+ static public function get_item_parent_id($post)
{
return (int) $post['topic_id'];
}
@@ -131,31 +149,27 @@ class post extends \phpbb\notification\type\base
}
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
- $update_notifications = array();
- $sql = 'SELECT n.*
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
- AND n.item_parent_id = ' . (int) static::get_item_parent_id($post) . '
- AND n.notification_read = 0
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
+ $notified_users = $this->notification_manager->get_notified_users($this->get_type(), array(
+ 'item_parent_id' => static::get_item_parent_id($post),
+ 'read' => 0,
+ ));
+
+ foreach ($notified_users as $user => $notification_data)
{
- // Do not create a new notification
- unset($notify_users[$row['user_id']]);
+ unset($notify_users[$user]);
- $notification = $this->notification_manager->get_item_type_class($this->get_type(), $row);
+ /** @var post $notification */
+ $notification = $this->notification_manager->get_item_type_class($this->get_type(), $notification_data);
$update_responders = $notification->add_responders($post);
if (!empty($update_responders))
{
- $sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $update_responders) . '
- WHERE notification_id = ' . $row['notification_id'];
- $this->db->sql_query($sql);
+ $this->notification_manager->update_notification($notification, $update_responders, array(
+ 'item_parent_id' => self::get_item_parent_id($post),
+ 'read' => 0,
+ 'user_id' => $user,
+ ));
}
}
- $this->db->sql_freeresult($result);
return $notify_users;
}
@@ -206,14 +220,14 @@ class post extends \phpbb\notification\type\base
if ($trimmed_responders_cnt > 20)
{
- $usernames[] = $this->user->lang('NOTIFICATION_MANY_OTHERS');
+ $usernames[] = $this->language->lang('NOTIFICATION_MANY_OTHERS');
}
else if ($trimmed_responders_cnt)
{
- $usernames[] = $this->user->lang('NOTIFICATION_X_OTHERS', $trimmed_responders_cnt);
+ $usernames[] = $this->language->lang('NOTIFICATION_X_OTHERS', $trimmed_responders_cnt);
}
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
phpbb_generate_string_list($usernames, $this->user),
$responders_cnt
@@ -227,7 +241,7 @@ class post extends \phpbb\notification\type\base
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -363,13 +377,7 @@ class post extends \phpbb\notification\type\base
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
@@ -394,13 +402,14 @@ class post extends \phpbb\notification\type\base
$this->notification_read = true;
}
- return parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
}
/**
* Add responders to the notification
*
* @param mixed $post
+ * @return array Array of responder data
*/
public function add_responders($post)
{
diff --git a/phpBB/phpbb/notification/type/post_in_queue.php b/phpBB/phpbb/notification/type/post_in_queue.php
index 5832c99cd2..2d556fc9c8 100644
--- a/phpBB/phpbb/notification/type/post_in_queue.php
+++ b/phpBB/phpbb/notification/type/post_in_queue.php
@@ -43,7 +43,7 @@ class post_in_queue extends \phpbb\notification\type\post
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'notification.type.needs_approval',
'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_MODERATION',
@@ -131,19 +131,22 @@ class post_in_queue extends \phpbb\notification\type\post
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
- $data = parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php
index 2732cb84e4..323c18b204 100644
--- a/phpBB/phpbb/notification/type/quote.php
+++ b/phpBB/phpbb/notification/type/quote.php
@@ -21,6 +21,11 @@ namespace phpbb\notification\type;
class quote extends \phpbb\notification\type\post
{
/**
+ * @var \phpbb\textformatter\utils_interface
+ */
+ protected $utils;
+
+ /**
* Get notification type name
*
* @return string
@@ -31,13 +36,6 @@ class quote extends \phpbb\notification\type\post
}
/**
- * regular expression to match to find usernames
- *
- * @var string
- */
- protected static $regular_expression_match = '#\[quote=&quot;(.+?)&quot;#';
-
- /**
* Language key used to output the text
*
* @var string
@@ -50,7 +48,7 @@ class quote extends \phpbb\notification\type\post
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_QUOTE',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
@@ -77,17 +75,16 @@ class quote extends \phpbb\notification\type\post
'ignore_users' => array(),
), $options);
- $usernames = false;
- preg_match_all(static::$regular_expression_match, $post['post_text'], $usernames);
+ $usernames = $this->utils->get_outermost_quote_authors($post['post_text']);
- if (empty($usernames[1]))
+ if (empty($usernames))
{
return array();
}
- $usernames[1] = array_unique($usernames[1]);
+ $usernames = array_unique($usernames);
- $usernames = array_map('utf8_clean_string', $usernames[1]);
+ $usernames = array_map('utf8_clean_string', $usernames);
$users = array();
@@ -109,32 +106,23 @@ class quote extends \phpbb\notification\type\post
* Update a notification
*
* @param array $post Data specific for this type that will be updated
+ * @return true
*/
public function update_notifications($post)
{
- $old_notifications = array();
- $sql = 'SELECT n.user_id
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
- WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
- AND n.item_id = ' . static::get_item_id($post) . '
- AND nt.notification_type_id = n.notification_type_id
- AND nt.notification_type_enabled = 1';
- $result = $this->db->sql_query($sql);
- while ($row = $this->db->sql_fetchrow($result))
- {
- $old_notifications[] = $row['user_id'];
- }
- $this->db->sql_freeresult($result);
+ $old_notifications = $this->notification_manager->get_notified_users($this->get_type(), array(
+ 'item_id' => static::get_item_id($post),
+ ));
// Find the new users to notify
$notifications = $this->find_users_for_notification($post);
// Find the notifications we must delete
- $remove_notifications = array_diff($old_notifications, array_keys($notifications));
+ $remove_notifications = array_diff(array_keys($old_notifications), array_keys($notifications));
// Find the notifications we must add
$add_notifications = array();
- foreach (array_diff(array_keys($notifications), $old_notifications) as $user_id)
+ foreach (array_diff(array_keys($notifications), array_keys($old_notifications)) as $user_id)
{
$add_notifications[$user_id] = $notifications[$user_id];
}
@@ -145,11 +133,7 @@ class quote extends \phpbb\notification\type\post
// Remove the necessary notifications
if (!empty($remove_notifications))
{
- $sql = 'DELETE FROM ' . $this->notifications_table . '
- WHERE notification_type_id = ' . (int) $this->notification_type_id . '
- AND item_id = ' . static::get_item_id($post) . '
- AND ' . $this->db->sql_in_set('user_id', $remove_notifications);
- $this->db->sql_query($sql);
+ $this->notification_manager->delete_notifications($this->get_type(), static::get_item_id($post), false, $remove_notifications);
}
// return true to continue with the update code in the notifications service (this will update the rest of the notifications)
@@ -187,4 +171,14 @@ class quote extends \phpbb\notification\type\post
'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
));
}
+
+ /**
+ * Set the utils service used to retrieve quote authors
+ *
+ * @param \phpbb\textformatter\utils_interface $utils
+ */
+ public function set_utils(\phpbb\textformatter\utils_interface $utils)
+ {
+ $this->utils = $utils;
+ }
}
diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php
index cc32984ac6..239805204c 100644
--- a/phpBB/phpbb/notification/type/report_pm.php
+++ b/phpBB/phpbb/notification/type/report_pm.php
@@ -60,7 +60,7 @@ class report_pm extends \phpbb\notification\type\pm
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'notification.type.report',
'lang' => 'NOTIFICATION_TYPE_REPORT',
'group' => 'NOTIFICATION_GROUP_MODERATION',
@@ -70,8 +70,9 @@ class report_pm extends \phpbb\notification\type\pm
* Get the id of the parent
*
* @param array $pm The data from the pm
+ * @return int The report id
*/
- public static function get_item_parent_id($pm)
+ static public function get_item_parent_id($pm)
{
return (int) $pm['report_id'];
}
@@ -141,11 +142,13 @@ class report_pm extends \phpbb\notification\type\pm
*/
public function get_email_template_variables()
{
+ $user_data = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
+
return array(
- 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
- 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
+ '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}&amp;i=pm_reports&amp;mode=pm_report_details",
+ 'U_VIEW_REPORT' => generate_board_url() . "mcp.{$this->php_ext}?r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details",
);
}
@@ -166,11 +169,11 @@ class report_pm extends \phpbb\notification\type\pm
*/
public function get_title()
{
- $this->user->add_lang('mcp');
+ $this->language->add_lang('mcp');
$username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -183,7 +186,7 @@ class report_pm extends \phpbb\notification\type\pm
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('message_subject'))
);
@@ -198,21 +201,21 @@ class report_pm extends \phpbb\notification\type\pm
{
if ($this->get_data('report_text'))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('report_text')
);
}
- if (isset($this->user->lang[$this->get_data('reason_title')]))
+ if ($this->language->is_set($this->get_data('reason_title')))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
- $this->user->lang[$this->get_data('reason_title')]
+ $this->language->lang($this->get_data('reason_title'))
);
}
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('reason_description')
);
@@ -237,13 +240,7 @@ class report_pm extends \phpbb\notification\type\pm
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
@@ -252,6 +249,6 @@ class report_pm extends \phpbb\notification\type\pm
$this->set_data('reason_description', $post['reason_description']);
$this->set_data('report_text', $post['report_text']);
- return parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
}
}
diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php
index 1c99db60c3..5e98eb5feb 100644
--- a/phpBB/phpbb/notification/type/report_pm_closed.php
+++ b/phpBB/phpbb/notification/type/report_pm_closed.php
@@ -64,7 +64,7 @@ class report_pm_closed extends \phpbb\notification\type\pm
return array();
}
- return array($pm['reporter'] => array(''));
+ return array($pm['reporter'] => $this->notification_manager->get_default_methods());
}
/**
@@ -106,7 +106,7 @@ class report_pm_closed extends \phpbb\notification\type\pm
{
$username = $this->user_loader->get_username($this->get_data('closer_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -119,7 +119,7 @@ class report_pm_closed extends \phpbb\notification\type\pm
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('message_subject'))
);
@@ -144,21 +144,24 @@ class report_pm_closed extends \phpbb\notification\type\pm
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $pm PM Data
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($pm, $pre_create_data = array())
{
$this->set_data('closer_id', $pm['closer_id']);
- $data = parent::create_insert_array($pm, $pre_create_data);
+ parent::create_insert_array($pm, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php
index aed31e8642..84a5241417 100644
--- a/phpBB/phpbb/notification/type/report_post.php
+++ b/phpBB/phpbb/notification/type/report_post.php
@@ -66,7 +66,7 @@ class report_post extends \phpbb\notification\type\post_in_queue
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id' and 'lang')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'notification.type.report',
'lang' => 'NOTIFICATION_TYPE_REPORT',
'group' => 'NOTIFICATION_GROUP_MODERATION',
@@ -139,11 +139,11 @@ class report_post extends \phpbb\notification\type\post_in_queue
*/
public function get_title()
{
- $this->user->add_lang('mcp');
+ $this->language->add_lang('mcp');
$username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -156,7 +156,7 @@ class report_post extends \phpbb\notification\type\post_in_queue
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('post_subject'))
);
@@ -171,21 +171,21 @@ class report_post extends \phpbb\notification\type\post_in_queue
{
if ($this->get_data('report_text'))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('report_text')
);
}
- if (isset($this->user->lang[$this->get_data('reason_title')]))
+ if ($this->language->is_set($this->get_data('reason_title')))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
- $this->user->lang[$this->get_data('reason_title')]
+ $this->language->lang($this->get_data('reason_title'))
);
}
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('reason_description')
);
@@ -210,13 +210,7 @@ class report_post extends \phpbb\notification\type\post_in_queue
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
@@ -225,6 +219,6 @@ class report_post extends \phpbb\notification\type\post_in_queue
$this->set_data('reason_description', $post['reason_description']);
$this->set_data('report_text', $post['report_text']);
- return parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
}
}
diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php
index 3f4378628b..165034d57e 100644
--- a/phpBB/phpbb/notification/type/report_post_closed.php
+++ b/phpBB/phpbb/notification/type/report_post_closed.php
@@ -71,7 +71,7 @@ class report_post_closed extends \phpbb\notification\type\post
return array();
}
- return array($post['reporter'] => array(''));
+ return array($post['reporter'] => $this->notification_manager->get_default_methods());
}
/**
@@ -113,7 +113,7 @@ class report_post_closed extends \phpbb\notification\type\post
{
$username = $this->user_loader->get_username($this->get_data('closer_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -126,7 +126,7 @@ class report_post_closed extends \phpbb\notification\type\post
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('post_subject'))
);
@@ -151,21 +151,24 @@ class report_post_closed extends \phpbb\notification\type\post
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
$this->set_data('closer_id', $post['closer_id']);
- $data = parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php
index fb08a9eee1..671c34fe96 100644
--- a/phpBB/phpbb/notification/type/topic.php
+++ b/phpBB/phpbb/notification/type/topic.php
@@ -50,11 +50,27 @@ class topic extends \phpbb\notification\type\base
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'lang' => 'NOTIFICATION_TYPE_TOPIC',
'group' => 'NOTIFICATION_GROUP_POSTING',
);
+ /** @var \phpbb\user_loader */
+ protected $user_loader;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ public function set_config(\phpbb\config\config $config)
+ {
+ $this->config = $config;
+ }
+
+ public function set_user_loader(\phpbb\user_loader $user_loader)
+ {
+ $this->user_loader = $user_loader;
+ }
+
/**
* Is available
*/
@@ -67,8 +83,9 @@ class topic extends \phpbb\notification\type\base
* Get the id of the item
*
* @param array $post The data from the post
+ * @return int The topic id
*/
- public static function get_item_id($post)
+ static public function get_item_id($post)
{
return (int) $post['topic_id'];
}
@@ -77,8 +94,9 @@ class topic extends \phpbb\notification\type\base
* Get the id of the parent
*
* @param array $post The data from the post
+ * @return int The forum id
*/
- public static function get_item_parent_id($post)
+ static public function get_item_parent_id($post)
{
return (int) $post['forum_id'];
}
@@ -138,7 +156,7 @@ class topic extends \phpbb\notification\type\base
$username = $this->user_loader->get_username($this->get_data('poster_id'), 'no_profile');
}
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -151,7 +169,7 @@ class topic extends \phpbb\notification\type\base
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -164,7 +182,7 @@ class topic extends \phpbb\notification\type\base
*/
public function get_forum()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_FORUM',
$this->get_data('forum_name')
);
@@ -263,13 +281,7 @@ class topic extends \phpbb\notification\type\base
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $post Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($post, $pre_create_data = array())
{
@@ -290,6 +302,6 @@ class topic extends \phpbb\notification\type\base
$this->notification_read = true;
}
- return parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
}
}
diff --git a/phpBB/phpbb/notification/type/topic_in_queue.php b/phpBB/phpbb/notification/type/topic_in_queue.php
index 6e57b9ac0c..2d732b9cd7 100644
--- a/phpBB/phpbb/notification/type/topic_in_queue.php
+++ b/phpBB/phpbb/notification/type/topic_in_queue.php
@@ -43,7 +43,7 @@ class topic_in_queue extends \phpbb\notification\type\topic
* @var bool|array False if the service should use it's default data
* Array of data (including keys 'id', 'lang', and 'group')
*/
- public static $notification_option = array(
+ static public $notification_option = array(
'id' => 'notification.type.needs_approval',
'lang' => 'NOTIFICATION_TYPE_IN_MODERATION_QUEUE',
'group' => 'NOTIFICATION_GROUP_MODERATION',
@@ -123,19 +123,22 @@ class topic_in_queue extends \phpbb\notification\type\topic
}
/**
- * Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
- *
- * @param array $topic Data from submit_post
- * @param array $pre_create_data Data from pre_create_insert_array()
- *
- * @return array Array of data ready to be inserted into the database
+ * {@inheritdoc}
*/
public function create_insert_array($topic, $pre_create_data = array())
{
- $data = parent::create_insert_array($topic, $pre_create_data);
+ parent::create_insert_array($topic, $pre_create_data);
+
+ $this->notification_time = time();
+ }
- $this->notification_time = $data['notification_time'] = time();
+ /**
+ * {@inheritdoc}
+ */
+ public function get_insert_array()
+ {
+ $data = parent::get_insert_array();
+ $data['notification_time'] = $this->notification_time;
return $data;
}
diff --git a/phpBB/phpbb/notification/type/type_interface.php b/phpBB/phpbb/notification/type/type_interface.php
index 5c5a110836..f9f832bdda 100644
--- a/phpBB/phpbb/notification/type/type_interface.php
+++ b/phpBB/phpbb/notification/type/type_interface.php
@@ -37,14 +37,14 @@ interface type_interface
*
* @param array $type_data The type specific data
*/
- public static function get_item_id($type_data);
+ static public function get_item_id($type_data);
/**
* Get the id of the parent
*
* @param array $type_data The type specific data
*/
- public static function get_item_parent_id($type_data);
+ static public function get_item_parent_id($type_data);
/**
* Is this type available to the current user (defines whether or not it will be shown in the UCP Edit notification options)
@@ -177,14 +177,18 @@ interface type_interface
/**
* Function for preparing the data for insertion in an SQL query
- * (The service handles insertion)
*
* @param array $type_data The type specific data
* @param array $pre_create_data Data from pre_create_insert_array()
+ */
+ public function create_insert_array($type_data, $pre_create_data);
+
+ /**
+ * Function for getting the data for insertion in an SQL query
*
* @return array Array of data ready to be inserted into the database
*/
- public function create_insert_array($type_data, $pre_create_data);
+ public function get_insert_array();
/**
* Function for preparing the data for update in an SQL query
@@ -202,7 +206,7 @@ interface type_interface
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string
*/
- public function mark_read($return);
+ public function mark_read($return = false);
/**
* Mark this item unread
@@ -210,5 +214,5 @@ interface type_interface
* @param bool $return True to return a string containing the SQL code to update this item, False to execute it (Default: False)
* @return string
*/
- public function mark_unread($return);
+ public function mark_unread($return = false);
}
diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php
index aa9147ecf4..b2caba81f2 100644
--- a/phpBB/phpbb/passwords/manager.php
+++ b/phpBB/phpbb/passwords/manager.php
@@ -50,21 +50,47 @@ class manager
protected $config;
/**
+ * @var bool Whether or not initialized() has been called
+ */
+ private $initialized = false;
+
+ /**
+ * @var array Hashing driver service collection
+ */
+ private $hashing_algorithms;
+
+ /**
+ * @var array List of default driver types
+ */
+ private $defaults;
+
+ /**
* Construct a passwords object
*
- * @param \phpbb\config\config $config phpBB configuration
- * @param array $hashing_algorithms Hashing driver
- * service collection
- * @param \phpbb\passwords\helper $helper Passwords helper object
- * @param array $defaults List of default driver types
+ * @param \phpbb\config\config $config phpBB configuration
+ * @param array $hashing_algorithms Hashing driver service collection
+ * @param \phpbb\passwords\helper $helper Passwords helper object
+ * @param array $defaults List of default driver types
*/
public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults)
{
$this->config = $config;
$this->helper = $helper;
+ $this->hashing_algorithms = $hashing_algorithms;
+ $this->defaults = $defaults;
+ }
- $this->fill_type_map($hashing_algorithms);
- $this->register_default_type($defaults);
+ /**
+ * Initialize the internal state
+ */
+ protected function initialize()
+ {
+ if (!$this->initialized)
+ {
+ $this->initialized = true;
+ $this->fill_type_map($this->hashing_algorithms);
+ $this->register_default_type($this->defaults);
+ }
}
/**
@@ -144,6 +170,8 @@ class manager
return false;
}
+ $this->initialize();
+
// Be on the lookout for multiple hashing algorithms
// 2 is correct: H\2a > 2, H\P > 2
if (strlen($match[1]) > 2)
@@ -192,6 +220,8 @@ class manager
return false;
}
+ $this->initialize();
+
// Try to retrieve algorithm by service name if type doesn't
// start with dollar sign
if (!is_array($type) && strpos($type, '$') !== 0 && isset($this->algorithms[$type]))
@@ -242,6 +272,8 @@ class manager
return false;
}
+ $this->initialize();
+
// First find out what kind of hash we're dealing with
$stored_hash_type = $this->detect_algorithm($hash);
if ($stored_hash_type == false)
@@ -297,6 +329,8 @@ class manager
*/
public function combined_hash_password($password_hash, $type)
{
+ $this->initialize();
+
$data = array(
'prefix' => '$',
'settings' => '$',
diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php
index 5400c1c5a6..154361ef64 100644
--- a/phpBB/phpbb/path_helper.php
+++ b/phpBB/phpbb/path_helper.php
@@ -21,7 +21,7 @@ class path_helper
/** @var \phpbb\symfony_request */
protected $symfony_request;
- /** @var \phpbb\filesystem */
+ /** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
/** @var \phpbb\request\request_interface */
@@ -43,13 +43,13 @@ class path_helper
* Constructor
*
* @param \phpbb\symfony_request $symfony_request
- * @param \phpbb\filesystem $filesystem
+ * @param \phpbb\filesystem\filesystem_interface $filesystem
* @param \phpbb\request\request_interface $request
* @param string $phpbb_root_path Relative path to phpBB root
* @param string $php_ext PHP file extension
* @param mixed $adm_relative_path Relative path admin path to adm/ root
*/
- public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null)
+ public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null)
{
$this->symfony_request = $symfony_request;
$this->filesystem = $filesystem;
@@ -100,11 +100,18 @@ class path_helper
*/
public function update_web_root_path($path)
{
+ $web_root_path = $this->get_web_root_path();
+
+ // Removes the web root path if it is already present
+ if (strpos($path, $web_root_path) === 0)
+ {
+ $path = $this->phpbb_root_path . substr($path, strlen($web_root_path));
+ }
+
if (strpos($path, $this->phpbb_root_path) === 0)
{
$path = substr($path, strlen($this->phpbb_root_path));
- $web_root_path = $this->get_web_root_path();
if (substr($web_root_path, -8) === 'app.php/' && substr($path, 0, 7) === 'app.php')
{
$path = substr($path, 8);
diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php
index e75476f59b..c9181e6202 100644
--- a/phpBB/phpbb/permissions.php
+++ b/phpBB/phpbb/permissions.php
@@ -273,6 +273,7 @@ class permissions
'f_post' => array('lang' => 'ACL_F_POST', 'cat' => 'post'),
'f_sticky' => array('lang' => 'ACL_F_STICKY', 'cat' => 'post'),
'f_announce' => array('lang' => 'ACL_F_ANNOUNCE', 'cat' => 'post'),
+ 'f_announce_global' => array('lang' => 'ACL_F_ANNOUNCE_GLOBAL', 'cat' => 'post'),
'f_reply' => array('lang' => 'ACL_F_REPLY', 'cat' => 'post'),
'f_edit' => array('lang' => 'ACL_F_EDIT', 'cat' => 'post'),
'f_delete' => array('lang' => 'ACL_F_DELETE', 'cat' => 'post'),
diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php
index 7f6267ed32..a47fc87adf 100644
--- a/phpBB/phpbb/plupload/plupload.php
+++ b/phpBB/phpbb/plupload/plupload.php
@@ -39,7 +39,7 @@ class plupload
protected $user;
/**
- * @var \phpbb\php\ini
+ * @var \bantu\IniGetWrapper\IniGetWrapper
*/
protected $php_ini;
@@ -67,10 +67,10 @@ class plupload
* @param \phpbb\config\config $config
* @param \phpbb\request\request_interface $request
* @param \phpbb\user $user
- * @param \phpbb\php\ini $php_ini
+ * @param \bantu\IniGetWrapper\IniGetWrapper $php_ini
* @param \phpbb\mimetype\guesser $mimetype_guesser
*/
- public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \phpbb\php\ini $php_ini, \phpbb\mimetype\guesser $mimetype_guesser)
+ public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \phpbb\mimetype\guesser $mimetype_guesser)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->config = $config;
@@ -284,9 +284,9 @@ class plupload
public function get_chunk_size()
{
$max = min(
- $this->php_ini->get_bytes('upload_max_filesize'),
- $this->php_ini->get_bytes('post_max_size'),
- max(1, $this->php_ini->get_bytes('memory_limit')),
+ $this->php_ini->getBytes('upload_max_filesize'),
+ $this->php_ini->getBytes('post_max_size'),
+ max(1, $this->php_ini->getBytes('memory_limit')),
$this->config['max_filesize']
);
@@ -303,7 +303,7 @@ class plupload
$this->temporary_directory,
$this->config['plupload_salt'],
md5($file_name),
- \filespec::get_extension($file_name)
+ \phpbb\files\filespec::get_extension($file_name)
);
}
diff --git a/phpBB/phpbb/profilefields/type/type_date.php b/phpBB/phpbb/profilefields/type/type_date.php
index 90ac9a6703..414484920b 100644
--- a/phpBB/phpbb/profilefields/type/type_date.php
+++ b/phpBB/phpbb/profilefields/type/type_date.php
@@ -72,7 +72,7 @@ class type_date extends type_base
'lang_options' => $field_data['lang_options'],
);
- $always_now = request_var('always_now', -1);
+ $always_now = $request->variable('always_now', -1);
if ($always_now == -1)
{
$s_checked = ($field_data['field_default_value'] == 'now') ? true : false;
diff --git a/phpBB/phpbb/report/controller/report.php b/phpBB/phpbb/report/controller/report.php
new file mode 100644
index 0000000000..e1c14afde0
--- /dev/null
+++ b/phpBB/phpbb/report/controller/report.php
@@ -0,0 +1,319 @@
+<?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\report\controller;
+
+use phpbb\exception\http_exception;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+
+class report
+{
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * @var \phpbb\controller\helper
+ */
+ protected $helper;
+
+ /**
+ * @var \phpbb\request\request_interface
+ */
+ protected $request;
+
+ /**
+ * @var \phpbb\captcha\factory
+ */
+ protected $captcha_factory;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var \phpbb\report\report_handler_interface
+ */
+ protected $report_handler;
+
+ /**
+ * @var \phpbb\report\report_reason_list_provider
+ */
+ protected $report_reason_provider;
+
+ public function __construct(\phpbb\config\config $config, \phpbb\user $user, \phpbb\template\template $template, \phpbb\controller\helper $helper, \phpbb\request\request_interface $request, \phpbb\captcha\factory $captcha_factory, \phpbb\report\handler_factory $report_factory, \phpbb\report\report_reason_list_provider $ui_provider, $phpbb_root_path, $php_ext)
+ {
+ $this->config = $config;
+ $this->user = $user;
+ $this->template = $template;
+ $this->helper = $helper;
+ $this->request = $request;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->captcha_factory = $captcha_factory;
+ $this->report_handler = $report_factory;
+
+ // User interface factory
+ $this->report_reason_provider = $ui_provider;
+ }
+
+ /**
+ * Controller for /path_to_entities/{id}/report routes
+ *
+ * Because of how phpBB organizes routes $mode must be set in the route config.
+ *
+ * @param int $id ID of the entity to report
+ * @param string $mode
+ * @return \Symfony\Component\HttpFoundation\Response a Symfony response object
+ * @throws \phpbb\exception\http_exception when $mode or $id is invalid for some reason
+ */
+ public function handle($id, $mode)
+ {
+ // Get report handler
+ $this->report_handler = $this->report_handler->get_instance($mode);
+
+ $this->user->add_lang('mcp');
+
+ $user_notify = ($this->user->data['is_registered']) ? $this->request->variable('notify', 0) : false;
+ $reason_id = $this->request->variable('reason_id', 0);
+ $report_text = $this->request->variable('report_text', '', true);
+
+ $submit = $this->request->variable('submit', '');
+ $cancel = $this->request->variable('cancel', '');
+
+ $error = array();
+ $s_hidden_fields = '';
+
+ $redirect_url = append_sid(
+ $this->phpbb_root_path . ( ($mode === 'pm') ? 'ucp' : 'viewtopic' ) . ".{$this->php_ext}",
+ ($mode == 'pm') ? "i=pm&mode=view&p=$id" : "p=$id"
+ );
+ $redirect_url .= ($mode === 'post') ? "#p$id" : '';
+
+ // Set up CAPTCHA if necessary
+ if ($this->config['enable_post_confirm'] && !$this->user->data['is_registered'])
+ {
+ $captcha = $this->captcha_factory->get_instance($this->config['captcha_plugin']);
+ $captcha->init(CONFIRM_REPORT);
+ }
+
+ //Has the report been cancelled?
+ if (!empty($cancel))
+ {
+ return new RedirectResponse($redirect_url, 302);
+ }
+
+ // Check CAPTCHA, if the form was submited
+ if (!empty($submit) && isset($captcha))
+ {
+ $captcha_template_array = $this->check_captcha($captcha);
+ $error = $captcha_template_array['error'];
+ $s_hidden_fields = $captcha_template_array['hidden_fields'];
+ }
+
+ // Handle request
+ try
+ {
+ if (!empty($submit) && sizeof($error) === 0)
+ {
+ $this->report_handler->add_report(
+ (int) $id,
+ (int) $reason_id,
+ (string) $report_text,
+ (int) $user_notify
+ );
+
+ // Send success message
+ switch ($mode)
+ {
+ case 'pm':
+ $lang_return = $this->user->lang['RETURN_PM'];
+ $lang_success = $this->user->lang['PM_REPORTED_SUCCESS'];
+ break;
+ case 'post':
+ $lang_return = $this->user->lang['RETURN_TOPIC'];
+ $lang_success = $this->user->lang['POST_REPORTED_SUCCESS'];
+ break;
+ }
+
+ $this->helper->assign_meta_refresh_var(3, $redirect_url);
+ $message = $lang_success . '<br /><br />' . sprintf($lang_return, '<a href="' . $redirect_url . '">', '</a>');
+ return $this->helper->message($message);
+ }
+ else
+ {
+ $this->report_handler->validate_report_request($id);
+ }
+ }
+ catch (\phpbb\report\exception\pm_reporting_disabled_exception $exception)
+ {
+ throw new http_exception(404, 'PAGE_NOT_FOUND');
+ }
+ catch (\phpbb\report\exception\already_reported_exception $exception)
+ {
+ switch ($mode)
+ {
+ case 'pm':
+ $message = $this->user->lang['ALREADY_REPORTED_PM'];
+ $message .= '<br /><br />' . sprintf($this->user->lang['RETURN_PM'], '<a href="' . $redirect_url . '">', '</a>');
+ break;
+ case 'post':
+ $message = $this->user->lang['ALREADY_REPORTED'];
+ $message .= '<br /><br />' . sprintf($this->user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
+ break;
+ }
+
+ return $this->helper->message($message);
+ }
+ catch (\phpbb\report\exception\report_permission_denied_exception $exception)
+ {
+ $message = $exception->getMessage();
+ if (isset($this->user->lang[$message]))
+ {
+ $message = $this->user->lang[$message];
+ }
+
+ throw new http_exception(403, $message);
+ }
+ catch (\phpbb\report\exception\entity_not_found_exception $exception)
+ {
+ $message = $exception->getMessage();
+ if (isset($this->user->lang[$message]))
+ {
+ $message = $this->user->lang[$message];
+ }
+
+ throw new http_exception(404, $message);
+ }
+ catch (\phpbb\report\exception\empty_report_exception $exception)
+ {
+ $error[] = $this->user->lang['EMPTY_REPORT'];
+ }
+ catch (\phpbb\report\exception\invalid_report_exception $exception)
+ {
+ return $this->helper->message($exception->getMessage());
+ }
+
+ // Setting up an rendering template
+ $page_title = ($mode === 'pm') ? $this->user->lang['REPORT_MESSAGE'] : $this->user->lang['REPORT_POST'];
+ $this->assign_template_data(
+ $mode,
+ $id,
+ $reason_id,
+ $report_text,
+ $user_notify,
+ $error,
+ $s_hidden_fields,
+ ( isset($captcha) ? $captcha : false )
+ );
+
+ return $this->helper->render('report_body.html', $page_title);
+ }
+
+ /**
+ * Assigns template variables
+ *
+ * @param int $mode
+ * @param int $id
+ * @param int $reason_id
+ * @param string $report_text
+ * @param mixed $user_notify
+ * @param array $error
+ * @param string $s_hidden_fields
+ * @param mixed $captcha
+ * @return null
+ */
+ protected function assign_template_data($mode, $id, $reason_id, $report_text, $user_notify, $error = array(), $s_hidden_fields = '', $captcha = false)
+ {
+ if ($captcha !== false && $captcha->is_solved() === false)
+ {
+ $this->template->assign_vars(array(
+ 'S_CONFIRM_CODE' => true,
+ 'CAPTCHA_TEMPLATE' => $captcha->get_template(),
+ ));
+ }
+
+ $this->report_reason_provider->display_reasons($reason_id);
+
+ switch ($mode)
+ {
+ case 'pm':
+ $report_route = $this->helper->route('phpbb_report_pm_controller', array('id' => $id));
+ break;
+ case 'post':
+ $report_route = $this->helper->route('phpbb_report_post_controller', array('id' => $id));
+ break;
+ }
+
+ $this->template->assign_vars(array(
+ 'ERROR' => (sizeof($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,
+ 'S_REPORT_ACTION' => $report_route,
+
+ 'S_NOTIFY' => $user_notify,
+ 'S_CAN_NOTIFY' => ($this->user->data['is_registered']) ? true : false,
+ 'S_IN_REPORT' => true,
+ ));
+ }
+
+ /**
+ * Check CAPTCHA
+ *
+ * @param object $captcha A phpBB CAPTCHA object
+ * @return array template variables which ensures that CAPTCHA's work correctly
+ */
+ protected function check_captcha($captcha)
+ {
+ $error = array();
+ $captcha_hidden_fields = '';
+
+ $visual_confirmation_response = $captcha->validate();
+ if ($visual_confirmation_response)
+ {
+ $error[] = $visual_confirmation_response;
+ }
+
+ if (sizeof($error) === 0)
+ {
+ $captcha->reset();
+ }
+ else if ($captcha->is_solved() !== false)
+ {
+ $captcha_hidden_fields = build_hidden_fields($captcha->get_hidden_fields());
+ }
+
+ return array(
+ 'error' => $error,
+ 'hidden_fields' => $captcha_hidden_fields,
+ );
+ }
+}
diff --git a/phpBB/phpbb/report/exception/already_reported_exception.php b/phpBB/phpbb/report/exception/already_reported_exception.php
new file mode 100644
index 0000000000..54174044fe
--- /dev/null
+++ b/phpBB/phpbb/report/exception/already_reported_exception.php
@@ -0,0 +1,19 @@
+<?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\report\exception;
+
+class already_reported_exception extends invalid_report_exception
+{
+
+}
diff --git a/phpBB/phpbb/report/exception/empty_report_exception.php b/phpBB/phpbb/report/exception/empty_report_exception.php
new file mode 100644
index 0000000000..8c968dca80
--- /dev/null
+++ b/phpBB/phpbb/report/exception/empty_report_exception.php
@@ -0,0 +1,22 @@
+<?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\report\exception;
+
+class empty_report_exception extends invalid_report_exception
+{
+ public function __construct()
+ {
+ parent::__construct('EMPTY_REPORT');
+ }
+}
diff --git a/phpBB/phpbb/report/exception/entity_not_found_exception.php b/phpBB/phpbb/report/exception/entity_not_found_exception.php
new file mode 100644
index 0000000000..732aa58a13
--- /dev/null
+++ b/phpBB/phpbb/report/exception/entity_not_found_exception.php
@@ -0,0 +1,19 @@
+<?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\report\exception;
+
+class entity_not_found_exception extends invalid_report_exception
+{
+
+}
diff --git a/phpBB/phpbb/report/exception/factory_invalid_argument_exception.php b/phpBB/phpbb/report/exception/factory_invalid_argument_exception.php
new file mode 100644
index 0000000000..19de91eea3
--- /dev/null
+++ b/phpBB/phpbb/report/exception/factory_invalid_argument_exception.php
@@ -0,0 +1,21 @@
+<?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\report\exception;
+
+use \phpbb\exception\runtime_exception;
+
+class factory_invalid_argument_exception extends runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/report/exception/invalid_report_exception.php b/phpBB/phpbb/report/exception/invalid_report_exception.php
new file mode 100644
index 0000000000..03ff0a872d
--- /dev/null
+++ b/phpBB/phpbb/report/exception/invalid_report_exception.php
@@ -0,0 +1,21 @@
+<?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\report\exception;
+
+use \phpbb\exception\runtime_exception;
+
+class invalid_report_exception extends runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php b/phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php
new file mode 100644
index 0000000000..2c8ab8cf84
--- /dev/null
+++ b/phpBB/phpbb/report/exception/pm_reporting_disabled_exception.php
@@ -0,0 +1,22 @@
+<?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\report\exception;
+
+class pm_reporting_disabled_exception extends invalid_report_exception
+{
+ public function __construct()
+ {
+
+ }
+}
diff --git a/phpBB/phpbb/report/exception/report_permission_denied_exception.php b/phpBB/phpbb/report/exception/report_permission_denied_exception.php
new file mode 100644
index 0000000000..c7069288b8
--- /dev/null
+++ b/phpBB/phpbb/report/exception/report_permission_denied_exception.php
@@ -0,0 +1,19 @@
+<?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\report\exception;
+
+class report_permission_denied_exception extends invalid_report_exception
+{
+
+}
diff --git a/phpBB/phpbb/report/handler_factory.php b/phpBB/phpbb/report/handler_factory.php
new file mode 100644
index 0000000000..ec229aac54
--- /dev/null
+++ b/phpBB/phpbb/report/handler_factory.php
@@ -0,0 +1,56 @@
+<?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\report;
+
+use phpbb\report\exception\factory_invalid_argument_exception;
+
+class handler_factory
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * Constructor
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+ */
+ public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * Return a new instance of an appropriate report handler
+ *
+ * @param string $type
+ * @return \phpbb\report\report_handler_interface
+ * @throws \phpbb\report\exception\factory_invalid_argument_exception if $type is not valid
+ */
+ public function get_instance($type)
+ {
+ switch ($type)
+ {
+ case 'pm':
+ return $this->container->get('phpbb.report.handlers.report_handler_pm');
+ break;
+ case 'post':
+ return $this->container->get('phpbb.report.handlers.report_handler_post');
+ break;
+ }
+
+ throw new factory_invalid_argument_exception();
+ }
+}
diff --git a/phpBB/phpbb/report/report_handler.php b/phpBB/phpbb/report/report_handler.php
new file mode 100644
index 0000000000..854318c559
--- /dev/null
+++ b/phpBB/phpbb/report/report_handler.php
@@ -0,0 +1,104 @@
+<?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\report;
+
+abstract class report_handler implements report_handler_interface
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\event\dispatcher_interface
+ */
+ protected $dispatcher;
+
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\auth\auth
+ */
+ protected $auth;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * @var \phpbb\notification\manager
+ */
+ protected $notifications;
+
+ /**
+ * @var array
+ */
+ protected $report_data;
+
+ /**
+ * Construtor
+ *
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\event\dispatcher_interface $dispatcher
+ * @param \phpbb\config\db $config
+ * @param \phpbb\auth\auth $auth
+ * @param \phpbb\user $user
+ * @param \phpbb\notification\manager $notification
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\config\config $config, \phpbb\auth\auth $auth, \phpbb\user $user, \phpbb\notification\manager $notification)
+ {
+ $this->db = $db;
+ $this->dispatcher = $dispatcher;
+ $this->config = $config;
+ $this->auth = $auth;
+ $this->user = $user;
+ $this->notifications = $notification;
+ $this->report_data = array();
+ }
+
+ /**
+ * Creates a report entity in the database
+ *
+ * @param array $report_data
+ * @return int the ID of the created entity
+ */
+ protected function create_report(array $report_data)
+ {
+ $sql_ary = array(
+ 'reason_id' => (int) $report_data['reason_id'],
+ 'post_id' => $report_data['post_id'],
+ 'pm_id' => $report_data['pm_id'],
+ 'user_id' => (int) $this->user->data['user_id'],
+ 'user_notify' => (int) $report_data['user_notify'],
+ 'report_closed' => 0,
+ 'report_time' => (int) time(),
+ 'report_text' => (string) $report_data['report_text'],
+ 'reported_post_text' => $report_data['reported_post_text'],
+ 'reported_post_uid' => $report_data['reported_post_uid'],
+ 'reported_post_bitfield' => $report_data['reported_post_bitfield'],
+ 'reported_post_enable_bbcode' => $report_data['reported_post_enable_bbcode'],
+ 'reported_post_enable_smilies' => $report_data['reported_post_enable_smilies'],
+ 'reported_post_enable_magic_url' => $report_data['reported_post_enable_magic_url'],
+ );
+
+ $sql = 'INSERT INTO ' . REPORTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
+ $this->db->sql_query($sql);
+
+ return $this->db->sql_nextid();
+ }
+}
diff --git a/phpBB/phpbb/report/report_handler_interface.php b/phpBB/phpbb/report/report_handler_interface.php
new file mode 100644
index 0000000000..8dafc392d0
--- /dev/null
+++ b/phpBB/phpbb/report/report_handler_interface.php
@@ -0,0 +1,43 @@
+<?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\report;
+
+interface report_handler_interface
+{
+ /**
+ * Reports a message
+ *
+ * @param int $id
+ * @param int $reason_id
+ * @param string $report_text
+ * @param int $user_notify
+ * @return null
+ * @throws \phpbb\report\exception\empty_report_exception when the given report is empty
+ * @throws \phpbb\report\exception\already_reported_exception when the entity is already reported
+ * @throws \phpbb\report\exception\entity_not_found_exception when the entity does not exist or the user does not have viewing permissions for it
+ * @throws \phpbb\report\exception\invalid_report_exception when the entity cannot be reported for some other reason
+ */
+ public function add_report($id, $reason_id, $report_text, $user_notify);
+
+ /**
+ * Checks if the message is reportable
+ *
+ * @param int $id
+ * @return null
+ * @throws \phpbb\report\exception\already_reported_exception when the entity is already reported
+ * @throws \phpbb\report\exception\entity_not_found_exception when the entity does not exist or the user does not have viewing permissions for it
+ * @throws \phpbb\report\exception\invalid_report_exception when the entity cannot be reported for some other reason
+ */
+ public function validate_report_request($id);
+}
diff --git a/phpBB/phpbb/report/report_handler_pm.php b/phpBB/phpbb/report/report_handler_pm.php
new file mode 100644
index 0000000000..2f2a697efc
--- /dev/null
+++ b/phpBB/phpbb/report/report_handler_pm.php
@@ -0,0 +1,137 @@
+<?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\report;
+
+use phpbb\report\exception\empty_report_exception;
+use phpbb\report\exception\already_reported_exception;
+use phpbb\report\exception\pm_reporting_disabled_exception;
+use phpbb\report\exception\entity_not_found_exception;
+
+class report_handler_pm extends report_handler
+{
+ /**
+ * {@inheritdoc}
+ * @throws \phpbb\report\exception\pm_reporting_disabled_exception when PM reporting is disabled on the board
+ */
+ public function add_report($id, $reason_id, $report_text, $user_notify)
+ {
+ // Cast the input variables
+ $id = (int) $id;
+ $reason_id = (int) $reason_id;
+ $report_text = (string) $report_text;
+ $user_notify = (int) $user_notify;
+
+ $this->validate_report_request($id);
+
+ $sql = 'SELECT *
+ FROM ' . REPORTS_REASONS_TABLE . "
+ WHERE reason_id = $reason_id";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row || (empty($report_text) && strtolower($row['reason_title']) === 'other'))
+ {
+ throw new empty_report_exception();
+ }
+
+ $report_data = array(
+ 'reason_id' => $reason_id,
+ 'post_id' => 0,
+ 'pm_id' => $id,
+ '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_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'],
+ );
+
+ $report_id = $this->create_report($report_data);
+
+ $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
+ SET message_reported = 1
+ WHERE msg_id = ' . $id;
+ $this->db->sql_query($sql);
+
+ $sql_ary = array(
+ 'msg_id' => $id,
+ 'user_id' => ANONYMOUS,
+ 'author_id' => (int) $this->report_data['author_id'],
+ 'pm_deleted' => 0,
+ 'pm_new' => 0,
+ 'pm_unread' => 0,
+ 'pm_replied' => 0,
+ 'pm_marked' => 0,
+ 'pm_forwarded' => 0,
+ 'folder_id' => PRIVMSGS_INBOX,
+ );
+
+ $sql = 'INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
+ $this->db->sql_query($sql);
+
+ $this->notifications->add_notifications('notification.type.report_pm', array_merge($this->report_data, $row, array(
+ 'report_text' => $report_text,
+ 'from_user_id' => $this->report_data['author_id'],
+ 'report_id' => $report_id,
+ )));
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws \phpbb\report\exception\pm_reporting_disabled_exception when PM reporting is disabled on the board
+ */
+ public function validate_report_request($id)
+ {
+ $id = (int) $id;
+
+ // Check if reporting PMs is enabled
+ if (!$this->config['allow_pm_report'])
+ {
+ throw new pm_reporting_disabled_exception();
+ }
+ else if ($id <= 0)
+ {
+ throw new entity_not_found_exception('NO_POST_SELECTED');
+ }
+
+ // Grab all relevant data
+ $sql = 'SELECT p.*, pt.*
+ FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . " pt
+ WHERE p.msg_id = $id
+ AND p.msg_id = pt.msg_id
+ AND (p.author_id = " . $this->user->data['user_id'] . "
+ OR pt.user_id = " . $this->user->data['user_id'] . ")";
+ $result = $this->db->sql_query($sql);
+ $report_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ // Check if message exists
+ if (!$report_data)
+ {
+ $this->user->add_lang('ucp');
+ throw new entity_not_found_exception('NO_MESSAGE');
+ }
+
+ // Check if message is already reported
+ if ($report_data['message_reported'])
+ {
+ throw new already_reported_exception();
+ }
+
+ $this->report_data = $report_data;
+ }
+}
diff --git a/phpBB/phpbb/report/report_handler_post.php b/phpBB/phpbb/report/report_handler_post.php
new file mode 100644
index 0000000000..5574a16dc0
--- /dev/null
+++ b/phpBB/phpbb/report/report_handler_post.php
@@ -0,0 +1,175 @@
+<?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\report;
+
+use phpbb\report\exception\invalid_report_exception;
+use phpbb\report\exception\empty_report_exception;
+use phpbb\report\exception\already_reported_exception;
+use phpbb\report\exception\entity_not_found_exception;
+use phpbb\report\exception\report_permission_denied_exception;
+
+class report_handler_post extends report_handler
+{
+ /**
+ * @var array
+ */
+ protected $forum_data;
+
+ /**
+ * {@inheritdoc}
+ * @throws \phpbb\report\exception\report_permission_denied_exception when the user does not have permission to report the post
+ */
+ public function add_report($id, $reason_id, $report_text, $user_notify)
+ {
+ // Cast the input variables
+ $id = (int) $id;
+ $reason_id = (int) $reason_id;
+ $report_text = (string) $report_text;
+ $user_notify = (int) $user_notify;
+
+ $this->validate_report_request($id);
+
+ $sql = 'SELECT *
+ FROM ' . REPORTS_REASONS_TABLE . "
+ WHERE reason_id = $reason_id";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row || (empty($report_text) && strtolower($row['reason_title']) === 'other'))
+ {
+ throw new empty_report_exception();
+ }
+
+ $report_data = array(
+ 'reason_id' => $reason_id,
+ 'post_id' => $id,
+ 'pm_id' => 0,
+ '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_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'],
+ );
+
+ $this->create_report($report_data);
+
+ $sql = 'UPDATE ' . POSTS_TABLE . '
+ SET post_reported = 1
+ WHERE post_id = ' . $id;
+ $this->db->sql_query($sql);
+
+ if (!$this->report_data['topic_reported'])
+ {
+ $sql = 'UPDATE ' . TOPICS_TABLE . '
+ SET topic_reported = 1
+ WHERE topic_id = ' . $this->report_data['topic_id'] . '
+ OR topic_moved_id = ' . $this->report_data['topic_id'];
+ $this->db->sql_query($sql);
+ }
+
+ $this->notifications->add_notifications('notification.type.report_post', array_merge($this->report_data, $row, $this->forum_data, array(
+ 'report_text' => $report_text,
+ )));
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws \phpbb\report\exception\report_permission_denied_exception when the user does not have permission to report the post
+ */
+ public function validate_report_request($id)
+ {
+ $id = (int) $id;
+
+ // Check if id is valid
+ if ($id <= 0)
+ {
+ throw new entity_not_found_exception('NO_POST_SELECTED');
+ }
+
+ // Grab all relevant data
+ $sql = 'SELECT t.*, p.*
+ FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
+ WHERE p.post_id = $id
+ AND p.topic_id = t.topic_id";
+ $result = $this->db->sql_query($sql);
+ $report_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$report_data)
+ {
+ throw new entity_not_found_exception('POST_NOT_EXIST');
+ }
+
+ $forum_id = (int) $report_data['forum_id'];
+
+ $sql = 'SELECT *
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $forum_id;
+ $result = $this->db->sql_query($sql);
+ $forum_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$forum_data)
+ {
+ throw new invalid_report_exception('FORUM_NOT_EXIST');
+ }
+
+ $acl_check_ary = array(
+ 'f_list' => 'POST_NOT_EXIST',
+ 'f_read' => 'USER_CANNOT_READ',
+ 'f_report' => 'USER_CANNOT_REPORT'
+ );
+
+ /**
+ * This event allows you to do extra auth checks and verify if the user
+ * has the required permissions
+ *
+ * @event core.report_post_auth
+ * @var array forum_data All data available from the forums table on this post's forum
+ * @var array report_data All data available from the topics and the posts tables on this post (and its topic)
+ * @var array acl_check_ary An array with the ACL to be tested. The evaluation is made in the same order as the array is sorted
+ * The key is the ACL name and the value is the language key for the error message.
+ * @since 3.1.3-RC1
+ */
+ $vars = array(
+ 'forum_data',
+ 'report_data',
+ 'acl_check_ary',
+ );
+ extract($this->dispatcher->trigger_event('core.report_post_auth', compact($vars)));
+
+ $this->auth->acl($this->user->data);
+
+ foreach ($acl_check_ary as $acl => $error)
+ {
+ if (!$this->auth->acl_get($acl, $forum_id))
+ {
+ throw new report_permission_denied_exception($error);
+ }
+ }
+ unset($acl_check_ary);
+
+ if ($report_data['post_reported'])
+ {
+ throw new already_reported_exception();
+ }
+
+ $this->report_data = $report_data;
+ $this->forum_data = $forum_data;
+ }
+}
diff --git a/phpBB/phpbb/report/report_reason_list_provider.php b/phpBB/phpbb/report/report_reason_list_provider.php
new file mode 100644
index 0000000000..388a61d577
--- /dev/null
+++ b/phpBB/phpbb/report/report_reason_list_provider.php
@@ -0,0 +1,78 @@
+<?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\report;
+
+class report_reason_list_provider
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\template\template $template
+ * @param \phpbb\user $user
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\template\template $template, \phpbb\user $user)
+ {
+ $this->db = $db;
+ $this->template = $template;
+ $this->user = $user;
+ }
+
+ /**
+ * Sets template variables to render report reasons select HTML input
+ *
+ * @param int $reason_id
+ * @return null
+ */
+ public function display_reasons($reason_id = 0)
+ {
+ $sql = 'SELECT *
+ FROM ' . REPORTS_REASONS_TABLE . '
+ ORDER BY reason_order ASC';
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // If the reason is defined within the language file, we will use the localized version, else just use the database entry...
+ if (isset($this->user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($this->user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]))
+ {
+ $row['reason_description'] = $this->user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])];
+ $row['reason_title'] = $this->user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])];
+ }
+
+ $this->template->assign_block_vars('reason', array(
+ 'ID' => $row['reason_id'],
+ 'TITLE' => $row['reason_title'],
+ 'DESCRIPTION' => $row['reason_description'],
+ 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false,
+ ));
+ }
+ $this->db->sql_freeresult($result);
+ }
+}
diff --git a/phpBB/phpbb/request/deactivated_super_global.php b/phpBB/phpbb/request/deactivated_super_global.php
index b6cad59be4..ab56240b14 100644
--- a/phpBB/phpbb/request/deactivated_super_global.php
+++ b/phpBB/phpbb/request/deactivated_super_global.php
@@ -56,7 +56,7 @@ class deactivated_super_global implements \ArrayAccess, \Countable, \IteratorAgg
$file = '';
$line = 0;
- $message = 'Illegal use of $' . $this->name . '. You must use the request class or request_var() to access input data. Found in %s on line %d. This error message was generated by deactivated_super_global.';
+ $message = 'Illegal use of $' . $this->name . '. You must use the request class to access input data. Found in %s on line %d. This error message was generated by deactivated_super_global.';
$backtrace = debug_backtrace();
if (isset($backtrace[1]))
diff --git a/phpBB/phpbb/request/type_cast_helper.php b/phpBB/phpbb/request/type_cast_helper.php
index bc654e6182..96e66950ca 100644
--- a/phpBB/phpbb/request/type_cast_helper.php
+++ b/phpBB/phpbb/request/type_cast_helper.php
@@ -172,7 +172,6 @@ class type_cast_helper implements \phpbb\request\type_cast_helper_interface
}
list($default_key, $default_value) = each($default);
- $value_type = gettype($default_value);
$key_type = gettype($default_key);
$_var = $var;
diff --git a/phpBB/phpbb/routing/file_locator.php b/phpBB/phpbb/routing/file_locator.php
new file mode 100644
index 0000000000..64efcc6c76
--- /dev/null
+++ b/phpBB/phpbb/routing/file_locator.php
@@ -0,0 +1,33 @@
+<?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\routing;
+
+use phpbb\filesystem\filesystem_interface;
+use Symfony\Component\Config\FileLocator;
+
+class file_locator extends FileLocator
+{
+ public function __construct(filesystem_interface $filesystem, $paths = [])
+ {
+ $paths = (array) $paths;
+ $absolute_paths = [];
+
+ foreach ($paths as $path)
+ {
+ $absolute_paths[] = $filesystem->realpath($path);
+ }
+
+ parent::__construct($absolute_paths);
+ }
+}
diff --git a/phpBB/phpbb/routing/helper.php b/phpBB/phpbb/routing/helper.php
new file mode 100644
index 0000000000..c15608dce5
--- /dev/null
+++ b/phpBB/phpbb/routing/helper.php
@@ -0,0 +1,162 @@
+<?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\routing;
+
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Routing\RequestContext;
+
+/**
+* Controller helper class, contains methods that do things for controllers
+*/
+class helper
+{
+ /**
+ * config object
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * phpBB router
+ * @var \phpbb\routing\router
+ */
+ protected $router;
+
+ /**
+ * @var \phpbb\symfony_request
+ */
+ protected $symfony_request;
+
+ /**
+ * @var \phpbb\request\request_interface
+ */
+ protected $request;
+
+ /**
+ * @var \phpbb\filesystem The filesystem object
+ */
+ protected $filesystem;
+
+ /**
+ * phpBB root path
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * PHP file extension
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\config\config $config Config object
+ * @param \phpbb\routing\router $router phpBB router
+ * @param \phpbb\symfony_request $symfony_request Symfony Request object
+ * @param \phpbb\request\request_interface $request phpBB request object
+ * @param \phpbb\filesystem\filesystem $filesystem The filesystem object
+ * @param string $phpbb_root_path phpBB root path
+ * @param string $php_ext PHP file extension
+ */
+ public function __construct(\phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem $filesystem, $phpbb_root_path, $php_ext)
+ {
+ $this->config = $config;
+ $this->router = $router;
+ $this->symfony_request = $symfony_request;
+ $this->request = $request;
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Generate a URL to a route
+ *
+ * @param string $route Name of the route to travel
+ * @param array $params String or array of additional url parameters
+ * @param bool $is_amp Is url using &amp; (true) or & (false)
+ * @param string|bool $session_id Possibility to use a custom session id instead of the global one
+ * @param bool|string $reference_type The type of reference to be generated (one of the constants)
+ * @return string The URL already passed through append_sid()
+ */
+ public function route($route, array $params = array(), $is_amp = true, $session_id = false, $reference_type = UrlGeneratorInterface::ABSOLUTE_PATH)
+ {
+ $anchor = '';
+ if (isset($params['#']))
+ {
+ $anchor = '#' . $params['#'];
+ unset($params['#']);
+ }
+
+ $context = new RequestContext();
+ $context->fromRequest($this->symfony_request);
+
+ if ($this->config['force_server_vars'])
+ {
+ $context->setHost($this->config['server_name']);
+ $context->setScheme(substr($this->config['server_protocol'], 0, -3));
+ $context->setHttpPort($this->config['server_port']);
+ $context->setHttpsPort($this->config['server_port']);
+ $context->setBaseUrl(rtrim($this->config['script_path'], '/'));
+ }
+
+ $script_name = $this->symfony_request->getScriptName();
+ $page_name = substr($script_name, -1, 1) == '/' ? '' : utf8_basename($script_name);
+
+ $base_url = $context->getBaseUrl();
+
+ // Append page name if base URL does not contain it
+ if (!empty($page_name) && strpos($base_url, '/' . $page_name) === false)
+ {
+ $base_url .= '/' . $page_name;
+ }
+
+ // If enable_mod_rewrite is false we need to replace the current front-end by app.php, otherwise we need to remove it.
+ $base_url = str_replace('/' . $page_name, empty($this->config['enable_mod_rewrite']) ? '/app.' . $this->php_ext : '', $base_url);
+
+ // We need to update the base url to move to the directory of the app.php file if the current script is not app.php
+ if ($page_name !== 'app.php' && !$this->config['force_server_vars'])
+ {
+ if (empty($this->config['enable_mod_rewrite']))
+ {
+ $base_url = str_replace('/app.' . $this->php_ext, '/' . $this->phpbb_root_path . 'app.' . $this->php_ext, $base_url);
+ }
+ else
+ {
+ $base_url .= preg_replace(get_preg_expression('path_remove_dot_trailing_slash'), '$2', $this->phpbb_root_path);
+ }
+ }
+
+ $base_url = $this->request->escape($this->filesystem->clean_path($base_url), true);
+
+ $context->setBaseUrl($base_url);
+
+ $this->router->setContext($context);
+ $route_url = $this->router->generate($route, $params, $reference_type);
+
+ if ($is_amp)
+ {
+ $route_url = str_replace(array('&amp;', '&'), array('&', '&amp;'), $route_url);
+ }
+
+ if ($reference_type === UrlGeneratorInterface::RELATIVE_PATH && empty($this->config['enable_mod_rewrite']))
+ {
+ $route_url = 'app.' . $this->php_ext . '/' . $route_url;
+ }
+
+ return append_sid($route_url . $anchor, false, $is_amp, $session_id, true);
+ }
+}
diff --git a/phpBB/phpbb/routing/loader_resolver.php b/phpBB/phpbb/routing/loader_resolver.php
new file mode 100644
index 0000000000..13fbc6405c
--- /dev/null
+++ b/phpBB/phpbb/routing/loader_resolver.php
@@ -0,0 +1,50 @@
+<?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\routing;
+
+use Symfony\Component\Config\Loader\LoaderResolverInterface;
+
+/**
+ * @see Symfony\Component\Config\Loader\LoaderResolver
+ */
+class loader_resolver implements LoaderResolverInterface
+{
+ /**
+ * @var \Symfony\Component\Config\Loader\LoaderInterface[] An array of LoaderInterface objects
+ */
+ protected $loaders = [];
+
+ public function __construct($loaders = [])
+ {
+ $this->loaders = $loaders;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve($resource, $type = null)
+ {
+ /** @var \Symfony\Component\Config\Loader\LoaderInterface $loader */
+ foreach ($this->loaders as $loader)
+ {
+ if ($loader->supports($resource, $type))
+ {
+ $loader->setResolver($this);
+ return $loader;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/routing/resources_locator/chained_resources_locator.php b/phpBB/phpbb/routing/resources_locator/chained_resources_locator.php
new file mode 100644
index 0000000000..db9abf2095
--- /dev/null
+++ b/phpBB/phpbb/routing/resources_locator/chained_resources_locator.php
@@ -0,0 +1,47 @@
+<?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\routing\resources_locator;
+
+class chained_resources_locator implements resources_locator_interface
+{
+ /**
+ * @var resources_locator_interface[]
+ */
+ protected $locators;
+
+ /**
+ * Construct method
+ *
+ * @param resources_locator_interface[] $locators Locators
+ */
+ public function __construct($locators)
+ {
+ $this->locators = $locators;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function locate_resources()
+ {
+ $resources = [];
+
+ foreach ($this->locators as $locator)
+ {
+ $resources = array_merge($resources, $locator->locate_resources());
+ }
+
+ return $resources;
+ }
+}
diff --git a/phpBB/phpbb/routing/resources_locator/default_resources_locator.php b/phpBB/phpbb/routing/resources_locator/default_resources_locator.php
new file mode 100644
index 0000000000..90c3877007
--- /dev/null
+++ b/phpBB/phpbb/routing/resources_locator/default_resources_locator.php
@@ -0,0 +1,105 @@
+<?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\routing\resources_locator;
+
+use phpbb\extension\manager;
+
+/**
+ * Locates the yaml routing resources located in the default locations
+ */
+class default_resources_locator implements resources_locator_interface
+{
+ /**
+ * phpBB root path
+ *
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Name of the current environment
+ *
+ * @var string
+ */
+ protected $environment;
+
+ /**
+ * Extension manager
+ *
+ * @var manager
+ */
+ protected $extension_manager;
+
+ /**
+ * Construct method
+ *
+ * @param string $phpbb_root_path phpBB root path
+ * @param string $environment Name of the current environment
+ * @param manager $extension_manager Extension manager
+ */
+ public function __construct($phpbb_root_path, $environment, manager $extension_manager = null)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->environment = $environment;
+ $this->extension_manager = $extension_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function locate_resources()
+ {
+ $resources = [['config/' . $this->environment . '/routing/environment.yml', 'yaml']];
+
+ $resources = $this->append_ext_resources($resources);
+
+ return $resources;
+ }
+
+ /**
+ * Append extension resources to an array of resouces
+ *
+ * @see resources_locator_interface::locate_resources()
+ *
+ * @param mixed[] $resources List of resources
+ *
+ * @return mixed[] List of resources
+ */
+ protected function append_ext_resources(array $resources)
+ {
+ if ($this->extension_manager !== null)
+ {
+ foreach ($this->extension_manager->all_enabled(false) as $path)
+ {
+ if (file_exists($this->phpbb_root_path . $path . 'config/' . $this->environment . '/routing/environment.yml'))
+ {
+ $resources[] = [$path . 'config/' . $this->environment . '/routing/environment.yml', 'yaml'];
+ }
+ else if (!is_dir($this->phpbb_root_path . $path . 'config/' . $this->environment))
+ {
+ if (file_exists($this->phpbb_root_path . $path . 'config/default/routing/environment.yml'))
+ {
+ $resources[] = [$path . 'config/default/routing/environment.yml', 'yaml'];
+ }
+ else if (!is_dir($this->phpbb_root_path . $path . 'config/default/routing') && file_exists($this->phpbb_root_path . $path . 'config/routing.yml'))
+ {
+ $resources[] = [$path . 'config/routing.yml', 'yaml'];
+ }
+ }
+ }
+ }
+
+ return $resources;
+ }
+}
diff --git a/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php b/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php
new file mode 100644
index 0000000000..42cd0f11af
--- /dev/null
+++ b/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php
@@ -0,0 +1,78 @@
+<?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\routing\resources_locator;
+
+use phpbb\filesystem\filesystem_interface;
+
+/**
+ * Locates the yaml routing resources taking update directories into consideration
+ */
+class installer_resources_locator implements resources_locator_interface
+{
+ /**
+ * phpBB's filesystem handler
+ *
+ * @var filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * phpBB root path
+ *
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Name of the current environment
+ *
+ * @var string
+ */
+ protected $environment;
+
+ /**
+ * Construct method
+ *
+ * @param filesystem_interface $filesystem phpBB's filesystem handler
+ * @param string $phpbb_root_path phpBB root path
+ * @param string $environment Name of the current environment
+ */
+ public function __construct(filesystem_interface $filesystem, $phpbb_root_path, $environment)
+ {
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->environment = $environment;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function locate_resources()
+ {
+ if ($this->filesystem->exists($this->phpbb_root_path . 'install/update/new/config'))
+ {
+ $resources = array(
+ array('install/update/new/config/' . $this->environment . '/routing/environment.yml', 'yaml')
+ );
+ }
+ else
+ {
+ $resources = array(
+ array('config/' . $this->environment . '/routing/environment.yml', 'yaml')
+ );
+ }
+
+ return $resources;
+ }
+}
diff --git a/phpBB/phpbb/routing/resources_locator/resources_locator_interface.php b/phpBB/phpbb/routing/resources_locator/resources_locator_interface.php
new file mode 100644
index 0000000000..46335cb288
--- /dev/null
+++ b/phpBB/phpbb/routing/resources_locator/resources_locator_interface.php
@@ -0,0 +1,27 @@
+<?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\routing\resources_locator;
+
+interface resources_locator_interface
+{
+ /**
+ * Locates a list of resources used to load the routes
+ *
+ * Each entry of the list can be either the resource or an array composed of 2 elements:
+ * the resource and its type.
+ *
+ * @return mixed[] List of resources
+ */
+ public function locate_resources();
+}
diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php
new file mode 100644
index 0000000000..f19886fb0b
--- /dev/null
+++ b/phpBB/phpbb/routing/router.php
@@ -0,0 +1,395 @@
+<?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\routing;
+
+use phpbb\routing\resources_locator\resources_locator_interface;
+use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\Filesystem\Exception\IOException;
+use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper;
+use Symfony\Component\Routing\Generator\UrlGenerator;
+use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\RouterInterface;
+
+/**
+ * Integration of all pieces of the routing system for easier use.
+ */
+class router implements RouterInterface
+{
+ /**
+ * @var ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * @var resources_locator_interface
+ */
+ protected $resources_locator;
+
+ /**
+ * @var LoaderInterface
+ */
+ protected $loader;
+
+ /**
+ * PHP file extensions
+ *
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|null
+ */
+ protected $matcher;
+
+ /**
+ * @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface|null
+ */
+ protected $generator;
+
+ /**
+ * @var RequestContext
+ */
+ protected $context;
+
+ /**
+ * @var RouteCollection
+ */
+ protected $route_collection;
+
+ /**
+ * @var string
+ */
+ protected $cache_dir;
+
+ /**
+ * Construct method
+ *
+ * @param ContainerInterface $container DI container
+ * @param resources_locator_interface $resources_locator Resources locator
+ * @param LoaderInterface $loader Resources loader
+ * @param string $php_ext PHP file extension
+ * @param string $cache_dir phpBB cache directory
+ */
+ public function __construct(ContainerInterface $container, resources_locator_interface $resources_locator, LoaderInterface $loader, $php_ext, $cache_dir)
+ {
+ $this->container = $container;
+ $this->resources_locator = $resources_locator;
+ $this->loader = $loader;
+ $this->php_ext = $php_ext;
+ $this->context = new RequestContext();
+ $this->cache_dir = $cache_dir;
+ }
+
+ /**
+ * Get the list of routes
+ *
+ * @return RouteCollection Get the route collection
+ */
+ public function get_routes()
+ {
+ if ($this->route_collection === null /*|| $this->route_collection->count() === 0*/)
+ {
+ $this->route_collection = new RouteCollection;
+ foreach ($this->resources_locator->locate_resources() as $resource)
+ {
+ if (is_array($resource))
+ {
+ $this->route_collection->addCollection($this->loader->load($resource[0], $resource[1]));
+ }
+ else
+ {
+ $this->route_collection->addCollection($this->loader->load($resource));
+ }
+ }
+
+ $this->resolveParameters($this->route_collection);
+ }
+
+ return $this->route_collection;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRouteCollection()
+ {
+ return $this->get_routes();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setContext(RequestContext $context)
+ {
+ $this->context = $context;
+
+ if ($this->matcher !== null)
+ {
+ $this->get_matcher()->setContext($context);
+ }
+ if ($this->generator !== null)
+ {
+ $this->get_generator()->setContext($context);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getContext()
+ {
+ return $this->context;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
+ {
+ return $this->get_generator()->generate($name, $parameters, $referenceType);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function match($pathinfo)
+ {
+ return $this->get_matcher()->match($pathinfo);
+ }
+
+ /**
+ * Gets the UrlMatcher instance associated with this Router.
+ *
+ * @return \Symfony\Component\Routing\Matcher\UrlMatcherInterface A UrlMatcherInterface instance
+ */
+ public function get_matcher()
+ {
+ if ($this->matcher !== null)
+ {
+ return $this->matcher;
+ }
+
+ $this->create_dumped_url_matcher();
+
+ return $this->matcher;
+ }
+
+ /**
+ * Creates a new dumped URL Matcher (dump it if necessary)
+ */
+ protected function create_dumped_url_matcher()
+ {
+ try
+ {
+ $cache = new ConfigCache("{$this->cache_dir}url_matcher.{$this->php_ext}", defined('DEBUG'));
+ if (!$cache->isFresh())
+ {
+ $dumper = new PhpMatcherDumper($this->get_routes());
+
+ $options = array(
+ 'class' => 'phpbb_url_matcher',
+ 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
+ );
+
+ $cache->write($dumper->dump($options), $this->get_routes()->getResources());
+ }
+
+ require_once($cache->getPath());
+
+ $this->matcher = new \phpbb_url_matcher($this->context);
+ }
+ catch (IOException $e)
+ {
+ $this->create_new_url_matcher();
+ }
+ }
+
+ /**
+ * Creates a new URL Matcher
+ */
+ protected function create_new_url_matcher()
+ {
+ $this->matcher = new UrlMatcher($this->get_routes(), $this->context);
+ }
+
+ /**
+ * Gets the UrlGenerator instance associated with this Router.
+ *
+ * @return \Symfony\Component\Routing\Generator\UrlGeneratorInterface A UrlGeneratorInterface instance
+ */
+ public function get_generator()
+ {
+ if ($this->generator !== null)
+ {
+ return $this->generator;
+ }
+
+ $this->create_dumped_url_generator();
+
+ return $this->generator;
+ }
+
+ /**
+ * Creates a new dumped URL Generator (dump it if necessary)
+ */
+ protected function create_dumped_url_generator()
+ {
+ try
+ {
+ $cache = new ConfigCache("{$this->cache_dir}url_generator.{$this->php_ext}", defined('DEBUG'));
+ if (!$cache->isFresh())
+ {
+ $dumper = new PhpGeneratorDumper($this->get_routes());
+
+ $options = array(
+ 'class' => 'phpbb_url_generator',
+ 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
+ );
+
+ $cache->write($dumper->dump($options), $this->get_routes()->getResources());
+ }
+
+ require_once($cache->getPath());
+
+ $this->generator = new \phpbb_url_generator($this->context);
+ }
+ catch (IOException $e)
+ {
+ $this->create_new_url_generator();
+ }
+ }
+
+ /**
+ * Creates a new URL Generator
+ */
+ protected function create_new_url_generator()
+ {
+ $this->generator = new UrlGenerator($this->get_routes(), $this->context);
+ }
+
+ /**
+ * Replaces placeholders with service container parameter values in:
+ * - the route defaults,
+ * - the route requirements,
+ * - the route path,
+ * - the route host,
+ * - the route schemes,
+ * - the route methods.
+ *
+ * @param RouteCollection $collection
+ */
+ protected function resolveParameters(RouteCollection $collection)
+ {
+ /** @var \Symfony\Component\Routing\Route $route */
+ foreach ($collection as $route)
+ {
+ foreach ($route->getDefaults() as $name => $value)
+ {
+ $route->setDefault($name, $this->resolve($value));
+ }
+
+ $requirements = $route->getRequirements();
+ unset($requirements['_scheme']);
+ unset($requirements['_method']);
+
+ foreach ($requirements as $name => $value)
+ {
+ $route->setRequirement($name, $this->resolve($value));
+ }
+
+ $route->setPath($this->resolve($route->getPath()));
+ $route->setHost($this->resolve($route->getHost()));
+
+ $schemes = array();
+ foreach ($route->getSchemes() as $scheme)
+ {
+ $schemes = array_merge($schemes, explode('|', $this->resolve($scheme)));
+ }
+
+ $route->setSchemes($schemes);
+ $methods = array();
+ foreach ($route->getMethods() as $method)
+ {
+ $methods = array_merge($methods, explode('|', $this->resolve($method)));
+ }
+
+ $route->setMethods($methods);
+ $route->setCondition($this->resolve($route->getCondition()));
+ }
+ }
+
+ /**
+ * Recursively replaces placeholders with the service container parameters.
+ *
+ * @param mixed $value The source which might contain "%placeholders%"
+ *
+ * @return mixed The source with the placeholders replaced by the container
+ * parameters. Arrays are resolved recursively.
+ *
+ * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter
+ * @throws RuntimeException When a container value is not a string or a numeric value
+ */
+ private function resolve($value)
+ {
+ if (is_array($value))
+ {
+ foreach ($value as $key => $val)
+ {
+ $value[$key] = $this->resolve($val);
+ }
+
+ return $value;
+ }
+
+ if (!is_string($value))
+ {
+ return $value;
+ }
+
+ $container = $this->container;
+ $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($container, $value)
+ {
+ // skip %%
+ if (!isset($match[1]))
+ {
+ return '%%';
+ }
+
+ $resolved = $container->getParameter($match[1]);
+ if (is_string($resolved) || is_numeric($resolved))
+ {
+ return (string) $resolved;
+ }
+
+ throw new RuntimeException(sprintf(
+ 'The container parameter "%s", used in the route configuration value "%s", '.
+ 'must be a string or numeric, but it is of type %s.',
+ $match[1],
+ $value,
+ gettype($resolved)
+ )
+ );
+ }, $value);
+
+ return str_replace('%%', '%', $escapedValue);
+ }
+}
diff --git a/phpBB/phpbb/search/base.php b/phpBB/phpbb/search/base.php
index d9313dddab..56de973b65 100644
--- a/phpBB/phpbb/search/base.php
+++ b/phpBB/phpbb/search/base.php
@@ -286,7 +286,7 @@ class base
$sql = 'DELETE
FROM ' . SEARCH_RESULTS_TABLE . '
- WHERE search_time < ' . (time() - $config['search_store_results']);
+ WHERE search_time < ' . (time() - (int) $config['search_store_results']);
$db->sql_query($sql);
}
}
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index 9faf5ca08b..73d7bc1574 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -198,8 +198,8 @@ class fulltext_mysql extends \phpbb\search\base
}
$this->db->sql_freeresult($result);
- set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']);
- set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']);
+ $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']);
return false;
}
@@ -921,7 +921,7 @@ class fulltext_mysql extends \phpbb\search\base
// destroy too old cached search results
$this->destroy_cache(array());
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index 63b0b24edf..2071a973e5 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -18,6 +18,13 @@ namespace phpbb\search;
*/
class fulltext_native extends \phpbb\search\base
{
+ const UTF8_HANGUL_FIRST = "\xEA\xB0\x80";
+ const UTF8_HANGUL_LAST = "\xED\x9E\xA3";
+ const UTF8_CJK_FIRST = "\xE4\xB8\x80";
+ const UTF8_CJK_LAST = "\xE9\xBE\xBB";
+ const UTF8_CJK_B_FIRST = "\xF0\xA0\x80\x80";
+ const UTF8_CJK_B_LAST = "\xF0\xAA\x9B\x96";
+
/**
* Associative array holding index stats
* @var array
@@ -99,7 +106,7 @@ class fulltext_native extends \phpbb\search\base
protected $user;
/**
- * Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded
+ * Initialises the fulltext_native search backend with min/max word length
*
* @param boolean|string &$error is passed by reference and should either be set to false on success or an error message on failure
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
@@ -118,10 +125,6 @@ class fulltext_native extends \phpbb\search\base
/**
* Load the UTF tools
*/
- if (!class_exists('utf_normalizer'))
- {
- include($this->phpbb_root_path . 'includes/utf/utf_normalizer.' . $this->php_ext);
- }
if (!function_exists('utf8_decode_ncr'))
{
include($this->phpbb_root_path . 'includes/utf/utf_tools.' . $this->php_ext);
@@ -349,9 +352,6 @@ class fulltext_native extends \phpbb\search\base
$this->must_not_contain_ids = array();
$this->must_exclude_one_ids = array();
- $mode = '';
- $ignore_no_id = true;
-
foreach ($query as $word)
{
if (empty($word))
@@ -594,7 +594,6 @@ class fulltext_native extends \phpbb\search\base
$id_ary = array();
$sql_where = array();
- $group_by = false;
$m_num = 0;
$w_num = 0;
@@ -879,7 +878,6 @@ class fulltext_native extends \phpbb\search\base
break;
- case 'sqlite':
case 'sqlite3':
$sql_array_count['SELECT'] = ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id';
$sql = 'SELECT COUNT(' . (($type == 'posts') ? 'post_id' : 'topic_id') . ') as total_results
@@ -1186,7 +1184,7 @@ class fulltext_native extends \phpbb\search\base
}
else
{
- if ($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3')
+ if ($this->db->get_sql_layer() == 'sqlite3')
{
$sql = 'SELECT COUNT(topic_id) as total_results
FROM (SELECT DISTINCT t.topic_id';
@@ -1203,7 +1201,7 @@ class fulltext_native extends \phpbb\search\base
$post_visibility
$sql_fora
AND t.topic_id = p.topic_id
- $sql_time" . (($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3') ? ')' : '');
+ $sql_time" . ($this->db->get_sql_layer() == 'sqlite3' ? ')' : '');
}
$result = $this->db->sql_query($sql);
@@ -1325,7 +1323,6 @@ class fulltext_native extends \phpbb\search\base
$match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#';
$min = $this->word_length['min'];
- $max = $this->word_length['max'];
$isset_min = $min - 1;
@@ -1361,9 +1358,9 @@ class fulltext_native extends \phpbb\search\base
* Note: this could be optimized. If the codepoint is lower than Hangul's range
* we know that it will also be lower than CJK ranges
*/
- if ((strncmp($word, UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, UTF8_HANGUL_LAST, 3) > 0)
- && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0)
- && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, UTF8_CJK_B_LAST, 4) > 0))
+ if ((strncmp($word, self::UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, self::UTF8_HANGUL_LAST, 3) > 0)
+ && (strncmp($word, self::UTF8_CJK_FIRST, 3) < 0 || strncmp($word, self::UTF8_CJK_LAST, 3) > 0)
+ && (strncmp($word, self::UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, self::UTF8_CJK_B_LAST, 4) > 0))
{
$word = strtok(' ');
continue;
@@ -1608,7 +1605,7 @@ class fulltext_native extends \phpbb\search\base
// carry on ... it's okay ... I know when I'm not wanted boo hoo
if (!$this->config['fulltext_native_load_upd'])
{
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
return;
}
@@ -1643,7 +1640,7 @@ class fulltext_native extends \phpbb\search\base
// by setting search_last_gc to the new time here we make sure that if a user reloads because the
// following query takes too long, he won't run into it again
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
// Delete the matches
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
@@ -1659,7 +1656,7 @@ class fulltext_native extends \phpbb\search\base
$this->destroy_cache(array_unique($destroy_cache_words));
}
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
@@ -1669,7 +1666,6 @@ class fulltext_native extends \phpbb\search\base
{
switch ($this->db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$this->db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE);
$this->db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE);
@@ -1730,13 +1726,11 @@ class fulltext_native extends \phpbb\search\base
* @param string $allowed_chars String of special chars to allow
* @param string $encoding Text encoding
* @return string Cleaned up text, only alphanumeric chars are left
- *
- * @todo \normalizer::cleanup being able to be used?
*/
protected function cleanup($text, $allowed_chars = null, $encoding = 'utf-8')
{
static $conv = array(), $conv_loaded = array();
- $words = $allow = array();
+ $allow = array();
// Convert the text to UTF-8
$encoding = strtolower($encoding);
@@ -1758,12 +1752,9 @@ class fulltext_native extends \phpbb\search\base
$text = htmlspecialchars_decode(utf8_decode_ncr($text), ENT_QUOTES);
/**
- * Load the UTF-8 normalizer
- *
- * If we use it more widely, an instance of that class should be held in a
- * a global variable instead
+ * Normalize to NFC
*/
- \utf_normalizer::nfc($text);
+ $text = \Normalizer::normalize($text);
/**
* The first thing we do is:
@@ -1856,9 +1847,9 @@ class fulltext_native extends \phpbb\search\base
$utf_char = substr($text, $pos, $utf_len);
$pos += $utf_len;
- if (($utf_char >= UTF8_HANGUL_FIRST && $utf_char <= UTF8_HANGUL_LAST)
- || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST)
- || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST))
+ if (($utf_char >= self::UTF8_HANGUL_FIRST && $utf_char <= self::UTF8_HANGUL_LAST)
+ || ($utf_char >= self::UTF8_CJK_FIRST && $utf_char <= self::UTF8_CJK_LAST)
+ || ($utf_char >= self::UTF8_CJK_B_FIRST && $utf_char <= self::UTF8_CJK_B_LAST))
{
/**
* All characters within these ranges are valid
diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php
index 04441e6226..8dbc7212a1 100644
--- a/phpBB/phpbb/search/fulltext_postgres.php
+++ b/phpBB/phpbb/search/fulltext_postgres.php
@@ -501,7 +501,6 @@ class fulltext_postgres extends \phpbb\search\base
$sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';
$sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : '';
$field = ($type == 'posts') ? 'post_id' : 'topic_id';
- $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')';
if (sizeof($author_ary) && $author_name)
{
@@ -526,7 +525,6 @@ class fulltext_postgres extends \phpbb\search\base
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_where_options .= $sql_match_where;
- $tmp_sql_match = array();
$sql_match = str_replace(',', " || ' ' ||", $sql_match);
$tmp_sql_match = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')";
@@ -838,7 +836,7 @@ class fulltext_postgres extends \phpbb\search\base
GROUP BY t.topic_id, $sort_by_sql[$sort_key]";
}
- $result = $this->db->sql_query($sql_count);
+ $this->db->sql_query($sql_count);
$result_count = (int) $this->db->sql_fetchfield('result_count');
if (!$result_count)
@@ -916,7 +914,7 @@ class fulltext_postgres extends \phpbb\search\base
// destroy too old cached search results
$this->destroy_cache(array());
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php
index 0dbc6e33df..89c615e087 100644
--- a/phpBB/phpbb/search/fulltext_sphinx.php
+++ b/phpBB/phpbb/search/fulltext_sphinx.php
@@ -85,7 +85,7 @@ class fulltext_sphinx
/**
* Database Tools object
- * @var \phpbb\db\tools
+ * @var \phpbb\db\tools\tools_interface
*/
protected $db_tools;
@@ -143,12 +143,13 @@ class fulltext_sphinx
$this->db = $db;
$this->auth = $auth;
- // Initialize \phpbb\db\tools object
- $this->db_tools = new \phpbb\db\tools($this->db);
+ // Initialize \phpbb\db\tools\tools object
+ global $phpbb_container; // TODO inject into object
+ $this->db_tools = $phpbb_container->get('dbal.tools');
if (!$this->config['fulltext_sphinx_id'])
{
- set_config('fulltext_sphinx_id', unique_id());
+ $this->config->set('fulltext_sphinx_id', unique_id());
}
$this->id = $this->config['fulltext_sphinx_id'];
$this->indexes = 'index_phpbb_' . $this->id . '_delta;index_phpbb_' . $this->id . '_main';
@@ -219,7 +220,7 @@ class fulltext_sphinx
}
// Move delta to main index each hour
- set_config('search_gc', 3600);
+ $this->config->set('search_gc', 3600);
return false;
}
@@ -403,7 +404,7 @@ class fulltext_sphinx
$variable = $section->get_variable_by_name($key);
if (!$variable)
{
- $variable = $section->create_variable($key, $value);
+ $section->create_variable($key, $value);
}
else
{
@@ -412,7 +413,7 @@ class fulltext_sphinx
}
else
{
- $variable = $section->create_variable($key, $value);
+ $section->create_variable($key, $value);
}
}
}
@@ -436,7 +437,6 @@ class fulltext_sphinx
$match = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#', '#@#');
$replace = array(' & ', ' | ', ' - ', ' +', ' -', ' |', '');
- $replacements = 0;
$keywords = preg_replace($match, $replace, $keywords);
$this->sphinx->SetMatchMode(SPH_MATCH_EXTENDED);
}
@@ -479,6 +479,8 @@ class fulltext_sphinx
*/
public function keyword_search($type, $fields, $terms, $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)
{
+ global $user, $phpbb_log;
+
// No keywords? No posts.
if (!strlen($this->search_query) && !sizeof($author_ary))
{
@@ -487,8 +489,6 @@ class fulltext_sphinx
$id_ary = array();
- $join_topic = ($type != 'posts');
-
// Sorting
if ($type == 'topics')
@@ -661,7 +661,7 @@ class fulltext_sphinx
if ($this->sphinx->GetLastError())
{
- add_log('critical', 'LOG_SPHINX_ERROR', $this->sphinx->GetLastError());
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_SPHINX_ERROR', false, array($this->sphinx->GetLastError()));
if ($this->auth->acl_get('a_'))
{
trigger_error($this->user->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError()));
@@ -815,7 +815,7 @@ class fulltext_sphinx
*/
public function tidy($create = false)
{
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php
index eb5543b50b..cbe2f02851 100644
--- a/phpBB/phpbb/session.php
+++ b/phpBB/phpbb/session.php
@@ -92,8 +92,8 @@ class session
}
// current directory within the phpBB root (for example: adm)
- $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path)));
- $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./')));
+ $root_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath($root_path)));
+ $page_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath('./')));
$intersection = array_intersect_assoc($root_dirs, $page_dirs);
$root_dirs = array_diff_assoc($root_dirs, $intersection);
@@ -219,7 +219,7 @@ class session
function session_begin($update_session_page = true)
{
global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path;
- global $request, $phpbb_container, $phpbb_dispatcher;
+ global $request, $phpbb_container, $user, $phpbb_log, $phpbb_dispatcher;
// Give us some basic information
$this->time_now = time();
@@ -257,23 +257,23 @@ class session
if ($request->is_set($config['cookie_name'] . '_sid', \phpbb\request\request_interface::COOKIE) || $request->is_set($config['cookie_name'] . '_u', \phpbb\request\request_interface::COOKIE))
{
- $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true);
- $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true);
- $this->session_id = request_var($config['cookie_name'] . '_sid', '', false, true);
+ $this->cookie_data['u'] = $request->variable($config['cookie_name'] . '_u', 0, false, \phpbb\request\request_interface::COOKIE);
+ $this->cookie_data['k'] = $request->variable($config['cookie_name'] . '_k', '', false, \phpbb\request\request_interface::COOKIE);
+ $this->session_id = $request->variable($config['cookie_name'] . '_sid', '', false, \phpbb\request\request_interface::COOKIE);
$SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid=';
$_SID = (defined('NEED_SID')) ? $this->session_id : '';
if (empty($this->session_id))
{
- $this->session_id = $_SID = request_var('sid', '');
+ $this->session_id = $_SID = $request->variable('sid', '');
$SID = '?sid=' . $this->session_id;
$this->cookie_data = array('u' => 0, 'k' => '');
}
}
else
{
- $this->session_id = $_SID = request_var('sid', '');
+ $this->session_id = $_SID = $request->variable('sid', '');
$SID = '?sid=' . $this->session_id;
}
@@ -359,8 +359,8 @@ class session
}
else
{
- set_config('limit_load', '0');
- set_config('limit_search_load', '0');
+ $config->set('limit_load', '0');
+ $config->set('limit_search_load', '0');
}
}
@@ -423,6 +423,7 @@ class session
$session_expired = false;
// Check whether the session is still valid if we have one
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$provider = $provider_collection->get_provider();
@@ -470,11 +471,18 @@ class session
{
if ($referer_valid)
{
- add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for));
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_IP_BROWSER_FORWARDED_CHECK', false, array(
+ $u_ip,
+ $s_ip,
+ $u_browser,
+ $s_browser,
+ htmlspecialchars($u_forwarded_for),
+ htmlspecialchars($s_forwarded_for)
+ ));
}
else
{
- add_log('critical', 'LOG_REFERER_INVALID', $this->referer);
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_REFERER_INVALID', false, array($this->referer));
}
}
}
@@ -496,7 +504,7 @@ class session
*/
function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
{
- global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
+ global $SID, $_SID, $db, $config, $cache, $phpbb_container, $phpbb_dispatcher;
$this->data = array();
@@ -559,6 +567,7 @@ class session
}
}
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$provider = $provider_collection->get_provider();
$this->data = $provider->autologin();
@@ -884,7 +893,7 @@ class session
*/
function session_kill($new_session = true)
{
- global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
+ global $SID, $_SID, $db, $phpbb_container, $phpbb_dispatcher;
$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
WHERE session_id = '" . $db->sql_escape($this->session_id) . "'
@@ -909,6 +918,7 @@ class session
unset($session_id);
// Allow connecting logout with external auth method logout
+ /* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
$provider = $provider_collection->get_provider();
$provider->logout($this->data, $new_session);
@@ -975,7 +985,7 @@ class session
*/
function session_gc()
{
- global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
+ global $db, $config, $phpbb_container, $phpbb_dispatcher;
$batch_size = 10;
@@ -1025,7 +1035,7 @@ class session
{
// Less than 10 users, update gc timer ... else we want gc
// called again to delete other sessions
- set_config('session_last_gc', $this->time_now, true);
+ $config->set('session_last_gc', $this->time_now, false);
if ($config['max_autologin_time'])
{
@@ -1035,6 +1045,7 @@ class session
}
// only called from CRON; should be a safe workaround until the infrastructure gets going
+ /* @var $captcha_factory \phpbb\captcha\factory */
$captcha_factory = $phpbb_container->get('captcha.factory');
$captcha_factory->garbage_collect($config['captcha_plugin']);
@@ -1068,6 +1079,12 @@ class session
{
global $config;
+ // If headers are already set, we just return
+ if (headers_sent())
+ {
+ return;
+ }
+
$name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata);
$expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime);
$domain = (!$config['cookie_domain'] || $config['cookie_domain'] == '127.0.0.1' || strpos($config['cookie_domain'], '.') === false) ? '' : '; domain=' . $config['cookie_domain'];
@@ -1219,7 +1236,7 @@ class session
if ($banned && !$return)
{
- global $template, $phpbb_root_path, $phpEx;
+ global $phpbb_root_path, $phpEx;
// If the session is empty we need to create a valid one...
if (empty($this->session_id))
@@ -1396,7 +1413,7 @@ class session
*/
function set_login_key($user_id = false, $key = false, $user_ip = false)
{
- global $config, $db;
+ global $db;
$user_id = ($user_id === false) ? $this->data['user_id'] : $user_id;
$user_ip = ($user_ip === false) ? $this->ip : $user_ip;
@@ -1406,7 +1423,7 @@ class session
$sql_ary = array(
'key_id' => (string) md5($key_id),
- 'last_ip' => (string) $this->ip,
+ 'last_ip' => (string) $user_ip,
'last_login' => (int) time()
);
@@ -1443,7 +1460,7 @@ class session
*/
function reset_login_keys($user_id = false)
{
- global $config, $db;
+ global $db;
$user_id = ($user_id === false) ? (int) $this->data['user_id'] : (int) $user_id;
diff --git a/phpBB/phpbb/template/asset.php b/phpBB/phpbb/template/asset.php
index ff9366af4a..cb00f16549 100644
--- a/phpBB/phpbb/template/asset.php
+++ b/phpBB/phpbb/template/asset.php
@@ -20,15 +20,20 @@ class asset
/** @var \phpbb\path_helper **/
protected $path_helper;
+ /** @var \phpbb\filesystem\filesystem */
+ protected $filesystem;
+
/**
* Constructor
*
* @param string $url URL
* @param \phpbb\path_helper $path_helper Path helper object
+ * @param \phpbb\filesystem\filesystem $filesystem
*/
- public function __construct($url, \phpbb\path_helper $path_helper)
+ public function __construct($url, \phpbb\path_helper $path_helper, \phpbb\filesystem\filesystem $filesystem)
{
$this->path_helper = $path_helper;
+ $this->filesystem = $filesystem;
$this->set_url($url);
}
@@ -152,18 +157,18 @@ class asset
*/
public function set_path($path, $urlencode = false)
{
- // Since 1.7.0 Twig returns the real path of the file. We need it to be relative to the working directory.
- $real_root_path = realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR;
+ // Since 1.7.0 Twig returns the real path of the file. We need it to be relative.
+ $real_root_path = $this->filesystem->realpath($this->path_helper->get_phpbb_root_path()) . DIRECTORY_SEPARATOR;
// If the asset is under the phpBB root path we need to remove its path and then prepend $phpbb_root_path
- if (substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path)
+ if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path)
{
$path = $this->path_helper->get_phpbb_root_path() . str_replace('\\', '/', substr($path, strlen($real_root_path)));
}
else
{
// Else we make the path relative to the current working directory
- $real_root_path = realpath('.') . DIRECTORY_SEPARATOR;
+ $real_root_path = $this->filesystem->realpath('.') . DIRECTORY_SEPARATOR;
if ($real_root_path && substr($path . DIRECTORY_SEPARATOR, 0, strlen($real_root_path)) === $real_root_path)
{
$path = str_replace('\\', '/', substr($path, strlen($real_root_path)));
diff --git a/phpBB/phpbb/template/assets_bag.php b/phpBB/phpbb/template/assets_bag.php
new file mode 100644
index 0000000000..9013061b96
--- /dev/null
+++ b/phpBB/phpbb/template/assets_bag.php
@@ -0,0 +1,95 @@
+<?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\template;
+
+class assets_bag
+{
+ /** @var asset[] */
+ protected $stylesheets = [];
+
+ /** @var asset[] */
+ protected $scripts = [];
+
+ /**
+ * Add a css asset to the bag
+ *
+ * @param asset $asset
+ */
+ public function add_stylesheet(asset $asset)
+ {
+ $this->stylesheets[] = $asset;
+ }
+
+ /**
+ * Add a js script asset to the bag
+ *
+ * @param asset $asset
+ */
+ public function add_script(asset $asset)
+ {
+ $this->scripts[] = $asset;
+ }
+
+ /**
+ * Returns all css assets
+ *
+ * @return asset[]
+ */
+ public function get_stylesheets()
+ {
+ return $this->stylesheets;
+ }
+
+ /**
+ * Returns all js assets
+ *
+ * @return asset[]
+ */
+ public function get_scripts()
+ {
+ return $this->scripts;
+ }
+
+ /**
+ * Returns the HTML code to includes all css assets
+ *
+ * @return string
+ */
+ public function get_stylesheets_content()
+ {
+ $output = '';
+ foreach ($this->stylesheets as $stylesheet)
+ {
+ $output .= "<link href=\"{$stylesheet->get_url()}\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />\n";
+ }
+
+ return $output;
+ }
+
+ /**
+ * Returns the HTML code to includes all js assets
+ *
+ * @return string
+ */
+ public function get_scripts_content()
+ {
+ $output = '';
+ foreach ($this->scripts as $script)
+ {
+ $output .= "<script type=\"text/javascript\" src=\"{$script->get_url()}\"></script>\n";
+ }
+
+ return $output;
+ }
+}
diff --git a/phpBB/phpbb/template/exception/user_object_not_available.php b/phpBB/phpbb/template/exception/user_object_not_available.php
new file mode 100644
index 0000000000..62fd2743c1
--- /dev/null
+++ b/phpBB/phpbb/template/exception/user_object_not_available.php
@@ -0,0 +1,22 @@
+<?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\template\exception;
+
+/**
+ * This exception is thrown when the user object was not set but it is required by the called method
+ */
+class user_object_not_available extends \phpbb\exception\runtime_exception
+{
+
+}
diff --git a/phpBB/phpbb/template/twig/environment.php b/phpBB/phpbb/template/twig/environment.php
index 476ffd935e..179412a2e3 100644
--- a/phpBB/phpbb/template/twig/environment.php
+++ b/phpBB/phpbb/template/twig/environment.php
@@ -13,14 +13,22 @@
namespace phpbb\template\twig;
+use phpbb\template\assets_bag;
+
class environment extends \Twig_Environment
{
/** @var \phpbb\config\config */
protected $phpbb_config;
+ /** @var \phpbb\filesystem\filesystem */
+ protected $filesystem;
+
/** @var \phpbb\path_helper */
protected $phpbb_path_helper;
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
/** @var \phpbb\extension\manager */
protected $extension_manager;
@@ -33,26 +41,41 @@ class environment extends \Twig_Environment
/** @var array **/
protected $namespace_look_up_order = array('__main__');
+ /** @var assets_bag */
+ protected $assets_bag;
+
/**
* Constructor
*
* @param \phpbb\config\config $phpbb_config The phpBB configuration
+ * @param \phpbb\filesystem\filesystem $filesystem
* @param \phpbb\path_helper $path_helper phpBB path helper
+ * @param string $cache_path The path to the cache directory
* @param \phpbb\extension\manager $extension_manager phpBB extension manager
* @param \Twig_LoaderInterface $loader Twig loader interface
* @param array $options Array of options to pass to Twig
*/
- public function __construct($phpbb_config, \phpbb\path_helper $path_helper, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array())
+ public function __construct(\phpbb\config\config $phpbb_config, \phpbb\filesystem\filesystem $filesystem, \phpbb\path_helper $path_helper, $cache_path, \phpbb\extension\manager $extension_manager = null, \Twig_LoaderInterface $loader = null, $options = array())
{
$this->phpbb_config = $phpbb_config;
+ $this->filesystem = $filesystem;
$this->phpbb_path_helper = $path_helper;
$this->extension_manager = $extension_manager;
$this->phpbb_root_path = $this->phpbb_path_helper->get_phpbb_root_path();
$this->web_root_path = $this->phpbb_path_helper->get_web_root_path();
- return parent::__construct($loader, $options);
+ $this->assets_bag = new assets_bag();
+
+ $options = array_merge(array(
+ 'cache' => (defined('IN_INSTALL')) ? false : $cache_path,
+ 'debug' => false,
+ 'auto_reload' => (bool) $this->phpbb_config['load_tplcompile'],
+ 'autoescape' => false,
+ ), $options);
+
+ parent::__construct($loader, $options);
}
/**
@@ -78,16 +101,26 @@ class environment extends \Twig_Environment
}
/**
- * Get the phpBB root path
- *
- * @return string
- */
+ * Get the phpBB root path
+ *
+ * @return string
+ */
public function get_phpbb_root_path()
{
return $this->phpbb_root_path;
}
/**
+ * Get the filesystem object
+ *
+ * @return \phpbb\filesystem\filesystem
+ */
+ public function get_filesystem()
+ {
+ return $this->filesystem;
+ }
+
+ /**
* Get the web root path
*
* @return string
@@ -108,6 +141,16 @@ class environment extends \Twig_Environment
}
/**
+ * Gets the assets bag
+ *
+ * @return assets_bag
+ */
+ public function get_assets_bag()
+ {
+ return $this->assets_bag;
+ }
+
+ /**
* Get the namespace look up order
*
* @return array
@@ -131,6 +174,55 @@ class environment extends \Twig_Environment
}
/**
+ * {@inheritdoc}
+ */
+ public function render($name, array $context = [])
+ {
+ return $this->display_with_assets($name, $context);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function display($name, array $context = [])
+ {
+ echo $this->display_with_assets($name, $context);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ private function display_with_assets($name, array $context = [])
+ {
+ $placeholder_salt = unique_id();
+
+ if (array_key_exists('definition', $context))
+ {
+ $context['definition']->set('SCRIPTS', '__SCRIPTS_' . $placeholder_salt . '__');
+ $context['definition']->set('STYLESHEETS', '__STYLESHEETS_' . $placeholder_salt . '__');
+ }
+
+ $output = parent::render($name, $context);
+
+ return $this->inject_assets($output, $placeholder_salt);
+ }
+
+ /**
+ * Injects the assets (from INCLUDECSS/JS) in the output.
+ *
+ * @param string $output
+ *
+ * @return string
+ */
+ private function inject_assets($output, $placeholder_salt)
+ {
+ $output = str_replace('__STYLESHEETS_' . $placeholder_salt . '__', $this->assets_bag->get_stylesheets_content(), $output);
+ $output = str_replace('__SCRIPTS_' . $placeholder_salt . '__', $this->assets_bag->get_scripts_content(), $output);
+
+ return $output;
+ }
+
+ /**
* Loads a template by name.
*
* @param string $name The template name
diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php
index 3a983491b9..92f87a0331 100644
--- a/phpBB/phpbb/template/twig/extension.php
+++ b/phpBB/phpbb/template/twig/extension.php
@@ -18,20 +18,20 @@ class extension extends \Twig_Extension
/** @var \phpbb\template\context */
protected $context;
- /** @var \phpbb\user */
- protected $user;
+ /** @var \phpbb\language\language */
+ protected $language;
/**
* Constructor
*
* @param \phpbb\template\context $context
- * @param \phpbb\user $user
+ * @param \phpbb\language\language $language
* @return \phpbb\template\twig\extension
*/
- public function __construct(\phpbb\template\context $context, $user)
+ public function __construct(\phpbb\template\context $context, $language)
{
$this->context = $context;
- $this->user = $user;
+ $this->language = $language;
}
/**
@@ -71,6 +71,7 @@ class extension extends \Twig_Extension
{
return array(
new \Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)),
+ // @deprecated 3.2.0 Uses twig's JS escape method instead of addslashes
new \Twig_SimpleFilter('addslashes', 'addslashes'),
);
}
@@ -177,9 +178,9 @@ class extension extends \Twig_Extension
return $context_vars['L_' . $key];
}
- // LA_ is transformed into lang(\'$1\')|addslashes, so we should not
+ // LA_ is transformed into lang(\'$1\')|escape('js'), so we should not
// need to check for it
- return call_user_func_array(array($this->user, 'lang'), $args);
+ return call_user_func_array(array($this->language, 'lang'), $args);
}
}
diff --git a/phpBB/phpbb/template/twig/extension/routing.php b/phpBB/phpbb/template/twig/extension/routing.php
new file mode 100644
index 0000000000..829ce738eb
--- /dev/null
+++ b/phpBB/phpbb/template/twig/extension/routing.php
@@ -0,0 +1,43 @@
+<?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\template\twig\extension;
+
+use Symfony\Bridge\Twig\Extension\RoutingExtension;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+
+class routing extends RoutingExtension
+{
+ /** @var \phpbb\controller\helper */
+ protected $helper;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\routing\helper $helper
+ */
+ public function __construct(\phpbb\routing\helper $helper)
+ {
+ $this->helper = $helper;
+ }
+
+ public function getPath($name, $parameters = array(), $relative = false)
+ {
+ return $this->helper->route($name, $parameters, true, false, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
+ }
+
+ public function getUrl($name, $parameters = array(), $schemeRelative = false)
+ {
+ return $this->helper->route($name, $parameters, true, false, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
+ }
+}
diff --git a/phpBB/phpbb/template/twig/lexer.php b/phpBB/phpbb/template/twig/lexer.php
index c5dc7273ba..de03aec04b 100644
--- a/phpBB/phpbb/template/twig/lexer.php
+++ b/phpBB/phpbb/template/twig/lexer.php
@@ -15,8 +15,18 @@ namespace phpbb\template\twig;
class lexer extends \Twig_Lexer
{
+ public function set_environment(\Twig_Environment $env)
+ {
+ $this->env = $env;
+ }
+
public function tokenize($code, $filename = null)
{
+ if ($code instanceof \Twig_Source)
+ {
+ $filename = $code->getName();
+ $code = $code->getCode();
+ }
// Our phpBB tags
// Commented out tokens are handled separately from the main replace
$phpbb_tags = array(
@@ -112,15 +122,15 @@ class lexer extends \Twig_Lexer
// Appends any filters after lang()
$code = preg_replace('#{L_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2 }}', $code);
- // Replace all of our escaped language variables, {LA_VARNAME}, with Twig style, {{ lang('NAME')|addslashes }}
- // Appends any filters after lang(), but before addslashes
- $code = preg_replace('#{LA_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2|addslashes }}', $code);
+ // Replace all of our escaped language variables, {LA_VARNAME}, with Twig style, {{ lang('NAME')|escape('js') }}
+ // Appends any filters after lang(), but before escape('js')
+ $code = preg_replace('#{LA_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2|escape(\'js\') }}', $code);
// Replace all of our variables, {VARNAME}, with Twig style, {{ VARNAME }}
// Appends any filters
$code = preg_replace('#{([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ $1$2 }}', $code);
- return parent::tokenize($code, $filename);
+ return parent::tokenize(new \Twig_Source($code, $filename));
}
/**
diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php
index 139a413b70..d2b42852ce 100644
--- a/phpBB/phpbb/template/twig/loader.php
+++ b/phpBB/phpbb/template/twig/loader.php
@@ -21,6 +21,24 @@ class loader extends \Twig_Loader_Filesystem
protected $safe_directories = array();
/**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\filesystem\filesystem_interface $filesystem
+ * @param string|array $paths
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $paths = array())
+ {
+ $this->filesystem = $filesystem;
+
+ parent::__construct($paths);
+ }
+
+ /**
* Set safe directories
*
* @param array $directories Array of directories that are safe (empty to clear)
@@ -49,7 +67,7 @@ class loader extends \Twig_Loader_Filesystem
*/
public function addSafeDirectory($directory)
{
- $directory = phpbb_realpath($directory);
+ $directory = $this->filesystem->realpath($directory);
if ($directory !== false)
{
@@ -83,6 +101,16 @@ class loader extends \Twig_Loader_Filesystem
}
/**
+ * Adds a realpath call to fix a BC break in Twig 1.26 (https://github.com/twigphp/Twig/issues/2145)
+ *
+ * {@inheritdoc}
+ */
+ public function addPath($path, $namespace = self::MAIN_NAMESPACE)
+ {
+ return parent::addPath($this->filesystem->realpath($path), $namespace);
+ }
+
+ /**
* Find the template
*
* Override for Twig_Loader_Filesystem::findTemplate to add support
@@ -119,7 +147,7 @@ class loader extends \Twig_Loader_Filesystem
// can now check if we're within a "safe" directory
// Find the real path of the directory the file is in
- $directory = phpbb_realpath(dirname($file));
+ $directory = $this->filesystem->realpath(dirname($file));
if ($directory === false)
{
diff --git a/phpBB/phpbb/template/twig/node/event.php b/phpBB/phpbb/template/twig/node/event.php
index b765bde98d..11fdb75247 100644
--- a/phpBB/phpbb/template/twig/node/event.php
+++ b/phpBB/phpbb/template/twig/node/event.php
@@ -46,7 +46,7 @@ class event extends \Twig_Node
{
$ext_namespace = str_replace('/', '_', $ext_namespace);
- if (defined('DEBUG'))
+ if ($this->environment->isDebug())
{
// If debug mode is enabled, lets check for new/removed EVENT
// templates on page load rather than at compile. This is
@@ -58,7 +58,7 @@ class event extends \Twig_Node
;
}
- if (defined('DEBUG') || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html'))
+ if ($this->environment->isDebug() || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html'))
{
$compiler
->write("\$previous_look_up_order = \$this->env->getNamespaceLookUpOrder();\n")
@@ -70,7 +70,7 @@ class event extends \Twig_Node
;
}
- if (defined('DEBUG'))
+ if ($this->environment->isDebug())
{
$compiler
->outdent()
diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php
index 15195a226b..6d50eafc9d 100644
--- a/phpBB/phpbb/template/twig/node/includeasset.php
+++ b/phpBB/phpbb/template/twig/node/includeasset.php
@@ -39,7 +39,7 @@ abstract class includeasset extends \Twig_Node
->write("\$asset_file = ")
->subcompile($this->getNode('expr'))
->raw(";\n")
- ->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_path_helper());\n")
+ ->write("\$asset = new \phpbb\\template\\asset(\$asset_file, \$this->getEnvironment()->get_path_helper(), \$this->getEnvironment()->get_filesystem());\n")
->write("if (substr(\$asset_file, 0, 2) !== './' && \$asset->is_relative()) {\n")
->indent()
->write("\$asset_path = \$asset->get_path();")
@@ -49,33 +49,18 @@ abstract class includeasset extends \Twig_Node
->write("\$local_file = \$this->getEnvironment()->findTemplate(\$asset_path);\n")
->write("\$asset->set_path(\$local_file, true);\n")
->outdent()
- ->write("\$asset->add_assets_version('{$config['assets_version']}');\n")
- ->write("\$asset_file = \$asset->get_url();\n")
->write("}\n")
+ ->write("\$asset->add_assets_version('{$config['assets_version']}');\n")
->outdent()
->write("}\n")
- ->write("\$context['definition']->append('{$this->get_definition_name()}', '")
- ;
-
- $this->append_asset($compiler);
-
- $compiler
- ->raw("\n');\n")
+ ->write("\$this->getEnvironment()->get_assets_bag()->add_{$this->get_setters_name()}(\$asset);")
;
}
/**
- * Get the definition name
+ * Get the name of the assets bag setter
*
- * @return string (e.g. 'SCRIPTS')
- */
- abstract public function get_definition_name();
-
- /**
- * Append the output code for the asset
- *
- * @param \Twig_Compiler A Twig_Compiler instance
- * @return null
+ * @return string (e.g. 'script')
*/
- abstract protected function append_asset(\Twig_Compiler $compiler);
+ abstract public function get_setters_name();
}
diff --git a/phpBB/phpbb/template/twig/node/includecss.php b/phpBB/phpbb/template/twig/node/includecss.php
index 2dac154036..2e97d4972d 100644
--- a/phpBB/phpbb/template/twig/node/includecss.php
+++ b/phpBB/phpbb/template/twig/node/includecss.php
@@ -18,20 +18,8 @@ class includecss extends \phpbb\template\twig\node\includeasset
/**
* {@inheritdoc}
*/
- public function get_definition_name()
+ public function get_setters_name()
{
- return 'STYLESHEETS';
- }
-
- /**
- * {@inheritdoc}
- */
- public function append_asset(\Twig_Compiler $compiler)
- {
- $compiler
- ->raw("<link href=\"' . ")
- ->raw("\$asset_file . '\"")
- ->raw(' rel="stylesheet" type="text/css" media="screen" />')
- ;
+ return 'stylesheet';
}
}
diff --git a/phpBB/phpbb/template/twig/node/includejs.php b/phpBB/phpbb/template/twig/node/includejs.php
index 0f67f9ff60..505b49757b 100644
--- a/phpBB/phpbb/template/twig/node/includejs.php
+++ b/phpBB/phpbb/template/twig/node/includejs.php
@@ -18,22 +18,8 @@ class includejs extends \phpbb\template\twig\node\includeasset
/**
* {@inheritdoc}
*/
- public function get_definition_name()
+ public function get_setters_name()
{
- return 'SCRIPTS';
- }
-
- /**
- * {@inheritdoc}
- */
- protected function append_asset(\Twig_Compiler $compiler)
- {
- $config = $this->environment->get_phpbb_config();
-
- $compiler
- ->raw("<script type=\"text/javascript\" src=\"' . ")
- ->raw("\$asset_file")
- ->raw(". '\"></script>\n")
- ;
+ return 'script';
}
}
diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php
index d1bbb2b55a..f322778eda 100644
--- a/phpBB/phpbb/template/twig/twig.php
+++ b/phpBB/phpbb/template/twig/twig.php
@@ -13,6 +13,8 @@
namespace phpbb\template\twig;
+use phpbb\template\exception\user_object_not_available;
+
/**
* Twig Template class.
*/
@@ -76,11 +78,14 @@ class twig extends \phpbb\template\base
*
* @param \phpbb\path_helper $path_helper
* @param \phpbb\config\config $config
- * @param \phpbb\user $user
* @param \phpbb\template\context $context template context
+ * @param \phpbb\template\twig\environment $twig_environment
+ * @param string $cache_path
+ * @param \phpbb\user|null $user
+ * @param array|\ArrayAccess $extensions
* @param \phpbb\extension\manager $extension_manager extension manager, if null then template events will not be invoked
*/
- public function __construct(\phpbb\path_helper $path_helper, $config, $user, \phpbb\template\context $context, \phpbb\extension\manager $extension_manager = null)
+ public function __construct(\phpbb\path_helper $path_helper, $config, \phpbb\template\context $context, \phpbb\template\twig\environment $twig_environment, $cache_path, \phpbb\user $user = null, $extensions = array(), \phpbb\extension\manager $extension_manager = null)
{
$this->path_helper = $path_helper;
$this->phpbb_root_path = $path_helper->get_phpbb_root_path();
@@ -89,41 +94,14 @@ class twig extends \phpbb\template\base
$this->user = $user;
$this->context = $context;
$this->extension_manager = $extension_manager;
+ $this->cachepath = $cache_path;
+ $this->twig = $twig_environment;
- $this->cachepath = $this->phpbb_root_path . 'cache/twig/';
-
- // Initiate the loader, __main__ namespace paths will be setup later in set_style_names()
- $loader = new \phpbb\template\twig\loader('');
-
- $this->twig = new \phpbb\template\twig\environment(
- $this->config,
- $this->path_helper,
- $this->extension_manager,
- $loader,
- array(
- 'cache' => (defined('IN_INSTALL')) ? false : $this->cachepath,
- 'debug' => defined('DEBUG'),
- 'auto_reload' => (bool) $this->config['load_tplcompile'],
- 'autoescape' => false,
- )
- );
-
- $this->twig->addExtension(
- new \phpbb\template\twig\extension(
- $this->context,
- $this->user
- )
- );
-
- if (defined('DEBUG'))
+ foreach ($extensions as $extension)
{
- $this->twig->addExtension(new \Twig_Extension_Debug());
+ $this->twig->addExtension($extension);
}
- $lexer = new \phpbb\template\twig\lexer($this->twig);
-
- $this->twig->setLexer($lexer);
-
// Add admin namespace
if ($this->path_helper->get_adm_relative_path() !== null && is_dir($this->phpbb_root_path . $this->path_helper->get_adm_relative_path() . 'style/'))
{
@@ -150,9 +128,16 @@ class twig extends \phpbb\template\base
* Get the style tree of the style preferred by the current user
*
* @return array Style tree, most specific first
+ *
+ * @throws \phpbb\template\exception\user_object_not_available When user service was not set
*/
public function get_user_style()
{
+ if ($this->user === null)
+ {
+ throw new user_object_not_available();
+ }
+
$style_list = array(
$this->user->style['style_path'],
);
@@ -368,14 +353,24 @@ class twig extends \phpbb\template\base
$context_vars['.'][0], // To get normal vars
array(
'definition' => new \phpbb\template\twig\definition(),
- 'user' => $this->user,
'loops' => $context_vars, // To get loops
)
);
+ if ($this->user instanceof \phpbb\user)
+ {
+ $vars['user'] = $this->user;
+ }
+
// cleanup
unset($vars['loops']['.']);
+ // Inject in the main context the value added by assign_block_vars() to be able to use directly the Twig loops.
+ foreach ($vars['loops'] as $key => &$value)
+ {
+ $vars[$key] = $value;
+ }
+
return $vars;
}
diff --git a/phpBB/phpbb/textformatter/cache_interface.php b/phpBB/phpbb/textformatter/cache_interface.php
new file mode 100644
index 0000000000..f6b5f195c7
--- /dev/null
+++ b/phpBB/phpbb/textformatter/cache_interface.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\textformatter;
+
+/**
+* Currently only used to signal that something that could effect the rendering has changed.
+* BBCodes, smilies, censored words, templates, etc...
+*/
+interface cache_interface
+{
+ /**
+ * Invalidate and/or regenerate this text formatter's cache(s)
+ */
+ public function invalidate();
+
+ /**
+ * Tidy/prune this text formatter's cache(s)
+ */
+ public function tidy();
+}
diff --git a/phpBB/phpbb/textformatter/data_access.php b/phpBB/phpbb/textformatter/data_access.php
new file mode 100644
index 0000000000..2103bf8e60
--- /dev/null
+++ b/phpBB/phpbb/textformatter/data_access.php
@@ -0,0 +1,228 @@
+<?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;
+
+/**
+* Data access layer that fetchs BBCodes, smilies and censored words from the database.
+* To be extended to include insert/update/delete operations.
+*
+* Also used to get templates.
+*/
+class data_access
+{
+ /**
+ * @var string Name of the BBCodes table
+ */
+ protected $bbcodes_table;
+
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var string Name of the smilies table
+ */
+ protected $smilies_table;
+
+ /**
+ * @var string Name of the styles table
+ */
+ protected $styles_table;
+
+ /**
+ * @var string Path to the styles dir
+ */
+ protected $styles_path;
+
+ /**
+ * @var string Name of the words table
+ */
+ protected $words_table;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param string $bbcodes_table Name of the BBCodes table
+ * @param string $smilies_table Name of the smilies table
+ * @param string $styles_table Name of the styles table
+ * @param string $words_table Name of the words table
+ * @param string $styles_path Path to the styles dir
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $bbcodes_table, $smilies_table, $styles_table, $words_table, $styles_path)
+ {
+ $this->db = $db;
+
+ $this->bbcodes_table = $bbcodes_table;
+ $this->smilies_table = $smilies_table;
+ $this->styles_table = $styles_table;
+ $this->words_table = $words_table;
+
+ $this->styles_path = $styles_path;
+ }
+
+ /**
+ * Return the list of custom BBCodes
+ *
+ * @return array
+ */
+ public function get_bbcodes()
+ {
+ $sql = 'SELECT bbcode_match, bbcode_tpl FROM ' . $this->bbcodes_table;
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ /**
+ * Return the list of smilies
+ *
+ * @return array
+ */
+ public function get_smilies()
+ {
+ // NOTE: smilies that are displayed on the posting page are processed first because they're
+ // typically the most used smilies and it ends up producing a slightly more efficient
+ // renderer
+ $sql = 'SELECT code, emotion, smiley_url, smiley_width, smiley_height
+ FROM ' . $this->smilies_table . '
+ ORDER BY display_on_posting DESC';
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ /**
+ * Return the list of installed styles
+ *
+ * @return array
+ */
+ protected function get_styles()
+ {
+ $sql = 'SELECT style_id, style_path, style_parent_id, bbcode_bitfield FROM ' . $this->styles_table;
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ /**
+ * Return the bbcode.html template for every installed style
+ *
+ * @return array 2D array. style_id as keys, each element is an array with a "template" element that contains the style's bbcode.html and a "bbcodes" element that contains the name of each BBCode that is to be stylised
+ */
+ public function get_styles_templates()
+ {
+ $templates = array();
+
+ $bbcode_ids = array(
+ 'quote' => 0,
+ 'b' => 1,
+ 'i' => 2,
+ 'url' => 3,
+ 'img' => 4,
+ 'size' => 5,
+ 'color' => 6,
+ 'u' => 7,
+ 'code' => 8,
+ 'list' => 9,
+ '*' => 9,
+ 'email' => 10,
+ 'flash' => 11,
+ 'attachment' => 12,
+ );
+
+ $styles = array();
+ foreach ($this->get_styles() as $row)
+ {
+ $styles[$row['style_id']] = $row;
+ }
+
+ foreach ($styles as $style_id => $style)
+ {
+ $bbcodes = array();
+
+ // Collect the name of the BBCodes whose bit is set in the style's bbcode_bitfield
+ $template_bitfield = new \bitfield($style['bbcode_bitfield']);
+ foreach ($bbcode_ids as $bbcode_name => $bit)
+ {
+ if ($template_bitfield->get($bit))
+ {
+ $bbcodes[] = $bbcode_name;
+ }
+ }
+
+ $filename = $this->resolve_style_filename($styles, $style);
+ if ($filename === false)
+ {
+ // Ignore this style, it will use the default templates
+ continue;
+ }
+
+ $templates[$style_id] = array(
+ 'bbcodes' => $bbcodes,
+ 'template' => file_get_contents($filename),
+ );
+ }
+
+ return $templates;
+ }
+
+ /**
+ * Resolve inheritance for given style and return the path to their bbcode.html file
+ *
+ * @param array $styles Associative array of [style_id => style] containing all styles
+ * @param array $style Style for which we resolve
+ * @return string|bool Path to this style's bbcode.html, or FALSE
+ */
+ protected function resolve_style_filename(array $styles, array $style)
+ {
+ // Look for a bbcode.html in this style's dir
+ $filename = $this->styles_path . $style['style_path'] . '/template/bbcode.html';
+ if (file_exists($filename))
+ {
+ return $filename;
+ }
+
+ // Resolve using this style's parent
+ $parent_id = $style['style_parent_id'];
+ if ($parent_id && !empty($styles[$parent_id]))
+ {
+ return $this->resolve_style_filename($styles, $styles[$parent_id]);
+ }
+
+ return false;
+ }
+
+ /**
+ * Return the list of censored words
+ *
+ * @return array
+ */
+ public function get_censored_words()
+ {
+ $sql = 'SELECT word, replacement FROM ' . $this->words_table;
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+}
diff --git a/phpBB/phpbb/textformatter/parser_interface.php b/phpBB/phpbb/textformatter/parser_interface.php
new file mode 100644
index 0000000000..ad611fb5b4
--- /dev/null
+++ b/phpBB/phpbb/textformatter/parser_interface.php
@@ -0,0 +1,112 @@
+<?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;
+
+interface parser_interface
+{
+ /**
+ * Parse given text
+ *
+ * @param string $text
+ * @return string
+ */
+ public function parse($text);
+
+ /**
+ * Disable a specific BBCode
+ *
+ * @param string $name BBCode name
+ * @return null
+ */
+ public function disable_bbcode($name);
+
+ /**
+ * Disable BBCodes in general
+ */
+ public function disable_bbcodes();
+
+ /**
+ * Disable the censor
+ */
+ public function disable_censor();
+
+ /**
+ * Disable magic URLs
+ */
+ public function disable_magic_url();
+
+ /**
+ * Disable smilies
+ */
+ public function disable_smilies();
+
+ /**
+ * Enable a specific BBCode
+ *
+ * @param string $name BBCode name
+ * @return null
+ */
+ public function enable_bbcode($name);
+
+ /**
+ * Enable BBCodes in general
+ */
+ public function enable_bbcodes();
+
+ /**
+ * Enable the censor
+ */
+ public function enable_censor();
+
+ /**
+ * Enable magic URLs
+ */
+ public function enable_magic_url();
+
+ /**
+ * Enable smilies
+ */
+ public function enable_smilies();
+
+ /**
+ * Get the list of errors that were generated during last parsing
+ *
+ * @return array[] Array of arrays. Each array contains a lang string at index 0 plus any number
+ * of optional parameters
+ */
+ public function get_errors();
+
+ /**
+ * Set a variable to be used by the parser
+ *
+ * - max_font_size
+ * - max_img_height
+ * - max_img_width
+ * - max_smilies
+ * - max_urls
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return null
+ */
+ public function set_var($name, $value);
+
+ /**
+ * Set multiple variables to be used by the parser
+ *
+ * @param array $vars Associative array of [name => value]
+ * @return null
+ */
+ public function set_vars(array $vars);
+}
diff --git a/phpBB/phpbb/textformatter/renderer_interface.php b/phpBB/phpbb/textformatter/renderer_interface.php
new file mode 100644
index 0000000000..609b0bb642
--- /dev/null
+++ b/phpBB/phpbb/textformatter/renderer_interface.php
@@ -0,0 +1,92 @@
+<?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;
+
+interface renderer_interface
+{
+ /**
+ * Render given text
+ *
+ * @param string $text Text, as parsed by something that implements \phpbb\textformatter\parser
+ * @return string
+ */
+ public function render($text);
+
+ /**
+ * Set the smilies' path
+ *
+ * @return null
+ */
+ public function set_smilies_path($path);
+
+ /**
+ * Return the value of the "viewcensors" option
+ *
+ * @return bool Option's value
+ */
+ public function get_viewcensors();
+
+ /**
+ * Return the value of the "viewflash" option
+ *
+ * @return bool Option's value
+ */
+ public function get_viewflash();
+
+ /**
+ * Return the value of the "viewimg" option
+ *
+ * @return bool Option's value
+ */
+ public function get_viewimg();
+
+ /**
+ * Return the value of the "viewsmilies" option
+ *
+ * @return bool Option's value
+ */
+ public function get_viewsmilies();
+
+ /**
+ * Set the "viewcensors" option
+ *
+ * @param bool $value Option's value
+ * @return null
+ */
+ public function set_viewcensors($value);
+
+ /**
+ * Set the "viewflash" option
+ *
+ * @param bool $value Option's value
+ * @return null
+ */
+ public function set_viewflash($value);
+
+ /**
+ * Set the "viewimg" option
+ *
+ * @param bool $value Option's value
+ * @return null
+ */
+ public function set_viewimg($value);
+
+ /**
+ * Set the "viewsmilies" option
+ *
+ * @param bool $value Option's value
+ * @return null
+ */
+ public function set_viewsmilies($value);
+}
diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php
new file mode 100644
index 0000000000..f62daefdd9
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/factory.php
@@ -0,0 +1,618 @@
+<?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 s9e\TextFormatter\Configurator;
+use s9e\TextFormatter\Configurator\Items\AttributeFilters\RegexpFilter;
+use s9e\TextFormatter\Configurator\Items\UnsafeTemplate;
+
+/**
+* Creates s9e\TextFormatter objects
+*/
+class factory implements \phpbb\textformatter\cache_interface
+{
+ /**
+ * @var \phpbb\textformatter\s9e\link_helper
+ */
+ protected $link_helper;
+
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var string Path to the cache dir
+ */
+ protected $cache_dir;
+
+ /**
+ * @var string Cache key used for the parser
+ */
+ protected $cache_key_parser;
+
+ /**
+ * @var string Cache key used for the renderer
+ */
+ protected $cache_key_renderer;
+
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var array Custom tokens used in bbcode.html and their corresponding token from the definition
+ */
+ protected $custom_tokens = array(
+ 'email' => array('{DESCRIPTION}' => '{TEXT}'),
+ 'flash' => array('{WIDTH}' => '{NUMBER1}', '{HEIGHT}' => '{NUMBER2}'),
+ 'img' => array('{URL}' => '{IMAGEURL}'),
+ 'list' => array('{LIST_TYPE}' => '{HASHMAP}'),
+ 'quote' => array('{USERNAME}' => '{TEXT1}'),
+ 'size' => array('{SIZE}' => '{FONTSIZE}'),
+ 'url' => array('{DESCRIPTION}' => '{TEXT}'),
+ );
+
+ /**
+ * @var \phpbb\textformatter\data_access
+ */
+ protected $data_access;
+
+ /**
+ * @var array Default BBCode definitions
+ */
+ protected $default_definitions = array(
+ 'attachment' => '[ATTACHMENT index={NUMBER} filename={TEXT;useContent}]',
+ '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]',
+ 'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]',
+ 'i' => '[I]{TEXT}[/I]',
+ 'img' => '[IMG src={IMAGEURL;useContent}]',
+ 'list' => '[LIST type={HASHMAP=1:decimal,a:lower-alpha,A:upper-alpha,i:lower-roman,I:upper-roman;optional;postFilter=#simpletext} #createChild=LI]{TEXT}[/LIST]',
+ 'li' => '[* $tagName=LI]{TEXT}[/*]',
+ 'quote' =>
+ "[QUOTE
+ author={TEXT1;optional}
+ post_id={UINT;optional}
+ post_url={URL;optional;postFilter=#false}
+ profile_url={URL;optional;postFilter=#false}
+ time={UINT;optional}
+ url={URL;optional}
+ user_id={UINT;optional}
+ author={PARSE=/^\\[url=(?'url'.*?)](?'author'.*)\\[\\/url]$/i}
+ author={PARSE=/^\\[url](?'author'(?'url'.*?))\\[\\/url]$/i}
+ author={PARSE=/(?'url'https?:\\/\\/[^[\\]]+)/i}
+ ]{TEXT2}[/QUOTE]",
+ 'size' => '[SIZE={FONTSIZE}]{TEXT}[/SIZE]',
+ 'u' => '[U]{TEXT}[/U]',
+ 'url' => '[URL={URL;useContent} $forceLookahead=true]{TEXT}[/URL]',
+ );
+
+ /**
+ * @var array Default templates, taken from bbcode::bbcode_tpl()
+ */
+ protected $default_templates = array(
+ 'b' => '<span style="font-weight: bold"><xsl:apply-templates/></span>',
+ 'i' => '<span style="font-style: italic"><xsl:apply-templates/></span>',
+ 'u' => '<span style="text-decoration: underline"><xsl:apply-templates/></span>',
+ 'img' => '<img src="{IMAGEURL}" class="postimage" alt="{L_IMAGE}"/>',
+ 'size' => '<span style="font-size: {FONTSIZE}%; line-height: normal"><xsl:apply-templates/></span>',
+ 'color' => '<span style="color: {COLOR}"><xsl:apply-templates/></span>',
+ 'email' => '<a>
+ <xsl:attribute name="href">
+ <xsl:text>mailto:</xsl:text>
+ <xsl:value-of select="@email"/>
+ <xsl:if test="@subject or @body">
+ <xsl:text>?</xsl:text>
+ <xsl:if test="@subject">subject=<xsl:value-of select="@subject"/></xsl:if>
+ <xsl:if test="@body"><xsl:if test="@subject">&amp;</xsl:if>body=<xsl:value-of select="@body"/></xsl:if>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </a>',
+ );
+
+ /**
+ * @var \phpbb\event\dispatcher_interface
+ */
+ protected $dispatcher;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\textformatter\data_access $data_access
+ * @param \phpbb\cache\driver\driver_interface $cache
+ * @param \phpbb\event\dispatcher_interface $dispatcher
+ * @param \phpbb\config\config $config
+ * @param \phpbb\textformatter\s9e\link_helper $link_helper
+ * @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)
+ {
+ $this->link_helper = $link_helper;
+ $this->cache = $cache;
+ $this->cache_dir = $cache_dir;
+ $this->cache_key_parser = $cache_key_parser;
+ $this->cache_key_renderer = $cache_key_renderer;
+ $this->config = $config;
+ $this->data_access = $data_access;
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidate()
+ {
+ $this->regenerate();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Will remove old renderers from the cache dir but won't touch the current renderer
+ */
+ public function tidy()
+ {
+ // Get the name of current renderer
+ $renderer_data = $this->cache->get($this->cache_key_renderer);
+ $renderer_file = ($renderer_data) ? $renderer_data['class'] . '.php' : null;
+
+ foreach (glob($this->cache_dir . 's9e_*') as $filename)
+ {
+ // Only remove the file if it's not the current renderer
+ if (!$renderer_file || substr($filename, -strlen($renderer_file)) !== $renderer_file)
+ {
+ unlink($filename);
+ }
+ }
+ }
+
+ /**
+ * Generate and return a new configured instance of s9e\TextFormatter\Configurator
+ *
+ * @return Configurator
+ */
+ public function get_configurator()
+ {
+ // Create a new Configurator
+ $configurator = new Configurator;
+
+ /**
+ * Modify the s9e\TextFormatter configurator before the default settings are set
+ *
+ * @event core.text_formatter_s9e_configure_before
+ * @var \s9e\TextFormatter\Configurator configurator Configurator instance
+ * @since 3.2.0-a1
+ */
+ $vars = array('configurator');
+ extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_before', compact($vars)));
+
+ // Reset the list of allowed schemes
+ foreach ($configurator->urlConfig->getAllowedSchemes() as $scheme)
+ {
+ $configurator->urlConfig->disallowScheme($scheme);
+ }
+ foreach (explode(',', $this->config['allowed_schemes_links']) as $scheme)
+ {
+ $configurator->urlConfig->allowScheme(trim($scheme));
+ }
+
+ // Convert newlines to br elements by default
+ $configurator->rootRules->enableAutoLineBreaks();
+
+ // Don't automatically ignore text in places where text is not allowed
+ $configurator->rulesGenerator->remove('IgnoreTextIfDisallowed');
+
+ // Don't remove comments and instead convert them to xsl:comment elements
+ $configurator->templateNormalizer->remove('RemoveComments');
+ $configurator->templateNormalizer->add('TransposeComments');
+
+ // Set the rendering engine and configure it to save to the cache dir
+ $configurator->rendering->engine = 'PHP';
+ $configurator->rendering->engine->cacheDir = $this->cache_dir;
+ $configurator->rendering->engine->defaultClassPrefix = 's9e_renderer_';
+ $configurator->rendering->engine->enableQuickRenderer = true;
+
+ // Create custom filters for BBCode tokens that are supported in phpBB but not in
+ // s9e\TextFormatter
+ $filter = new RegexpFilter('#^' . get_preg_expression('relative_url') . '$#Du');
+ $configurator->attributeFilters->add('#local_url', $filter);
+ $configurator->attributeFilters->add('#relative_url', $filter);
+
+ // INTTEXT regexp from acp_bbcodes
+ $filter = new RegexpFilter('!^([\p{L}\p{N}\-+,_. ]+)$!Du');
+ $configurator->attributeFilters->add('#inttext', $filter);
+
+ // Create custom filters for Flash restrictions, which use the same values as the image
+ // restrictions but have their own error message
+ $configurator->attributeFilters
+ ->add('#flashheight', __NAMESPACE__ . '\\parser::filter_flash_height')
+ ->addParameterByName('max_img_height')
+ ->addParameterByName('logger');
+
+ $configurator->attributeFilters
+ ->add('#flashwidth', __NAMESPACE__ . '\\parser::filter_flash_width')
+ ->addParameterByName('max_img_width')
+ ->addParameterByName('logger');
+
+ // Create a custom filter for phpBB's per-mode font size limits
+ $configurator->attributeFilters
+ ->add('#fontsize', __NAMESPACE__ . '\\parser::filter_font_size')
+ ->addParameterByName('max_font_size')
+ ->addParameterByName('logger')
+ ->markAsSafeInCSS();
+
+ // Create a custom filter for image URLs
+ $configurator->attributeFilters
+ ->add('#imageurl', __NAMESPACE__ . '\\parser::filter_img_url')
+ ->addParameterByName('urlConfig')
+ ->addParameterByName('logger')
+ ->addParameterByName('max_img_height')
+ ->addParameterByName('max_img_width')
+ ->markAsSafeAsURL();
+
+ // Add default BBCodes
+ foreach ($this->get_default_bbcodes($configurator) as $bbcode)
+ {
+ $configurator->BBCodes->addCustom($bbcode['usage'], $bbcode['template']);
+ }
+
+ // Modify the template to disable images/flash depending on user's settings
+ foreach (array('FLASH', 'IMG') as $name)
+ {
+ $tag = $configurator->tags[$name];
+ $tag->template = '<xsl:choose><xsl:when test="$S_VIEW' . $name . '">' . $tag->template . '</xsl:when><xsl:otherwise><xsl:apply-templates/></xsl:otherwise></xsl:choose>';
+ }
+
+ // Load custom BBCodes
+ foreach ($this->data_access->get_bbcodes() as $row)
+ {
+ // Insert the board's URL before {LOCAL_URL} tokens
+ $tpl = preg_replace_callback(
+ '#\\{LOCAL_URL\\d*\\}#',
+ function ($m)
+ {
+ return generate_board_url() . '/' . $m[0];
+ },
+ $row['bbcode_tpl']
+ );
+
+ try
+ {
+ $configurator->BBCodes->addCustom($row['bbcode_match'], new UnsafeTemplate($tpl));
+ }
+ catch (\Exception $e)
+ {
+ /**
+ * @todo log an error?
+ */
+ }
+ }
+
+ // Load smilies
+ foreach ($this->data_access->get_smilies() as $row)
+ {
+ $configurator->Emoticons->set(
+ $row['code'],
+ '<img class="smilies" src="{$T_SMILIES_PATH}/' . htmlspecialchars($row['smiley_url']) . '" alt="{.}" title="' . htmlspecialchars($row['emotion']) . '"/>'
+ );
+ }
+
+ if (isset($configurator->Emoticons))
+ {
+ // Force emoticons to be rendered as text if $S_VIEWSMILIES is not set
+ $configurator->Emoticons->notIfCondition = 'not($S_VIEWSMILIES)';
+
+ // Only parse emoticons at the beginning of the text or if they're preceded by any
+ // one of: a new line, a space, a dot, or a right square bracket
+ $configurator->Emoticons->notAfter = '[^\\n .\\]]';
+ }
+
+ // Load the censored words
+ $censor = $this->data_access->get_censored_words();
+ if (!empty($censor))
+ {
+ // Use a namespaced tag to avoid collisions
+ $configurator->plugins->load('Censor', array('tagName' => 'censor:tag'));
+ foreach ($censor as $row)
+ {
+ // NOTE: words are stored as HTML, we need to decode them to plain text
+ $configurator->Censor->add(htmlspecialchars_decode($row['word']), htmlspecialchars_decode($row['replacement']));
+ }
+ }
+
+ // Load the magic links plugins. We do that after BBCodes so that they use the same tags
+ $this->configure_autolink($configurator);
+
+ // Register some vars with a default value. Those should be set at runtime by whatever calls
+ // the parser
+ $configurator->registeredVars['max_font_size'] = 0;
+ $configurator->registeredVars['max_img_height'] = 0;
+ $configurator->registeredVars['max_img_width'] = 0;
+
+ // Load the Emoji plugin and modify its tag's template to obey viewsmilies
+ $configurator->Emoji->setImageSize(18);
+ $configurator->Emoji->useSVG();
+ $tag = $configurator->Emoji->getTag();
+ $tag->template = '<xsl:choose><xsl:when test="$S_VIEWSMILIES">' . str_replace('class="emoji"', 'class="smilies"', $tag->template) . '</xsl:when><xsl:otherwise><xsl:value-of select="."/></xsl:otherwise></xsl:choose>';
+
+ /**
+ * Modify the s9e\TextFormatter configurator after the default settings are set
+ *
+ * @event core.text_formatter_s9e_configure_after
+ * @var \s9e\TextFormatter\Configurator configurator Configurator instance
+ * @since 3.2.0-a1
+ */
+ $vars = array('configurator');
+ extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_after', compact($vars)));
+
+ return $configurator;
+ }
+
+ /**
+ * Regenerate and cache a new parser and renderer
+ *
+ * @return array Associative array with at least two elements: "parser" and "renderer"
+ */
+ public function regenerate()
+ {
+ $configurator = $this->get_configurator();
+
+ // Get the censor helper and remove the Censor plugin if applicable
+ if (isset($configurator->Censor))
+ {
+ $censor = $configurator->Censor->getHelper();
+ unset($configurator->Censor);
+ unset($configurator->tags['censor:tag']);
+ }
+
+ $objects = $configurator->finalize();
+ $parser = $objects['parser'];
+ $renderer = $objects['renderer'];
+
+ // Cache the parser as-is
+ $this->cache->put($this->cache_key_parser, $parser);
+
+ // We need to cache the name of the renderer's generated class
+ $renderer_data = array('class' => get_class($renderer));
+ if (isset($censor))
+ {
+ $renderer_data['censor'] = $censor;
+ }
+ $this->cache->put($this->cache_key_renderer, $renderer_data);
+
+ return array('parser' => $parser, 'renderer' => $renderer);
+ }
+
+ /**
+ * Configure the Autolink / Autoemail plugins used to linkify text
+ *
+ * @param \s9e\TextFormatter\Configurator $configurator
+ * @return void
+ */
+ protected function configure_autolink(Configurator $configurator)
+ {
+ $configurator->plugins->load('Autoemail');
+ $configurator->plugins->load('Autolink', array('matchWww' => true));
+
+ // Add a tag filter that creates a tag that stores and replace the
+ // content of a link created by the Autolink plugin
+ $configurator->Autolink->getTag()->filterChain
+ ->add(array($this->link_helper, 'generate_link_text_tag'))
+ ->resetParameters()
+ ->addParameterByName('tag')
+ ->addParameterByName('parser');
+
+ // Create a tag that will be used to display the truncated text by
+ // replacing the original content with the content of the @text attribute
+ $tag = $configurator->tags->add('LINK_TEXT');
+ $tag->attributes->add('text');
+ $tag->template = '<xsl:value-of select="@text"/>';
+
+ $tag->filterChain
+ ->add(array($this->link_helper, 'truncate_local_url'))
+ ->resetParameters()
+ ->addParameterByName('tag')
+ ->addParameterByValue(generate_board_url() . '/');
+ $tag->filterChain
+ ->add(array($this->link_helper, 'truncate_text'))
+ ->resetParameters()
+ ->addParameterByName('tag');
+ $tag->filterChain
+ ->add(array($this->link_helper, 'cleanup_tag'))
+ ->resetParameters()
+ ->addParameterByName('tag')
+ ->addParameterByName('parser');
+ }
+
+ /**
+ * Return the default BBCodes configuration
+ *
+ * @return array 2D array. Each element has a 'usage' key, a 'template' key, and an optional 'options' key
+ */
+ protected function get_default_bbcodes($configurator)
+ {
+ // For each BBCode, build an associative array matching style_ids to their template
+ $templates = array();
+ foreach ($this->data_access->get_styles_templates() as $style_id => $data)
+ {
+ foreach ($this->extract_templates($data['template']) as $bbcode_name => $template)
+ {
+ $templates[$bbcode_name][$style_id] = $template;
+ }
+
+ // Add default templates wherever missing, or for BBCodes that were not specified in
+ // this template's bitfield. For instance, prosilver has a custom template for b but its
+ // bitfield does not enable it so the default template is used instead
+ foreach ($this->default_templates as $bbcode_name => $template)
+ {
+ if (!isset($templates[$bbcode_name][$style_id]) || !in_array($bbcode_name, $data['bbcodes'], true))
+ {
+ $templates[$bbcode_name][$style_id] = $template;
+ }
+ }
+ }
+
+ // Replace custom tokens and normalize templates
+ foreach ($templates as $bbcode_name => $style_templates)
+ {
+ foreach ($style_templates as $i => $template)
+ {
+ if (isset($this->custom_tokens[$bbcode_name]))
+ {
+ $template = strtr($template, $this->custom_tokens[$bbcode_name]);
+ }
+
+ $templates[$bbcode_name][$i] = $configurator->templateNormalizer->normalizeTemplate($template);
+ }
+ }
+
+ $bbcodes = array();
+ foreach ($this->default_definitions as $bbcode_name => $usage)
+ {
+ $bbcodes[$bbcode_name] = array(
+ 'usage' => $usage,
+ 'template' => $this->merge_templates($templates[$bbcode_name]),
+ );
+ }
+
+ return $bbcodes;
+ }
+
+ /**
+ * Extract and recompose individual BBCode templates from a style's template file
+ *
+ * @param string $template Style template (bbcode.html)
+ * @return array Associative array matching BBCode names to their template
+ */
+ protected function extract_templates($template)
+ {
+ // Capture the template fragments
+ preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END .*? -->#s', $template, $matches, PREG_SET_ORDER);
+
+ $fragments = array();
+ foreach ($matches as $match)
+ {
+ // Normalize the whitespace
+ $fragment = preg_replace('#>\\n\\t*<#', '><', trim($match[2]));
+
+ $fragments[$match[1]] = $fragment;
+ }
+
+ // Automatically recompose templates split between *_open and *_close
+ foreach ($fragments as $fragment_name => $fragment)
+ {
+ if (preg_match('#^(\\w+)_close$#', $fragment_name, $match))
+ {
+ $bbcode_name = $match[1];
+
+ if (isset($fragments[$bbcode_name . '_open']))
+ {
+ $templates[$bbcode_name] = $fragments[$bbcode_name . '_open'] . '<xsl:apply-templates/>' . $fragment;
+ }
+ }
+ }
+
+ // Manually recompose and overwrite irregular templates
+ $templates['list'] =
+ '<xsl:choose>
+ <xsl:when test="not(@type)">
+ ' . $fragments['ulist_open_default'] . '<xsl:apply-templates/>' . $fragments['ulist_close'] . '
+ </xsl:when>
+ <xsl:when test="contains(\'upperlowerdecim\',substring(@type,1,5))">
+ ' . $fragments['olist_open'] . '<xsl:apply-templates/>' . $fragments['olist_close'] . '
+ </xsl:when>
+ <xsl:otherwise>
+ ' . $fragments['ulist_open'] . '<xsl:apply-templates/>' . $fragments['ulist_close'] . '
+ </xsl:otherwise>
+ </xsl:choose>';
+
+ $templates['li'] = $fragments['listitem'] . '<xsl:apply-templates/>' . $fragments['listitem_close'];
+
+ // Replace the regular quote template with the extended quote template if available
+ if (isset($fragments['quote_extended']))
+ {
+ $templates['quote'] = $fragments['quote_extended'];
+ }
+
+ // The [attachment] BBCode uses the inline_attachment template to output a comment that
+ // is post-processed by parse_attachments()
+ $templates['attachment'] = $fragments['inline_attachment_open'] . '<xsl:comment> ia<xsl:value-of select="@index"/> </xsl:comment><xsl:value-of select="@filename"/><xsl:comment> ia<xsl:value-of select="@index"/> </xsl:comment>' . $fragments['inline_attachment_close'];
+
+ // Add fragments as templates
+ foreach ($fragments as $fragment_name => $fragment)
+ {
+ if (preg_match('#^\\w+$#', $fragment_name))
+ {
+ $templates[$fragment_name] = $fragment;
+ }
+ }
+
+ // Keep only templates that are named after an existing BBCode
+ $templates = array_intersect_key($templates, $this->default_definitions);
+
+ return $templates;
+ }
+
+ /**
+ * Merge the templates from any number of styles into one BBCode template
+ *
+ * When multiple templates are available for the same BBCode (because of multiple styles) we
+ * merge them into a single template that uses an xsl:choose construct that determines which
+ * style to use at rendering time.
+ *
+ * @param array $style_templates Associative array matching style_ids to their template
+ * @return string
+ */
+ protected function merge_templates(array $style_templates)
+ {
+ // Return the template as-is if there's only one style or all styles share the same template
+ if (count(array_unique($style_templates)) === 1)
+ {
+ return end($style_templates);
+ }
+
+ // Group identical templates together
+ $grouped_templates = array();
+ foreach ($style_templates as $style_id => $style_template)
+ {
+ $grouped_templates[$style_template][] = '$STYLE_ID=' . $style_id;
+ }
+
+ // Sort templates by frequency descending
+ $templates_cnt = array_map('sizeof', $grouped_templates);
+ array_multisort($grouped_templates, $templates_cnt);
+
+ // Remove the most frequent template from the list; It becomes the default
+ reset($grouped_templates);
+ $default_template = key($grouped_templates);
+ unset($grouped_templates[$default_template]);
+
+ // Build an xsl:choose switch
+ $template = '<xsl:choose>';
+ foreach ($grouped_templates as $style_template => $exprs)
+ {
+ $template .= '<xsl:when test="' . implode(' or ', $exprs) . '">' . $style_template . '</xsl:when>';
+ }
+ $template .= '<xsl:otherwise>' . $default_template . '</xsl:otherwise></xsl:choose>';
+
+ return $template;
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/link_helper.php b/phpBB/phpbb/textformatter/s9e/link_helper.php
new file mode 100644
index 0000000000..0f44603dec
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/link_helper.php
@@ -0,0 +1,118 @@
+<?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;
+
+class link_helper
+{
+ /**
+ * Clean up and invalidate a LINK_TEXT tag if applicable
+ *
+ * Will invalidate the tag if its replacement text is the same as the original
+ * text and would have no visible effect
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag
+ * @param \s9e\TextFormatter\Parser $parser Parser
+ * @return bool Whether the tag is valid
+ */
+ 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'));
+ }
+
+ /**
+ * Create a LINK_TEXT tag inside of a link
+ *
+ * Meant to only apply to linkified URLs and [url] BBCodes without a parameter
+ *
+ * @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
+ */
+ public function generate_link_text_tag(\s9e\TextFormatter\Parser\Tag $tag, \s9e\TextFormatter\Parser $parser)
+ {
+ // Only create a LINK_TEXT tag if the start tag is paired with an end
+ // tag, which is the case with tags from the Autolink plugins and with
+ // the [url] BBCode when its content is used for the URL
+ if (!$tag->getEndTag() || !$this->should_shorten($tag, $parser->getText()))
+ {
+ return true;
+ }
+
+ // Capture the text between the start tag and its end tag
+ $start = $tag->getPos() + $tag->getLen();
+ $end = $tag->getEndTag()->getPos();
+ $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;
+ }
+
+ /**
+ * Test whether we should shorten this tag's text
+ *
+ * Will test whether the tag either does not use any markup or uses a single
+ * [url] BBCode
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag URL tag
+ * @param string $text Original text
+ * @return bool
+ */
+ protected function should_shorten(\s9e\TextFormatter\Parser\Tag $tag, $text)
+ {
+ return ($tag->getLen() === 0 || strtolower(substr($text, $tag->getPos(), $tag->getLen())) === '[url]');
+ }
+
+ /**
+ * Remove the board's root URL from a the start of a string
+ *
+ * @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
+ */
+ public function truncate_local_url(\s9e\TextFormatter\Parser\Tag $tag, $board_url)
+ {
+ $text = $tag->getAttribute('text');
+ if (stripos($text, $board_url) === 0 && strlen($text) > strlen($board_url))
+ {
+ $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
+ */
+ public function truncate_text(\s9e\TextFormatter\Parser\Tag $tag)
+ {
+ $text = $tag->getAttribute('text');
+ if (utf8_strlen($text) > 55)
+ {
+ $text = utf8_substr($text, 0, 39) . ' ... ' . utf8_substr($text, -10);
+ }
+
+ $tag->setAttribute('text', $text);
+
+ return true;
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php
new file mode 100644
index 0000000000..e2653d60f0
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/parser.php
@@ -0,0 +1,397 @@
+<?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 s9e\TextFormatter\Parser\BuiltInFilters;
+use s9e\TextFormatter\Parser\Logger;
+
+/**
+* s9e\TextFormatter\Parser adapter
+*/
+class parser implements \phpbb\textformatter\parser_interface
+{
+ /**
+ * @var \phpbb\event\dispatcher_interface
+ */
+ protected $dispatcher;
+
+ /**
+ * @var \s9e\TextFormatter\Parser
+ */
+ protected $parser;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\cache\driver_interface $cache
+ * @param string $key Cache key
+ * @param factory $factory
+ * @param \phpbb\event\dispatcher_interface $dispatcher
+ */
+ public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, factory $factory, \phpbb\event\dispatcher_interface $dispatcher)
+ {
+ $parser = $cache->get($key);
+ if (!$parser)
+ {
+ $objects = $factory->regenerate();
+ $parser = $objects['parser'];
+ }
+
+ $this->dispatcher = $dispatcher;
+ $this->parser = $parser;
+
+ $parser = $this;
+
+ /**
+ * Configure the parser service
+ *
+ * Can be used to:
+ * - toggle features or BBCodes
+ * - register variables or custom parsers in the s9e\TextFormatter parser
+ * - configure the s9e\TextFormatter parser's runtime settings
+ *
+ * @event core.text_formatter_s9e_parser_setup
+ * @var \phpbb\textformatter\s9e\parser parser This parser service
+ * @since 3.2.0-a1
+ */
+ $vars = array('parser');
+ extract($dispatcher->trigger_event('core.text_formatter_s9e_parser_setup', compact($vars)));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function parse($text)
+ {
+ $parser = $this;
+
+ /**
+ * Modify a text before it is parsed
+ *
+ * @event core.text_formatter_s9e_parse_before
+ * @var \phpbb\textformatter\s9e\parser parser This parser service
+ * @var string text The original text
+ * @since 3.2.0-a1
+ */
+ $vars = array('parser', 'text');
+ extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_before', compact($vars)));
+
+ $xml = $this->parser->parse($text);
+
+ /**
+ * Modify a parsed text in its XML form
+ *
+ * @event core.text_formatter_s9e_parse_after
+ * @var \phpbb\textformatter\s9e\parser parser This parser service
+ * @var string xml The parsed text, in XML
+ * @since 3.2.0-a1
+ */
+ $vars = array('parser', 'xml');
+ extract($this->dispatcher->trigger_event('core.text_formatter_s9e_parse_after', compact($vars)));
+
+ return $xml;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable_bbcode($name)
+ {
+ $this->parser->disableTag(strtoupper($name));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable_bbcodes()
+ {
+ $this->parser->disablePlugin('BBCodes');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable_censor()
+ {
+ $this->parser->disablePlugin('Censor');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable_magic_url()
+ {
+ $this->parser->disablePlugin('Autoemail');
+ $this->parser->disablePlugin('Autolink');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disable_smilies()
+ {
+ $this->parser->disablePlugin('Emoticons');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable_bbcode($name)
+ {
+ $this->parser->enableTag(strtoupper($name));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable_bbcodes()
+ {
+ $this->parser->enablePlugin('BBCodes');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable_censor()
+ {
+ $this->parser->enablePlugin('Censor');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable_magic_url()
+ {
+ $this->parser->enablePlugin('Autoemail');
+ $this->parser->enablePlugin('Autolink');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enable_smilies()
+ {
+ $this->parser->enablePlugin('Emoticons');
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * This will convert the log entries found in s9e\TextFormatter's logger into phpBB error
+ * messages
+ */
+ public function get_errors()
+ {
+ $errors = array();
+ foreach ($this->parser->getLogger()->get() as $entry)
+ {
+ list(, $msg, $context) = $entry;
+
+ if ($msg === 'Tag limit exceeded')
+ {
+ if ($context['tagName'] === 'E')
+ {
+ $errors[] = array('TOO_MANY_SMILIES', $context['tagLimit']);
+ }
+ else if ($context['tagName'] === 'URL')
+ {
+ $errors[] = array('TOO_MANY_URLS', $context['tagLimit']);
+ }
+ }
+ else if ($msg === 'MAX_FONT_SIZE_EXCEEDED')
+ {
+ $errors[] = array($msg, $context['max_size']);
+ }
+ else if (preg_match('/^MAX_(?:FLASH|IMG)_(HEIGHT|WIDTH)_EXCEEDED$/D', $msg, $m))
+ {
+ $errors[] = array($msg, $context['max_' . strtolower($m[1])]);
+ }
+ else if ($msg === 'Tag is disabled')
+ {
+ $name = strtolower($context['tag']->getName());
+ $errors[] = array('UNAUTHORISED_BBCODE', '[' . $name . ']');
+ }
+ else if ($msg === 'UNABLE_GET_IMAGE_SIZE')
+ {
+ $errors[] = array($msg);
+ }
+ }
+
+ // Deduplicate error messages. array_unique() only works on strings so we have to serialize
+ if (!empty($errors))
+ {
+ $errors = array_map('unserialize', array_unique(array_map('serialize', $errors)));
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Return the instance of s9e\TextFormatter\Parser used by this object
+ *
+ * @return \s9e\TextFormatter\Parser
+ */
+ public function get_parser()
+ {
+ return $this->parser;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_var($name, $value)
+ {
+ if ($name === 'max_smilies')
+ {
+ $this->parser->setTagLimit('E', $value ?: PHP_INT_MAX);
+ }
+ else if ($name === 'max_urls')
+ {
+ $this->parser->setTagLimit('URL', $value ?: PHP_INT_MAX);
+ }
+ else
+ {
+ $this->parser->registeredVars[$name] = $value;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_vars(array $vars)
+ {
+ foreach ($vars as $name => $value)
+ {
+ $this->set_var($name, $value);
+ }
+ }
+
+ /**
+ * Filter a flash object's height
+ *
+ * @see bbcode_firstpass::bbcode_flash()
+ *
+ * @param string $height
+ * @param integer $max_height
+ * @param Logger $logger
+ * @return mixed Original value if valid, FALSE otherwise
+ */
+ static public function filter_flash_height($height, $max_height, Logger $logger)
+ {
+ if ($max_height && $height > $max_height)
+ {
+ $logger->err('MAX_FLASH_HEIGHT_EXCEEDED', array('max_height' => $max_height));
+
+ return false;
+ }
+
+ return $height;
+ }
+
+ /**
+ * Filter a flash object's width
+ *
+ * @see bbcode_firstpass::bbcode_flash()
+ *
+ * @param string $width
+ * @param integer $max_width
+ * @param Logger $logger
+ * @return mixed Original value if valid, FALSE otherwise
+ */
+ static public function filter_flash_width($width, $max_width, Logger $logger)
+ {
+ if ($max_width && $width > $max_width)
+ {
+ $logger->err('MAX_FLASH_WIDTH_EXCEEDED', array('max_width' => $max_width));
+
+ return false;
+ }
+
+ return $width;
+ }
+
+ /**
+ * Filter the value used in a [size] BBCode
+ *
+ * @see bbcode_firstpass::bbcode_size()
+ *
+ * @param string $size Original size
+ * @param integer $max_size Maximum allowed size
+ * @param Logger $logger
+ * @return mixed Original value if valid, FALSE otherwise
+ */
+ static public function filter_font_size($size, $max_size, Logger $logger)
+ {
+ if ($max_size && $size > $max_size)
+ {
+ $logger->err('MAX_FONT_SIZE_EXCEEDED', array('max_size' => $max_size));
+
+ return false;
+ }
+
+ if ($size < 1)
+ {
+ return false;
+ }
+
+ return $size;
+ }
+
+ /**
+ * Filter an image's URL to enforce restrictions on its dimensions
+ *
+ * @see bbcode_firstpass::bbcode_img()
+ *
+ * @param string $url Original URL
+ * @param array $url_config Config used by the URL filter
+ * @param Logger $logger
+ * @param integer $max_height Maximum height allowed
+ * @param integer $max_width Maximum width allowed
+ * @return string|bool Original value if valid, FALSE otherwise
+ */
+ 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);
+ if ($url === false)
+ {
+ return false;
+ }
+
+ if ($max_height || $max_width)
+ {
+ $imagesize = new \FastImageSize\FastImageSize();
+ $size_info = $imagesize->getImageSize($url);
+ if ($size_info === false)
+ {
+ $logger->err('UNABLE_GET_IMAGE_SIZE');
+ return false;
+ }
+
+ if ($max_height && $max_height < $size_info['height'])
+ {
+ $logger->err('MAX_IMG_HEIGHT_EXCEEDED', array('max_height' => $max_height));
+ return false;
+ }
+
+ if ($max_width && $max_width < $size_info['width'])
+ {
+ $logger->err('MAX_IMG_WIDTH_EXCEEDED', array('max_width' => $max_width));
+ return false;
+ }
+ }
+
+ return $url;
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/quote_helper.php b/phpBB/phpbb/textformatter/s9e/quote_helper.php
new file mode 100644
index 0000000000..24109ac8cc
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/quote_helper.php
@@ -0,0 +1,81 @@
+<?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;
+
+class quote_helper
+{
+ /**
+ * @var string Base URL for a post link, uses {POST_ID} as placeholder
+ */
+ protected $post_url;
+
+ /**
+ * @var string Base URL for a profile link, uses {USER_ID} as placeholder
+ */
+ protected $profile_url;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\user $user
+ * @param string $root_path
+ * @param string $php_ext
+ */
+ public function __construct(\phpbb\user $user, $root_path, $php_ext)
+ {
+ $this->post_url = append_sid($root_path . 'viewtopic.' . $php_ext, 'p={POST_ID}#p{POST_ID}');
+ $this->profile_url = append_sid($root_path . 'memberlist.' . $php_ext, 'mode=viewprofile&u={USER_ID}');
+ $this->user = $user;
+ }
+
+ /**
+ * Inject dynamic metadata into QUOTE tags in given XML
+ *
+ * @param string $xml Original XML
+ * @return string Modified XML
+ */
+ public function inject_metadata($xml)
+ {
+ $post_url = $this->post_url;
+ $profile_url = $this->profile_url;
+ $user = $this->user;
+
+ return \s9e\TextFormatter\Utils::replaceAttributes(
+ $xml,
+ 'QUOTE',
+ function ($attributes) use ($post_url, $profile_url, $user)
+ {
+ if (isset($attributes['post_id']))
+ {
+ $attributes['post_url'] = str_replace('{POST_ID}', $attributes['post_id'], $post_url);
+ }
+ if (isset($attributes['time']))
+ {
+ $attributes['date'] = $user->format_date($attributes['time']);
+ }
+ if (isset($attributes['user_id']))
+ {
+ $attributes['profile_url'] = str_replace('{USER_ID}', $attributes['user_id'], $profile_url);
+ }
+
+ return $attributes;
+ }
+ );
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php
new file mode 100644
index 0000000000..9be20b7f53
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/renderer.php
@@ -0,0 +1,315 @@
+<?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;
+
+/**
+* s9e\TextFormatter\Renderer adapter
+*/
+class renderer implements \phpbb\textformatter\renderer_interface
+{
+ /**
+ * @var \s9e\TextFormatter\Plugins\Censor\Helper
+ */
+ protected $censor;
+
+ /**
+ * @var \phpbb\event\dispatcher_interface
+ */
+ protected $dispatcher;
+
+ /**
+ * @var quote_helper
+ */
+ protected $quote_helper;
+
+ /**
+ * @var \s9e\TextFormatter\Renderer
+ */
+ protected $renderer;
+
+ /**
+ * @var bool Status of the viewcensors option
+ */
+ protected $viewcensors = false;
+
+ /**
+ * @var bool Status of the viewflash option
+ */
+ protected $viewflash = false;
+
+ /**
+ * @var bool Status of the viewimg option
+ */
+ protected $viewimg = false;
+
+ /**
+ * @var bool Status of the viewsmilies option
+ */
+ protected $viewsmilies = false;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\cache\driver\driver_interface $cache
+ * @param string $cache_dir Path to the cache dir
+ * @param string $key Cache key
+ * @param factory $factory
+ * @param \phpbb\event\dispatcher_interface $dispatcher
+ */
+ public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, factory $factory, \phpbb\event\dispatcher_interface $dispatcher)
+ {
+ $renderer_data = $cache->get($key);
+ if ($renderer_data)
+ {
+ $class = $renderer_data['class'];
+ if (!class_exists($class, false))
+ {
+ // Try to load the renderer class from its cache file
+ $cache_file = $cache_dir . $class . '.php';
+
+ if (file_exists($cache_file))
+ {
+ include($cache_file);
+ }
+ }
+ if (class_exists($class, false))
+ {
+ $renderer = new $class;
+ }
+ if (isset($renderer_data['censor']))
+ {
+ $censor = $renderer_data['censor'];
+ }
+ }
+ if (!isset($renderer))
+ {
+ $objects = $factory->regenerate();
+ $renderer = $objects['renderer'];
+ }
+
+ if (isset($censor))
+ {
+ $this->censor = $censor;
+ }
+ $this->dispatcher = $dispatcher;
+ $this->renderer = $renderer;
+ $renderer = $this;
+
+ /**
+ * Configure the renderer service
+ *
+ * @event core.text_formatter_s9e_renderer_setup
+ * @var \phpbb\textformatter\s9e\renderer renderer This renderer service
+ * @since 3.2.0-a1
+ */
+ $vars = array('renderer');
+ extract($dispatcher->trigger_event('core.text_formatter_s9e_renderer_setup', compact($vars)));
+ }
+
+ /**
+ * Configure the quote_helper object used to display extended information in quotes
+ *
+ * @param quote_helper $quote_helper
+ */
+ public function configure_quote_helper(quote_helper $quote_helper)
+ {
+ $this->quote_helper = $quote_helper;
+ }
+
+ /**
+ * Automatically set the smilies path based on config
+ *
+ * @param \phpbb\config\config $config
+ * @param \phpbb\path_helper $path_helper
+ * @return null
+ */
+ public function configure_smilies_path(\phpbb\config\config $config, \phpbb\path_helper $path_helper)
+ {
+ /**
+ * @see smiley_text()
+ */
+ $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $path_helper->get_web_root_path();
+
+ $this->set_smilies_path($root_path . $config['smilies_path']);
+ }
+
+ /**
+ * Configure this renderer as per the user's settings
+ *
+ * Should set the locale as well as the viewcensor/viewflash/viewimg/viewsmilies options.
+ *
+ * @param \phpbb\user $user
+ * @param \phpbb\config\config $config
+ * @param \phpbb\auth\auth $auth
+ * @return null
+ */
+ public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth)
+ {
+ $censor = $user->optionget('viewcensors') || !$config['allow_nocensors'] || !$auth->acl_get('u_chgcensors');
+
+ $this->set_viewcensors($censor);
+ $this->set_viewflash($user->optionget('viewflash'));
+ $this->set_viewimg($user->optionget('viewimg'));
+ $this->set_viewsmilies($user->optionget('viewsmilies'));
+
+ // Set the stylesheet parameters
+ foreach (array_keys($this->renderer->getParameters()) as $param_name)
+ {
+ if (strpos($param_name, 'L_') === 0)
+ {
+ // L_FOO is set to $user->lang('FOO')
+ $this->renderer->setParameter($param_name, $user->lang(substr($param_name, 2)));
+ }
+ }
+
+ // Set this user's style id and other parameters
+ $this->renderer->setParameters(array(
+ 'S_IS_BOT' => $user->data['is_bot'],
+ 'S_REGISTERED_USER' => $user->data['is_registered'],
+ 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS),
+ 'STYLE_ID' => $user->style['style_id'],
+ ));
+ }
+
+ /**
+ * Return the instance of s9e\TextFormatter\Renderer used by this object
+ *
+ * @return \s9e\TextFormatter\Renderer
+ */
+ public function get_renderer()
+ {
+ return $this->renderer;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_viewcensors()
+ {
+ return $this->viewcensors;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_viewflash()
+ {
+ return $this->viewflash;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_viewimg()
+ {
+ return $this->viewimg;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_viewsmilies()
+ {
+ return $this->viewsmilies;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render($xml)
+ {
+ if (isset($this->quote_helper))
+ {
+ $xml = $this->quote_helper->inject_metadata($xml);
+ }
+
+ $renderer = $this;
+
+ /**
+ * Modify a parsed text before it is rendered
+ *
+ * @event core.text_formatter_s9e_render_before
+ * @var \phpbb\textformatter\s9e\renderer renderer This renderer service
+ * @var string xml The parsed text, in its XML form
+ * @since 3.2.0-a1
+ */
+ $vars = array('renderer', 'xml');
+ extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_before', compact($vars)));
+
+ if (isset($this->censor) && $this->viewcensors)
+ {
+ // NOTE: censorHtml() is XML-safe
+ $xml = $this->censor->censorHtml($xml, true);
+ }
+
+ $html = $this->renderer->render($xml);
+
+ /**
+ * Modify a rendered text
+ *
+ * @event core.text_formatter_s9e_render_after
+ * @var string html The rendered text's HTML
+ * @var \phpbb\textformatter\s9e\renderer renderer This renderer service
+ * @since 3.2.0-a1
+ */
+ $vars = array('html', 'renderer');
+ extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_after', compact($vars)));
+
+ return $html;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_smilies_path($path)
+ {
+ $this->renderer->setParameter('T_SMILIES_PATH', $path);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_viewcensors($value)
+ {
+ $this->viewcensors = $value;
+ $this->renderer->setParameter('S_VIEWCENSORS', $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_viewflash($value)
+ {
+ $this->viewflash = $value;
+ $this->renderer->setParameter('S_VIEWFLASH', $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_viewimg($value)
+ {
+ $this->viewimg = $value;
+ $this->renderer->setParameter('S_VIEWIMG', $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set_viewsmilies($value)
+ {
+ $this->viewsmilies = $value;
+ $this->renderer->setParameter('S_VIEWSMILIES', $value);
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php
new file mode 100644
index 0000000000..b317fe4a8d
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/utils.php
@@ -0,0 +1,139 @@
+<?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;
+
+/**
+* Text manipulation utilities
+*/
+class utils implements \phpbb\textformatter\utils_interface
+{
+ /**
+ * Replace BBCodes and other formatting elements with whitespace
+ *
+ * NOTE: preserves smilies as text
+ *
+ * @param string $xml Parsed text
+ * @return string Plain text
+ */
+ public function clean_formatting($xml)
+ {
+ // Insert a space before <s> and <e> then remove formatting
+ $xml = preg_replace('#<[es]>#', ' $0', $xml);
+
+ return \s9e\TextFormatter\Utils::removeFormatting($xml);
+ }
+
+ /**
+ * Format given string to be used as an attribute value
+ *
+ * Will return the string as-is if it can be used in a BBCode without quotes. Otherwise,
+ * it will use either single- or double- quotes depending on whichever requires less escaping.
+ * Quotes and backslashes are escaped with backslashes where necessary
+ *
+ * @param string $str Original string
+ * @return string Same string if possible, escaped string within quotes otherwise
+ */
+ protected function format_attribute_value($str)
+ {
+ if (!preg_match('/[ "\'\\\\\\]]/', $str))
+ {
+ // Return as-is if it contains none of: space, ' " \ or ]
+ return $str;
+ }
+ $singleQuoted = "'" . addcslashes($str, "\\'") . "'";
+ $doubleQuoted = '"' . addcslashes($str, '\\"') . '"';
+
+ return (strlen($singleQuoted) < strlen($doubleQuoted)) ? $singleQuoted : $doubleQuoted;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function generate_quote($text, array $attributes = array())
+ {
+ $text = trim($text);
+ $quote = '[quote';
+ if (isset($attributes['author']))
+ {
+ // Add the author as the BBCode's default attribute
+ $quote .= '=' . $this->format_attribute_value($attributes['author']);
+ unset($attributes['author']);
+ }
+
+ if (isset($attributes['user_id']) && $attributes['user_id'] == ANONYMOUS)
+ {
+ unset($attributes['user_id']);
+ }
+
+ ksort($attributes);
+ foreach ($attributes as $name => $value)
+ {
+ $quote .= ' ' . $name . '=' . $this->format_attribute_value($value);
+ }
+ $quote .= ']';
+ $newline = (strlen($quote . $text . '[/quote]') > 80 || strpos($text, "\n") !== false) ? "\n" : '';
+ $quote .= $newline . $text . $newline . '[/quote]';
+
+ return $quote;
+ }
+
+ /**
+ * Get a list of quote authors, limited to the outermost quotes
+ *
+ * @param string $xml Parsed text
+ * @return string[] List of authors
+ */
+ public function get_outermost_quote_authors($xml)
+ {
+ $authors = array();
+ if (strpos($xml, '<QUOTE ') === false)
+ {
+ return $authors;
+ }
+
+ $dom = new \DOMDocument;
+ $dom->loadXML($xml);
+ $xpath = new \DOMXPath($dom);
+ foreach ($xpath->query('//QUOTE[not(ancestor::QUOTE)]/@author') as $author)
+ {
+ $authors[] = $author->textContent;
+ }
+
+ return $authors;
+ }
+
+ /**
+ * Remove given BBCode and its content, at given nesting depth
+ *
+ * @param string $xml Parsed text
+ * @param string $bbcode_name BBCode's name
+ * @param integer $depth Minimum nesting depth (number of parents of the same name)
+ * @return string Parsed text
+ */
+ public function remove_bbcode($xml, $bbcode_name, $depth = 0)
+ {
+ return \s9e\TextFormatter\Utils::removeTag($xml, strtoupper($bbcode_name), $depth);
+ }
+
+ /**
+ * Return a parsed text to its original form
+ *
+ * @param string $xml Parsed text
+ * @return string Original plain text
+ */
+ public function unparse($xml)
+ {
+ return \s9e\TextFormatter\Unparser::unparse($xml);
+ }
+}
diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php
new file mode 100644
index 0000000000..4810453cd1
--- /dev/null
+++ b/phpBB/phpbb/textformatter/utils_interface.php
@@ -0,0 +1,71 @@
+<?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;
+
+/**
+* Used to manipulate a parsed text
+*/
+interface utils_interface
+{
+ /**
+ * Replace BBCodes and other formatting elements with whitespace
+ *
+ * NOTE: preserves smilies as text
+ *
+ * @param string $text Parsed text
+ * @return string Plain text
+ */
+ public function clean_formatting($text);
+
+ /**
+ * Create a quote block for given text
+ *
+ * Possible attributes:
+ * - author: author's name (usually a username)
+ * - post_id: post_id of the post being quoted
+ * - user_id: user_id of the user being quoted
+ * - time: timestamp of the original message
+ *
+ * @param string $text Quote's text
+ * @param array $attributes Quote's attributes
+ * @return string Quote block to be used in a new post/text
+ */
+ public function generate_quote($text, array $attributes = array());
+
+ /**
+ * Get a list of quote authors, limited to the outermost quotes
+ *
+ * @param string $text Parsed text
+ * @return string[] List of authors
+ */
+ public function get_outermost_quote_authors($text);
+
+ /**
+ * Remove given BBCode and its content, at given nesting depth
+ *
+ * @param string $text Parsed text
+ * @param string $bbcode_name BBCode's name
+ * @param integer $depth Minimum nesting depth (number of parents of the same name)
+ * @return string Parsed text
+ */
+ public function remove_bbcode($text, $bbcode_name, $depth = 0);
+
+ /**
+ * Return a parsed text to its original form
+ *
+ * @param string $text Parsed text
+ * @return string Original plain text
+ */
+ public function unparse($text);
+}
diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php
new file mode 100644
index 0000000000..afa5ccacad
--- /dev/null
+++ b/phpBB/phpbb/textreparser/base.php
@@ -0,0 +1,244 @@
+<?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\textreparser;
+
+abstract class base implements reparser_interface
+{
+ /**
+ * @var bool Whether to save changes to the database
+ */
+ protected $save_changes = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ abstract public function get_max_id();
+
+ /**
+ * Return all records in given range
+ *
+ * @param integer $min_id Lower bound
+ * @param integer $max_id Upper bound
+ * @return array Array of records
+ */
+ abstract protected function get_records_by_range($min_id, $max_id);
+
+ /**
+ * {@inheritdoc}
+ */
+ abstract protected function save_record(array $record);
+
+ /**
+ * Add fields to given record, if applicable
+ *
+ * The enable_* fields are not always saved to the database. Sometimes we need to guess their
+ * original value based on the text content or possibly other fields
+ *
+ * @param array $record Original record
+ * @return array Complete record
+ */
+ protected function add_missing_fields(array $record)
+ {
+ if (!isset($record['enable_bbcode'], $record['enable_smilies'], $record['enable_magic_url']))
+ {
+ if (isset($record['options']))
+ {
+ $record += array(
+ 'enable_bbcode' => (bool) ($record['options'] & OPTION_FLAG_BBCODE),
+ 'enable_smilies' => (bool) ($record['options'] & OPTION_FLAG_SMILIES),
+ 'enable_magic_url' => (bool) ($record['options'] & OPTION_FLAG_LINKS),
+ );
+ }
+ else
+ {
+ $record += array(
+ 'enable_bbcode' => $this->guess_bbcodes($record),
+ 'enable_smilies' => $this->guess_smilies($record),
+ 'enable_magic_url' => $this->guess_magic_url($record),
+ );
+ }
+ }
+
+ // Those BBCodes are disabled based on context and user permissions and that value is never
+ // stored in the database. Here we test whether they were used in the original text.
+ $bbcodes = array('flash', 'img', 'quote', 'url');
+ foreach ($bbcodes as $bbcode)
+ {
+ $field_name = 'enable_' . $bbcode . '_bbcode';
+ $record[$field_name] = $this->guess_bbcode($record, $bbcode);
+ }
+
+ // Magic URLs are tied to the URL BBCode, that's why if magic URLs are enabled we make sure
+ // that the URL BBCode is also enabled
+ if ($record['enable_magic_url'])
+ {
+ $record['enable_url_bbcode'] = true;
+ }
+
+ return $record;
+ }
+
+ /**
+ * Disable saving changes to the database
+ */
+ public function disable_save()
+ {
+ $this->save_changes = false;
+ }
+
+ /**
+ * Enable saving changes to the database
+ */
+ public function enable_save()
+ {
+ $this->save_changes = true;
+ }
+
+ /**
+ * Guess whether given BBCode is in use in given record
+ *
+ * @param array $record
+ * @param string $bbcode
+ * @return bool
+ */
+ protected function guess_bbcode(array $record, $bbcode)
+ {
+ if (!empty($record['bbcode_uid']))
+ {
+ // Look for the closing tag, e.g. [/url]
+ $match = '[/' . $bbcode . ':' . $record['bbcode_uid'];
+ if (strpos($record['text'], $match) !== false)
+ {
+ return true;
+ }
+ }
+
+ if (substr($record['text'], 0, 2) === '<r')
+ {
+ // 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)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Guess whether any BBCode is in use in given record
+ *
+ * @param array $record
+ * @return bool
+ */
+ protected function guess_bbcodes(array $record)
+ {
+ if (!empty($record['bbcode_uid']))
+ {
+ // Test whether the bbcode_uid is in use
+ $match = ':' . $record['bbcode_uid'];
+ if (strpos($record['text'], $match) !== false)
+ {
+ return true;
+ }
+ }
+
+ if (substr($record['text'], 0, 2) === '<r')
+ {
+ // Look for a closing tag inside of an e element
+ return (bool) preg_match('(<e>\\[/\\w+\\]</e>)', $match);
+ }
+
+ return false;
+ }
+
+ /**
+ * Guess whether magic URLs are in use in given record
+ *
+ * @param array $record
+ * @return bool
+ */
+ protected function guess_magic_url(array $record)
+ {
+ // Look for <!-- m --> or for a URL tag that's not immediately followed by <s>
+ return (strpos($record['text'], '<!-- m -->') !== false || preg_match('(<URL [^>]++>(?!<s>))', $record['text']));
+ }
+
+ /**
+ * Guess whether smilies are in use in given record
+ *
+ * @param array $record
+ * @return bool
+ */
+ protected function guess_smilies(array $record)
+ {
+ return (strpos($record['text'], '<!-- s') !== false || strpos($record['text'], '<E>') !== false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reparse_range($min_id, $max_id)
+ {
+ foreach ($this->get_records_by_range($min_id, $max_id) as $record)
+ {
+ $this->reparse_record($record);
+ }
+ }
+
+ /**
+ * Reparse given record
+ *
+ * @param array $record Associative array containing the record's data
+ */
+ protected function reparse_record(array $record)
+ {
+ $record = $this->add_missing_fields($record);
+ $flags = ($record['enable_bbcode']) ? OPTION_FLAG_BBCODE : 0;
+ $flags |= ($record['enable_smilies']) ? OPTION_FLAG_SMILIES : 0;
+ $flags |= ($record['enable_magic_url']) ? OPTION_FLAG_LINKS : 0;
+ $unparsed = array_merge(
+ $record,
+ generate_text_for_edit($record['text'], $record['bbcode_uid'], $flags)
+ );
+
+ // generate_text_for_edit() and decode_message() actually return the text as HTML. It has to
+ // be decoded to plain text before it can be reparsed
+ $text = html_entity_decode($unparsed['text'], ENT_QUOTES, 'UTF-8');
+ $bitfield = $flags = null;
+ generate_text_for_storage(
+ $text,
+ $unparsed['bbcode_uid'],
+ $bitfield,
+ $flags,
+ $unparsed['enable_bbcode'],
+ $unparsed['enable_magic_url'],
+ $unparsed['enable_smilies'],
+ $unparsed['enable_img_bbcode'],
+ $unparsed['enable_flash_bbcode'],
+ $unparsed['enable_quote_bbcode'],
+ $unparsed['enable_url_bbcode'],
+ 'reparse'
+ );
+
+ // Save the new text if it has changed and it's not a dry run
+ if ($text !== $record['text'] && $this->save_changes)
+ {
+ $record['text'] = $text;
+ $this->save_record($record);
+ }
+ }
+}
diff --git a/phpBB/phpbb/textreparser/manager.php b/phpBB/phpbb/textreparser/manager.php
new file mode 100644
index 0000000000..fddd867923
--- /dev/null
+++ b/phpBB/phpbb/textreparser/manager.php
@@ -0,0 +1,128 @@
+<?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\textreparser;
+
+class manager
+{
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\config\db_text
+ */
+ protected $config_text;
+
+ /**
+ * @var \phpbb\di\service_collection
+ */
+ protected $reparsers;
+
+ /**
+ * @var array
+ */
+ protected $resume_data;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\config\config $config
+ * @param \phpbb\config\db_text $config_text
+ * @param \phpbb\di\service_collection $reparsers
+ */
+ public function __construct(\phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\di\service_collection $reparsers)
+ {
+ $this->config = $config;
+ $this->config_text = $config_text;
+ $this->reparsers = $reparsers;
+ }
+
+ /**
+ * Loads resume data from the database
+ *
+ * @param string $name Name of the reparser to which the resume data belongs
+ *
+ * @return array
+ */
+ public function get_resume_data($name)
+ {
+ if ($this->resume_data === null)
+ {
+ $resume_data = $this->config_text->get('reparser_resume');
+ $this->resume_data = !empty($resume_data) ? unserialize($resume_data) : array();
+ }
+
+ return isset($this->resume_data[$name]) ? $this->resume_data[$name] : array();
+ }
+
+ /**
+ * Updates the resume data in the database
+ *
+ * @param string $name Name of the reparser to which the resume data belongs
+ * @param int $min Lowest record ID
+ * @param int $current Current record ID
+ * @param int $size Number of records to process at a time
+ * @param bool $update_db True if the resume data should be written to the database, false if not. (default: true)
+ */
+ public function update_resume_data($name, $min, $current, $size, $update_db = true)
+ {
+ // Prevent overwriting the old, stored array
+ if ($this->resume_data === null)
+ {
+ $this->get_resume_data('');
+ }
+
+ $this->resume_data[$name] = array(
+ 'range-min' => $min,
+ 'range-max' => $current,
+ 'range-size' => $size,
+ );
+
+ if ($update_db)
+ {
+ $this->config_text->set('reparser_resume', serialize($this->resume_data));
+ }
+ }
+
+ /**
+ * Sets the interval for a text_reparser cron task
+ *
+ * @param string $name Name of the reparser to schedule
+ * @param int $interval Interval in seconds, 0 to disable the cron task
+ */
+ public function schedule($name, $interval)
+ {
+ if (isset($this->reparsers[$name]) && isset($this->config[$name . '_cron_interval']))
+ {
+ $this->config->set($name . '_cron_interval', $interval);
+ }
+ }
+
+ /**
+ * Sets the interval for all text_reparser cron tasks
+ *
+ * @param int $interval Interval in seconds, 0 to disable the cron task
+ */
+ public function schedule_all($interval)
+ {
+ // This way we don't construct every registered reparser
+ $reparser_array = array_keys($this->reparsers->getArrayCopy());
+
+ foreach ($reparser_array as $reparser)
+ {
+ $this->schedule($reparser, $interval);
+ }
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/contact_admin_info.php b/phpBB/phpbb/textreparser/plugins/contact_admin_info.php
new file mode 100644
index 0000000000..8910f2256b
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/contact_admin_info.php
@@ -0,0 +1,69 @@
+<?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\textreparser\plugins;
+
+class contact_admin_info extends \phpbb\textreparser\base
+{
+ /**
+ * @var \phpbb\config\db_text
+ */
+ protected $config_text;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\config\db_text $config_text
+ */
+ public function __construct(\phpbb\config\db_text $config_text)
+ {
+ $this->config_text = $config_text;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_max_id()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_records_by_range($min_id, $max_id)
+ {
+ $values = $this->config_text->get_array(array(
+ 'contact_admin_info',
+ 'contact_admin_info_uid',
+ 'contact_admin_info_flags',
+ ));
+
+ return array(array(
+ 'id' => 1,
+ 'text' => $values['contact_admin_info'],
+ 'bbcode_uid' => $values['contact_admin_info_uid'],
+ 'enable_bbcode' => $values['contact_admin_info_flags'] & OPTION_FLAG_BBCODE,
+ 'enable_magic_url' => $values['contact_admin_info_flags'] & OPTION_FLAG_LINKS,
+ 'enable_smilies' => $values['contact_admin_info_flags'] & OPTION_FLAG_SMILIES,
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function save_record(array $record)
+ {
+ $this->config_text->set('contact_admin_info', $record['text']);
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/forum_description.php b/phpBB/phpbb/textreparser/plugins/forum_description.php
new file mode 100644
index 0000000000..b0f5a42452
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/forum_description.php
@@ -0,0 +1,30 @@
+<?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\textreparser\plugins;
+
+class forum_description extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'forum_id',
+ 'text' => 'forum_desc',
+ 'bbcode_uid' => 'forum_desc_uid',
+ 'options' => 'forum_desc_options',
+ );
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/forum_rules.php b/phpBB/phpbb/textreparser/plugins/forum_rules.php
new file mode 100644
index 0000000000..d131d00707
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/forum_rules.php
@@ -0,0 +1,30 @@
+<?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\textreparser\plugins;
+
+class forum_rules extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'forum_id',
+ 'text' => 'forum_rules',
+ 'bbcode_uid' => 'forum_rules_uid',
+ 'options' => 'forum_rules_options',
+ );
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/group_description.php b/phpBB/phpbb/textreparser/plugins/group_description.php
new file mode 100644
index 0000000000..2c45c00474
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/group_description.php
@@ -0,0 +1,30 @@
+<?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\textreparser\plugins;
+
+class group_description extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'group_id',
+ 'text' => 'group_desc',
+ 'bbcode_uid' => 'group_desc_uid',
+ 'options' => 'group_desc_options',
+ );
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/pm_text.php b/phpBB/phpbb/textreparser/plugins/pm_text.php
new file mode 100644
index 0000000000..867da624ee
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/pm_text.php
@@ -0,0 +1,32 @@
+<?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\textreparser\plugins;
+
+class pm_text extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'msg_id',
+ 'enable_bbcode' => 'enable_bbcode',
+ 'enable_smilies' => 'enable_smilies',
+ 'enable_magic_url' => 'enable_magic_url',
+ 'text' => 'message_text',
+ 'bbcode_uid' => 'bbcode_uid',
+ );
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/poll_option.php b/phpBB/phpbb/textreparser/plugins/poll_option.php
new file mode 100644
index 0000000000..44cacfae62
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/poll_option.php
@@ -0,0 +1,74 @@
+<?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\textreparser\plugins;
+
+class poll_option extends \phpbb\textreparser\base
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db)
+ {
+ $this->db = $db;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_max_id()
+ {
+ $sql = 'SELECT MAX(topic_id) AS max_id FROM ' . POLL_OPTIONS_TABLE;
+ $result = $this->db->sql_query($sql);
+ $max_id = (int) $this->db->sql_fetchfield('max_id');
+ $this->db->sql_freeresult($result);
+
+ return $max_id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_records_by_range($min_id, $max_id)
+ {
+ $sql = 'SELECT o.topic_id, o.poll_option_id, o.poll_option_text AS text, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.bbcode_uid
+ FROM ' . POLL_OPTIONS_TABLE . ' o, ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
+ WHERE o.topic_id BETWEEN ' . $min_id . ' AND ' . $max_id .'
+ AND t.topic_id = o.topic_id
+ AND p.post_id = t.topic_first_post_id';
+ $result = $this->db->sql_query($sql);
+ $records = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $records;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function save_record(array $record)
+ {
+ $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
+ SET poll_option_text = '" . $this->db->sql_escape($record['text']) . "'
+ WHERE topic_id = " . $record['topic_id'] . '
+ AND poll_option_id = ' . $record['poll_option_id'];
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php
new file mode 100644
index 0000000000..76d30655c9
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/poll_title.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\textreparser\plugins;
+
+class poll_title extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'topic_id',
+ 'text' => 'poll_title',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_records_by_range_query($min_id, $max_id)
+ {
+ $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 p.post_id = t.topic_first_post_id';
+
+ return $sql;
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/post_text.php b/phpBB/phpbb/textreparser/plugins/post_text.php
new file mode 100644
index 0000000000..1c98e86067
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/post_text.php
@@ -0,0 +1,32 @@
+<?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\textreparser\plugins;
+
+class post_text extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'post_id',
+ 'enable_bbcode' => 'enable_bbcode',
+ 'enable_smilies' => 'enable_smilies',
+ 'enable_magic_url' => 'enable_magic_url',
+ 'text' => 'post_text',
+ 'bbcode_uid' => 'bbcode_uid',
+ );
+ }
+}
diff --git a/phpBB/phpbb/textreparser/plugins/user_signature.php b/phpBB/phpbb/textreparser/plugins/user_signature.php
new file mode 100644
index 0000000000..647d3a7b14
--- /dev/null
+++ b/phpBB/phpbb/textreparser/plugins/user_signature.php
@@ -0,0 +1,65 @@
+<?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\textreparser\plugins;
+
+class user_signature extends \phpbb\textreparser\row_based_plugin
+{
+ /**
+ * @var array Bit numbers used for user options
+ * @see \phpbb\user
+ */
+ protected $keyoptions;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function add_missing_fields(array $row)
+ {
+ if (!isset($this->keyoptions))
+ {
+ $this->save_keyoptions();
+ }
+
+ $options = $row['user_options'];
+ $row += array(
+ 'enable_bbcode' => phpbb_optionget($this->keyoptions['sig_bbcode'], $options),
+ 'enable_smilies' => phpbb_optionget($this->keyoptions['sig_smilies'], $options),
+ 'enable_magic_url' => phpbb_optionget($this->keyoptions['sig_links'], $options),
+ );
+
+ return parent::add_missing_fields($row);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_columns()
+ {
+ return array(
+ 'id' => 'user_id',
+ 'text' => 'user_sig',
+ 'bbcode_uid' => 'user_sig_bbcode_uid',
+ 'user_options' => 'user_options',
+ );
+ }
+
+ /**
+ * Save the keyoptions var from \phpbb\user
+ */
+ protected function save_keyoptions()
+ {
+ $class_vars = get_class_vars('phpbb\\user');
+ $this->keyoptions = $class_vars['keyoptions'];
+ }
+}
diff --git a/phpBB/phpbb/textreparser/reparser_interface.php b/phpBB/phpbb/textreparser/reparser_interface.php
new file mode 100644
index 0000000000..9ea1732870
--- /dev/null
+++ b/phpBB/phpbb/textreparser/reparser_interface.php
@@ -0,0 +1,32 @@
+<?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\textreparser;
+
+interface reparser_interface
+{
+ /**
+ * Return the highest ID for all existing records
+ *
+ * @return integer
+ */
+ public function get_max_id();
+
+ /**
+ * Reparse all records in given range
+ *
+ * @param integer $min_id Lower bound
+ * @param integer $max_id Upper bound
+ */
+ public function reparse_range($min_id, $max_id);
+}
diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php
new file mode 100644
index 0000000000..2d32104493
--- /dev/null
+++ b/phpBB/phpbb/textreparser/row_based_plugin.php
@@ -0,0 +1,117 @@
+<?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\textreparser;
+
+abstract class row_based_plugin extends base
+{
+ /**
+ * @var \phpbb\db\driver\driver_interface
+ */
+ protected $db;
+
+ /**
+ * @var string
+ */
+ protected $table;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param string $table
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, $table)
+ {
+ $this->db = $db;
+ $this->table = $table;
+ }
+
+ /**
+ * Return the name of the column that correspond to each field
+ *
+ * @return array
+ */
+ abstract public function get_columns();
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_max_id()
+ {
+ $columns = $this->get_columns();
+
+ $sql = 'SELECT MAX(' . $columns['id'] . ') AS max_id FROM ' . $this->table;
+ $result = $this->db->sql_query($sql);
+ $max_id = (int) $this->db->sql_fetchfield('max_id');
+ $this->db->sql_freeresult($result);
+
+ return $max_id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function get_records_by_range($min_id, $max_id)
+ {
+ $sql = $this->get_records_by_range_query($min_id, $max_id);
+ $result = $this->db->sql_query($sql);
+ $records = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $records;
+ }
+
+ /**
+ * Generate the query that retrieves all records for given range
+ *
+ * @param integer $min_id Lower bound
+ * @param integer $max_id Upper bound
+ * @return string SQL query
+ */
+ protected function get_records_by_range_query($min_id, $max_id)
+ {
+ $columns = $this->get_columns();
+ $fields = array();
+ foreach ($columns as $field_name => $column_name)
+ {
+ if ($column_name === $field_name)
+ {
+ $fields[] = $column_name;
+ }
+ else
+ {
+ $fields[] = $column_name . ' AS ' . $field_name;
+ }
+ }
+
+ $sql = 'SELECT ' . implode(', ', $fields) . '
+ FROM ' . $this->table . '
+ WHERE ' . $columns['id'] . ' BETWEEN ' . $min_id . ' AND ' . $max_id;
+
+ return $sql;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function save_record(array $record)
+ {
+ $columns = $this->get_columns();
+
+ $sql = 'UPDATE ' . $this->table . '
+ SET ' . $columns['text'] . " = '" . $this->db->sql_escape($record['text']) . "'
+ WHERE " . $columns['id'] . ' = ' . $record['id'];
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/phpbb/tree/nestedset.php b/phpBB/phpbb/tree/nestedset.php
index 8490c7c299..7149513fd9 100644
--- a/phpBB/phpbb/tree/nestedset.php
+++ b/phpBB/phpbb/tree/nestedset.php
@@ -391,7 +391,6 @@ abstract class nestedset implements \phpbb\tree\tree_interface
throw new \OutOfBoundsException($this->message_prefix . 'INVALID_PARENT');
}
- $diff = sizeof($move_items) * 2;
$sql_exclude_moved_items = $this->db->sql_in_set($this->column_item_id, $move_items, true);
$this->db->sql_transaction('begin');
@@ -490,7 +489,6 @@ abstract class nestedset implements \phpbb\tree\tree_interface
throw new \OutOfBoundsException($this->message_prefix . 'INVALID_PARENT');
}
- $diff = sizeof($move_items) * 2;
$sql_exclude_moved_items = $this->db->sql_in_set($this->column_item_id, $move_items, true);
$this->db->sql_transaction('begin');
diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php
index faedd79703..305510851c 100644
--- a/phpBB/phpbb/user.php
+++ b/phpBB/phpbb/user.php
@@ -21,8 +21,11 @@ namespace phpbb;
*/
class user extends \phpbb\session
{
- var $lang = array();
- var $help = array();
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
var $style = array();
var $date_format;
@@ -42,35 +45,63 @@ class user extends \phpbb\session
var $img_lang;
var $img_array = array();
+ /** @var bool */
+ protected $is_setup_flag;
+
// Able to add new options (up to id 31)
var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17);
/**
* Constructor to set the lang path
- * @param string $datetime_class Class name of datetime class
+ *
+ * @param \phpbb\language\language $lang phpBB's Language loader
+ * @param string $datetime_class Class name of datetime class
*/
- function __construct($datetime_class)
+ function __construct(\phpbb\language\language $lang, $datetime_class)
{
global $phpbb_root_path;
$this->lang_path = $phpbb_root_path . 'language/';
+ $this->language = $lang;
$this->datetime = $datetime_class;
+
+ $this->is_setup_flag = false;
}
/**
- * Function to set custom language path (able to use directory outside of phpBB)
- *
- * @param string $lang_path New language path used.
- * @access public
- */
- function set_custom_lang_path($lang_path)
+ * Returns whether user::setup was called
+ *
+ * @return bool
+ */
+ public function is_setup()
{
- $this->lang_path = $lang_path;
+ return $this->is_setup_flag;
+ }
- if (substr($this->lang_path, -1) != '/')
+ /**
+ * Magic getter for BC compatibility
+ *
+ * Implement array access for user::lang.
+ *
+ * @param string $param_name Name of the BC component the user want to access
+ *
+ * @return array The appropriate array
+ *
+ * @deprecated 3.2.0-dev (To be removed: 4.0.0)
+ */
+ public function __get($param_name)
+ {
+ if ($param_name === 'lang')
+ {
+ return $this->language->get_lang_array();
+ }
+ else if ($param_name === 'help')
{
- $this->lang_path .= '/';
+ $help_array = $this->language->get_lang_array();
+ return $help_array['__help'];
}
+
+ return array();
}
/**
@@ -81,6 +112,8 @@ class user extends \phpbb\session
global $db, $request, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
global $phpbb_dispatcher;
+ $this->language->set_default_language($config['default_lang']);
+
if ($this->data['user_id'] != ANONYMOUS)
{
$user_lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
@@ -98,6 +131,7 @@ class user extends \phpbb\session
{
$lang_override = $request->variable($config['cookie_name'] . '_lang', '', true, \phpbb\request\request_interface::COOKIE);
}
+
if ($lang_override)
{
$use_lang = basename($lang_override);
@@ -108,6 +142,7 @@ class user extends \phpbb\session
{
$user_lang_name = basename($config['default_lang']);
}
+
$user_date_format = $config['default_dateformat'];
$user_timezone = $config['board_timezone'];
@@ -187,6 +222,8 @@ class user extends \phpbb\session
$this->lang_name = $user_lang_name;
$this->date_format = $user_date_format;
+ $this->language->set_user_language($user_lang_name);
+
try
{
$this->timezone = new \DateTimeZone($user_timezone);
@@ -197,17 +234,6 @@ class user extends \phpbb\session
$this->timezone = new \DateTimeZone('UTC');
}
- // We include common language file here to not load it every time a custom language file is included
- $lang = &$this->lang;
-
- // Do not suppress error if in DEBUG mode
- $include_result = (defined('DEBUG')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx");
-
- if ($include_result === false)
- {
- die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened.");
- }
-
$this->add_lang($lang_set);
unset($lang_set);
@@ -401,6 +427,8 @@ class user extends \phpbb\session
}
}
+ $this->is_setup_flag = true;
+
return;
}
@@ -414,103 +442,13 @@ class user extends \phpbb\session
*
* If the first parameter is an array, the elements are used as keys and subkeys to get the language entry:
* Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry.
+ *
+ * @deprecated 3.2.0-dev (To be removed 4.0.0)
*/
function lang()
{
$args = func_get_args();
- $key = $args[0];
-
- if (is_array($key))
- {
- $lang = &$this->lang[array_shift($key)];
-
- foreach ($key as $_key)
- {
- $lang = &$lang[$_key];
- }
- }
- else
- {
- $lang = &$this->lang[$key];
- }
-
- // Return if language string does not exist
- if (!isset($lang) || (!is_string($lang) && !is_array($lang)))
- {
- return $key;
- }
-
- // If the language entry is a string, we simply mimic sprintf() behaviour
- if (is_string($lang))
- {
- if (sizeof($args) == 1)
- {
- return $lang;
- }
-
- // Replace key with language entry and simply pass along...
- $args[0] = $lang;
- return call_user_func_array('sprintf', $args);
- }
- else if (sizeof($lang) == 0)
- {
- // If the language entry is an empty array, we just return the language key
- return $args[0];
- }
-
- // It is an array... now handle different nullar/singular/plural forms
- $key_found = false;
-
- // We now get the first number passed and will select the key based upon this number
- for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++)
- {
- if (is_int($args[$i]) || is_float($args[$i]))
- {
- if ($args[$i] == 0 && isset($lang[0]))
- {
- // We allow each translation using plural forms to specify a version for the case of 0 things,
- // so that "0 users" may be displayed as "No users".
- $key_found = 0;
- break;
- }
- else
- {
- $use_plural_form = $this->get_plural_form($args[$i]);
- if (isset($lang[$use_plural_form]))
- {
- // The key we should use exists, so we use it.
- $key_found = $use_plural_form;
- }
- else
- {
- // If the key we need to use does not exist, we fall back to the previous one.
- $numbers = array_keys($lang);
-
- foreach ($numbers as $num)
- {
- if ($num > $use_plural_form)
- {
- break;
- }
-
- $key_found = $num;
- }
- }
- break;
- }
- }
- }
-
- // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form)
- if ($key_found === false)
- {
- $numbers = array_keys($lang);
- $key_found = end($numbers);
- }
-
- // Use the language string we determined and pass it to sprintf()
- $args[0] = $lang[$key_found];
- return call_user_func_array('sprintf', $args);
+ return call_user_func_array(array($this->language, 'lang'), $args);
}
/**
@@ -520,24 +458,22 @@ class user extends \phpbb\session
* @param $number int|float The number we want to get the plural case for. Float numbers are floored.
* @param $force_rule mixed False to use the plural rule of the language package
* or an integer to force a certain plural rule
- * @return int The plural-case we need to use for the number plural-rule combination
+ * @return int|bool The plural-case we need to use for the number plural-rule combination, false if $force_rule
+ * was invalid.
+ *
+ * @deprecated: 3.2.0-dev (To be removed: 3.3.0)
*/
function get_plural_form($number, $force_rule = false)
{
- $number = (int) $number;
-
- // Default to English system
- $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1);
-
- return phpbb_get_plural_form($plural_rule, $number);
+ return $this->language->get_plural_form($number, $force_rule);
}
/**
* Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
*
* @param mixed $lang_set specifies the language entries to include
- * @param bool $use_db internal variable for recursion, do not use
- * @param bool $use_help internal variable for recursion, do not use
+ * @param bool $use_db internal variable for recursion, do not use @deprecated 3.2.0-dev (To be removed: 3.3.0)
+ * @param bool $use_help internal variable for recursion, do not use @deprecated 3.2.0-dev (To be removed: 3.3.0)
* @param string $ext_name The extension to load language from, or empty for core files
*
* Examples:
@@ -548,11 +484,14 @@ class user extends \phpbb\session
* $lang_set = 'posting'
* $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
* </code>
+ *
+ * Note: $use_db and $use_help should be removed. The old function was kept for BC purposes,
+ * so the BC logic is handled here.
+ *
+ * @deprecated: 3.2.0-dev (To be removed: 3.3.0)
*/
function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '')
{
- global $phpEx;
-
if (is_array($lang_set))
{
foreach ($lang_set as $key => $lang_file)
@@ -563,6 +502,7 @@ class user extends \phpbb\session
if ($key == 'db')
{
+ // This is never used
$this->add_lang($lang_file, true, $use_help, $ext_name);
}
else if ($key == 'help')
@@ -571,7 +511,7 @@ class user extends \phpbb\session
}
else if (!is_array($lang_file))
{
- $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name);
+ $this->set_lang($lang_file, $use_help, $ext_name);
}
else
{
@@ -582,8 +522,37 @@ class user extends \phpbb\session
}
else if ($lang_set)
{
- $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name);
+ $this->set_lang($lang_set, $use_help, $ext_name);
+ }
+ }
+
+ /**
+ * BC function for loading language files
+ *
+ * @deprecated 3.2.0-dev (To be removed: 3.3.0)
+ */
+ private function set_lang($lang_set, $use_help, $ext_name)
+ {
+ if (empty($ext_name))
+ {
+ $ext_name = null;
}
+
+ if ($use_help && strpos($lang_set, '/') !== false)
+ {
+ $component = dirname($lang_set) . '/help_' . basename($lang_set);
+
+ if ($component[0] === '/')
+ {
+ $component = substr($component, 1);
+ }
+ }
+ else
+ {
+ $component = (($use_help) ? 'help_' : '') . $lang_set;
+ }
+
+ $this->language->add_lang($component, $ext_name);
}
/**
@@ -593,6 +562,10 @@ class user extends \phpbb\session
* @param mixed $lang_set specifies the language entries to include
* @param bool $use_db internal variable for recursion, do not use
* @param bool $use_help internal variable for recursion, do not use
+ *
+ * Note: $use_db and $use_help should be removed. Kept for BC purposes.
+ *
+ * @deprecated: 3.2.0-dev (To be removed: 3.3.0)
*/
function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false)
{
@@ -605,109 +578,6 @@ class user extends \phpbb\session
}
/**
- * Set language entry (called by add_lang)
- * @access private
- */
- function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '')
- {
- global $phpbb_root_path, $phpEx;
-
- // Make sure the language name is set (if the user setup did not happen it is not set)
- if (!$this->lang_name)
- {
- global $config;
- $this->lang_name = basename($config['default_lang']);
- }
-
- // $lang == $this->lang
- // $help == $this->help
- // - add appropriate variables here, name them as they are used within the language file...
- if (!$use_db)
- {
- if ($use_help && strpos($lang_file, '/') !== false)
- {
- $filename = dirname($lang_file) . '/help_' . basename($lang_file);
- }
- else
- {
- $filename = (($use_help) ? 'help_' : '') . $lang_file;
- }
-
- if ($ext_name)
- {
- global $phpbb_extension_manager;
- $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true);
-
- $lang_path = $ext_path . 'language/';
- }
- else
- {
- $lang_path = $this->lang_path;
- }
-
- if (strpos($phpbb_root_path . $filename, $lang_path) === 0)
- {
- $language_filename = $phpbb_root_path . $filename;
- }
- else
- {
- $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx;
- }
-
- // If we are in install, try to use the updated version, when available
- $install_language_filename = str_replace('language/', 'install/update/new/language/', $language_filename);
- if (defined('IN_INSTALL') && file_exists($install_language_filename))
- {
- $language_filename = $install_language_filename;
- }
-
- if (!file_exists($language_filename))
- {
- global $config;
-
- if ($this->lang_name == 'en')
- {
- // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en.
- $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename);
- trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
- }
- else if ($this->lang_name == basename($config['default_lang']))
- {
- // Fall back to the English Language
- $reset_lang_name = $this->lang_name;
- $this->lang_name = 'en';
- $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
- $this->lang_name = $reset_lang_name;
- }
- else if ($this->lang_name == $this->data['user_lang'])
- {
- // Fall back to the board default language
- $reset_lang_name = $this->lang_name;
- $this->lang_name = basename($config['default_lang']);
- $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
- $this->lang_name = $reset_lang_name;
- }
-
- return;
- }
-
- // Do not suppress error if in DEBUG mode
- $include_result = (defined('DEBUG')) ? (include $language_filename) : (@include $language_filename);
-
- if ($include_result === false)
- {
- trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
- }
- }
- else if ($use_db)
- {
- // Get Database Language Strings
- // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
- // For example: help:faq, posting
- }
- }
-
- /**
* Format user date
*
* @param int $gmepoch unix timestamp
@@ -816,7 +686,7 @@ class user extends \phpbb\session
if ($alt)
{
- $alt = $this->lang($alt);
+ $alt = $this->language->lang($alt);
$title = ' title="' . $alt . '"';
}
return '<span class="imageset ' . $img . '"' . $title . '>' . $alt . '</span>';
@@ -877,8 +747,6 @@ class user extends \phpbb\session
*/
function leave_newly_registered()
{
- global $db;
-
if (empty($this->data['user_new']))
{
return false;
diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php
index 967d96d73a..cdd28329db 100644
--- a/phpBB/phpbb/user_loader.php
+++ b/phpBB/phpbb/user_loader.php
@@ -175,7 +175,7 @@ class user_loader
/**
* Get avatar
*
- * @param int $user_id User ID of the user you want to retreive the avatar for
+ * @param int $user_id User ID of the user you want to retrieve the avatar for
* @param bool $query Should we query the database if this user has not yet been loaded?
* Typically this should be left as false and you should make sure
* you load users ahead of time with load_users()
@@ -189,7 +189,14 @@ class user_loader
return '';
}
- return phpbb_get_avatar(\phpbb\avatar\manager::clean_row($user, 'user'), 'USER_AVATAR', false, $lazy);
+ $row = array(
+ 'avatar' => $user['user_avatar'],
+ 'avatar_type' => $user['user_avatar_type'],
+ 'avatar_width' => $user['user_avatar_width'],
+ 'avatar_height' => $user['user_avatar_height'],
+ );
+
+ return phpbb_get_avatar($row, 'USER_AVATAR', false, $lazy);
}
/**
diff --git a/phpBB/phpbb/viewonline_helper.php b/phpBB/phpbb/viewonline_helper.php
index b722f9d911..89915f2228 100644
--- a/phpBB/phpbb/viewonline_helper.php
+++ b/phpBB/phpbb/viewonline_helper.php
@@ -18,13 +18,13 @@ namespace phpbb;
*/
class viewonline_helper
{
- /** @var \phpbb\filesystem */
+ /** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
/**
- * @param \phpbb\filesystem $filesystem
+ * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB's filesystem service
*/
- public function __construct(\phpbb\filesystem $filesystem)
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem)
{
$this->filesystem = $filesystem;
}
diff --git a/phpBB/posting.php b/phpBB/posting.php
index db580d926b..b0aef2482a 100644
--- a/phpBB/posting.php
+++ b/phpBB/posting.php
@@ -29,11 +29,11 @@ $auth->acl($user->data);
// Grab only parameters needed here
-$post_id = request_var('p', 0);
-$topic_id = request_var('t', 0);
-$forum_id = request_var('f', 0);
-$draft_id = request_var('d', 0);
-$lastclick = request_var('lastclick', 0);
+$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;
@@ -43,7 +43,7 @@ $cancel = (isset($_POST['cancel']) && !isset($_POST['save'])) ? true : false;
$refresh = (isset($_POST['add_file']) || isset($_POST['delete_file']) || isset($_POST['cancel_unglobalise']) || $save || $load || $preview);
$submit = $request->is_set_post('post') && !$refresh && !$preview;
-$mode = request_var('mode', '');
+$mode = $request->variable('mode', '');
// If the user is not allowed to delete the post, we try to soft delete it, so we overwrite the mode here.
if ($mode == 'delete' && (($confirm && !$request->is_set_post('delete_permanent')) || !$auth->acl_gets('f_delete', 'm_delete', $forum_id)))
@@ -104,7 +104,7 @@ $vars = array(
extract($phpbb_dispatcher->trigger_event('core.modify_posting_parameters', compact($vars)));
// Was cancel pressed? If so then redirect to the appropriate page
-if ($cancel || ($current_time - $lastclick < 2 && $submit))
+if ($cancel)
{
$f = ($forum_id) ? 'f=' . $forum_id . '&amp;' : '';
$redirect = ($post_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $f . 'p=' . $post_id) . '#p' . $post_id : (($topic_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $f . 't=' . $topic_id) : (($forum_id) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) : append_sid("{$phpbb_root_path}index.$phpEx")));
@@ -116,6 +116,7 @@ if (in_array($mode, array('post', 'reply', 'quote', 'edit', 'delete')) && !$foru
trigger_error('NO_FORUM');
}
+/* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
// We need to know some basic information in all cases before we do anything.
@@ -492,7 +493,7 @@ if ($mode == 'delete' || $mode == 'soft_delete')
if ($mode == 'bump')
{
if ($bump_time = bump_topic_allowed($forum_id, $post_data['topic_bumped'], $post_data['topic_last_post_time'], $post_data['topic_poster'], $post_data['topic_last_poster_id'])
- && check_link_hash(request_var('hash', ''), "topic_{$post_data['topic_id']}"))
+ && check_link_hash($request->variable('hash', ''), "topic_{$post_data['topic_id']}"))
{
$meta_url = phpbb_bump_topic($forum_id, $topic_id, $post_data, $current_time);
meta_refresh(3, $meta_url);
@@ -567,10 +568,12 @@ if ($mode == 'edit')
$orig_poll_options_size = sizeof($post_data['poll_options']);
$message_parser = new parse_message();
+/* @var $plupload \phpbb\plupload\plupload */
$plupload = $phpbb_container->get('plupload');
+
+/* @var $mimetype_guesser \phpbb\mimetype\guesser */
$mimetype_guesser = $phpbb_container->get('mimetype.guesser');
$message_parser->set_plupload($plupload);
-$message_parser->set_mimetype_guesser($mimetype_guesser);
if (isset($post_data['post_text']))
{
@@ -683,9 +686,9 @@ $quote_status = true;
// Save Draft
if ($save && $user->data['is_registered'] && $auth->acl_get('u_savedrafts') && ($mode == 'reply' || $mode == 'post' || $mode == 'quote'))
{
- $subject = utf8_normalize_nfc(request_var('subject', '', true));
+ $subject = $request->variable('subject', '', true);
$subject = (!$subject && $mode != 'post') ? $post_data['topic_title'] : $subject;
- $message = utf8_normalize_nfc(request_var('message', '', true));
+ $message = $request->variable('message', '', true);
if ($subject && $message)
{
@@ -755,11 +758,11 @@ if ($save && $user->data['is_registered'] && $auth->acl_get('u_savedrafts') && (
if (is_bool($default))
{
// Use the string representation
- $hidden_fields[$name] = request_var($name, '');
+ $hidden_fields[$name] = $request->variable($name, '');
}
else
{
- $hidden_fields[$name] = request_var($name, $default);
+ $hidden_fields[$name] = $request->variable($name, $default);
}
}
@@ -816,20 +819,20 @@ if ($load && ($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_
if ($submit || $preview || $refresh)
{
- $post_data['topic_cur_post_id'] = request_var('topic_cur_post_id', 0);
- $post_data['post_subject'] = utf8_normalize_nfc(request_var('subject', '', true));
- $message_parser->message = utf8_normalize_nfc(request_var('message', '', true));
+ $post_data['topic_cur_post_id'] = $request->variable('topic_cur_post_id', 0);
+ $post_data['post_subject'] = $request->variable('subject', '', true);
+ $message_parser->message = $request->variable('message', '', true);
- $post_data['username'] = utf8_normalize_nfc(request_var('username', $post_data['username'], true));
- $post_data['post_edit_reason'] = ($request->variable('edit_reason', false, false, \phpbb\request\request_interface::POST) && $mode == 'edit' && $auth->acl_get('m_edit', $forum_id)) ? utf8_normalize_nfc(request_var('edit_reason', '', true)) : '';
+ $post_data['username'] = $request->variable('username', $post_data['username'], true);
+ $post_data['post_edit_reason'] = ($request->variable('edit_reason', false, false, \phpbb\request\request_interface::POST) && $mode == 'edit' && $auth->acl_get('m_edit', $forum_id)) ? $request->variable('edit_reason', '', true) : '';
$post_data['orig_topic_type'] = $post_data['topic_type'];
- $post_data['topic_type'] = request_var('topic_type', (($mode != 'post') ? (int) $post_data['topic_type'] : POST_NORMAL));
- $post_data['topic_time_limit'] = request_var('topic_time_limit', (($mode != 'post') ? (int) $post_data['topic_time_limit'] : 0));
+ $post_data['topic_type'] = $request->variable('topic_type', (($mode != 'post') ? (int) $post_data['topic_type'] : POST_NORMAL));
+ $post_data['topic_time_limit'] = $request->variable('topic_time_limit', (($mode != 'post') ? (int) $post_data['topic_time_limit'] : 0));
if ($post_data['enable_icons'] && $auth->acl_get('f_icons', $forum_id))
{
- $post_data['icon_id'] = request_var('icon', (int) $post_data['icon_id']);
+ $post_data['icon_id'] = $request->variable('icon', (int) $post_data['icon_id']);
}
$post_data['enable_bbcode'] = (!$bbcode_status || isset($_POST['disable_bbcode'])) ? false : true;
@@ -894,10 +897,10 @@ if ($submit || $preview || $refresh)
}
else
{
- $post_data['poll_title'] = utf8_normalize_nfc(request_var('poll_title', '', true));
- $post_data['poll_length'] = request_var('poll_length', 0);
- $post_data['poll_option_text'] = utf8_normalize_nfc(request_var('poll_option_text', '', true));
- $post_data['poll_max_options'] = request_var('poll_max_options', 1);
+ $post_data['poll_title'] = $request->variable('poll_title', '', true);
+ $post_data['poll_length'] = $request->variable('poll_length', 0);
+ $post_data['poll_option_text'] = $request->variable('poll_option_text', '', true);
+ $post_data['poll_max_options'] = $request->variable('poll_max_options', 1);
$post_data['poll_vote_change'] = ($auth->acl_get('f_votechg', $forum_id) && $auth->acl_get('f_vote', $forum_id) && isset($_POST['poll_vote_change'])) ? 1 : 0;
}
@@ -966,8 +969,8 @@ if ($submit || $preview || $refresh)
// Notify and show user the changed post
if ($mode == 'edit' && $post_data['forum_flags'] & FORUM_FLAG_POST_REVIEW)
{
- $edit_post_message_checksum = request_var('edit_post_message_checksum', '');
- $edit_post_subject_checksum = request_var('edit_post_subject_checksum', '');
+ $edit_post_message_checksum = $request->variable('edit_post_message_checksum', '');
+ $edit_post_subject_checksum = $request->variable('edit_post_subject_checksum', '');
// $post_data['post_checksum'] is the checksum of the post submitted in the meantime
// $message_md5 is the checksum of the post we're about to submit
@@ -1082,9 +1085,9 @@ if ($submit || $preview || $refresh)
if ($config['enable_post_confirm'] && !$user->data['is_registered'] && in_array($mode, array('quote', 'post', 'reply')))
{
$captcha_data = array(
- 'message' => utf8_normalize_nfc(request_var('message', '', true)),
- 'subject' => utf8_normalize_nfc(request_var('subject', '', true)),
- 'username' => utf8_normalize_nfc(request_var('username', '', true)),
+ 'message' => $request->variable('message', '', true),
+ 'subject' => $request->variable('subject', '', true),
+ 'username' => $request->variable('username', '', true),
);
$vc_response = $captcha->validate($captcha_data);
if ($vc_response)
@@ -1202,6 +1205,9 @@ if ($submit || $preview || $refresh)
switch ($post_data['topic_type'])
{
case POST_GLOBAL:
+ $auth_option = 'f_announce_global';
+ break;
+
case POST_ANNOUNCE:
$auth_option = 'f_announce';
break;
@@ -1253,7 +1259,6 @@ if ($submit || $preview || $refresh)
* @var array poll Array with poll data from post (must be used instead of the post_data equivalent)
* @var string mode What action to take if the form is submitted
* post|reply|quote|edit|delete|bump|smilies|popup
- * @var string page_title Title of the mode page
* @var int post_id ID of the post
* @var int topic_id ID of the topic
* @var int forum_id ID of the forum
@@ -1262,12 +1267,12 @@ if ($submit || $preview || $refresh)
* NOTE: Should be actual language strings, NOT language keys.
* @since 3.1.0-RC5
* @change 3.1.5-RC1 Added poll array to the event
+ * @change 3.2.0-a1 Removed undefined page_title
*/
$vars = array(
'post_data',
'poll',
'mode',
- 'page_title',
'post_id',
'topic_id',
'forum_id',
@@ -1304,7 +1309,11 @@ if ($submit || $preview || $refresh)
$user_lock = ($auth->acl_get('f_user_lock', $forum_id) && $user->data['is_registered'] && $user->data['user_id'] == $post_data['topic_poster']) ? 'USER_' : '';
- add_log('mod', $forum_id, $topic_id, 'LOG_' . $user_lock . (($change_topic_status == ITEM_LOCKED) ? 'LOCK' : 'UNLOCK'), $post_data['topic_title']);
+ $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_' . $user_lock . (($change_topic_status == ITEM_LOCKED) ? 'LOCK' : 'UNLOCK'), false, array(
+ 'forum_id' => $forum_id,
+ 'topic_id' => $topic_id,
+ $post_data['topic_title']
+ ));
}
// Lock/Unlock Post Edit
@@ -1376,7 +1385,6 @@ if ($submit || $preview || $refresh)
* @var array data Array with post data going to be stored in the database
* @var string mode What action to take if the form is submitted
* post|reply|quote|edit|delete
- * @var string page_title Title of the mode page
* @var int post_id ID of the post
* @var int topic_id ID of the topic
* @var int forum_id ID of the forum
@@ -1386,13 +1394,13 @@ if ($submit || $preview || $refresh)
* NOTE: Should be actual language strings, NOT language keys.
* @since 3.1.0-RC5
* @changed 3.1.6-RC1 remove submit and error from event Submit and Error are checked previously prior to running event
+ * @change 3.2.0-a1 Removed undefined page_title
*/
$vars = array(
'post_data',
'poll',
'data',
'mode',
- 'page_title',
'post_id',
'topic_id',
'forum_id',
@@ -1414,7 +1422,6 @@ if ($submit || $preview || $refresh)
* @var array data Array with post data going to be stored in the database
* @var string mode What action to take if the form is submitted
* post|reply|quote|edit|delete
- * @var string page_title Title of the mode page
* @var int post_id ID of the post
* @var int topic_id ID of the topic
* @var int forum_id ID of the forum
@@ -1425,13 +1432,13 @@ if ($submit || $preview || $refresh)
* NOTE: Should be actual language strings, NOT language keys.
* @since 3.1.0-RC5
* @changed 3.1.6-RC1 remove submit and error from event Submit and Error are checked previously prior to running event
+ * @change 3.2.0-a1 Removed undefined page_title
*/
$vars = array(
'post_data',
'poll',
'data',
'mode',
- 'page_title',
'post_id',
'topic_id',
'forum_id',
@@ -1485,14 +1492,11 @@ if (!sizeof($error) && $preview)
// Signature
if ($post_data['enable_sig'] && $config['allow_sig'] && $preview_signature && $auth->acl_get('f_sigs', $forum_id))
{
- $parse_sig = new parse_message($preview_signature);
- $parse_sig->bbcode_uid = $preview_signature_uid;
- $parse_sig->bbcode_bitfield = $preview_signature_bitfield;
-
- // Not sure about parameters for bbcode/smilies/urls... in signatures
- $parse_sig->format_display($config['allow_sig_bbcode'], $config['allow_sig_links'], $config['allow_sig_smilies']);
- $preview_signature = $parse_sig->message;
- unset($parse_sig);
+ $flags = ($config['allow_sig_bbcode']) ? OPTION_FLAG_BBCODE : 0;
+ $flags |= ($config['allow_sig_links']) ? OPTION_FLAG_LINKS : 0;
+ $flags |= ($config['allow_sig_smilies']) ? OPTION_FLAG_SMILIES : 0;
+
+ $preview_signature = generate_text_for_display($preview_signature, $preview_signature_uid, $preview_signature_bitfield, $flags, false);
}
else
{
@@ -1597,7 +1601,16 @@ if ($generate_quote)
if ($config['allow_bbcode'])
{
- $message_parser->message = '[quote=&quot;' . $post_data['quote_username'] . '&quot;]' . censor_text(trim($message_parser->message)) . "[/quote]\n";
+ $message_parser->message = $phpbb_container->get('text_formatter.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
{
@@ -1719,7 +1732,7 @@ 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_var('draft_loaded', $draft_id) . '" />' : '';
+$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')
{
@@ -1738,6 +1751,8 @@ if (isset($captcha) && $captcha->is_solved() !== false)
$form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_attachments'] || !$auth->acl_get('u_attach') || !$auth->acl_get('f_attach', $forum_id)) ? '' : ' enctype="multipart/form-data"';
add_form_key('posting');
+/** @var \phpbb\controller\helper $controller_helper */
+$controller_helper = $phpbb_container->get('controller.helper');
// Build array of variables for main posting page
$page_data = array(
@@ -1753,7 +1768,7 @@ $page_data = array(
'USERNAME' => ((!$preview && $mode != 'quote') || $preview) ? $post_data['username'] : '',
'SUBJECT' => $post_data['post_subject'],
'MESSAGE' => $post_data['post_text'],
- 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
+ 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
diff --git a/phpBB/report.php b/phpBB/report.php
index 3ea6bb40c5..bb26b972aa 100644
--- a/phpBB/report.php
+++ b/phpBB/report.php
@@ -11,6 +11,8 @@
*
*/
+use Symfony\Component\HttpFoundation\RedirectResponse;
+
/**
* @ignore
*/
@@ -18,321 +20,22 @@ define('IN_PHPBB', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
-include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
// Start session management
$user->session_begin();
$auth->acl($user->data);
-$user->setup('mcp');
-
-$forum_id = request_var('f', 0);
-$post_id = request_var('p', 0);
-$pm_id = request_var('pm', 0);
-$reason_id = request_var('reason_id', 0);
-$report_text = utf8_normalize_nfc(request_var('report_text', '', true));
-$user_notify = ($user->data['is_registered']) ? request_var('notify', 0) : false;
-
-$submit = (isset($_POST['submit'])) ? true : false;
-
-if (!$post_id && (!$pm_id || !$config['allow_pm_report']))
-{
- trigger_error('NO_POST_SELECTED');
-}
-
-if ($post_id)
-{
- $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;p=$post_id") . "#p$post_id";
- $return_forum_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id");
- $pm_id = 0;
-}
-else
-{
- $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&p=$pm_id");
- $return_forum_url = '';
- $post_id = 0;
- $forum_id = 0;
-}
-
-// Has the report been cancelled?
-if (isset($_POST['cancel']))
-{
- redirect($redirect_url);
-}
-
-if ($post_id)
-{
- // Grab all relevant data
- $sql = 'SELECT t.*, p.*
- FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
- WHERE p.post_id = $post_id
- AND p.topic_id = t.topic_id";
- $result = $db->sql_query($sql);
- $report_data = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$report_data)
- {
- trigger_error('POST_NOT_EXIST');
- }
-
- $forum_id = (int) $report_data['forum_id'];
- $topic_id = (int) $report_data['topic_id'];
- $reported_post_text = $report_data['post_text'];
- $reported_post_bitfield = $report_data['bbcode_bitfield'];
- $reported_post_uid = $report_data['bbcode_uid'];
- $reported_post_enable_bbcode = $report_data['enable_bbcode'];
- $reported_post_enable_smilies = $report_data['enable_smilies'];
- $reported_post_enable_magic_url = $report_data['enable_magic_url'];
-
- $sql = 'SELECT *
- FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . $forum_id;
- $result = $db->sql_query($sql);
- $forum_data = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$forum_data)
- {
- trigger_error('FORUM_NOT_EXIST');
- }
-
- // Check required permissions
- $acl_check_ary = array('f_list' => 'POST_NOT_EXIST', 'f_read' => 'USER_CANNOT_READ', 'f_report' => 'USER_CANNOT_REPORT');
-
- /**
- * This event allows you to do extra auth checks and verify if the user
- * has the required permissions
- *
- * @event core.report_post_auth
- * @var array forum_data All data available from the forums table on this post's forum
- * @var array report_data All data available from the topics and the posts tables on this post (and its topic)
- * @var array acl_check_ary An array with the ACL to be tested. The evaluation is made in the same order as the array is sorted
- * The key is the ACL name and the value is the language key for the error message.
- * @since 3.1.3-RC1
- */
- $vars = array(
- 'forum_data',
- 'report_data',
- 'acl_check_ary',
- );
- extract($phpbb_dispatcher->trigger_event('core.report_post_auth', compact($vars)));
-
- foreach ($acl_check_ary as $acl => $error)
- {
- if (!$auth->acl_get($acl, $forum_id))
- {
- trigger_error($error);
- }
- }
- unset($acl_check_ary);
-
- if ($report_data['post_reported'])
- {
- $message = $user->lang['ALREADY_REPORTED'];
- $message .= '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
- $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . $return_forum_url . '">', '</a>');
- trigger_error($message);
- }
-}
-else
-{
- // Grab all relevant data
- $sql = 'SELECT p.*, pt.*
- FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . " pt
- WHERE p.msg_id = $pm_id
- AND p.msg_id = pt.msg_id
- AND (p.author_id = " . $user->data['user_id'] . " OR pt.user_id = " . $user->data['user_id'] . ")";
- $result = $db->sql_query($sql);
- $report_data = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$report_data)
- {
- $user->add_lang('ucp');
- trigger_error('NO_MESSAGE');
- }
-
- if ($report_data['message_reported'])
- {
- $message = $user->lang['ALREADY_REPORTED_PM'];
- $message .= '<br /><br />' . sprintf($user->lang['RETURN_PM'], '<a href="' . $redirect_url . '">', '</a>');
- trigger_error($message);
- }
-
- $reported_post_text = $report_data['message_text'];
- $reported_post_bitfield = $report_data['bbcode_bitfield'];
- $reported_post_uid = $report_data['bbcode_uid'];
- $reported_post_enable_bbcode = $report_data['enable_bbcode'];
- $reported_post_enable_smilies = $report_data['enable_smilies'];
- $reported_post_enable_magic_url = $report_data['enable_magic_url'];
-}
-
-if ($config['enable_post_confirm'] && !$user->data['is_registered'])
-{
- $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']);
- $captcha->init(CONFIRM_REPORT);
-}
-
-$error = array();
-$s_hidden_fields = '';
-
-// Submit report?
-if ($submit && $reason_id)
-{
- if (isset($captcha))
- {
- $visual_confirmation_response = $captcha->validate();
- if ($visual_confirmation_response)
- {
- $error[] = $visual_confirmation_response;
- }
- }
-
- $sql = 'SELECT *
- FROM ' . REPORTS_REASONS_TABLE . "
- WHERE reason_id = $reason_id";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
- if (!$row || (!$report_text && strtolower($row['reason_title']) == 'other'))
- {
- $error[] = $user->lang('EMPTY_REPORT');
- }
+$post_id = $request->variable('p', 0);
+$pm_id = $request->variable('pm', 0);
- if (!sizeof($error))
- {
- if (isset($captcha))
- {
- $captcha->reset();
- }
+$redirect_route_name = ($pm_id === 0) ? 'phpbb_report_post_controller' : 'phpbb_report_pm_controller';
- $sql_ary = array(
- 'reason_id' => (int) $reason_id,
- 'post_id' => $post_id,
- 'pm_id' => $pm_id,
- 'user_id' => (int) $user->data['user_id'],
- 'user_notify' => (int) $user_notify,
- 'report_closed' => 0,
- 'report_time' => (int) time(),
- 'report_text' => (string) $report_text,
- 'reported_post_text' => $reported_post_text,
- 'reported_post_uid' => $reported_post_uid,
- 'reported_post_bitfield' => $reported_post_bitfield,
- 'reported_post_enable_bbcode' => $reported_post_enable_bbcode,
- 'reported_post_enable_smilies' => $reported_post_enable_smilies,
- 'reported_post_enable_magic_url' => $reported_post_enable_magic_url,
- );
-
- $sql = 'INSERT INTO ' . REPORTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
- $db->sql_query($sql);
- $report_id = $db->sql_nextid();
-
- $phpbb_notifications = $phpbb_container->get('notification_manager');
-
- if ($post_id)
- {
- $sql = 'UPDATE ' . POSTS_TABLE . '
- SET post_reported = 1
- WHERE post_id = ' . $post_id;
- $db->sql_query($sql);
-
- if (!$report_data['topic_reported'])
- {
- $sql = 'UPDATE ' . TOPICS_TABLE . '
- SET topic_reported = 1
- WHERE topic_id = ' . $report_data['topic_id'] . '
- OR topic_moved_id = ' . $report_data['topic_id'];
- $db->sql_query($sql);
- }
-
- $lang_return = $user->lang['RETURN_TOPIC'];
- $lang_success = $user->lang['POST_REPORTED_SUCCESS'];
-
- $phpbb_notifications->add_notifications('notification.type.report_post', array_merge($report_data, $row, $forum_data, array(
- 'report_text' => $report_text,
- )));
- }
- else
- {
- $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
- SET message_reported = 1
- WHERE msg_id = ' . $pm_id;
- $db->sql_query($sql);
-
- $sql_ary = array(
- 'msg_id' => $pm_id,
- 'user_id' => ANONYMOUS,
- 'author_id' => (int) $report_data['author_id'],
- 'pm_deleted' => 0,
- 'pm_new' => 0,
- 'pm_unread' => 0,
- 'pm_replied' => 0,
- 'pm_marked' => 0,
- 'pm_forwarded' => 0,
- 'folder_id' => PRIVMSGS_INBOX,
- );
-
- $sql = 'INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
- $db->sql_query($sql);
-
- $lang_return = $user->lang['RETURN_PM'];
- $lang_success = $user->lang['PM_REPORTED_SUCCESS'];
-
- $phpbb_notifications->add_notifications('notification.type.report_pm', array_merge($report_data, $row, array(
- 'report_text' => $report_text,
- 'from_user_id' => $report_data['author_id'],
- 'report_id' => $report_id,
- )));
- }
-
- meta_refresh(3, $redirect_url);
-
- $message = $lang_success . '<br /><br />' . sprintf($lang_return, '<a href="' . $redirect_url . '">', '</a>');
- if ($return_forum_url)
- {
- $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . $return_forum_url . '">', '</a>');
- }
- trigger_error($message);
- }
- else if (isset($captcha) && $captcha->is_solved() !== false)
- {
- $s_hidden_fields .= build_hidden_fields($captcha->get_hidden_fields());
- }
-}
-
-// Generate the reasons
-display_reasons($reason_id);
-
-$page_title = ($pm_id) ? $user->lang['REPORT_MESSAGE'] : $user->lang['REPORT_POST'];
-
-if (isset($captcha) && $captcha->is_solved() === false)
-{
- $template->assign_vars(array(
- 'S_CONFIRM_CODE' => true,
- 'CAPTCHA_TEMPLATE' => $captcha->get_template(),
- ));
-}
-
-$template->assign_vars(array(
- 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'S_REPORT_POST' => ($pm_id) ? false : true,
- 'REPORT_TEXT' => $report_text,
- 'S_REPORT_ACTION' => append_sid("{$phpbb_root_path}report.$phpEx", 'f=' . $forum_id . '&amp;p=' . $post_id . '&amp;pm=' . $pm_id),
- 'S_HIDDEN_FIELDS' => (sizeof($s_hidden_fields)) ? $s_hidden_fields : null,
-
- 'S_NOTIFY' => $user_notify,
- 'S_CAN_NOTIFY' => ($user->data['is_registered']) ? true : false,
- 'S_IN_REPORT' => true,
-));
-
-generate_forum_nav($forum_data);
-
-// Start output of page
-page_header($page_title);
-
-$template->set_filenames(array(
- 'body' => 'report_body.html')
+/** @var \phpbb\controller\helper $controller_helper */
+$controller_helper = $phpbb_container->get('controller.helper');
+$response = new RedirectResponse(
+ $controller_helper->route($redirect_route_name, array(
+ 'id' => ($pm_id === 0) ? $post_id : $pm_id,
+ )),
+ 301
);
-
-page_footer();
+$response->send();
diff --git a/phpBB/search.php b/phpBB/search.php
index 27ec8e4dab..0d9b2bbfe8 100644
--- a/phpBB/search.php
+++ b/phpBB/search.php
@@ -25,30 +25,30 @@ $auth->acl($user->data);
$user->setup('search');
// Define initial vars
-$mode = request_var('mode', '');
-$search_id = request_var('search_id', '');
-$start = max(request_var('start', 0), 0);
-$post_id = request_var('p', 0);
-$topic_id = request_var('t', 0);
-$view = request_var('view', '');
-
-$submit = request_var('submit', false);
-$keywords = utf8_normalize_nfc(request_var('keywords', '', true));
-$add_keywords = utf8_normalize_nfc(request_var('add_keywords', '', true));
-$author = request_var('author', '', true);
-$author_id = request_var('author_id', 0);
-$show_results = ($topic_id) ? 'posts' : request_var('sr', 'posts');
+$mode = $request->variable('mode', '');
+$search_id = $request->variable('search_id', '');
+$start = max($request->variable('start', 0), 0);
+$post_id = $request->variable('p', 0);
+$topic_id = $request->variable('t', 0);
+$view = $request->variable('view', '');
+
+$submit = $request->variable('submit', false);
+$keywords = $request->variable('keywords', '', true);
+$add_keywords = $request->variable('add_keywords', '', true);
+$author = $request->variable('author', '', true);
+$author_id = $request->variable('author_id', 0);
+$show_results = ($topic_id) ? 'posts' : $request->variable('sr', 'posts');
$show_results = ($show_results == 'posts') ? 'posts' : 'topics';
-$search_terms = request_var('terms', 'all');
-$search_fields = request_var('sf', 'all');
-$search_child = request_var('sc', true);
+$search_terms = $request->variable('terms', 'all');
+$search_fields = $request->variable('sf', 'all');
+$search_child = $request->variable('sc', true);
-$sort_days = request_var('st', 0);
-$sort_key = request_var('sk', 't');
-$sort_dir = request_var('sd', 'd');
+$sort_days = $request->variable('st', 0);
+$sort_key = $request->variable('sk', 't');
+$sort_dir = $request->variable('sd', 'd');
-$return_chars = request_var('ch', ($topic_id) ? -1 : 300);
-$search_forum = request_var('fid', array(0));
+$return_chars = $request->variable('ch', ($topic_id) ? -1 : 300);
+$search_forum = $request->variable('fid', array(0));
// We put login boxes for the case if search_id is newposts, egosearch or unreadposts
// because a guest should be able to log in even if guests search is not permitted
@@ -123,7 +123,10 @@ $sort_by_text = array('a' => $user->lang['SORT_AUTHOR'], 't' => $user->lang['SOR
$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);
+/* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
+
+/* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
/**
@@ -324,7 +327,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
if (!$keywords && sizeof($author_id_ary))
{
// if it is an author search we want to show topics by default
- $show_results = ($topic_id) ? 'posts' : request_var('sr', ($search_id == 'egosearch') ? 'topics' : 'posts');
+ $show_results = ($topic_id) ? 'posts' : $request->variable('sr', ($search_id == 'egosearch') ? 'topics' : 'posts');
$show_results = ($show_results == 'posts') ? 'posts' : 'topics';
}
@@ -368,7 +371,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
$show_results = 'topics';
$sort_key = 't';
$sort_dir = 'd';
- $sort_days = request_var('st', 7);
+ $sort_days = $request->variable('st', 7);
$sort_by_sql['t'] = 't.topic_last_post_time';
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);
@@ -388,7 +391,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
case 'unanswered':
$l_search_title = $user->lang['SEARCH_UNANSWERED'];
- $show_results = request_var('sr', 'topics');
+ $show_results = $request->variable('sr', 'topics');
$show_results = ($show_results == 'posts') ? 'posts' : 'topics';
$sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time';
$sort_by_sql['s'] = ($show_results == 'posts') ? 'p.post_subject' : 't.topic_title';
@@ -459,7 +462,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
case 'newposts':
$l_search_title = $user->lang['SEARCH_NEW'];
// force sorting
- $show_results = (request_var('sr', 'topics') == 'posts') ? 'posts' : 'topics';
+ $show_results = ($request->variable('sr', 'topics') == 'posts') ? 'posts' : 'topics';
$sort_key = 't';
$sort_dir = 'd';
$sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time';
@@ -853,7 +856,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
$result = $db->sql_query($sql);
$result_topic_id = 0;
- $rowset = array();
+ $rowset = $attachments = $topic_tracking_info = array();
if ($show_results == 'topics')
{
@@ -1487,7 +1490,6 @@ if ($auth->acl_get('a_search'))
ORDER BY search_time DESC';
break;
- case 'mssql':
case 'mssql_odbc':
case 'mssqlnative':
$sql = 'SELECT search_time, search_keywords
diff --git a/phpBB/styles/all/template/feed.xml.twig b/phpBB/styles/all/template/feed.xml.twig
new file mode 100644
index 0000000000..91467c62cd
--- /dev/null
+++ b/phpBB/styles/all/template/feed.xml.twig
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="{{ FEED_LANG }}">
+ <link rel="self" type="application/atom+xml" href="{{ SELF_LINK }}" />
+
+ {% if not FEED_TITLE is empty %}<title>{{ FEED_TITLE }}</title>{% endif %}
+
+ {% if not FEED_SUBTITLE is empty %}<subtitle>{{ FEED_SUBTITLE }}</subtitle>{% endif %}
+
+ {% if not FEED_LINK is empty %}<link href="{{ FEED_LINK }}" />{% endif %}
+
+ <updated>{{ FEED_UPDATED }}</updated>
+
+ <author><name><![CDATA[{{ FEED_AUTHOR }}]]></name></author>
+ <id>{{ SELF_LINK }}</id>
+
+ {% for row in FEED_ROWS %}
+ <entry>
+ {% if not row.author is empty %}<author><name><![CDATA[{{ row.author }}]]></name></author>{% endif %}
+
+ <updated>{% if not row.updated is empty %}{{ row.updated }} {% else %}{{ row.published }}{% endif %}</updated>
+
+ {% if not row.published is empty %}<published>{{ row.published }}</published>{% endif %}
+
+ <id>{{ row.link }}</id>
+ <link href="{{ row.link }}"/>
+ <title type="html"><![CDATA[{{ row.title }}]]></title>
+
+ {% if not row.category is empty and row.category_name is defined and row.category_name != '' %}
+ <category term="{{ row.category_name }}" scheme="{{ row.category }}" label="{{ row.category_name }}"/>
+ {% endif %}
+
+ <content type="html" xml:base="{{ row.link }}"><![CDATA[
+{{ row.description }}{% if not row.statistics is empty %}<p>{{ lang('STATISTICS') }}: {{ row.statistics }}</p>{% endif %}<hr />
+]]></content>
+ </entry>
+ {% endfor %}
+</feed>
diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg
index 300a83164b..895ee49dc4 100644
--- a/phpBB/styles/prosilver/style.cfg
+++ b/phpBB/styles/prosilver/style.cfg
@@ -21,8 +21,8 @@
# General Information about this style
name = prosilver
copyright = © phpBB Limited, 2007
-style_version = 3.1.10
-phpbb_version = 3.1.10
+style_version = 3.2.0-RC1
+phpbb_version = 3.2.0-RC1
# Defining a different template bitfield
# template_bitfield = lNg=
diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js
index 311da92a95..3888d26785 100644
--- a/phpBB/styles/prosilver/template/ajax.js
+++ b/phpBB/styles/prosilver/template/ajax.js
@@ -87,7 +87,7 @@ phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) {
});
// Remove link to first unread post
- $('a').has('span.icon_topic_newest').remove();
+ $('a.unread').has('.icon-red').remove();
// Update mark topics read links
if (updateTopicLinks) {
diff --git a/phpBB/styles/prosilver/template/attachment.html b/phpBB/styles/prosilver/template/attachment.html
index 4546f53d6c..0978d9189e 100644
--- a/phpBB/styles/prosilver/template/attachment.html
+++ b/phpBB/styles/prosilver/template/attachment.html
@@ -29,36 +29,7 @@
</dl>
<!-- ENDIF -->
- <!-- IF _file.S_WM_FILE -->
- <!-- method used here from http://alistapart.com/articles/byebyeembed / autosizing seems to not work always, this will not fix -->
- <object width="320" height="285" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" id="wmstream_{_file.ATTACH_ID}">
- <param name="url" value="{_file.U_DOWNLOAD_LINK}" />
- <param name="showcontrols" value="1" />
- <param name="showdisplay" value="0" />
- <param name="showstatusbar" value="0" />
- <param name="autosize" value="1" />
- <param name="autostart" value="0" />
- <param name="visible" value="1" />
- <param name="animationstart" value="0" />
- <param name="loop" value="0" />
- <param name="src" value="{_file.U_DOWNLOAD_LINK}" />
- <!--[if !IE]>-->
- <object width="320" height="285" type="video/x-ms-wmv" data="{_file.U_DOWNLOAD_LINK}">
- <param name="src" value="{_file.U_DOWNLOAD_LINK}" />
- <param name="controller" value="1" />
- <param name="showcontrols" value="1" />
- <param name="showdisplay" value="0" />
- <param name="showstatusbar" value="0" />
- <param name="autosize" value="1" />
- <param name="autostart" value="0" />
- <param name="visible" value="1" />
- <param name="animationstart" value="0" />
- <param name="loop" value="0" />
- </object>
- <!--<![endif]-->
- </object>
-
- <!-- ELSEIF _file.S_FLASH_FILE -->
+ <!-- IF _file.S_FLASH_FILE -->
<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{_file.WIDTH}" height="{_file.HEIGHT}">
<param name="movie" value="{_file.U_VIEW_LINK}" />
<param name="play" value="true" />
@@ -68,53 +39,7 @@
<param name="allowNetworking" value="internal" />
<embed src="{_file.U_VIEW_LINK}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{_file.WIDTH}" height="{_file.HEIGHT}" play="true" loop="true" quality="high" allowscriptaccess="never" allownetworking="internal"></embed>
</object>
- <!-- ELSEIF _file.S_QUICKTIME_FILE -->
- <object id="qtstream_{_file.ATTACH_ID}" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="320" height="285">
- <param name="src" value="{_file.U_DOWNLOAD_LINK}" />
- <param name="controller" value="true" />
- <param name="autoplay" value="false" />
- <param name="type" value="video/quicktime" />
- <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="320" height="285" type="video/quicktime" autoplay="false"></embed>
- </object>
- <!-- ELSEIF _file.S_RM_FILE -->
- <object id="rmstream_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="200" height="50">
- <param name="src" value="{_file.U_DOWNLOAD_LINK}" />
- <param name="autostart" value="false" />
- <param name="controls" value="ImageWindow" />
- <param name="console" value="ctrls_{_file.ATTACH_ID}" />
- <param name="prefetch" value="false" />
- <embed name="rmstream_{_file.ATTACH_ID}" type="audio/x-pn-realaudio-plugin" src="{_file.U_DOWNLOAD_LINK}" width="0" height="0" autostart="false" controls="ImageWindow" console="ctrls_{_file.ATTACH_ID}" prefetch="false"></embed>
- </object>
- <br />
- <object id="ctrls_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="0" height="36">
- <param name="controls" value="ControlPanel" />
- <param name="console" value="ctrls_{_file.ATTACH_ID}" />
- <embed name="ctrls_{_file.ATTACH_ID}" type="audio/x-pn-realaudio-plugin" width="200" height="36" controls="ControlPanel" console="ctrls_{_file.ATTACH_ID}"></embed>
- </object>
-
- <script type="text/javascript">
- // <![CDATA[
- if (document.rmstream_{_file.ATTACH_ID}.GetClipWidth)
- {
- while (!document.rmstream_{_file.ATTACH_ID}.GetClipWidth())
- {
- }
-
- var width = document.rmstream_{_file.ATTACH_ID}.GetClipWidth();
- var height = document.rmstream_{_file.ATTACH_ID}.GetClipHeight();
-
- document.rmstream_{_file.ATTACH_ID}.width = width;
- document.rmstream_{_file.ATTACH_ID}.height = height;
- document.ctrls_{_file.ATTACH_ID}.width = width;
- }
- // ]]>
- </script>
- <!-- ENDIF -->
-
- <!-- IF _file.S_WM_FILE or _file.S_RM_FILE or _file.S_FLASH_FILE or _file.S_QUICKTIME_FILE -->
- <p>
- <!-- IF _file.S_QUICKTIME_FILE --><a href="#" onclick="play_qt_file(document.qtstream_{_file.ATTACH_ID}); return false;">[ {L_PLAY_QUICKTIME_FILE} ]</a> <!-- ENDIF -->
- <a href="{_file.U_DOWNLOAD_LINK}">{_file.DOWNLOAD_NAME}</a> [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]</p>
+ <p><a href="{_file.U_DOWNLOAD_LINK}">{_file.DOWNLOAD_NAME}</a> [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]</p>
<!-- ENDIF -->
<!-- EVENT attachment_file_append -->
diff --git a/phpBB/styles/prosilver/template/bbcode.html b/phpBB/styles/prosilver/template/bbcode.html
index 3e38d13a32..8c4e941092 100644
--- a/phpBB/styles/prosilver/template/bbcode.html
+++ b/phpBB/styles/prosilver/template/bbcode.html
@@ -11,9 +11,44 @@
<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open -->
<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open -->
<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close -->
+<!-- BEGIN quote_extended -->
+<blockquote>
+ <xsl:if test="not(@author)">
+ <xsl:attribute name="class">uncited</xsl:attribute>
+ </xsl:if>
+ <div>
+ <xsl:if test="@author">
+ <cite>
+ <xsl:choose>
+ <xsl:when test="@url">
+ <a href="{@url}" class="postlink"><xsl:value-of select="@author"/></a>
+ </xsl:when>
+ <xsl:when test="@profile_url">
+ <a href="{@profile_url}"><xsl:value-of select="@author"/></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@author"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$L_WROTE"/>
+ <xsl:value-of select="$L_COLON"/>
+ <xsl:if test="@post_url">
+ <xsl:text> </xsl:text>
+ <a href="{@post_url}" data-post-id="{@post_id}" onclick="if(document.getElementById(hash.substr(1)))href=hash">&#8593;</a>
+ </xsl:if>
+ <xsl:if test="@date">
+ <div class="responsive-hide"><xsl:value-of select="@date"/></div>
+ </xsl:if>
+ </cite>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </div>
+</blockquote>
+<!-- END quote_extended -->
-<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open -->
-<!-- BEGIN code_close --></code></div><!-- END code_close -->
+<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><pre><code><!-- END code_open -->
+<!-- BEGIN code_close --></code></pre></div><!-- END code_close -->
<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open -->
<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close -->
diff --git a/phpBB/styles/prosilver/template/captcha_recaptcha.html b/phpBB/styles/prosilver/template/captcha_recaptcha.html
index fee0f7423e..a123f543a8 100644
--- a/phpBB/styles/prosilver/template/captcha_recaptcha.html
+++ b/phpBB/styles/prosilver/template/captcha_recaptcha.html
@@ -12,24 +12,11 @@
<dl>
<dt><label>{L_CONFIRM_CODE}{L_COLON}</label><br /><span>{L_RECAPTCHA_EXPLAIN}</span></dt>
<dd class="captcha">
- <script>
- var RecaptchaOptions = {
- lang : '{LA_RECAPTCHA_LANG}',
- theme : 'clean',
- tabindex : <!-- IF $CAPTCHA_TAB_INDEX -->{$CAPTCHA_TAB_INDEX}<!-- ELSE -->10<!-- ENDIF -->
- };
- </script>
- <script src="{RECAPTCHA_SERVER}/challenge?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}"></script>
-
<noscript>
- <div>
- <object data="{RECAPTCHA_SERVER}/noscript?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}" type="text/html" height="300" width="500"></object><br />
- <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
- <input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
- </div>
+ <div>{L_RECAPTCHA_NOSCRIPT}</div>
</noscript>
-
- <a href="http://www.google.com/intl/{LA_RECAPTCHA_LANG}/policies/" target="_blank" class="recaptcha-responsive" style="display: none"><img alt="" width="71" height="36" src="{RECAPTCHA_SERVER}/img/clean/logo.png"></a>
+ <script src="{RECAPTCHA_SERVER}.js?hl={LA_RECAPTCHA_LANG}" async defer></script>
+ <div class="g-recaptcha" data-sitekey="{RECAPTCHA_PUBKEY}" data-tabindex="<!-- IF $CAPTCHA_TAB_INDEX -->{$CAPTCHA_TAB_INDEX}<!-- ELSE -->10<!-- ENDIF -->"></div>
</dd>
</dl>
<!-- ELSE -->
diff --git a/phpBB/styles/prosilver/template/confirm_delete_body.html b/phpBB/styles/prosilver/template/confirm_delete_body.html
index fbd881a940..98974963c0 100644
--- a/phpBB/styles/prosilver/template/confirm_delete_body.html
+++ b/phpBB/styles/prosilver/template/confirm_delete_body.html
@@ -58,7 +58,7 @@
<fieldset class="submit-buttons">
{S_HIDDEN_FIELDS}
- <input type="submit" name="confirm" value="{L_YES}" class="button1" />&nbsp;
+ <input type="submit" name="confirm" value="{L_YES}" class="button1" />&nbsp;
<input type="submit" name="cancel" value="{L_NO}" class="button2" />
</fieldset>
diff --git a/phpBB/styles/prosilver/template/display_options.html b/phpBB/styles/prosilver/template/display_options.html
new file mode 100644
index 0000000000..d1ec3dcef1
--- /dev/null
+++ b/phpBB/styles/prosilver/template/display_options.html
@@ -0,0 +1,27 @@
+<div class="dropdown-container dropdown-container-{S_CONTENT_FLOW_BEGIN} dropdown-button-control sort-tools">
+ <span title="{L_SORT_OPTIONS}" class="button button-secondary dropdown-trigger dropdown-select">
+ <i class="icon fa-sort-amount-asc fa-fw" aria-hidden="true"></i>
+ <span class="caret"><i class="icon fa-sort-down fa-fw" aria-hidden="true"></i></span>
+ </span>
+ <div class="dropdown hidden">
+ <div class="pointer"><div class="pointer-inner"></div></div>
+ <div class="dropdown-contents">
+ <fieldset class="display-options">
+ <!-- IF S_SORT_OPTIONS -->
+ <label>{L_SORT_BY}{L_COLON} <select name="sk" id="sk">{S_SORT_OPTIONS}</select></label>
+ <label>{L_SORT_DIRECTION}{L_COLON} <select name="sd" id="sd">{S_ORDER_SELECT}</select></label>
+ <hr class="dashed" />
+ <input type="submit" class="button2" name="sort" value="{L_SORT}" />
+ <!-- ELSE -->
+ <label>{L_DISPLAY}{L_COLON} {S_SELECT_SORT_DAYS}</label>
+ <!-- IF S_SELECT_SORT_KEY -->
+ <label>{L_SORT_BY}{L_COLON} {S_SELECT_SORT_KEY}</label>
+ <label>{L_SORT_DIRECTION}{L_COLON} {S_SELECT_SORT_DIR}</label>
+ <!-- ENDIF -->
+ <hr class="dashed" />
+ <input type="submit" class="button2" name="sort" value="{L_GO}" />
+ <!-- ENDIF -->
+ </fieldset>
+ </div>
+ </div>
+</div>
diff --git a/phpBB/styles/prosilver/template/faq_body.html b/phpBB/styles/prosilver/template/faq_body.html
index 53205d14e9..e55c12ac48 100644
--- a/phpBB/styles/prosilver/template/faq_body.html
+++ b/phpBB/styles/prosilver/template/faq_body.html
@@ -34,8 +34,10 @@
<dl class="faq">
<dt id="f{faq_block.S_ROW_COUNT}r{faq_block.faq_row.S_ROW_COUNT}"><strong>{faq_block.faq_row.FAQ_QUESTION}</strong></dt>
<dd>{faq_block.faq_row.FAQ_ANSWER}</dd>
- <dd><a href="#faqlinks" class="top2">{L_BACK_TO_TOP}</a></dd>
</dl>
+ <a href="#faqlinks" class="top">
+ <i class="icon fa-chevron-circle-up fa-fw icon-gray" aria-hidden="true"></i><span>{L_BACK_TO_TOP}</span>
+ </a>
<!-- IF not faq_block.faq_row.S_LAST_ROW --><hr class="dashed" /><!-- ENDIF -->
<!-- END faq_row -->
</div>
diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js
index 99f3108fad..b803a6f5c8 100644
--- a/phpBB/styles/prosilver/template/forum_fn.js
+++ b/phpBB/styles/prosilver/template/forum_fn.js
@@ -365,13 +365,13 @@ function parseDocument($container) {
/**
* Adjust HTML code for IE8 and older versions
*/
- if (oldBrowser) {
- // Fix .linklist.bulletin lists
- $container
- .find('ul.linklist.bulletin > li')
- .filter(':first-child, .rightside:last-child')
- .addClass('no-bulletin');
- }
+ // if (oldBrowser) {
+ // // Fix .linklist.bulletin lists
+ // $container
+ // .find('ul.linklist.bulletin > li')
+ // .filter(':first-child, .rightside:last-child')
+ // .addClass('no-bulletin');
+ // }
/**
* Resize navigation (breadcrumbs) block to keep all links on same line
@@ -492,7 +492,7 @@ function parseDocument($container) {
$linksFirst = $linksNotSkip.not(filterLast), // The items that will be hidden first
$linksLast = $linksNotSkip.filter(filterLast), // The items that will be hidden last
persistent = $this.attr('id') === 'nav-main', // Does this list already have a menu (such as quick-links)?
- html = '<li class="responsive-menu hidden"><a href="javascript:void(0);" class="responsive-menu-link">&nbsp;</a><div class="dropdown hidden"><div class="pointer"><div class="pointer-inner" /></div><ul class="dropdown-contents" /></div></li>',
+ html = '<li class="responsive-menu hidden"><a href="javascript:void(0);" class="js-responsive-menu-link responsive-menu-link"><i class="icon fa-bars fa-fw" aria-hidden="true"></i></a><div class="dropdown"><div class="pointer"><div class="pointer-inner" /></div><ul class="dropdown-contents" /></div></li>',
slack = 3; // Vertical slack space (in pixels). Determines how sensitive the script is in determining whether a line-break has occured.
// Add a hidden drop-down menu to each links list (except those that already have one)
@@ -581,8 +581,10 @@ function parseDocument($container) {
$menuContents.prepend($clones1.addClass('clone clone-first').removeClass('leftside rightside'));
if ($this.hasClass('post-buttons')) {
- $('.button', $menuContents).removeClass('button icon-button');
- $('.responsive-menu-link', $menu).addClass('button icon-button').prepend('<span></span>');
+ $('.button', $menuContents).removeClass('button');
+ $('.sr-only', $menuContents).removeClass('sr-only');
+ $('.js-responsive-menu-link').addClass('button').addClass('button-icon-only');
+ $('.js-responsive-menu-link .icon').removeClass('fa-bars').addClass('fa-ellipsis-h');
}
copied1 = true;
}
@@ -636,7 +638,7 @@ function parseDocument($container) {
}
if (!persistent) {
- phpbb.registerDropdown($menu.find('a.responsive-menu-link'), $menu.find('.dropdown'), false);
+ phpbb.registerDropdown($menu.find('a.js-responsive-menu-link'), $menu.find('.dropdown'), false);
}
// If there are any images in the links list, run the check again after they have loaded
diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html
index f8d6e36c8c..211f402503 100644
--- a/phpBB/styles/prosilver/template/forumlist_body.html
+++ b/phpBB/styles/prosilver/template/forumlist_body.html
@@ -14,7 +14,7 @@
<ul class="topiclist">
<li class="header">
<!-- EVENT forumlist_body_category_header_row_prepend -->
- <dl class="icon">
+ <dl class="row-item">
<dt><div class="list-inner"><!-- IF forumrow.S_IS_CAT --><a href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a><!-- ELSE -->{L_FORUM}<!-- ENDIF --></div></dt>
<dd class="topics">{L_TOPICS}</dd>
<dd class="posts">{L_POSTS}</dd>
@@ -31,12 +31,17 @@
<!-- EVENT forumlist_body_forum_row_before -->
<li class="row">
<!-- EVENT forumlist_body_forum_row_prepend -->
- <dl class="icon {forumrow.FORUM_IMG_STYLE}">
+ <dl class="row-item {forumrow.FORUM_IMG_STYLE}">
<dt title="{forumrow.FORUM_FOLDER_IMG_ALT}">
- <!-- IF forumrow.S_UNREAD_FORUM --><a href="{forumrow.U_VIEWFORUM}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF forumrow.S_UNREAD_FORUM --><a href="{forumrow.U_VIEWFORUM}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
- <!-- IF S_ENABLE_FEEDS and forumrow.S_FEED_ENABLED --><!-- <a class="feed-icon-forum" title="{L_FEED} - {forumrow.FORUM_NAME}" href="{U_FEED}?f={forumrow.FORUM_ID}"><img src="{T_THEME_PATH}/images/feed.gif" alt="{L_FEED} - {forumrow.FORUM_NAME}" /></a> --><!-- ENDIF -->
-
+ <!-- IF S_ENABLE_FEEDS and forumrow.S_FEED_ENABLED -->
+ <!--
+ <a class="feed-icon-forum" title="{L_FEED} - {forumrow.FORUM_NAME}" href="{U_FEED}?f={forumrow.FORUM_ID}">
+ <i class="icon fa-rss-square fa-fw icon-orange" aria-hidden="true"></i><span class="sr-only">{L_FEED} - {forumrow.FORUM_NAME}</span>
+ </a>
+ -->
+ <!-- ENDIF -->
<!-- IF forumrow.FORUM_IMAGE --><span class="forum-image">{forumrow.FORUM_IMAGE}</span><!-- ENDIF -->
<a href="{forumrow.U_VIEWFORUM}" class="forumtitle">{forumrow.FORUM_NAME}</a>
<!-- IF forumrow.FORUM_DESC --><br />{forumrow.FORUM_DESC}<!-- ENDIF -->
@@ -47,7 +52,10 @@
<!-- EVENT forumlist_body_subforums_before -->
<br /><strong>{forumrow.L_SUBFORUM_STR}{L_COLON}</strong>
<!-- BEGIN subforum -->
- <a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.S_UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->">{forumrow.subforum.SUBFORUM_NAME}</a><!-- IF not forumrow.subforum.S_LAST_ROW -->{L_COMMA_SEPARATOR}<!-- ENDIF -->
+ <a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.S_UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->">
+ <i class="icon fa-file-o fa-fw <!-- IF forumrow.subforum.S_UNREAD --> icon-red<!-- ELSE --> icon-blue<!-- ENDIF --> icon-md" aria-hidden="true"></i>{forumrow.subforum.SUBFORUM_NAME}
+ </a>
+ <!-- IF not forumrow.subforum.S_LAST_ROW -->{L_COMMA_SEPARATOR}<!-- ENDIF -->
<!-- END subforum -->
<!-- EVENT forumlist_body_subforums_after -->
<!-- ENDIF -->
@@ -68,19 +76,34 @@
<!-- ELSEIF not forumrow.S_IS_LINK -->
<dd class="topics">{forumrow.TOPICS} <dfn>{L_TOPICS}</dfn></dd>
<dd class="posts">{forumrow.POSTS} <dfn>{L_POSTS}</dfn></dd>
- <dd class="lastpost"><span>
- <!-- IF forumrow.U_UNAPPROVED_TOPICS -->
- <a href="{forumrow.U_UNAPPROVED_TOPICS}">{UNAPPROVED_IMG}</a>
- <!-- ELSEIF forumrow.U_UNAPPROVED_POSTS -->
- <a href="{forumrow.U_UNAPPROVED_POSTS}">{UNAPPROVED_POST_IMG}</a>
- <!-- ENDIF -->
- <!-- IF forumrow.LAST_POST_TIME --><dfn>{L_LAST_POST}</dfn>
- <!-- IF forumrow.S_DISPLAY_SUBJECT -->
- <!-- EVENT forumlist_body_last_post_title_prepend -->
- <a href="{forumrow.U_LAST_POST}" title="{forumrow.LAST_POST_SUBJECT}" class="lastsubject">{forumrow.LAST_POST_SUBJECT_TRUNCATED}</a> <br />
- <!-- ENDIF -->
- {L_POST_BY_AUTHOR} {forumrow.LAST_POSTER_FULL}
- <!-- IF not S_IS_BOT --><a href="{forumrow.U_LAST_POST}">{LAST_POST_IMG}</a> <!-- ENDIF --><br />{forumrow.LAST_POST_TIME}<!-- ELSE -->{L_NO_POSTS}<br />&nbsp;<!-- ENDIF --></span>
+ <dd class="lastpost">
+ <span>
+ <!-- IF forumrow.U_UNAPPROVED_TOPICS -->
+ <a href="{forumrow.U_UNAPPROVED_TOPICS}" title="{L_TOPICS_UNAPPROVED}">
+ <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPICS_UNAPPROVED}</span>
+ </a>
+ <!-- ELSEIF forumrow.U_UNAPPROVED_POSTS -->
+ <a href="{forumrow.U_UNAPPROVED_POSTS}" title="{L_POSTS_UNAPPROVED_FORUM}">
+ <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_POSTS_UNAPPROVED_FORUM}</span>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF forumrow.LAST_POST_TIME -->
+ <dfn>{L_LAST_POST}</dfn>
+ <!-- IF forumrow.S_DISPLAY_SUBJECT -->
+ <!-- EVENT forumlist_body_last_post_title_prepend -->
+ <a href="{forumrow.U_LAST_POST}" title="{forumrow.LAST_POST_SUBJECT}" class="lastsubject">{forumrow.LAST_POST_SUBJECT_TRUNCATED}</a> <br />
+ <!-- ENDIF -->
+ {L_POST_BY_AUTHOR} {forumrow.LAST_POSTER_FULL}
+ <!-- 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>
+ </a>
+ <!-- ENDIF -->
+ <br />{forumrow.LAST_POST_TIME}
+ <!-- ELSE -->
+ {L_NO_POSTS}<br />&nbsp;
+ <!-- ENDIF -->
+ </span>
</dd>
<!-- ELSE -->
<dd>&nbsp;</dd>
diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html
index 3096d08318..0c40e85783 100644
--- a/phpBB/styles/prosilver/template/jumpbox.html
+++ b/phpBB/styles/prosilver/template/jumpbox.html
@@ -1,26 +1,43 @@
<!-- IF S_VIEWTOPIC -->
- <p class="jumpbox-return"><a href="{U_VIEW_FORUM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO_FORUM}</a></p>
+ <p class="jumpbox-return">
+ <a href="{U_VIEW_FORUM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_TO_FORUM}</span>
+ </a>
+ </p>
<!-- ELSEIF S_VIEWFORUM -->
- <p class="jumpbox-return"><a href="{U_INDEX}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO_INDEX}</a></p>
+ <p class="jumpbox-return">
+ <a href="{U_INDEX}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_TO_INDEX}</span>
+ </a>
+ </p>
<!-- ELSEIF SEARCH_TOPIC -->
- <p class="jumpbox-return"><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}" accesskey="r">{L_RETURN_TO_TOPIC}</a></p>
+ <p class="jumpbox-return">
+ <a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_TO_TOPIC}</span>
+ </a>
+ </p>
<!-- ELSEIF S_SEARCH_ACTION -->
- <p class="jumpbox-return"><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}" accesskey="r">{L_GO_TO_SEARCH_ADV}</a></p>
+ <p class="jumpbox-return">
+ <a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_GO_TO_SEARCH_ADV}</span>
+ </a>
+ </p>
<!-- ENDIF -->
<!-- IF S_DISPLAY_JUMPBOX -->
- <div class="dropdown-container dropdown-container-{S_CONTENT_FLOW_END}<!-- IF not S_IN_MCP --> dropdown-up<!-- ENDIF --> dropdown-{S_CONTENT_FLOW_BEGIN} dropdown-button-control" id="jumpbox">
- <span title="<!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->" class="dropdown-trigger button dropdown-select">
- <!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->
+ <div class="jumpbox dropdown-container dropdown-container-right<!-- IF not S_IN_MCP --> dropdown-up<!-- ENDIF --> dropdown-{S_CONTENT_FLOW_BEGIN} dropdown-button-control" id="jumpbox">
+ <span title="<!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->" class="button button-secondary dropdown-trigger dropdown-select">
+ <span><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF --></span>
+ <span class="caret"><i class="icon fa-sort-down fa-fw" aria-hidden="true"></i></span>
</span>
- <div class="dropdown hidden">
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents">
<!-- BEGIN jumpbox_forums -->
<!-- IF jumpbox_forums.FORUM_ID neq -1 -->
- <li><!-- BEGIN level -->&nbsp; &nbsp;<!-- END level --><a href="{jumpbox_forums.LINK}">{jumpbox_forums.FORUM_NAME}</a></li>
+ <li><a href="{jumpbox_forums.LINK}" class="<!-- IF jumpbox_forums.level -->jumpbox-sub-link<!-- ELSEIF jumpbox_forums.S_IS_CAT -->jumpbox-cat-link<!-- ELSE -->jumpbox-forum-link<!-- ENDIF -->"><!-- BEGIN level --><span class="spacer"></span><!-- END level --> <span><!-- IF jumpbox_forums.level --> &#8627; &nbsp;<!-- ENDIF --> {jumpbox_forums.FORUM_NAME}</span></a></li>
<!-- ENDIF -->
<!-- END jumpbox_forums -->
</ul>
diff --git a/phpBB/styles/prosilver/template/mcp_approve.html b/phpBB/styles/prosilver/template/mcp_approve.html
index 14472bcf4f..f7874ab90b 100644
--- a/phpBB/styles/prosilver/template/mcp_approve.html
+++ b/phpBB/styles/prosilver/template/mcp_approve.html
@@ -39,7 +39,7 @@
<fieldset>
<!-- IF S_NOTIFY_POSTER -->
- <dl class="panel">
+ <dl class="fields2 nobg">
<dt>&nbsp;</dt>
<dd><label><input type="checkbox" name="notify_poster" checked="checked" /> <!-- IF S_APPROVE -->{L_NOTIFY_POSTER_APPROVAL}<!-- ELSE -->{L_NOTIFY_POSTER_DISAPPROVAL}<!-- ENDIF --></label></dd>
</dl>
@@ -66,7 +66,7 @@
</fieldset>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="submit" name="confirm" value="{YES_VALUE}" class="button1" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="submit" name="confirm" value="{YES_VALUE}" class="button1" />&nbsp;
<input type="submit" name="cancel" value="{L_NO}" class="button2" />
</fieldset>
diff --git a/phpBB/styles/prosilver/template/mcp_ban.html b/phpBB/styles/prosilver/template/mcp_ban.html
index 5a7eaa7840..5b798d9b6c 100644
--- a/phpBB/styles/prosilver/template/mcp_ban.html
+++ b/phpBB/styles/prosilver/template/mcp_ban.html
@@ -74,7 +74,7 @@
<dl>
<dt><label for="banexclude0">{L_BAN_EXCLUDE}{L_COLON}</label><br /><span>{L_BAN_EXCLUDE_EXPLAIN}</span></dt>
<dd>
- <label for="banexclude1"><input type="radio" name="banexclude" id="banexclude1" value="1" /> {L_YES}</label>
+ <label for="banexclude1"><input type="radio" name="banexclude" id="banexclude1" value="1" /> {L_YES}</label>
<label for="banexclude0"><input type="radio" name="banexclude" id="banexclude0" value="0" checked="checked" /> {L_NO}</label>
</dd>
</dl>
@@ -85,7 +85,7 @@
</div>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="bansubmit" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
@@ -122,7 +122,7 @@
</div>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="unbansubmit" value="{L_SUBMIT}" class="button1" />
</fieldset>
diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html
index 5858a2c801..b4ef9e66af 100644
--- a/phpBB/styles/prosilver/template/mcp_forum.html
+++ b/phpBB/styles/prosilver/template/mcp_forum.html
@@ -10,7 +10,7 @@
<div class="panel">
<div class="inner">
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<div class="pagination">
{TOTAL_TOPICS}
<!-- IF .pagination -->
@@ -24,7 +24,7 @@
<!-- IF .topicrow -->
<ul class="topiclist<!-- IF S_MERGE_SELECT --> missing-column<!-- ENDIF -->">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt><div class="list-inner">{L_TOPICS}</div></dt>
<dd class="posts">{L_REPLIES}</dd>
<dd class="lastpost"><span>{L_LAST_POST}</span></dd>
@@ -36,23 +36,35 @@
<!-- BEGIN topicrow -->
<li class="row<!-- IF topicrow.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- IF topicrow.S_TOPIC_REPORTED --> reported<!-- ENDIF -->">
- <dl class="icon {topicrow.TOPIC_IMG_STYLE}">
+ <dl class="row-item {topicrow.TOPIC_IMG_STYLE}">
<dt <!-- IF topicrow.TOPIC_ICON_IMG -->style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF -->>
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
<!-- EVENT topiclist_row_prepend -->
<!-- IF topicrow.S_SELECT_TOPIC --><a href="{topicrow.U_SELECT_TOPIC}" class="topictitle">[ {L_SELECT_MERGE} ]</a>&nbsp;&nbsp; <!-- ENDIF -->
<!-- EVENT mcp_forum_topic_title_before -->
<a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
<!-- EVENT mcp_forum_topic_title_after -->
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --><a href="{topicrow.U_MCP_QUEUE}">{topicrow.UNAPPROVED_IMG}</a> <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_DELETED or topicrow.S_POSTS_DELETED --><a href="{topicrow.U_MCP_QUEUE}">{topicrow.DELETED_IMG}</a> <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED --><a href="{topicrow.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- 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>
+ <!-- ENDIF -->
+ <!-- IF topicrow.S_TOPIC_DELETED or topicrow.S_POSTS_DELETED -->
+ <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_DELETED}">
+ <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_DELETED}</span>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF topicrow.S_TOPIC_REPORTED -->
+ <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}">
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span>
+ </a>
+ <!-- ENDIF -->
<!-- IF topicrow.S_MOVED_TOPIC and S_CAN_DELETE -->&nbsp;<a href="{topicrow.U_DELETE_TOPIC}" class="topictitle">[ {L_DELETE_SHADOW_TOPIC} ]</a><!-- ENDIF -->
<br />
<!-- EVENT topiclist_row_topic_title_after -->
<div class="responsive-show" style="display: none;">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- ENDIF -->
+ <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <!-- ENDIF -->
{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} &laquo; {topicrow.LAST_POST_TIME}<br />
</div>
<span class="responsive-show left-box" style="display: none;">{L_REPLIES}{L_COLON} <strong>{topicrow.REPLIES}</strong></span>
@@ -73,15 +85,14 @@
<!-- ENDIF -->
<div class="responsive-hide">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- 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} &raquo; {topicrow.FIRST_POST_TIME}
</div>
<!-- EVENT topiclist_row_append -->
</div>
</dt>
<dd class="posts">{topicrow.REPLIES} <dfn>{L_REPLIES}</dfn></dd>
- <dd class="lastpost"><span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}<br />{topicrow.LAST_POST_TIME}</span>
- </dd>
+ <dd class="lastpost"><span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}<br />{topicrow.LAST_POST_TIME}</span></dd>
<!-- IF not S_MERGE_SELECT -->
<dd class="mark">
<!-- IF not topicrow.S_MOVED_TOPIC --><input type="checkbox" name="topic_id_list[]" value="{topicrow.TOPIC_ID}"<!-- IF topicrow.S_TOPIC_CHECKED --> checked="checked"<!-- ENDIF --> /><!-- ELSE -->&nbsp;<!-- ENDIF -->
@@ -97,16 +108,9 @@
</ul>
<!-- ENDIF -->
- <fieldset class="display-options">
- <label>{L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+
<div class="pagination">
{TOTAL_TOPICS}
<!-- IF .pagination -->
@@ -134,10 +138,8 @@
<!-- IF S_CAN_SYNC --><option value="resync">{L_RESYNC}</option><!-- ENDIF -->
<!-- IF S_CAN_MAKE_NORMAL --><option value="make_normal">{L_MAKE_NORMAL}</option><!-- ENDIF -->
<!-- IF S_CAN_MAKE_STICKY --><option value="make_sticky">{L_MAKE_STICKY}</option><!-- ENDIF -->
- <!-- IF S_CAN_MAKE_ANNOUNCE -->
- <option value="make_announce">{L_MAKE_ANNOUNCE}</option>
- <option value="make_global">{L_MAKE_GLOBAL}</option>
- <!-- ENDIF -->
+ <!-- IF S_CAN_MAKE_ANNOUNCE --><option value="make_announce">{L_MAKE_ANNOUNCE}</option><!-- ENDIF -->
+ <!-- IF S_CAN_MAKE_ANNOUNCE_GLOBAL --><option value="make_global">{L_MAKE_GLOBAL}</option><!-- ENDIF -->
</select>
<input class="button2" type="submit" value="{L_SUBMIT}" />
<div><a href="#" onclick="marklist('mcp', 'topic_id_list', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp', 'topic_id_list', false); return false;">{L_UNMARK_ALL}</a></div>
diff --git a/phpBB/styles/prosilver/template/mcp_front.html b/phpBB/styles/prosilver/template/mcp_front.html
index 8fe7dfdf65..97775814db 100644
--- a/phpBB/styles/prosilver/template/mcp_front.html
+++ b/phpBB/styles/prosilver/template/mcp_front.html
@@ -30,7 +30,7 @@
<dl>
<dt>
<div class="list-inner">
- <a href="{unapproved.U_POST_DETAILS}" class="topictitle">{unapproved.SUBJECT}</a> {unapproved.ATTACH_ICON_IMG}<br />
+ <a href="{unapproved.U_POST_DETAILS}" class="topictitle">{unapproved.SUBJECT}</a> <i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
{L_POSTED} {L_POST_BY_AUTHOR} {unapproved.AUTHOR_FULL} &raquo; {unapproved.POST_TIME}
</div>
</dt>
@@ -86,12 +86,12 @@
<dl>
<dt>
<div class="list-inner">
- <a href="{report.U_POST_DETAILS}#reports" class="topictitle">{report.SUBJECT}</a> {report.ATTACH_ICON_IMG}<br />
+ <a href="{report.U_POST_DETAILS}#reports" class="topictitle">{report.SUBJECT}</a> <i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
<span>{L_POSTED} {L_POST_BY_AUTHOR} {report.AUTHOR_FULL} &raquo; {report.POST_TIME}</span>
</div>
</dt>
<dd class="moderation">
- <span>{L_REPORTED} {L_POST_BY_AUTHOR} {report.REPORTER_FULL} {L_REPORTED_ON_DATE} {report.REPORT_TIME}<br />
+ <span>{L_REPORTED} {L_POST_BY_AUTHOR} {report.REPORTER_FULL} {L_REPORTED_ON_DATE} <i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
{L_FORUM}{L_COLON} <a href="{report.U_FORUM}">{report.FORUM_NAME}</a></span>
</dd>
</dl>
@@ -129,7 +129,7 @@
<dl>
<dt>
<div class="list-inner">
- <a href="{pm_report.U_PM_DETAILS}" class="topictitle">{pm_report.PM_SUBJECT}</a> {pm_report.ATTACH_ICON_IMG}<br />
+ <a href="{pm_report.U_PM_DETAILS}" class="topictitle">{pm_report.PM_SUBJECT}</a> <i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
<span>{L_MESSAGE_BY_AUTHOR} {pm_report.PM_AUTHOR_FULL} &raquo; {pm_report.PM_TIME}</span><br />
<span>{L_MESSAGE_TO} {pm_report.RECIPIENTS}</span>
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_header.html b/phpBB/styles/prosilver/template/mcp_header.html
index 69239887e3..5841c1bbd2 100644
--- a/phpBB/styles/prosilver/template/mcp_header.html
+++ b/phpBB/styles/prosilver/template/mcp_header.html
@@ -8,7 +8,7 @@
</p>
<!-- ENDIF -->
-<div id="tabs">
+<div id="tabs" class="tabs">
<ul>
<!-- BEGIN l_block1 -->
<li class="tab<!-- IF l_block1.S_SELECTED --> activetab<!-- ENDIF -->"><a href="{l_block1.U_TITLE}">{l_block1.L_TITLE}</a></li>
@@ -21,14 +21,14 @@
<div style="width: 100%;">
- <div id="cp-menu">
- <div id="navigation" role="navigation">
+ <div id="cp-menu" class="cp-menu">
+ <div id="navigation" class="navigation" role="navigation">
<ul>
<!-- BEGIN l_block1 -->
<!-- IF l_block1.S_SELECTED -->
<!-- BEGIN l_block2 -->
<!-- IF l_block1.l_block2.S_SELECTED -->
- <li id="active-subsection"><a href="{l_block1.l_block2.U_TITLE}"><span>{l_block1.l_block2.L_TITLE}<!-- IF l_block1.l_block2.ADD_ITEM --> ({l_block1.l_block2.ADD_ITEM})<!-- ENDIF --></span></a></li>
+ <li id="active-subsection" class="active-subsection"><a href="{l_block1.l_block2.U_TITLE}"><span>{l_block1.l_block2.L_TITLE}<!-- IF l_block1.l_block2.ADD_ITEM --> ({l_block1.l_block2.ADD_ITEM})<!-- ENDIF --></span></a></li>
<!-- ELSE -->
<li><a href="{l_block1.l_block2.U_TITLE}"><span>{l_block1.l_block2.L_TITLE}<!-- IF l_block1.l_block2.ADD_ITEM --> ({l_block1.l_block2.ADD_ITEM})<!-- ENDIF --></span></a></li>
<!-- ENDIF -->
@@ -39,7 +39,7 @@
</div>
</div>
- <div id="cp-main" class="mcp-main panel-container">
+ <div id="cp-main" class="cp-main mcp-main panel-container">
<!-- IF MESSAGE -->
<div class="content">
<h2 class="message-title">{L_MESSAGE}</h2>
diff --git a/phpBB/styles/prosilver/template/mcp_logs.html b/phpBB/styles/prosilver/template/mcp_logs.html
index 4f74085968..03216b4f38 100644
--- a/phpBB/styles/prosilver/template/mcp_logs.html
+++ b/phpBB/styles/prosilver/template/mcp_logs.html
@@ -7,13 +7,13 @@
<div class="panel">
<div class="inner">
- <div class="action-bar top">
+ <div class="action-bar bar-top">
{L_SEARCH_KEYWORDS}{L_COLON} <input type="search" class="inputbox autowidth" name="keywords" value="{S_KEYWORDS}" />&nbsp;<input type="submit" class="button2" name="filter" value="{L_SEARCH}" />
<div class="pagination">
{TOTAL}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -51,21 +51,14 @@
</table>
<!-- IF .log -->
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+
<div class="pagination">
{TOTAL}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_notes_front.html b/phpBB/styles/prosilver/template/mcp_notes_front.html
index db10284bce..11f362376d 100644
--- a/phpBB/styles/prosilver/template/mcp_notes_front.html
+++ b/phpBB/styles/prosilver/template/mcp_notes_front.html
@@ -19,7 +19,7 @@
</div>
<fieldset class="submit-buttons">
- <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="submituser" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/mcp_notes_user.html b/phpBB/styles/prosilver/template/mcp_notes_user.html
index 3e8d47eb9d..62d0562a46 100644
--- a/phpBB/styles/prosilver/template/mcp_notes_user.html
+++ b/phpBB/styles/prosilver/template/mcp_notes_user.html
@@ -50,13 +50,13 @@
<div class="panel">
<div class="inner">
- <div class="action-bar top">
+ <div class="action-bar bar-top">
{L_SEARCH_KEYWORDS}{L_COLON} <input type="search" class="inputbox autowidth" name="keywords" value="{S_KEYWORDS}" />&nbsp;<input type="submit" class="button2" name="filter" value="{L_SEARCH}" />
<div class="pagination">
{TOTAL_REPORTS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -90,22 +90,14 @@
</tbody>
</table>
- <hr />
-
- <fieldset class="display-options">
- <label>{L_DISPLAY_LOG}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+
<div class="pagination">
{TOTAL_REPORTS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html
index e5777d206a..a0de554e21 100644
--- a/phpBB/styles/prosilver/template/mcp_post.html
+++ b/phpBB/styles/prosilver/template/mcp_post.html
@@ -14,7 +14,7 @@
<h3>{L_REPORT_REASON}{L_COLON} {REPORT_REASON_TITLE}</h3>
<p class="author">{L_REPORTED} {L_POST_BY_AUTHOR} {REPORTER_FULL} &laquo; {REPORT_DATE}</p>
<!-- IF S_REPORT_CLOSED -->
- <p class="post-notice reported">{L_REPORT_CLOSED}</p>
+ <p class="post-notice reported"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i>{L_REPORT_CLOSED}</p>
<!-- ENDIF -->
<div class="content">
<!-- IF REPORT_TEXT -->
@@ -58,8 +58,8 @@
</li>
<!-- IF U_EDIT -->
<li>
- <a href="{U_EDIT}" title="{L_EDIT_POST}" class="button icon-button edit-icon">
- <span>{L_EDIT_POST}</span>
+ <a href="{U_EDIT}" title="{L_EDIT_POST}" class="button">
+ <i class="icon fa-pencil fa-fw" aria-hidden="true"></i><span class="sr-only">{L_EDIT_POST}</span>
</a>
</li>
<!-- ENDIF -->
@@ -73,7 +73,7 @@
<!-- 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 -->&nbsp;<!-- END bcc_recipient --><!-- ENDIF -->
</p>
<!-- ELSE -->
- <p class="author">{MINI_POST_IMG} {L_POSTED} {L_POST_BY_AUTHOR} {POST_AUTHOR_FULL} &raquo; {POST_DATE}</p>
+ <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} &raquo; {POST_DATE}</p>
<!-- ENDIF -->
<!-- IF S_POST_UNAPPROVED -->
@@ -102,11 +102,11 @@
<!-- IF S_MESSAGE_REPORTED -->
<p class="post-notice reported">
- {REPORTED_IMG} <a href="{U_MCP_REPORT}"><strong>{L_MESSAGE_REPORTED}</strong></a>
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> <a href="{U_MCP_REPORT}"><strong>{L_MESSAGE_REPORTED}</strong></a>
</p>
<!-- ENDIF -->
- <div class="content" id="post_details">
+ <div id="post_details" class="content post_details">
{POST_PREVIEW}
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_queue.html b/phpBB/styles/prosilver/template/mcp_queue.html
index 864b231142..c82aae5f8c 100644
--- a/phpBB/styles/prosilver/template/mcp_queue.html
+++ b/phpBB/styles/prosilver/template/mcp_queue.html
@@ -16,12 +16,12 @@
<p>{L_EXPLAIN}</p>
<!-- IF .postrow -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<div class="pagination">
{TOTAL}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -48,7 +48,7 @@
<dl>
<dt>
<div class="list-inner">
- <a href="{postrow.U_VIEW_DETAILS}" class="topictitle">{postrow.POST_SUBJECT}</a> {postrow.ATTACH_ICON_IMG}<br />
+ <a href="{postrow.U_VIEW_DETAILS}" class="topictitle">{postrow.POST_SUBJECT}</a> <i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
<span>{L_POSTED} {L_POST_BY_AUTHOR} {postrow.POST_AUTHOR_FULL} &raquo; {postrow.POST_TIME}</span>
</div>
</dt>
@@ -73,21 +73,15 @@
<!-- END postrow -->
</ul>
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" />&nbsp; <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+ <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" onClick="document.getElementById('mcp').submit()" /> <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
+
<div class="pagination">
{TOTAL}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_reports.html b/phpBB/styles/prosilver/template/mcp_reports.html
index 24c0479f63..e7e0a5c9ba 100644
--- a/phpBB/styles/prosilver/template/mcp_reports.html
+++ b/phpBB/styles/prosilver/template/mcp_reports.html
@@ -18,12 +18,12 @@
<p>{L_EXPLAIN}</p>
<!-- IF .postrow -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<div class="pagination">
{TOTAL_REPORTS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -46,7 +46,7 @@
<!-- IF S_PM -->
<dt>
<div class="list-inner">
- <a href="{postrow.U_VIEW_DETAILS}" class="topictitle">{postrow.PM_SUBJECT}</a> {postrow.ATTACH_ICON_IMG}<br />
+ <a href="{postrow.U_VIEW_DETAILS}" class="topictitle">{postrow.PM_SUBJECT}</a> <i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
<span>{L_MESSAGE_BY_AUTHOR} {postrow.PM_AUTHOR_FULL} &raquo; {postrow.PM_TIME}</span><br />
<span>{L_MESSAGE_TO} {postrow.RECIPIENTS}</span>
<div class="responsive-show" style="display: none;">
@@ -60,7 +60,7 @@
<!-- ELSE -->
<dt>
<div class="list-inner">
- <a href="{postrow.U_VIEW_DETAILS}" class="topictitle">{postrow.POST_SUBJECT}</a> {postrow.ATTACH_ICON_IMG}<br />
+ <a href="{postrow.U_VIEW_DETAILS}" class="topictitle">{postrow.POST_SUBJECT}</a><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <br />
<span>{L_POSTED} {L_POST_BY_AUTHOR} {postrow.POST_AUTHOR_FULL} &raquo; {postrow.POST_TIME}</span>
<div class="responsive-show" style="display: none;">
{L_REPORTER}{L_COLON} {postrow.REPORTER_FULL} &laquo; {postrow.REPORT_TIME}<br />
@@ -79,21 +79,15 @@
<!-- END postrow -->
</ul>
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" />&nbsp; <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+ <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" onClick="document.getElementById('mcp').submit()" /> <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
+
<div class="pagination">
{TOTAL_REPORTS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html
index 22d837b3d1..d64c9c9a21 100644
--- a/phpBB/styles/prosilver/template/mcp_topic.html
+++ b/phpBB/styles/prosilver/template/mcp_topic.html
@@ -11,7 +11,7 @@
<!-- DEFINE $SHOW_PANEL = 'display-panel' -->
<!-- ENDIF -->
-<div id="minitabs" class="sub-panels" data-show-panel="{$SHOW_PANEL}" role="tablist">
+<div id="minitabs" class="minitabs sub-panels" data-show-panel="{$SHOW_PANEL}" role="tablist">
<ul>
<li id="display-panel-tab" class="tab<!-- IF not S_MERGE_VIEW --> activetab<!-- ENDIF -->">
<a href="#minitabs" data-subpanel="display-panel" role="tab" aria-controls="display-panel">{L_DISPLAY_OPTIONS}</a>
@@ -87,12 +87,12 @@
<div class="panel">
<div class="inner">
- <h3 id="review">
+ <h3 id="review" class="review">
<span class="right-box"><a href="#review" onclick="viewableArea(getElementById('topicreview'), true); var rev_text = getElementById('review').getElementsByTagName('a').item(0).firstChild; if (rev_text.data == '{LA_EXPAND_VIEW}'){rev_text.data = '{LA_COLLAPSE_VIEW}'; } else if (rev_text.data == '{LA_COLLAPSE_VIEW}'){rev_text.data = '{LA_EXPAND_VIEW}'};">{L_EXPAND_VIEW}</a></span>
{L_TOPIC_REVIEW}{L_COLON} <!-- EVENT mcp_topic_topic_title_before -->{TOPIC_TITLE}<!-- EVENT mcp_topic_topic_title_after -->
</h3>
- <div id="topicreview">
+ <div id="topicreview" class="topicreview">
<!-- BEGIN postrow -->
<div class="post <!-- IF postrow.S_ROW_COUNT is odd -->bg1<!-- ELSE -->bg2<!-- ENDIF -->">
<div class="inner">
@@ -100,8 +100,8 @@
<div class="postbody" id="pr{postrow.POST_ID}">
<ul class="post-buttons">
<li>
- <a href="{postrow.U_POST_DETAILS}" title="{L_POST_DETAILS}" class="button icon-button info-icon">
- <span>{L_POST_DETAILS}</span>
+ <a href="{postrow.U_POST_DETAILS}" title="{L_POST_DETAILS}" class="button button-icon-only">
+ <i class="icon fa-info fa-fw" aria-hidden="true"></i><span class="sr-only">{L_POST_DETAILS}</span>
</a>
</li>
<li>
@@ -114,12 +114,16 @@
<h3><a href="{postrow.U_POST_DETAILS}">{postrow.POST_SUBJECT}</a></h3>
<!-- EVENT mcp_topic_postrow_post_details_before -->
- <p class="author"><a href="#pr{postrow.POST_ID}">{postrow.MINI_POST_IMG}</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 --></p>
+ <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 -->
+ </p>
<!-- EVENT mcp_topic_postrow_post_details_after -->
<!-- IF postrow.S_POST_UNAPPROVED -->
<p class="post-notice unapproved">
- <a href="{postrow.U_MCP_APPROVE}"><strong>{L_POST_UNAPPROVED}</strong></a>
+ <a href="{postrow.U_MCP_APPROVE}"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><strong>{L_POST_UNAPPROVED}</strong></a>
</p>
<!-- ENDIF -->
@@ -131,7 +135,7 @@
<!-- IF postrow.S_POST_REPORTED -->
<p class="post-notice reported">
- <a href="{postrow.U_MCP_REPORT}"><strong>{L_POST_REPORTED}</strong></a>
+ <a href="{postrow.U_MCP_REPORT}"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><strong>{L_POST_REPORTED}</strong></a>
</p>
<!-- ENDIF -->
@@ -155,7 +159,7 @@
<hr />
- <div class="action-bar bottom">
+ <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_POSTS}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/mcp_warn_front.html b/phpBB/styles/prosilver/template/mcp_warn_front.html
index 668a0d81a8..9b188b52ac 100644
--- a/phpBB/styles/prosilver/template/mcp_warn_front.html
+++ b/phpBB/styles/prosilver/template/mcp_warn_front.html
@@ -21,7 +21,7 @@
</div>
<fieldset class="submit-buttons">
- <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="submituser" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/mcp_warn_list.html b/phpBB/styles/prosilver/template/mcp_warn_list.html
index d0e80a1479..29a2d29e8f 100644
--- a/phpBB/styles/prosilver/template/mcp_warn_list.html
+++ b/phpBB/styles/prosilver/template/mcp_warn_list.html
@@ -10,12 +10,12 @@
<p>{L_WARNED_USERS_EXPLAIN}</p>
<!-- IF .user -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<div class="pagination">
{TOTAL_USERS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -43,20 +43,14 @@
</tbody>
</table>
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+
<div class="pagination">
{TOTAL_USERS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/mcp_warn_post.html b/phpBB/styles/prosilver/template/mcp_warn_post.html
index 59c7d0d495..5e39480658 100644
--- a/phpBB/styles/prosilver/template/mcp_warn_post.html
+++ b/phpBB/styles/prosilver/template/mcp_warn_post.html
@@ -69,7 +69,7 @@
<!-- EVENT mcp_warn_post_add_warning_field_after -->
<fieldset class="submit-buttons">
- <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="action[add_warning]" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/mcp_warn_user.html b/phpBB/styles/prosilver/template/mcp_warn_user.html
index 1ad6df7ade..f4dbf2819e 100644
--- a/phpBB/styles/prosilver/template/mcp_warn_user.html
+++ b/phpBB/styles/prosilver/template/mcp_warn_user.html
@@ -53,7 +53,7 @@
<!-- EVENT mcp_warn_user_add_warning_field_after -->
<fieldset class="submit-buttons">
- <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="action[add_warning]" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/mcp_whois.html b/phpBB/styles/prosilver/template/mcp_whois.html
index 41a825458d..1d08a4627e 100644
--- a/phpBB/styles/prosilver/template/mcp_whois.html
+++ b/phpBB/styles/prosilver/template/mcp_whois.html
@@ -3,13 +3,19 @@
<div class="panel">
<div class="inner">
-
- <p><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_RETURN_POST}">{L_RETURN_POST}</a></p>
+ <p>
+ <a href="{U_RETURN_POST}" class="arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_POST}</span>
+ </a>
+ </p>
<div class="postbody"><div class="content">
<pre>{WHOIS}</pre>
</div></div>
- <p><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_RETURN_POST}">{L_RETURN_POST}</a></p>
-
+ <p>
+ <a href="{U_RETURN_POST}" class="arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_POST}</span>
+ </a>
+ </p>
</div>
</div>
diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html
index 5fba59159c..255e6746e1 100644
--- a/phpBB/styles/prosilver/template/memberlist_body.html
+++ b/phpBB/styles/prosilver/template/memberlist_body.html
@@ -27,21 +27,21 @@
<!-- ELSE -->
<h2 class="solo">{PAGE_TITLE}<!-- IF SEARCH_WORDS -->{L_COLON} <a href="{U_SEARCH_WORDS}">{SEARCH_WORDS}</a><!-- ENDIF --></h2>
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<div class="member-search panel">
- <!-- IF U_FIND_MEMBER and not S_SEARCH_USER --><a href="{U_FIND_MEMBER}" id="member_search" data-alt-text="{LA_HIDE_MEMBER_SEARCH}">{L_FIND_USERNAME}</a> &bull; <!-- ELSEIF S_SEARCH_USER and U_HIDE_FIND_MEMBER and not S_IN_SEARCH_POPUP --><a href="{U_HIDE_FIND_MEMBER}" id="member_search" data-alt-text="{LA_FIND_USERNAME}">{L_HIDE_MEMBER_SEARCH}</a> &bull; <!-- ENDIF -->
+ <!-- IF U_FIND_MEMBER and not S_SEARCH_USER --><a href="{U_FIND_MEMBER}" id="member_search" data-alt-text="{L_HIDE_MEMBER_SEARCH}">{L_FIND_USERNAME}</a> &bull; <!-- ELSEIF S_SEARCH_USER and U_HIDE_FIND_MEMBER and not S_IN_SEARCH_POPUP --><a href="{U_HIDE_FIND_MEMBER}" id="member_search" data-alt-text="{L_FIND_USERNAME}">{L_HIDE_MEMBER_SEARCH}</a> &bull; <!-- ENDIF -->
<strong>
<!-- BEGIN first_char -->
<a href="{first_char.U_SORT}">{first_char.DESC}</a>&nbsp;
<!-- END first_char -->
</strong>
</div>
-
+
<div class="pagination">
{TOTAL_USERS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -52,7 +52,7 @@
<div class="forumbg forumbg-table">
<div class="inner">
- <table class="table1" id="memberlist">
+ <table class="table1 memberlist" id="memberlist">
<thead>
<tr>
<th class="name" data-dfn="{L_RANK}{L_COMMA_SEPARATOR}<!-- IF S_SHOW_GROUP and .memberrow -->{L_GROUP_LEADER}<!-- ELSE -->{L_USERNAME}<!-- ENDIF -->"><span class="rank-img"><a href="{U_SORT_RANK}">{L_RANK}</a></span><a href="{U_SORT_USERNAME}"><!-- IF S_SHOW_GROUP and .memberrow -->{L_GROUP_LEADER}<!-- ELSE -->{L_USERNAME}<!-- ENDIF --></a></th>
@@ -145,12 +145,12 @@
</form>
-<div class="action-bar bottom">
+<div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_USERS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/memberlist_team.html b/phpBB/styles/prosilver/template/memberlist_team.html
index b7f2d66d94..63349064bb 100644
--- a/phpBB/styles/prosilver/template/memberlist_team.html
+++ b/phpBB/styles/prosilver/template/memberlist_team.html
@@ -36,7 +36,7 @@
<!-- END user -->
</tbody>
</table>
-
+
</div>
</div>
<!-- END group -->
diff --git a/phpBB/styles/prosilver/template/message_body.html b/phpBB/styles/prosilver/template/message_body.html
index 71eca203bc..330203e19e 100644
--- a/phpBB/styles/prosilver/template/message_body.html
+++ b/phpBB/styles/prosilver/template/message_body.html
@@ -8,7 +8,13 @@
<div class="inner">
<h2 class="message-title">{MESSAGE_TITLE}</h2>
<p>{MESSAGE_TEXT}</p>
- <!-- IF SCRIPT_NAME == "search" and not S_BOARD_DISABLED and not S_NO_SEARCH and L_RETURN_TO_SEARCH_ADV --><p><a href="{U_SEARCH}" class="arrow-{S_CONTENT_FLOW_BEGIN}">{L_GO_TO_SEARCH_ADV}</a></p><!-- ENDIF -->
+ <!-- IF SCRIPT_NAME == "search" and not S_BOARD_DISABLED and not S_NO_SEARCH and L_RETURN_TO_SEARCH_ADV -->
+ <p>
+ <a href="{U_SEARCH}" class="arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_GO_TO_SEARCH_ADV}</span>
+ </a>
+ </p>
+ <!-- ENDIF -->
</div>
</div>
diff --git a/phpBB/styles/prosilver/template/navbar_footer.html b/phpBB/styles/prosilver/template/navbar_footer.html
index b5a705d567..4e3d1e295e 100644
--- a/phpBB/styles/prosilver/template/navbar_footer.html
+++ b/phpBB/styles/prosilver/template/navbar_footer.html
@@ -1,26 +1,68 @@
<div class="navbar" role="navigation">
<div class="inner">
- <ul id="nav-footer" class="linklist bulletin" role="menubar">
- <li class="small-icon icon-home breadcrumbs">
- <!-- IF U_SITE_HOME --><span class="crumb"><a href="{U_SITE_HOME}" data-navbar-reference="home">{L_SITE_HOME}</a></span><!-- ENDIF -->
+ <ul id="nav-footer" class="nav-footer linklist" role="menubar">
+ <li class="breadcrumbs">
+ <!-- IF U_SITE_HOME -->
+ {% spaceless %}
+ <span class="crumb">
+ <a href="{U_SITE_HOME}" data-navbar-reference="home">
+ <i class="icon fa-home fa-fw" aria-hidden="true"></i><span>{L_SITE_HOME}</span>
+ </a>
+ </span>
+ {% endspaceless %}
+ <!-- ENDIF -->
<!-- EVENT overall_footer_breadcrumb_prepend -->
- <span class="crumb"><a href="{U_INDEX}" data-navbar-reference="index">{L_INDEX}</a></span>
+ {% spaceless %}
+ <span class="crumb">
+ <a href="{U_INDEX}" data-navbar-reference="index">
+ <!-- IF not U_SITE_HOME --><i class="icon fa-home fa-fw" aria-hidden="true"></i><!-- ENDIF --><span>{L_INDEX}</span>
+ </a>
+ </span>
+ {% endspaceless %}
<!-- EVENT overall_footer_breadcrumb_append -->
</li>
- <!-- IF U_WATCH_FORUM_LINK and not S_IS_BOT --><li class="small-icon icon-<!-- IF S_WATCHING_FORUM -->unsubscribe<!-- ELSE -->subscribe<!-- ENDIF -->" data-last-responsive="true"><a href="{U_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}" data-ajax="toggle_link" data-toggle-class="small-icon icon-<!-- IF not S_WATCHING_FORUM -->unsubscribe<!-- ELSE -->subscribe<!-- ENDIF -->" data-toggle-text="{S_WATCH_FORUM_TOGGLE}" data-toggle-url="{U_WATCH_FORUM_TOGGLE}">{S_WATCH_FORUM_TITLE}</a></li><!-- ENDIF -->
+ <!-- IF U_WATCH_FORUM_LINK and not S_IS_BOT -->
+ <li data-last-responsive="true">
+ <a href="{U_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}" data-ajax="toggle_link" data-toggle-class="icon <!-- IF S_WATCHING_FORUM -->fa-check-square-o<!-- ELSE -->fa-square-o<!-- ENDIF --> fa-fw" data-toggle-text="{S_WATCH_FORUM_TOGGLE}" data-toggle-url="{U_WATCH_FORUM_TOGGLE}">
+ <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_FORUM_TITLE}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
<!-- EVENT overall_footer_timezone_before -->
<li class="rightside">{S_TIMEZONE}</li>
<!-- EVENT overall_footer_timezone_after -->
<!-- IF not S_IS_BOT -->
- <li class="small-icon icon-delete-cookies rightside"><a href="{U_DELETE_COOKIES}" data-ajax="true" data-refresh="true" role="menuitem">{L_DELETE_COOKIES}</a></li>
- <!-- IF S_DISPLAY_MEMBERLIST --><li class="small-icon icon-members rightside" data-last-responsive="true"><a href="{U_MEMBERLIST}" title="{L_MEMBERLIST_EXPLAIN}" role="menuitem">{L_MEMBERLIST}</a></li><!-- ENDIF -->
+ <li class="rightside">
+ <a href="{U_DELETE_COOKIES}" data-ajax="true" data-refresh="true" role="menuitem">
+ <i class="icon fa-trash fa-fw" aria-hidden="true"></i><span>{L_DELETE_COOKIES}</span>
+ </a>
+ </li>
+ <!-- IF S_DISPLAY_MEMBERLIST -->
+ <li class="rightside" data-last-responsive="true">
+ <a href="{U_MEMBERLIST}" title="{L_MEMBERLIST_EXPLAIN}" role="menuitem">
+ <i class="icon fa-group fa-fw" aria-hidden="true"></i><span>{L_MEMBERLIST}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
<!-- ENDIF -->
<!-- EVENT overall_footer_teamlink_before -->
- <!-- IF U_TEAM --><li class="small-icon icon-team rightside" data-last-responsive="true"><a href="{U_TEAM}" role="menuitem">{L_THE_TEAM}</a></li><!-- ENDIF -->
+ <!-- IF U_TEAM -->
+ <li class="rightside" data-last-responsive="true">
+ <a href="{U_TEAM}" role="menuitem">
+ <i class="icon fa-shield fa-fw" aria-hidden="true"></i><span>{L_THE_TEAM}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
<!-- EVENT overall_footer_teamlink_after -->
- <!-- IF U_CONTACT_US --><li class="small-icon icon-contact rightside" data-last-responsive="true"><a href="{U_CONTACT_US}" role="menuitem">{L_CONTACT_US}</a></li><!-- ENDIF -->
+ <!-- IF U_CONTACT_US -->
+ <li class="rightside" data-last-responsive="true">
+ <a href="{U_CONTACT_US}" role="menuitem">
+ <i class="icon fa-envelope fa-fw" aria-hidden="true"></i><span>{L_CONTACT_US}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
</ul>
</div>
diff --git a/phpBB/styles/prosilver/template/navbar_header.html b/phpBB/styles/prosilver/template/navbar_header.html
index e5f354a943..ab6eb0805b 100644
--- a/phpBB/styles/prosilver/template/navbar_header.html
+++ b/phpBB/styles/prosilver/template/navbar_header.html
@@ -1,11 +1,13 @@
<div class="navbar" role="navigation">
<div class="inner">
- <ul id="nav-main" class="linklist bulletin" role="menubar">
+ <ul id="nav-main" class="nav-main linklist" role="menubar">
- <li id="quick-links" class="small-icon responsive-menu dropdown-container<!-- IF not S_DISPLAY_QUICK_LINKS and not S_DISPLAY_SEARCH --> hidden<!-- ENDIF -->" data-skip-responsive="true">
- <a href="#" class="responsive-menu-link dropdown-trigger">{L_QUICK_LINKS}</a>
- <div class="dropdown hidden">
+ <li id="quick-links" class="quick-links dropdown-container responsive-menu<!-- IF not S_DISPLAY_QUICK_LINKS and not S_DISPLAY_SEARCH --> hidden<!-- ENDIF -->" data-skip-responsive="true">
+ <a href="#" class="dropdown-trigger">
+ <i class="icon fa-bars fa-fw" aria-hidden="true"></i><span>{L_QUICK_LINKS}</span>
+ </a>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents" role="menu">
<!-- EVENT navbar_header_quick_links_before -->
@@ -13,24 +15,60 @@
<!-- IF S_DISPLAY_SEARCH -->
<li class="separator"></li>
<!-- IF S_REGISTERED_USER -->
- <li class="small-icon icon-search-self"><a href="{U_SEARCH_SELF}" role="menuitem">{L_SEARCH_SELF}</a></li>
+ <li>
+ <a href="{U_SEARCH_SELF}" role="menuitem">
+ <i class="icon fa-file-o fa-fw icon-gray" aria-hidden="true"></i><span>{L_SEARCH_SELF}</span>
+ </a>
+ </li>
<!-- ENDIF -->
<!-- IF S_USER_LOGGED_IN -->
- <li class="small-icon icon-search-new"><a href="{U_SEARCH_NEW}" role="menuitem">{L_SEARCH_NEW}</a></li>
+ <li>
+ <a href="{U_SEARCH_NEW}" role="menuitem">
+ <i class="icon fa-file-o fa-fw icon-red" aria-hidden="true"></i><span>{L_SEARCH_NEW}</span>
+ </a>
+ </li>
<!-- ENDIF -->
<!-- IF S_LOAD_UNREADS -->
- <li class="small-icon icon-search-unread"><a href="{U_SEARCH_UNREAD}" role="menuitem">{L_SEARCH_UNREAD}</a></li>
+ <li>
+ <a href="{U_SEARCH_UNREAD}" role="menuitem">
+ <i class="icon fa-file-o fa-fw icon-red" aria-hidden="true"></i><span>{L_SEARCH_UNREAD}</span>
+ </a>
+ </li>
<!-- ENDIF -->
- <li class="small-icon icon-search-unanswered"><a href="{U_SEARCH_UNANSWERED}" role="menuitem">{L_SEARCH_UNANSWERED}</a></li>
- <li class="small-icon icon-search-active"><a href="{U_SEARCH_ACTIVE_TOPICS}" role="menuitem">{L_SEARCH_ACTIVE_TOPICS}</a></li>
- <li class="separator"></li>
- <li class="small-icon icon-search"><a href="{U_SEARCH}" role="menuitem">{L_SEARCH}</a></li>
+ <li>
+ <a href="{U_SEARCH_UNANSWERED}" role="menuitem">
+ <i class="icon fa-file-o fa-fw icon-gray" aria-hidden="true"></i><span>{L_SEARCH_UNANSWERED}</span>
+ </a>
+ </li>
+ <li>
+ <a href="{U_SEARCH_ACTIVE_TOPICS}" role="menuitem">
+ <i class="icon fa-file-o fa-fw icon-blue" aria-hidden="true"></i><span>{L_SEARCH_ACTIVE_TOPICS}</span>
+ </a>
+ </li>
+ <li class="separator"></li>
+ <li>
+ <a href="{U_SEARCH}" role="menuitem">
+ <i class="icon fa-search fa-fw" aria-hidden="true"></i><span>{L_SEARCH}</span>
+ </a>
+ </li>
<!-- ENDIF -->
<!-- IF not S_IS_BOT and (S_DISPLAY_MEMBERLIST or U_TEAM) -->
<li class="separator"></li>
- <!-- IF S_DISPLAY_MEMBERLIST --><li class="small-icon icon-members"><a href="{U_MEMBERLIST}" role="menuitem">{L_MEMBERLIST}</a></li><!-- ENDIF -->
- <!-- IF U_TEAM --><li class="small-icon icon-team"><a href="{U_TEAM}" role="menuitem">{L_THE_TEAM}</a></li><!-- ENDIF -->
+ <!-- IF S_DISPLAY_MEMBERLIST -->
+ <li>
+ <a href="{U_MEMBERLIST}" role="menuitem">
+ <i class="icon fa-group fa-fw" aria-hidden="true"></i><span>{L_MEMBERLIST}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
+ <!-- IF U_TEAM -->
+ <li>
+ <a href="{U_TEAM}" role="menuitem">
+ <i class="icon fa-shield fa-fw" aria-hidden="true"></i><span>{L_THE_TEAM}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
<!-- ENDIF -->
<li class="separator"></li>
@@ -40,67 +78,116 @@
</li>
<!-- EVENT overall_header_navigation_prepend -->
- <li class="small-icon icon-faq" <!-- IF not S_USER_LOGGED_IN -->data-skip-responsive="true"<!-- ELSE -->data-last-responsive="true"<!-- ENDIF -->><a href="{U_FAQ}" rel="help" title="{L_FAQ_EXPLAIN}" role="menuitem">{L_FAQ}</a></li>
+ <li <!-- IF not S_USER_LOGGED_IN -->data-skip-responsive="true"<!-- ELSE -->data-last-responsive="true"<!-- ENDIF -->>
+ <a href="{U_FAQ}" rel="help" title="{L_FAQ_EXPLAIN}" role="menuitem">
+ <i class="icon fa-question-circle fa-fw" aria-hidden="true"></i><span>{L_FAQ}</span>
+ </a>
+ </li>
<!-- EVENT overall_header_navigation_append -->
- <!-- IF U_ACP --><li class="small-icon icon-acp" data-last-responsive="true"><a href="{U_ACP}" title="{L_ACP}" role="menuitem">{L_ACP_SHORT}</a></li><!-- ENDIF -->
- <!-- IF U_MCP --><li class="small-icon icon-mcp" data-last-responsive="true"><a href="{U_MCP}" title="{L_MCP}" role="menuitem">{L_MCP_SHORT}</a></li><!-- ENDIF -->
+ <!-- IF U_ACP -->
+ <li data-last-responsive="true">
+ <a href="{U_ACP}" title="{L_ACP}" role="menuitem">
+ <i class="icon fa-cogs fa-fw" aria-hidden="true"></i><span>{L_ACP_SHORT}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
+ <!-- IF U_MCP -->
+ <li data-last-responsive="true">
+ <a href="{U_MCP}" title="{L_MCP}" role="menuitem">
+ <i class="icon fa-gavel fa-fw" aria-hidden="true"></i><span>{L_MCP_SHORT}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
<!-- IF S_REGISTERED_USER -->
<!-- EVENT navbar_header_user_profile_prepend -->
<li id="username_logged_in" class="rightside <!-- IF CURRENT_USER_AVATAR --> no-bulletin<!-- ENDIF -->" data-skip-responsive="true">
<!-- EVENT navbar_header_username_prepend -->
<div class="header-profile dropdown-container">
- <a href="{U_PROFILE}" class="header-avatar dropdown-trigger"><!-- IF CURRENT_USER_AVATAR -->{CURRENT_USER_AVATAR} <!-- ENDIF -->{CURRENT_USERNAME_SIMPLE}</a>
- <div class="dropdown hidden">
+ <a href="{U_PROFILE}" class="header-avatar dropdown-trigger"><!-- IF CURRENT_USER_AVATAR -->{CURRENT_USER_AVATAR} <!-- ENDIF --> {CURRENT_USERNAME_SIMPLE}</a>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents" role="menu">
- <!-- IF U_RESTORE_PERMISSIONS --><li class="small-icon icon-restore-permissions"><a href="{U_RESTORE_PERMISSIONS}">{L_RESTORE_PERMISSIONS}</a></li><!-- ENDIF -->
+ <!-- IF U_RESTORE_PERMISSIONS -->
+ <li>
+ <a href="{U_RESTORE_PERMISSIONS}">
+ <i class="icon fa-refresh fa-fw" aria-hidden="true"></i><span>{L_RESTORE_PERMISSIONS}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
- <!-- EVENT navbar_header_profile_list_before -->
+ <!-- EVENT navbar_header_profile_list_before -->
- <li class="small-icon icon-ucp"><a href="{U_PROFILE}" title="{L_PROFILE}" role="menuitem">{L_PROFILE}</a></li>
- <li class="small-icon icon-profile"><a href="{U_USER_PROFILE}" title="{L_READ_PROFILE}" role="menuitem">{L_READ_PROFILE}</a></li>
+ <li>
+ <a href="{U_PROFILE}" title="{L_PROFILE}" role="menuitem">
+ <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>
<!-- EVENT navbar_header_profile_list_after -->
<li class="separator"></li>
- <li class="small-icon icon-logout"><a href="{U_LOGIN_LOGOUT}" title="{L_LOGIN_LOGOUT}" accesskey="x" role="menuitem">{L_LOGIN_LOGOUT}</a></li>
+ <li>
+ <a href="{U_LOGIN_LOGOUT}" title="{L_LOGIN_LOGOUT}" accesskey="x" role="menuitem">
+ <i class="icon fa-power-off fa-fw" aria-hidden="true"></i><span>{L_LOGIN_LOGOUT}</span>
+ </a>
+ </li>
</ul>
</div>
</div>
<!-- EVENT navbar_header_username_append -->
</li>
<!-- IF S_DISPLAY_PM -->
- <li class="small-icon icon-pm rightside" data-skip-responsive="true">
- <a href="{U_PRIVATEMSGS}" role="menuitem"><span>{L_PRIVATE_MESSAGES} </span><!-- IF PRIVATE_MESSAGE_COUNT --><strong class="badge">{PRIVATE_MESSAGE_COUNT}</strong><!-- ENDIF --></a>
+ <li class="rightside" data-skip-responsive="true">
+ <a href="{U_PRIVATEMSGS}" role="menuitem">
+ <i class="icon fa-inbox fa-fw" aria-hidden="true"></i><span><span>{L_PRIVATE_MESSAGES} <!-- IF PRIVATE_MESSAGE_COUNT --><strong class="badge">{PRIVATE_MESSAGE_COUNT}</strong><!-- ENDIF --></span>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF S_NOTIFICATIONS_DISPLAY -->
- <li class="small-icon icon-notification dropdown-container dropdown-{S_CONTENT_FLOW_END} rightside" data-skip-responsive="true">
- <a href="{U_VIEW_ALL_NOTIFICATIONS}" id="notification_list_button" class="dropdown-trigger"><span>{L_NOTIFICATIONS} </span><!-- IF NOTIFICATIONS_COUNT --><strong class="badge">{NOTIFICATIONS_COUNT}</strong><!-- ENDIF --></a>
+ <li class="dropdown-container dropdown-{S_CONTENT_FLOW_END} rightside" data-skip-responsive="true">
+ <a href="{U_VIEW_ALL_NOTIFICATIONS}" id="notification_list_button" class="dropdown-trigger">
+ <i class="icon fa-bell fa-fw" aria-hidden="true"></i><span><span>{L_NOTIFICATIONS} <!-- IF NOTIFICATIONS_COUNT --><strong class="badge">{NOTIFICATIONS_COUNT}</strong><!-- ENDIF --></span>
+ </a>
<!-- INCLUDE notification_dropdown.html -->
</li>
<!-- ENDIF -->
<!-- EVENT navbar_header_user_profile_append -->
<!-- ELSE -->
- <li class="small-icon icon-logout rightside" data-skip-responsive="true"><a href="{U_LOGIN_LOGOUT}" title="{L_LOGIN_LOGOUT}" accesskey="x" role="menuitem">{L_LOGIN_LOGOUT}</a></li>
+ <li class="rightside" data-skip-responsive="true">
+ <a href="{U_LOGIN_LOGOUT}" title="{L_LOGIN_LOGOUT}" accesskey="x" role="menuitem">
+ <i class="icon fa-power-off fa-fw" aria-hidden="true"></i><span>{L_LOGIN_LOGOUT}</span>
+ </a>
+ </li>
<!-- IF S_REGISTER_ENABLED and not (S_SHOW_COPPA or S_REGISTRATION) -->
- <li class="small-icon icon-register rightside" data-skip-responsive="true"><a href="{U_REGISTER}" role="menuitem">{L_REGISTER}</a></li>
+ <li class="rightside" data-skip-responsive="true">
+ <a href="{U_REGISTER}" role="menuitem">
+ <i class="icon fa-pencil-square-o fa-fw" aria-hidden="true"></i><span>{L_REGISTER}</span>
+ </a>
+ </li>
<!-- ENDIF -->
<!-- EVENT navbar_header_logged_out_content -->
<!-- ENDIF -->
</ul>
- <ul id="nav-breadcrumbs" class="linklist navlinks" role="menubar">
+ <ul id="nav-breadcrumbs" class="nav-breadcrumbs linklist navlinks" role="menubar">
<!-- DEFINE $MICRODATA = ' itemtype="http://data-vocabulary.org/Breadcrumb" itemscope=""' -->
<!-- EVENT overall_header_breadcrumbs_before -->
- <li class="small-icon icon-home breadcrumbs">
- <!-- IF U_SITE_HOME --><span class="crumb"{$MICRODATA}><a href="{U_SITE_HOME}" data-navbar-reference="home" itemprop="url"><span itemprop="title">{L_SITE_HOME}</span></a></span><!-- ENDIF -->
+ <li class="breadcrumbs">
+ <!-- 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>
+ <!-- ENDIF -->
<!-- EVENT overall_header_breadcrumb_prepend -->
- <span class="crumb"{$MICRODATA}><a href="{U_INDEX}" accesskey="h" data-navbar-reference="index" itemprop="url"><span itemprop="title">{L_INDEX}</span></a></span>
+ <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>
+
<!-- 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}" itemprop="url"><span itemprop="title">{navlinks.FORUM_NAME}</span></a></span>
<!-- EVENT overall_header_navlink_append -->
<!-- END navlinks -->
<!-- EVENT overall_header_breadcrumb_append -->
@@ -108,7 +195,11 @@
<!-- EVENT overall_header_breadcrumbs_after -->
<!-- IF S_DISPLAY_SEARCH and not S_IN_SEARCH -->
- <li class="rightside responsive-search" style="display: none;"><a href="{U_SEARCH}" title="{L_SEARCH_ADV_EXPLAIN}" role="menuitem">{L_SEARCH}</a></li>
+ <li class="rightside responsive-search">
+ <a href="{U_SEARCH}" title="{L_SEARCH_ADV_EXPLAIN}" role="menuitem">
+ <i class="icon fa-search fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH}</span>
+ </a>
+ </li>
<!-- ENDIF -->
</ul>
diff --git a/phpBB/styles/prosilver/template/notification_dropdown.html b/phpBB/styles/prosilver/template/notification_dropdown.html
index 13d90a9d38..e444d8fb90 100644
--- a/phpBB/styles/prosilver/template/notification_dropdown.html
+++ b/phpBB/styles/prosilver/template/notification_dropdown.html
@@ -32,7 +32,9 @@
</div>
<!-- IF notifications.URL --></a><!-- ENDIF -->
<!-- IF notifications.UNREAD -->
- <a href="{notifications.U_MARK_READ}" class="mark_read icon-mark" data-ajax="notification.mark_read" title="{L_MARK_READ}"></a>
+ <a href="{notifications.U_MARK_READ}" class="mark_read icon-mark" data-ajax="notification.mark_read" title="{L_MARK_READ}">
+ <i class="icon fa-check-circle icon-xl fa-fw" aria-hidden="true"></i><span class="sr-only">{L_MARK_READ}</span>
+ </a>
<!-- ENDIF -->
</li>
<!-- END notifications -->
diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html
index ff54f3a0aa..39468201e5 100644
--- a/phpBB/styles/prosilver/template/overall_footer.html
+++ b/phpBB/styles/prosilver/template/overall_footer.html
@@ -3,7 +3,7 @@
<!-- EVENT overall_footer_page_body_after -->
-<div id="page-footer" role="contentinfo">
+<div id="page-footer" class="page-footer" role="contentinfo">
<!-- INCLUDE navbar_footer.html -->
<div class="copyright">
@@ -15,16 +15,20 @@
<!-- IF U_ACP --><br /><strong><a href="{U_ACP}">{L_ACP}</a></strong><!-- ENDIF -->
</div>
- <div id="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}">
- <div id="darken">&nbsp;</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}">
+ <div id="darken" class="darken">&nbsp;</div>
</div>
<div id="phpbb_alert" class="phpbb_alert" data-l-err="{L_ERROR}" data-l-timeout-processing-req="{L_TIMEOUT_PROCESSING_REQ}">
- <a href="#" class="alert_close"></a>
+ <a href="#" class="alert_close">
+ <i class="icon fa-times-circle fa-fw" aria-hidden="true"></i>
+ </a>
<h3 class="alert_title">&nbsp;</h3><p class="alert_text"></p>
</div>
<div id="phpbb_confirm" class="phpbb_alert">
- <a href="#" class="alert_close"></a>
+ <a href="#" class="alert_close">
+ <i class="icon fa-times-circle fa-fw" aria-hidden="true"></i>
+ </a>
<div class="alert_text"></div>
</div>
</div>
@@ -41,6 +45,19 @@
<script type="text/javascript" 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">
+ (function($){
+ var $fa_cdn = $('head').find('link[rel="stylesheet"]').first(),
+ $span = $('<span class="fa" style="display:none"></span>').appendTo('body');
+ if ($span.css('fontFamily') !== 'FontAwesome' ) {
+ $fa_cdn.after('<link href="{T_ASSETS_PATH}/css/font-awesome.min.css" rel="stylesheet">');
+ $fa_cdn.remove();
+ }
+ $span.remove();
+ })(jQuery);
+ </script>
+<!-- ENDIF -->
<!-- EVENT overall_footer_after -->
diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html
index e583c6e890..4a31a0adde 100644
--- a/phpBB/styles/prosilver/template/overall_header.html
+++ b/phpBB/styles/prosilver/template/overall_header.html
@@ -8,13 +8,13 @@
<title><!-- IF UNREAD_NOTIFICATIONS_COUNT -->({UNREAD_NOTIFICATIONS_COUNT}) <!-- ENDIF --><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --></title>
<!-- IF S_ENABLE_FEEDS -->
- <!-- IF S_ENABLE_FEEDS_OVERALL --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {SITENAME}" href="{U_FEED}"><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_NEWS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_NEWS}" href="{U_FEED}?mode=news"><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_FORUMS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_ALL_FORUMS}" href="{U_FEED}?mode=forums"><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_TOPICS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_TOPICS_NEW}" href="{U_FEED}?mode=topics"><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_TOPICS_ACTIVE --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_TOPICS_ACTIVE}" href="{U_FEED}?mode=topics_active"><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_FORUM and S_FORUM_ID --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FORUM} - {FORUM_NAME}" href="{U_FEED}?f={S_FORUM_ID}"><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_TOPIC and S_TOPIC_ID --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_TOPIC} - {TOPIC_TITLE}" href="{U_FEED}?f={S_FORUM_ID}&amp;t={S_TOPIC_ID}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_OVERALL --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {SITENAME}" href="{{ path('phpbb_feed_index') }}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_NEWS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_NEWS}" href="{{ path('phpbb_feed_news') }}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_FORUMS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_ALL_FORUMS}" href="{{ path('phpbb_feed_forums') }}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_TOPICS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_TOPICS_NEW}" href="{{ path('phpbb_feed_topics') }}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_TOPICS_ACTIVE --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_TOPICS_ACTIVE}" href="{{ path('phpbb_feed_topics_active') }}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_FORUM and S_FORUM_ID --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FORUM} - {FORUM_NAME}" href="{{ path('phpbb_feed_forum', { forum_id : S_FORUM_ID } ) }}"><!-- ENDIF -->
+ <!-- IF S_ENABLE_FEEDS_TOPIC and S_TOPIC_ID --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_TOPIC} - {TOPIC_TITLE}" href="{{ path('phpbb_feed_topic', { topic_id : S_TOPIC_ID } ) }}"><!-- ENDIF -->
<!-- EVENT overall_header_feeds -->
<!-- ENDIF -->
@@ -45,9 +45,9 @@
})(document);
</script>
<!-- ENDIF -->
+<link href="{T_FONT_AWESOME_LINK}" rel="stylesheet">
<link href="{T_STYLESHEET_LINK}" rel="stylesheet">
<link href="{T_STYLESHEET_LANG_LINK}" rel="stylesheet">
-<link href="{T_THEME_PATH}/responsive.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet" media="all and (max-width: 700px)">
<!-- IF S_CONTENT_DIRECTION eq 'rtl' -->
<link href="{T_THEME_PATH}/bidi.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet">
@@ -72,15 +72,15 @@
<!-- EVENT overall_header_body_before -->
-<div id="wrap">
- <a id="top" class="anchor" accesskey="t"></a>
+<div id="wrap" class="wrap">
+ <a id="top" class="top-anchor" accesskey="t"></a>
<div id="page-header">
<div class="headerbar" role="banner">
<!-- EVENT overall_header_headerbar_before -->
<div class="inner">
- <div id="site-description">
- <a id="logo" class="logo" href="<!-- IF U_SITE_HOME -->{U_SITE_HOME}<!-- ELSE -->{U_INDEX}<!-- ENDIF -->" title="<!-- IF U_SITE_HOME -->{L_SITE_HOME}<!-- ELSE -->{L_INDEX}<!-- ENDIF -->">{SITE_LOGO_IMG}</a>
+ <div id="site-description" class="site-description">
+ <a id="logo" class="logo" href="<!-- IF U_SITE_HOME -->{U_SITE_HOME}<!-- ELSE -->{U_INDEX}<!-- ENDIF -->" title="<!-- IF U_SITE_HOME -->{L_SITE_HOME}<!-- ELSE -->{L_INDEX}<!-- ENDIF -->"><span class="site_logo"></span></a>
<h1>{SITENAME}</h1>
<p>{SITE_DESCRIPTION}</p>
<p class="skiplink"><a href="#start_here">{L_SKIP}</a></p>
@@ -92,8 +92,12 @@
<form action="{U_SEARCH}" method="get" id="search">
<fieldset>
<input name="keywords" id="keywords" type="search" maxlength="128" title="{L_SEARCH_KEYWORDS}" class="inputbox search tiny" size="20" value="{SEARCH_WORDS}" placeholder="{L_SEARCH_MINI}" />
- <button class="button icon-button search-icon" type="submit" title="{L_SEARCH}">{L_SEARCH}</button>
- <a href="{U_SEARCH}" class="button icon-button search-adv-icon" title="{L_SEARCH_ADV}">{L_SEARCH_ADV}</a>
+ <button class="button button-search" type="submit" title="{L_SEARCH}">
+ <i class="icon fa-search fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH}</span>
+ </button>
+ <a href="{U_SEARCH}" class="button button-search-end" title="{L_SEARCH_ADV}">
+ <i class="icon fa-cog fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH_ADV}</span>
+ </a>
{S_SEARCH_HIDDEN_FIELDS}
</fieldset>
</form>
@@ -111,7 +115,7 @@
<!-- EVENT overall_header_page_body_before -->
<a id="start_here" class="anchor"></a>
- <div id="page-body" role="main">
+ <div id="page-body" class="page-body" role="main">
<!-- IF S_BOARD_DISABLED and S_USER_LOGGED_IN and (U_MCP or U_ACP) -->
<div id="information" class="rules">
<div class="inner">
diff --git a/phpBB/styles/prosilver/template/pagination.html b/phpBB/styles/prosilver/template/pagination.html
index 88c67459c2..78b0df84e0 100644
--- a/phpBB/styles/prosilver/template/pagination.html
+++ b/phpBB/styles/prosilver/template/pagination.html
@@ -1,8 +1,8 @@
<ul>
<!-- IF BASE_URL and TOTAL_PAGES > 6 -->
<li class="dropdown-container dropdown-button-control dropdown-page-jump page-jump">
- <a href="#" class="dropdown-trigger" title="{L_JUMP_TO_PAGE_CLICK}" role="button">{PAGE_NUMBER}</a>
- <div class="dropdown hidden">
+ <a class="button button-icon-only dropdown-trigger" href="#" title="{L_JUMP_TO_PAGE_CLICK}" role="button"><i class="icon fa-level-down fa-rotate-270" aria-hidden="true"></i><span class="sr-only">{PAGE_NUMBER}</span></a>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents">
<li>{L_JUMP_TO_PAGE}{L_COLON}</li>
@@ -16,15 +16,15 @@
<!-- ENDIF -->
<!-- BEGIN pagination -->
<!-- IF pagination.S_IS_PREV -->
- <li class="previous"><a href="{pagination.PAGE_URL}" rel="prev" role="button">{L_PREVIOUS}</a></li>
+ <li class="arrow previous"><a class="button button-icon-only" href="{pagination.PAGE_URL}" rel="prev" role="button"><i class="icon fa-chevron-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_PREVIOUS}</span></a></li>
<!-- ELSEIF pagination.S_IS_CURRENT -->
<li class="active"><span>{pagination.PAGE_NUMBER}</span></li>
<!-- ELSEIF pagination.S_IS_ELLIPSIS -->
<li class="ellipsis" role="separator"><span>{L_ELLIPSIS}</span></li>
<!-- ELSEIF pagination.S_IS_NEXT -->
- <li class="next"><a href="{pagination.PAGE_URL}" rel="next" role="button">{L_NEXT}</a></li>
+ <li class="arrow next"><a class="button button-icon-only" href="{pagination.PAGE_URL}" rel="next" role="button"><i class="icon fa-chevron-right fa-fw" aria-hidden="true"></i><span class="sr-only">{L_NEXT}</span></a></li>
<!-- ELSE -->
- <li><a href="{pagination.PAGE_URL}" role="button">{pagination.PAGE_NUMBER}</a></li>
+ <li><a class="button" href="{pagination.PAGE_URL}" role="button">{pagination.PAGE_NUMBER}</a></li>
<!-- ENDIF -->
<!-- END pagination -->
</ul>
diff --git a/phpBB/styles/prosilver/template/posting_attach_body.html b/phpBB/styles/prosilver/template/posting_attach_body.html
index 81b2c2bf41..da527e9a75 100644
--- a/phpBB/styles/prosilver/template/posting_attach_body.html
+++ b/phpBB/styles/prosilver/template/posting_attach_body.html
@@ -2,12 +2,12 @@
<div class="inner">
<p>{L_ADD_ATTACHMENT_EXPLAIN} <span class="hidden" id="drag-n-drop-message">{L_PLUPLOAD_DRAG_TEXTAREA}</span></p>
-
+
<fieldset class="fields2" id="attach-panel-basic">
<dl>
<dt><label for="fileupload">{L_FILENAME}{L_COLON}</label></dt>
<dd>
- <input type="file" name="fileupload" id="fileupload" maxlength="{FILESIZE}" value="" class="inputbox autowidth" />
+ <input type="file" name="fileupload" id="fileupload" maxlength="{FILESIZE}" value="" class="inputbox autowidth" />
<input type="submit" name="add_file" value="{L_ADD_FILE}" class="button2" onclick="upload = true;" />
</dd>
</dl>
@@ -17,11 +17,11 @@
</dl>
</fieldset>
- <div id="attach-panel-multi">
+ <div id="attach-panel-multi" class="attach-panel-multi">
<input type="button" class="button2" value="{L_PLUPLOAD_ADD_FILES}" id="add_files" />
</div>
- <div class="panel<!-- IF not .attach_row --> hidden<!-- ENDIF -->" id="file-list-container">
+ <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">
<thead>
@@ -32,7 +32,7 @@
<th class="attach-status">{L_PLUPLOAD_STATUS}</th>
</tr>
</thead>
- <tbody class="responsive-skip-empty" id="file-list">
+ <tbody class="responsive-skip-empty file-list" id="file-list">
<tr class="attach-row" id="attach-row-tpl">
<td class="attach-name">
<span class="file-name ellipsis-text"></span>
diff --git a/phpBB/styles/prosilver/template/posting_buttons.html b/phpBB/styles/prosilver/template/posting_buttons.html
index 1555b12369..14185ed66b 100644
--- a/phpBB/styles/prosilver/template/posting_buttons.html
+++ b/phpBB/styles/prosilver/template/posting_buttons.html
@@ -55,31 +55,56 @@
<div id="colour_palette" style="display: none;">
<dl style="clear: left;">
<dt><label>{L_FONT_COLOR}{L_COLON}</label></dt>
- <dd id="color_palette_placeholder" data-orientation="h" data-height="12" data-width="15" data-bbcode="true"></dd>
+ <dd id="color_palette_placeholder" class="color_palette_placeholder" data-orientation="h" data-height="12" data-width="15" data-bbcode="true"></dd>
</dl>
</div>
<!-- EVENT posting_editor_buttons_before -->
-<div id="format-buttons">
- <input type="button" class="button2 bbcode-b" accesskey="b" name="addbbcode0" value=" B " style="font-weight:bold; width: 30px" onclick="bbstyle(0)" title="{L_BBCODE_B_HELP}" />
- <input type="button" class="button2 bbcode-i" accesskey="i" name="addbbcode2" value=" i " style="font-style:italic; width: 30px" onclick="bbstyle(2)" title="{L_BBCODE_I_HELP}" />
- <input type="button" class="button2 bbcode-u" accesskey="u" name="addbbcode4" value=" u " style="text-decoration: underline; width: 30px" onclick="bbstyle(4)" title="{L_BBCODE_U_HELP}" />
+<div id="format-buttons" class="format-buttons">
+ <button type="button" class="button button-icon-only bbcode-b" accesskey="b" name="addbbcode0" value=" B " onclick="bbstyle(0)" title="{L_BBCODE_B_HELP}">
+ <i class="icon fa-bold fa-fw" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="button button-icon-only bbcode-i" accesskey="i" name="addbbcode2" value=" i " onclick="bbstyle(2)" title="{L_BBCODE_I_HELP}">
+ <i class="icon fa-italic fa-fw" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="button button-icon-only bbcode-u" accesskey="u" name="addbbcode4" value=" u " onclick="bbstyle(4)" title="{L_BBCODE_U_HELP}">
+ <i class="icon fa-underline fa-fw" aria-hidden="true"></i>
+ </button>
<!-- IF S_BBCODE_QUOTE -->
- <input type="button" class="button2 bbcode-quote" accesskey="q" name="addbbcode6" value="Quote" style="width: 50px" onclick="bbstyle(6)" title="{L_BBCODE_Q_HELP}" />
+ <button type="button" class="button button-icon-only bbcode-quote" accesskey="q" name="addbbcode6" value="Quote" onclick="bbstyle(6)" title="{L_BBCODE_Q_HELP}">
+ <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i>
+ </button>
<!-- ENDIF -->
- <input type="button" class="button2 bbcode-code" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" title="{L_BBCODE_C_HELP}" />
- <input type="button" class="button2 bbcode-list" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" title="{L_BBCODE_L_HELP}" />
- <input type="button" class="button2 bbcode-list-" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" title="{L_BBCODE_O_HELP}" />
- <input type="button" class="button2 bbcode-asterisk" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}" />
+ <button type="button" class="button button-icon-only bbcode-code" accesskey="c" name="addbbcode8" value="Code" onclick="bbstyle(8)" title="{L_BBCODE_C_HELP}">
+ <i class="icon fa-code fa-fw" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="button button-icon-only bbcode-list" accesskey="l" name="addbbcode10" value="List" onclick="bbstyle(10)" title="{L_BBCODE_L_HELP}">
+ <i class="icon fa-list fa-fw" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="button button-icon-only bbcode-list-" accesskey="o" name="addbbcode12" value="List=" onclick="bbstyle(12)" title="{L_BBCODE_O_HELP}">
+ <i class="icon fa-list-ol fa-fw" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="button button-icon-only bbcode-asterisk" accesskey="y" name="addlistitem" value="[*]" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}">
+ <i class="icon fa-asterisk fa-fw" aria-hidden="true"></i>
+ </button>
<!-- IF S_BBCODE_IMG -->
- <input type="button" class="button2 bbcode-img" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" title="{L_BBCODE_P_HELP}" />
+ <button type="button" class="button button-icon-only bbcode-img" accesskey="p" name="addbbcode14" value="Img" onclick="bbstyle(14)" title="{L_BBCODE_P_HELP}">
+ <i class="icon fa-image fa-fw" aria-hidden="true"></i>
+ </button>
<!-- ENDIF -->
<!-- IF S_LINKS_ALLOWED -->
- <input type="button" class="button2 bbcode-url" accesskey="w" name="addbbcode16" value="URL" style="text-decoration: underline; width: 40px" onclick="bbstyle(16)" title="{L_BBCODE_W_HELP}" />
+ <button type="button" class="button button-icon-only bbcode-url" accesskey="w" name="addbbcode16" value="URL" onclick="bbstyle(16)" title="{L_BBCODE_W_HELP}">
+ <i class="icon fa-link fa-fw" aria-hidden="true"></i>
+ </button>
<!-- ENDIF -->
<!-- IF S_BBCODE_FLASH -->
- <input type="button" class="button2 bbcode-flash" accesskey="d" name="addbbcode18" value="Flash" onclick="bbstyle(18)" title="{L_BBCODE_D_HELP}" />
+ <button type="button" class="button button-icon-only bbcode-flash" accesskey="d" name="addbbcode18" value="Flash" onclick="bbstyle(18)" title="{L_BBCODE_D_HELP}">
+ <i class="icon fa-flash fa-fw" aria-hidden="true"></i>
+ </button>
<!-- ENDIF -->
+ <button type="button" class="button button-icon-only bbcode-color" name="bbpalette" id="bbpalette" value="{L_FONT_COLOR}" onclick="change_palette();" title="{L_BBCODE_S_HELP}">
+ <i class="icon fa-tint fa-fw" aria-hidden="true"></i>
+ </button>
<select name="addbbcode20" class="bbcode-size" onchange="bbfontstyle('[size=' + this.form.addbbcode20.options[this.form.addbbcode20.selectedIndex].value + ']', '[/size]');this.form.addbbcode20.selectedIndex = 2;" title="{L_BBCODE_F_HELP}">
<option value="50">{L_FONT_TINY}</option>
<option value="85">{L_FONT_SMALL}</option>
@@ -91,12 +116,13 @@
<!-- ENDIF -->
<!-- ENDIF -->
</select>
- <input type="button" class="button2 bbcode-color" name="bbpalette" id="bbpalette" value="{L_FONT_COLOR}" onclick="change_palette();" title="{L_BBCODE_S_HELP}" />
<!-- EVENT posting_editor_buttons_custom_tags_before -->
<!-- BEGIN custom_tags -->
- <input type="button" class="button2 bbcode-{custom_tags.BBCODE_TAG_CLEAN}" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})" title="{custom_tags.BBCODE_HELPLINE}" />
+ <button type="button" class="button button-secondary bbcode-{custom_tags.BBCODE_TAG_CLEAN}" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})" title="{custom_tags.BBCODE_HELPLINE}">
+ {custom_tags.BBCODE_TAG}
+ </button>
<!-- END custom_tags -->
</div>
<!-- EVENT posting_editor_buttons_after -->
diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html
index 5258ea09a2..d963c98e08 100644
--- a/phpBB/styles/prosilver/template/posting_editor.html
+++ b/phpBB/styles/prosilver/template/posting_editor.html
@@ -6,7 +6,7 @@
<dt><label for="icon">{L_ICON}{L_COLON}</label></dt>
<dd>
<label for="icon"><input type="radio" name="icon" id="icon" value="0" checked="checked" tabindex="1" /> <!-- IF S_SHOW_TOPIC_ICONS -->{L_NO_TOPIC_ICON}<!-- ELSE -->{L_NO_PM_ICON}<!-- ENDIF --></label>
- <!-- BEGIN topic_icon --><label for="icon-{topic_icon.ICON_ID}"><input type="radio" name="icon" id="icon-{topic_icon.ICON_ID}" value="{topic_icon.ICON_ID}" {topic_icon.S_ICON_CHECKED} tabindex="1" /><img src="{topic_icon.ICON_IMG}" width="{topic_icon.ICON_WIDTH}" height="{topic_icon.ICON_HEIGHT}" alt="{topic_icon.ICON_NAME}" title="" /></label> <!-- END topic_icon -->
+ <!-- BEGIN topic_icon --><label for="icon-{topic_icon.ICON_ID}"><input type="radio" name="icon" id="icon-{topic_icon.ICON_ID}" value="{topic_icon.ICON_ID}" {topic_icon.S_ICON_CHECKED} tabindex="1" /><img src="{topic_icon.ICON_IMG}" width="{topic_icon.ICON_WIDTH}" height="{topic_icon.ICON_HEIGHT}" alt="{topic_icon.ICON_ALT}" title="{topic_icon.ICON_ALT}" /></label> <!-- END topic_icon -->
</dd>
</dl>
<!-- ENDIF -->
@@ -39,8 +39,8 @@
<!-- INCLUDE posting_buttons.html -->
- <div id="smiley-box">
- <!-- EVENT posting_editor_smilies_before -->
+ <div id="smiley-box" class="smiley-box">
+ <!-- EVENT posting_editor_smilies_before -->
<!-- IF S_SMILIES_ALLOWED and .smiley -->
<strong>{L_SMILIES}</strong><br />
<!-- BEGIN smiley -->
@@ -73,7 +73,7 @@
<!-- EVENT posting_editor_message_before -->
- <div id="message-box">
+ <div id="message-box" class="message-box">
<textarea <!-- IF S_UCP_ACTION and not S_PRIVMSGS and not S_EDIT_DRAFT -->name="signature" id="signature" style="height: 9em;"<!-- ELSE -->name="message" id="message"<!-- ENDIF --> rows="15" cols="76" tabindex="4" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();" class="inputbox">{MESSAGE}{DRAFT_MESSAGE}{SIGNATURE}</textarea>
</div>
@@ -106,13 +106,13 @@
<!-- ENDIF -->
<!-- IF not S_PRIVMSGS and not S_SHOW_DRAFTS and not $SIG_EDIT eq 1 -->
- <div id="tabs" class="sub-panels" data-show-panel="<!-- IF SHOW_PANEL -->{SHOW_PANEL}<!-- ELSE -->options-panel<!-- ENDIF -->" role="tablist">
+ <div id="tabs" class="tabs sub-panels" data-show-panel="<!-- IF SHOW_PANEL -->{SHOW_PANEL}<!-- ELSE -->options-panel<!-- ENDIF -->" role="tablist">
<ul>
<li id="options-panel-tab" class="tab activetab"><a href="#tabs" data-subpanel="options-panel" role="tab" aria-controls="options-panel"><span>{L_OPTIONS}</span></a></li>
<!-- IF S_SHOW_ATTACH_BOX -->
<li id="attach-panel-tab" class="tab">
<a href="#tabs" data-subpanel="attach-panel" role="tab" aria-controls="attach-panel">
- {L_ATTACHMENTS} <strong id="file-total-progress"><strong id="file-total-progress-bar"></strong></strong>
+ {L_ATTACHMENTS} <strong id="file-total-progress" class="file-total-progress"><strong id="file-total-progress-bar" class="file-total-progress-bar"></strong></strong>
</a>
</li>
<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/posting_layout.html b/phpBB/styles/prosilver/template/posting_layout.html
index 22da32076c..bca9195f0e 100644
--- a/phpBB/styles/prosilver/template/posting_layout.html
+++ b/phpBB/styles/prosilver/template/posting_layout.html
@@ -9,14 +9,14 @@
<!-- IF S_FORUM_RULES -->
<div class="rules<!-- IF U_FORUM_RULES --> rules-link<!-- ENDIF -->">
<div class="inner">
-
+
<!-- IF U_FORUM_RULES -->
<a href="{U_FORUM_RULES}">{L_FORUM_RULES}</a>
<!-- ELSE -->
<strong>{L_FORUM_RULES}</strong><br />
{FORUM_RULES}
<!-- ENDIF -->
-
+
</div>
</div>
<!-- ENDIF -->
@@ -26,10 +26,10 @@
<!-- IF S_DRAFT_LOADED -->
<div class="panel">
<div class="inner">
-
+
<h3>{L_INFORMATION}</h3>
<p>{L_DRAFT_LOADED}</p>
-
+
</div>
</div>
<!-- ENDIF -->
@@ -48,7 +48,7 @@
<dt><label for="to_forum_id">{L_MOVE}{L_COLON}</label></dt>
<dd><select id="to_forum_id" name="to_forum_id">{S_FORUM_SELECT}</select></dd>
</dl>
-
+
<dl>
<dt>&nbsp;</dt>
<dd><input class="button1" type="submit" name="post" value="{L_CONFIRM}" /> <input class="button2" type="submit" name="cancel_unglobalise" value="{L_CANCEL}" /></dd>
@@ -63,7 +63,7 @@
<div class="panel" id="postingbox">
<div class="inner">
-
+
<h3>{L_POST_A}</h3>
<!-- DEFINE $EXTRA_POSTING_OPTIONS = 1 -->
diff --git a/phpBB/styles/prosilver/template/posting_pm_layout.html b/phpBB/styles/prosilver/template/posting_pm_layout.html
index 7f4a0ea8d7..316fa791e4 100644
--- a/phpBB/styles/prosilver/template/posting_pm_layout.html
+++ b/phpBB/styles/prosilver/template/posting_pm_layout.html
@@ -3,10 +3,10 @@
<!-- IF S_DRAFT_LOADED -->
<div class="panel">
<div class="inner">
-
+
<h3>{L_INFORMATION}</h3>
<p>{L_DRAFT_LOADED_PM}</p>
-
+
</div>
</div>
<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/posting_review.html b/phpBB/styles/prosilver/template/posting_review.html
index 25b719420b..1304046b23 100644
--- a/phpBB/styles/prosilver/template/posting_review.html
+++ b/phpBB/styles/prosilver/template/posting_review.html
@@ -14,7 +14,16 @@
<div class="postbody" id="ppr{post_review_row.POST_ID}">
<h3><a href="#ppr{post_review_row.POST_ID}">{post_review_row.POST_SUBJECT}</a></h3>
- <p class="author"><!-- IF S_IS_BOT -->{post_review_row.MINI_POST_IMG}<!-- ELSE --><a href="{post_review_row.U_MINI_POST}">{post_review_row.MINI_POST_IMG}</a><!-- ENDIF --> {L_POST_BY_AUTHOR}<strong> {post_review_row.POST_AUTHOR_FULL}</strong> &raquo; {post_review_row.POST_DATE}</p>
+ <p class="author">
+ <!-- IF S_IS_BOT -->
+ <span><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></span>
+ <!-- ELSE -->
+ <a href="{post_review_row.U_MINI_POST}" title="{post_review_row.MINI_POST}">
+ <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> &raquo; {post_review_row.POST_DATE}
+ </p>
<div class="content">{post_review_row.MESSAGE}</div>
<!-- IF post_review_row.S_HAS_ATTACHMENTS -->
diff --git a/phpBB/styles/prosilver/template/posting_smilies.html b/phpBB/styles/prosilver/template/posting_smilies.html
index 3bd51275ec..54e82a58bc 100644
--- a/phpBB/styles/prosilver/template/posting_smilies.html
+++ b/phpBB/styles/prosilver/template/posting_smilies.html
@@ -11,13 +11,13 @@
<h2>{L_SMILIES}</h2>
<div class="panel">
<div class="inner">
- <!-- BEGIN smiley -->
- <a href="#" onclick="initInsertions(); insert_text('{smiley.A_SMILEY_CODE}', true, true); return false;"><img src="{smiley.SMILEY_IMG}" width="{smiley.SMILEY_WIDTH}" height="{smiley.SMILEY_HEIGHT}" alt="{smiley.SMILEY_CODE}" title="{smiley.SMILEY_DESC}" /></a>
+ <!-- BEGIN smiley -->
+ <a href="#" onclick="initInsertions(); insert_text('{smiley.A_SMILEY_CODE}', true, true); return false;"><img src="{smiley.SMILEY_IMG}" width="{smiley.SMILEY_WIDTH}" height="{smiley.SMILEY_HEIGHT}" alt="{smiley.SMILEY_CODE}" title="{smiley.SMILEY_DESC}" /></a>
<!-- END smiley -->
-
+
</div>
</div>
-<!-- IF .pagination -->
+<!-- IF .pagination -->
<div class="pagination">
<!-- INCLUDE pagination.html -->
</div>
diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html
index 4d5ab16afe..857c686774 100644
--- a/phpBB/styles/prosilver/template/posting_topic_review.html
+++ b/phpBB/styles/prosilver/template/posting_topic_review.html
@@ -1,10 +1,10 @@
-<h3 id="review">
+<h3 id="review" class="review">
<span class="right-box"><a href="#review" onclick="viewableArea(getElementById('topicreview'), true); var rev_text = getElementById('review').getElementsByTagName('a').item(0).firstChild; if (rev_text.data == '{LA_EXPAND_VIEW}'){rev_text.data = '{LA_COLLAPSE_VIEW}'; } else if (rev_text.data == '{LA_COLLAPSE_VIEW}'){rev_text.data = '{LA_EXPAND_VIEW}'};">{L_EXPAND_VIEW}</a></span>
{L_TOPIC_REVIEW}{L_COLON} {TOPIC_TITLE}
</h3>
-<div id="topicreview">
+<div id="topicreview" class="topicreview">
<script type="text/javascript">
// <![CDATA[
bbcodeEnabled = {S_BBCODE_ALLOWED};
@@ -32,15 +32,15 @@
<ul class="post-buttons">
<!-- IF topic_review_row.U_MCP_DETAILS -->
<li>
- <a href="{topic_review_row.U_MCP_DETAILS}" title="{L_POST_DETAILS}" class="button icon-button info-icon">
- <span>{L_POST_DETAILS}</span>
+ <a href="{topic_review_row.U_MCP_DETAILS}" title="{L_POST_DETAILS}" class="button button-icon-only">
+ <i class="icon fa-info fa-fw" aria-hidden="true"></i><span class="sr-only">{L_POST_DETAILS}</span>
</a>
<li>
<!-- ENDIF -->
<!-- IF topic_review_row.POSTER_QUOTE and topic_review_row.DECODED_MESSAGE -->
<li>
- <a href="#postingbox" onclick="addquote({topic_review_row.POST_ID}, '{topic_review_row.POSTER_QUOTE}', '{LA_WROTE}');" title="{L_QUOTE} {topic_review_row.POST_AUTHOR}" class="button icon-button quote-icon">
- <span>{L_QUOTE} {topic_review_row.POST_AUTHOR}</span>
+ <a href="#postingbox" onclick="addquote({topic_review_row.POST_ID}, '{topic_review_row.POSTER_QUOTE}', '{LA_WROTE}', {post_id:{topic_review_row.POST_ID},time:{topic_review_row.POST_TIME},user_id:{topic_review_row.USER_ID}});" title="{L_QUOTE} {topic_review_row.POST_AUTHOR}" class="button button-icon-only">
+ <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_QUOTE} {topic_review_row.POST_AUTHOR}</span>
</a>
</li>
<!-- ENDIF -->
@@ -48,7 +48,16 @@
<!-- ENDIF -->
<!-- EVENT posting_topic_review_row_post_details_before -->
- <p class="author"><!-- IF S_IS_BOT -->{topic_review_row.MINI_POST_IMG}<!-- ELSE --><a href="{topic_review_row.U_MINI_POST}">{topic_review_row.MINI_POST_IMG}</a><!-- ENDIF --> {L_POST_BY_AUTHOR} <strong>{topic_review_row.POST_AUTHOR_FULL}</strong> &raquo; {topic_review_row.POST_DATE} </p>
+ <p class="author">
+ <!-- IF S_IS_BOT -->
+ <span><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></span>
+ <!-- ELSE -->
+ <a href="{topic_review_row.U_MINI_POST}" title="{topic_review_row.MINI_POST}">
+ <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> &raquo; {topic_review_row.POST_DATE}
+ </p>
<!-- EVENT posting_topic_review_row_post_details_after -->
<div class="content">{topic_review_row.MESSAGE}</div>
@@ -73,8 +82,8 @@
<hr />
-<!-- IF S_MCP_REPORT -->
- <p><a href="#report" class="top2">{L_BACK_TO_TOP}</a></p>
-<!-- ELSE -->
- <p><a href="#postingbox" class="top2">{L_BACK_TO_TOP}</a></p>
-<!-- ENDIF -->
+<p>
+ <a href="<!-- IF S_MCP_REPORT -->#report<!-- ELSE -->#postingbox<!-- ENDIF -->" class="top">
+ <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/quickreply_editor.html b/phpBB/styles/prosilver/template/quickreply_editor.html
index ca8ccc0a6b..9839494491 100644
--- a/phpBB/styles/prosilver/template/quickreply_editor.html
+++ b/phpBB/styles/prosilver/template/quickreply_editor.html
@@ -10,7 +10,7 @@
<dd><input type="text" name="subject" id="subject" size="45" maxlength="124" tabindex="2" value="{SUBJECT}" class="inputbox autowidth" /></dd>
</dl>
<!-- EVENT quickreply_editor_message_before -->
- <div id="message-box">
+ <div id="message-box" class="message-box">
<textarea style="height: 9em;" name="message" rows="7" cols="76" tabindex="3" class="inputbox"></textarea>
</div>
<!-- EVENT quickreply_editor_message_after -->
diff --git a/phpBB/styles/prosilver/template/report_body.html b/phpBB/styles/prosilver/template/report_body.html
index 2a5e6c9d0e..285e8ec8d7 100644
--- a/phpBB/styles/prosilver/template/report_body.html
+++ b/phpBB/styles/prosilver/template/report_body.html
@@ -8,7 +8,7 @@
<div class="content">
<p><!-- IF S_REPORT_POST -->{L_REPORT_POST_EXPLAIN}<!-- ELSE -->{L_REPORT_MESSAGE_EXPLAIN}<!-- ENDIF --></p>
-
+
<fieldset>
<!-- IF ERROR --><dl><dd class="error">{ERROR}</dd></dl><!-- ENDIF -->
<dl class="fields2">
@@ -19,7 +19,7 @@
<dl class="fields2">
<dt><label for="notify1">{L_REPORT_NOTIFY}{L_COLON}</label><br /><span>{L_REPORT_NOTIFY_EXPLAIN}</span></dt>
<dd>
- <label for="notify1"><input type="radio" name="notify" id="notify1" value="1" <!-- IF not S_NOTIFY -->checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="notify1"><input type="radio" name="notify" id="notify1" value="1" <!-- IF not S_NOTIFY -->checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="notify0"><input type="radio" name="notify" id="notify0" value="0" <!-- IF S_NOTIFY -->checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html
index b6c454bf05..f7114567e5 100644
--- a/phpBB/styles/prosilver/template/search_results.html
+++ b/phpBB/styles/prosilver/template/search_results.html
@@ -8,23 +8,35 @@
<!-- IF PHRASE_SEARCH_DISABLED --> <p><strong>{L_PHRASE_SEARCH_DISABLED}</strong></p><!-- ENDIF -->
<!-- IF SEARCH_TOPIC -->
- <p class="return-link"><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}">{L_RETURN_TO_TOPIC}</a></p>
+ <p class="return-link">
+ <a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_TO_TOPIC}</span>
+ </a>
+ </p>
<!-- ELSE -->
- <p class="advanced-search-link"><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}">{L_GO_TO_SEARCH_ADV}</a></p>
+ <p class="advanced-search-link">
+ <a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_GO_TO_SEARCH_ADV}</span>
+ </a>
+ </p>
<!-- ENDIF -->
<!-- EVENT search_results_header_after -->
<!-- IF .pagination or SEARCH_MATCHES or TOTAL_MATCHES or PAGE_NUMBER -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<!-- IF TOTAL_MATCHES > 0 -->
<div class="search-box" role="search">
<form method="post" action="{S_SEARCH_ACTION}">
<fieldset>
<input class="inputbox search tiny" type="search" name="add_keywords" id="add_keywords" value="" placeholder="{L_SEARCH_IN_RESULTS}" />
- <button class="button icon-button search-icon" type="submit" title="{L_SEARCH}">{L_SEARCH}</button>
- <a href="{U_SEARCH}" class="button icon-button search-adv-icon" title="{L_SEARCH_ADV}">{L_SEARCH_ADV}</a>
+ <button class="button button-search" type="submit" title="{L_SEARCH}">
+ <i class="icon fa-search fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH}</span>
+ </button>
+ <a href="{U_SEARCH}" class="button button-search-end" title="{L_SEARCH_ADV}">
+ <i class="icon fa-cog fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH_ADV}</span>
+ </a>
</fieldset>
</form>
</div>
@@ -52,7 +64,7 @@
<div class="inner">
<ul class="topiclist">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt><div class="list-inner">{L_TOPICS}</div></dt>
<dd class="posts">{L_REPLIES}</dd>
<dd class="views">{L_VIEWS}</dd>
@@ -65,43 +77,79 @@
<!-- BEGIN searchresults -->
<!-- EVENT search_results_topic_before -->
<li class="row<!-- IF searchresults.S_ROW_COUNT is even --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
- <dl class="icon {searchresults.TOPIC_IMG_STYLE}">
- <dt <!-- IF searchresults.TOPIC_ICON_IMG -->style="background-image: url({T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{searchresults.TOPIC_FOLDER_IMG_ALT}">
- <!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{searchresults.U_NEWEST_POST}" class="icon-link"></a><!-- ENDIF -->
+ <dl class="row-item {searchresults.TOPIC_IMG_STYLE}">
+ <dt<!-- IF searchresults.TOPIC_ICON_IMG and S_TOPIC_ICONS --> style="background-image: url({T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{searchresults.TOPIC_FOLDER_IMG_ALT}">
+ <!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{searchresults.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
-
<!-- EVENT topiclist_row_prepend -->
- <!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{searchresults.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF -->
- <a href="{searchresults.U_VIEW_TOPIC}" class="topictitle">{searchresults.TOPIC_TITLE}</a> {searchresults.ATTACH_ICON_IMG}
- <!-- IF searchresults.S_TOPIC_UNAPPROVED or searchresults.S_POSTS_UNAPPROVED --><a href="{searchresults.U_MCP_QUEUE}">{searchresults.UNAPPROVED_IMG}</a> <!-- ENDIF -->
- <!-- IF searchresults.S_TOPIC_DELETED --><a href="{searchresults.U_MCP_QUEUE}">{DELETED_IMG}</a> <!-- ENDIF -->
- <!-- IF searchresults.S_TOPIC_REPORTED --><a href="{searchresults.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- ENDIF --><br />
+ <!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT -->
+ <a class="unread" href="{searchresults.U_NEWEST_POST}">
+ <i class="icon fa-file fa-fw icon-red icon-md" aria-hidden="true"></i><span class="sr-only">{L_NEW_POST}</span>
+ </a>
+ <!-- ENDIF -->
+ <a href="{searchresults.U_VIEW_TOPIC}" class="topictitle">{searchresults.TOPIC_TITLE}</a>
+ <!-- IF searchresults.S_TOPIC_UNAPPROVED or searchresults.S_POSTS_UNAPPROVED -->
+ <a href="{searchresults.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>
+ <!-- ENDIF -->
+ <!-- IF searchresults.S_TOPIC_DELETED -->
+ <a href="{searchresults.U_MCP_QUEUE}" title="{L_TOPIC_DELETED}">
+ <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_DELETED}</span>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF searchresults.S_TOPIC_REPORTED -->
+ <a href="{searchresults.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}">
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span>
+ </a>
+ <!-- ENDIF -->
+ <br />
+
+ <!-- IF not S_IS_BOT -->
+ <div class="responsive-show" style="display: none;">
+ {L_LAST_POST} {L_POST_BY_AUTHOR} {searchresults.LAST_POST_AUTHOR_FULL} &laquo; <a href="{searchresults.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{searchresults.LAST_POST_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 -->
+ <!-- ENDIF -->
+
+ <div class="responsive-hide">
+ <!-- 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} &raquo; {searchresults.FIRST_POST_TIME} &raquo; {L_IN} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a>
+ </div>
+
<!-- IF .searchresults.pagination -->
<div class="pagination">
+ <span><i class="icon fa-clone fa-fw" aria-hidden="true"></i></span>
<ul>
<!-- BEGIN pagination -->
<!-- IF searchresults.pagination.S_IS_PREV -->
<!-- ELSEIF searchresults.pagination.S_IS_CURRENT --><li class="active"><span>{searchresults.pagination.PAGE_NUMBER}</span></li>
<!-- ELSEIF searchresults.pagination.S_IS_ELLIPSIS --><li class="ellipsis"><span>{L_ELLIPSIS}</span></li>
<!-- ELSEIF searchresults.pagination.S_IS_NEXT -->
- <!-- ELSE --><li><a href="{searchresults.pagination.PAGE_URL}">{searchresults.pagination.PAGE_NUMBER}</a></li>
+ <!-- ELSE --><li><a class="button" href="{searchresults.pagination.PAGE_URL}">{searchresults.pagination.PAGE_NUMBER}</a></li>
<!-- ENDIF -->
<!-- END pagination -->
</ul>
</div>
<!-- ENDIF -->
- <!-- IF searchresults.S_HAS_POLL -->{POLL_IMG} <!-- ENDIF -->
<!-- EVENT topiclist_row_topic_title_after -->
- {L_POST_BY_AUTHOR} {searchresults.TOPIC_AUTHOR_FULL} &raquo; {searchresults.FIRST_POST_TIME} &raquo; {L_IN} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a>
- <!-- EVENT topiclist_row_append -->
+ <!-- EVENT topiclist_row_append -->
</div>
</dt>
- <dd class="posts">{searchresults.TOPIC_REPLIES}</dd>
- <dd class="views">{searchresults.TOPIC_VIEWS}</dd>
- <dd class="lastpost"><span>
- {L_POST_BY_AUTHOR} {searchresults.LAST_POST_AUTHOR_FULL}
- <!-- IF not S_IS_BOT --><a href="{searchresults.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{LAST_POST_IMG}</a> <!-- ENDIF --><br />{searchresults.LAST_POST_TIME}<br /> </span>
+ <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}
+ <!-- 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>
+ </a>
+ <!-- ENDIF -->
+ <br />{searchresults.LAST_POST_TIME}
+ </span>
</dd>
</dl>
</li>
@@ -150,7 +198,11 @@
<!-- IF not searchresults.S_IGNORE_POST -->
<ul class="searchresults">
- <li ><a href="{searchresults.U_VIEW_POST}" class="arrow-{S_CONTENT_FLOW_END}">{L_JUMP_TO_POST}</a></li>
+ <li>
+ <a href="{searchresults.U_VIEW_POST}" class="arrow-{S_CONTENT_FLOW_END}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_END} fa-fw icon-black" aria-hidden="true"></i><span>{L_JUMP_TO_POST}</span>
+ </a>
+ </li>
</ul>
<!-- ENDIF -->
@@ -166,24 +218,13 @@
<!-- END searchresults -->
<!-- ENDIF -->
-<!-- IF .pagination or .searchresults or S_SELECT_SORT_KEY or S_SELECT_SORT_DAYS -->
+<div class="action-bar bottom">
+ <!-- IF .searchresults and (S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY) -->
<form method="post" action="{S_SEARCH_ACTION}">
-
- <fieldset class="display-options">
- <!-- IF S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY -->
- <label><!-- IF S_SHOW_TOPICS -->{L_DISPLAY_POSTS}<!-- ELSE -->{L_SORT_BY}</label><label><!-- ENDIF --> {S_SELECT_SORT_DAYS}<!-- IF S_SELECT_SORT_KEY --></label> <label>{S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}<!-- ENDIF --></label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <!-- ENDIF -->
- </fieldset>
-
+ <!-- INCLUDE display_options.html -->
</form>
+ <!-- ENDIF -->
- <hr />
-<!-- ENDIF -->
-
-<!-- IF .pagination or .searchresults or PAGE_NUMBER -->
-<div class="action-bar bottom">
<div class="pagination">
{SEARCH_MATCHES}
<!-- IF .pagination -->
@@ -193,7 +234,6 @@
<!-- ENDIF -->
</div>
</div>
-<!-- ENDIF -->
<!-- INCLUDE jumpbox.html -->
diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html
index 77980a9dea..614c137835 100644
--- a/phpBB/styles/prosilver/template/simple_footer.html
+++ b/phpBB/styles/prosilver/template/simple_footer.html
@@ -5,17 +5,21 @@
<!-- IF DEBUG_OUTPUT --><br />{DEBUG_OUTPUT}<!-- ENDIF -->
</div>
- <div id="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}">
- <div id="darken">&nbsp;</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}">
+ <div id="darken" class="darken">&nbsp;</div>
</div>
- <div id="loading_indicator"></div>
+ <div id="loading_indicator" class="loading_indicator"></div>
<div id="phpbb_alert" class="phpbb_alert" data-l-err="{L_ERROR}" data-l-timeout-processing-req="{L_TIMEOUT_PROCESSING_REQ}">
- <a href="#" class="alert_close"></a>
+ <a href="#" class="alert_close">
+ <i class="icon fa-times-circle fa-fw" aria-hidden="true"></i>
+ </a>
<h3 class="alert_title"></h3><p class="alert_text"></p>
</div>
- <div id="phpbb_confirm" class="phpbb_alert">
- <a href="#" class="alert_close"></a>
+ <div id="phpbb_confirm" class="phpbb_confirm phpbb_alert">
+ <a href="#" class="alert_close">
+ <i class="icon fa-times-circle fa-fw" aria-hidden="true"></i>
+ </a>
<div class="alert_text"></div>
</div>
</div>
diff --git a/phpBB/styles/prosilver/template/simple_header.html b/phpBB/styles/prosilver/template/simple_header.html
index 3924aa29d9..0e889b476d 100644
--- a/phpBB/styles/prosilver/template/simple_header.html
+++ b/phpBB/styles/prosilver/template/simple_header.html
@@ -23,9 +23,9 @@
})(document);
</script>
<!-- ENDIF -->
+<link href="{T_FONT_AWESOME_LINK}" rel="stylesheet">
<link href="{T_STYLESHEET_LINK}" rel="stylesheet">
<link href="{T_STYLESHEET_LANG_LINK}" rel="stylesheet">
-<link href="{T_THEME_PATH}/responsive.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet" media="all and (max-width: 700px)">
<!-- IF S_CONTENT_DIRECTION eq 'rtl' -->
<link href="{T_THEME_PATH}/bidi.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet">
@@ -49,6 +49,6 @@
<!-- EVENT simple_header_body_before -->
-<div id="wrap">
- <a id="top" class="anchor" accesskey="t"></a>
- <div id="page-body" role="main">
+<div id="wrap" class="wrap">
+ <a id="top" class="top-anchor" accesskey="t"></a>
+ <div id="page-body" class="page-body" role="main">
diff --git a/phpBB/styles/prosilver/template/timezone_option.html b/phpBB/styles/prosilver/template/timezone_option.html
index b8be456489..728dc9487a 100644
--- a/phpBB/styles/prosilver/template/timezone_option.html
+++ b/phpBB/styles/prosilver/template/timezone_option.html
@@ -12,7 +12,7 @@
</dd>
<!-- ENDIF -->
<dd>
- <select name="tz" id="timezone" class="autowidth tz_select">
+ <select name="tz" id="timezone" class="autowidth tz_select timezone">
<option value="">{L_SELECT_TIMEZONE}</option>
<!-- BEGIN timezone_select -->
<optgroup label="{timezone_select.LABEL}" data-tz-value="{timezone_select.VALUE}">
diff --git a/phpBB/styles/prosilver/template/ucp_attachments.html b/phpBB/styles/prosilver/template/ucp_attachments.html
index 1d4963273c..696f621116 100644
--- a/phpBB/styles/prosilver/template/ucp_attachments.html
+++ b/phpBB/styles/prosilver/template/ucp_attachments.html
@@ -6,21 +6,21 @@
<div class="panel">
<div class="inner">
-
+
<p>{L_ATTACHMENTS_EXPLAIN}</p>
<!-- IF .attachrow -->
<div class="action-bar top">
<div class="pagination">
{NUM_ATTACHMENTS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
</div>
-
+
<ul class="topiclist">
<li class="header">
<dl>
@@ -50,21 +50,15 @@
<!-- END attachrow -->
</ul>
- <fieldset class="display-options">
- <label for="sk">{L_SORT_BY}{L_COLON} <select name="sk" id="sk">{S_SORT_OPTIONS}</select></label>
- <label><select name="sd" id="sd">{S_ORDER_SELECT}</select></label>
- <input class="button2" type="submit" name="sort" value="{L_SORT}" />
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
{S_FORM_TOKEN}
- </fieldset>
- <hr />
-
- <div class="action-bar bottom">
<div class="pagination">
{TOTAL_ATTACHMENTS} {L_TITLE}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -76,9 +70,9 @@
</div>
</div>
-
+
<!-- IF S_ATTACHMENT_ROWS -->
- <fieldset class="display-actions">
+ <fieldset class="display-actions">
<input class="button2" type="submit" name="delete" value="{L_DELETE_MARKED}" />
<div><a href="#" onclick="marklist('ucp', 'attachment', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('ucp', 'attachment', false); return false;">{L_UNMARK_ALL}</a></div>
{S_FORM_TOKEN}
diff --git a/phpBB/styles/prosilver/template/ucp_avatar_options_local.html b/phpBB/styles/prosilver/template/ucp_avatar_options_local.html
index 80c7f28ca3..e431b7425e 100644
--- a/phpBB/styles/prosilver/template/ucp_avatar_options_local.html
+++ b/phpBB/styles/prosilver/template/ucp_avatar_options_local.html
@@ -6,7 +6,7 @@
</select></label>
<input type="submit" value="{L_GO}" name="avatar_local_go" class="button2" />
-<div id="gallery">
+<div id="gallery" class="gallery">
<!-- BEGIN avatar_local_row -->
<!-- BEGIN avatar_local_col -->
<label for="av-{avatar_local_row.S_ROW_COUNT}-{avatar_local_row.avatar_local_col.S_ROW_COUNT}"><img src="{avatar_local_row.avatar_local_col.AVATAR_IMAGE}" alt="" /><br />
diff --git a/phpBB/styles/prosilver/template/ucp_groups_manage.html b/phpBB/styles/prosilver/template/ucp_groups_manage.html
index 3b805c4862..f2b4f003e0 100644
--- a/phpBB/styles/prosilver/template/ucp_groups_manage.html
+++ b/phpBB/styles/prosilver/template/ucp_groups_manage.html
@@ -33,9 +33,9 @@
<dl>
<dt><label for="group_type1">{L_GROUP_TYPE}{L_COLON}</label><br /><span>{L_GROUP_TYPE_EXPLAIN}</span></dt>
<dd>
- <label for="group_type1"><input type="radio" class="radio" name="group_type" id="group_type1" value="{GROUP_TYPE_FREE}"{GROUP_FREE} /> {L_GROUP_OPEN}</label>
- <label for="group_type2"><input type="radio" class="radio" name="group_type" id="group_type2" value="{GROUP_TYPE_OPEN}"{GROUP_OPEN} /> {L_GROUP_REQUEST}</label>
- <label for="group_type3"><input type="radio" class="radio" name="group_type" id="group_type3" value="{GROUP_TYPE_CLOSED}"{GROUP_CLOSED} /> {L_GROUP_CLOSED}</label>
+ <label for="group_type1"><input type="radio" class="radio" name="group_type" id="group_type1" value="{GROUP_TYPE_FREE}"{GROUP_FREE} /> {L_GROUP_OPEN}</label>
+ <label for="group_type2"><input type="radio" class="radio" name="group_type" id="group_type2" value="{GROUP_TYPE_OPEN}"{GROUP_OPEN} /> {L_GROUP_REQUEST}</label>
+ <label for="group_type3"><input type="radio" class="radio" name="group_type" id="group_type3" value="{GROUP_TYPE_CLOSED}"{GROUP_CLOSED} /> {L_GROUP_CLOSED}</label>
<label for="group_type4"><input type="radio" class="radio" name="group_type" id="group_type4" value="{GROUP_TYPE_HIDDEN}"{GROUP_HIDDEN} /> {L_GROUP_HIDDEN}</label>
</dd>
</dl>
@@ -58,7 +58,7 @@
<input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" class="inputbox narrow" />
<span style="background-color: #{GROUP_COLOUR};">&nbsp;&nbsp;&nbsp;</span>
[ <a href="#" id="color_palette_toggle">{L_COLOUR_SWATCH}</a> ]
- <div id="color_palette_placeholder" class="hidden" data-orientation="h" data-height="12" data-width="15" data-target="#group_colour"></div>
+ <div id="color_palette_placeholder" class="color_palette_placeholder hidden" data-orientation="h" data-height="12" data-width="15" data-target="#group_colour"></div>
</dd>
</dl>
<dl>
@@ -74,7 +74,7 @@
<fieldset class="submit-buttons">
{S_HIDDEN_FIELDS}
- <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ <input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="update" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
@@ -160,8 +160,8 @@
</table>
<!-- IF .pagination -->
- <div class="action-bar bottom">
- <div class="pagination">
+ <div class="action-bar bar-bottom">
+ <div class="pagination">
<!-- INCLUDE pagination.html -->
</div>
</div>
@@ -170,7 +170,7 @@
</div>
</div>
-<fieldset class="display-actions">
+<fieldset class="display-actions">
<select name="action"><option value="">{L_SELECT_OPTION}</option>{S_ACTION_OPTIONS}</select>
<input class="button2" type="submit" name="update" value="{L_SUBMIT}" />
<div><a href="#" onclick="marklist('ucp', 'mark', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('ucp', 'mark', false); return false;">{L_UNMARK_ALL}</a></div>
@@ -187,7 +187,7 @@
<dl>
<dt><label for="default0">{L_USER_GROUP_DEFAULT}{L_COLON}</label><br /><span>{L_USER_GROUP_DEFAULT_EXPLAIN}</span></dt>
<dd>
- <label for="default1"><input type="radio" name="default" id="default1" value="1" /> {L_YES}</label>
+ <label for="default1"><input type="radio" name="default" id="default1" value="1" /> {L_YES}</label>
<label for="default0"><input type="radio" name="default" id="default0" value="0" checked="checked" /> {L_NO}</label>
</dd>
</dl>
diff --git a/phpBB/styles/prosilver/template/ucp_groups_membership.html b/phpBB/styles/prosilver/template/ucp_groups_membership.html
index d7df3b02c2..e824a7b867 100644
--- a/phpBB/styles/prosilver/template/ucp_groups_membership.html
+++ b/phpBB/styles/prosilver/template/ucp_groups_membership.html
@@ -55,7 +55,7 @@
<!-- BEGIN member -->
<!-- IF not member.GROUP_SPECIAL -->
<!-- DEFINE $SHOW_BUTTONS = 1 -->
- <!-- ENDIF -->
+ <!-- ENDIF -->
<li class="row<!-- IF member.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
<dl>
<dt>
@@ -73,11 +73,11 @@
</ul>
<!-- ENDIF -->
</div>
-</div>
+</div>
<!-- IF .pending -->
<div class="panel">
- <div class="inner">
+ <div class="inner">
<ul class="topiclist two-columns">
<li class="header">
<dl>
@@ -91,7 +91,7 @@
<!-- BEGIN pending -->
<!-- IF not pending.GROUP_SPECIAL -->
<!-- DEFINE $SHOW_BUTTONS = 1 -->
- <!-- ENDIF -->
+ <!-- ENDIF -->
<li class="row<!-- IF pending.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
<dl>
<dt>
@@ -125,7 +125,7 @@
<!-- BEGIN nonmember -->
<!-- IF nonmember.S_CAN_JOIN -->
<!-- DEFINE $SHOW_BUTTONS = 1 -->
- <!-- ENDIF -->
+ <!-- ENDIF -->
<li class="row<!-- IF nonmember.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
<dl>
<dt>
@@ -143,7 +143,7 @@
</div>
</div>
<!-- ENDIF -->
-
+
<!-- IF S_CHANGE_DEFAULT or $SHOW_BUTTONS eq 1 -->
<fieldset>
@@ -156,7 +156,7 @@
<!-- IF $SHOW_BUTTONS eq 1 -->
<div class="right-box">
- <label for="action">{L_SELECT}{L_COLON}</label>
+ <label for="action">{L_SELECT}{L_COLON}</label>
<select name="action" id="action">
<option value="join">{L_JOIN_SELECTED}</option>
<option value="resign">{L_RESIGN_SELECTED}</option>
diff --git a/phpBB/styles/prosilver/template/ucp_header.html b/phpBB/styles/prosilver/template/ucp_header.html
index a17f145cbc..98d2eee1a0 100644
--- a/phpBB/styles/prosilver/template/ucp_header.html
+++ b/phpBB/styles/prosilver/template/ucp_header.html
@@ -2,7 +2,7 @@
<h2 class="ucp-title">{L_UCP}</h2>
-<div id="tabs">
+<div id="tabs" class="tabs">
<ul>
<!-- BEGIN t_block1 -->
<li class="tab<!-- IF t_block1.S_SELECTED --> activetab<!-- ENDIF -->"><a href="{t_block1.U_TITLE}">{t_block1.L_TITLE}</a></li>
@@ -19,15 +19,15 @@
<div style="width: 100%;">
- <div id="cp-menu">
- <div id="navigation" role="navigation">
+ <div id="cp-menu" class="cp-menu">
+ <div id="navigation" class="navigation" role="navigation">
<!-- IF S_PRIVMSGS -->
<!-- BEGIN t_block2 -->
<!-- IF S_PRIVMSGS and not t_block2.S_LAST_ROW -->
<ul>
<!-- IF t_block2.S_SELECTED -->
- <li id="active-subsection"><a href="{t_block2.U_TITLE}"><span>{t_block2.L_TITLE}</span></a></li>
+ <li id="active-subsection" class="active-subsection"><a href="{t_block2.U_TITLE}"><span>{t_block2.L_TITLE}</span></a></li>
<!-- ELSE -->
<li><a href="{t_block2.U_TITLE}"><span>{t_block2.L_TITLE}</span></a></li>
<!-- ENDIF -->
@@ -39,7 +39,7 @@
<!-- BEGIN folder -->
<!-- IF folder.S_FIRST_ROW --><ul><!-- ENDIF -->
<!-- IF folder.S_CUR_FOLDER -->
- <li id="active-subsection"><a href="{folder.U_FOLDER}"><!-- IF folder.UNREAD_MESSAGES > 0 --><strong>{folder.FOLDER_NAME} ({folder.UNREAD_MESSAGES})</strong><!-- ELSE -->{folder.FOLDER_NAME}<!-- ENDIF --></a></li>
+ <li id="active-subsection" class="active-subsection"><a href="{folder.U_FOLDER}"><!-- IF folder.UNREAD_MESSAGES > 0 --><strong>{folder.FOLDER_NAME} ({folder.UNREAD_MESSAGES})</strong><!-- ELSE -->{folder.FOLDER_NAME}<!-- ENDIF --></a></li>
<!-- ELSE -->
<li><a href="{folder.U_FOLDER}"><span><!-- IF folder.UNREAD_MESSAGES > 0 --><strong>{folder.FOLDER_NAME} ({folder.UNREAD_MESSAGES})</strong><!-- ELSE -->{folder.FOLDER_NAME}<!-- ENDIF --></span></a></li>
<!-- ENDIF -->
@@ -52,7 +52,7 @@
<!-- BEGIN t_block2 -->
<!-- IF (S_PRIVMSGS and t_block2.S_LAST_ROW) or not S_PRIVMSGS -->
<!-- IF t_block2.S_SELECTED -->
- <li id="active-subsection"><a href="{t_block2.U_TITLE}"><span>{t_block2.L_TITLE}</span></a></li>
+ <li id="active-subsection" class="active-subsection"><a href="{t_block2.U_TITLE}"><span>{t_block2.L_TITLE}</span></a></li>
<!-- ELSE -->
<li><a href="{t_block2.U_TITLE}"><span>{t_block2.L_TITLE}</span></a></li>
<!-- ENDIF -->
@@ -98,4 +98,4 @@
</div>
- <div id="cp-main" class="ucp-main panel-container">
+ <div id="cp-main" class="cp-main ucp-main panel-container">
diff --git a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html
index f74728bdb3..25647afe1a 100644
--- a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html
+++ b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html
@@ -16,7 +16,7 @@
<!-- IF .topicrow -->
<ul class="topiclist missing-column">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt><div class="list-inner">{L_BOOKMARKS}</div></dt>
<dd class="lastpost"><span>{L_LAST_POST}</span></dd>
<dd class="mark">{L_MARK}</dd>
@@ -34,13 +34,26 @@
<dd class="mark"><input type="checkbox" name="t[{topicrow.TOPIC_ID}]" id="t{topicrow.TOPIC_ID}" /></dd>
</dl>
<!-- ELSE -->
- <dl class="icon {topicrow.TOPIC_IMG_STYLE}">
+ <dl class="row-item {topicrow.TOPIC_IMG_STYLE}">
<dt<!-- IF topicrow.TOPIC_ICON_IMG --> 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 --><a href="{topicrow.U_NEWEST_POST}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --><a href="{topicrow.U_MCP_QUEUE}">{topicrow.UNAPPROVED_IMG}</a> <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED --><a href="{topicrow.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- ENDIF --><br />
+ <!-- IF topicrow.S_UNREAD_TOPIC -->
+ <a class="unread" href="{topicrow.U_NEWEST_POST}">
+ <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.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>
+ <!-- ENDIF -->
+ <!-- IF topicrow.S_TOPIC_REPORTED -->
+ <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}">
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span>
+ </a>
+ <!-- ENDIF -->
+ <br />
<!-- IF .topicrow.pagination -->
<div class="pagination">
<ul>
@@ -56,18 +69,21 @@
</div>
<!-- ENDIF -->
<div class="responsive-hide">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- 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} &raquo; {topicrow.FIRST_POST_TIME}
</div>
<div class="responsive-show" style="display: none;">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- ENDIF -->
+ <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <!-- ENDIF -->
{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} &laquo;
<a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{topicrow.LAST_POST_TIME}</a>
</div>
</div>
</dt>
<dd class="lastpost"><span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}
- <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{LAST_POST_IMG}</a> <br />{topicrow.LAST_POST_TIME}</span>
+ <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>
+ <br />{topicrow.LAST_POST_TIME}</span>
</dd>
<dd class="mark"><input type="checkbox" name="t[{topicrow.TOPIC_ID}]" id="t{topicrow.TOPIC_ID}" /></dd>
</dl>
@@ -76,12 +92,12 @@
<!-- END topicrow -->
</ul>
- <div class="action-bar bottom">
+ <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_TOPICS}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/ucp_main_front.html b/phpBB/styles/prosilver/template/ucp_main_front.html
index 7bc8d40078..a3100524ce 100644
--- a/phpBB/styles/prosilver/template/ucp_main_front.html
+++ b/phpBB/styles/prosilver/template/ucp_main_front.html
@@ -13,11 +13,16 @@
<ul class="topiclist cplist two-long-columns">
<!-- BEGIN topicrow -->
<li class="row<!-- IF topicrow.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
- <dl class="icon {topicrow.TOPIC_IMG_STYLE}">
+ <dl class="row-item {topicrow.TOPIC_IMG_STYLE}">
<dt <!-- IF topicrow.TOPIC_ICON_IMG -->style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF -->>
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
- <!-- IF topicrow.S_UNREAD --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a><br />
+ <!-- IF topicrow.S_UNREAD -->
+ <a class="unread" href="{topicrow.U_NEWEST_POST}">
+ <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><br />
<!-- IF .topicrow.pagination -->
<div class="pagination">
<ul>
@@ -33,17 +38,22 @@
</div>
<!-- ENDIF -->
<div class="responsive-hide">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- 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} &raquo; {topicrow.FIRST_POST_TIME}
</div>
<div class="responsive-show" style="display: none;">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- ENDIF -->
+ <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <!-- ENDIF -->
{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} &laquo; <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{topicrow.LAST_POST_TIME}</a>
</div>
</div>
</dt>
- <dd class="lastpost"><span>{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}
- <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{LAST_POST_IMG}</a> <br />{topicrow.LAST_POST_TIME}</span>
+ <dd class="lastpost">
+ <span>{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}
+ <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>
+ <br />{topicrow.LAST_POST_TIME}
+ </span>
</dd>
</dl>
</li>
@@ -60,7 +70,7 @@
<dt>{L_TOTAL_POSTS}{L_COLON}</dt> <dd><!-- IF POSTS_PCT -->{POSTS}<!-- IF S_DISPLAY_SEARCH --> | <strong><a href="{U_SEARCH_USER}">{L_SEARCH_YOUR_POSTS}</a></strong><!-- ENDIF --><br />({POSTS_DAY} / {POSTS_PCT})<!-- ELSE -->{POSTS}<!-- ENDIF --></dd>
<!-- IF ACTIVE_FORUM != '' --><dt>{L_ACTIVE_IN_FORUM}{L_COLON}</dt> <dd><strong><a href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></strong><br />({ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT})</dd><!-- ENDIF -->
<!-- IF ACTIVE_TOPIC != '' --><dt>{L_ACTIVE_IN_TOPIC}{L_COLON}</dt> <dd><strong><a href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></strong><br />({ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT})</dd><!-- ENDIF -->
- <!-- IF WARNINGS --><dt>{L_YOUR_WARNINGS}{L_COLON}</dt> <dd class="error">{WARNING_IMG} [{WARNINGS}]</dd><!-- ENDIF -->
+ <!-- IF WARNINGS --><dt>{L_YOUR_WARNINGS}{L_COLON}</dt> <dd class="error"><i class="icon fa-exclamation-triangle fa-fw icon-red" aria-hidden="true"></i> [{WARNINGS}]</dd><!-- ENDIF -->
</dl>
<!-- EVENT ucp_main_front_user_activity_after -->
diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html
index 2d65b800a0..d8de7fd093 100644
--- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html
+++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html
@@ -11,7 +11,7 @@
<!-- IF .forumrow -->
<ul class="topiclist missing-column">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt><div class="list-inner">{L_WATCHED_FORUMS}</div></dt>
<dd class="lastpost"><span>{L_LAST_POST}</span></dd>
<dd class="mark">{L_MARK}</dd>
@@ -22,9 +22,9 @@
<!-- BEGIN forumrow -->
<li class="row<!-- IF forumrow.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
- <dl class="icon {forumrow.FORUM_IMG_STYLE}">
+ <dl class="row-item {forumrow.FORUM_IMG_STYLE}">
<dt>
- <!-- IF forumrow.S_UNREAD_FORUM --><a href="{forumrow.U_VIEWFORUM}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF forumrow.S_UNREAD_FORUM --><a href="{forumrow.U_VIEWFORUM}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
<a href="{forumrow.U_VIEWFORUM}" class="forumtitle">{forumrow.FORUM_NAME}</a><br />
{forumrow.FORUM_DESC}
@@ -35,9 +35,16 @@
<!-- ENDIF -->
</div>
</dt>
- <dd class="lastpost"><!-- IF forumrow.LAST_POST_TIME --><span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {forumrow.LAST_POST_AUTHOR_FULL}
- <a href="{forumrow.U_LAST_POST}">{LAST_POST_IMG}</a> <br />{forumrow.LAST_POST_TIME}</span>
- <!-- ELSE -->{L_NO_POSTS}<br />&nbsp;<!-- ENDIF -->
+ <dd class="lastpost">
+ <!-- IF forumrow.LAST_POST_TIME -->
+ <span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {forumrow.LAST_POST_AUTHOR_FULL}
+ <a href="{forumrow.U_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>
+ <br />{forumrow.LAST_POST_TIME}</span>
+ <!-- ELSE -->
+ {L_NO_POSTS}<br />&nbsp;
+ <!-- ENDIF -->
</dd>
<dd class="mark"><input type="checkbox" name="f[{forumrow.FORUM_ID}]" id="f{forumrow.FORUM_ID}" /></dd>
</dl>
@@ -47,7 +54,7 @@
<!-- ELSEIF S_FORUM_NOTIFY -->
<ul class="topiclist">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt>{L_WATCHED_FORUMS}</dt>
</dl>
</li>
@@ -59,7 +66,7 @@
<!-- IF .topicrow -->
<ul class="topiclist missing-column">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt><div class="list-inner">{L_WATCHED_TOPICS}</div></dt>
<dd class="lastpost"><span>{L_LAST_POST}</span></dd>
<dd class="mark">{L_MARK}</dd>
@@ -70,13 +77,26 @@
<!-- BEGIN topicrow -->
<li class="row<!-- IF topicrow.S_TOPIC_REPORTED --> reported<!-- ELSEIF topicrow.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF -->">
- <dl class="icon {topicrow.TOPIC_IMG_STYLE}">
+ <dl class="row-item {topicrow.TOPIC_IMG_STYLE}">
<dt<!-- IF topicrow.TOPIC_ICON_IMG --> 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 --><a href="{topicrow.U_NEWEST_POST}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --><a href="{topicrow.U_MCP_QUEUE}">{topicrow.UNAPPROVED_IMG}</a> <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED --><a href="{topicrow.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- ENDIF --><br />
+ <!-- IF topicrow.S_UNREAD_TOPIC -->
+ <a class="unread" href="{topicrow.U_NEWEST_POST}">
+ <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.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>
+ <!-- ENDIF -->
+ <!-- IF topicrow.S_TOPIC_REPORTED -->
+ <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}">
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span>
+ </a>
+ <!-- ENDIF -->
+ <br />
<!-- IF .topicrow.pagination -->
<div class="pagination">
<ul>
@@ -92,17 +112,20 @@
</div>
<!-- ENDIF -->
<div class="responsive-hide">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- 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} &raquo; {topicrow.FIRST_POST_TIME}
</div>
<div class="responsive-show" style="display: none;">
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- ENDIF -->
+ <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <!-- ENDIF -->
{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} &laquo; <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{topicrow.LAST_POST_TIME}</a>
</div>
</div>
</dt>
<dd class="lastpost"><span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}
- <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{LAST_POST_IMG}</a> <br />{topicrow.LAST_POST_TIME}</span>
+ <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>
+ <br />{topicrow.LAST_POST_TIME}</span>
</dd>
<dd class="mark"><input type="checkbox" name="t[{topicrow.TOPIC_ID}]" id="t{topicrow.TOPIC_ID}" /></dd>
</dl>
@@ -110,7 +133,7 @@
<!-- END topicrow -->
</ul>
- <div class="action-bar bottom">
+ <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_TOPICS}
<!-- IF .pagination -->
@@ -124,7 +147,7 @@
<!-- ELSEIF S_TOPIC_NOTIFY -->
<ul class="topiclist">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt>{L_WATCHED_TOPICS}</dt>
</dl>
</li>
diff --git a/phpBB/styles/prosilver/template/ucp_notifications.html b/phpBB/styles/prosilver/template/ucp_notifications.html
index 500bae0c47..32efae17fd 100644
--- a/phpBB/styles/prosilver/template/ucp_notifications.html
+++ b/phpBB/styles/prosilver/template/ucp_notifications.html
@@ -16,7 +16,6 @@
<!-- BEGIN notification_methods -->
<th class="mark">{notification_methods.NAME}</th>
<!-- END notification_methods -->
- <th class="mark">{L_NOTIFICATIONS}</th>
</tr>
</thead>
<tbody>
@@ -34,7 +33,6 @@
<!-- BEGIN notification_methods -->
<td class="mark"><input type="checkbox" name="{notification_types.TYPE}_{notification_methods.METHOD}"<!-- IF notification_methods.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /></td>
<!-- END notification_methods -->
- <td class="mark"><input type="checkbox" name="{notification_types.TYPE}_notification"<!-- IF notification_types.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /></td>
</tr>
<!-- ENDIF -->
<!-- END notification_types -->
@@ -42,7 +40,7 @@
</table>
<!-- ELSE -->
<!-- IF .notification_list -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<div class="pagination">
<!-- IF U_MARK_ALL --><a href="{U_MARK_ALL}" class="mark">{L_NOTIFICATIONS_MARK_ALL_READ}</a> &bull; <!-- ENDIF -->
{L_NOTIFICATIONS} [<strong>{TOTAL_COUNT}</strong>]
@@ -68,12 +66,12 @@
<li class="row<!-- IF notification_list.UNREAD --> bg3<!-- ELSE --><!-- IF notification_list.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- ENDIF --><!-- IF notification_list.STYLING --> {notification_list.STYLING}<!-- ENDIF -->">
<dl>
<dt>
- <div class="list-inner">
+ <div class="list-inner">
<!-- IF notification_list.AVATAR -->{notification_list.AVATAR}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF -->
<div class="notifications">
<!-- IF notification_list.URL --><a href="<!-- IF notification_list.UNREAD -->{notification_list.U_MARK_READ}<!-- ELSE -->{notification_list.URL}<!-- ENDIF -->"><!-- ENDIF -->
<p class="notifications_title">{notification_list.FORMATTED_TITLE}<!-- IF notification_list.REFERENCE --> {notification_list.REFERENCE}<!-- ENDIF --></p>
- <!-- IF notification_list.URL --></a><!-- ENDIF -->
+ <!-- IF notification_list.URL --></a><!-- ENDIF -->
<!-- IF notification_list.FORUM --><p class="notifications_forum">{notification_list.FORUM}</p><!-- ENDIF -->
<!-- IF notification_list.REASON --><p class="notifications_reason">{notification_list.REASON}</p><!-- ENDIF -->
<p class="notifications_time">{notification_list.TIME}</p>
@@ -88,7 +86,7 @@
</ul>
</div>
- <div class="action-bar bottom">
+ <div class="action-bar bar-bottom">
<div class="pagination">
{L_NOTIFICATIONS} [<strong>{TOTAL_COUNT}</strong>]
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/ucp_pm_history.html b/phpBB/styles/prosilver/template/ucp_pm_history.html
index 28f217ef66..e97befc552 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_history.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_history.html
@@ -1,11 +1,11 @@
-<h3 id="review">
+<h3 id="review" class="review">
<span class="right-box"><a href="#review" onclick="viewableArea(getElementById('topicreview'), true); var rev_text = getElementById('review').getElementsByTagName('a').item(0).firstChild; if (rev_text.data == '{LA_EXPAND_VIEW}'){rev_text.data = '{LA_COLLAPSE_VIEW}'; } else if (rev_text.data == '{LA_COLLAPSE_VIEW}'){rev_text.data = '{LA_EXPAND_VIEW}'};">{L_EXPAND_VIEW}</a></span>
{L_MESSAGE_HISTORY}{L_COLON}
</h3>
<!-- EVENT ucp_pm_history_review_before -->
-<div id="topicreview">
+<div id="topicreview" class="topicreview">
<script type="text/javascript">
// <![CDATA[
bbcodeEnabled = {S_BBCODE_ALLOWED};
@@ -25,8 +25,8 @@
<!-- EVENT ucp_pm_history_post_buttons_before -->
<!-- IF history_row.U_QUOTE or history_row.MESSAGE_AUTHOR_QUOTE -->
<li>
- <a <!-- IF history_row.U_QUOTE -->href="{history_row.U_QUOTE}"<!-- ELSE -->href="#postingbox" onclick="addquote({history_row.MSG_ID}, '{history_row.MESSAGE_AUTHOR_QUOTE}', '{LA_WROTE}');"<!-- ENDIF --> title="{L_QUOTE} {history_row.MESSAGE_AUTHOR}" class="button icon-button quote-icon">
- <span>{L_QUOTE} {history_row.MESSAGE_AUTHOR}</span>
+ <a <!-- IF history_row.U_QUOTE -->href="{history_row.U_QUOTE}"<!-- ELSE -->href="#postingbox" onclick="addquote({history_row.MSG_ID}, '{history_row.MESSAGE_AUTHOR_QUOTE}', '{LA_WROTE}', {time:{history_row.MESSAGE_TIME},user_id:{history_row.USER_ID}});"<!-- ENDIF --> title="{L_QUOTE} {history_row.MESSAGE_AUTHOR}" class="button button-icon-only">
+ <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_QUOTE} {history_row.MESSAGE_AUTHOR}</span>
</a>
</li>
<!-- ENDIF -->
@@ -35,8 +35,11 @@
<!-- ENDIF -->
<!-- EVENT ucp_pm_history_post_buttons_list_after -->
- <p class="author">{history_row.MINI_POST_IMG} {L_SENT_AT}{L_COLON} <strong>{history_row.SENT_DATE}</strong><br />
- {L_MESSAGE_BY_AUTHOR} {history_row.MESSAGE_AUTHOR_FULL}</p>
+ <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}
+ </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>
</div>
@@ -48,4 +51,9 @@
<!-- EVENT ucp_pm_history_review_after -->
<hr />
-<p><a href="#cp-main" class="top2">{L_BACK_TO_TOP}</a></p>
+<p>
+ <a href="#cp-main" class="top">
+ <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_message_header.html b/phpBB/styles/prosilver/template/ucp_pm_message_header.html
index 7be51e0034..6ad9e9cab6 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_message_header.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_message_header.html
@@ -6,38 +6,45 @@
<div class="inner">
<!-- IF FOLDER_STATUS and FOLDER_MAX_MESSAGES neq 0 --><p>{FOLDER_STATUS}</p><!-- ENDIF -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<!-- IF U_POST_REPLY_PM or U_POST_NEW_TOPIC or U_FORWARD_PM -->
- <div class="buttons">
- <!-- IF U_POST_REPLY_PM -->
- <a title="{L_POST_REPLY_PM}" href="{U_POST_REPLY_PM}" class="button icon-button pmreply-icon">
- {L_BUTTON_PM_REPLY}
- </a>
- <!-- ELSEIF U_POST_NEW_TOPIC -->
- <a href="{U_POST_NEW_TOPIC}" accesskey="n" title="{L_UCP_PM_COMPOSE}" class="button icon-button newpm-icon">
- {L_BUTTON_PM_NEW}
- </a>
- <!-- ENDIF -->
- <!-- IF U_FORWARD_PM -->
- <a title="{L_POST_FORWARD_PM}" href="{U_FORWARD_PM}" class="button icon-button forwardpm-icon">
- {L_BUTTON_PM_FORWARD}
- </a>
- <!-- ENDIF -->
- <!-- IF U_POST_REPLY_PM and S_PM_RECIPIENTS gt 1 -->
- <a title="{L_REPLY_TO_ALL}" href="{U_POST_REPLY_ALL}" class="button icon-button reply-all">
- {L_BUTTON_PM_REPLY_ALL}
- </a>
- <!-- ENDIF -->
- </div>
+ <!-- IF U_POST_REPLY_PM -->
+ <a title="{L_POST_REPLY_PM}" href="{U_POST_REPLY_PM}" class="button">
+ <span>{L_BUTTON_PM_REPLY}</span> <i class="icon fa-reply fa-fw" aria-hidden="true"></i>
+ </a>
+ <!-- ELSEIF U_POST_NEW_TOPIC -->
+ <a href="{U_POST_NEW_TOPIC}" accesskey="n" title="{L_UCP_PM_COMPOSE}" class="button">
+ <span>{L_BUTTON_PM_NEW}</span> <i class="icon fa-pencil fa-fw" aria-hidden="true"></i>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF U_FORWARD_PM -->
+ <a title="{L_POST_FORWARD_PM}" href="{U_FORWARD_PM}" class="button">
+ <span>{L_BUTTON_PM_FORWARD}</span> <i class="icon fa-mail-forward fa-fw" aria-hidden="true"></i>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF U_POST_REPLY_PM and S_PM_RECIPIENTS gt 1 -->
+ <a title="{L_REPLY_TO_ALL}" href="{U_POST_REPLY_ALL}" class="button">
+ <span>{L_BUTTON_PM_REPLY_ALL}</span> <i class="icon fa-pencil fa-fw" aria-hidden="true"></i>
+ </a>
+ <!-- ENDIF -->
<!-- ENDIF -->
<!-- IF not S_IS_BOT and U_PRINT_PM -->
<div class="dropdown-container dropdown-button-control topic-tools">
- <span title="{L_PM_TOOLS}" class="dropdown-trigger dropdown-select button icon-button tools-icon"></span>
- <div class="dropdown hidden">
+ <span title="{L_PM_TOOLS}" class="button button-secondary dropdown-trigger dropdown-select">
+ <i class="icon fa-wrench fa-fw" aria-hidden="true"></i>
+ <span class="caret"><i class="icon fa-sort-down fa-fw" aria-hidden="true"></i></span>
+ </span>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents">
- <!-- IF U_PRINT_PM --><li class="small-icon icon-print"><a href="{U_PRINT_PM}" title="{L_PRINT_PM}" accesskey="p">{L_PRINT_PM}</a></li><!-- ENDIF -->
+ <!-- IF U_PRINT_PM -->
+ <li>
+ <a href="{U_PRINT_PM}" title="{L_PRINT_PM}" accesskey="p">
+ <i class="icon fa-print fa-fw" aria-hidden="true"></i><span>{L_PRINT_PM}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
</ul>
</div>
</div>
@@ -46,7 +53,9 @@
<!-- IF TOTAL_MESSAGES or S_VIEW_MESSAGE -->
<div class="pagination">
<!-- IF S_VIEW_MESSAGE -->
- <a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_CURRENT_FOLDER}">{L_RETURN_TO_FOLDER}</a>
+ <a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_CURRENT_FOLDER}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_RETURN_TO_FOLDER}</span>
+ </a>
<!-- ELSEIF FOLDER_CUR_MESSAGES neq 0 -->
<!-- IF U_MARK_ALL --><a href="{U_MARK_ALL}" class="mark">{L_PM_MARK_ALL_READ}</a> &bull; <!-- ENDIF -->
{TOTAL_MESSAGES}
diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html b/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html
index 47e4d1c63a..a290313df7 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html
@@ -57,9 +57,9 @@
<!-- BEGIN messagerow -->
<li class="row<!-- IF messagerow.S_ROW_COUNT is odd --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- IF messagerow.PM_CLASS --> {messagerow.PM_CLASS}<!-- ENDIF -->">
- <dl class="icon {messagerow.FOLDER_IMG_STYLE}">
+ <dl class="row-item {messagerow.FOLDER_IMG_STYLE}">
<dt<!-- IF messagerow.PM_ICON_URL and S_PM_ICONS --> style="background-image: url({messagerow.PM_ICON_URL}); background-repeat: no-repeat;"<!-- ENDIF -->>
- <!-- IF messagerow.S_PM_UNREAD and not messagerow.S_PM_DELETED --><a href="{messagerow.U_VIEW_PM}" class="icon-link"></a><!-- ENDIF -->
+ <!-- IF messagerow.S_PM_UNREAD and not messagerow.S_PM_DELETED --><a href="{messagerow.U_VIEW_PM}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
<!-- IF messagerow.S_PM_DELETED -->
@@ -71,8 +71,11 @@
<!-- IF messagerow.S_AUTHOR_DELETED -->
<br /><em class="small">{L_PM_FROM_REMOVED_AUTHOR}</em>
<!-- ENDIF -->
-
- <!-- IF messagerow.S_PM_REPORTED --><a href="{messagerow.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- ENDIF --> {messagerow.ATTACH_ICON_IMG}<br />
+ <!-- IF messagerow.S_PM_REPORTED -->
+ <a href="{messagerow.U_MCP_REPORT}">
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{PM_REPORTED}</span>
+ </a>
+ <!-- ENDIF --> <!-- IF messagerow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <!-- ENDIF --><br />
<!-- IF S_SHOW_RECIPIENTS -->{L_MESSAGE_TO} {messagerow.RECIPIENTS}<!-- ELSE -->{L_MESSAGE_BY_AUTHOR} {messagerow.MESSAGE_AUTHOR_FULL} &raquo; {messagerow.SENT_TIME}<!-- ENDIF -->
</div>
@@ -101,15 +104,18 @@
<select name="mark_option">{S_MARK_OPTIONS}{S_MOVE_MARKED_OPTIONS}</select> <input class="button2" type="submit" name="submit_mark" value="{L_GO}" />
<div><a href="#" onclick="marklist('viewfolder', 'marked_msg', true); return false;">{L_MARK_ALL}</a> &bull; <a href="#" onclick="marklist('viewfolder', 'marked_msg', false); return false;">{L_UNMARK_ALL}</a></div>
</fieldset>
-
+
<hr />
-
+
<div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+ <input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
+
<div class="pagination">
{TOTAL_MESSAGES}
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
&bull; {PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -119,16 +125,6 @@
</div>
</div>
- <!-- IF FOLDER_CUR_MESSAGES neq 0 -->
- <fieldset class="display-options">
- <label>{L_DISPLAY}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
- </fieldset>
- <!-- ENDIF -->
-
<!-- INCLUDE ucp_pm_message_footer.html -->
<!-- ENDIF -->
<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html
index d92b90a045..59317da8f7 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html
@@ -8,8 +8,16 @@
<!-- IF S_DISPLAY_HISTORY and (U_VIEW_PREVIOUS_HISTORY or U_VIEW_NEXT_HISTORY) -->
<fieldset class="display-options clearfix">
- <!-- IF U_VIEW_PREVIOUS_HISTORY --><a href="{U_VIEW_PREVIOUS_HISTORY}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_VIEW_PREVIOUS_HISTORY}</a><!-- ENDIF -->
- <!-- IF U_VIEW_NEXT_HISTORY --><a href="{U_VIEW_NEXT_HISTORY}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_VIEW_NEXT_HISTORY}</a><!-- ENDIF -->
+ <!-- IF U_VIEW_PREVIOUS_HISTORY -->
+ <a href="{U_VIEW_PREVIOUS_HISTORY}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_PREVIOUS_HISTORY}</span>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF U_VIEW_NEXT_HISTORY -->
+ <a href="{U_VIEW_NEXT_HISTORY}" class="right-box arrow-{S_CONTENT_FLOW_END}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_NEXT_HISTORY}</span>
+ </a>
+ <!-- ENDIF -->
</fieldset>
<!-- ENDIF -->
@@ -47,8 +55,8 @@
<dd class="profile-contact">
<strong>{L_CONTACT}{L_COLON}</strong>
<div class="dropdown-container dropdown-left">
- <a href="#" class="dropdown-trigger"><span class="imageset icon_contact" title="{CONTACT_USER}">{CONTACT_USER}</span></a>
- <div class="dropdown hidden">
+ <a href="#" class="dropdown-trigger" title="{CONTACT_USER}"><i class="icon fa-commenting-o fa-fw icon-lg" aria-hidden="true"></i><span class="sr-only">{CONTACT_USER}</span></a>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<div class="dropdown-contents contact-icons">
<!-- BEGIN contact -->
@@ -82,22 +90,30 @@
<!-- EVENT ucp_pm_viewmessage_post_buttons_before -->
<!-- IF U_EDIT -->
<li>
- <a href="{U_EDIT}" title="{L_POST_EDIT_PM}" class="button icon-button edit-icon"><span>{L_POST_EDIT_PM}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF U_DELETE -->
<li>
- <a href="{U_DELETE}" title="{L_DELETE_MESSAGE}" class="button icon-button delete-icon"><span>{L_DELETE_MESSAGE}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF U_REPORT -->
<li>
- <a href="{U_REPORT}" title="{L_REPORT_PM}" class="button icon-button report-icon"><span>{L_REPORT_PM}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF U_QUOTE -->
<li>
- <a href="{U_QUOTE}" title="{L_POST_QUOTE_PM}" class="button icon-button quote-icon"><span>{L_POST_QUOTE_PM}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- EVENT ucp_pm_viewmessage_post_buttons_after -->
@@ -141,17 +157,30 @@
<!-- ENDIF -->
</div>
- <div class="back2top"><a href="#top" class="top" title="{L_BACK_TO_TOP}">{L_BACK_TO_TOP}</a></div>
+ <div class="back2top">
+ <a href="#top" class="top" title="{L_BACK_TO_TOP}">
+ <i class="icon fa-chevron-circle-up fa-fw icon-gray" aria-hidden="true"></i>
+ <span class="sr-only">{L_BACK_TO_TOP}</span>
+ </a>
+ </div>
</div>
</div>
<!-- IF S_VIEW_MESSAGE -->
<fieldset class="display-options">
- <!-- IF U_PREVIOUS_PM --><a href="{U_PREVIOUS_PM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_VIEW_PREVIOUS_PM}</a><!-- ENDIF -->
- <!-- IF U_NEXT_PM --><a href="{U_NEXT_PM}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_VIEW_NEXT_PM}</a><!-- ENDIF -->
<!-- IF S_MARK_OPTIONS --><label for="mark_option"><select name="mark_option" id="mark_option">{S_MARK_OPTIONS}</select></label>&nbsp;<input class="button2" type="submit" name="submit_mark" value="{L_GO}" /><!-- ENDIF -->
+ <!-- IF U_PREVIOUS_PM -->
+ <a href="{U_PREVIOUS_PM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_PREVIOUS_PM}</span>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF U_NEXT_PM -->
+ <a href="{U_NEXT_PM}" class="right-box arrow-{S_CONTENT_FLOW_END}">
+ <i class="icon fa-angle-{S_CONTENT_FLOW_BEGIN} fa-fw icon-black" aria-hidden="true"></i><span>{L_VIEW_NEXT_PM}</span>
+ </a>
+ <!-- ENDIF -->
<!-- IF not S_UNREAD and not S_SPECIAL_FOLDER --><label for="dest_folder"><!-- IF S_VIEW_MESSAGE -->{L_MOVE_TO_FOLDER}{L_COLON} <!-- ELSE -->{L_MOVE_MARKED_TO_FOLDER}<!-- ENDIF --> <select name="dest_folder" id="dest_folder">{S_TO_FOLDER_OPTIONS}</select></label> <input class="button2" type="submit" name="move_pm" value="{L_GO}" /><!-- ENDIF -->
<input type="hidden" name="marked_msg_id[]" value="{MSG_ID}" />
<input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html
index d431561834..9377eeb9f5 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html
@@ -11,8 +11,8 @@
<!-- EVENT ucp_pm_viewmessage_print_head_append -->
</head>
<body id="phpbb">
-<div id="wrap">
- <a id="top" class="anchor" accesskey="t"></a>
+<div id="wrap" class="wrap">
+ <a id="top" class="top-anchor" accesskey="t"></a>
<div id="page-header">
<h1>{SITENAME}</h1>
@@ -21,7 +21,7 @@
<h2>{L_PRIVATE_MESSAGING}</h2>
</div>
- <div id="page-body">
+ <div id="page-body" class="page-body">
<div class="page-number">{PAGE_NUMBER}</div>
<div class="post">
<h3>{SUBJECT}</h3>
@@ -39,7 +39,7 @@
<hr />
</div>
- <div id="page-footer">
+ <div id="page-footer" class="page-footer">
<div class="page-number">{S_TIMEZONE}<br />{PAGE_NUMBER}</div>
<div class="copyright">Powered by phpBB&reg; Forum Software &copy; phpBB Limited<br />https://www.phpbb.com/</div>
</div>
diff --git a/phpBB/styles/prosilver/template/ucp_prefs_post.html b/phpBB/styles/prosilver/template/ucp_prefs_post.html
index 891e49af6f..169d41bf72 100644
--- a/phpBB/styles/prosilver/template/ucp_prefs_post.html
+++ b/phpBB/styles/prosilver/template/ucp_prefs_post.html
@@ -12,39 +12,39 @@
<dl>
<dt><label for="bbcode1">{L_DEFAULT_BBCODE}{L_COLON}</label></dt>
<dd>
- <label for="bbcode1"><input type="radio" name="bbcode" id="bbcode1" value="1"<!-- IF S_BBCODE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="bbcode1"><input type="radio" name="bbcode" id="bbcode1" value="1"<!-- IF S_BBCODE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="bbcode0"><input type="radio" name="bbcode" id="bbcode0" value="0"<!-- IF not S_BBCODE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="smilies1">{L_DEFAULT_SMILIES}{L_COLON}</label></dt>
<dd>
- <label for="smilies1"><input type="radio" name="smilies" id="smilies1" value="1"<!-- IF S_SMILIES --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="smilies1"><input type="radio" name="smilies" id="smilies1" value="1"<!-- IF S_SMILIES --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="smilies0"><input type="radio" name="smilies" id="smilies0" value="0"<!-- IF not S_SMILIES --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="sig1">{L_DEFAULT_ADD_SIG}{L_COLON}</label></dt>
<dd>
- <label for="sig1"><input type="radio" name="sig" id="sig1" value="1"<!-- IF S_SIG --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="sig1"><input type="radio" name="sig" id="sig1" value="1"<!-- IF S_SIG --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="sig0"><input type="radio" name="sig" id="sig0" value="0"<!-- IF not S_SIG --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="notify1">{L_DEFAULT_NOTIFY}{L_COLON}</label></dt>
<dd>
- <label for="notify1"><input type="radio" name="notify" id="notify1" value="1"<!-- IF S_NOTIFY --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="notify1"><input type="radio" name="notify" id="notify1" value="1"<!-- IF S_NOTIFY --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="notify0"><input type="radio" name="notify" id="notify0" value="0"<!-- IF not S_NOTIFY --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<!-- EVENT ucp_prefs_post_append -->
</fieldset>
-
+
</div>
</div>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="submit" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/ucp_prefs_view.html b/phpBB/styles/prosilver/template/ucp_prefs_view.html
index 7f8d0a344c..4b7142fbea 100644
--- a/phpBB/styles/prosilver/template/ucp_prefs_view.html
+++ b/phpBB/styles/prosilver/template/ucp_prefs_view.html
@@ -13,35 +13,35 @@
<dl>
<dt><label for="images1">{L_VIEW_IMAGES}{L_COLON}</label></dt>
<dd>
- <label for="images1"><input type="radio" name="images" id="images1" value="1"<!-- IF S_IMAGES --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="images1"><input type="radio" name="images" id="images1" value="1"<!-- IF S_IMAGES --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="images0"><input type="radio" name="images" id="images0" value="0"<!-- IF not S_IMAGES --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="flash0">{L_VIEW_FLASH}{L_COLON}</label></dt>
<dd>
- <label for="flash1"><input type="radio" name="flash" id="flash1" value="1"<!-- IF S_FLASH --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="flash1"><input type="radio" name="flash" id="flash1" value="1"<!-- IF S_FLASH --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="flash0"><input type="radio" name="flash" id="flash0" value="0"<!-- IF not S_FLASH --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="smilies1">{L_VIEW_SMILIES}{L_COLON}</label></dt>
<dd>
- <label for="smilies1"><input type="radio" name="smilies" id="smilies1" value="1"<!-- IF S_SMILIES --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="smilies1"><input type="radio" name="smilies" id="smilies1" value="1"<!-- IF S_SMILIES --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="smilies0"><input type="radio" name="smilies" id="smilies0" value="0"<!-- IF not S_SMILIES --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="sigs1">{L_VIEW_SIGS}{L_COLON}</label></dt>
<dd>
- <label for="sigs1"><input type="radio" name="sigs" id="sigs1" value="1"<!-- IF S_SIGS --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="sigs1"><input type="radio" name="sigs" id="sigs1" value="1"<!-- IF S_SIGS --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="sigs0"><input type="radio" name="sigs" id="sigs0" value="0"<!-- IF not S_SIGS --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
<dl>
<dt><label for="avatars1">{L_VIEW_AVATARS}{L_COLON}</label></dt>
<dd>
- <label for="avatars1"><input type="radio" name="avatars" id="avatars1" value="1"<!-- IF S_AVATARS --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="avatars1"><input type="radio" name="avatars" id="avatars1" value="1"<!-- IF S_AVATARS --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="avatars0"><input type="radio" name="avatars" id="avatars0" value="0"<!-- IF not S_AVATARS --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
@@ -49,7 +49,7 @@
<dl>
<dt><label for="wordcensor1">{L_DISABLE_CENSORS}{L_COLON}</label></dt>
<dd>
- <label for="wordcensor1"><input type="radio" name="wordcensor" id="wordcensor1" value="1"<!-- IF S_DISABLE_CENSORS --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
+ <label for="wordcensor1"><input type="radio" name="wordcensor" id="wordcensor1" value="1"<!-- IF S_DISABLE_CENSORS --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label for="wordcensor0"><input type="radio" name="wordcensor" id="wordcensor0" value="0"<!-- IF not S_DISABLE_CENSORS --> checked="checked"<!-- ENDIF --> /> {L_NO}</label>
</dd>
</dl>
@@ -89,7 +89,7 @@
</div>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="submit" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/ucp_profile_reg_details.html b/phpBB/styles/prosilver/template/ucp_profile_reg_details.html
index 462a7f8f20..f62d3cf37d 100644
--- a/phpBB/styles/prosilver/template/ucp_profile_reg_details.html
+++ b/phpBB/styles/prosilver/template/ucp_profile_reg_details.html
@@ -31,7 +31,7 @@
<dd><input type="password" name="password_confirm" id="password_confirm" maxlength="255" value="{PASSWORD_CONFIRM}" class="inputbox" title="{L_CONFIRM_PASSWORD}" autocomplete="off" /></dd>
</dl>
<!-- ENDIF -->
- <!-- EVENT ucp_profile_register_details_after -->
+ <!-- EVENT ucp_profile_register_details_after -->
</fieldset>
</div>
</div>
diff --git a/phpBB/styles/prosilver/template/ucp_zebra_foes.html b/phpBB/styles/prosilver/template/ucp_zebra_foes.html
index 712479dc18..2a0f6e0dea 100644
--- a/phpBB/styles/prosilver/template/ucp_zebra_foes.html
+++ b/phpBB/styles/prosilver/template/ucp_zebra_foes.html
@@ -32,7 +32,7 @@
</div>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="submit" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/ucp_zebra_friends.html b/phpBB/styles/prosilver/template/ucp_zebra_friends.html
index fac0a18706..e584d876b8 100644
--- a/phpBB/styles/prosilver/template/ucp_zebra_friends.html
+++ b/phpBB/styles/prosilver/template/ucp_zebra_friends.html
@@ -34,7 +34,7 @@
</div>
<fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
+ {S_HIDDEN_FIELDS}<input type="reset" value="{L_RESET}" name="reset" class="button2" />&nbsp;
<input type="submit" name="submit" value="{L_SUBMIT}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html
index 643b78823f..9824989687 100644
--- a/phpBB/styles/prosilver/template/viewforum_body.html
+++ b/phpBB/styles/prosilver/template/viewforum_body.html
@@ -35,18 +35,19 @@
<!-- ENDIF -->
<!-- IF S_DISPLAY_POST_INFO or .pagination or TOTAL_POSTS or TOTAL_TOPICS -->
- <div class="action-bar top">
+ <div class="action-bar bar-top">
<!-- IF not S_IS_BOT and S_DISPLAY_POST_INFO -->
- <div class="buttons">
<!-- EVENT viewforum_buttons_top_before -->
- <a href="{U_POST_NEW_TOPIC}" class="button icon-button <!-- IF S_IS_LOCKED -->locked-icon<!-- ELSE -->post-icon<!-- ENDIF -->" title="<!-- IF S_IS_LOCKED -->{L_FORUM_LOCKED}<!-- ELSE -->{L_POST_TOPIC}<!-- ENDIF -->">
- <!-- IF S_IS_LOCKED -->{L_BUTTON_FORUM_LOCKED}<!-- ELSE -->{L_BUTTON_NEW_TOPIC}<!-- ENDIF -->
- </a>
-
+ <a href="{U_POST_NEW_TOPIC}" class="button" title="<!-- IF S_IS_LOCKED -->{L_FORUM_LOCKED}<!-- ELSE -->{L_POST_TOPIC}<!-- ENDIF -->">
+ <!-- IF S_IS_LOCKED -->
+ <span>{L_BUTTON_FORUM_LOCKED}</span> <i class="icon fa-lock fa-fw" aria-hidden="true"></i>
+ <!-- ELSE -->
+ <span>{L_BUTTON_NEW_TOPIC}</span> <i class="icon fa-pencil fa-fw" aria-hidden="true"></i>
+ <!-- ENDIF -->
+ </a>
<!-- EVENT viewforum_buttons_top_after -->
- </div>
<!-- ENDIF -->
<!-- IF S_DISPLAY_SEARCHBOX -->
@@ -54,8 +55,12 @@
<form method="get" id="forum-search" action="{S_SEARCHBOX_ACTION}">
<fieldset>
<input class="inputbox search tiny" type="search" name="keywords" id="search_keywords" size="20" placeholder="{L_SEARCH_FORUM}" />
- <button class="button icon-button search-icon" type="submit" title="{L_SEARCH}">{L_SEARCH}</button>
- <a href="{U_SEARCH}" class="button icon-button search-adv-icon" title="{L_SEARCH_ADV}">{L_SEARCH_ADV}</a>
+ <button class="button button-search" type="submit" title="{L_SEARCH}">
+ <i class="icon fa-search fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH}</span>
+ </button>
+ <a href="{U_SEARCH}" class="button button-search-end" title="{L_SEARCH_ADV}">
+ <i class="icon fa-cog fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH_ADV}</span>
+ </a>
{S_SEARCH_LOCAL_HIDDEN_FIELDS}
</fieldset>
</form>
@@ -136,7 +141,7 @@
<div class="inner">
<ul class="topiclist">
<li class="header">
- <dl class="icon">
+ <dl class="row-item">
<dt<!-- IF S_DISPLAY_ACTIVE --> id="active_topics"<!-- ENDIF -->><div class="list-inner"><!-- IF S_DISPLAY_ACTIVE -->{L_ACTIVE_TOPICS}<!-- ELSEIF topicrow.S_TOPIC_TYPE_SWITCH and (topicrow.S_POST_ANNOUNCE or topicrow.S_POST_GLOBAL) -->{L_ANNOUNCEMENTS}<!-- ELSE -->{L_TOPICS}<!-- ENDIF --></div></dt>
<dd class="posts">{L_REPLIES}</dd>
<dd class="views">{L_VIEWS}</dd>
@@ -150,16 +155,35 @@
<!-- EVENT viewforum_body_topicrow_row_before -->
<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="icon {topicrow.TOPIC_IMG_STYLE}">
+ <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}">
- <!-- IF topicrow.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{topicrow.U_NEWEST_POST}" class="icon-link"></a><!-- ENDIF -->
+ <!-- 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 -->
- <!-- IF topicrow.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --><a href="{topicrow.U_MCP_QUEUE}">{topicrow.UNAPPROVED_IMG}</a> <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_DELETED --><a href="{topicrow.U_MCP_QUEUE}">{DELETED_IMG}</a> <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED --><a href="{topicrow.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- ENDIF --><br />
+ <!-- IF topicrow.S_UNREAD_TOPIC and not S_IS_BOT -->
+ <a class="unread" href="{topicrow.U_NEWEST_POST}">
+ <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.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>
+ <!-- ENDIF -->
+ <!-- IF topicrow.S_TOPIC_DELETED -->
+ <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_DELETED}">
+ <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_DELETED}</span>
+ </a>
+ <!-- ENDIF -->
+ <!-- IF topicrow.S_TOPIC_REPORTED -->
+ <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}">
+ <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span>
+ </a>
+ <!-- ENDIF -->
+ <br />
<!-- EVENT topiclist_row_topic_title_after -->
+
<!-- IF not S_IS_BOT -->
<div class="responsive-show" style="display: none;">
{L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} &laquo; <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{topicrow.LAST_POST_TIME}</a>
@@ -168,35 +192,43 @@
<!-- IF topicrow.REPLIES --><span class="responsive-show left-box" style="display: none;">{L_REPLIES}{L_COLON} <strong>{topicrow.REPLIES}</strong></span><!-- ENDIF -->
<!-- ENDIF -->
+ <div class="responsive-hide">
+ <!-- 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} &raquo; {topicrow.FIRST_POST_TIME}
+ <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --> &raquo; {L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a><!-- ENDIF -->
+ </div>
+
<!-- IF .topicrow.pagination -->
<div class="pagination">
+ <span><i class="icon fa-clone fa-fw" aria-hidden="true"></i></span>
<ul>
<!-- BEGIN pagination -->
<!-- IF topicrow.pagination.S_IS_PREV -->
<!-- ELSEIF topicrow.pagination.S_IS_CURRENT --><li class="active"><span>{topicrow.pagination.PAGE_NUMBER}</span></li>
<!-- ELSEIF topicrow.pagination.S_IS_ELLIPSIS --><li class="ellipsis"><span>{L_ELLIPSIS}</span></li>
<!-- ELSEIF topicrow.pagination.S_IS_NEXT -->
- <!-- ELSE --><li><a href="{topicrow.pagination.PAGE_URL}">{topicrow.pagination.PAGE_NUMBER}</a></li>
+ <!-- ELSE --><li><a class="button" href="{topicrow.pagination.PAGE_URL}">{topicrow.pagination.PAGE_NUMBER}</a></li>
<!-- ENDIF -->
<!-- END pagination -->
</ul>
</div>
<!-- ENDIF -->
- <div class="responsive-hide">
- <!-- IF topicrow.S_HAS_POLL -->{POLL_IMG} <!-- ENDIF -->
- <!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- ENDIF -->
- {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} &raquo; {topicrow.FIRST_POST_TIME}
- <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --> &raquo; {L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a><!-- ENDIF -->
- </div>
-
<!-- EVENT topiclist_row_append -->
</div>
</dt>
<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 --><a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}">{LAST_POST_IMG}</a> <!-- ENDIF --><br />{topicrow.LAST_POST_TIME}</span>
+ <dd class="lastpost">
+ <span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}
+ <!-- IF not S_IS_BOT -->
+ <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>
+ <!-- ENDIF -->
+ <br />{topicrow.LAST_POST_TIME}
+ </span>
</dd>
</dl>
<!-- EVENT viewforum_body_topic_row_append -->
@@ -219,32 +251,26 @@
<!-- ENDIF -->
<!-- END topicrow -->
-<!-- IF S_SELECT_SORT_DAYS and not S_DISPLAY_ACTIVE -->
- <form method="post" action="{S_FORUM_ACTION}">
- <fieldset class="display-options">
- <!-- IF not S_IS_BOT -->
- <label>{L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <!-- ENDIF -->
- </fieldset>
- </form>
- <hr />
-<!-- ENDIF -->
-
<!-- IF .topicrow and not S_DISPLAY_ACTIVE -->
- <div class="action-bar bottom">
+ <div class="action-bar bar-bottom">
<!-- IF not S_IS_BOT and S_DISPLAY_POST_INFO -->
- <div class="buttons">
- <!-- EVENT viewforum_buttons_bottom_before -->
+ <!-- EVENT viewforum_buttons_bottom_before -->
- <a href="{U_POST_NEW_TOPIC}" class="button icon-button <!-- IF S_IS_LOCKED -->locked-icon<!-- ELSE -->post-icon<!-- ENDIF -->" title="<!-- IF S_IS_LOCKED -->{L_FORUM_LOCKED}<!-- ELSE -->{L_POST_TOPIC}<!-- ENDIF -->">
- <!-- IF S_IS_LOCKED -->{L_BUTTON_FORUM_LOCKED}<!-- ELSE -->{L_BUTTON_NEW_TOPIC}<!-- ENDIF -->
- </a>
+ <a href="{U_POST_NEW_TOPIC}" class="button" title="<!-- IF S_IS_LOCKED -->{L_FORUM_LOCKED}<!-- ELSE -->{L_POST_TOPIC}<!-- ENDIF -->">
+ <!-- IF S_IS_LOCKED -->
+ <span>{L_BUTTON_FORUM_LOCKED}</span> <i class="icon fa-lock fa-fw" aria-hidden="true"></i>
+ <!-- ELSE -->
+ <span>{L_BUTTON_NEW_TOPIC}</span> <i class="icon fa-pencil fa-fw" aria-hidden="true"></i>
+ <!-- ENDIF -->
+ </a>
- <!-- EVENT viewforum_buttons_bottom_after -->
- </div>
+ <!-- EVENT viewforum_buttons_bottom_after -->
+ <!-- ENDIF -->
+
+ <!-- IF S_SELECT_SORT_DAYS and not S_IS_BOT -->
+ <form method="post" action="{S_FORUM_ACTION}">
+ <!-- INCLUDE display_options.html -->
+ </form>
<!-- ENDIF -->
<div class="pagination">
diff --git a/phpBB/styles/prosilver/template/viewonline_body.html b/phpBB/styles/prosilver/template/viewonline_body.html
index ee1672c6c9..dd0ca72502 100644
--- a/phpBB/styles/prosilver/template/viewonline_body.html
+++ b/phpBB/styles/prosilver/template/viewonline_body.html
@@ -3,11 +3,11 @@
<h2 class="viewonline-title">{TOTAL_REGISTERED_USERS_ONLINE}</h2>
<p>{TOTAL_GUEST_USERS_ONLINE}<!-- IF S_SWITCH_GUEST_DISPLAY --> &bull; <a href="{U_SWITCH_GUEST_DISPLAY}">{L_SWITCH_GUEST_DISPLAY}</a><!-- ENDIF --></p>
-<div class="action-bar top">
+<div class="action-bar bar-top">
<div class="pagination">
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
{PAGE_NUMBER}
<!-- ENDIF -->
</div>
@@ -15,7 +15,7 @@
<div class="forumbg forumbg-table">
<div class="inner">
-
+
<table class="table1">
<!-- IF .user_row -->
@@ -43,17 +43,17 @@
<!-- ENDIF -->
</tbody>
</table>
-
+
</div>
</div>
<!-- IF LEGEND --><p><em>{L_LEGEND}{L_COLON} {LEGEND}</em></p><!-- ENDIF -->
-<div class="action-bar bottom">
+<div class="action-bar bar-bottom">
<div class="pagination">
- <!-- IF .pagination -->
+ <!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
- <!-- ELSE -->
+ <!-- ELSE -->
{PAGE_NUMBER}
<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html
index d2a253bb77..522151cf7d 100644
--- a/phpBB/styles/prosilver/template/viewtopic_body.html
+++ b/phpBB/styles/prosilver/template/viewtopic_body.html
@@ -26,20 +26,20 @@
</div>
<!-- ENDIF -->
-<div class="action-bar top">
-
- <div class="buttons">
- <!-- EVENT viewtopic_buttons_top_before -->
+<div class="action-bar bar-top">
+ <!-- EVENT viewtopic_buttons_top_before -->
<!-- IF not S_IS_BOT and S_DISPLAY_REPLY_INFO -->
- <a href="{U_POST_REPLY_TOPIC}" class="button icon-button <!-- IF S_IS_LOCKED -->locked-icon<!-- ELSE -->reply-icon<!-- ENDIF -->" title="<!-- IF S_IS_LOCKED -->{L_TOPIC_LOCKED}<!-- ELSE -->{L_POST_REPLY}<!-- ENDIF -->">
- <!-- IF S_IS_LOCKED -->{L_BUTTON_TOPIC_LOCKED}<!-- ELSE -->{L_BUTTON_POST_REPLY}<!-- ENDIF -->
+ <a href="{U_POST_REPLY_TOPIC}" class="button" title="<!-- IF S_IS_LOCKED -->{L_TOPIC_LOCKED}<!-- ELSE -->{L_POST_REPLY}<!-- ENDIF -->">
+ <!-- IF S_IS_LOCKED -->
+ <span>{L_BUTTON_TOPIC_LOCKED}</span> <i class="icon fa-lock fa-fw" aria-hidden="true"></i>
+ <!-- ELSE -->
+ <span>{L_BUTTON_POST_REPLY}</span> <i class="icon fa-reply fa-fw" aria-hidden="true"></i>
+ <!-- ENDIF -->
</a>
<!-- ENDIF -->
- <!-- EVENT viewtopic_buttons_top_after -->
- </div>
-
+ <!-- EVENT viewtopic_buttons_top_after -->
<!-- INCLUDE viewtopic_topic_tools.html -->
<!-- EVENT viewtopic_dropdown_top_custom -->
@@ -48,8 +48,12 @@
<form method="get" id="topic-search" action="{S_SEARCHBOX_ACTION}">
<fieldset>
<input class="inputbox search tiny" type="search" name="keywords" id="search_keywords" size="20" placeholder="{L_SEARCH_TOPIC}" />
- <button class="button icon-button search-icon" type="submit" title="{L_SEARCH}">{L_SEARCH}</button>
- <a href="{U_SEARCH}" class="button icon-button search-adv-icon" title="{L_SEARCH_ADV}">{L_SEARCH_ADV}</a>
+ <button class="button button-search" type="submit" title="{L_SEARCH}">
+ <i class="icon fa-search fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH}</span>
+ </button>
+ <a href="{U_SEARCH}" class="button button-search-end" title="{L_SEARCH_ADV}">
+ <i class="icon fa-cog fa-fw" aria-hidden="true"></i><span class="sr-only">{L_SEARCH_ADV}</span>
+ </a>
{S_SEARCH_LOCAL_HIDDEN_FIELDS}
</fieldset>
</form>
@@ -174,8 +178,10 @@
<dd class="profile-contact">
<strong>{L_CONTACT}{L_COLON}</strong>
<div class="dropdown-container dropdown-left">
- <a href="#" class="dropdown-trigger"><span class="imageset icon_contact" title="{postrow.CONTACT_USER}">{postrow.CONTACT_USER}</span></a>
- <div class="dropdown hidden">
+ <a href="#" class="dropdown-trigger" title="{postrow.CONTACT_USER}">
+ <i class="icon fa-commenting-o fa-fw icon-lg" aria-hidden="true"></i><span class="sr-only">{postrow.CONTACT_USER}</span>
+ </a>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<div class="dropdown-contents contact-icons">
<!-- BEGIN contact -->
@@ -217,7 +223,7 @@
<div id="post_content{postrow.POST_ID}"<!-- IF postrow.S_POST_HIDDEN --> style="display: none;"<!-- ENDIF -->>
<!-- EVENT viewtopic_body_post_subject_before -->
- <h3 <!-- IF postrow.S_FIRST_ROW -->class="first"<!-- ENDIF -->><!-- IF postrow.POST_ICON_IMG --><img src="{T_ICONS_PATH}{postrow.POST_ICON_IMG}" width="{postrow.POST_ICON_IMG_WIDTH}" height="{postrow.POST_ICON_IMG_HEIGHT}" alt="" /> <!-- ENDIF --><a href="#p{postrow.POST_ID}">{postrow.POST_SUBJECT}</a></h3>
+ <h3 <!-- IF postrow.S_FIRST_ROW -->class="first"<!-- ENDIF -->><!-- IF postrow.POST_ICON_IMG --><img src="{T_ICONS_PATH}{postrow.POST_ICON_IMG}" width="{postrow.POST_ICON_IMG_WIDTH}" height="{postrow.POST_ICON_IMG_HEIGHT}" alt="{postrow.POST_ICON_IMG_ALT}" title="{postrow.POST_ICON_IMG_ALT}" /> <!-- ENDIF --><a href="#p{postrow.POST_ID}">{postrow.POST_SUBJECT}</a></h3>
<!-- DEFINE $SHOW_POST_BUTTONS = (postrow.U_EDIT or postrow.U_DELETE or postrow.U_REPORT or postrow.U_WARN or postrow.U_INFO or postrow.U_QUOTE) -->
<!-- EVENT viewtopic_body_post_buttons_list_before -->
@@ -227,32 +233,44 @@
<!-- EVENT viewtopic_body_post_buttons_before -->
<!-- IF postrow.U_EDIT -->
<li>
- <a href="{postrow.U_EDIT}" title="{L_EDIT_POST}" class="button icon-button edit-icon"><span>{L_BUTTON_EDIT}</span></a>
+ <a href="{postrow.U_EDIT}" title="{L_EDIT_POST}" class="button button-icon-only">
+ <i class="icon fa-pencil fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_EDIT}</span>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF postrow.U_DELETE -->
<li>
- <a href="{postrow.U_DELETE}" title="{L_DELETE_POST}" class="button icon-button delete-icon"><span>{L_DELETE_POST}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF postrow.U_REPORT -->
<li>
- <a href="{postrow.U_REPORT}" title="{L_REPORT_POST}" class="button icon-button report-icon"><span>{L_REPORT_POST}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF postrow.U_WARN -->
<li>
- <a href="{postrow.U_WARN}" title="{L_WARN_USER}" class="button icon-button warn-icon"><span>{L_WARN_USER}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF postrow.U_INFO -->
<li>
- <a href="{postrow.U_INFO}" title="{L_INFORMATION}" class="button icon-button info-icon"><span>{L_INFORMATION}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF postrow.U_QUOTE -->
<li>
- <a href="{postrow.U_QUOTE}" title="{L_REPLY_WITH_QUOTE}" class="button icon-button quote-icon"><span>{L_QUOTE}</span></a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- EVENT viewtopic_body_post_buttons_after -->
@@ -262,12 +280,22 @@
<!-- EVENT viewtopic_body_post_buttons_list_after -->
<!-- EVENT viewtopic_body_postrow_post_details_before -->
- <p class="author"><!-- IF S_IS_BOT -->{postrow.MINI_POST_IMG}<!-- ELSE --><a href="{postrow.U_MINI_POST}">{postrow.MINI_POST_IMG}</a><!-- ENDIF --><span class="responsive-hide">{L_POST_BY_AUTHOR} <strong>{postrow.POST_AUTHOR_FULL}</strong> &raquo; </span>{postrow.POST_DATE} </p>
+ <p class="author">
+ <!-- IF S_IS_BOT -->
+ <span><i class="icon fa-file fa-fw <!-- IF postrow.S_UNREAD_POST -->icon-red<!-- ELSE -->icon-lightgray<!-- ENDIF --> icon-md" aria-hidden="true"></i><span class="sr-only">{postrow.MINI_POST}</span></span>
+ <!-- ELSE -->
+ <a class="unread" href="{postrow.U_MINI_POST}" title="{postrow.MINI_POST}">
+ <i class="icon fa-file fa-fw <!-- IF postrow.S_UNREAD_POST -->icon-red<!-- ELSE -->icon-lightgray<!-- ENDIF --> icon-md" aria-hidden="true"></i><span class="sr-only">{postrow.MINI_POST}</span>
+ </a>
+ <!-- ENDIF -->
+ <span class="responsive-hide">{L_POST_BY_AUTHOR} <strong>{postrow.POST_AUTHOR_FULL}</strong> &raquo; </span>{postrow.POST_DATE}
+ </p>
<!-- EVENT viewtopic_body_postrow_post_details_after -->
<!-- IF postrow.S_POST_UNAPPROVED -->
<form method="post" class="mcp_approve" action="{postrow.U_APPROVE_ACTION}">
<p class="post-notice unapproved">
+ <span><i class="icon fa-question icon-red fa-fw" aria-hidden="true"></i></span>
<strong>{L_POST_UNAPPROVED_ACTION}</strong>
<input class="button2" type="submit" value="{L_DISAPPROVE}" name="action[disapprove]" />
<input class="button1" type="submit" value="{L_APPROVE}" name="action[approve]" />
@@ -291,7 +319,7 @@
<!-- IF postrow.S_POST_REPORTED -->
<p class="post-notice reported">
- <a href="{postrow.U_MCP_REPORT}"><strong>{L_POST_REPORTED}</strong></a>
+ <a href="{postrow.U_MCP_REPORT}"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><strong>{L_POST_REPORTED}</strong></a>
</p>
<!-- ENDIF -->
@@ -332,7 +360,14 @@
</div>
<!-- EVENT viewtopic_body_postrow_back2top_before -->
- <div class="back2top"><!-- EVENT viewtopic_body_postrow_back2top_prepend --><a href="#top" class="top" title="{L_BACK_TO_TOP}">{L_BACK_TO_TOP}</a><!-- EVENT viewtopic_body_postrow_back2top_append --></div>
+ <div class="back2top">
+ <!-- EVENT viewtopic_body_postrow_back2top_prepend -->
+ <a href="#top" class="top" title="{L_BACK_TO_TOP}">
+ <i class="icon fa-chevron-circle-up fa-fw icon-gray" aria-hidden="true"></i>
+ <span class="sr-only">{L_BACK_TO_TOP}</span>
+ </a>
+ <!-- EVENT viewtopic_body_postrow_back2top_append -->
+ </div>
<!-- EVENT viewtopic_body_postrow_back2top_after -->
</div>
@@ -346,39 +381,36 @@
<!-- INCLUDE quickreply_editor.html -->
<!-- ENDIF -->
-<!-- IF S_NUM_POSTS > 1 or .pagination -->
- <form id="viewtopic" method="post" action="{S_TOPIC_ACTION}">
- <fieldset class="display-options" style="margin-top: 0; ">
- <!-- IF not S_IS_BOT -->
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <!-- ENDIF -->
- </fieldset>
- </form>
- <hr />
-<!-- ENDIF -->
-
<!-- EVENT viewtopic_body_topic_actions_before -->
-<div class="action-bar bottom">
- <div class="buttons">
- <!-- EVENT viewtopic_buttons_bottom_before -->
+ <div class="action-bar bar-bottom">
+ <!-- EVENT viewtopic_buttons_bottom_before -->
<!-- IF not S_IS_BOT and S_DISPLAY_REPLY_INFO -->
- <a href="{U_POST_REPLY_TOPIC}" class="button icon-button <!-- IF S_IS_LOCKED -->locked-icon<!-- ELSE -->reply-icon<!-- ENDIF -->" title="<!-- IF S_IS_LOCKED -->{L_TOPIC_LOCKED}<!-- ELSE -->{L_POST_REPLY}<!-- ENDIF -->">
- <!-- IF S_IS_LOCKED -->{L_BUTTON_TOPIC_LOCKED}<!-- ELSE -->{L_BUTTON_POST_REPLY}<!-- ENDIF -->
+ <a href="{U_POST_REPLY_TOPIC}" class="button" title="<!-- IF S_IS_LOCKED -->{L_TOPIC_LOCKED}<!-- ELSE -->{L_POST_REPLY}<!-- ENDIF -->">
+ <!-- IF S_IS_LOCKED -->
+ <span>{L_BUTTON_TOPIC_LOCKED}</span> <i class="icon fa-lock fa-fw" aria-hidden="true"></i>
+ <!-- ELSE -->
+ <span>{L_BUTTON_POST_REPLY}</span> <i class="icon fa-reply fa-fw" aria-hidden="true"></i>
+ <!-- ENDIF -->
</a>
<!-- ENDIF -->
-
- <!-- EVENT viewtopic_buttons_bottom_after -->
- </div>
+ <!-- EVENT viewtopic_buttons_bottom_after -->
<!-- INCLUDE viewtopic_topic_tools.html -->
+ <!-- IF (S_NUM_POSTS > 1 or .pagination) and not S_IS_BOT -->
+ <form method="post" action="{S_TOPIC_ACTION}">
+ <!-- INCLUDE display_options.html -->
+ </form>
+ <!-- ENDIF -->
+
<!-- IF .quickmod -->
- <div class="dropdown-container dropdown-container-{S_CONTENT_FLOW_BEGIN} dropdown-up dropdown-{S_CONTENT_FLOW_END} dropdown-button-control" id="quickmod">
- <span title="{L_QUICK_MOD}" class="dropdown-trigger button icon-button modtools-icon dropdown-select">{L_QUICK_MOD}</span>
- <div class="dropdown hidden">
+ <div class="quickmod dropdown-container dropdown-container-left dropdown-up dropdown-{S_CONTENT_FLOW_END} dropdown-button-control" id="quickmod">
+ <span title="{L_QUICK_MOD}" class="button button-secondary dropdown-trigger dropdown-select">
+ <i class="icon fa-gavel fa-fw" aria-hidden="true"></i><span class="sr-only">{L_QUICK_MOD}</span>
+ <span class="caret"><i class="icon fa-sort-down fa-fw" aria-hidden="true"></i></span>
+ </span>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents">
<!-- BEGIN quickmod -->
@@ -389,7 +421,7 @@
</div>
</div>
<!-- ENDIF -->
-
+
<!-- EVENT viewtopic_dropdown_bottom_custom -->
<!-- IF .pagination or TOTAL_POSTS -->
@@ -402,7 +434,6 @@
<!-- ENDIF -->
</div>
<!-- ENDIF -->
- <div class="clear"></div>
</div>
<!-- EVENT viewtopic_body_footer_before -->
diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html
index 919c9397e1..3c1ed4c3f1 100644
--- a/phpBB/styles/prosilver/template/viewtopic_print.html
+++ b/phpBB/styles/prosilver/template/viewtopic_print.html
@@ -11,8 +11,8 @@
<!-- EVENT viewtopic_print_head_append -->
</head>
<body id="phpbb">
-<div id="wrap">
- <a id="top" class="anchor" accesskey="t"></a>
+<div id="wrap" class="wrap">
+ <a id="top" class="top-anchor" accesskey="t"></a>
<div id="page-header">
<h1>{SITENAME}</h1>
@@ -22,7 +22,7 @@
<p><a href="{U_TOPIC}">{U_TOPIC}</a></p>
</div>
- <div id="page-body">
+ <div id="page-body" class="page-body">
<div class="page-number">{PAGE_NUMBER}</div>
<!-- BEGIN postrow -->
<div class="post">
@@ -35,7 +35,7 @@
<!-- END postrow -->
</div>
- <div id="page-footer">
+ <div id="page-footer" class="page-footer">
<div class="page-number">{S_TIMEZONE}<br />{PAGE_NUMBER}</div>
<div class="copyright">Powered by phpBB&reg; Forum Software &copy; phpBB Limited<br />https://www.phpbb.com/</div>
</div>
diff --git a/phpBB/styles/prosilver/template/viewtopic_topic_tools.html b/phpBB/styles/prosilver/template/viewtopic_topic_tools.html
index 8378e3bcf4..397c807bb3 100644
--- a/phpBB/styles/prosilver/template/viewtopic_topic_tools.html
+++ b/phpBB/styles/prosilver/template/viewtopic_topic_tools.html
@@ -1,23 +1,48 @@
<!-- IF not S_IS_BOT and (U_WATCH_TOPIC or U_BOOKMARK_TOPIC or U_BUMP_TOPIC or U_EMAIL_TOPIC or U_PRINT_TOPIC or S_DISPLAY_TOPIC_TOOLS) -->
<div class="dropdown-container dropdown-button-control topic-tools">
- <span title="{L_TOPIC_TOOLS}" class="button icon-button tools-icon dropdown-trigger dropdown-select"></span>
- <div class="dropdown hidden">
+ <span title="{L_TOPIC_TOOLS}" class="button button-secondary dropdown-trigger dropdown-select">
+ <i class="icon fa-wrench fa-fw" aria-hidden="true"></i>
+ <span class="caret"><i class="icon fa-sort-down fa-fw" aria-hidden="true"></i></span>
+ </span>
+ <div class="dropdown">
<div class="pointer"><div class="pointer-inner"></div></div>
<ul class="dropdown-contents">
<!-- EVENT viewtopic_topic_tools_before -->
<!-- IF U_WATCH_TOPIC -->
- <li class="small-icon icon-<!-- IF S_WATCHING_TOPIC -->unsubscribe<!-- ELSE -->subscribe<!-- ENDIF -->">
- <a href="{U_WATCH_TOPIC}" class="watch-topic-link" title="{S_WATCH_TOPIC_TITLE}" data-ajax="toggle_link" data-toggle-class="small-icon icon-<!-- IF not S_WATCHING_TOPIC -->unsubscribe<!-- ELSE -->subscribe<!-- ENDIF -->" data-toggle-text="{S_WATCH_TOPIC_TOGGLE}" data-toggle-url="{U_WATCH_TOPIC_TOGGLE}" data-update-all=".watch-topic-link">{S_WATCH_TOPIC_TITLE}</a>
+ <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>
+ </a>
</li>
<!-- ENDIF -->
<!-- IF U_BOOKMARK_TOPIC -->
- <li class="small-icon icon-bookmark">
- <a href="{U_BOOKMARK_TOPIC}" class="bookmark-link" title="{L_BOOKMARK_TOPIC}" data-ajax="alt_text" data-alt-text="{S_BOOKMARK_TOGGLE}" data-update-all=".bookmark-link">{S_BOOKMARK_TOPIC}</a>
+ <li>
+ <a href="{U_BOOKMARK_TOPIC}" class="bookmark-link" title="{L_BOOKMARK_TOPIC}" data-ajax="alt_text" data-alt-text="{S_BOOKMARK_TOGGLE}" data-update-all=".bookmark-link">
+ <i class="icon fa-bookmark-o fa-fw" aria-hidden="true"></i><span>{S_BOOKMARK_TOPIC}</span>
+ </a>
</li>
<!-- ENDIF -->
- <!-- IF U_BUMP_TOPIC --><li class="small-icon icon-bump"><a href="{U_BUMP_TOPIC}" title="{L_BUMP_TOPIC}" data-ajax="true">{L_BUMP_TOPIC}</a></li><!-- ENDIF -->
- <!-- IF U_EMAIL_TOPIC --><li class="small-icon icon-sendemail"><a href="{U_EMAIL_TOPIC}" title="{L_EMAIL_TOPIC}">{L_EMAIL_TOPIC}</a></li><!-- ENDIF -->
- <!-- IF U_PRINT_TOPIC --><li class="small-icon icon-print"><a href="{U_PRINT_TOPIC}" title="{L_PRINT_TOPIC}" accesskey="p">{L_PRINT_TOPIC}</a></li><!-- ENDIF -->
+ <!-- IF U_BUMP_TOPIC -->
+ <li>
+ <a href="{U_BUMP_TOPIC}" title="{L_BUMP_TOPIC}" data-ajax="true">
+ <i class="icon fa-level-up fa-fw" aria-hidden="true"></i><span>{L_BUMP_TOPIC}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
+ <!-- IF U_EMAIL_TOPIC -->
+ <li>
+ <a href="{U_EMAIL_TOPIC}" title="{L_EMAIL_TOPIC}">
+ <i class="icon fa-envelope-o fa-fw" aria-hidden="true"></i><span>{L_EMAIL_TOPIC}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
+ <!-- IF U_PRINT_TOPIC -->
+ <li>
+ <a href="{U_PRINT_TOPIC}" title="{L_PRINT_TOPIC}" accesskey="p">
+ <i class="icon fa-print fa-fw" aria-hidden="true"></i><span>{L_PRINT_TOPIC}</span>
+ </a>
+ </li>
+ <!-- ENDIF -->
<!-- EVENT viewtopic_topic_tools_after -->
</ul>
</div>
diff --git a/phpBB/styles/prosilver/theme/base.css b/phpBB/styles/prosilver/theme/base.css
new file mode 100644
index 0000000000..98c57d9264
--- /dev/null
+++ b/phpBB/styles/prosilver/theme/base.css
@@ -0,0 +1,115 @@
+/* --------------------------------------------------------------
+ $Base
+-------------------------------------------------------------- */
+
+/** {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+*:before,
+*:after {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}*/
+
+/* Define your base font-size here; most elements will inherit this. _NO__DOTCOMMA__AFTER__*/
+html {
+ font-size: 1em; /* Assuming 16px... */
+ line-height: 1.5; /* 24px (This is now our magic number; all subsequent margin-bottoms and line-heights want to be a multiple of this number in order to maintain vertical rhythm.) _NO__DOTCOMMA__AFTER__*/
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #333333;
+ background-color: #ffffff;
+}
+
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+
+figure { margin: 0 }
+img { vertical-align: middle }
+
+hr {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 0;
+ border-top: 1px solid #e5e5e5;
+}
+
+a {
+ color: #428bca;
+ text-decoration: none;
+}
+
+a:hover,
+a:focus,
+a:active {
+ color: #2a6496;
+ text-decoration: underline;
+}
+
+blockquote,
+dl,
+dd,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+figure,
+p,
+pre { margin: 0 }
+button {
+ background: transparent;
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Work around a Firefox/IE bug where the transparent `button` background
+ * results in a loss of the default `button` focus styles.
+ */
+button:focus {
+ outline: 1px dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+}
+
+fieldset {
+ border: 0;
+ margin: 0;
+ padding: 0;
+}
+
+iframe { border: 0 }
+ol,
+ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+/**
+ * Suppress the focus outline on links that cannot be accessed via keyboard.
+ * This prevents an unwanted focus outline from appearing around elements that
+ * might still respond to pointer events.
+ */
+[tabindex="-1"]:focus { outline: none !important }
+
+/**
+ * Remove double underline from recent version of firefox
+ */
+abbr[title] {
+ text-decoration: none;
+}
+
diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css
index f3468ebcf2..f09493ab3b 100644
--- a/phpBB/styles/prosilver/theme/bidi.css
+++ b/phpBB/styles/prosilver/theme/bidi.css
@@ -20,6 +20,11 @@
/* Main blocks
---------------------------------------- */
+.rtl .icon {
+ padding-right: 0;
+ padding-left: 2px;
+}
+
.rtl .logo {
float: right;
padding: 10px 10px 0 13px;
@@ -27,11 +32,11 @@
/* Site Description
--------------------------------------------- */
-.rtl #site-description {
+.rtl .site-description {
float: right;
}
-.rtl #site-description h1 {
+.rtl .site-description h1 {
margin-left: 0;
}
@@ -81,14 +86,9 @@
padding-right: 0;
}
-.rtl ul.linklist li.responsive-menu a.responsive-menu-link:before {
- left: auto;
- right: 0;
-}
-
/* Dropdown menu
---------------------------------------- */
-.rtl .dropdown-container.topic-tools {
+.rtl .dropdown-container.topic-tools, .rtl .dropdown-container-left {
float: right;
}
@@ -114,12 +114,12 @@
text-align: right;
}
-.rtl .dropdown-extended .header .header_settings {
+.rtl .dropdown-extended .header .header_settings, .rtl .dropdown-container-right {
float: left;
}
/* Notifications
-----------------------------------------*/
+-----------------------------------------*/
.rtl .notification_list ul li img {
float: right;
margin-left: 5px;
@@ -261,23 +261,27 @@
margin-right: 0;
}
-.pagination li.previous a { background-position: -50px 2px; }
-.pagination li.next a { background-position: -30px 2px; }
-.pagination li.previous a:hover { background-position: -50px -18px; }
-.pagination li.next a:hover { background-position: -30px -18px; }
-/* Miscellaneous styles
+/* Action Bar styles
---------------------------------------- */
-.rtl #forum-permissions {
- float: left;
- padding-right: 5px;
- padding-left: 0;
- margin-right: 5px;
- margin-left: 0;
- text-align: left;
+.rtl .action-bar .button {
+ margin-right: 0;
+ float: right;
+}
+
+.rtl .action-bar > .button {
+ margin-left: 5px;
+ float: right;
}
-.rtl #quick-links {
+.rtl .action-bar .dropdown-button-control .button {
+ margin-left: 5px;
+}
+
+
+/* Miscellaneous styles
+---------------------------------------- */
+.rtl .quick-links {
margin-left: 7px;
margin-right: 0;
}
@@ -296,11 +300,6 @@
* links.css
*/
-/* Back to top of page */
-.rtl .back2top {
- text-align: left;
-}
-
/* Links adjustment to correctly display an order of rtl/ltr mixed content */
.rtl a {
direction: rtl;
@@ -309,7 +308,6 @@
li.breadcrumbs span:first-child > a {
padding-left: 0;
- padding-right: 19px;
}
/* Notification mark read link */
@@ -319,14 +317,9 @@ li.breadcrumbs span:first-child > a {
right: auto;
}
-.rtl a.top {
+.rtl .back2top .top {
float: left;
-}
-
-.rtl a.top2 {
- background-position: 100% 50%;
- padding-left: 0;
- padding-right: 15px;
+ margin-left: -10px;
}
.rtl .skiplink {
@@ -416,26 +409,26 @@ li.breadcrumbs span:first-child > a {
padding-right: 1px;
}
-.rtl dl.icon {
+.rtl dl.row-item{
background-position: 99.5% 50%;
}
-.rtl li.header dl.icon dt .list-inner {
+.rtl li.header dl.row-item dt .list-inner {
/* Tweak for headers alignment when folder icon used */
padding-right: 0;
padding-left: 50px;
}
-.rtl dl.icon dt {
+.rtl dl.row-item dt {
background-position: 99.5% 95%; /* Position of topic icon */
}
-.rtl dl.icon dt .list-inner {
+.rtl dl.row-item dt .list-inner {
padding-left: 5px;
padding-right: 45px; /* Space for folder icon */
}
-.rtl dl a.icon-link { /* topic row icon links */
+.rtl dl a.row-item-link { /* topic row icon links */
display: inline-block;
left: auto;
right: 0;
@@ -461,7 +454,6 @@ li.breadcrumbs span:first-child > a {
.rtl p.post-notice {
padding-left: 5px;
- padding-right: 26px;
}
.rtl p.post-notice:before {
@@ -471,7 +463,7 @@ li.breadcrumbs span:first-child > a {
/* Topic review panel
----------------------------------------*/
-.rtl #topicreview {
+.rtl .topicreview {
padding-right: 0;
padding-left: 5px;
}
@@ -602,49 +594,12 @@ li.breadcrumbs span:first-child > a {
/**
* buttons.css
*/
-.rtl .dropdown-select {
- padding-left: 24px;
- padding-right: 8px;
-}
-
-.rtl .icon-button:before {
- float: left;
- margin-left: 0;
- margin-right: 2px;
-}
-
-.rtl .dropdown-select.icon-button:before {
- margin-left: 4px;
- margin-right: 0;
-}
-.rtl .dropdown-select:after {
- border-left: 0;
- border-right-style: solid;
- border-right-width: 1px;
- left: 0;
- right: auto;
-}
-
-.rtl .buttons, .rtl .buttons .button {
+.rtl .caret {
float: right;
}
-.rtl .buttons .button, .rtl .dropdown-select {
- margin-left: 5px;
- margin-right: 0;
-}
-
-/* Icon images
----------------------------------------- */
-.rtl .small-icon {
- background-position: 100% 50%;
-}
-.rtl .small-icon > a {
- padding-left: 0;
- padding-right: 19px;
-}
/* Post control buttons
--------------------------------------------- */
@@ -661,10 +616,6 @@ li.breadcrumbs span:first-child > a {
float: right;
}
-.post-buttons .icon-button:before {
- margin-right: 0;
-}
-
/* Poster contact icons
----------------------------------------*/
.rtl .contact-icons a {
@@ -687,20 +638,20 @@ li.breadcrumbs span:first-child > a {
/* Main CP box
----------------------------------------*/
-.rtl #cp-menu {
+.rtl .cp-menu {
float: right;
}
-.rtl #cp-main {
+.rtl .cp-main {
float: right;
}
-.rtl #cp-main .panel ol {
+.rtl .cp-main .panel ol {
margin-right: 2em;
margin-left: 0;
}
-.rtl #cp-main .buttons {
+.rtl .cp-main .buttons {
margin-right: 0;
margin-left: 0;
}
@@ -711,52 +662,52 @@ li.breadcrumbs span:first-child > a {
/* CP tabbed menu
----------------------------------------*/
-.rtl #tabs {
+.rtl .tabs {
margin-left: 0;
margin-right: 7px;
}
-.rtl #tabs .tab {
+.rtl .tabs .tab {
float: right;
}
-.rtl #tabs .tab > a {
+.rtl .tabs .tab > a {
margin-left: 1px;
margin-right: 0;
}
/* Mini tabbed menu used in MCP
----------------------------------------*/
-.rtl #minitabs {
+.rtl .minitabs {
float: left;
margin-right: 0;
margin-left: 7px;
}
-.rtl #minitabs .tab {
+.rtl .minitabs .tab {
float: left;
}
-.rtl #minitabs .tab > a {
+.rtl .minitabs .tab > a {
margin-right: 2px;
margin-left: 0;
}
/* Responsive tabs
----------------------------------------*/
-.rtl #tabs .dropdown {
+.rtl .tabs .dropdown {
margin-left: -2px;
}
-.rtl #tabs .dropdown li {
+.rtl .tabs .dropdown li {
text-align: left;
}
-.rtl #minitabs .dropdown {
+.rtl .minitabs .dropdown {
margin-left: -4px;
}
-.rtl #minitabs .dropdown li {
+.rtl .minitabs .dropdown li {
text-align: right;
}
@@ -764,7 +715,7 @@ li.breadcrumbs span:first-child > a {
----------------------------------------*/
@media only screen and (max-width: 900px), only screen and (max-device-width: 900px)
{
- .rtl #cp-menu, .rtl #navigation, .rtl #cp-main {
+ .rtl .cp-menu, .rtl .navigation, .rtl .cp-main {
float: none;
}
}
@@ -774,7 +725,7 @@ li.breadcrumbs span:first-child > a {
/* Preferences pane layout
----------------------------------------*/
-.rtl #cp-main h2 {
+.rtl .cp-main h2 {
margin-left: 0;
margin-right: 10px;
}
@@ -815,7 +766,7 @@ li.breadcrumbs span:first-child > a {
}
/* Avatar gallery */
-.rtl #gallery label {
+.rtl .gallery label {
float: right;
}
@@ -823,7 +774,7 @@ li.breadcrumbs span:first-child > a {
----------------------------------------*/
@media only screen and (max-width: 900px), only screen and (max-device-width: 900px)
{
- .rtl #cp-menu, .rtl #navigation, .rtl #cp-main {
+ .rtl .cp-menu, .rtl .navigation, .rtl .cp-main {
float: none;
}
}
@@ -910,6 +861,10 @@ li.breadcrumbs span:first-child > a {
padding-right: 0;
}
+.rtl .dropdown fieldset.display-options label {
+ text-align: left;
+}
+
/* Display actions for ucp and mcp pages */
.rtl fieldset.display-actions {
text-align: left;
@@ -935,7 +890,7 @@ li.breadcrumbs span:first-child > a {
----------------------------------------*/
/* Emoticons panel */
-.rtl #smiley-box {
+.rtl .smiley-box {
float: left;
}
@@ -955,16 +910,19 @@ li.breadcrumbs span:first-child > a {
padding: 3px;
}
-.rtl .search-box .button {
+.rtl .button-search,
+.button-search-end {
float: right;
}
-.rtl .search-box a.button {
+.button-search-end {
border-left-width: 1px;
border-right-width: 0;
+}
+
+.rtl .search-header .button-search-end {
+ border: 0;
border-radius: 4px 0 0 4px;
- padding-left: 5px;
- padding-right: 3px;
}
.rtl .search-header {
@@ -973,47 +931,14 @@ li.breadcrumbs span:first-child > a {
margin-left: 5px;
}
-.rtl input.search {
- background-position: right 1px;
- padding-right: 17px;
- padding-left: 0;
-}
-
-
/* Form button styles
---------------------------------------- */
/** Reference: Bug #27155 */
-.rtl #wrap, .rtl .headerbar, .rtl #site-description, .rtl .navbar {
+.rtl .wrap, .rtl .headerbar, .rtl .site-description, .rtl .navbar {
position: relative;
}
-/* Former imageset */
-.rtl .imageset.forum_link, .rtl .imageset.forum_read, .rtl .imageset.forum_read_locked, .rtl .imageset.forum_read_subforum, .rtl .imageset.forum_unread, .rtl .imageset.forum_unread_locked, .rtl .imageset.forum_unread_subforum, .rtl .imageset.topic_moved, .rtl .imageset.topic_read, .rtl .imageset.topic_read_mine, .rtl .imageset.topic_read_hot, .rtl .imageset.topic_read_hot_mine, .rtl .imageset.topic_read_locked, .rtl .imageset.topic_read_locked_mine, .rtl .imageset.topic_unread, .rtl .imageset.topic_unread_mine, .rtl .imageset.topic_unread_hot, .rtl .imageset.topic_unread_hot_mine, .rtl .imageset.topic_unread_locked, .rtl .imageset.topic_unread_locked_mine, .rtl .imageset.sticky_read, .rtl .imageset.sticky_read_mine, .rtl .imageset.sticky_read_locked, .rtl .imageset.sticky_read_locked_mine, .rtl .imageset.sticky_unread, .rtl .imageset.sticky_unread_mine, .rtl .imageset.sticky_unread_locked, .rtl .imageset.sticky_unread_locked_mine, .rtl .imageset.announce_read, .rtl .imageset.announce_read_mine, .rtl .imageset.announce_read_locked, .rtl .imageset.announce_read_locked_mine, .rtl .imageset.announce_unread, .rtl .imageset.announce_unread_mine, .rtl .imageset.announce_unread_locked, .rtl .imageset.announce_unread_locked_mine, .rtl .imageset.global_read, .rtl .imageset.global_read_mine, .rtl .imageset.global_read_locked, .rtl .imageset.global_read_locked_mine, .rtl .imageset.global_unread, .rtl .imageset.global_unread_mine, .rtl .imageset.global_unread_locked, .rtl .imageset.global_unread_locked_mine, .rtl .imageset.pm_read, .rtl .imageset.pm_unread {
- padding-right: 27px;
- padding-left: 0;
-}
-.rtl .imageset.subforum_read, .rtl .imageset.subforum_unread, .rtl .imageset.icon_post_target, .rtl .imageset.icon_post_target_unread, .rtl .imageset.icon_topic_latest, .rtl .imageset.icon_topic_newest {
- padding-right: 11px;
- padding-left: 0;
-}
-.rtl .imageset.icon_back_top {
- padding-right: 11px;
- padding-left: 0;
-}
-.rtl .imageset.icon_contact_aim, .rtl .imageset.phpbb_aol-icon, .rtl .imageset.icon_contact_email, .rtl .imageset.icon_contact_icq, .rtl .imageset.phpbb_icq-icon, .rtl .imageset.icon_contact_jabber, .rtl .imageset.icon_contact_msnm, .rtl .imageset.phpbb_wlm-icon, .rtl .imageset.icon_contact_www, .rtl .imageset.phpbb_website-icon, .rtl .imageset.icon_contact_yahoo, .rtl .imageset.phpbb_yahoo-icon, .rtl .imageset.icon_post_delete, .rtl .imageset.icon_post_info, .rtl .imageset.icon_post_report, .rtl .imageset.icon_user_warn {
- padding-right: 20px;
- padding-left: 0;
-}
-.rtl .imageset.icon_topic_attach {
- padding-right: 7px;
- padding-left: 0;
-}
-.rtl .imageset.icon_topic_reported, .rtl .imageset.icon_topic_unapproved {
- padding-right: 16px;
- padding-left: 0;
-}
-
/**
* plupload.css
*/
diff --git a/phpBB/styles/prosilver/theme/buttons.css b/phpBB/styles/prosilver/theme/buttons.css
index a816c7f7f2..4c8283fdc0 100644
--- a/phpBB/styles/prosilver/theme/buttons.css
+++ b/phpBB/styles/prosilver/theme/buttons.css
@@ -2,125 +2,71 @@
---------------------------------------- */
.button {
- cursor: pointer;
display: inline-block;
- height: 18px;
- font-size: 1.2em;
+ padding: 2px 8px;
+ font-size: 13px;
+ font-weight: normal;
+ font-family: "Open Sans", "Droid Sans", Verdana, Arial, Helvetica;
+ line-height: 1.4;
+ text-align: center;
white-space: nowrap;
+ vertical-align: middle;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
border: 1px solid transparent;
border-radius: 4px;
- background: transparent none 0 0 repeat-x;
- padding: 2px 8px;
- font-family: "Open Sans", "Droid Sans", Verdana, Arial, Helvetica;
- position: relative;
- text-decoration: none !important;
- outline-style: none !important;
- vertical-align: bottom;
}
-.dropdown-select {
- padding-right: 24px;
+.button:focus,
+.button:hover {
+ text-decoration: none;
+ outline: none;
}
-.icon-button:before {
- background: transparent 0 0 no-repeat;
- content: '';
- display: inline-block;
- float: right;
- height: 12px;
- margin: 3px 0 0 2px;
- width: 12px;
-}
-
-.dropdown-select.icon-button:before {
- margin-right: 4px;
-}
-
-.dropdown-select:after {
- background-position: -103px 10px;
+.caret {
border-left: 1px solid;
- content: '';
- position: absolute;
- top: 0;
- right: 0;
- height: 22px;
- width: 16px;
+ position: relative;
+ right: -6px;
}
-.dropdown-visible .dropdown-select:after, .nojs .dropdown-container:hover .dropdown-select:after {
- background-position: -103px -10px;
+.caret i {
+ vertical-align: top;
}
-.buttons, .buttons .button {
+/* Posting page styles
+----------------------------------------*/
+.button-search,
+.button-search-end {
float: left;
-}
-
-.buttons .button, .dropdown-select {
- margin-right: 5px;
-}
-
-#jumpbox .dropdown-select {
+ border-radius: 0;
margin: 0;
+ padding: 2px 5px;
}
-/* Big button images */
-.reply-icon:before, .pmreply-icon:before { background-position: -20px 0; }
-.reply-icon:hover:before, .pmreply-icon:hover:before { background-position: -20px -20px; }
-
-.post-icon:before, .newpm-icon:before, .reply-all:before { background-position: 0 0; }
-.post-icon:hover:before,
-.newpm-icon:hover:before,
-.reply-all:hover:before { background-position: 0 -20px; }
-
-.locked-icon:before { background-position: -60px 0; }
-.locked-icon:hover:before { background-position: -60px -20px; }
-
-.forwardpm-icon:before { background-position: -40px 0; }
-.forwardpm-icon:hover:before { background-position: -40px -20px; }
-
-.modtools-icon {
- font-size: 0;
+.button-search-end {
+ border-left-width: 0;
+ border-radius: 0 4px 4px 0;
}
-.tools-icon:before, .modtools-icon:before, .search-icon:before, .search-adv-icon:before {
- background-position: -80px 0;
- height: 16px;
- margin-top: 2px;
- width: 16px;
+.search-header .button-search,
+.search-header .button-search-end {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding: 3px 5px;
}
-.dropdown-visible .tools-icon:before,
-.nojs .dropdown-container:hover .tools-icon:before { background-position: -80px -20px; }
-
-.search-icon:before { background-position: -245px 0; }
-.search-icon:hover:before { background-position: -245px -20px; }
-
-.search-adv-icon:before { background-position: -265px 0; }
-.search-adv-icon:hover:before { background-position: -265px -20px; }
-
-.modtools-icon:before { background-position: -225px 0; }
-.dropdown-visible .modtools-icon:before,
-.nojs .dropdown-container:hover .modtools-icon:before { background-position: -225px -20px; }
-
-/* Icon images
----------------------------------------- */
-.small-icon {
- background-position: 0 50%;
- background-repeat: no-repeat;
- background-image: none;
+.search-header .button-search-end {
+ border-right-width: 0;
}
-.small-icon > a {
- display: inline-block;
- padding: 0 0 0 18px;
-}
-
-ul.linklist.bulletin > li.small-icon:before {
- display: none;
-}
-
-.dropdown .small-icon > a {
- display: block;
+.button-icon-only {
+ padding-left: 3px;
+ padding-right: 3px;
}
/* Poster contact icons
@@ -157,21 +103,6 @@ ul.linklist.bulletin > li.small-icon:before {
clear: left;
}
-/* Profile icons */
-.pm-icon { background-position: 0 0; }
-.email-icon { background-position: -21px 0; }
-.jabber-icon { background-position: -80px 0; }
-.phpbb_icq-icon { background-position: -61px 0 ; }
-.phpbb_wlm-icon { background-position: -182px 0; }
-.phpbb_aol-icon { background-position: -244px 0; }
-.phpbb_website-icon { background-position: -40px 0; }
-.phpbb_youtube-icon { background-position: -98px 0; }
-.phpbb_facebook-icon { background-position: -119px 0; }
-.phpbb_googleplus-icon { background-position: -140px 0; }
-.phpbb_skype-icon { background-position: -161px 0; }
-.phpbb_twitter-icon { background-position: -203px 0; }
-.phpbb_yahoo-icon { background-position: -224px 0; }
-
/* Post control buttons
--------------------------------------------- */
.post-buttons {
@@ -193,41 +124,19 @@ ul.linklist.bulletin > li.small-icon:before {
margin-right: 3px;
}
-.post-buttons .icon-button {
- padding: 0 5px;
+.post-buttons .button, .format-buttons .button {
+ padding-left: 3px;
+ padding-right: 3px;
}
-.hastouch .post-buttons .icon-button {
- padding: 2px 8px;
+.hastouch .post-buttons {
+ margin-right: 10px;
}
-.post-buttons .icon-button span {
- display: block;
- height: 0;
- overflow: hidden;
- position: absolute;
- width: 1px;
-}
-
-.post-buttons .icon-button:before {
- margin-left: 0;
+.post-buttons .button span {
+ font-size: 0;
}
-.quote-icon:before { background-position: -122px 0; }
-.quote-icon:hover:before { background-position: -122px -21px; }
-.edit-icon:before { background-position: -137px 0; }
-.edit-icon:hover:before { background-position: -137px -21px; }
-.warn-icon:before { background-position: -208px 0; }
-.warn-icon:hover:before { background-position: -208px -21px; }
-.delete-icon:before { background-position: -152px 0; }
-.delete-icon:hover:before { background-position: -152px -21px; }
-.report-icon:before { background-position: -165px 0; }
-.report-icon:hover:before { background-position: -165px -21px; }
-.info-icon:before { background-position: -175px 0; }
-.info-icon:hover:before { background-position: -175px -21px; }
-.button.responsive-menu-link:before { background-position: -191px 0; }
-.button.responsive-menu-link:hover:before { background-position: -191px -21px; }
-
/* Responsive buttons in post body */
.post-buttons .dropdown {
top: 18px;
@@ -248,3 +157,37 @@ button::-moz-focus-inner {
padding: 0;
border: 0
}
+
+/* Deprecated as of version 3.2
+-------------------------------------------------*/
+.small-icon {
+ background-position: 0 50%;
+ background-repeat: no-repeat;
+ background-image: none;
+}
+
+.dropdown .small-icon {
+ background-position: 5px 50%;
+ padding: 5px;
+}
+
+.small-icon > a {
+ padding: 0 0 0 18px;
+}
+
+ul.linklist.bulletin > li.small-icon:before {
+ display: none;
+}
+
+.dropdown .small-icon > a {
+ display: block;
+}
+
+.rtl .small-icon {
+ background-position: 100% 50%;
+}
+
+.rtl .small-icon > a {
+ padding-left: 0;
+ padding-right: 19px;
+}
diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css
index 9095e61369..cf21ac216b 100644
--- a/phpBB/styles/prosilver/theme/colours.css
+++ b/phpBB/styles/prosilver/theme/colours.css
@@ -26,45 +26,85 @@ hr {
border-top-color: #CCCCCC;
}
-/* Search box
---------------------------------------------- */
+/*
+--------------------------------------------------------------
+Colours and backgrounds for links.css
+-------------------------------------------------------------- */
-.search-box .inputbox,
-.search-box .inputbox:hover,
-.search-box .inputbox:focus,
-.search-box .button:hover {
- border-color: #C7C3BF;
+a { color: #105289; }
+a:hover { color: #D31141; }
+
+/* Links on gradient backgrounds */
+.forumbg .header a, .forabg .header a, th a {
+ color: #FFFFFF;
}
-.search-header {
- box-shadow: 0 0 10px #0075B0;
+.forumbg .header a:hover, .forabg .header a:hover, th a:hover {
+ color: #A8D8FF;
+}
+
+/* Notification mark read link */
+.dropdown-extended a.mark_read {
+ background-color: #FFFFFF;
+}
+
+/* Post body links */
+.postlink {
+ border-bottom-color: #368AD2;
+ color: #368AD2;
+}
+
+.postlink:visited {
+ border-bottom-color: #5D8FBD;
+ color: #5D8FBD;
+}
+
+.postlink:hover {
+ background-color: #D0E4F6;
+ color: #0D4473;
+}
+
+.signature a, .signature a:hover {
+ background-color: transparent;
+}
+
+/* Back to top of page */
+.top i {
+ color: #999999;
+}
+
+/* Arrow links */
+.arrow-left:hover, .arrow-right:hover {
+ color: #368AD2;
}
/* Round cornered boxes and backgrounds
---------------------------------------- */
-#wrap {
+.wrap {
background-color: #FFF;
border-color: #E6E9ED;
}
.headerbar {
- background-color: #12A3EB;
- background-image: url("./images/bg_header.gif");
color: #FFFFFF;
}
-.navbar {
- background-color: #cadceb;
+.headerbar, .forumbg {
+ background-color: #12A3EB;
+ background-image: -webkit-linear-gradient(top, #6ACEFF 0%, #0076B1 2px, #12A3EB 92px, #12A3EB 100%);
+ background-image: linear-gradient(to bottom, #6ACEFF 0%,#0076B1 2px,#12A3EB 92px,#12A3EB 100%);
+ background-repeat: repeat-x;
}
.forabg {
- background-color: #0076b1;
- background-image: url("./images/bg_list.gif");
+ background-color: #0076B1;
+ background-image: -webkit-linear-gradient(top, #6ACEFF 0%, #12A3EB 2px, #0076B1 92px, #0076B1 100%);
+ background-image: linear-gradient(to bottom, #6ACEFF 0%,#12A3EB 2px,#0076B1 92px,#0076B1 100%);
+ background-repeat: repeat-x;
}
-.forumbg {
- background-color: #12A3EB;
- background-image: url("./images/bg_header.gif");
+.navbar {
+ background-color: #CADCEB;
}
.panel {
@@ -89,15 +129,15 @@ table.zebra-list tr:nth-child(odd) td, ul.zebra-list li:nth-child(odd) {
}
.bg2 {
- background-color: #e1ebf2;
+ background-color: #E1EBF2;
}
table.zebra-list tr:nth-child(even) td, ul.zebra-list li:nth-child(even) {
- background-color: #e1ebf2;
+ background-color: #E1EBF2;
}
.bg3 {
- background-color: #cadceb;
+ background-color: #CADCEB;
}
.ucprowbg {
@@ -108,6 +148,10 @@ table.zebra-list tr:nth-child(even) td, ul.zebra-list li:nth-child(even) {
background-color: #E7E8EA;
}
+.site_logo {
+ background-image: url("./images/site_logo.gif");
+}
+
/* Horizontal lists
----------------------------------------*/
@@ -162,152 +206,111 @@ dl.details dd {
color: #1198D9;
}
-/* Pagination
+/* Icon styles
---------------------------------------- */
-
-.pagination li a {
- background-color: #ECEDEE;
- border-color: #B4BAC0;
- color: #5C758C;
-}
-
-.pagination li.ellipsis span {
- background-color: transparent;
- color: #000000;
+.icon.icon-blue, a:hover .icon.icon-blue {
+ color: #196db5;
}
-.pagination li.active span {
- background-color: #4692BF;
- border-color: #4692BF;
- color: #FFFFFF;
-}
-
-.pagination li a:hover, .pagination .dropdown-visible a.dropdown-trigger, .nojs .pagination .dropdown-container:hover a.dropdown-trigger {
- background-color: #368AD2;
- border-color: #368AD2;
- color: #FFFFFF;
+.icon.icon-green, a:hover .icon.icon-green{
+ color: #1b9A1B;
}
-.pagination li.next a, .pagination li.previous a, .pagination li.page-jump a {
- background-image: url("./images/icons_pagination.png");
+.icon.icon-red, a:hover .icon.icon-red{
+ color: #BC2A4D;
}
-/* Pagination in viewforum for multipage topics */
-.row .pagination {
- background-image: url("./images/icon_pages.gif");
+.icon.icon-orange, a:hover .icon.icon-orange{
+ color: #FF6600;
}
-/* Miscellaneous styles
----------------------------------------- */
-
-.copyright {
- color: #555555;
+.icon.icon-bluegray, a:hover .icon.icon-bluegray{
+ color: #536482;
}
-.error {
- color: #BC2A4D;
+.icon.icon-gray, a:hover .icon.icon-gray{
+ color: #777777;
}
-.reported {
- background-color: #F7ECEF;
+.icon.icon-lightgray, a:hover .icon.icon-lightgray{
+ color: #999999;
}
-li.reported:hover {
- background-color: #ECD5D8 !important;
-}
-.sticky, .announce {
- /* you can add a background for stickies and announcements*/
+.icon.icon-black, a:hover .icon.icon-black{
+ color: #333333;
}
-div.rules {
- background-color: #ECD5D8;
- color: #BC2A4D;
+.alert_close .icon:before {
+ background-color: #FFFFFF;
}
-p.post-notice {
- background-color: #ECD5D8;
- background-image: none;
+/* Jumpbox */
+.jumpbox .dropdown li {
+ border-top-color: #CCCCCC;
}
-p.post-notice.deleted:before {
- background-image: url("./images/icon_topic_deleted.png");
+.jumpbox-cat-link {
+ background-color: #0076b1;
+ border-top-color: #0076B1;
+ color: #FFFFFF;
}
-p.post-notice.unapproved:before {
- background-image: url("./images/icon_topic_unapproved.gif");
+.jumpbox-cat-link:hover {
+ background-color: #12A3EB;
+ border-top-color: #12A3EB;
+ color: #FFFFFF;
}
-p.post-notice.reported:before, p.post-notice.error:before {
- background-image: url("./images/icon_topic_reported.gif");
+.jumpbox-forum-link {
+ background-color: #E1EBF2;
}
-/*
---------------------------------------------------------------
-Colours and backgrounds for links.css
--------------------------------------------------------------- */
-
-a { color: #105289; }
-a:hover { color: #D31141; }
-
-/* Links on gradient backgrounds */
-.forumbg .header a, .forabg .header a, th a {
- color: #FFFFFF;
+.jumpbox-forum-link:hover {
+ background-color: #F6F4D0;
}
-.forumbg .header a:hover, .forabg .header a:hover, th a:hover {
- color: #A8D8FF;
+.jumpbox .dropdown .pointer-inner {
+ border-color: #E1EBF2 transparent;
}
-/* Notification mark read link */
-.dropdown-extended a.mark_read {
- background-color: #FFFFFF;
+.jumpbox-sub-link {
+ background-color: #E1EBF2;
}
-/* Post body links */
-.postlink {
- border-bottom-color: #368AD2;
- color: #368AD2;
+.jumpbox-sub-link:hover {
+ background-color: #F1F8FF;
}
-.postlink:visited {
- border-bottom-color: #5D8FBD;
- color: #5D8FBD;
-}
+/* Miscellaneous styles
+---------------------------------------- */
-.postlink:hover {
- background-color: #D0E4F6;
- color: #0D4473;
+.copyright {
+ color: #555555;
}
-.signature a, .signature a:hover {
- background-color: transparent;
+.error {
+ color: #BC2A4D;
}
-/* Back to top of page */
-a.top {
- background-image: url("./images/icon_back_top.gif");
+.reported {
+ background-color: #F7ECEF;
}
-a.top2 {
- background-image: url("./images/icon_back_top.gif");
+li.reported:hover {
+ background-color: #ECD5D8 !important;
}
-
-/* Arrow links */
-a.arrow-up { background-image: url("./images/arrow_up.gif"); }
-a.arrow-down { background-image: url("./images/arrow_down.gif"); }
-a.arrow-left { background-image: url("./images/arrow_left.gif"); }
-a.arrow-right { background-image: url("./images/arrow_right.gif"); }
-
-a.arrow-up:hover {
- background-color: transparent;
+.sticky, .announce {
+ /* you can add a background for stickies and announcements*/
}
-a.arrow-left:hover {
- color: #368AD2;
+div.rules {
+ background-color: #ECD5D8;
+ color: #BC2A4D;
}
-a.arrow-right:hover {
- color: #368AD2;
+p.post-notice {
+ background-color: #ECD5D8;
+ background-image: none;
}
/*
@@ -316,8 +319,10 @@ Colours and backgrounds for content.css
-------------------------------------------------------------- */
ul.forums {
- background-color: #eef5f9;
- background-image: url("./images/gradient.gif");
+ background-color: #EEF5F9; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #D2E0EB 0%, #EEF5F9 100%);
+ background-image: linear-gradient(to bottom, #D2E0EB 0%,#EEF5F9 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#D2E0EB', endColorstr='#EEF5F9',GradientType=0 ); /* IE6-9 */
}
ul.topiclist li {
@@ -329,18 +334,10 @@ ul.topiclist dd {
}
.rtl ul.topiclist dd {
- border-right-color: #fff;
+ border-right-color: #FFFFFF;
border-left-color: transparent;
}
-ul.topiclist li.row dt a.subforum.read {
- background-image: url("./images/subforum_read.gif");
-}
-
-ul.topiclist li.row dt a.subforum.unread {
- background-image: url("./images/subforum_unread.gif");
-}
-
li.row {
border-top-color: #FFFFFF;
border-bottom-color: #00608F;
@@ -600,130 +597,165 @@ Colours and backgrounds for buttons.css
-------------------------------------------------------------- */
.button {
border-color: #C7C3BF;
- background-color: #FFFFFF;
- background-image: -moz-linear-gradient(top, #FFFFFF, #E9E9E9);
- background-image: -webkit-linear-gradient(top, #FFFFFF, #E9E9E9);
- background-image: -o-linear-gradient(top, #FFFFFF, #E9E9E9);
- background-image: linear-gradient(to bottom, #FFFFFF, #E9E9E9);
- -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#FFFFFF', EndColorStr='#E9E9E9')";
+ background-color: #E9E9E9; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #FFFFFF 0%, #E9E9E9 100%);
+ background-image: linear-gradient(to bottom, #FFFFFF 0%,#E9E9E9 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#E9E9E9',GradientType=0 ); /* IE6-9 */
box-shadow: 0 0 0 1px #FFFFFF inset;
-webkit-box-shadow: 0 0 0 1px #FFFFFF inset;
color: #D31141;
}
-.dropdown-select {
- color: #536482;
+.button:hover,
+.button:focus {
+ border-color: #0A8ED0;
+ background-color: #FFFFFF; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #E9E9E9 0%, #FFFFFF 100%);
+ background-image: linear-gradient(to bottom, #E9E9E9 0%,#FFFFFF 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#E9E9E9', endColorstr='#FFFFFF',GradientType=0 ); /* IE6-9 */
+ text-shadow: 1px 1px 0 #FFFFFF, -1px -1px 0 #FFFFFF, -1px -1px 0 rgba(188, 42, 77, 0.2);
}
-.button:hover, .dropdown-visible .dropdown-select, .nojs .dropdown-container:hover .dropdown-select {
- border-color: #0a8ed0;
- background-image: -moz-linear-gradient(top, #E9E9E9, #FFFFFF);
- background-image: -webkit-linear-gradient(top, #E9E9E9, #FFFFFF);
- background-image: -o-linear-gradient(top, #E9E9E9, #FFFFFF);
- background-image: linear-gradient(to bottom, #E9E9E9, #FFFFFF);
- -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#E9E9E9', EndColorStr='#FFFFFF')";
- text-shadow: 1px 1px 0 #FFFFFF, -1px -1px 0 #FFFFFF, -1px -1px 0 rgba(188, 42, 77, 0.2);
+
+.button .icon,
+.button-secondary {
+ color: #8f8f8f;
}
-.dropdown-select:after { border-color: #DADADA; }
-.dropdown-select:hover { border-color: #C7C3BF; }
+.button-secondary:focus,
+.button-secondary:hover,
+.button:focus .icon,
+.button:hover .icon {
+ color: #0A8ED0;
+}
-.dropdown-visible .dropdown-select, .dropdown-visible .dropdown-select:hover, .nojs .dropdown-container:hover .dropdown-select {
- border-color: #A6B2BA;
- color: #105289;
+.button-search:hover,
+.button-search-end:hover {
+ border-color: #C7C3BF;
}
+.caret { border-color: #DADADA; }
+.caret { border-color: #C7C3BF; }
+
.contact-icons a { border-color: #DCDCDC; }
.contact-icons a:hover { background-color: #F2F6F9; }
+/* Pagination
+---------------------------------------- */
+
+.pagination li a {
+ background: #ECEDEE;
+ filter: none;
+ border-color: #B4BAC0;
+ box-shadow: none;
+ -webkit-box-shadow: none;
+ color: #5C758C;
+}
+
+.pagination li.ellipsis span {
+ background: transparent;
+ color: #000000;
+}
+
+.pagination li.active span {
+ background: #4692BF;
+ border-color: #4692BF;
+ color: #FFFFFF;
+}
+
+.pagination li a:hover, .pagination li a:hover .icon, .pagination .dropdown-visible a.dropdown-trigger, .nojs .pagination .dropdown-container:hover a.dropdown-trigger {
+ background: #368AD2;
+ border-color: #368AD2;
+ filter: none;
+ color: #FFFFFF;
+ text-shadow: none;
+}
+
+/* Search box
+--------------------------------------------- */
+
+.search-box .inputbox,
+.search-box .inputbox:hover,
+.search-box .inputbox:focus {
+ border-color: #C7C3BF;
+}
+
+.search-header {
+ box-shadow: 0 0 10px #0075B0;
+}
+
/* Icon images
---------------------------------------- */
-.icon-acp { background-image: url("./images/icon_acp.gif"); }
-.icon-bookmark { background-image: url("./images/icon_bookmark.gif"); }
-.icon-bump { background-image: url("./images/icon_bump.gif"); }
-.icon-contact { background-image: url("./images/icon_pm.gif"); }
-.icon-delete-cookies { background-image: url("./images/icon_delete_cookies.gif"); }
-.icon-download { background-image: url("./images/icon_download.gif"); }
-.icon-faq { background-image: url("./images/icon_faq.gif"); }
-.icon-home { background-image: url("./images/icon_home.gif"); }
-.icon-logout { background-image: url("./images/icon_logout.gif"); }
-.icon-mark { background-image: url("./images/icon_mark.gif"); }
-.icon-mcp { background-image: url("./images/icon_mcp.gif"); }
-.icon-members { background-image: url("./images/icon_members.gif"); }
-.icon-notification { background-image: url("./images/icon_notification.gif"); }
-.icon-pages { background-image: url("./images/icon_pages.gif"); }
-.icon-pm { background-image: url("./images/icon_pm.gif"); }
-.icon-print { background-image: url("./images/icon_print.gif"); }
-.icon-profile { background-image: url("./images/icon_profile.gif"); }
-.icon-register { background-image: url("./images/icon_register.gif"); }
-.icon-search, .responsive-search a { background-image: url("./images/icon_search.gif"); }
-.icon-search-active { background-image: url("./images/subforum_read.gif"); }
-.icon-search-new { background-image: url("./images/subforum_unread.gif"); }
-.icon-search-self { background-image: url("./images/icon_topic_latest.gif"); }
-.icon-search-unanswered { background-image: url("./images/icon_post_target.gif"); }
-.icon-search-unread { background-image: url("./images/subforum_unread.gif"); }
-.icon-sendemail { background-image: url("./images/icon_sendemail.gif"); }
-.icon-subscribe { background-image: url("./images/icon_subscribe.gif"); }
-.icon-team { background-image: url("./images/icon_team.gif"); }
-.icon-ucp { background-image: url("./images/icon_ucp.gif"); }
-.icon-unsubscribe { background-image: url("./images/icon_unsubscribe.gif"); }
+
+.contact-icon { background-image: url("./images/icons_contact.png"); }
/* Profile & navigation icons */
-.contact-icon { background-image: url("./images/icons_contact.png"); }
-.icon-button:before, .dropdown-select:after { background-image: url("./images/icons_button.png"); }
+.pm-icon { background-position: 0 0; }
+.email-icon { background-position: -21px 0; }
+.jabber-icon { background-position: -80px 0; }
+.phpbb_icq-icon { background-position: -61px 0 ; }
+.phpbb_wlm-icon { background-position: -182px 0; }
+.phpbb_aol-icon { background-position: -244px 0; }
+.phpbb_website-icon { background-position: -40px 0; }
+.phpbb_youtube-icon { background-position: -98px 0; }
+.phpbb_facebook-icon { background-position: -119px 0; }
+.phpbb_googleplus-icon { background-position: -140px 0; }
+.phpbb_skype-icon { background-position: -161px 0; }
+.phpbb_twitter-icon { background-position: -203px 0; }
+.phpbb_yahoo-icon { background-position: -224px 0; }
/* Forum icons & Topic icons */
-.global_read { background-image: url("./images/announce_read.gif"); }
-.global_read_mine { background-image: url("./images/announce_read_mine.gif"); }
-.global_read_locked { background-image: url("./images/announce_read_locked.gif"); }
-.global_read_locked_mine { background-image: url("./images/announce_read_locked_mine.gif"); }
-.global_unread { background-image: url("./images/announce_unread.gif"); }
-.global_unread_mine { background-image: url("./images/announce_unread_mine.gif"); }
-.global_unread_locked { background-image: url("./images/announce_unread_locked.gif"); }
-.global_unread_locked_mine { background-image: url("./images/announce_unread_locked_mine.gif"); }
-
-.announce_read { background-image: url("./images/announce_read.gif"); }
-.announce_read_mine { background-image: url("./images/announce_read_mine.gif"); }
-.announce_read_locked { background-image: url("./images/announce_read_locked.gif"); }
-.announce_read_locked_mine { background-image: url("./images/announce_read_locked_mine.gif"); }
-.announce_unread { background-image: url("./images/announce_unread.gif"); }
-.announce_unread_mine { background-image: url("./images/announce_unread_mine.gif"); }
-.announce_unread_locked { background-image: url("./images/announce_unread_locked.gif"); }
-.announce_unread_locked_mine { background-image: url("./images/announce_unread_locked_mine.gif"); }
-
-.forum_link { background-image: url("./images/forum_link.gif"); }
-.forum_read { background-image: url("./images/forum_read.gif"); }
-.forum_read_locked { background-image: url("./images/forum_read_locked.gif"); }
-.forum_read_subforum { background-image: url("./images/forum_read_subforum.gif"); }
-.forum_unread { background-image: url("./images/forum_unread.gif"); }
-.forum_unread_locked { background-image: url("./images/forum_unread_locked.gif"); }
-.forum_unread_subforum { background-image: url("./images/forum_unread_subforum.gif"); }
-
-.sticky_read { background-image: url("./images/sticky_read.gif"); }
-.sticky_read_mine { background-image: url("./images/sticky_read_mine.gif"); }
-.sticky_read_locked { background-image: url("./images/sticky_read_locked.gif"); }
-.sticky_read_locked_mine { background-image: url("./images/sticky_read_locked_mine.gif"); }
-.sticky_unread { background-image: url("./images/sticky_unread.gif"); }
-.sticky_unread_mine { background-image: url("./images/sticky_unread_mine.gif"); }
-.sticky_unread_locked { background-image: url("./images/sticky_unread_locked.gif"); }
-.sticky_unread_locked_mine { background-image: url("./images/sticky_unread_locked_mine.gif"); }
-
-.topic_moved { background-image: url("./images/topic_moved.gif"); }
-.topic_read { background-image: url("./images/topic_read.gif"); }
-.topic_read_mine { background-image: url("./images/topic_read_mine.gif"); }
-.topic_read_hot { background-image: url("./images/topic_read_hot.gif"); }
-.topic_read_hot_mine { background-image: url("./images/topic_read_hot_mine.gif"); }
-.topic_read_locked { background-image: url("./images/topic_read_locked.gif"); }
-.topic_read_locked_mine { background-image: url("./images/topic_read_locked_mine.gif"); }
-.topic_unread { background-image: url("./images/topic_unread.gif"); }
-.topic_unread_mine { background-image: url("./images/topic_unread_mine.gif"); }
-.topic_unread_hot { background-image: url("./images/topic_unread_hot.gif"); }
-.topic_unread_hot_mine { background-image: url("./images/topic_unread_hot_mine.gif"); }
-.topic_unread_locked { background-image: url("./images/topic_unread_locked.gif"); }
-.topic_unread_locked_mine { background-image: url("./images/topic_unread_locked_mine.gif"); }
-
-.pm_read { background-image: url("./images/topic_read.gif"); }
-.pm_unread { background-image: url("./images/topic_unread.gif"); }
+.global_read { background-image: url("./images/announce_read.gif"); }
+.global_read_mine { background-image: url("./images/announce_read_mine.gif"); }
+.global_read_locked { background-image: url("./images/announce_read_locked.gif"); }
+.global_read_locked_mine { background-image: url("./images/announce_read_locked_mine.gif"); }
+.global_unread { background-image: url("./images/announce_unread.gif"); }
+.global_unread_mine { background-image: url("./images/announce_unread_mine.gif"); }
+.global_unread_locked { background-image: url("./images/announce_unread_locked.gif"); }
+.global_unread_locked_mine { background-image: url("./images/announce_unread_locked_mine.gif"); }
+
+.announce_read { background-image: url("./images/announce_read.gif"); }
+.announce_read_mine { background-image: url("./images/announce_read_mine.gif"); }
+.announce_read_locked { background-image: url("./images/announce_read_locked.gif"); }
+.announce_read_locked_mine { background-image: url("./images/announce_read_locked_mine.gif"); }
+.announce_unread { background-image: url("./images/announce_unread.gif"); }
+.announce_unread_mine { background-image: url("./images/announce_unread_mine.gif"); }
+.announce_unread_locked { background-image: url("./images/announce_unread_locked.gif"); }
+.announce_unread_locked_mine { background-image: url("./images/announce_unread_locked_mine.gif"); }
+
+.forum_link { background-image: url("./images/forum_link.gif"); }
+.forum_read { background-image: url("./images/forum_read.gif"); }
+.forum_read_locked { background-image: url("./images/forum_read_locked.gif"); }
+.forum_read_subforum { background-image: url("./images/forum_read_subforum.gif"); }
+.forum_unread { background-image: url("./images/forum_unread.gif"); }
+.forum_unread_locked { background-image: url("./images/forum_unread_locked.gif"); }
+.forum_unread_subforum { background-image: url("./images/forum_unread_subforum.gif"); }
+
+.sticky_read { background-image: url("./images/sticky_read.gif"); }
+.sticky_read_mine { background-image: url("./images/sticky_read_mine.gif"); }
+.sticky_read_locked { background-image: url("./images/sticky_read_locked.gif"); }
+.sticky_read_locked_mine { background-image: url("./images/sticky_read_locked_mine.gif"); }
+.sticky_unread { background-image: url("./images/sticky_unread.gif"); }
+.sticky_unread_mine { background-image: url("./images/sticky_unread_mine.gif"); }
+.sticky_unread_locked { background-image: url("./images/sticky_unread_locked.gif"); }
+.sticky_unread_locked_mine { background-image: url("./images/sticky_unread_locked_mine.gif"); }
+
+.topic_moved { background-image: url("./images/topic_moved.gif"); }
+.pm_read,
+.topic_read { background-image: url("./images/topic_read.gif"); }
+.topic_read_mine { background-image: url("./images/topic_read_mine.gif"); }
+.topic_read_hot { background-image: url("./images/topic_read_hot.gif"); }
+.topic_read_hot_mine { background-image: url("./images/topic_read_hot_mine.gif"); }
+.topic_read_locked { background-image: url("./images/topic_read_locked.gif"); }
+.topic_read_locked_mine { background-image: url("./images/topic_read_locked_mine.gif"); }
+.pm_unread,
+.topic_unread { background-image: url("./images/topic_unread.gif"); }
+.topic_unread_mine { background-image: url("./images/topic_unread_mine.gif"); }
+.topic_unread_hot { background-image: url("./images/topic_unread_hot.gif"); }
+.topic_unread_hot_mine { background-image: url("./images/topic_unread_hot_mine.gif"); }
+.topic_unread_locked { background-image: url("./images/topic_unread_locked.gif"); }
+.topic_unread_locked_mine { background-image: url("./images/topic_unread_locked_mine.gif"); }
+
/*
--------------------------------------------------------------
@@ -733,7 +765,7 @@ Colours and backgrounds for cp.css
/* Main CP box
----------------------------------------*/
-.panel-container h3, .panel-container hr, #cp-menu hr {
+.panel-container h3, .panel-container hr, .cp-menu hr {
border-color: #A4B3BF;
}
@@ -755,50 +787,46 @@ ul.cplist {
border-bottom-color: #333333;
}
-#cp-main .pm-message {
+.cp-main .pm-message {
border-color: #DBDEE2;
background-color: #FFFFFF;
}
/* CP tabbed menu
----------------------------------------*/
-#tabs .tab > a {
+.tabs .tab > a {
background: #BACCD9;
color: #536482;
}
-#tabs .tab > a:hover {
+.tabs .tab > a:hover {
background: #DDEDFB;
color: #D31141;
}
-#tabs .activetab > a,
-#tabs .activetab > a:hover {
- background: #CADCEB;
- background: -moz-linear-gradient(top, #E2F2FF 0%, #CADCEB 100%);
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #E2F2FF), color-stop(100%, #CADCEB));
- background: -webkit-linear-gradient(top, #E2F2FF 0%, #CADCEB 100%);
- background: -o-linear-gradient(top, #E2F2FF 0%, #CADCEB 100%);
- background: -ms-linear-gradient(top, #E2F2FF 0%, #CADCEB 100%);
- background: linear-gradient(to bottom, #E2F2FF 0%, #CADCEB 100%);
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#E2F2FF', endColorstr='#CADCEB', GradientType=0 );
+.tabs .activetab > a,
+.tabs .activetab > a:hover {
+ background-color: #CADCEB; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #E2F2FF 0%, #CADCEB 100%);
+ background-image: linear-gradient(to bottom, #E2F2FF 0%,#CADCEB 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#E2F2FF', endColorstr='#CADCEB',GradientType=0 ); /* IE6-9 */
border-color: #CADCEB;
box-shadow: 0 1px 1px #F2F9FF inset;
color: #333333;
}
-#tabs .activetab > a:hover {
+.tabs .activetab > a:hover {
color: #000000;
}
/* Mini tabbed menu used in MCP
----------------------------------------*/
-#minitabs .tab > a {
+.minitabs .tab > a {
background-color: #E1EBF2;
}
-#minitabs .activetab > a,
-#minitabs .activetab > a:hover {
+.minitabs .activetab > a,
+.minitabs .activetab > a:hover {
background-color: #F9F9F9;
color: #333333;
}
@@ -817,42 +845,34 @@ ul.cplist {
----------------------------------------*/
/* Link styles for the sub-section links */
-#navigation a {
+.navigation a {
color: #333;
- background: #B4C4D1;
- background: -moz-linear-gradient(left, #B4C4D1 50%, #CADCEB 100%);
- background: -webkit-gradient(left top, right top, color-stop(50%, #B4C4D1), color-stop(100%, #CADCEB));
+ background: #CADCEB; /* Old browsers */ /* FF3.6+ */
background: -webkit-linear-gradient(left, #B4C4D1 50%, #CADCEB 100%);
- background: -o-linear-gradient(left, #B4C4D1 50%, #CADCEB 100%);
- background: -ms-linear-gradient(left, #B4C4D1 50%, #CADCEB 100%);
- background: linear-gradient(to right, #B4C4D1 50%, #CADCEB 100%);
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#B4C4D1', endColorstr='#CADCEB', GradientType=1 );
+ background: linear-gradient(to right, #B4C4D1 50%,#CADCEB 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#B4C4D1', endColorstr='#CADCEB',GradientType=1 ); /* IE6-9 */
}
-.rtl #navigation a {
- background: #B4C4D1;
- background: -moz-linear-gradient(left, #CADCEB 0%, #B4C4D1 50%);
- background: -webkit-gradient(left top, right top, color-stop(0%, #CADCEB), color-stop(50%, #B4C4D1));
- background: -webkit-linear-gradient(left, #CADCEB 0%, #B4C4D1 50%);
- background: -o-linear-gradient(left, #CADCEB 0%, #B4C4D1 50%);
- background: -ms-linear-gradient(left, #CADCEB 0%, #B4C4D1 50%);
- background: linear-gradient(to right, #CADCEB 0%, #B4C4D1 50%);
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CADCEB', endColorstr='#B4C4D1', GradientType=1 );
+.rtl .navigation a {
+ background: #B4C4D1; /* Old browsers */ /* FF3.6+ */
+ background: -webkit-linear-gradient(left, #CADCEB 50%, #B4C4D1 100%);
+ background: linear-gradient(to right, #CADCEB 50%,#B4C4D1 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CADCEB', endColorstr='#B4C4D1',GradientType=1 ); /* IE6-9 */
}
-#navigation a:hover {
+.navigation a:hover {
background: #AABAC6;
color: #BC2A4D;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
-#navigation #active-subsection a {
+.navigation .active-subsection a {
background: #F9F9F9;
color: #D31141;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
-#navigation #active-subsection a:hover {
+.navigation .active-subsection a:hover {
color: #D31141;
}
@@ -873,13 +893,13 @@ ul.cplist {
background-color: #F9F9F9;
}
-#cp-main .pm {
+.cp-main .pm {
background-color: #FFFFFF;
}
/* Friends list */
.cp-mini {
- background-color: #eef5f9;
+ background-color: #EEF5F9;
}
dl.mini dt {
@@ -916,12 +936,12 @@ dl.mini dt {
}
/* Avatar gallery */
-#gallery label {
+.gallery label {
background: #FFFFFF;
border-color: #CCC;
}
-#gallery label:hover {
+.gallery label:hover {
background-color: #EEE;
}
@@ -973,15 +993,15 @@ fieldset.quick-login input.inputbox {
/* Posting page styles
----------------------------------------*/
-#message-box textarea {
+.message-box textarea {
color: #333333;
}
-#message-box textarea.drag-n-drop {
+.message-box textarea.drag-n-drop {
outline-color: rgba(102, 102, 102, 0.5);
}
-#message-box textarea.drag-n-drop-highlight {
+.message-box textarea.drag-n-drop-highlight {
outline-color: rgba(17, 163, 234, 0.5);
}
@@ -1007,7 +1027,6 @@ fieldset.quick-login input.inputbox {
.inputbox:focus {
border-color: #11A3EA;
- color: #0F4987;
}
.inputbox:focus:-moz-placeholder {
@@ -1024,8 +1043,10 @@ fieldset.quick-login input.inputbox {
a.button1, input.button1, input.button3, a.button2, input.button2 {
color: #000;
- background-color: #FAFAFA;
- background-image: url("./images/bg_button.gif");
+ background-color: #EFEFEF; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #D2D2D2 0%, #EFEFEF 100%);
+ background-image: linear-gradient(to bottom, #D2D2D2 0%,#EFEFEF 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#D2D2D2', endColorstr='#EFEFEF',GradientType=0 ); /* IE6-9 */
}
a.button1, input.button1 {
@@ -1048,8 +1069,12 @@ a.button1, a.button2 {
/* Hover states */
a.button1:hover, input.button1:hover, a.button2:hover, input.button2:hover, input.button3:hover {
- border-color: #BC2A4D;
- color: #BC2A4D;
+ border-color: #D31141;
+ color: #D31141;
+ background-color: #D2D2D2; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #EFEFEF 0%, #D2D2D2 100%);
+ background-image: linear-gradient(to bottom, #EFEFEF 0%,#D2D2D2 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EFEFEF', endColorstr='#D2D2D2',GradientType=0 ); /* IE6-9 */
}
/* Focus states */
@@ -1058,10 +1083,6 @@ input.button1:focus, input.button2:focus, input.button3:focus {
color: #0F4987;
}
-input.search {
- background-image: url("./images/icon_textbox_search.gif");
-}
-
input.disabled {
color: #666666;
}
@@ -1072,14 +1093,11 @@ input.disabled {
background-color: #FFFFFF;
border-color: #999999;
}
-.phpbb_alert .alert_close {
- background-image: url("./images/alert_close.png");
-}
-#darken {
+.darken {
background-color: #000000;
}
-#loading_indicator {
+.loading_indicator {
background-color: #000000;
background-image: url("./images/loading.gif");
}
@@ -1104,13 +1122,10 @@ input.disabled {
}
.dropdown-extended .header {
- background: #F1F8FF;
- background: -moz-linear-gradient(top, #F1F8FF 0%, #CADCEB 100%);
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F1F8FF), color-stop(100%, #CADCEB));
- background: -webkit-linear-gradient(top, #F1F8FF 0%, #CADCEB 100%);
- background: -o-linear-gradient(top, #F1F8FF 0%, #CADCEB 100%);
- background: -ms-linear-gradient(top, #F1F8FF 0%, #CADCEB 100%);
- background: linear-gradient(to bottom, #F1F8FF 0%, #CADCEB 100%);
+ background-color: #F1F8FF; /* Old browsers */ /* FF3.6+ */
+ background-image: -webkit-linear-gradient(top, #F1F8FF 0%, #CADCEB 100%);
+ background-image: linear-gradient(to bottom, #F1F8FF 0%,#CADCEB 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F1F8FF', endColorstr='#CADCEB',GradientType=0 ); /* IE6-9 */
}
.dropdown .pointer {
@@ -1125,17 +1140,9 @@ input.disabled {
border-color: #F1F8FF transparent;
}
-ul.linklist li.responsive-menu a.responsive-menu-link:before {
- border-color: #105289;
-}
-
-ul.linklist li.responsive-menu a.responsive-menu-link:hover:before, ul.linklist li.responsive-menu.visible a.responsive-menu-link:before {
- border-color: #D31141;
-}
-
.dropdown .dropdown-contents {
background: #fff;
- border-color: #b9b9b9;
+ border-color: #B9B9B9;
box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.2);
}
diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css
index 9c2f33f7a9..8368fc158c 100644
--- a/phpBB/styles/prosilver/theme/common.css
+++ b/phpBB/styles/prosilver/theme/common.css
@@ -1,52 +1,3 @@
-/* CSS Reset http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126
----------------------------------------- */
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
-body {
- line-height: 1;
-}
-ol, ul {
- list-style: none;
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-abbr {
- text-decoration: none;
-}
-
/* General Markup Styles
---------------------------------------- */
html {
@@ -172,10 +123,11 @@ ol ol ul, ol ul ul, ul ol ul, ul ul ul {
list-style-type: square;
}
+a:hover { text-decoration: underline; }
/* Main blocks
---------------------------------------- */
-#wrap {
+.wrap {
border: 1px solid transparent;
border-radius: 8px;
margin: 0 auto;
@@ -185,21 +137,21 @@ ol ol ul, ol ul ul, ul ol ul, ul ul ul {
}
@media only screen and (max-width: 1220px), only screen and (max-device-width: 1220px) {
- #wrap {
+ .wrap {
margin: 0 12px;
}
}
-#page-body {
+.page-body {
margin: 4px 0;
clear: both;
}
-#page-footer {
+.page-footer {
clear: both;
}
-#page-footer h3 {
+.page-footer h3 {
margin-top: 20px;
}
@@ -213,20 +165,25 @@ ol ol ul, ol ul ul, ul ol ul, ul ul ul {
text-decoration: none;
}
+.site_logo {
+ display: inline-block;
+ width: 149px;
+ height: 52px;
+}
+
/* Site description and logo */
-#site-description {
+.site-description {
float: left;
width: 65%;
}
-#site-description h1 {
+.site-description h1 {
margin-right: 0;
}
/* Round cornered boxes and backgrounds
---------------------------------------- */
.headerbar {
- background: transparent none repeat-x 0 0;
margin-bottom: 4px;
padding: 5px;
border-radius: 7px;
@@ -238,7 +195,6 @@ ol ol ul, ol ul ul, ul ol ul, ul ul ul {
}
.forabg {
- background: transparent none repeat-x 0 0;
margin-bottom: 4px;
padding: 5px;
clear: both;
@@ -246,7 +202,6 @@ ol ol ul, ol ul ul, ul ol ul, ul ul ul {
}
.forumbg {
- background: transparent none repeat-x 0 0;
margin-bottom: 4px;
padding: 5px;
clear: both;
@@ -276,6 +231,7 @@ ol ol ul, ol ul ul, ul ol ul, ul ul ul {
----------------------------------------*/
.navbar ul.linklist {
padding: 2px 0;
+ list-style-type: none;
}
ul.linklist {
@@ -283,7 +239,7 @@ ul.linklist {
margin: 0;
}
-#cp-main .panel {
+.cp-main .panel {
padding: 5px 10px;
}
@@ -324,28 +280,7 @@ ul.rightside {
ul.linklist li.responsive-menu {
position: relative;
- margin: 0 5px;
-}
-
-ul.linklist li.responsive-menu a.responsive-menu-link {
- display: inline-block;
- margin: 0 5px;
- font-size: 1.455em;
- position: relative;
- width: 16px;
- line-height: 1.2em;
- text-decoration: none;
-}
-
-ul.linklist li.responsive-menu a.responsive-menu-link:before {
- content: '';
- position: absolute;
- left: 0;
- top: 7px;
- height: .125em;
- width: 14px;
- border-bottom: 0.125em solid transparent;
- border-top: 0.375em double transparent;
+ margin: 0 5px 0 0;
}
.hasjs ul.linklist.leftside, .hasjs ul.linklist.rightside {
@@ -414,12 +349,12 @@ ul.linklist.bulletin > li.no-bulletin:before {
}
.header-avatar span:after {
- content: '\25BC';
+ content: '\f0dd';
display: inline-block;
- font-size: 9px;
- float: right;
- padding-left: 2px;
- opacity: 0.7;
+ font: normal normal normal 14px/1 FontAwesome;
+ padding-left: 6px;
+ padding-top: 2px;
+ vertical-align: top;
}
/* Dropdown menu
@@ -441,6 +376,7 @@ ul.linklist.bulletin > li.no-bulletin:before {
}
.dropdown {
+ display: none;
position: absolute;
left: 0;
top: 1.2em;
@@ -501,12 +437,12 @@ ul.linklist.bulletin > li.no-bulletin:before {
.dropdown .pointer {
right: auto;
left: 10px;
- top: 0;
+ top: -1px;
z-index: 3;
}
.dropdown-up .pointer {
- bottom: 0;
+ bottom: -1px;
top: auto;
}
@@ -534,22 +470,72 @@ ul.linklist.bulletin > li.no-bulletin:before {
border-radius: 5px;
padding: 5px;
position: relative;
- min-width: 40px;
max-height: 300px;
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+}
+
+.dropdown-contents a {
+ display: block;
+ padding: 5px;
+}
+
+.jumpbox {
+ margin: 5px 0;
+}
+
+.jumpbox .dropdown li {
+ border-top: 1px solid transparent;
+}
+
+.jumpbox .dropdown-select {
+ margin: 0;
+}
+
+.jumpbox .dropdown-contents {
+ padding: 0;
+ text-decoration: none;
+}
+
+.jumpbox .dropdown-contents li {
+ padding: 0;
+}
+
+.jumpbox .dropdown-contents a {
+ margin-right: 20px;
+ padding: 5px 10px;
+ text-decoration: none;
+ width: 100%;
+}
+
+.jumpbox .spacer {
+ display: inline-block;
+ width: 0px;
+}
+
+.jumpbox .spacer + .spacer {
+ width: 20px;
+}
+
+.dropdown-contents a {
+ display: block;
+ padding: 5px;
+}
+
+.jumpbox .dropdown-select {
+ margin: 0;
+}
+
+.jumpbox .dropdown-contents a {
+ text-decoration: none;
}
.dropdown li {
+ display: list-item;
border-top: 1px dotted transparent;
float: none !important;
line-height: normal !important;
font-size: 1em !important;
list-style: none;
margin: 0;
- padding-top: 4px;
- padding-bottom: 4px;
white-space: nowrap;
text-align: left;
}
@@ -585,7 +571,6 @@ ul.linklist.bulletin > li.no-bulletin:before {
.dropdown li.separator {
border-top: 1px solid transparent;
- margin: 4px 0;
padding: 0;
}
@@ -612,7 +597,6 @@ ul.linklist.bulletin > li.no-bulletin:before {
}
.breadcrumbs .crumb a {
- display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: bottom;
@@ -635,7 +619,7 @@ table.table1 {
width: 100%;
}
-#ucp-main table.table1 {
+.ucp-main table.table1 {
padding: 2px;
}
@@ -707,7 +691,7 @@ table.info tbody th {
margin: 0 -1px;
}
-#color_palette_placeholder table {
+.color_palette_placeholder table {
border-collapse: separate;
border-spacing: 1px;
}
@@ -802,7 +786,7 @@ fieldset.fields1 dl.pmlist dd.recipients {
/* Action-bars (container for post/reply buttons, pagination, etc.)
---------------------------------------- */
.action-bar {
- font-size: 1.1em;
+ font-size: 11px;
margin: 4px 0;
}
@@ -810,19 +794,32 @@ fieldset.fields1 dl.pmlist dd.recipients {
margin-top: 2em;
}
+.action-bar .button {
+ margin-right: 5px;
+ float: left;
+}
+
+.action-bar .button-search {
+ margin-right: 0;
+}
+
/* Pagination
---------------------------------------- */
.pagination {
float: right;
- margin-top: 3px;
text-align: right;
width: auto;
}
-.action-bar.bottom .pagination {
+.action-bar.bar-bottom .pagination {
margin-top: 0;
}
+.action-bar .pagination .button {
+ margin-right: 0;
+ float: none;
+}
+
.pagination > ul {
display: inline-block;
list-style: none !important;
@@ -838,16 +835,20 @@ fieldset.fields1 dl.pmlist dd.recipients {
}
.pagination li a, .pagination li span {
- border: 1px solid transparent;
border-radius: 2px;
- display: block;
- font-size: 0.9em;
+ padding: 2px 5px;
+}
+
+.pagination li.active span {
+ display: inline-block;
+ font-size: 13px;
font-weight: normal;
- line-height: 1.4em;
- min-width: 10px;
- padding: 3px;
+ font-family: "Open Sans", "Droid Sans", Verdana, Arial, Helvetica;
+ line-height: 1.4;
text-align: center;
- text-decoration: none;
+ white-space: nowrap;
+ vertical-align: middle;
+ border: 1px solid transparent;
}
.pagination li.ellipsis span {
@@ -859,37 +860,22 @@ fieldset.fields1 dl.pmlist dd.recipients {
margin-right: 5px;
}
-.pagination li.page-jump a, .pagination li.next a, .pagination li.previous a {
- background-repeat: no-repeat;
- font-size: 0;
- height: 13px;
- width: 11px;
-}
-
.pagination li.page-jump a {
- background-position: 0 2px;
- width: 24px;
+ padding: 0 8px;
}
-.pagination li.next a {
- background-position: -50px 2px;
+.pagination li.page-jump a i {
+ font-size: 21px;
}
-.pagination li.previous a {
- background-position: -30px 2px;
+.pagination .arrow a {
+ padding: 2px 0;
}
-.pagination li.page-jump a:hover, .pagination .dropdown-visible a.dropdown-trigger, .nojs .pagination .dropdown-container:hover a.dropdown-trigger { background-position: 0 -18px; }
-.pagination li.next a:hover { background-position: -50px -18px; }
-.pagination li.previous a:hover { background-position: -30px -18px; }
-
/* Pagination in viewforum for multipage topics */
.row .pagination {
display: block;
- margin-top: 0;
- padding: 1px 0 1px 15px;
- font-size: 0.9em;
- background: none 0 50% no-repeat;
+ margin-top: -12px;
}
.row .pagination > ul {
@@ -897,8 +883,9 @@ fieldset.fields1 dl.pmlist dd.recipients {
}
.row .pagination li a, .row .pagination li span {
- border-radius: 1px;
- padding: 1px;
+ border-radius: 2px;
+ padding: 1px 3px;
+ font-size: 9px;
}
/* jQuery popups
@@ -924,18 +911,9 @@ fieldset.fields1 dl.pmlist dd.recipients {
}
.phpbb_alert .alert_close {
- display: block;
float: right;
- width: 16px;
- height: 16px;
- overflow: hidden;
- text-decoration: none !important;
- background: transparent none 0 0 no-repeat;
- margin-top: -7px;
- margin-right: -31px;
-}
-.phpbb_alert .alert_close:hover {
- background-position: 0 -16px;
+ margin-right: -36px;
+ margin-top: -8px;
}
.phpbb_alert p {
@@ -957,13 +935,13 @@ fieldset.fields1 dl.pmlist dd.recipients {
font-size: 1.1em;
}
-#darkenwrapper {
+.darkenwrapper {
display: none;
position: relative;
z-index: 44;
}
-#darken {
+.darken {
position: fixed;
left: 0;
top: 0;
@@ -973,7 +951,7 @@ fieldset.fields1 dl.pmlist dd.recipients {
z-index: 45;
}
-#loading_indicator {
+.loading_indicator {
background: center center no-repeat;
border-radius: 5px;
display: none;
@@ -990,15 +968,6 @@ fieldset.fields1 dl.pmlist dd.recipients {
/* Miscellaneous styles
---------------------------------------- */
-#forum-permissions {
- float: right;
- width: auto;
- padding-left: 5px;
- margin-left: 5px;
- margin-top: 10px;
- text-align: right;
-}
-
.copyright {
padding: 5px;
text-align: center;
@@ -1035,36 +1004,20 @@ div.rules ul, div.rules ol {
p.post-notice {
position: relative;
padding: 5px;
- padding-left: 26px;
min-height: 14px;
margin-bottom: 1em;
}
-p.post-notice:before {
- content: '';
- display: block;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- width: 28px;
- background: transparent none 50% 50% no-repeat;
- pointer-events: none;
-}
-
form > p.post-notice strong {
line-height: 20px;
}
-#jumpbox {
- margin: 5px 0;
-}
-
.stat-block {
clear: both;
}
-#top {
+.top-anchor {
+ display: block;
position: absolute;
top: -20px;
}
@@ -1083,18 +1036,14 @@ ul.linklist:after,
.action-bar:after,
.notification_text:after,
.tabs-container:after,
-#tabs > ul:after,
-#minitabs > ul:after,
+.tabs > ul:after,
+.minitabs > ul:after,
.postprofile .avatar-container:after {
clear: both;
content: '';
display: block;
}
-.hidden {
- display: none;
-}
-
.smilies {
vertical-align: text-bottom;
}
@@ -1173,6 +1122,11 @@ ul.linklist:after,
text-transform: none;
}
+.dropdown-extended .header .header_settings a {
+ display: inline-block;
+ padding: 0 5px;
+}
+
.dropdown-extended .header:after {
content: '';
display: table;
@@ -1270,30 +1224,11 @@ ul.linklist:after,
/* Navbar specific list items
----------------------------------------*/
-#quick-links {
+.linklist .quick-links {
margin: 0 7px 0 0;
}
-#quick-links a.responsive-menu-link {
- display: block;
- font-size: inherit;
- line-height: inherit;
- margin: 0;
- width: auto;
-}
-
-#quick-links a.responsive-menu-link:before {
- font-size: 1.455em;
- line-height: 16.5px;
-}
-
-.compact #quick-links a.responsive-menu-link {
- width: 0;
- overflow: hidden;
- white-space: nowrap;
-}
-
-.compact .icon-notification > a > span, .compact .icon-pm > a > span {
+.linklist.compact .rightside > a > span span {
display: none;
}
diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css
index 92a7db81d9..ef18e26ef1 100644
--- a/phpBB/styles/prosilver/theme/content.css
+++ b/phpBB/styles/prosilver/theme/content.css
@@ -7,10 +7,6 @@ ul.topiclist {
margin: 0;
}
-ul.forums {
- background: transparent none repeat-x 0 0;
-}
-
ul.topiclist li {
display: block;
list-style-type: none;
@@ -81,15 +77,6 @@ ul.topiclist dfn {
width: 990px;
}
-ul.topiclist li.row dt a.subforum {
- background-image: none;
- background-position: 0 50%;
- background-repeat: no-repeat;
- position: relative;
- white-space: nowrap;
- padding: 0 0 0 12px;
-}
-
.forum-image {
float: left;
padding-top: 5px;
@@ -133,36 +120,40 @@ li.header dd {
box-sizing: border-box;
}
-li.header dl.icon dt, li.header dl.icon dd {
+li.header dl.row-item dt, li.header dl.row-item dd {
min-height: 0;
}
-li.header dl.icon dt .list-inner {
+li.header dl.row-item dt .list-inner {
/* Tweak for headers alignment when folder icon used */
padding-left: 0;
padding-right: 50px;
}
/* Forum list column styles */
-dl.icon {
+dl.row-item {
background-position: 10px 50%; /* Position of folder icon */
background-repeat: no-repeat;
}
-dl.icon dt {
+dl.row-item dt {
background-repeat: no-repeat;
background-position: 5px 95%; /* Position of topic icon */
}
-dl.icon dt .list-inner {
+dl.row-item dt .list-inner {
padding-left: 45px; /* Space for folder icon */
}
-dl.icon dt, dl.icon dd {
+dl.row-item dt, dl.row-item dd {
min-height: 35px;
}
-dl a.icon-link { /* topic row icon links */
+dl.row-item dt a {
+ display: inline;
+}
+
+dl a.row-item-link { /* topic row icon links */
display: block;
width: 30px;
height: 30px;
@@ -186,13 +177,13 @@ dd.posts, dd.topics, dd.views {
}
/* List in forum description */
-dl.icon dt ol,
-dl.icon dt ul {
+dl.row-item dt ol,
+dl.row-item dt ul {
list-style-position: inside;
margin-left: 1em;
}
-dl.icon dt li {
+dl.row-item dt li {
display: list-item;
list-style-type: inherit;
}
@@ -286,28 +277,28 @@ dd.option {
/* Topic review panel
----------------------------------------*/
-#review {
+.panel .review {
margin-top: 2em;
}
-#topicreview {
+.topicreview {
padding-right: 5px;
overflow: auto;
height: 300px;
}
-#topicreview .postbody {
+.topicreview .postbody {
width: auto;
float: none;
margin: 0;
height: auto;
}
-#topicreview .post {
+.topicreview .post {
height: auto;
}
-#topicreview h2 {
+.topicreview h2 {
border-bottom-width: 0;
}
@@ -317,7 +308,7 @@ dd.option {
/* MCP Post details
----------------------------------------*/
-#post_details {
+.post_details {
/* This will only work in IE7+, plus the others */
overflow: auto;
max-height: 300px;
@@ -383,8 +374,7 @@ dl.faq dt {
}
.content ul, .content ol {
- margin-bottom: 1em;
- margin-left: 3em;
+ margin: 0.8em 0 0.9em 3em;
}
.posthilit {
@@ -430,8 +420,7 @@ dd .signature {
}
.signature ul, .signature ol {
- margin-bottom: 1em;
- margin-left: 3em;
+ margin: 0.8em 0 0.9em 3em;
}
/* Post noticies */
@@ -460,7 +449,7 @@ blockquote {
background: transparent none 6px 8px no-repeat;
border: 1px solid transparent;
font-size: 0.95em;
- margin: 0.5em 1px 0 25px;
+ margin: 1em 1px 1em 25px;
overflow: hidden;
padding: 5px;
}
@@ -468,7 +457,7 @@ blockquote {
blockquote blockquote {
/* Nested quotes */
font-size: 1em;
- margin: 0.5em 1px 0 15px;
+ margin: 1em 1px 1em 15px;
}
blockquote cite {
@@ -488,11 +477,22 @@ blockquote.uncited {
padding-top: 25px;
}
+blockquote cite > div {
+ float: right;
+ font-weight: normal;
+}
+
+.postbody .content li blockquote {
+ overflow: inherit;
+ margin-left: 0;
+}
+
/* Code block */
.codebox {
padding: 3px;
border: 1px solid transparent;
font-size: 1em;
+ margin: 1em 0 1.2em 0;
}
.codebox p {
@@ -513,7 +513,6 @@ blockquote .codebox {
display: block;
height: auto;
max-height: 200px;
- white-space: normal;
padding-top: 5px;
font: 0.9em Monaco, "Andale Mono","Courier New", Courier, mono;
line-height: 1.3em;
@@ -830,7 +829,7 @@ table.fixed-width-table {
/* Show scrollbars for items with overflow on iOS devices
----------------------------------------*/
-.postbody .content::-webkit-scrollbar, #topicreview::-webkit-scrollbar, #post_details::-webkit-scrollbar, .codebox code::-webkit-scrollbar, .attachbox dd::-webkit-scrollbar, .attach-image::-webkit-scrollbar, .dropdown-extended ul::-webkit-scrollbar {
+.postbody .content::-webkit-scrollbar, .topicreview::-webkit-scrollbar, .post_details::-webkit-scrollbar, .codebox code::-webkit-scrollbar, .attachbox dd::-webkit-scrollbar, .attach-image::-webkit-scrollbar, .dropdown-extended ul::-webkit-scrollbar {
width: 8px;
height: 8px;
-webkit-appearance: none;
@@ -838,7 +837,7 @@ table.fixed-width-table {
border-radius: 3px;
}
-.postbody .content::-webkit-scrollbar-thumb, #topicreview::-webkit-scrollbar-thumb, #post_details::-webkit-scrollbar-thumb, .codebox code::-webkit-scrollbar-thumb, .attachbox dd::-webkit-scrollbar-thumb, .attach-image::-webkit-scrollbar-thumb, .dropdown-extended ul::-webkit-scrollbar-thumb {
+.postbody .content::-webkit-scrollbar-thumb, .topicreview::-webkit-scrollbar-thumb, .post_details::-webkit-scrollbar-thumb, .codebox code::-webkit-scrollbar-thumb, .attachbox dd::-webkit-scrollbar-thumb, .attach-image::-webkit-scrollbar-thumb, .dropdown-extended ul::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, .3);
border-radius: 3px;
}
diff --git a/phpBB/styles/prosilver/theme/cp.css b/phpBB/styles/prosilver/theme/cp.css
index 8a223f653f..d54c948343 100644
--- a/phpBB/styles/prosilver/theme/cp.css
+++ b/phpBB/styles/prosilver/theme/cp.css
@@ -4,19 +4,19 @@
/* Main CP box
----------------------------------------*/
-#cp-menu {
+.cp-menu {
float:left;
width: 19%;
margin-top: 1em;
margin-bottom: 5px;
}
-#cp-main {
+.cp-main {
float: left;
width: 81%;
}
-#cp-main .content {
+.cp-main .content {
padding: 0;
}
@@ -59,7 +59,7 @@ ul.cplist {
border-bottom: none;
}
-#cp-main .pm-message {
+.cp-main .pm-message {
border: 1px solid transparent;
margin: 10px 0;
width: auto;
@@ -70,7 +70,7 @@ ul.cplist {
padding-bottom: 5px;
}
-#cp-main .postbody h3, #cp-main .box2 h3 {
+.cp-main .postbody h3, .cp-main .box2 h3 {
margin-top: 0;
}
@@ -78,11 +78,11 @@ ul.cplist {
font-size: 1.1em;
}
-#cp-main .buttons {
+.cp-main .buttons {
margin-left: 0;
}
-#cp-main ul.linklist {
+.cp-main ul.linklist {
margin: 0;
}
@@ -98,18 +98,18 @@ ul.cplist {
/* CP tabs shared
----------------------------------------*/
-#tabs, #minitabs {
+.tabs, .minitabs {
line-height: normal;
}
-#tabs > ul, #minitabs > ul {
+.tabs > ul, .minitabs > ul {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
-#tabs .tab, #minitabs .tab {
+.tabs .tab, .minitabs .tab {
display: block;
float: left;
font-size: 1em;
@@ -117,7 +117,7 @@ ul.cplist {
line-height: 1.4em;
}
-#tabs .tab > a, #minitabs .tab > a {
+.tabs .tab > a, .minitabs .tab > a {
display: block;
padding: 5px 9px;
position: relative;
@@ -128,39 +128,39 @@ ul.cplist {
/* CP tabbed menu
----------------------------------------*/
-#tabs {
+.tabs {
margin: 20px 0 0 7px;
}
-#tabs .tab > a {
+.tabs .tab > a {
border: 1px solid transparent;
border-radius: 4px 4px 0 0;
margin: 1px 1px 0 0;
}
-#tabs .activetab > a {
+.tabs .activetab > a {
margin-top: 0;
padding-bottom: 7px;
}
/* Mini tabbed menu used in MCP
----------------------------------------*/
-#minitabs {
+.minitabs {
float: right;
margin: 15px 7px 0 0;
max-width: 50%;
}
-#minitabs .tab {
+.minitabs .tab {
float: right;
}
-#minitabs .tab > a {
+.minitabs .tab > a {
border-radius: 5px 5px 0 0;
margin-left: 2px;
}
-#minitabs .tab > a:hover {
+.minitabs .tab > a:hover {
text-decoration: none;
}
@@ -190,44 +190,44 @@ ul.cplist {
border-top: 0.375em double transparent;
}
-#tabs .dropdown, #minitabs .dropdown {
+.tabs .dropdown, .minitabs .dropdown {
top: 20px;
margin-right: -2px;
font-size: 1.1em;
font-weight: normal;
}
-#minitabs .dropdown {
+.minitabs .dropdown {
margin-right: -4px;
}
-#tabs .dropdown-up .dropdown, #minitabs .dropdown-up .dropdown {
+.tabs .dropdown-up .dropdown, .minitabs .dropdown-up .dropdown {
bottom: 20px;
top: auto;
}
-#tabs .dropdown li {
+.tabs .dropdown li {
text-align: right;
}
-#minitabs .dropdown li {
+.minitabs .dropdown li {
text-align: left;
}
/* UCP navigation menu
----------------------------------------*/
/* Container for sub-navigation list */
-#navigation {
+.navigation {
width: 100%;
padding-top: 36px;
}
-#navigation ul {
+.navigation ul {
list-style: none;
}
/* Default list state */
-#navigation li {
+.navigation li {
display: inline;
font-weight: bold;
margin: 1px 0;
@@ -235,20 +235,20 @@ ul.cplist {
}
/* Link styles for the sub-section links */
-#navigation a {
+.navigation a {
display: block;
padding: 5px;
margin: 1px 0;
text-decoration: none;
}
-#navigation a:hover {
+.navigation a:hover {
text-decoration: none;
}
/* Preferences pane layout
----------------------------------------*/
-#cp-main h2 {
+.cp-main h2 {
border-bottom: none;
padding: 0;
margin-left: 10px;
@@ -281,10 +281,6 @@ dl.mini dd {
/* PM Styles
----------------------------------------*/
-#pm-menu {
- line-height: 2.5em;
-}
-
/* Defined rules list for PM options */
ol.def-rules {
padding-left: 0;
@@ -327,7 +323,7 @@ ol.def-rules li {
}
/* Avatar gallery */
-#gallery label {
+.gallery label {
position: relative;
float: left;
margin: 10px;
@@ -341,35 +337,35 @@ ol.def-rules li {
----------------------------------------*/
@media only screen and (max-width: 900px), only screen and (max-device-width: 900px)
{
- .nojs #tabs a span, .nojs #minitabs a span {
+ .nojs .tabs a span, .nojs .minitabs a span {
max-width: 40px;
overflow: hidden;
text-overflow: ellipsis;
letter-spacing: -.5px;
}
- #cp-menu, #navigation, #cp-main {
+ .cp-menu, .navigation, .cp-main {
float: none;
width: auto;
margin: 0;
}
- #navigation {
+ .navigation {
padding: 0;
margin: 0 auto;
max-width: 320px;
}
- #navigation a {
+ .navigation a {
background-image: none;
}
- #navigation li:first-child a {
+ .navigation li:first-child a {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
- #navigation li:last-child a {
+ .navigation li:last-child a {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
diff --git a/phpBB/styles/prosilver/theme/en/stylesheet.css b/phpBB/styles/prosilver/theme/en/stylesheet.css
index bf4bd31ffc..604b299488 100644
--- a/phpBB/styles/prosilver/theme/en/stylesheet.css
+++ b/phpBB/styles/prosilver/theme/en/stylesheet.css
@@ -1,8 +1,2 @@
/* Online image */
.online { background-image: url("./icon_user_online.gif"); }
-
-.imageset.icon_user_online {
- background-image: url("./icon_user_online.gif");
- padding-left: 58px;
- padding-top: 58px;
-}
diff --git a/phpBB/styles/prosilver/theme/forms.css b/phpBB/styles/prosilver/theme/forms.css
index 777f011c35..e8efbc6045 100644
--- a/phpBB/styles/prosilver/theme/forms.css
+++ b/phpBB/styles/prosilver/theme/forms.css
@@ -96,7 +96,7 @@ fieldset.fields1 div {
}
/* Set it back to 0px for the reCaptcha divs: PHPBB3-9587 */
-fieldset.fields1 #recaptcha_widget_div div, fieldset.fields1 .live-search div {
+fieldset.fields1 .live-search div {
margin-bottom: 0;
}
@@ -138,10 +138,16 @@ dd textarea {
}
/* Hover effects */
-#timezone {
+.timezone {
width: 95%;
}
+/* Browser-specific tweaks */
+button::-moz-focus-inner {
+ padding: 0;
+ border: 0
+}
+
/* Quick-login on index page */
fieldset.quick-login {
margin-top: 5px;
@@ -177,6 +183,24 @@ fieldset.display-options a {
margin-top: 3px;
}
+.dropdown fieldset.display-options {
+ font-size: 1em;
+ margin: 0;
+ padding: 0;
+}
+
+.dropdown fieldset.display-options label {
+ display: block;
+ margin: 4px;
+ padding: 0;
+ text-align: right;
+ white-space: nowrap;
+}
+
+.dropdown fieldset.display-options select {
+ min-width: 120px;
+}
+
/* Display actions for ucp and mcp pages */
fieldset.display-actions {
text-align: right;
@@ -214,28 +238,26 @@ fieldset.submit-buttons {
fieldset.submit-buttons input {
vertical-align: middle;
- padding-top: 3px;
- padding-bottom: 3px;
}
/* Posting page styles
----------------------------------------*/
/* Buttons used in the editor */
-#format-buttons {
+.format-buttons {
margin: 15px 0 2px 0;
}
-#format-buttons input, #format-buttons select {
+.format-buttons input, .format-buttons select {
vertical-align: middle;
}
/* Main message box */
-#message-box {
+.message-box {
width: 80%;
}
-#message-box textarea {
+.message-box textarea {
font-family: "Trebuchet MS", Verdana, Helvetica, Arial, sans-serif;
width: 450px;
height: 270px;
@@ -253,12 +275,12 @@ fieldset.submit-buttons input {
}
/* Emoticons panel */
-#smiley-box {
+.smiley-box {
width: 18%;
float: right;
}
-#smiley-box img {
+.smiley-box img {
margin: 3px;
}
@@ -316,6 +338,7 @@ a.button1, input.button1, input.button3, a.button2, input.button2 {
padding-bottom: 1px;
font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
background: transparent none repeat-x top left;
+ line-height: 1.5;
}
a.button1, input.button1 {
@@ -342,18 +365,15 @@ a.button2, input.button2, input.button3 {
}
/* <a> button in the style of the form buttons */
-a.button1, a.button1:link, a.button1:visited, a.button1:active, a.button2, a.button2:link, a.button2:visited, a.button2:active {
+a.button1, a.button2 {
text-decoration: none;
- padding: 2px 8px;
- line-height: 250%;
+ padding: 0 3px;
vertical-align: text-bottom;
- background-position: 0 1px;
}
/* Hover states */
a.button1:hover, input.button1:hover, a.button2:hover, input.button2:hover, input.button3:hover {
border: 1px solid transparent;
- background-position: 0 100%;
}
input.disabled {
@@ -382,26 +402,6 @@ input.button1:focus, input.button2:focus, input.button3:focus {
box-sizing: border-box;
}
-.search-box button {
- float: left;
-}
-
-.search-box button.search-icon {
- border-radius: 0;
- font-size: 0;
- height: 24px;
- margin: 0;
- padding: 3px 5px;
-}
-
-.search-box a.button {
- border-left-width: 0;
- border-radius: 0 4px 4px 0;
- font-size: 0;
- margin: 0;
- padding: 2px 5px 2px 3px;
-}
-
/* Search box (header)
--------------------------------------------- */
.search-header {
@@ -414,16 +414,7 @@ input.button1:focus, input.button2:focus, input.button3:focus {
.search-header .inputbox { border: 0; }
-.search-header button {
- border-top: 0;
- border-bottom: 0;
-}
-
-.search-header a.button {
- border: 0;
- border-left: 1px;
- padding: 3px 5px 3px 4px;
-}
+.navbar .linklist > li.responsive-search { display: none; }
input.search {
background-image: none;
diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css
new file mode 100644
index 0000000000..9fb7244f4b
--- /dev/null
+++ b/phpBB/styles/prosilver/theme/icons.css
@@ -0,0 +1,83 @@
+/* --------------------------------------------------------------
+ $Icons
+-------------------------------------------------------------- */
+
+/* Global module setup
+--------------------------------*/
+
+/* Renamed version of .fa class for agnostic useage of icon fonts.
+ * Just change the name of the font after the 14/1 to the name of
+ * the font you wish to use.
+ */
+.icon, .button .icon {
+ display: inline-block;
+ font-weight: normal;
+ font-style: normal;
+ font-variant: normal;
+ font-family: FontAwesome;
+ font-size: 14px;
+ line-height: 1;
+ text-rendering: auto; /* optimizelegibility throws things off #1094 */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon:before { padding-right: 2px; }
+
+.button .icon:before {
+ padding-right: 0;
+}
+
+/* Icon size classes - Default size is 14px, use these for small variations */
+
+.icon.icon-xl {
+ font-size: 20px;
+}
+
+.icon.icon-lg {
+ font-size: 16px;
+}
+
+.icon.icon-md {
+ font-size: 10px;
+}
+
+.icon.icon-sm {
+ font-size: 8px;
+}
+
+/* icon modifiers */
+.icon-tiny {
+ width: 12px;
+ transform: scale(0.65, 0.75);
+ vertical-align: text-bottom;
+ font-size: 16px;
+}
+
+.arrow-left:hover .icon {
+ margin-left: -5px;
+ margin-right: 5px;
+}
+
+.arrow-right .icon {
+ float: right;
+}
+
+.arrow-right:hover .icon {
+ margin-left: 5px;
+ margin-right: -5px;
+}
+
+.post-buttons .dropdown-contents .icon {
+ float: right;
+ margin-left: 5px;
+}
+
+.alert_close .icon:before {
+ padding: 0;
+ border-radius: 50%;
+ width: 11px;
+ display: block;
+ line-height: .9;
+ height: 12px;
+}
diff --git a/phpBB/styles/prosilver/theme/images/alert_close.png b/phpBB/styles/prosilver/theme/images/alert_close.png
deleted file mode 100644
index 79750a013c..0000000000
--- a/phpBB/styles/prosilver/theme/images/alert_close.png
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/arrow_down.gif b/phpBB/styles/prosilver/theme/images/arrow_down.gif
deleted file mode 100644
index b7fbf7e276..0000000000
--- a/phpBB/styles/prosilver/theme/images/arrow_down.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/arrow_left.gif b/phpBB/styles/prosilver/theme/images/arrow_left.gif
deleted file mode 100644
index ac92cb4971..0000000000
--- a/phpBB/styles/prosilver/theme/images/arrow_left.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/arrow_right.gif b/phpBB/styles/prosilver/theme/images/arrow_right.gif
deleted file mode 100644
index 3a080ffdfe..0000000000
--- a/phpBB/styles/prosilver/theme/images/arrow_right.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/arrow_up.gif b/phpBB/styles/prosilver/theme/images/arrow_up.gif
deleted file mode 100644
index 0ff5872182..0000000000
--- a/phpBB/styles/prosilver/theme/images/arrow_up.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/bg_button.gif b/phpBB/styles/prosilver/theme/images/bg_button.gif
deleted file mode 100644
index 03172ff5c6..0000000000
--- a/phpBB/styles/prosilver/theme/images/bg_button.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/feed.gif b/phpBB/styles/prosilver/theme/images/feed.gif
deleted file mode 100644
index ff19905874..0000000000
--- a/phpBB/styles/prosilver/theme/images/feed.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/gradient.gif b/phpBB/styles/prosilver/theme/images/gradient.gif
deleted file mode 100644
index 21dc11f13b..0000000000
--- a/phpBB/styles/prosilver/theme/images/gradient.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_acp.gif b/phpBB/styles/prosilver/theme/images/icon_acp.gif
deleted file mode 100644
index 3afa98ee8f..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_acp.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_back_top.gif b/phpBB/styles/prosilver/theme/images/icon_back_top.gif
deleted file mode 100644
index 4d2b8f3822..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_back_top.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_bookmark.gif b/phpBB/styles/prosilver/theme/images/icon_bookmark.gif
deleted file mode 100644
index 2644293f7d..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_bookmark.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_bump.gif b/phpBB/styles/prosilver/theme/images/icon_bump.gif
deleted file mode 100644
index 014cd9bd15..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_bump.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_contact.png b/phpBB/styles/prosilver/theme/images/icon_contact.png
deleted file mode 100644
index 04e4d9ad17..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_contact.png
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_delete_cookies.gif b/phpBB/styles/prosilver/theme/images/icon_delete_cookies.gif
deleted file mode 100644
index f7665ebff8..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_delete_cookies.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_faq.gif b/phpBB/styles/prosilver/theme/images/icon_faq.gif
deleted file mode 100644
index 4e26460629..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_faq.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_home.gif b/phpBB/styles/prosilver/theme/images/icon_home.gif
deleted file mode 100644
index 8ae9004534..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_home.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_logout.gif b/phpBB/styles/prosilver/theme/images/icon_logout.gif
deleted file mode 100644
index b8ad5c4e5c..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_logout.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_mark.gif b/phpBB/styles/prosilver/theme/images/icon_mark.gif
deleted file mode 100644
index 1a33fc3264..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_mark.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_mcp.gif b/phpBB/styles/prosilver/theme/images/icon_mcp.gif
deleted file mode 100644
index 80de2e53f7..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_mcp.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_members.gif b/phpBB/styles/prosilver/theme/images/icon_members.gif
deleted file mode 100644
index 48e3e5f5f3..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_members.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_notification.gif b/phpBB/styles/prosilver/theme/images/icon_notification.gif
deleted file mode 100644
index 11092f4dce..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_notification.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_pages.gif b/phpBB/styles/prosilver/theme/images/icon_pages.gif
deleted file mode 100644
index 20b2fe9f81..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_pages.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_pm.gif b/phpBB/styles/prosilver/theme/images/icon_pm.gif
deleted file mode 100644
index 103421a26f..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_pm.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_post_target.gif b/phpBB/styles/prosilver/theme/images/icon_post_target.gif
deleted file mode 100644
index a2bc2a2c47..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_post_target.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_post_target_unread.gif b/phpBB/styles/prosilver/theme/images/icon_post_target_unread.gif
deleted file mode 100644
index 65d47bb900..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_post_target_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_print.gif b/phpBB/styles/prosilver/theme/images/icon_print.gif
deleted file mode 100644
index e464e304ea..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_print.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_profile.gif b/phpBB/styles/prosilver/theme/images/icon_profile.gif
deleted file mode 100644
index a0ec098460..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_profile.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_register.gif b/phpBB/styles/prosilver/theme/images/icon_register.gif
deleted file mode 100644
index 9ecf126c4f..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_register.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_search.gif b/phpBB/styles/prosilver/theme/images/icon_search.gif
deleted file mode 100644
index 8492cd308c..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_search.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_sendemail.gif b/phpBB/styles/prosilver/theme/images/icon_sendemail.gif
deleted file mode 100644
index 92a39c8af9..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_sendemail.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_subscribe.gif b/phpBB/styles/prosilver/theme/images/icon_subscribe.gif
deleted file mode 100644
index 5ca18af80a..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_subscribe.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_team.gif b/phpBB/styles/prosilver/theme/images/icon_team.gif
deleted file mode 100644
index 613158257b..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_team.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_textbox_search.gif b/phpBB/styles/prosilver/theme/images/icon_textbox_search.gif
deleted file mode 100644
index b3b51d8425..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_textbox_search.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_attach.gif b/phpBB/styles/prosilver/theme/images/icon_topic_attach.gif
deleted file mode 100644
index 70203124fe..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_attach.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_deleted.png b/phpBB/styles/prosilver/theme/images/icon_topic_deleted.png
deleted file mode 100644
index 494b4fb563..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_deleted.png
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_latest.gif b/phpBB/styles/prosilver/theme/images/icon_topic_latest.gif
deleted file mode 100644
index 815b26927a..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_latest.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_newest.gif b/phpBB/styles/prosilver/theme/images/icon_topic_newest.gif
deleted file mode 100644
index fd6652d957..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_newest.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_poll.gif b/phpBB/styles/prosilver/theme/images/icon_topic_poll.gif
deleted file mode 100644
index 1c80ec87c1..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_poll.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_reported.gif b/phpBB/styles/prosilver/theme/images/icon_topic_reported.gif
deleted file mode 100644
index 006b1e2291..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_reported.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_topic_unapproved.gif b/phpBB/styles/prosilver/theme/images/icon_topic_unapproved.gif
deleted file mode 100644
index 09d8f387a7..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_topic_unapproved.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_ucp.gif b/phpBB/styles/prosilver/theme/images/icon_ucp.gif
deleted file mode 100644
index 2a5fcc3f0c..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_ucp.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icon_unsubscribe.gif b/phpBB/styles/prosilver/theme/images/icon_unsubscribe.gif
deleted file mode 100644
index 27013fc1cb..0000000000
--- a/phpBB/styles/prosilver/theme/images/icon_unsubscribe.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icons_button.png b/phpBB/styles/prosilver/theme/images/icons_button.png
deleted file mode 100644
index 50ac8994de..0000000000
--- a/phpBB/styles/prosilver/theme/images/icons_button.png
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/icons_pagination.png b/phpBB/styles/prosilver/theme/images/icons_pagination.png
deleted file mode 100644
index 872b7308c2..0000000000
--- a/phpBB/styles/prosilver/theme/images/icons_pagination.png
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/subforum_read.gif b/phpBB/styles/prosilver/theme/images/subforum_read.gif
deleted file mode 100644
index 595595c296..0000000000
--- a/phpBB/styles/prosilver/theme/images/subforum_read.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/images/subforum_unread.gif b/phpBB/styles/prosilver/theme/images/subforum_unread.gif
deleted file mode 100644
index b2b661dc78..0000000000
--- a/phpBB/styles/prosilver/theme/images/subforum_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/prosilver/theme/imageset.css b/phpBB/styles/prosilver/theme/imageset.css
deleted file mode 100644
index 5cd91348be..0000000000
--- a/phpBB/styles/prosilver/theme/imageset.css
+++ /dev/null
@@ -1,376 +0,0 @@
-/* Former imageset */
-span.imageset {
- display: inline-block !important;
- background: transparent none 0 0 no-repeat;
- margin: 0;
- padding: 0;
- width: 0;
- height: 0;
- overflow: hidden;
-}
-
-/* Global imageset items */
-.imageset.site_logo {
- background-image: url("./images/site_logo.gif");
- padding-left: 149px;
- padding-top: 52px;
-}
-.imageset.forum_link {
- background-image: url("./images/forum_link.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.forum_read {
- background-image: url("./images/forum_read.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.forum_read_locked {
- background-image: url("./images/forum_read_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.forum_read_subforum {
- background-image: url("./images/forum_read_subforum.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.forum_unread {
- background-image: url("./images/forum_unread.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.forum_unread_locked {
- background-image: url("./images/forum_unread_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.forum_unread_subforum {
- background-image: url("./images/forum_unread_subforum.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_moved {
- background-image: url("./images/topic_moved.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_read {
- background-image: url("./images/topic_read.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_read_mine {
- background-image: url("./images/topic_read_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_read_hot {
- background-image: url("./images/topic_read_hot.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_read_hot_mine {
- background-image: url("./images/topic_read_hot_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_read_locked {
- background-image: url("./images/topic_read_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_read_locked_mine {
- background-image: url("./images/topic_read_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_unread {
- background-image: url("./images/topic_unread.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_unread_mine {
- background-image: url("./images/topic_unread_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_unread_hot {
- background-image: url("./images/topic_unread_hot.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_unread_hot_mine {
- background-image: url("./images/topic_unread_hot_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_unread_locked {
- background-image: url("./images/topic_unread_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.topic_unread_locked_mine {
- background-image: url("./images/topic_unread_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_read {
- background-image: url("./images/sticky_read.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_read_mine {
- background-image: url("./images/sticky_read_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_read_locked {
- background-image: url("./images/sticky_read_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_read_locked_mine {
- background-image: url("./images/sticky_read_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_unread {
- background-image: url("./images/sticky_unread.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_unread_mine {
- background-image: url("./images/sticky_unread_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_unread_locked {
- background-image: url("./images/sticky_unread_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.sticky_unread_locked_mine {
- background-image: url("./images/sticky_unread_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_read {
- background-image: url("./images/announce_read.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_read_mine {
- background-image: url("./images/announce_read_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_read_locked {
- background-image: url("./images/announce_read_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_read_locked_mine {
- background-image: url("./images/announce_read_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_unread {
- background-image: url("./images/announce_unread.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_unread_mine {
- background-image: url("./images/announce_unread_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_unread_locked {
- background-image: url("./images/announce_unread_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.announce_unread_locked_mine {
- background-image: url("./images/announce_unread_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_read {
- background-image: url("./images/announce_read.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_read_mine {
- background-image: url("./images/announce_read_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_read_locked {
- background-image: url("./images/announce_read_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_read_locked_mine {
- background-image: url("./images/announce_read_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_unread {
- background-image: url("./images/announce_unread.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_unread_mine {
- background-image: url("./images/announce_unread_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_unread_locked {
- background-image: url("./images/announce_unread_locked.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.global_unread_locked_mine {
- background-image: url("./images/announce_unread_locked_mine.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.subforum_read {
- background-image: url("./images/subforum_read.gif");
- padding-left: 11px;
- padding-top: 9px;
-}
-.imageset.subforum_unread {
- background-image: url("./images/subforum_unread.gif");
- padding-left: 11px;
- padding-top: 9px;
-}
-.imageset.pm_read {
- background-image: url("./images/topic_read.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.pm_unread {
- background-image: url("./images/topic_unread.gif");
- padding-left: 27px;
- padding-top: 27px;
-}
-.imageset.icon_back_top {
- background-image: url("./images/icon_back_top.gif");
- padding-left: 11px;
- padding-top: 11px;
-}
-.imageset.phpbb_aol-icon, .imageset.icon_contact_aim {
- background-image: url("./images/icon_contact_aim.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_contact_email {
- background-image: url("./images/icon_contact_email.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_contact_icq, .imageset.phpbb_icq-icon {
- background-image: url("./images/icon_contact_icq.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_contact_jabber {
- background-image: url("./images/icon_contact_jabber.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.phpbb_wlm-icon, .imageset.icon_contact_msnm {
- background-image: url("./images/icon_contact_msnm.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_contact_www, .imageset.phpbb_website-icon {
- background-image: url("./images/icon_contact_www.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_contact_yahoo, .imageset.phpbb_yahoo-icon {
- background-image: url("./images/icon_contact_yahoo.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_delete {
- background-image: url("./images/icon_post_delete.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_info {
- background-image: url("./images/icon_post_info.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_report {
- background-image: url("./images/icon_post_report.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_target {
- background-image: url("./images/icon_post_target.gif");
- padding-left: 11px;
- padding-top: 9px;
-}
-.imageset.icon_post_target_unread {
- background-image: url("./images/icon_post_target_unread.gif");
- padding-left: 11px;
- padding-top: 9px;
-}
-.imageset.icon_topic_attach {
- background-image: url("./images/icon_topic_attach.gif");
- padding-left: 7px;
- padding-top: 10px;
-}
-.imageset.icon_topic_latest {
- background-image: url("./images/icon_topic_latest.gif");
- padding-left: 11px;
- padding-top: 9px;
-}
-.imageset.icon_topic_newest {
- background-image: url("./images/icon_topic_newest.gif");
- padding-left: 11px;
- padding-top: 9px;
-}
-.imageset.icon_topic_reported {
- background-image: url("./images/icon_topic_reported.gif");
- padding-left: 16px;
- padding-top: 14px;
-}
-.imageset.icon_topic_deleted {
- background-image: url("./images/icon_topic_deleted.png");
- padding-left: 16px;
- padding-top: 14px;
-}
-.imageset.icon_topic_unapproved {
- background-image: url("./images/icon_topic_unapproved.gif");
- padding-left: 16px;
- padding-top: 14px;
-}
-.imageset.icon_topic_poll {
- background-image: url("./images/icon_topic_poll.gif");
- padding-left: 11px;
- padding-top: 10px;
-}
-.imageset.icon_user_warn {
- background-image: url("./images/icon_user_warn.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-
-.imageset.icon_contact {
- background-image: url("./images/icon_contact.png");
- padding-left: 16px;
- padding-top: 12px;
-}
-
-
-/* English images for fallback */
-.imageset.icon_user_online {
- background-image: url("./en/icon_user_online.gif");
- padding-left: 58px;
- padding-top: 58px;
-}
diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css
index a2f512443c..6da14c9326 100644
--- a/phpBB/styles/prosilver/theme/links.css
+++ b/phpBB/styles/prosilver/theme/links.css
@@ -6,9 +6,11 @@ a {
direction: ltr;
unicode-bidi: embed;
text-decoration: none;
-}
+ /* we use links inline more often then not so to address several bugs with
+ IE and some other browsers we render all links as inlineblock by default */
+ display: inline-block;
-a:hover { text-decoration: underline; }
+}
/* Coloured usernames */
.username-coloured {
@@ -26,12 +28,6 @@ a:hover { text-decoration: underline; }
text-decoration: underline;
}
-/* Navigation bar links */
-li.breadcrumbs span:first-child > a {
- display: inline-block;
- padding-left: 17px;
-}
-
/* Notification mark read link */
.dropdown-extended a.mark_read {
background-position: center center;
@@ -43,8 +39,6 @@ li.breadcrumbs span:first-child > a {
z-index: 2;
right: 0;
top: 50%;
- width: 30px;
- height: 40px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
@@ -55,9 +49,13 @@ li.breadcrumbs span:first-child > a {
}
.dropdown-extended a.mark_read:hover {
- width: 40px;
+ width: 50px;
}
+.jumpbox-cat-link,
+.jumpbox-forum-link { font-weight: bold; }
+
+
/* Links for forum/topic lists */
a.forumtitle {
font-family: "Trebuchet MS", Helvetica, Arial, Sans-serif;
@@ -75,6 +73,7 @@ a.topictitle {
font-size: 1.2em;
font-weight: bold;
text-decoration: none;
+ display: inline;
}
a.topictitle:hover {
@@ -126,72 +125,49 @@ a.lastsubject:hover {
text-decoration: underline;
}
+.top {
+ font-size: 12px;
+ text-decoration: none;
+ margin-top: 10px;
+}
+
/* Back to top of page */
.back2top {
clear: both;
- height: 11px;
- text-align: right;
}
-a.top {
- background: none no-repeat top left;
- text-decoration: none;
- width: 11px;
- height: 11px;
- display: block;
+.back2top .top {
float: right;
- overflow: hidden;
- letter-spacing: 1000px;
- text-indent: 11px;
-}
-
-a.top2 {
- background: none no-repeat 0 50%;
- text-decoration: none;
- padding-left: 15px;
+ margin-right: -10px;
+ margin-top: 0;
}
/* Arrow links */
-a.arrow-up { background: none no-repeat left center; }
-a.arrow-down { background: none no-repeat right center; }
-a.arrow-left { background: none no-repeat 3px 60%; }
-a.arrow-right { background: none no-repeat 95% 60%; }
-a.arrow-up {
+.arrow-up {
padding-left: 10px;
text-decoration: none;
border-bottom-width: 0;
}
-a.arrow-up:hover {
- background-position: left top;
+.arrow-up:hover {
+
}
-a.arrow-down {
+.arrow-down {
padding-right: 10px;
}
-a.arrow-down:hover {
- background-position: right bottom;
- text-decoration: none;
-}
+.arrow-down:hover {
-a.arrow-left {
- padding-left: 12px;
}
-a.arrow-left:hover {
+.arrow-left:hover {
text-decoration: none;
- background-position: 0 60%;
-}
-
-a.arrow-right {
- padding-right: 12px;
}
-a.arrow-right:hover {
+.arrow-right:hover {
text-decoration: none;
- background-position: 100% 60%;
}
/* invisible skip link, used for accessibility */
diff --git a/phpBB/styles/prosilver/theme/normalize.css b/phpBB/styles/prosilver/theme/normalize.css
new file mode 100644
index 0000000000..23d84492c8
--- /dev/null
+++ b/phpBB/styles/prosilver/theme/normalize.css
@@ -0,0 +1,424 @@
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS and IE text size adjust after device orientation change,
+ * without disabling user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability of focused elements when they are also in an
+ * active/hover state.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ box-sizing: content-box; /* 2 */
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
diff --git a/phpBB/styles/prosilver/theme/plupload.css b/phpBB/styles/prosilver/theme/plupload.css
index b17cca5f25..f466803964 100644
--- a/phpBB/styles/prosilver/theme/plupload.css
+++ b/phpBB/styles/prosilver/theme/plupload.css
@@ -1,9 +1,9 @@
-#attach-panel-multi {
+.attach-panel-multi {
display: none;
margin-bottom: 1em;
}
-#file-list td {
+.file-list td {
vertical-align: middle;
}
@@ -37,11 +37,11 @@
float: right;
}
-#attach-row-tpl, .nojs .file-inline-bbcode {
+.nojs .file-inline-bbcode {
display: none;
}
-#file-total-progress {
+.file-total-progress {
height: 2px;
display: block;
position: relative;
@@ -55,7 +55,7 @@
width: 50px;
}
-.file-progress-bar, #file-total-progress-bar {
+.file-progress-bar, .file-total-progress-bar {
background-color: green;
display: block;
height: 100%;
diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css
index 34129c92e8..a3295ac367 100644
--- a/phpBB/styles/prosilver/theme/print.css
+++ b/phpBB/styles/prosilver/theme/print.css
@@ -19,14 +19,14 @@ a:link { color: #000000; text-decoration: none; }
a:visited { color: #000000; text-decoration: none; }
a:active { color: #000000; text-decoration: none; }
-img, .noprint, #sub-header, #sub-footer, .navbar, .box1, .divider, .signature { display: none; }
+img, .noprint, .navbar, .box1, .divider, .signature { display: none; }
/* Display smilies (Bug #47265) */
.content img {
display: inline;
}
/* Container for the main body */
-#wrap {
+.wrap {
margin: 0 2em;
}
diff --git a/phpBB/styles/prosilver/theme/responsive.css b/phpBB/styles/prosilver/theme/responsive.css
index 8653042a69..d71fd142e6 100644
--- a/phpBB/styles/prosilver/theme/responsive.css
+++ b/phpBB/styles/prosilver/theme/responsive.css
@@ -1,167 +1,110 @@
/* Responsive Design
---------------------------------------- */
-.responsive-hide { display: none !important; }
-.responsive-show { display: block !important; }
-.responsive-show-inline { display: inline !important; }
-.responsive-show-inline-block { display: inline-block !important; }
-
-/* Content wrappers
-----------------------------------------*/
-html {
- height: auto;
-}
-
-body {
- padding: 0;
-}
-
-#wrap {
- border: none;
- border-radius: 0;
- margin: 0;
- min-width: 290px;
- padding: 0 5px;
+@media (max-width: 320px) {
+ select, .inputbox {
+ max-width: 240px;
+ }
}
-/* Common block wrappers
+/* Notifications list
----------------------------------------*/
-.headerbar, .navbar, .forabg, .forumbg, .post, .panel {
- border-radius: 0;
- margin-left: -5px;
- margin-right: -5px;
+@media (max-width: 350px) {
+ .dropdown-extended .dropdown-contents {
+ width: auto;
+ }
}
-#cp-main .forabg, #cp-main .forumdb, #cp-main .post, #cp-main .panel {
- border-radius: 7px;
-}
+@media (max-width: 430px) {
+ .action-bar .search-box .inputbox {
+ width: 120px;
+ }
-/* Logo block
-----------------------------------------*/
-#site-description {
- float: none;
- width: auto;
- text-align: center;
-}
+ .section-viewtopic .search-box .inputbox {
+ width: 57px;
+ }
-.logo {
- /* change display value to inline-block to show logo */
- display: none;
- float: none;
- padding: 10px;
-}
+ .action-bar .search-box .inputbox ::-moz-placeholder {
+ content: "Search...";
+ }
-#site-description h1, #site-description p {
- text-align: inherit;
- float: none;
- margin: 5px;
- line-height: 1.2em;
- overflow: hidden;
- text-overflow: ellipsis;
-}
+ .action-bar .search-box .inputbox :-ms-input-placeholder {
+ content: "Search...";
+ }
-#site-description p, .search-header {
- display: none;
+ .action-bar .search-box .inputbox ::-webkit-input-placeholder {
+ content: "Search...";
+ }
}
-/* Navigation
-----------------------------------------*/
-.headerbar + .navbar {
- margin-top: -5px;
-}
+@media (max-width: 500px) {
+ dd label {
+ white-space: normal;
+ }
-/* Search
-----------------------------------------*/
-.responsive-search { display: block !important; }
-.responsive-search a {
- display: block;
- width: 16px;
- height: 22px;
- text-indent: 99px;
- overflow: hidden;
- background-position: 50% 50%;
- background-repeat: no-repeat;
- text-decoration: none;
-}
+ select, .inputbox {
+ max-width: 260px;
+ }
-/* .topiclist lists
-----------------------------------------*/
-li.header dt {
- text-align: center;
- text-transform: none;
- line-height: 1em;
- font-size: 1.2em;
- padding-bottom: 4px;
-}
+ .captcha-panel dd.captcha {
+ margin-left: 0;
+ }
-ul.topiclist li.header dt, ul.topiclist li.header dt .list-inner {
- margin-right: 0 !important;
- padding-right: 0;
-}
+ .captcha-panel dd.captcha-image img {
+ width: 100%;
+ }
-ul.topiclist li.header dd {
- display: none !important;
-}
+ dl.details dt, dl.details dd {
+ width: auto;
+ float: none;
+ text-align: left;
+ }
-ul.topiclist dt, ul.topiclist dt .list-inner,
-ul.topiclist.missing-column dt, ul.topiclist.missing-column dt .list-inner,
-ul.topiclist.two-long-columns dt, ul.topiclist.two-long-columns dt .list-inner,
-ul.topiclist.two-columns dt, ul.topiclist.two-columns dt .list-inner {
- margin-right: 0;
-}
+ dl.details dd {
+ margin-left: 20px;
+ }
-ul.topiclist dt .list-inner.with-mark {
- padding-right: 34px;
-}
+ p.responsive-center {
+ float: none;
+ text-align: center;
+ margin-bottom: 5px;
+ }
-ul.topiclist dt .list-inner {
- min-height: 28px;
-}
+ .action-bar > div {
+ margin-bottom: 5px;
+ }
-ul.topiclist li.header dt .list-inner {
- min-height: 0;
-}
+ .action-bar > .pagination {
+ float: none;
+ clear: both;
+ padding-bottom: 1px;
+ text-align: center;
+ }
-ul.topiclist dd {
- display: none;
-}
-ul.topiclist dd.mark {
- display: block;
-}
+ .action-bar > .pagination li.page-jump {
+ margin: 0 2px;
+ }
-/* Forums and topics lists
-----------------------------------------*/
-ul.topiclist.forums dt {
- margin-right: -250px;
-}
-ul.topiclist.forums dt .list-inner {
- margin-right: 250px;
-}
+ p.jumpbox-return {
+ display: none;
+ }
-ul.topiclist.forums dd.lastpost {
- display: block;
-}
+ .display-options > label:nth-child(1) {
+ display: block;
+ margin-bottom: 5px;
+ }
-ul.topiclist dd.mark {
- display: block;
- position: absolute;
- right: 5px;
- top: 0;
- margin: 0;
- width: auto;
- min-width: 0;
- text-align: left;
-}
+ .attach-controls {
+ margin-top: 5px;
+ width: 100%;
+ }
-ul.topiclist.forums dd.topics dfn, ul.topiclist.topics dd.posts dfn {
- position: relative;
- left: 0;
- width: auto;
- display: inline;
- font-weight: normal;
+ .quick-links .dropdown-trigger span {
+ display: none;
+ }
}
-@media only screen and (max-width: 550px), only screen and (max-device-width: 550px) {
+@media (max-width: 550px) {
ul.topiclist.forums dt {
margin-right: 0;
}
@@ -175,400 +118,473 @@ ul.topiclist.forums dd.topics dfn, ul.topiclist.topics dd.posts dfn {
}
}
-li.row .responsive-show strong {
- font-weight: bold;
- color: inherit;
-}
-
-ul.topiclist li.row dt a.subforum {
- display: inline-block;
- vertical-align: bottom;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 100px;
-}
+@media (max-width: 700px) {
+ .responsive-hide { display: none !important; }
+ .responsive-show { display: block !important; }
+ .responsive-show-inline { display: inline !important; }
+ .responsive-show-inline-block { display: inline-block !important; }
-/* Notifications list
-----------------------------------------*/
-@media only screen and (max-width: 350px), only screen and (max-device-width: 350px) {
- .dropdown-extended .dropdown-contents {
- width: auto;
+ /* Content wrappers
+ ----------------------------------------*/
+ html {
+ height: auto;
}
-}
-
-/* Pagination
-----------------------------------------*/
-.pagination > ul {
- margin: 5px 0 0;
-}
-
-.row .pagination .ellipsis + li {
- display: none !important;
-}
-
-/* Responsive tables
-----------------------------------------*/
-table.responsive, table.responsive tbody, table.responsive tr, table.responsive td {
- display: block;
-}
-table.responsive thead, table.responsive th {
- display: none;
-}
+ body {
+ padding: 0;
+ }
-table.responsive.show-header thead, table.responsive.show-header th:first-child {
- display: block;
- width: auto !important;
- text-align: left !important;
-}
+ .wrap {
+ border: none;
+ border-radius: 0;
+ margin: 0;
+ min-width: 290px;
+ padding: 0 5px;
+ }
-table.responsive.show-header th:first-child span.rank-img {
- display: none;
-}
+ /* Common block wrappers
+ ----------------------------------------*/
+ .headerbar, .navbar, .forabg, .forumbg, .post, .panel {
+ border-radius: 0;
+ margin-left: -5px;
+ margin-right: -5px;
+ }
-table.responsive tr {
- margin: 2px 0;
-}
+ .cp-main .forabg, .cp-main .forumdb, .cp-main .post, .cp-main .panel {
+ border-radius: 7px;
+ }
-table.responsive td {
- width: auto !important;
- text-align: left !important;
- padding: 4px;
-}
+ /* Logo block
+ ----------------------------------------*/
+ .site-description {
+ float: none;
+ width: auto;
+ text-align: center;
+ }
-table.responsive td.empty {
- display: none !important;
-}
+ .logo {
+ /* change display value to inline-block to show logo */
+ display: none;
+ float: none;
+ padding: 10px;
+ }
-table.responsive td > dfn {
- display: inline-block !important;
-}
+ .site-description h1, .site-description p {
+ text-align: inherit;
+ float: none;
+ margin: 5px;
+ line-height: 1.2em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
-table.responsive td > dfn:after {
- content: ':';
- padding-right: 5px;
-}
+ .site-description p, .search-header {
+ display: none;
+ }
-table.responsive span.rank-img {
- float: none;
- padding-right: 5px;
-}
+ /* Navigation
+ ----------------------------------------*/
+ .headerbar + .navbar {
+ margin-top: -5px;
+ }
-table.responsive#memberlist td:first-child input[type="checkbox"] {
- float: right;
-}
+ /* Search
+ ----------------------------------------*/
+ .responsive-search { display: block !important; }
-/* Forms
-----------------------------------------*/
-fieldset dt, fieldset.fields1 dt, fieldset.fields2 dt {
- width: auto;
- float: none;
-}
+ /* .topiclist lists
+ ----------------------------------------*/
+ li.header dt {
+ text-align: center;
+ text-transform: none;
+ line-height: 1em;
+ font-size: 1.2em;
+ padding-bottom: 4px;
+ }
-fieldset dd, fieldset.fields1 dd, fieldset.fields2 dd {
- margin-left: 20px;
-}
+ ul.topiclist li.header dt, ul.topiclist li.header dt .list-inner {
+ margin-right: 0 !important;
+ padding-right: 0;
+ }
-textarea, dd textarea, #message-box textarea {
- width: 100%;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
+ ul.topiclist li.header dd {
+ display: none !important;
+ }
-dl.pmlist dt {
- width: auto !important;
- margin-bottom: 5px;
-}
+ ul.topiclist dt, ul.topiclist dt .list-inner,
+ ul.topiclist.missing-column dt, ul.topiclist.missing-column dt .list-inner,
+ ul.topiclist.two-long-columns dt, ul.topiclist.two-long-columns dt .list-inner,
+ ul.topiclist.two-columns dt, ul.topiclist.two-columns dt .list-inner {
+ margin-right: 0;
+ }
-dl.pmlist dd {
- display: inline-block;
- margin-left: 0 !important;
-}
+ ul.topiclist dt .list-inner.with-mark {
+ padding-right: 34px;
+ }
-dl.pmlist dd:first-of-type {
- padding-left: 20px;
-}
+ ul.topiclist dt .list-inner {
+ min-height: 28px;
+ }
-#smiley-box, #message-box {
- float: none;
- width: auto;
-}
+ ul.topiclist li.header dt .list-inner {
+ min-height: 0;
+ }
-#smiley-box {
- margin-top: 5px;
-}
+ ul.topiclist dd {
+ display: none;
+ }
+ ul.topiclist dd.mark {
+ display: block;
+ }
-.bbcode-status {
- display: none;
-}
+ /* Forums and topics lists
+ ----------------------------------------*/
+ ul.topiclist.forums dt {
+ margin-right: -250px;
+ }
-.colour-palette, .colour-palette tbody, .colour-palette tr {
- display: block;
-}
+ ul.topiclist dd.mark {
+ display: block;
+ position: absolute;
+ right: 5px;
+ top: 0;
+ margin: 0;
+ width: auto;
+ min-width: 0;
+ text-align: left;
+ }
-.colour-palette td {
- display: inline-block;
- margin-right: 2px;
-}
+ ul.topiclist.forums dd.topics dfn, ul.topiclist.topics dd.posts dfn {
+ position: relative;
+ left: 0;
+ width: auto;
+ display: inline;
+ font-weight: normal;
+ }
-.horizontal-palette td:nth-child(2n), .vertical-palette tr:nth-child(2n) {
- display: none;
-}
+ li.row .responsive-show strong {
+ font-weight: bold;
+ color: inherit;
+ }
-.colour-palette a {
- display: inline-block !important;
-}
+ ul.topiclist li.row dt a.subforum {
+ vertical-align: bottom;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100px;
+ }
-fieldset.quick-login label {
- display: block;
- margin-bottom: 5px;
- white-space: normal;
-}
+ /* Pagination
+ ----------------------------------------*/
+ .pagination > ul {
+ margin: 5px 0 0;
+ }
-fieldset.quick-login label > span {
- display: inline-block;
- min-width: 100px;
-}
+ .row .pagination {
+ margin-top: 2px;
+ margin-bottom: 2px;
+ }
-fieldset.quick-login input.inputbox {
- width: 85%;
- max-width: 300px;
- margin-left: 20px;
-}
+ .row .pagination .ellipsis + li {
+ display: none !important;
+ }
-fieldset.quick-login label[for="autologin"] {
- display: inline-block;
- text-align: right;
- min-width: 50%;
-}
+ /* Responsive tables
+ ----------------------------------------*/
+ table.responsive, table.responsive tbody, table.responsive tr, table.responsive td {
+ display: block;
+ }
-@media only screen and (max-width: 500px), only screen and (max-device-width: 500px) {
- dd label {
- white-space: normal;
+ table.responsive thead, table.responsive th {
+ display: none;
}
- select, .inputbox {
- max-width: 260px;
+ table.responsive.show-header thead, table.responsive.show-header th:first-child {
+ display: block;
+ width: auto !important;
+ text-align: left !important;
}
- .captcha-panel dd.captcha {
- margin-left: 0;
+ table.responsive.show-header th:first-child span.rank-img {
+ display: none;
}
- .captcha-panel dd.captcha-image img {
- width: 100%;
+ table.responsive tr {
+ margin: 2px 0;
}
- #recaptcha_challenge_image,
- #recaptcha_response_field,
- .recaptchatable #recaptcha_image {
- width: 100% !important;
- height: auto !important;
+ table.responsive td {
+ width: auto !important;
+ text-align: left !important;
+ padding: 4px;
}
- .recaptchatable tr td:last-child {
- display: none;
+ table.responsive td.empty {
+ display: none !important;
}
- .captcha-panel .recaptcha-responsive {
+ table.responsive td > dfn {
display: inline-block !important;
- margin-top: 10px;
- vertical-align: middle;
}
-}
-@media only screen and (max-width: 430px), only screen and (max-device-width: 430px) {
- .section-viewtopic .search-box .inputbox {
- width: 110px;
+ table.responsive td > dfn:after {
+ content: ':';
+ padding-right: 5px;
}
-}
-@media only screen and (max-width: 320px), only screen and (max-device-width: 320px) {
- select, .inputbox {
- max-width: 240px;
+ table.responsive span.rank-img {
+ float: none;
+ padding-right: 5px;
}
-}
-/* User profile
-----------------------------------------*/
-.column1, .column2, .left-box.profile-details {
- float: none;
- width: auto;
-}
+ table.responsive.memberlist td:first-child input[type="checkbox"] {
+ float: right;
+ }
-@media only screen and (max-width: 500px), only screen and (max-device-width: 500px) {
- dl.details dt, dl.details dd {
+ /* Forms
+ ----------------------------------------*/
+ fieldset dt, fieldset.fields1 dt, fieldset.fields2 dt {
width: auto;
float: none;
- text-align: left;
}
- dl.details dd {
+ fieldset dd, fieldset.fields1 dd, fieldset.fields2 dd {
margin-left: 20px;
}
-}
-/* Polls
-----------------------------------------*/
-fieldset.polls dt {
- width: 90%;
-}
+ textarea, dd textarea, .message-box textarea {
+ width: 100%;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
-fieldset.polls dd.resultbar {
- padding-left: 20px;
-}
+ dl.pmlist dt {
+ width: auto !important;
+ margin-bottom: 5px;
+ }
-fieldset.polls dd.poll_option_percent {
- width: 20%;
-}
+ dl.pmlist dd {
+ display: inline-block;
+ margin-left: 0 !important;
+ }
-fieldset.polls dd.resultbar, fieldset.polls dd.poll_option_percent {
- margin-top: 5px;
-}
+ dl.pmlist dd:first-of-type {
+ padding-left: 20px;
+ }
-/* Post
-----------------------------------------*/
-.postbody {
- position: inherit;
-}
+ .smiley-box, .message-box {
+ float: none;
+ width: auto;
+ }
-.postprofile, .postbody, .search .postbody {
- display: block;
- width: auto;
- float: none;
- padding: 0;
- min-height: 0;
-}
+ .smiley-box {
+ margin-top: 5px;
+ }
-.post .postprofile {
- width: auto;
- border-width: 0 0 1px 0;
- padding-bottom: 5px;
- margin: 0;
- margin-bottom: 5px;
- min-height: 40px;
- overflow: hidden;
-}
+ .bbcode-status {
+ display: none;
+ }
-.postprofile dd {
- display: none;
-}
+ .colour-palette, .colour-palette tbody, .colour-palette tr {
+ display: block;
+ }
-.postprofile dt, .postprofile dd.profile-rank, .search .postprofile dd {
- display: block;
- margin: 0;
-}
+ .colour-palette td {
+ display: inline-block;
+ margin-right: 2px;
+ }
-.postprofile .has-avatar .avatar-container {
- margin: 0;
- overflow: inherit;
-}
+ .horizontal-palette td:nth-child(2n), .vertical-palette tr:nth-child(2n) {
+ display: none;
+ }
-.postprofile .avatar-container:after {
- clear: none;
-}
+ fieldset.quick-login label {
+ display: block;
+ margin-bottom: 5px;
+ white-space: normal;
+ }
-.postprofile .avatar {
- margin-right: 5px;
-}
+ fieldset.quick-login label > span {
+ display: inline-block;
+ min-width: 100px;
+ }
-.postprofile .avatar img {
- width: auto !important;
- height: auto !important;
- max-height: 32px;
-}
+ fieldset.quick-login input.inputbox {
+ width: 85%;
+ max-width: 300px;
+ margin-left: 20px;
+ }
-.has-profile .postbody h3 {
- margin-left: 0 !important;
- margin-right: 0 !important;
-}
+ fieldset.quick-login label[for="autologin"] {
+ display: inline-block;
+ text-align: right;
+ min-width: 50%;
+ }
-.has-profile .post-buttons {
- right: 20px;
- top: 15px;
-}
+ /* User profile
+ ----------------------------------------*/
+ .column1, .column2, .left-box.profile-details {
+ float: none;
+ width: auto;
+ }
-.online {
- background-size: 40px;
-}
+ /* Polls
+ ----------------------------------------*/
+ fieldset.polls dt {
+ width: 90%;
+ }
-/* Misc stuff
-----------------------------------------*/
-h2 {
- margin-top: .5em;
-}
+ fieldset.polls dd.resultbar {
+ padding-left: 20px;
+ }
-p {
- margin-bottom: .5em;
- overflow: hidden;
-}
+ fieldset.polls dd.poll_option_percent {
+ width: 20%;
+ }
-p.rightside {
- margin-bottom: 0;
-}
+ fieldset.polls dd.resultbar, fieldset.polls dd.poll_option_percent {
+ margin-top: 5px;
+ }
-fieldset.display-options label {
- display: block;
- clear: both;
- margin-bottom: 5px;
-}
+ /* Post
+ ----------------------------------------*/
+ .postbody {
+ position: inherit;
+ }
-dl.mini dd.pm-legend {
- float: left;
- min-width: 200px;
-}
+ .postprofile, .postbody, .search .postbody {
+ display: block;
+ width: auto;
+ float: none;
+ padding: 0;
+ min-height: 0;
+ }
-#topicreview {
- margin: 0 -5px;
- padding: 0 5px;
-}
+ .post .postprofile {
+ width: auto;
+ border-width: 0 0 1px 0;
+ padding-bottom: 5px;
+ margin: 0;
+ margin-bottom: 5px;
+ min-height: 40px;
+ overflow: hidden;
+ }
-fieldset.display-actions {
- white-space: normal;
-}
+ .postprofile dd {
+ display: none;
+ }
-.phpbb_alert {
- width: auto;
- margin: 0 5px;
-}
+ .postprofile dt, .postprofile dd.profile-rank, .search .postprofile dd {
+ display: block;
+ margin: 0;
+ }
-.attach-comment dfn {
- width: 100%;
-}
+ .postprofile .has-avatar .avatar-container {
+ margin: 0;
+ overflow: inherit;
+ }
-@media only screen and (max-width: 500px), only screen and (max-device-width: 500px) {
- p.responsive-center {
- float: none;
- text-align: center;
- margin-bottom: 5px;
+ .postprofile .avatar-container:after {
+ clear: none;
}
- .action-bar > div {
- margin-bottom: 5px;
- }
+ .postprofile .avatar {
+ margin-right: 5px;
+ }
- .action-bar > .pagination {
- float: none;
- clear: both;
- padding-bottom: 1px;
- text-align: center;
+ .postprofile .avatar img {
+ width: auto !important;
+ height: auto !important;
+ max-height: 32px;
}
- .action-bar > .pagination li.page-jump {
- margin: 0 2px;
+ .has-profile .postbody h3 {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
}
- p.jumpbox-return {
- display: none;
+ .has-profile .post-buttons {
+ right: 30px;
+ top: 15px;
}
- .display-options > label:nth-child(1) {
+ .online {
+ background-size: 40px;
+ }
+
+ /* Misc stuff
+ ----------------------------------------*/
+ h2 {
+ margin-top: .5em;
+ }
+
+ p {
+ margin-bottom: .5em;
+ overflow: hidden;
+ }
+
+ p.rightside {
+ margin-bottom: 0;
+ }
+
+ fieldset.display-options label {
display: block;
+ clear: both;
margin-bottom: 5px;
}
- .attach-controls {
- margin-top: 5px;
+ dl.mini dd.pm-legend {
+ float: left;
+ min-width: 200px;
+ }
+
+ .topicreview {
+ margin: 0 -5px;
+ padding: 0 5px;
+ }
+
+ fieldset.display-actions {
+ white-space: normal;
+ }
+
+ .phpbb_alert {
+ width: auto;
+ margin: 0 5px;
+ }
+
+ .attach-comment dfn {
width: 100%;
}
}
+
+@media (min-width: 700px) {
+ .postbody { width: 70%; }
+}
+
+@media (min-width: 850px) {
+ .postbody { width: 76%; }
+}
+
+@media (max-width: 850px) {
+ .postprofile { width: 28%; }
+}
+
+@media (min-width: 701px) and (max-width: 950px) {
+ .row .pagination {
+ margin-top: 2px;
+ margin-bottom: 2px;
+ }
+
+ ul.topiclist dt {
+ margin-right: -410px;
+ }
+
+ ul.topiclist dt .list-inner {
+ margin-right: 410px;
+ }
+
+ dd.posts, dd.topics, dd.views {
+ width: 80px;
+ }
+}
+
diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css
index 77c7c88b07..f235f6030e 100644
--- a/phpBB/styles/prosilver/theme/stylesheet.css
+++ b/phpBB/styles/prosilver/theme/stylesheet.css
@@ -1,17 +1,21 @@
/* phpBB3 Style Sheet
--------------------------------------------------------------
Style name: prosilver (the default phpBB 3.1.x style)
- Based on style:
+ Based on style:
Original author: Tom Beddard ( http://www.subblue.com/ )
Modified by: phpBB Limited ( https://www.phpbb.com/ )
--------------------------------------------------------------
*/
+@import url("normalize.css");
+@import url("base.css");
+@import url("utilities.css");
@import url("common.css");
@import url("links.css");
@import url("content.css");
@import url("buttons.css");
@import url("cp.css");
@import url("forms.css");
+@import url("icons.css");
@import url("colours.css");
-@import url("imageset.css");
+@import url("responsive.css");
diff --git a/phpBB/styles/prosilver/theme/tweaks.css b/phpBB/styles/prosilver/theme/tweaks.css
index d2dad9e299..ba82551f85 100644
--- a/phpBB/styles/prosilver/theme/tweaks.css
+++ b/phpBB/styles/prosilver/theme/tweaks.css
@@ -27,3 +27,15 @@ dd label input { vertical-align: text-bottom\9; }
.search-header, .search-header .inputbox, .search-header a.button {
border-radius: 0;
}
+
+.headerbar, .forumbg {
+ background-image: url("./images/bg_header.gif");
+}
+
+.forabg {
+ background-image: url("./images/bg_list.gif");
+}
+
+.tabs .tab > a {
+ border-radius: 0;
+}
diff --git a/phpBB/styles/prosilver/theme/utilities.css b/phpBB/styles/prosilver/theme/utilities.css
new file mode 100644
index 0000000000..cbb8127d1c
--- /dev/null
+++ b/phpBB/styles/prosilver/theme/utilities.css
@@ -0,0 +1,66 @@
+/* --------------------------------------------------------------
+ $Utilities
+-------------------------------------------------------------- */
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
+
+.clearfix:before,
+.clearfix:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after {
+ content: " ";
+ display: table;
+}
+.clearfix:after,
+.container:after,
+.container-fluid:after,
+.row:after { clear: both }
+
+.center-block {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.pull-right { float: right !important }
+.pull-left { float: left !important }
+.hide { display: none !important }
+.show { display: block !important }
+.invisible { visibility: hidden }
+
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+.hidden {
+ display: none ;
+}
+
+.affix { position: fixed }
diff --git a/phpBB/styles/subsilver2/style.cfg b/phpBB/styles/subsilver2/style.cfg
deleted file mode 100644
index 4c9abcc02d..0000000000
--- a/phpBB/styles/subsilver2/style.cfg
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# phpBB Style Configuration File
-#
-# 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.
-#
-# At the left is the name, please do not change this
-# At the right the value is entered
-#
-# Values get trimmed, if you want to add a space in front or at the end of
-# the value, then enclose the value with single or double quotes.
-# Single and double quotes do not need to be escaped.
-#
-#
-
-# General Information about this style
-name = subsilver2
-copyright = © 2005 phpBB Limited
-style_version = 3.1.10
-phpbb_version = 3.1.10
-
-# Defining a different template bitfield
-# template_bitfield = lNg=
-
-# Parent style
-# Set value to empty or to this style's name if this style does not have a parent style
-parent = subsilver2
diff --git a/phpBB/styles/subsilver2/template/attachment.html b/phpBB/styles/subsilver2/template/attachment.html
deleted file mode 100644
index 65a28aead4..0000000000
--- a/phpBB/styles/subsilver2/template/attachment.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!-- EVENT attachment_file_before -->
-
-<!-- BEGIN _file -->
-
- <!-- IF _file.S_DENIED -->
- <span class="genmed">[{_file.DENIED_MESSAGE}]</span><br />
- <!-- ELSE -->
- <!-- EVENT attachment_file_prepend -->
-
- <!-- IF _file.COMMENT -->
- <span class="gensmall"><b>{L_FILE_COMMENT}{L_COLON}</b> {_file.COMMENT}</span><br />
- <!-- ENDIF -->
-
- <!-- IF _file.S_THUMBNAIL -->
- <a href="{_file.U_DOWNLOAD_LINK}"><img src="{_file.THUMB_IMAGE}" class="postimage" alt="{_file.DOWNLOAD_NAME}" /></a><br />
- <span class="gensmall">{_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]</span>
- <!-- ENDIF -->
-
- <!-- IF _file.S_IMAGE -->
- <img src="{_file.U_INLINE_LINK}" class="postimage" alt="{_file.DOWNLOAD_NAME}" /><br />
- <span class="gensmall">{_file.DOWNLOAD_NAME} [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]</span>
- <!-- ENDIF -->
-
- <!-- IF _file.S_FILE -->
- <span class="genmed">
- <!-- IF _file.UPLOAD_ICON -->{_file.UPLOAD_ICON} <!-- ENDIF -->
- <a href="{_file.U_DOWNLOAD_LINK}">{_file.DOWNLOAD_NAME}</a> [{_file.FILESIZE} {_file.SIZE_LANG}]
- </span><br />
- <span class="gensmall">{_file.L_DOWNLOAD_COUNT}</span>
- <!-- ENDIF -->
-
- <!-- IF _file.S_WM_FILE -->
- <!-- method used here from http://alistapart.com/articles/byebyeembed / autosizing seems to not work always, this will not fix -->
- <object width="320" height="285" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" id="wmstream_{_file.ATTACH_ID}">
- <param name="url" value="{_file.U_DOWNLOAD_LINK}" />
- <param name="showcontrols" value="1" />
- <param name="showdisplay" value="0" />
- <param name="showstatusbar" value="0" />
- <param name="autosize" value="1" />
- <param name="autostart" value="0" />
- <param name="visible" value="1" />
- <param name="animationstart" value="0" />
- <param name="loop" value="0" />
- <param name="src" value="{_file.U_DOWNLOAD_LINK}" />
- <!--[if !IE]>-->
- <object width="320" height="285" type="video/x-ms-wmv" data="{_file.U_DOWNLOAD_LINK}">
- <param name="src" value="{_file.U_DOWNLOAD_LINK}" />
- <param name="controller" value="1" />
- <param name="showcontrols" value="1" />
- <param name="showdisplay" value="0" />
- <param name="showstatusbar" value="0" />
- <param name="autosize" value="1" />
- <param name="autostart" value="0" />
- <param name="visible" value="1" />
- <param name="animationstart" value="0" />
- <param name="loop" value="0" />
- </object>
- <!--<![endif]-->
- </object>
-
- <!-- ELSEIF _file.S_FLASH_FILE -->
- <object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{_file.WIDTH}" height="{_file.HEIGHT}">
- <param name="movie" value="{_file.U_VIEW_LINK}" />
- <param name="play" value="true" />
- <param name="loop" value="true" />
- <param name="quality" value="high" />
- <param name="allowScriptAccess" value="never" />
- <param name="allowNetworking" value="internal" />
- <embed src="{_file.U_VIEW_LINK}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{_file.WIDTH}" height="{_file.HEIGHT}" play="true" loop="true" quality="high" allowscriptaccess="never" allownetworking="internal"></embed>
- </object>
- <!-- ELSEIF _file.S_QUICKTIME_FILE -->
- <object id="qtstream_{_file.ATTACH_ID}" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="320" height="285">
- <param name="src" value="{_file.U_DOWNLOAD_LINK}">
- <param name="controller" value="true">
- <param name="autoplay" value="false" />
- <param name="type" value="video/quicktime">
- <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="320" height="285" type="video/quicktime" autoplay="false"></embed>
- </object>
- <!-- ELSEIF _file.S_RM_FILE -->
- <object id="rmstream_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="200" height="50">
- <param name="src" value="{_file.U_DOWNLOAD_LINK}">
- <param name="autostart" value="false">
- <param name="controls" value="ImageWindow">
- <param name="console" value="ctrls_{_file.ATTACH_ID}">
- <param name="prefetch" value="false">
- <embed name="rmstream_{_file.ATTACH_ID}" type="audio/x-pn-realaudio-plugin" src="{_file.U_DOWNLOAD_LINK}" width="0" height="0" autostart="false" controls="ImageWindow" console="ctrls_{_file.ATTACH_ID}" prefetch="false"></embed>
- </object>
- <br />
- <object id="ctrls_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="0" height="36">
- <param name="controls" value="ControlPanel">
- <param name="console" value="ctrls_{_file.ATTACH_ID}">
- <embed name="ctrls_{_file.ATTACH_ID}" type="audio/x-pn-realaudio-plugin" width="200" height="36" controls="ControlPanel" console="ctrls_{_file.ATTACH_ID}"></embed>
- </object>
-
- <script type="text/javascript">
- // <![CDATA[
- if (document.rmstream_{_file.ATTACH_ID}.GetClipWidth)
- {
- while (!document.rmstream_{_file.ATTACH_ID}.GetClipWidth())
- {
- }
-
- var width = document.rmstream_{_file.ATTACH_ID}.GetClipWidth();
- var height = document.rmstream_{_file.ATTACH_ID}.GetClipHeight();
-
- document.rmstream_{_file.ATTACH_ID}.width = width;
- document.rmstream_{_file.ATTACH_ID}.height = height;
- document.ctrls_{_file.ATTACH_ID}.width = width;
- }
- // ]]>
- </script>
- <!-- ENDIF -->
-
- <!-- IF _file.S_WM_FILE or _file.S_RM_FILE or _file.S_FLASH_FILE or _file.S_QUICKTIME_FILE -->
- <br />
- <!-- IF _file.S_QUICKTIME_FILE --><a href="#" onclick="play_qt_file(document.qtstream_{_file.ATTACH_ID}); return false;">[ {L_PLAY_QUICKTIME_FILE} ]</a> <!-- ENDIF -->
- <span class="gensmall"><a href="{_file.U_DOWNLOAD_LINK}">{_file.DOWNLOAD_NAME}</a> [ {_file.FILESIZE} {_file.SIZE_LANG} | {_file.L_DOWNLOAD_COUNT} ]</span>
- <!-- ENDIF -->
-
- <!-- EVENT attachment_file_append -->
- <br />
- <!-- ENDIF -->
-
-<!-- END _file -->
-<!-- EVENT attachment_file_after -->
diff --git a/phpBB/styles/subsilver2/template/bbcode.html b/phpBB/styles/subsilver2/template/bbcode.html
deleted file mode 100644
index 9ee5acec34..0000000000
--- a/phpBB/styles/subsilver2/template/bbcode.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open -->
-<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default -->
-<!-- BEGIN ulist_close --></ul><!-- END ulist_close -->
-
-<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open -->
-<!-- BEGIN olist_close --></ol><!-- END olist_close -->
-
-<!-- BEGIN listitem --><li><!-- END listitem -->
-<!-- BEGIN listitem_close --></li><!-- END listitem_close -->
-
-<!-- BEGIN quote_username_open -->
-<div class="quotetitle">{USERNAME} {L_WROTE}{L_COLON}</div><div class="quotecontent">
-<!-- END quote_username_open -->
-
-<!-- BEGIN quote_open -->
-<div class="quotetitle"><b>{L_QUOTE}{L_COLON}</b></div><div class="quotecontent">
-<!-- END quote_open -->
-
-<!-- BEGIN quote_close -->
-</div>
-<!-- END quote_close -->
-
-<!-- BEGIN code_open -->
-<div class="codetitle"><b>{L_CODE}{L_COLON}</b></div><pre class="codecontent">
-<!-- END code_open -->
-
-<!-- BEGIN code_close -->
-</pre>
-<!-- END code_close -->
-
-<!-- BEGIN inline_attachment_open -->
-<div class="attachtitle">{L_ATTACHMENT}{L_COLON}</div><div class="attachcontent">
-<!-- END inline_attachment_open -->
-
-<!-- BEGIN inline_attachment_close -->
-</div>
-<!-- END inline_attachment_close -->
-
-
-<!-- BEGIN b_open --><strong><!-- END b_open -->
-<!-- BEGIN b_close --></strong><!-- END b_close -->
-
-<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open -->
-<!-- BEGIN u_close --></span><!-- END u_close -->
-
-<!-- BEGIN i_open --><em><!-- END i_open -->
-<!-- BEGIN i_close --></em><!-- END i_close -->
-
-<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color -->
-
-<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: normal">{TEXT}</span><!-- END size -->
-
-<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img -->
-
-<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url -->
-
-<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email -->
-
-<!-- BEGIN flash -->
- <object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}">
- <param name="movie" value="{URL}" />
- <param name="play" value="false" />
- <param name="loop" value="false" />
- <param name="quality" value="high" />
- <param name="allowScriptAccess" value="never" />
- <param name="allowNetworking" value="internal" />
- <embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed>
- </object>
-<!-- END flash -->
diff --git a/phpBB/styles/subsilver2/template/breadcrumbs.html b/phpBB/styles/subsilver2/template/breadcrumbs.html
deleted file mode 100644
index 36983a5d88..0000000000
--- a/phpBB/styles/subsilver2/template/breadcrumbs.html
+++ /dev/null
@@ -1,14 +0,0 @@
- <!-- IF $S_MICRODATA --><!-- DEFINE $MICRODATA = ' itemtype="http://data-vocabulary.org/Breadcrumb" itemscope=""' --><!-- ELSE --><!-- DEFINE $MICRODATA = '' --><!-- ENDIF -->
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="0" style="margin-top: 5px;">
- <tr>
- <td class="row1">
- <!-- EVENT overall_header_breadcrumbs_before -->
- <p class="breadcrumbs"><!-- IF U_SITE_HOME --><span{$MICRODATA}><a href="{U_SITE_HOME}" data-navbar-reference="home" itemprop="url"><span itemprop="title">{L_SITE_HOME}</span></a></span> <strong>&#187;</strong> <!-- ENDIF --><!-- IF $OVERALL_HEADER_BREADCRUMBS --><!-- EVENT overall_header_breadcrumb_prepend --><!-- ELSE --><!-- EVENT overall_footer_breadcrumb_prepend --><!-- ENDIF --><span{$MICRODATA}><a href="{U_INDEX}" data-navbar-reference="index" itemprop="url"><span itemprop="title">{L_INDEX}</span></a></span><!-- BEGIN navlinks --><!-- EVENT overall_header_navlink_prepend --> &#187; <span{$MICRODATA}<!-- IF navlinks.MICRODATA --> {navlinks.MICRODATA}<!-- ENDIF -->><a href="{navlinks.U_VIEW_FORUM}" itemprop="url"><span itemprop="title">{navlinks.FORUM_NAME}</span></a></span><!-- EVENT overall_header_navlink_append --><!-- END navlinks -->
- <!-- IF $OVERALL_HEADER_BREADCRUMBS --><!-- EVENT overall_header_breadcrumb_append --><!-- ELSE --><!-- EVENT overall_footer_breadcrumb_append --><!-- ENDIF --></p>
- <!-- EVENT overall_header_breadcrumbs_after -->
- <!-- EVENT overall_footer_timezone_before -->
- <p class="datetime">{S_TIMEZONE}</p>
- <!-- EVENT overall_footer_timezone_after -->
- </td>
- </tr>
- </table>
diff --git a/phpBB/styles/subsilver2/template/captcha_default.html b/phpBB/styles/subsilver2/template/captcha_default.html
deleted file mode 100644
index 1be25403ce..0000000000
--- a/phpBB/styles/subsilver2/template/captcha_default.html
+++ /dev/null
@@ -1,17 +0,0 @@
- <tr>
- <th colspan="2" valign="middle">{L_CONFIRM_CODE}</th>
- </tr>
- <!-- IF S_TYPE == 1 -->
- <tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_CONFIRM_EXPLAIN}</span></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="row1" colspan="2" align="center"><img src="{CONFIRM_IMAGE_LINK}" alt="{L_CONFIRM_CODE}" />
- <input type="hidden" name="confirm_id" id="confirm_id" value="{CONFIRM_ID}" /></td>
- </tr>
- <tr>
- <td class="row1"><b class="genmed">{L_CONFIRM_CODE}{L_COLON}</b><br /><span class="gensmall">{L_CONFIRM_CODE_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="text" name="confirm_code" size="8" maxlength="8"<!-- IF $CAPTCHA_TAB_INDEX --> tabindex="{$CAPTCHA_TAB_INDEX}"<!-- ENDIF --> />
- <!-- IF S_CONFIRM_REFRESH --><input type="submit" name="refresh_vc" id="refresh_vc" class="btnlite" value="{L_VC_REFRESH}" /><!-- ENDIF --></td>
- </tr>
diff --git a/phpBB/styles/subsilver2/template/captcha_qa.html b/phpBB/styles/subsilver2/template/captcha_qa.html
deleted file mode 100644
index 90a6492400..0000000000
--- a/phpBB/styles/subsilver2/template/captcha_qa.html
+++ /dev/null
@@ -1,8 +0,0 @@
- <tr>
- <th colspan="2" valign="middle">{L_CONFIRM_QUESTION}</th>
- </tr>
- <tr>
- <td class="row1"><b class="genmed">{QA_CONFIRM_QUESTION}{L_COLON}</b><br /><span class="gensmall">{L_CONFIRM_QUESTION_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="text" name="qa_answer" size="80"<!-- IF $CAPTCHA_TAB_INDEX --> tabindex="{$CAPTCHA_TAB_INDEX}"<!-- ENDIF --> />
- <input type="hidden" name="qa_confirm_id" id="confirm_id" value="{QA_CONFIRM_ID}" /></td>
- </tr>
diff --git a/phpBB/styles/subsilver2/template/captcha_recaptcha.html b/phpBB/styles/subsilver2/template/captcha_recaptcha.html
deleted file mode 100644
index 0d116b361f..0000000000
--- a/phpBB/styles/subsilver2/template/captcha_recaptcha.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!-- IF S_RECAPTCHA_AVAILABLE -->
- <tr>
- <th colspan="2" valign="middle">{L_CONFIRM_CODE}</th>
- </tr>
- <tr>
- <td class="row1"><b class="genmed">{L_CONFIRM_CODE}{L_COLON}</b><br /><span class="gensmall">{L_RECAPTCHA_EXPLAIN}</span></td>
- <td class="row2">
- <script type="text/javascript">
- // <![CDATA[
- var RecaptchaOptions = {
- lang : '{LA_RECAPTCHA_LANG}',
- theme : 'clean',
- tabindex : <!-- IF $CAPTCHA_TAB_INDEX -->{$CAPTCHA_TAB_INDEX}<!-- ELSE -->10<!-- ENDIF -->
- };
- // ]]>
- </script>
- <script type="text/javascript" src="{RECAPTCHA_SERVER}/challenge?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}" ></script>
- <script type="text/javascript">
- // <![CDATA[
- <!-- IF S_CONTENT_DIRECTION eq 'rtl' -->
- document.getElementById('recaptcha_table').style.direction = 'ltr';
- <!-- ENDIF -->
- // ]]>
- </script>
-
- <noscript>
- <iframe src="{RECAPTCHA_SERVER}/noscript?k={RECAPTCHA_PUBKEY}{RECAPTCHA_ERRORGET}" height="300" width="500" frameborder="0"></iframe><br />
- <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
- <input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
- </noscript>
- </td>
- </tr>
-
-<!-- ELSE -->
-{L_RECAPTCHA_NOT_AVAILABLE}
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/confirm_body.html b/phpBB/styles/subsilver2/template/confirm_body.html
deleted file mode 100644
index 1712017c38..0000000000
--- a/phpBB/styles/subsilver2/template/confirm_body.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div id="pagecontent">
-
- <form name="confirm" action="{S_CONFIRM_ACTION}" method="post">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{MESSAGE_TITLE}</th>
- </tr>
- <tr>
- <td class="row1" align="center"><br /><p class="gen">{MESSAGE_TEXT}</p><br />{S_HIDDEN_FIELDS}<input type="submit" name="confirm" value="{YES_VALUE}" class="btnlite" />&nbsp;&nbsp;<input type="submit" name="cancel" value="{L_NO}" class="btnlite" /></td>
- </tr>
- </table>
-
- </form>
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/confirm_delete_body.html b/phpBB/styles/subsilver2/template/confirm_delete_body.html
deleted file mode 100644
index 44aec9b60a..0000000000
--- a/phpBB/styles/subsilver2/template/confirm_delete_body.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div id="pagecontent">
-
- <form name="confirm" action="{S_CONFIRM_ACTION}" method="post">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{MESSAGE_TITLE}</th>
- </tr>
- <tr>
- <td class="row1" align="center">
- <br />
- <p class="gen">{MESSAGE_TEXT}</p>
- <br />
-
- <!-- IF not S_SHADOW_TOPICS -->
- <table border="0" width="90%" cellspacing="2" cellpadding="1">
- <!-- IF not S_SOFTDELETED and S_ALLOWED_DELETE and S_ALLOWED_SOFTDELETE -->
- <tr>
- <td class="row1" width="22%"><b class="gen">{L_DELETE_PERMANENTLY}{L_COLON}</b></td>
- <td class="row1" width="78%">
- <input id="delete_permanent" name="delete_permanent" type="checkbox" value="1" {S_CHECKED_PERMANENT} />
- <!-- IF S_TOPIC_MODE -->{L_DELETE_TOPIC_PERMANENTLY}<!-- ELSE -->{L_DELETE_POST_PERMANENTLY}<!-- ENDIF -->
- </td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="row1" valign="top"><span class="gen"><b>{L_DELETE_REASON}{L_COLON}</b></span><br /><span class="gensmall">{L_DELETE_REASON_EXPLAIN}</span></td>
- <td class="row1"><input type="text" name="delete_reason" value="" class="inputbox autowidth" maxlength="120" size="45" /></td>
- </tr>
- </table>
- <br />
- <!-- ENDIF -->
-
- {S_HIDDEN_FIELDS}
- <input type="submit" name="confirm" value="{L_YES}" class="btnmain" />&nbsp;&nbsp;
- <input type="submit" name="cancel" value="{L_NO}" class="btnlite" />
- </td>
- </tr>
- </table>
-
- </form>
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/faq_body.html b/phpBB/styles/subsilver2/template/faq_body.html
deleted file mode 100644
index b3c41e932a..0000000000
--- a/phpBB/styles/subsilver2/template/faq_body.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<a name="faqtop" class="anchor"></a>
-
-<div id="pagecontent">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_FAQ_TITLE}</th>
- </tr>
- <tr>
- <td class="row1">
- <!-- BEGIN faq_block -->
- <span class="gen"><b>{faq_block.BLOCK_TITLE}</b></span><br />
- <!-- BEGIN faq_row -->
- <span class="gen"><a href="#f{faq_block.S_ROW_COUNT}r{faq_block.faq_row.S_ROW_COUNT}">{faq_block.faq_row.FAQ_QUESTION}</a></span><br />
- <!-- END faq_row -->
- <br />
- <!-- END faq_block -->
- </td>
- </tr>
- <tr>
- <td class="cat">&nbsp;</td>
- </tr>
- </table>
-
- <br clear="all" />
-
- <!-- BEGIN faq_block -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat" align="center"><h4>{faq_block.BLOCK_TITLE}</h4></td>
- </tr>
- <!-- BEGIN faq_row -->
- <tr>
- <!-- IF faq_block.faq_row.S_ROW_COUNT is even -->
- <td class="row1" valign="top">
- <!-- ELSE -->
- <td class="row2" valign="top">
- <!-- ENDIF -->
- <div class="postbody"><a name="f{faq_block.S_ROW_COUNT}r{faq_block.faq_row.S_ROW_COUNT}" class="anchor"></a><b>&#187; {faq_block.faq_row.FAQ_QUESTION}</b></div>
- <div class="postbody">{faq_block.faq_row.FAQ_ANSWER}</div>
- <p class="gensmall"><a href="#faqtop">{L_BACK_TO_TOP}</a></p>
- </td>
- </tr>
- <tr>
- <td class="spacer" height="1"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
- </tr>
- <!-- END faq_row -->
- </table>
-
- <br clear="all" />
- <!-- END faq_block -->
-
-</div>
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/forumlist_body.html b/phpBB/styles/subsilver2/template/forumlist_body.html
deleted file mode 100644
index 6c9b64827a..0000000000
--- a/phpBB/styles/subsilver2/template/forumlist_body.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<table class="tablebg" cellspacing="1" width="100%">
-<tr>
- <td class="cat" colspan="5" align="{S_CONTENT_FLOW_END}"><!-- IF not S_IS_BOT and U_MARK_FORUMS --><a class="nav" href="{U_MARK_FORUMS}">{L_MARK_FORUMS_READ}</a><!-- ENDIF -->&nbsp;</td>
-</tr>
-<tr>
- <th colspan="2">&nbsp;{L_FORUM}&nbsp;</th>
- <th width="50">&nbsp;{L_TOPICS}&nbsp;</th>
- <th width="50">&nbsp;{L_POSTS}&nbsp;</th>
- <th>&nbsp;{L_LAST_POST}&nbsp;</th>
-</tr>
-<!-- BEGIN forumrow -->
- <!-- EVENT forumlist_body_category_header_before -->
- <!-- IF forumrow.S_IS_CAT -->
- <tr>
- <td class="cat" colspan="2"><h4><a href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a></h4></td>
- <td class="catdiv" colspan="3">&nbsp;</td>
- </tr>
- <!-- EVENT forumlist_body_category_header_after -->
- <!-- ELSEIF forumrow.S_IS_LINK -->
- <tr>
- <td class="row1" width="50" align="center">{forumrow.FORUM_FOLDER_IMG}</td>
- <td class="row1">
- <!-- IF forumrow.FORUM_IMAGE -->
- <div style="float: {S_CONTENT_FLOW_BEGIN}; margin-{S_CONTENT_FLOW_END}{L_COLON} 5px;">{forumrow.FORUM_IMAGE}</div>
- <!-- ENDIF -->
- <a class="forumlink" href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a>
- <p class="forumdesc">{forumrow.FORUM_DESC}</p>
- </td>
- <!-- IF forumrow.CLICKS -->
- <td class="row2" colspan="3" align="center"><span class="genmed">{L_REDIRECTS}{L_COLON} {forumrow.CLICKS}</span></td>
- <!-- ELSE -->
- <td class="row2" colspan="3" align="center">&nbsp;</td>
- <!-- ENDIF -->
- </tr>
- <!-- ELSE -->
- <!-- IF forumrow.S_NO_CAT -->
- <tr>
- <td class="cat" colspan="2"><h4>{L_FORUM}</h4></td>
- <td class="catdiv" colspan="3">&nbsp;</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT forumlist_body_forum_row_before -->
- <tr>
- <!-- EVENT forumlist_body_forum_row_prepend -->
- <td class="row1" width="50" align="center">{forumrow.FORUM_FOLDER_IMG}</td>
- <td class="row1" width="100%">
- <!-- IF forumrow.FORUM_IMAGE -->
- <div style="float: {S_CONTENT_FLOW_BEGIN}; margin-{S_CONTENT_FLOW_END}{L_COLON} 5px;">{forumrow.FORUM_IMAGE}</div>
- <!-- ENDIF -->
- <a class="forumlink" href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a>
- <p class="forumdesc">{forumrow.FORUM_DESC}</p>
- <!-- IF forumrow.MODERATORS -->
- <p class="forumdesc"><strong>{forumrow.L_MODERATOR_STR}{L_COLON}</strong> {forumrow.MODERATORS}</p>
- <!-- ENDIF -->
- <!-- IF .forumrow.subforum and forumrow.S_LIST_SUBFORUMS -->
- <!-- EVENT forumlist_body_subforums_before -->
- <p class="forumdesc"><strong>{forumrow.L_SUBFORUM_STR}{L_COLON}</strong>
- <!-- BEGIN subforum -->
- <a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.S_UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->">{forumrow.subforum.SUBFORUM_NAME}</a><!-- IF not forumrow.subforum.S_LAST_ROW -->{L_COMMA_SEPARATOR}<!-- ENDIF -->
- <!-- END subforum -->
- </p>
- <!-- EVENT forumlist_body_subforums_after -->
- <!-- ENDIF -->
- </td>
- <td class="row2" align="center"><p class="topicdetails">{forumrow.TOPICS}</p></td>
- <td class="row2" align="center"><p class="topicdetails">{forumrow.POSTS}</p></td>
- <td class="row2" align="center" nowrap="nowrap">
- <!-- IF forumrow.LAST_POST_TIME -->
- <!-- IF forumrow.S_DISPLAY_SUBJECT -->
- <!-- EVENT forumlist_body_last_post_title_prepend -->
- <p class="topicdetails"><a href="{forumrow.U_LAST_POST}" title="{forumrow.LAST_POST_SUBJECT}" class="lastsubject">{forumrow.LAST_POST_SUBJECT_TRUNCATED}</a></p>
- <!-- ENDIF -->
- <p class="topicdetails">
- <!-- IF forumrow.U_UNAPPROVED_TOPICS -->
- <a href="{forumrow.U_UNAPPROVED_TOPICS}" class="imageset">{UNAPPROVED_IMG}</a>&nbsp;
- <!-- ELSEIF forumrow.U_UNAPPROVED_POSTS -->
- <a href="{forumrow.U_UNAPPROVED_POSTS}" class="imageset">{UNAPPROVED_POST_IMG}</a>&nbsp;
- <!-- ENDIF -->
- {forumrow.LAST_POST_TIME}
- </p>
- <p class="topicdetails">{forumrow.LAST_POSTER_FULL}
- <!-- IF not S_IS_BOT --><a href="{forumrow.U_LAST_POST}" class="imageset">{LAST_POST_IMG}</a><!-- ENDIF -->
- </p>
- <!-- ELSE -->
- <p class="topicdetails">{L_NO_POSTS}</p>
- <!-- ENDIF -->
- </td>
- <!-- EVENT forumlist_body_forum_row_append -->
- </tr>
- <!-- EVENT forumlist_body_forum_row_after -->
- <!-- ENDIF -->
- <!-- EVENT forumlist_body_last_row_after -->
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="5" align="center"><p class="gensmall">{L_NO_FORUMS}</p></td>
- </tr>
-<!-- END forumrow -->
-</table>
diff --git a/phpBB/styles/subsilver2/template/index.htm b/phpBB/styles/subsilver2/template/index.htm
deleted file mode 100644
index a1356823e2..0000000000
--- a/phpBB/styles/subsilver2/template/index.htm
+++ /dev/null
@@ -1,16 +0,0 @@
-<html>
-<head>
-<title>subSilver created by subBlue Design</title>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-</head>
-
-<body bgcolor="#FFFFFF" text="#000000">
-
-<table width="100%" height="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td align="center" valign="middle"><a href="http://www.subblue.com/" target="_new"><img src="images/created_by.jpg" width="400" height="300" alt="Created by subBlue Design" /></a></td>
- </tr>
-</table>
-
-</body>
-</html> \ No newline at end of file
diff --git a/phpBB/styles/subsilver2/template/index_body.html b/phpBB/styles/subsilver2/template/index_body.html
deleted file mode 100644
index c0a8d5fd57..0000000000
--- a/phpBB/styles/subsilver2/template/index_body.html
+++ /dev/null
@@ -1,142 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- EVENT index_body_markforums_before -->
-
-<!-- IF U_MCP or U_ACP -->
- <div id="pageheader">
- <p class="linkmcp">[&nbsp;<!-- IF U_ACP --><a href="{U_ACP}">{L_ACP}</a><!-- IF U_MCP -->&nbsp;|&nbsp;<!-- ENDIF --><!-- ENDIF --><!-- IF U_MCP --><a href="{U_MCP}">{L_MCP}</a><!-- ENDIF -->&nbsp;]</p>
- </div>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<!-- EVENT index_body_markforums_after -->
-
-<!-- INCLUDE forumlist_body.html -->
-
-<!-- EVENT index_body_forumlist_body_after -->
-
-<!-- IF not S_IS_BOT or U_TEAM -->
-<span class="gensmall">
- <!-- IF not S_IS_BOT --><a href="{U_DELETE_COOKIES}">{L_DELETE_COOKIES}</a><!-- ENDIF -->
- <!-- IF not S_IS_BOT and U_TEAM --> | <!-- ENDIF -->
- <!-- EVENT overall_footer_teamlink_before -->
- <!-- IF U_TEAM --><a href="{U_TEAM}">{L_THE_TEAM}</a><!-- ENDIF -->
- <!-- IF U_CONTACT_US -->
- <!-- IF U_TEAM --> | <!-- ENDIF -->
- <a href="{U_CONTACT_US}">{L_CONTACT_US}</a>
- <!-- ENDIF -->
- <!-- EVENT overall_footer_teamlink_after -->
-</span>
-<!-- ENDIF -->
-<br />
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<!-- EVENT index_body_stat_blocks_before -->
-
-<!-- IF S_DISPLAY_ONLINE_LIST -->
- <br clear="all" />
-
- <table class="tablebg stat-block online-list" width="100%" cellspacing="1">
- <tr>
- <td class="cat" colspan="2"><!-- IF U_VIEWONLINE --><h4><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a></h4><!-- ELSE --><h4>{L_WHO_IS_ONLINE}</h4><!-- ENDIF --></td>
- </tr>
- <tr>
- <!-- IF LEGEND -->
- <td class="row1" rowspan="2" align="center" valign="middle"><img src="{T_THEME_PATH}/images/whosonline.gif" alt="{L_WHO_IS_ONLINE}" /></td>
- <!-- ELSE -->
- <td class="row1" align="center" valign="middle"><img src="{T_THEME_PATH}/images/whosonline.gif" alt="{L_WHO_IS_ONLINE}" /></td>
- <!-- ENDIF -->
- <td class="row1" width="100%">
- <span class="genmed">
- <!-- EVENT index_body_block_online_prepend -->
- {TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})<br />{RECORD_USERS}<br /><br />{LOGGED_IN_USER_LIST}
- <!-- EVENT index_body_block_online_append -->
- </span>
- </td>
- </tr>
- <!-- IF LEGEND -->
- <tr>
- <td class="row1"><b class="gensmall">{L_LEGEND} :: {LEGEND}</b></td>
- </tr>
- <!-- ENDIF -->
- </table>
-<!-- ENDIF -->
-
-<!-- IF S_DISPLAY_BIRTHDAY_LIST -->
- <br clear="all" />
-
- <table class="tablebg stat-block birthday-list" width="100%" cellspacing="1">
- <tr>
- <td class="cat" colspan="2"><h4>{L_BIRTHDAYS}</h4></td>
- </tr>
- <tr>
- <td class="row1" align="center" valign="middle"><img src="{T_THEME_PATH}/images/whosonline.gif" alt="{L_BIRTHDAYS}" /></td>
- <td class="row1" width="100%">
- <p class="genmed">
- <!-- EVENT index_body_block_birthday_prepend -->
- <!-- IF .birthdays -->{L_CONGRATULATIONS}{L_COLON} <b><!-- BEGIN birthdays -->{birthdays.USERNAME}<!-- IF birthdays.AGE !== '' --> ({birthdays.AGE})<!-- ENDIF --><!-- IF not birthdays.S_LAST_ROW -->, <!-- ENDIF --><!-- END birthdays --></b><!-- ELSE -->{L_NO_BIRTHDAYS}<!-- ENDIF -->
- <!-- EVENT index_body_block_birthday_append -->
- </p>
- </td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-<br clear="all" />
-
-<table class="tablebg stat-block statistics" width="100%" cellspacing="1">
-<tr>
- <td class="cat" colspan="2"><h4>{L_STATISTICS}</h4></td>
-</tr>
-<tr>
- <td class="row1"><img src="{T_THEME_PATH}/images/whosonline.gif" alt="{L_STATISTICS}" /></td>
- <td class="row1" width="100%" valign="middle">
- <p class="genmed">
- <!-- EVENT index_body_block_stats_prepend -->
- {TOTAL_POSTS} | {TOTAL_TOPICS} | {TOTAL_USERS} | {NEWEST_USER}
- <!-- EVENT index_body_block_stats_append -->
- </p>
- </td>
-</tr>
-</table>
-
-<!-- EVENT index_body_stat_blocks_after -->
-
-<!-- IF not S_USER_LOGGED_IN and not S_IS_BOT -->
- <br clear="all" />
-
- <form method="post" action="{S_LOGIN_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat"><h4><a href="{U_LOGIN_LOGOUT}">{L_LOGIN_LOGOUT}</a></h4></td>
- </tr>
- <tr>
- <td class="row1" align="center"><span class="genmed">{L_USERNAME}{L_COLON}</span> <input class="post" type="text" name="username" size="10" />&nbsp; <span class="genmed">{L_PASSWORD}{L_COLON}</span> <input class="post" type="password" name="password" size="10" autocomplete="off" />&nbsp; <!-- IF U_SEND_PASSWORD --><a href="{U_SEND_PASSWORD}">{L_FORGOT_PASS}</a>&nbsp; <!-- ENDIF --> <!-- IF S_AUTOLOGIN_ENABLED --> <span class="gensmall">{L_LOG_ME_IN}</span> <input type="checkbox" class="radio" name="autologin" /><!-- ENDIF -->&nbsp; <input type="submit" class="btnmain" name="login" value="{L_LOGIN}" /></td>
- </tr>
- </table>
- {S_LOGIN_REDIRECT}
- {S_FORM_TOKEN}
- </form>
-<!-- ENDIF -->
-
-<br clear="all" />
-
-<table class="legend">
-<tr>
- <td width="20" align="center">{FORUM_UNREAD_IMG}</td>
- <td><span class="gensmall">{L_UNREAD_POSTS}</span></td>
- <td>&nbsp;&nbsp;</td>
- <td width="20" align="center">{FORUM_IMG}</td>
- <td><span class="gensmall">{L_NO_UNREAD_POSTS}</span></td>
- <td>&nbsp;&nbsp;</td>
- <td width="20" align="center">{FORUM_LOCKED_IMG}</td>
- <td><span class="gensmall">{L_FORUM_LOCKED}</span></td>
-</tr>
-</table>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/jumpbox.html b/phpBB/styles/subsilver2/template/jumpbox.html
deleted file mode 100644
index e0603c6a6e..0000000000
--- a/phpBB/styles/subsilver2/template/jumpbox.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-<!-- IF S_DISPLAY_JUMPBOX -->
- <form method="get" name="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(document.jumpbox.f.value == -1){return false;}">
-
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td nowrap="nowrap">{HIDDEN_FIELDS_FOR_JUMPBOX}<span class="gensmall"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</span>&nbsp;<select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }">
-
- <!-- BEGIN jumpbox_forums -->
- <!-- IF jumpbox_forums.S_FORUM_COUNT eq 1 --><option value="-1">------------------</option><!-- ENDIF -->
- <option value="{jumpbox_forums.FORUM_ID}"{jumpbox_forums.SELECTED}><!-- BEGIN level -->&nbsp; &nbsp;<!-- END level -->{jumpbox_forums.FORUM_NAME}</option>
- <!-- END jumpbox_forums -->
-
- </select>&nbsp;<input class="btnlite" type="submit" value="{L_GO}" /></td>
- </tr>
- </table>
-
- </form>
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/login_body.html b/phpBB/styles/subsilver2/template/login_body.html
deleted file mode 100644
index 1067f3738d..0000000000
--- a/phpBB/styles/subsilver2/template/login_body.html
+++ /dev/null
@@ -1,111 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<form action="{S_LOGIN_ACTION}" method="post">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <!-- IF not S_ADMIN_AUTH -->
- <th colspan="2">{L_LOGIN}</th>
- <!-- ELSE -->
- <th>{LOGIN_EXPLAIN}</th>
- <!-- ENDIF -->
-</tr>
-<!-- IF LOGIN_EXPLAIN && not S_ADMIN_AUTH -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall">{LOGIN_EXPLAIN}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr><!-- IF not S_ADMIN_AUTH and S_REGISTER_ENABLED -->
- <td class="row1" width="50%">
- <p class="genmed">{L_LOGIN_INFO}</p>
-
- <p class="genmed" align="center">
- <a href="{U_TERMS_USE}">{L_TERMS_USE}</a> | <a href="{U_PRIVACY}">{L_PRIVACY}</a>
- </p>
- </td>
- <!-- ENDIF -->
- <td <!-- IF not S_ADMIN_AUTH -->class="row2"<!-- ELSE -->class="row1"<!-- ENDIF -->>
-
- <table align="center" cellspacing="1" cellpadding="4" style="width: 100%;">
- <!-- IF LOGIN_ERROR -->
- <tr>
- <td class="gensmall" colspan="2" align="center"><span class="error">{LOGIN_ERROR}</span></td>
- </tr>
- <!-- ENDIF -->
-
- <tr>
- <td valign="top" <!-- IF S_ADMIN_AUTH -->style="width: 50%; text-align: {S_CONTENT_FLOW_END};"<!-- ENDIF -->><b class="gensmall">{L_USERNAME}{L_COLON}</b></td>
- <td><input class="post" type="text" name="{USERNAME_CREDENTIAL}" size="25" value="{USERNAME}" tabindex="1" />
- <!-- IF not S_ADMIN_AUTH and S_REGISTER_ENABLED -->
- <br /><a class="gensmall" href="{U_REGISTER}">{L_REGISTER}</a>
- <!-- ENDIF -->
- </td>
- </tr>
- <tr>
- <td valign="top" <!-- IF S_ADMIN_AUTH -->style="width: 50%; text-align: {S_CONTENT_FLOW_END};"<!-- ENDIF -->><b class="gensmall">{L_PASSWORD}{L_COLON}</b></td>
- <td>
- <input class="post" type="password" name="{PASSWORD_CREDENTIAL}" size="25" tabindex="2" autocomplete="off" />
- <!-- IF U_SEND_PASSWORD --><br /><a class="gensmall" href="{U_SEND_PASSWORD}">{L_FORGOT_PASS}</a><!-- ENDIF -->
- <!-- IF U_RESEND_ACTIVATION and not S_ADMIN_AUTH --><br /><a class="gensmall" href="{U_RESEND_ACTIVATION}">{L_RESEND_ACTIVATION}</a><!-- ENDIF -->
- </td>
- </tr>
- <!-- IF S_DISPLAY_FULL_LOGIN -->
- <!-- IF S_AUTOLOGIN_ENABLED -->
- <tr>
- <td>&nbsp;</td>
- <td><input type="checkbox" class="radio" name="autologin" tabindex="3" /> <span class="gensmall">{L_LOG_ME_IN}</span></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td>&nbsp;</td>
- <td><input type="checkbox" class="radio" name="viewonline" tabindex="4" /> <span class="gensmall">{L_HIDE_ME}</span></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF not S_ADMIN_AUTH and PROVIDER_TEMPLATE_FILE -->
- <!-- INCLUDE {PROVIDER_TEMPLATE_FILE} -->
- <!-- ENDIF -->
- </table>
- </td>
-</tr>
-
-<!-- IF CAPTCHA_TEMPLATE and S_CONFIRM_CODE -->
-</table>
-<table class="tablebg" width="100%" cellspacing="1">
- <!-- DEFINE $CAPTCHA_TAB_INDEX = 4 -->
- <!-- INCLUDE {CAPTCHA_TEMPLATE} -->
-<!-- ENDIF -->
-
-{S_LOGIN_REDIRECT}
-<tr>
- <td class="cat" <!-- IF not S_ADMIN_AUTH or S_CONFIRM_CODE -->colspan="2"<!-- ENDIF --> align="center">{S_HIDDEN_FIELDS}<input type="submit" name="login" class="btnmain" value="{L_LOGIN}" tabindex="5" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<script type="text/javascript">
-// <![CDATA[
- (function()
- {
- var elements = document.getElementsByName("<!-- IF S_ADMIN_AUTH -->{PASSWORD_CREDENTIAL}<!-- ELSE -->{USERNAME_CREDENTIAL}<!-- ENDIF -->");
- for (var i = 0; i < elements.length; ++i)
- {
- if (elements[i].tagName.toLowerCase() == 'input')
- {
- elements[i].focus();
- break;
- }
- }
- })();
-// ]]>
-</script>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/login_body_oauth.html b/phpBB/styles/subsilver2/template/login_body_oauth.html
deleted file mode 100644
index 6f374fa4f2..0000000000
--- a/phpBB/styles/subsilver2/template/login_body_oauth.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- BEGIN oauth -->
- <tr>
- <td>
- <a href="{oauth.REDIRECT_URL}">{oauth.SERVICE_NAME}</a>
- </td>
- </tr>
-<!-- END oauth -->
diff --git a/phpBB/styles/subsilver2/template/login_forum.html b/phpBB/styles/subsilver2/template/login_forum.html
deleted file mode 100644
index 2cda9f3452..0000000000
--- a/phpBB/styles/subsilver2/template/login_forum.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- IF FORUM_NAME -->
- <div id="pageheader">
- <h2><a class="titles" href="{U_VIEW_FORUM}">{FORUM_NAME}</a></h2>
- </div>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<div id="pagecontent">
-
- <form name="login_forum" method="post" action="{S_LOGIN_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1" align="center">
- <tr>
- <th>{L_LOGIN}</th>
- </tr>
- <tr>
- <td class="row3" align="center"><span class="gensmall">{L_LOGIN_FORUM}</span></td>
- </tr>
- <tr>
- <td class="row1" align="center">
-
- <table cellspacing="1" cellpadding="4" border="0">
- <!-- IF LOGIN_ERROR -->
- <tr>
- <td class="gensmall" colspan="2" align="center"><span class="error">{LOGIN_ERROR}</span></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="gensmall"><b>{L_PASSWORD}{L_COLON}</b></td>
- <td><input class="post" type="password" name="password" size="25" tabindex="2" autocomplete="off" /></td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input type="submit" name="login" class="btnmain" value="{L_LOGIN}" tabindex="3" /></td>
- </tr>
- </table>
- {S_FORM_TOKEN}
- {S_LOGIN_REDIRECT}
- </form>
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_approve.html b/phpBB/styles/subsilver2/template/mcp_approve.html
deleted file mode 100644
index 8c2ef0806b..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_approve.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div id="pagecontent">
-
- <form name="confirm" action="{S_CONFIRM_ACTION}" method="post">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{MESSAGE_TITLE}</th>
- </tr>
- <tr>
- <td class="row1" align="center">
- <!-- IF ADDITIONAL_MSG -->
- <span class="gen error">{ADDITIONAL_MSG}</span><br />
- <!-- ENDIF -->
- <!-- IF S_NOTIFY_POSTER -->
- <input type="checkbox" class="radio" name="notify_poster" checked="checked" /><span class="gen"><!-- IF S_APPROVE -->{L_NOTIFY_POSTER_APPROVAL}<!-- ELSE -->{L_NOTIFY_POSTER_DISAPPROVAL}<!-- ENDIF --></span><br />
- <!-- ENDIF -->
- <!-- IF not S_APPROVE and not S_RESTORE and .reason -->
- <br />
- <table border="0" width="90%" cellspacing="2" cellpadding="1">
- <tr>
- <td class="row1" width="22%"><b class="gen">{L_DISAPPROVE_REASON}{L_COLON}</b></td>
- <td class="row1" width="78%"><select name="reason_id"><!-- BEGIN reason --><option value="{reason.ID}"<!-- IF reason.S_SELECTED --> selected="selected"<!-- ENDIF -->>{reason.DESCRIPTION}</option><!-- END reason --></select></td>
- </tr>
- <tr>
- <td class="row1" valign="top"><span class="gen"><b>{L_MORE_INFO}{L_COLON}</b></span><br /><span class="gensmall">{L_CAN_LEAVE_BLANK}</span></td>
- <td class="row1"><textarea class="post" style="width:500px" name="reason" rows="10" cols="40">{REASON}</textarea></td>
- </tr>
- </table>
- <br />
- <!-- ENDIF -->
- <br />{S_HIDDEN_FIELDS}<span class="gen">{MESSAGE_TEXT}</span><br /><br />
- <input type="submit" name="confirm" value="{YES_VALUE}" class="btnmain" />&nbsp;&nbsp;<input type="submit" name="cancel" value="{L_NO}" class="btnlite" /></span>
- </td>
- </tr>
- </table>
- {S_FORM_TOKEN}
- </form>
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_ban.html b/phpBB/styles/subsilver2/template/mcp_ban.html
deleted file mode 100644
index cc24d21d73..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_ban.html
+++ /dev/null
@@ -1,120 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
-
- var ban_length = new Array();
- ban_length[-1] = '';
- var ban_reason = new Array();
- ban_reason[-1] = '';
- var ban_give_reason = new Array();
- ban_give_reason[-1] = '';
-
- <!-- BEGIN bans -->
- ban_length['{bans.BAN_ID}'] = '{bans.A_LENGTH}';
- <!-- IF bans.A_REASON -->
- ban_reason['{bans.BAN_ID}'] = '{bans.A_REASON}';
- <!-- ENDIF -->
- <!-- IF bans.A_GIVE_REASON -->
- ban_give_reason['{bans.BAN_ID}'] = '{bans.A_GIVE_REASON}';
- <!-- ENDIF -->
- <!-- END bans -->
-
- function display_details(option)
- {
- document.getElementById('mcp_ban').unbanlength.value = ban_length[option];
- if (option in ban_reason) {
- document.getElementById('mcp_ban').unbanreason.value = ban_reason[option];
- } else {
- document.getElementById('mcp_ban').unbanreason.value = '';
- }
- if (option in ban_give_reason) {
- document.getElementById('mcp_ban').unbangivereason.value = ban_give_reason[option];
- } else {
- document.getElementById('mcp_ban').unbangivereason.value = '';
- }
- }
-
-// ]]>
-</script>
-
-<form id="mcp_ban" method="post" action="{U_ACTION}">
-
-<table width="100%" class="tablebg" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <th colspan="2" nowrap="nowrap">{L_TITLE}</th>
-</tr>
-<tr>
- <td class="row3" colspan="2">{L_EXPLAIN}</td>
-</tr>
-<!-- EVENT mcp_ban_fields_before -->
-<tr>
- <td class="row1" width="45%" valign="top"><b>{L_BAN_CELL}{L_COLON}</b></td>
- <td class="row2">
- <textarea name="ban" id="ban" cols="40" rows="3" class="post">{USERNAMES}</textarea>
- <!-- IF S_USERNAME_BAN --><br />[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]<!-- ENDIF -->
- </td>
-</tr>
-<tr>
- <td class="row1" valign="top"><b>{L_BAN_LENGTH}{L_COLON}</b></td>
- <td class="row2"><select name="banlength">{S_BAN_END_OPTIONS}</select><br /><input type="text" name="banlengthother" class="post" /> {L_YEAR_MONTH_DAY}</td>
-</tr>
-<tr>
- <td class="row1" valign="top"><b>{L_BAN_EXCLUDE}{L_COLON}</b><br /><span class="gensmall">{L_BAN_EXCLUDE_EXPLAIN}</span></td>
- <td class="row2"><input type="radio" class="radio" name="banexclude" value="1" /> {L_YES} &nbsp; <input type="radio" class="radio" name="banexclude" value="0" checked="checked" /> {L_NO}</td>
-</tr>
-<tr>
- <td class="row1" valign="top"><b>{L_BAN_REASON}{L_COLON}</b></td>
- <td class="row2"><input name="banreason" type="text" class="post" maxlength="255" /></td>
-</tr>
-<tr>
- <td class="row1" valign="top"><b>{L_BAN_GIVE_REASON}{L_COLON}</b></td>
- <td class="row2"><input name="bangivereason" type="text" class="post" maxlength="255" /></td>
-</tr>
-<!-- EVENT mcp_ban_fields_after -->
-<tr>
- <td class="cat" colspan="2" align="center"><input type="submit" name="bansubmit" value="{L_SUBMIT}" class="btnmain" />&nbsp; <input type="reset" value="{L_RESET}" class="btnlite" />&nbsp;</td>
-</tr>
-</table>
-
-<br /><br />
-
-<table width="100%" class="tablebg" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <th colspan="2" nowrap="nowrap">{L_UNBAN_TITLE}</th>
-</tr>
-<tr>
- <td class="row3" colspan="2">{L_UNBAN_EXPLAIN}</td>
-</tr>
-<!-- IF S_BANNED_OPTIONS -->
- <!-- EVENT mcp_ban_unban_before -->
- <tr>
- <td class="row1" valign="top" width="45%"><b>{L_BAN_CELL}{L_COLON}</b></td>
- <td class="row2"><select name="unban[]" multiple="multiple" size="10" style="width: 50%" onchange="if (this.selectedIndex > -1) display_details(this.options[this.selectedIndex].value); else display_details(-1);">{BANNED_OPTIONS}</select></td>
- </tr>
- <tr>
- <td class="row1" valign="top"><b>{L_BAN_LENGTH}{L_COLON}</b></td>
- <td class="row2"><input style="border: 0; width: 100%" type="text" name="unbanlength" readonly="readonly" /></td>
- </tr>
- <tr>
- <td class="row1" valign="top"><b>{L_BAN_REASON}{L_COLON}</b></td>
- <td class="row2"><textarea style="border: 0; width: 100%" name="unbanreason" readonly="readonly" rows="5" cols="80">&nbsp;</textarea></td>
- </tr>
- <tr>
- <td class="row1" valign="top"><b>{L_BAN_GIVE_REASON}{L_COLON}</b></td>
- <td class="row2"><textarea style="border: 0; width: 100%" name="unbangivereason" readonly="readonly" rows="5" cols="80">&nbsp;</textarea></td>
- </tr>
- <!-- EVENT mcp_ban_unban_after -->
- <tr>
- <td class="cat" colspan="2" align="center"><input type="submit" name="unbansubmit" value="{L_SUBMIT}" class="btnmain" />&nbsp; <input type="reset" value="{L_RESET}" class="btnlite" />&nbsp;</td>
- </tr>
-<!-- ELSE -->
- <tr>
- <td class="row1" colspan="2"><b>{L_NO_BAN_CELL}</b></td>
- </tr>
-<!-- ENDIF -->
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_footer.html b/phpBB/styles/subsilver2/template/mcp_footer.html
deleted file mode 100644
index 280920b148..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_footer.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
- </td>
- </tr>
- </table>
-
- <!-- IF .pagination -->
- <table width="80%" align="{S_CONTENT_FLOW_END}" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ <!-- IF TOTAL_TOPICS -->{TOTAL_TOPICS}<!-- ELSEIF TOTAL_POSTS -->{TOTAL_POSTS}<!-- ELSE -->{TOTAL}<!-- ENDIF --> ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
- <br />
- <!-- ENDIF -->
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_forum.html b/phpBB/styles/subsilver2/template/mcp_forum.html
deleted file mode 100644
index d905910c22..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_forum.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<!-- IF S_MERGE_SELECT --><div style="float: {S_CONTENT_FLOW_END};"><!-- INCLUDE jumpbox.html --></div><!-- ENDIF -->
-
-<!-- IF U_VIEW_FORUM_LOGS --><a href="{U_VIEW_FORUM_LOGS}">{L_VIEW_FORUM_LOGS}</a><!-- ENDIF -->
-
-<!-- IF S_MERGE_SELECT --><br clear="{S_CONTENT_FLOW_END}" /><!-- ENDIF -->
-
-<form method="post" id="mcp" action="{S_MCP_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <td class="cat" colspan="6" align="center"><span class="gensmall">{L_DISPLAY_TOPICS}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" name="sort" value="{L_GO}" /></td>
-</tr>
-<tr>
- <th width="4%" nowrap="nowrap">&nbsp;</th>
- <th nowrap="nowrap">&nbsp;{L_TOPICS}&nbsp;</th>
- <th width="8%" nowrap="nowrap">&nbsp;{L_REPLIES}&nbsp;</th>
- <th width="17%" nowrap="nowrap">&nbsp;{L_LAST_POST}&nbsp;</th>
- <th width="5%" nowrap="nowrap">&nbsp;{L_MARK}&nbsp;</th>
-</tr>
-<!-- BEGIN topicrow -->
- <tr>
- <td class="row1" width="25" align="center">{topicrow.TOPIC_FOLDER_IMG}</td>
- <!-- IF S_TOPIC_ICONS -->
- <!-- td class="row1" width="25" align="center">{topicrow.TOPIC_ICON_IMG}</td -->
- <!-- ENDIF -->
- <td class="row1">
- <!-- EVENT topiclist_row_prepend -->
- <!-- IF topicrow.S_SELECT_TOPIC -->
- <span class="genmed">[ <a href="{topicrow.U_SELECT_TOPIC}">{L_SELECT_MERGE}</a> ]&nbsp;</span>
- <!-- ENDIF -->
- <p class="topictitle">{NEWEST_POST_IMG} {topicrow.ATTACH_ICON_IMG} <!-- EVENT mcp_forum_topic_title_before --><a href="{topicrow.U_VIEW_TOPIC}">{topicrow.TOPIC_TITLE}</a><!-- EVENT mcp_forum_topic_title_after -->
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED -->
- <a href="{topicrow.U_MCP_QUEUE}" class="imageset">{topicrow.UNAPPROVED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_DELETED or topicrow.S_POSTS_DELETED -->
- <a href="{topicrow.U_MCP_QUEUE}" class="imageset">{topicrow.DELETED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED and topicrow.U_MCP_REPORT -->
- <a href="{topicrow.U_MCP_REPORT}" class="imageset">{REPORTED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_MOVED_TOPIC and S_CAN_DELETE -->
- [ <a href="{topicrow.U_DELETE_TOPIC}">{L_DELETE_SHADOW_TOPIC}</a> ]&nbsp;
- <!-- ENDIF -->
- <!-- EVENT topiclist_row_topic_title_after -->
- </p>
- <!-- EVENT topiclist_row_append -->
- </td>
- <td class="row1" width="50" align="center"><p class="topicdetails">{topicrow.REPLIES}</p></td>
- <td class="row1" width="120" align="center"><p class="topicdetails">{topicrow.LAST_POST_TIME}</p></td>
- <td class="row2" align="center">
- <!-- IF not topicrow.S_MOVED_TOPIC and not S_MERGE_SELECT --><input type="checkbox" class="radio" name="topic_id_list[]" value="{topicrow.TOPIC_ID}"<!-- IF topicrow.S_TOPIC_CHECKED --> checked="checked"<!-- ENDIF --> /><!-- ELSE -->&nbsp;<!-- ENDIF -->
- </td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="8" align="center"><p class="gen">{L_NO_TOPICS}</p></td>
- </tr>
-<!-- END topicrow -->
-<!-- EVENT mcp_forum_actions_before -->
-<!-- IF not S_MERGE_SELECT -->
-<tr>
- <td class="cat" colspan="6" align="{S_CONTENT_FLOW_END}">
- <select name="action">
- <option value="" selected="selected">{L_SELECT_ACTION}</option>
- <!-- IF S_CAN_DELETE --><option value="delete_topic">{L_DELETE}</option><!-- ENDIF -->
- <!-- IF S_CAN_RESTORE --><option value="restore_topic">{L_RESTORE}</option><!-- ENDIF -->
- <!-- IF S_CAN_MERGE --><option value="merge_topics">{L_MERGE}</option><!-- ENDIF -->
- <!-- IF S_CAN_MOVE --><option value="move">{L_MOVE}</option><!-- ENDIF -->
- <!-- IF S_CAN_FORK --><option value="fork">{L_FORK}</option><!-- ENDIF -->
- <!-- IF S_CAN_LOCK --><option value="lock">{L_LOCK}</option><option value="unlock">{L_UNLOCK}</option><!-- ENDIF -->
- <!-- IF S_CAN_SYNC --><option value="resync">{L_RESYNC}</option><!-- ENDIF -->
- <!-- IF S_CAN_MAKE_NORMAL --><option value="make_normal">{L_MAKE_NORMAL}</option><!-- ENDIF -->
- <!-- IF S_CAN_MAKE_STICKY --><option value="make_sticky">{L_MAKE_STICKY}</option><!-- ENDIF -->
- <!-- IF S_CAN_MAKE_ANNOUNCE -->
- <option value="make_announce">{L_MAKE_ANNOUNCE}</option>
- <option value="make_global">{L_MAKE_GLOBAL}</option>
- <!-- ENDIF -->
- </select>
- <input class="btnmain" type="submit" value="{L_SUBMIT}" />
- </td>
-</tr>
-<!-- ENDIF -->
-<!-- EVENT mcp_forum_actions_after -->
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<!-- IF not S_MERGE_SELECT -->
-<table width="100%" cellspacing="2" cellpadding="2" border="0" align="center">
-<tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="gensmall"><a href="#" onclick="marklist('mcp', 'topic_id_list', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp', 'topic_id_list', false); return false;">{L_UNMARK_ALL}</a></b></td>
-</tr>
-</table>
-<!-- ENDIF -->
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_front.html b/phpBB/styles/subsilver2/template/mcp_front.html
deleted file mode 100644
index 55adb3b550..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_front.html
+++ /dev/null
@@ -1,147 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<!-- EVENT mcp_front_latest_unapproved_before -->
-
-<!-- IF S_SHOW_UNAPPROVED -->
- <form name="mcp_queue" method="post" action="{S_MCP_QUEUE_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3" colspan="6" align="center"><b class="gen">{L_LATEST_UNAPPROVED}</b></td>
- </tr>
- <tr>
- <th>&nbsp;{L_FORUM}&nbsp;</th>
- <th>&nbsp;{L_TOPIC}&nbsp;</th>
- <th>&nbsp;{L_SUBJECT}&nbsp;</th>
- <th>&nbsp;{L_AUTHOR}&nbsp;</th>
- <th>&nbsp;{L_POST_TIME}&nbsp;</th>
- <th width="5%">&nbsp;{L_SELECT}&nbsp;</th>
- </tr>
- <!-- BEGIN unapproved -->
- <tr>
- <td class="row1" width="15%" valign="top"><span class="gen"><!-- IF unapproved.U_FORUM --><a href="{unapproved.U_FORUM}">{unapproved.FORUM_NAME}</a><!-- ELSE -->{unapproved.FORUM_NAME}<!-- ENDIF --></span><!-- IF unapproved.U_MCP_FORUM --><br /><span class="gensmall">[ <a href="{unapproved.U_MCP_FORUM}">{L_MODERATE}</a> ]</span><!-- ENDIF --></td>
- <td class="row2" valign="top"><span class="gen"><a href="{unapproved.U_TOPIC}">{unapproved.TOPIC_TITLE}</a></span><br /><span class="gensmall">[ <a href="{unapproved.U_MCP_TOPIC}">{L_MODERATE}</a> ]</span></td>
- <td class="row1" valign="top">{unapproved.ATTACH_ICON_IMG} <span class="gen">{unapproved.SUBJECT}</span><br /><span class="gensmall">[ <a href="{unapproved.U_POST_DETAILS}">{L_VIEW_DETAILS}</a> ]</span></td>
- <td class="row2" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gen">{unapproved.AUTHOR_FULL}</span></td>
- <td class="row1" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gensmall">{unapproved.POST_TIME}</span></td>
- <td class="row2" align="center"><input type="checkbox" class="radio" name="post_id_list[]" value="{unapproved.POST_ID}" /></td>
- </tr>
- <!-- END unapproved -->
- <tr>
- <td class="row3" colspan="6"><span class="gensmall">{L_UNAPPROVED_TOTAL}</span></td>
- </tr>
- <tr>
- <td class="cat" colspan="6" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="action[approve]" value="{L_APPROVE}" />&nbsp;&nbsp;<input class="btnlite" type="submit" name="action[disapprove]" value="{L_DISAPPROVE}" /></td>
- </tr>
- </table>
- {S_FORM_TOKEN}
- </form>
-
- <table width="100%" cellspacing="2" cellpadding="2" border="0" align="center">
- <tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="gensmall"><a href="#" onclick="marklist('mcp_queue', '', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp_queue', '', false); return false;">{L_UNMARK_ALL}</a></b></td>
- </tr>
- </table>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<!-- EVENT mcp_front_latest_reported_before -->
-
-<!-- IF S_SHOW_REPORTS -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3" colspan="5" align="center"><b class="gen">{L_LATEST_REPORTED}</b></td>
- </tr>
- <tr>
- <th>&nbsp;{L_FORUM}&nbsp;</th>
- <th>&nbsp;{L_TOPIC}&nbsp;</th>
- <th>&nbsp;{L_SUBJECT}&nbsp;</th>
- <th>&nbsp;{L_REPORTER}&nbsp;</th>
- <th>&nbsp;{L_REPORT_TIME}&nbsp;</th>
- </tr>
- <!-- BEGIN report -->
- <tr>
- <td class="row1" width="15%" valign="top"><span class="gen"><!-- IF report.U_FORUM --><a href="{report.U_FORUM}">{report.FORUM_NAME}</a><!-- ELSE -->{report.FORUM_NAME}<!-- ENDIF --></span><!-- IF report.U_MCP_FORUM --><br /><span class="gensmall">[ <a href="{report.U_MCP_FORUM}">{L_MODERATE}</a> ]</span><!-- ENDIF --></td>
- <td class="row2" valign="top"><span class="gen"><a href="{report.U_TOPIC}">{report.TOPIC_TITLE}</a></span><br /><span class="gensmall">[ <a href="{report.U_MCP_TOPIC}">{L_MODERATE}</a> ]</span></td>
- <td class="row1" valign="top">{report.ATTACH_ICON_IMG} <span class="gen">{report.SUBJECT}</span><br /><span class="gensmall">[ <a href="{report.U_POST_DETAILS}">{L_VIEW_DETAILS}</a> ]</span></td>
- <td class="row2" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gen">{report.REPORTER_FULL}</span></td>
- <td class="row1" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gensmall">{report.REPORT_TIME}</span></td>
- </tr>
- <!-- END report -->
- <tr>
- <td class="row3" colspan="5"><span class="gensmall">{L_REPORTS_TOTAL}</span></td>
- </tr>
- </table>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<!-- EVENT mcp_front_latest_reported_pms_before -->
-
-<!-- IF S_SHOW_PM_REPORTS -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3" colspan="6" align="center"><b class="gen">{L_LATEST_REPORTED_PMS}</b></td>
- </tr>
- <tr>
- <th>&nbsp;{L_PM_SUBJECT}&nbsp;</th>
- <th>&nbsp;{L_PM_FROM}&nbsp;</th>
- <th>&nbsp;{L_TO} &amp; {L_BCC}&nbsp;</th>
- <th>&nbsp;{L_SENT_AT}&nbsp;</th>
- <th>&nbsp;{L_REPORTER}&nbsp;</th>
- <th>&nbsp;{L_REPORT_TIME}&nbsp;</th>
- </tr>
- <!-- BEGIN pm_report -->
- <tr>
- <td class="row1" valign="top">{pm_report.ATTACH_ICON_IMG} <span class="gen">{pm_report.PM_SUBJECT}</span><br /><span class="gensmall">[ <a href="{pm_report.U_PM_DETAILS}">{L_VIEW_DETAILS}</a> ]</span></td>
- <td class="row2" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gen">{pm_report.PM_AUTHOR_FULL}</span></td>
- <td class="row1" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gen">{pm_report.RECIPIENTS}</span></td>
- <td class="row2" align="center" width="10%" nowrap="nowrap" valign="top"><span class="gensmall">{pm_report.PM_TIME}</span></td>
- <td class="row1" align="center" width="15%" nowrap="nowrap" valign="top"><span class="gen">{pm_report.REPORTER_FULL}</span></td>
- <td class="row2" align="center" width="10%" nowrap="nowrap" valign="top"><span class="gensmall">{pm_report.REPORT_TIME}</span></td>
- </tr>
- <!-- END pm_report -->
- <tr>
- <td class="row3" colspan="6"><span class="gensmall">{L_PM_REPORTS_TOTAL}</span></td>
- </tr>
- </table>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<!-- EVENT mcp_front_latest_logs_before -->
-
-<!-- IF S_SHOW_LOGS -->
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="4" border="0" align="{S_CONTENT_FLOW_END}">
- <tr>
- <td class="row3" colspan="5" align="center"><b class="gen">{L_LATEST_LOGS}</b></td>
- </tr>
- <tr>
- <th width="15%" nowrap="nowrap">{L_USERNAME}</th>
- <th width="12%" nowrap="nowrap">{L_IP}</th>
- <th width="45%" nowrap="nowrap">{L_ACTION}</th>
- <th nowrap="nowrap"></th>
- <th width="18%" nowrap="nowrap">{L_TIME}</th>
- </tr>
- <!-- BEGIN log -->
- <tr>
- <td class="row1" nowrap="nowrap"><span class="gen">{log.USERNAME}</span></td>
- <td class="row1" align="center" nowrap="nowrap"><span class="gen">{log.IP}</span></td>
- <td class="row1"><span class="genmed">{log.ACTION}</span></td>
- <td class="row1" align="center" nowrap="nowrap"><span class="gensmall"><!-- IF log.U_VIEW_TOPIC --><a href="{log.U_VIEW_TOPIC}">{L_VIEW_TOPIC}</a><!-- IF log.U_VIEWLOGS --> | <!-- ENDIF --><!-- ENDIF --><!-- IF log.U_VIEWLOGS --><a href="{log.U_VIEWLOGS}">{L_VIEW_TOPIC_LOGS}</a><!-- ENDIF --></span></td>
- <td class="row1" align="center" nowrap="nowrap"><span class="gensmall">{log.TIME}</span></td>
- </tr>
- <!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="5" align="center"><span class="gen">{L_NO_ENTRIES}</span></td>
- </tr>
- <!-- END log -->
- </table>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<!-- EVENT mcp_front_latest_logs_after -->
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_header.html b/phpBB/styles/subsilver2/template/mcp_header.html
deleted file mode 100644
index 7144750ed4..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_header.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div id="pageheader">
- <!-- IF U_MCP -->
- <p class="linkmcp">
- [<!-- IF U_ACP -->&nbsp;<a href="{U_ACP}">{L_ACP}</a>&nbsp;|<!-- ENDIF -->&nbsp;<a href="{U_MCP}">{L_MCP}</a><!-- IF U_MCP_FORUM -->&nbsp;|&nbsp;<a href="{U_MCP_FORUM}">{L_MODERATE_FORUM}</a><!-- ENDIF --><!-- IF U_MCP_TOPIC -->&nbsp;|&nbsp;<a href="{U_MCP_TOPIC}">{L_MODERATE_TOPIC}</a><!-- ENDIF --><!-- IF U_MCP_POST -->&nbsp;|&nbsp;<a href="{U_MCP_POST}">{L_MODERATE_POST}</a><!-- ENDIF -->&nbsp;]
- </p>
- <!-- ENDIF -->
-
- <!-- IF TOPIC_TITLE or FORUM_NAME -->
- <h2><!-- IF TOPIC_TITLE --><a class="titles" href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a><!-- ELSE --><a class="titles" href="{U_VIEW_FORUM}">{FORUM_NAME}</a><!-- ENDIF --></h2>
- <!-- ENDIF -->
-</div>
-
-<br clear="all" />
-
-<div id="pagecontent">
-
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td width="20%" valign="top">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_OPTIONS}</th>
- </tr>
- <!-- BEGIN l_block1 -->
- <tr>
- <!-- IF l_block1.S_SELECTED -->
- <td class="row1"><b class="nav">{l_block1.L_TITLE}</b>
-
- <ul class="nav" style="margin: 0; padding: 0; list-style-type: none; line-height: 175%;">
- <!-- BEGIN l_block2 -->
- <li>&#187; <!-- IF l_block1.l_block2.S_SELECTED --><b>{l_block1.l_block2.L_TITLE}</b><!-- ELSE --><a href="{l_block1.l_block2.U_TITLE}">{l_block1.l_block2.L_TITLE}</a><!-- ENDIF --></li>
- <!-- END l_block2 -->
- </ul>
- <!-- ELSE -->
- <td class="row2" nowrap="nowrap" onmouseover="this.className='row1'" onmouseout="this.className='row2'" onclick="location.href=this.firstChild.href;"><a class="nav" href="{l_block1.U_TITLE}">{l_block1.L_TITLE}</a>
- <!-- ENDIF -->
- </td>
- </tr>
- <!-- END l_block1 -->
- </table>
-
- </td>
- <td><img src="images/spacer.gif" width="4" alt="" /></td>
- <td width="80%" valign="top">
-
- <!-- IF MESSAGE -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_MESSAGE}</th>
- </tr>
- <tr>
- <td class="row1" align="center"><br /><span class="gen">{MESSAGE}<br /><br /><!-- BEGIN return_links -->{return_links.MESSAGE_LINK}<br /><br /><!-- END return_links --></span></td>
- </tr>
- </table>
-
- <br />
- <!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/mcp_logs.html b/phpBB/styles/subsilver2/template/mcp_logs.html
deleted file mode 100644
index 64f2a6a64d..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_logs.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th>{L_USERNAME}</th>
- <th>{L_IP}</th>
- <th>{L_TIME}</th>
- <th>{L_ACTION}</th>
- <!-- IF S_CLEAR_ALLOWED --><th>{L_MARK}</th><!-- ENDIF -->
-</tr>
-<!-- IF S_LOGS -->
-
- <!-- BEGIN log -->
- <!-- IF log.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td class="genmed">{log.USERNAME}</td>
- <td class="genmed" style="text-align: center;">{log.IP}</td>
- <td class="genmed" style="text-align: center;">{log.DATE}</td>
- <td class="genmed">{log.ACTION}<br />{log.DATA}</td>
- <!-- IF S_CLEAR_ALLOWED --><td width="5%" align="center"><input type="checkbox" class="radio" name="mark[]" value="{log.ID}" /></td><!-- ENDIF -->
- </tr>
- <!-- END log -->
- <tr align="center">
- <td class="row3" colspan="<!-- IF S_CLEAR_ALLOWED -->5<!-- ELSE -->4<!-- ENDIF -->"><span class="gensmall">{L_SEARCH_KEYWORDS}{L_COLON}</span> <input type="text" name="keywords" value="{S_KEYWORDS}" />&nbsp;<input type="submit" class="btnlite" name="filter" value="{L_SEARCH}" /></td>
- </tr>
- <tr align="center">
- <td class="row3" colspan="<!-- IF S_CLEAR_ALLOWED -->5<!-- ELSE -->4<!-- ENDIF -->"><span class="gensmall">{L_DISPLAY_LOG}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" value="{L_GO}" name="sort" /></td>
- </tr>
- <!-- IF S_CLEAR_ALLOWED -->
- <tr>
- <td class="cat" colspan="5" align="center"><input class="btnlite" type="submit" name="action[del_all]" value="{L_DELETE_ALL}" />&nbsp; <input class="btnlite" type="submit" name="action[del_marked]" value="{L_DELETE_MARKED}" /></td>
- </tr>
- <!-- ENDIF -->
-<!-- ELSE -->
- <tr>
- <td class="row1" colspan="<!-- IF S_CLEAR_ALLOWED -->5<!-- ELSE -->4<!-- ENDIF -->" align="center"><span class="gen">{L_NO_ENTRIES}</span></td>
- </tr>
-<!-- ENDIF -->
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_message.html b/phpBB/styles/subsilver2/template/mcp_message.html
deleted file mode 100644
index 5699dd54af..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_message.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1" cellpadding="4" border="0" align="center">
-<tr>
- <th><b>{MESSAGE_TITLE}</b></th>
-</tr>
-<tr>
- <td class="row1" align="center"><br /><span class="gen">{MESSAGE_TEXT}</span><br /><br /></td>
-</tr>
-</table>
-
-<br clear="all" />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_move.html b/phpBB/styles/subsilver2/template/mcp_move.html
deleted file mode 100644
index 429fee7e38..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_move.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- EVENT mcp_move_before -->
-
-<div id="pagecontent">
-
- <form name="confirm" action="{S_CONFIRM_ACTION}" method="post">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{MESSAGE_TITLE}</th>
- </tr>
- <tr>
- <td class="row1" align="center">
- <!-- IF ADDITIONAL_MSG -->
- <span class="gen error">{ADDITIONAL_MSG}</span><br />
- <!-- ENDIF -->
- <!-- IF S_FORUM_SELECT -->
- <span class="gen"><br />{L_SELECT_DESTINATION_FORUM}&nbsp;&nbsp;</span>
- <select name="to_forum_id">{S_FORUM_SELECT}</select><br />
- <!-- IF S_CAN_LEAVE_SHADOW -->
- <input type="checkbox" class="radio" name="move_leave_shadow" /><span class="gen">{L_LEAVE_SHADOW}</span><br />
- <!-- ENDIF -->
- <!-- IF S_CAN_LOCK_TOPIC -->
- <input type="checkbox" class="radio" name="move_lock_topics" /><span class="gen">{L_LOCK_TOPIC}</span><br />
- <!-- ENDIF -->
- <br />{S_HIDDEN_FIELDS}<span class="gen">{MESSAGE_TEXT}</span><br /><br />
- <input type="submit" name="confirm" value="{YES_VALUE}" class="btnmain" />&nbsp;&nbsp;<input type="submit" name="cancel" value="{L_NO}" class="btnlite" />
- <!-- ELSE -->
- <span class="gen">{L_NO_DESTINATION_FORUM}</span><br /><br />
- {S_HIDDEN_FIELDS}
- <input type="submit" name="cancel" value="{L_CANCEL}" class="btnlite" />
- <!-- ENDIF -->
- </td>
- </tr>
- </table>
- {S_FORM_TOKEN}
- </form>
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_notes_front.html b/phpBB/styles/subsilver2/template/mcp_notes_front.html
deleted file mode 100644
index e2e14e0150..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_notes_front.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1" cellpadding="4" border="0" align="center">
-<tr>
- <th colspan="2"align="center">{L_SELECT_USER}</th>
-</tr>
-<tr>
- <td class="row1" width="40%"><b class="gen">{L_FIND_USERNAME}{L_COLON} </b><br /><span class="gensmall">[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</span></td>
- <td class="row2"><input type="text" class="post" name="username" size="20" /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center"><input type="submit" name="submituser" value="{L_SUBMIT}" class="btnmain" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_notes_user.html b/phpBB/styles/subsilver2/template/mcp_notes_user.html
deleted file mode 100644
index 4bd8de6862..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_notes_user.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th colspan="2" align="center">{USERNAME}</th>
-</tr>
-<tr>
- <td class="row1" align="center">
- <table cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="center"><b>{USERNAME_FULL}</b></td>
- </tr>
- <!-- IF RANK_TITLE -->
- <tr>
- <td class="postdetails" align="center">{RANK_TITLE}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF RANK_IMG -->
- <tr>
- <td align="center">{RANK_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td align="center"><!-- IF AVATAR_IMG -->{AVATAR_IMG}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF --></td>
- </tr>
- </table>
- </td>
- <td class="row1">
- <table width="100%" cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_JOINED}{L_COLON} </td>
- <td width="100%"><b class="gen">{JOINED}</b></td>
- </tr>
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_TOTAL_POSTS}{L_COLON} </td>
- <td><b class="gen">{POSTS}</b></td>
- </tr>
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_WARNINGS}{L_COLON} </td>
- <td><b class="gen">{WARNINGS}</b></td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
-
-<br />
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th colspan="5" align="center">{L_FEEDBACK}</th>
-</tr>
-<!-- IF S_USER_NOTES -->
-
- <tr align="center">
- <td colspan="5" class="row3"><span class="gensmall">{L_SEARCH_KEYWORDS}{L_COLON}</span> <input type="text" name="keywords" value="{S_KEYWORDS}" />&nbsp;<input type="submit" class="btnlite" name="filter" value="{L_SEARCH}" /></td>
- </tr>
- <tr align="center">
- <td colspan="5" class="row3"><span class="gensmall">{L_DISPLAY_LOG}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}{L_COLON}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" value="{L_GO}" name="sort" /></td>
- </tr>
- <tr>
- <th>{L_REPORT_BY}</th>
- <th>{L_IP}</th>
- <th>{L_TIME}</th>
- <th>{L_ACTION}</th>
- <th><!-- IF S_CLEAR_ALLOWED -->{L_MARK}<!-- ENDIF --></th>
- </tr>
-
- <!-- BEGIN usernotes -->
- <!-- IF usernotes.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td class="gen">{usernotes.REPORT_BY}</td>
- <td style="text-align: center;">{usernotes.IP}</td>
- <td style="text-align: center;">{usernotes.REPORT_AT}</td>
- <td class="gen">
- {usernotes.ACTION}
- <!-- IF usernotes.DATA --><br />&#187; <span class="gensmall">[ {usernotes.DATA} ]</span><!-- ENDIF -->
- </td>
- <td style="text-align: center;"><!-- IF S_CLEAR_ALLOWED --><input type="checkbox" class="radio" name="marknote[]" value="{usernotes.ID}" /><!-- ENDIF --></td>
- </tr>
- <!-- END usernotes -->
-
- <!-- IF S_CLEAR_ALLOWED -->
- <tr>
- <td class="cat" colspan="5" align="center"><input class="btnlite" type="submit" name="action[del_all]" value="{L_DELETE_ALL}" />&nbsp; <input class="btnlite" type="submit" name="action[del_marked]" value="{L_DELETE_MARKED}" /></td>
- </tr>
- <!-- ENDIF -->
-
-<!-- ELSE -->
- <tr>
- <td class="row1" colspan="2" align="center"><span class="gen">{L_NO_FEEDBACK}</span></td>
- </tr>
-<!-- ENDIF -->
-</table>
-
-<br clear="all" />
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th colspan="2" align="center">{L_ADD_FEEDBACK}</th>
-</tr>
-<tr>
- <td class="row3" align="center" colspan="2"><span class="genmed">{L_ADD_FEEDBACK_EXPLAIN}</span></td>
-</tr>
-<tr>
- <td colspan="2" class="row1" align="center"><textarea name="usernote" rows="10" cols="76"></textarea></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center"><input class="btnmain" type="submit" name="action[add_feedback]" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" /></td>
-</tr>
-</table>
-
-<table width="100%" cellspacing="0" cellpadding="0">
-<tr>
- <td class="pagination">{PAGE_NUMBER} [ {TOTAL_REPORTS} ]</td>
- <td align="{S_CONTENT_FLOW_END}"><span class="pagination"><!-- INCLUDE pagination.html --></span></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_post.html b/phpBB/styles/subsilver2/template/mcp_post.html
deleted file mode 100644
index 1a29df94b0..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_post.html
+++ /dev/null
@@ -1,214 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<!-- IF S_MCP_REPORT -->
- <form method="post" name="mcp_report" action="{S_CLOSE_ACTION}">
-
- <table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
- <tr>
- <th colspan="2" align="center"><!-- IF S_PM -->{L_PM_REPORT_DETAILS}<!-- ELSE -->{L_REPORT_DETAILS}<!-- ENDIF --></th>
- </tr>
- <tr>
- <td class="row1"><b class="gen">{L_REPORT_REASON}{L_COLON} </b></td>
- <td class="row2"><span class="gen">{REPORT_REASON_TITLE} &raquo; {REPORT_REASON_DESCRIPTION}</span></td>
- </tr>
- <tr>
- <td class="row1" width="20%"><b class="gen">{L_REPORTER}{L_COLON} </b></td>
- <td class="row2" width="80%"><span class="gen"<!-- IF REPORTER_COLOUR --> style="font-weight: bold; color: {REPORTER_COLOUR};"<!-- ENDIF -->>{REPORTER_NAME}</span> &nbsp; <span class="gen">[ <!-- IF U_VIEW_REPORTER_PROFILE --><a href="{U_VIEW_REPORTER_PROFILE}">{L_READ_PROFILE}</a><!-- ENDIF --><!-- IF S_USER_NOTES --><!-- IF U_VIEW_REPORTER_PROFILE --> | <!-- ENDIF --><a href="{U_MCP_REPORTER_NOTES}">{L_VIEW_NOTES}</a> | <a href="{U_MCP_WARN_REPORTER}">{L_WARN_USER}</a><!-- ENDIF --> ]</span></td>
- </tr>
- <tr>
- <td class="row1"><b class="gen">{L_REPORTED}{L_COLON} </b></td>
- <td class="row2"><span class="postdetails">{REPORT_DATE}</span></td>
- </tr>
- <!-- IF REPORT_TEXT -->
- <tr>
- <th colspan="2" align="center">{L_MORE_INFO}</th>
- </tr>
- <tr>
- <td class="row1" colspan="2"><div class="gen" style="overflow: auto; width: 100%; height: 80pt; border: 1px;">{REPORT_TEXT}</div></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="cat" align="center" colspan="2"><!-- IF not S_REPORT_CLOSED --><input class="btnmain" type="submit" value="{L_CLOSE_REPORT}" name="action[close]" /><!-- ELSE -->{L_REPORT_CLOSED}<!-- ENDIF --> &nbsp; <input class="btnlite" type="submit" value="{L_DELETE_REPORT}" name="action[delete]" /></td>
- </tr>
- </table>
-
- <input type="hidden" name="report_id_list[]" value="{REPORT_ID}" />
- {S_FORM_TOKEN}
- </form>
-
- <br clear="all"/>
-<!-- ENDIF -->
-
-<!-- IF S_MCP_QUEUE --><form method="post" name="mcp_approve" action="{U_APPROVE_ACTION}"><!-- ELSE --><form method="post" name="mcp_report_details" action="{S_CLOSE_ACTION}"><!-- ENDIF -->
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th colspan="2" align="center"><!-- IF S_PM -->{L_PM}<!-- ELSE -->{L_POST_DETAILS}<!-- ENDIF --></th>
-</tr>
-<tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall"><!-- IF S_MCP_QUEUE -->{RETURN_QUEUE} | {RETURN_TOPIC_SIMPLE} | {RETURN_POST}<!-- ELSEIF S_MCP_REPORT -->{RETURN_REPORTS}<!-- IF not S_PM --> | <a href="{U_VIEW_POST}">{L_VIEW_POST}</a> | <a href="{U_VIEW_TOPIC}">{L_VIEW_TOPIC}</a> | <a href="{U_VIEW_FORUM}">{L_VIEW_FORUM}</a><!-- ENDIF --><!-- ELSE -->{RETURN_TOPIC}<!-- ENDIF --></span></td>
-</tr>
-<tr>
- <td class="row1"><b class="gen"><!-- IF S_PM -->{L_PM_SUBJECT}<!-- ELSE -->{L_POST_SUBJECT}<!-- ENDIF -->{L_COLON} </b></td>
- <td class="row2">
- <span class="gen">{POST_SUBJECT}</span>
- <!-- IF S_POST_UNAPPROVED --><span class="postapprove">{UNAPPROVED_IMG} <a href="{U_MCP_APPROVE}">{L_POST_UNAPPROVED}</a></span> <!-- ENDIF -->
- <!-- IF S_POST_DELETED --><span class="postapprove">{DELETED_IMG} <a href="{U_MCP_APPROVE}">{L_POST_DELETED}</a></span> <!-- ENDIF -->
- <!-- IF S_POST_REPORTED and not S_MCP_REPORT --><span class="postreported">{REPORTED_IMG} <a href="{U_MCP_REPORT}">{L_POST_REPORTED}</a></span><!-- ENDIF -->
- </td>
-</tr>
-<tr>
- <td class="row1" width="20%"><b class="gen"><!-- IF S_PM -->{L_PM_FROM}<!-- ELSE -->{L_POSTER}<!-- ENDIF -->{L_COLON} </b></td>
- <td class="row2" width="80%"><span class="gen"<!-- IF POST_AUTHOR_COLOUR --> style="font-weight: bold; color: {POST_AUTHOR_COLOUR}"<!-- ENDIF -->>{POST_AUTHOR}</span><span class="gen"> &nbsp; [ <!-- IF U_POST_AUTHOR --><a href="{U_POST_AUTHOR}">{L_READ_PROFILE}</a><!-- ENDIF --><!-- IF S_USER_NOTES --><!-- IF U_POST_AUTHOR --> | <!-- ENDIF --><a href="{U_MCP_USER_NOTES}">{L_VIEW_NOTES}</a> <!-- IF U_MCP_WARN_USER -->| <a href="{U_MCP_WARN_USER}">{L_WARN_USER}</a><!-- ENDIF --><!-- ENDIF --> ]</span></td>
-</tr>
-<!-- IF S_CAN_VIEWIP -->
- <tr>
- <td class="row1"><b class="gen"><!-- IF S_PM -->{L_THIS_PM_IP}<!-- ELSE -->{L_THIS_POST_IP}<!-- ENDIF -->{L_COLON} </b></td>
- <td class="row2"><span class="gen">
- <!-- IF U_WHOIS -->
- <a href="{U_WHOIS}"><!-- IF POST_IPADDR -->{POST_IPADDR}<!-- ELSE -->{POST_IP}<!-- ENDIF --></a> (<!-- IF POST_IPADDR -->{POST_IP}<!-- ELSE --><a href="{U_LOOKUP_IP}">{L_LOOKUP_IP}</a><!-- ENDIF -->)
- <!-- ELSE -->
- <!-- IF POST_IPADDR -->{POST_IPADDR} ({POST_IP})<!-- ELSE -->{POST_IP}<!-- IF U_LOOKUP_IP --> (<a href="{U_LOOKUP_IP}">{L_LOOKUP_IP}</a>)<!-- ENDIF --><!-- ENDIF -->
- <!-- ENDIF -->
- </span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1"><b class="gen"><!-- IF S_PM -->{L_SENT_AT}<!-- ELSE -->{L_POSTED}<!-- ENDIF -->{L_COLON} </b></td>
- <td class="row2"><span class="postdetails">{POST_DATE}</span></td>
-</tr>
-<!-- IF S_TO_RECIPIENT -->
- <tr>
- <td class="row1" nowrap="nowrap" width="150"><b class="gen">{L_TO}{L_COLON}</b></td>
- <td class="row2 gen">
- <!-- BEGIN to_recipient -->
- <!-- IF to_recipient.IS_GROUP --><span class="sep"><a href="{to_recipient.U_VIEW}">{to_recipient.NAME}</a></span><!-- ELSE -->{to_recipient.NAME_FULL}&nbsp;<!-- ENDIF -->
- <!-- END to_recipient -->
- </td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_BCC_RECIPIENT -->
- <tr>
- <td class="row1" nowrap="nowrap" width="150"><b class="gen">{L_BCC}{L_COLON}</b></td>
- <td class="row2 gen">
- <!-- BEGIN bcc_recipient -->
- <!-- IF bcc_recipient.IS_GROUP --><span class="sep"><a href="{bcc_recipient.U_VIEW}">{bcc_recipient.NAME}</a></span><!-- ELSE -->{bcc_recipient.NAME_FULL}&nbsp;<!-- ENDIF -->
- <!-- END bcc_recipient -->
- </td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <th colspan="2" align="center">{L_PREVIEW}</th>
-</tr>
-<tr>
- <td class="row1" colspan="2">
- <!-- IF U_EDIT --><div class="gen" style="float: {S_CONTENT_FLOW_END};"><a href="{U_EDIT}" class="imageset">{EDIT_IMG}</a></div><!-- ENDIF -->
-
- <div class="postbody">{POST_PREVIEW}</div>
-
- <!-- IF S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <!-- IF attachment.S_ROW_COUNT is even --><td class="row2"><!-- ELSE --><td class="row1"><!-- ENDIF -->{attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- </td>
-</tr>
-<!-- IF S_POST_UNAPPROVED and S_MCP_QUEUE -->
- <tr>
- <td class="cat" align="center" colspan="2"><input class="btnmain" type="submit" value="{L_APPROVE}" name="action[approve]" /> &nbsp; <input class="btnlite" type="submit" value="{L_DISAPPROVE}" name="action[disapprove]" /></td>
- </tr>
- <input type="hidden" name="post_id_list[]" value="{POST_ID}" />
-<!-- ENDIF -->
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<!-- IF S_MCP_QUEUE -->
- <br clear="all" />
-
- <!-- IF S_TOPIC_REVIEW --><!-- INCLUDE posting_topic_review.html --><!-- ENDIF -->
-<!-- ELSEIF S_MCP_REPORT -->
- <br clear="all" />
-
- <!-- IF S_TOPIC_REVIEW --><!-- INCLUDE posting_topic_review.html --><!-- ENDIF -->
-<!-- ELSE -->
- <!-- IF S_CAN_LOCK_POST or S_CAN_DELETE_POST or S_CAN_CHGPOSTER or S_MCP_POST_ADDITIONAL_OPTS -->
- <br /><a name="mod" class="anchor"></a>
-
- <table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
- <tr>
- <th colspan="2" align="center">{L_MOD_OPTIONS}</th>
- </tr>
- <!-- IF S_CAN_CHGPOSTER -->
- <tr>
- <td class="row1" valign="top"><b class="gen">{L_CHANGE_POSTER}</b></td>
- <td class="row2"><form method="post" name="mcp_chgposter" action="{U_POST_ACTION}"><input class="post" type="text" name="username" value="" /> <input class="btnmain" type="submit" value="{L_CONFIRM}" name="action[chgposter]" /><br /><span class="gensmall">[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</span><!-- IF S_USER_SELECT --><br /><select name="u">{S_USER_SELECT}</select> <input type="submit" class="btnmain" name="action[chgposter_ip]" value="{L_CONFIRM}" /><!-- ENDIF -->{S_FORM_TOKEN}</form></td>
- </tr>
- <!-- ENDIF -->
-
- <!-- EVENT mcp_post_additional_options -->
-
- <!-- IF S_CAN_LOCK_POST or S_CAN_DELETE_POST -->
- <tr>
- <td class="row1" valign="top"><b class="gen">{L_MOD_OPTIONS}</b></td>
- <td class="row2"><form method="post" name="mcp" action="{U_MCP_ACTION}"><select name="action"><!-- IF S_CAN_LOCK_POST --><!-- IF S_POST_LOCKED --><option value="unlock_post">{L_UNLOCK_POST} [{L_UNLOCK_POST_EXPLAIN}]</option><!-- ELSE --><option value="lock_post">{L_LOCK_POST} [{L_LOCK_POST_EXPLAIN}]</option><!-- ENDIF --><!-- ENDIF --><!-- IF S_CAN_DELETE_POST --><option value="delete_post">{L_DELETE_POST}</option><!-- ENDIF --></select> <input class="btnmain" type="submit" value="{L_SUBMIT}" /> {S_FORM_TOKEN}</form></td>
- </tr>
- <!-- ENDIF -->
- </table>
- <!-- ENDIF -->
-
- <!-- IF S_CAN_VIEWIP -->
- <br /><a name="ip" class="anchor"></a>
-
- <table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
- <tr>
- <th colspan="2" align="center">{L_IP_INFO}</th>
- </tr>
- <tr>
- <td colspan="2" class="cat"><b class="gen">{L_OTHER_USERS}</b></td>
- </tr>
- <!-- BEGIN userrow -->
- <!-- IF userrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td><span class="gen"><!-- IF userrow.U_PROFILE --><a href="{userrow.U_PROFILE}">{userrow.USERNAME}</a><!-- ELSE -->{userrow.USERNAME}<!-- ENDIF --> [ {userrow.NUM_POSTS} {userrow.L_POST_S} ]</span></td>
- <td align="center"><a href="{userrow.U_SEARCHPOSTS}" class="imageset">{SEARCH_IMG}</a></td>
- </tr>
- <!-- BEGINELSE -->
- <tr class="row1">
- <td colspan="2" align="center"><span class="gen">{L_NO_MATCHES_FOUND}</span></td>
- </tr>
- <!-- END userrow -->
- <tr>
- <td class="cat"><b class="gen">{L_IPS_POSTED_FROM}</b></td>
- <td class="cat" width="10%" nowrap="nowrap"><!-- IF U_LOOKUP_ALL --><span class="gen">[ <a href="{U_LOOKUP_ALL}">{L_LOOKUP_ALL}</a> ]</span><!-- ENDIF --></td>
- </tr>
- <!-- BEGIN iprow -->
- <!-- IF iprow.S_ROW_COUNT is even -->
- <tr class="row1">
- <!-- ELSE -->
- <tr class="row2">
- <!-- ENDIF -->
- <td><span class="gen"><!-- IF iprow.HOSTNAME --><a href="{iprow.U_WHOIS}">{iprow.HOSTNAME}</a> ({iprow.IP})<!-- ELSE --><a href="{iprow.U_WHOIS}">{iprow.IP}</a><!-- ENDIF --> [ {iprow.NUM_POSTS} {iprow.L_POST_S} ]</span></td>
- <td align="center"><!-- IF iprow.U_LOOKUP_IP --><span class="gen">[ <a href="{iprow.U_LOOKUP_IP}">{L_LOOKUP_IP}</a> ]</span><!-- ENDIF --></td>
- </tr>
- <!-- BEGINELSE -->
- <tr class="row1">
- <td colspan="2" align="center"><span class="gen">{L_NO_MATCHES_FOUND}</span></td>
- </tr>
- <!-- END iprow -->
- </table>
- <!-- ENDIF -->
-
-<!-- ENDIF -->
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_queue.html b/phpBB/styles/subsilver2/template/mcp_queue.html
deleted file mode 100644
index 7ca659b5da..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_queue.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form name="mcp" id="mcp" method="post" action="{S_MCP_ACTION}">
-
-<table width="100%" class="tablebg" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <th colspan="4" nowrap="nowrap">{L_DISPLAY_OPTIONS}</th>
-</tr>
-<tr>
- <td colspan="4" class="cat" align="center"><span class="gensmall">{L_DISPLAY_ITEMS}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<span class="gensmall">{L_FORUM}</span> <select name="f">{S_FORUM_OPTIONS}</select> &nbsp; <!-- IF TOPIC_ID --><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" />&nbsp; <b>{L_ONLY_TOPIC}</b> &nbsp; <!-- ENDIF --><input class="btnlite" type="submit" name="sort" value="{L_GO}" /></td>
-</tr>
-<tr>
- <th>&nbsp;<!-- IF S_TOPICS -->{L_TOPIC}<!-- ELSE -->{L_POST}<!-- ENDIF -->&nbsp;</th>
- <th>&nbsp;{L_AUTHOR}&nbsp;</th>
- <th>&nbsp;{L_POST_TIME}&nbsp;</th>
- <th width="5%">&nbsp;{L_SELECT}&nbsp;</th>
-</tr>
-<!-- BEGIN postrow -->
-
- <!-- IF postrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td style="padding: 4px;"><p class="topictitle">{postrow.ATTACH_ICON_IMG} <a href="{postrow.U_VIEWPOST}">{postrow.POST_SUBJECT}</a></p>
- <span class="gensmall"><!-- IF postrow.U_VIEWFORUM -->{L_FORUM}{L_COLON} <a href="{postrow.U_VIEWFORUM}">{postrow.FORUM_NAME}</a><!-- ELSE -->{postrow.FORUM_NAME}<!-- ENDIF --></span></td>
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap"><span class="gen">{postrow.POST_AUTHOR_FULL}</span><br />
- <span class="gensmall">[ <a href="{postrow.U_VIEW_DETAILS}">{L_VIEW_DETAILS}</a> ]</span></td>
- <td class="postdetails" style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap">{postrow.POST_TIME}</td>
- <td align="center">
- <!-- IF S_TOPICS -->
- <input type="checkbox" class="radio" name="topic_id_list[]" value="{postrow.TOPIC_ID}" />
- <!-- ELSE -->
- <input type="checkbox" class="radio" name="post_id_list[]" value="{postrow.POST_ID}" />
- <!-- ENDIF -->
- </td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="4" height="30" align="center" valign="middle">
- <span class="gen">
- <!-- IF S_RESTORE -->
- <!-- IF S_TOPICS -->{L_NO_TOPICS_DELETED}<!-- ELSE -->{L_NO_POSTS_DELETED}<!-- ENDIF -->
- <!-- ELSE -->
- <!-- IF S_TOPICS -->{L_NO_TOPICS_QUEUE}<!-- ELSE -->{L_NO_POSTS_QUEUE}<!-- ENDIF -->
- <!-- ENDIF -->
- </span>
- </td>
- </tr>
-<!-- END postrow -->
-<tr>
- <td class="cat" colspan="4" align="center">
- <!-- IF S_RESTORE -->
- <input class="btnlite" type="submit" name="action[delete]" value="{L_DELETE}" />&nbsp;&nbsp;
- <input class="btnmain" type="submit" name="action[restore]" value="{L_RESTORE}" />
- <!-- ELSE -->
- <input class="btnmain" type="submit" name="action[approve]" value="{L_APPROVE}" />&nbsp;&nbsp;
- <input class="btnlite" type="submit" name="action[disapprove]" value="{L_DISAPPROVE}" />
- <!-- ENDIF -->
- </td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<table width="100%" cellspacing="2" cellpadding="2" border="0" align="center">
-<tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">
- <b class="gensmall">
- <!-- IF S_TOPICS -->
- <a href="#" onclick="marklist('mcp', 'topic_id_list', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp', 'topic_id_list', false); return false;">{L_UNMARK_ALL}</a>
- <!-- ELSE -->
- <a href="#" onclick="marklist('mcp', 'post_id_list', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp', 'post_id_list', false); return false;">{L_UNMARK_ALL}</a>
- <!-- ENDIF -->
- </b>
- </td>
-</tr>
-</table>
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_reports.html b/phpBB/styles/subsilver2/template/mcp_reports.html
deleted file mode 100644
index 158f9c2603..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_reports.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form name="mcp" id="mcp" method="post" action="{S_MCP_ACTION}">
-
-<table width="100%" class="tablebg" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <th colspan="5" nowrap="nowrap">{L_DISPLAY_OPTIONS}</th>
-</tr>
-<tr>
- <td colspan="5" class="cat" align="center"><span class="gensmall">{L_DISPLAY_POSTS}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}<!-- IF not S_PM -->&nbsp;<span class="gensmall">{L_FORUM}</span> <select name="f">{S_FORUM_OPTIONS}</select> &nbsp; <!-- IF TOPIC_ID --><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" />&nbsp; <b>{L_ONLY_TOPIC}</b> &nbsp; <!-- ENDIF --><!-- ENDIF --><input class="btnlite" type="submit" name="sort" value="{L_GO}" /></td>
-</tr>
-<tr>
- <!-- IF S_PM -->
- <th>&nbsp;{L_PM}&nbsp;</th>
- <th>&nbsp;{L_TO} &amp; {L_BCC}&nbsp;</th>
- <!-- ELSE -->
- <th>&nbsp;{L_POST}&nbsp;</th>
- <th>&nbsp;{L_AUTHOR}&nbsp;</th>
- <!-- ENDIF -->
- <th>&nbsp;{L_REPORTER}&nbsp;</th>
- <th>&nbsp;{L_REPORT_TIME}&nbsp;</th>
- <th width="5%">&nbsp;{L_SELECT}&nbsp;</th>
-</tr>
-<!-- BEGIN postrow -->
-
- <!-- IF postrow.S_ROW_ is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <!-- IF S_PM -->
- <td style="padding: 4px;"><p class="topictitle">{postrow.ATTACH_ICON_IMG} <a href="{postrow.U_VIEW_DETAILS}">{postrow.PM_SUBJECT}</a></p>
- <span class="gensmall">{L_PM_FROM}{L_COLON} {postrow.PM_AUTHOR_FULL}</span></td>
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><span class="gen">{postrow.RECIPIENTS}</span><br />
- <span class="gensmall">{L_SENT_AT}{L_COLON} {postrow.PM_TIME}</span></td>
- <!-- ELSE -->
- <td style="padding: 4px;"><p class="topictitle">{postrow.ATTACH_ICON_IMG} <a href="{postrow.U_VIEWPOST}">{postrow.POST_SUBJECT}</a></p>
- <span class="gensmall"><!-- IF postrow.U_VIEWFORUM -->{L_FORUM}{L_COLON} <a href="{postrow.U_VIEWFORUM}">{postrow.FORUM_NAME}</a><!-- ELSE -->{postrow.FORUM_NAME}<!-- ENDIF --></span></td>
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap"><span class="gen">{postrow.POST_AUTHOR_FULL}</span><br />
- <span class="gensmall">{postrow.POST_TIME}</span></td>
- <!-- ENDIF -->
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap"><span class="gen">{postrow.REPORTER_FULL}</span></td>
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap"><span class="gen">{postrow.REPORT_TIME}</span><br />
- <span class="gensmall">[ <a href="{postrow.U_VIEW_DETAILS}">{L_VIEW_DETAILS}</a> ]</span></td>
- <td align="center"><input type="checkbox" class="radio" name="report_id_list[]" value="{postrow.REPORT_ID}" /></td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="5" height="30" align="center" valign="middle"><span class="gen">{L_NO_POSTS}</span></td>
- </tr>
-<!-- END postrow -->
-<tr>
- <td class="cat" colspan="5" align="center">
- <!-- IF S_CLOSED -->
- <input class="btnmain" type="submit" value="{L_DELETE_REPORTS}" name="action[delete]" />
- <!-- ELSE -->
- <input class="btnmain" type="submit" name="action[close]" value="{L_CLOSE_REPORTS}" /> &nbsp; <input class="btnlite" type="submit" value="{L_DELETE_REPORTS}" name="action[delete]" />
- <!-- ENDIF -->
- </td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<table width="100%" cellspacing="2" cellpadding="2" border="0" align="center">
-<tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="gensmall"><a href="#" onclick="marklist('mcp', '', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp', '', false); return false;">{L_UNMARK_ALL}</a></b></td>
-</tr>
-</table>
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_topic.html b/phpBB/styles/subsilver2/template/mcp_topic.html
deleted file mode 100644
index eee7fa95ea..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_topic.html
+++ /dev/null
@@ -1,158 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form name="mcp" id="mcp" method="post" action="{S_MCP_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<!-- IF S_CAN_SPLIT -->
- <tr>
- <th colspan="3" nowrap="nowrap">{L_SPLIT_TOPIC}</th>
- </tr>
- <tr>
- <td class="row2" colspan="3" align="center"><span class="gensmall">{L_SPLIT_TOPIC_EXPLAIN}</span></td>
- </tr>
- <!-- EVENT mcp_topic_options_before -->
- <tr>
- <td class="row1" nowrap="nowrap"><span class="gen">{L_SPLIT_SUBJECT}</span></td>
- <td class="row2" colspan="2"><input class="post" style="width: 350px" type="text" size="35" maxlength="124" name="subject" value="{SPLIT_SUBJECT}" /></td>
- </tr>
- <!-- EVENT mcp_topic_options_after -->
- <tr>
- <td class="row1" nowrap="nowrap"><span class="gen">{L_SPLIT_FORUM}</span></td>
- <td class="row2" colspan="2"><select name="to_forum_id">{S_FORUM_SELECT}</select></td>
- </tr>
-
- <!-- IF S_SHOW_TOPIC_ICONS -->
- <tr>
- <td class="row1"><span class="gen">{L_TOPIC_ICON}</span></td>
- <td class="row2" colspan="2">
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td><span class="genmed nowrap"><input type="radio" class="radio" name="icon" value="0"<!-- IF not S_TOPIC_ICON --> checked="checked"<!-- ENDIF --> />{L_NO_TOPIC_ICON}</span> <!-- BEGIN topic_icon --><span class="nowrap"><input type="radio" class="radio" name="icon" value="{topic_icon.ICON_ID}"<!-- IF topic_icon.S_CHECKED --> checked="checked"<!-- ENDIF --> /><img src="{topic_icon.ICON_IMG}" width="{topic_icon.ICON_WIDTH}" height="{topic_icon.ICON_HEIGHT}" alt="" title="" hspace="2" vspace="2" /></span> <!-- END topic_icon --></td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
-<!-- ENDIF -->
-
-<!-- IF S_CAN_MERGE -->
- <tr>
- <th colspan="3" nowrap="nowrap">{L_MERGE_POSTS}</th>
- </tr>
- <tr>
- <td class="row2" colspan="3" align="center"><span class="gensmall">{L_MERGE_TOPIC_EXPLAIN}</span></td>
- </tr>
- <tr>
- <td class="row1" nowrap="nowrap"><span class="gen">{L_MERGE_TOPIC_ID}</span></td>
- <td class="row2" colspan="2"><input class="post" type="number" min="0" max="9999999999" name="to_topic_id" value="{TO_TOPIC_ID}" /> <a href="{U_SELECT_TOPIC}">{L_SELECT_TOPIC}</a></td>
- </tr>
- <!-- IF TO_TOPIC_INFO -->
- <tr>
- <td class="row3" colspan="3" align="center"><b class="gen">{TO_TOPIC_INFO}</b></td>
- </tr>
- <!-- ENDIF -->
-<!-- ENDIF -->
-<tr>
- <th colspan="3" nowrap="nowrap">{L_DISPLAY_OPTIONS}</th>
-</tr>
-<tr>
- <td class="row1" nowrap="nowrap"><span class="gen">{L_POSTS_PER_PAGE}</span><br /><span class="gensmall">{L_POSTS_PER_PAGE_EXPLAIN}</span></td>
- <td class="row2" colspan="2"><input class="post" type="number" min="0" max="999999" name="posts_per_page" value="{POSTS_PER_PAGE}" /></td>
-</tr>
-<tr>
- <td class="cat" colspan="3" align="center"><span class="gensmall">{L_DISPLAY_POSTS}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" name="sort" value="{L_GO}" /></td>
-</tr>
-<tr>
- <th nowrap="nowrap" colspan="3">{L_TOPIC_REVIEW}{L_COLON} <!-- EVENT mcp_topic_topic_title_before -->{TOPIC_TITLE}<!-- EVENT mcp_topic_topic_title_after --></th>
-</tr>
-<tr>
- <td class="row3" colspan="3" align="center"><span class="gensmall">{RETURN_TOPIC}</span></td>
-</tr>
-<!-- BEGIN postrow -->
-
- <!-- IF postrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td align="center"><b class="postauthor">{postrow.POST_AUTHOR_FULL}</b></td>
- <td width="100%">
- <!-- EVENT mcp_topic_postrow_post_details_before -->
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr style="vertical-align: top;">
- <td class="gensmall" nowrap="nowrap">&nbsp;<b>{L_POST_SUBJECT}{L_COLON}</b>&nbsp;</td>
- <td class="gensmall" width="100%">{postrow.POST_SUBJECT}</td>
- </tr>
- </table>
- <!-- EVENT mcp_topic_postrow_post_details_after -->
- </td>
- <td width="5%" align="center"><a href="{postrow.U_POST_DETAILS}" class="imageset">{INFO_IMG}</a></td>
- </tr>
-
- <!-- IF postrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td width="100%" valign="top" colspan="2">
- <table width="100%" cellspacing="0" cellpadding="2" border="0">
- <tr>
- <td valign="top">
- <div class="postbody">{postrow.MESSAGE}</div>
- <!-- IF postrow.S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <!-- IF postrow.attachment.S_ROW_COUNT is even --><td class="row2"><!-- ELSE --><td class="row1"><!-- ENDIF -->{postrow.attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- </td>
- </tr>
- <tr>
- <td valign="bottom">
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr valign="middle">
- <td width="100%">
- <!-- IF postrow.S_POST_UNAPPROVED and postrow.U_MCP_APPROVE --><span class="postapprove">{UNAPPROVED_IMG} <a href="{postrow.U_MCP_APPROVE}">{L_POST_UNAPPROVED}</a></span><br /><!-- ENDIF -->
- <!-- IF postrow.S_POST_DELETED and postrow.U_MCP_APPROVE --><span class="postapprove">{DELETED_IMG} <a href="{postrow.U_MCP_APPROVE}">{L_POST_DELETED}</a></span><br /><!-- ENDIF -->
- <!-- IF postrow.S_POST_REPORTED and postrow.U_MCP_REPORT --><span class="postreported">{REPORTED_IMG} <a href="{postrow.U_MCP_REPORT}">{L_POST_REPORTED}</a></span><!-- ENDIF -->
- </td>
- <td width="10" nowrap="nowrap">{postrow.MINI_POST_IMG}</td>
- <td class="gensmall" nowrap="nowrap"><b>{L_POSTED}{L_COLON}</b> {postrow.POST_DATE}</td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td width="5%" align="center"><input type="checkbox" class="radio" name="post_id_list[]" value="{postrow.POST_ID}"<!-- IF postrow.S_CHECKED --> checked="checked"<!-- ENDIF --> /></td>
- </tr>
- <tr>
- <td class="row3" colspan="3" height="1"><img src="images/spacer.gif" width="1" height="1" alt="" /></td>
- </tr>
-<!-- END postrow -->
-<tr>
- <td class="cat" colspan="3" align="center"><select name="action"><option value="" selected="selected">{L_SELECT_ACTION}</option>
- <!-- IF S_CAN_APPROVE --><option value="approve">{L_APPROVE_POSTS}</option><!-- ENDIF -->
- <!-- IF S_CAN_LOCK --><option value="lock_post">{L_LOCK_POST_POSTS} [ {L_LOCK_POST_EXPLAIN} ]</option><option value="unlock_post">{L_UNLOCK_POST_POSTS}</option><!-- ENDIF -->
- <!-- IF S_CAN_DELETE --><option value="delete_post">{L_DELETE_POSTS}</option><!-- ENDIF -->
- <!-- IF S_CAN_RESTORE --><option value="restore">{L_RESTORE_POSTS}</option><!-- ENDIF -->
- <!-- IF S_CAN_MERGE --><option value="merge_posts"<!-- IF ACTION eq 'merge' --> selected="selected"<!-- ENDIF -->>{L_MERGE_POSTS}</option><!-- ENDIF -->
- <!-- IF S_CAN_SPLIT --><option value="split_all"<!-- IF ACTION eq 'split' --> selected="selected"<!-- ENDIF -->>{L_SPLIT_POSTS}</option><option value="split_beyond">{L_SPLIT_AFTER}</option><!-- ENDIF -->
- <!-- IF S_CAN_SYNC --><option value="resync">{L_RESYNC}</option><!-- ENDIF -->
- </select>&nbsp;<input class="btnmain" type="submit" name="mcp_topic_submit" value="{L_SUBMIT}" /></td>
-</tr>
-</table>
-{S_HIDDEN_FIELDS}
-{S_FORM_TOKEN}
-</form>
-
-<table width="100%" cellspacing="2" cellpadding="2" border="0" align="center">
-<tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="gensmall"><a href="#" onclick="marklist('mcp', '', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('mcp', '', false); return false;">{L_UNMARK_ALL}</a></b></td>
-</tr>
-</table>
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_warn_front.html b/phpBB/styles/subsilver2/template/mcp_warn_front.html
deleted file mode 100644
index f6daec9cc5..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_warn_front.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1" border="0" align="center">
-<tr>
- <th colspan="2"align="center">{L_SELECT_USER}</th>
-</tr>
-<tr>
- <td class="row1" width="40%"><b class="gen">{L_FIND_USERNAME}{L_COLON} </b><br /><span class="gensmall">[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</span></td>
- <td class="row2"><input type="text" class="post" name="username" size="20" /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center"><input type="submit" name="submituser" value="{L_SUBMIT}" class="btnmain" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <td class="row3" colspan="4" align="center"><b class="gen">{L_MOST_WARNINGS}</b></td>
-</tr>
-<tr>
- <th>&nbsp;{L_USERNAME}&nbsp;</th>
- <th>&nbsp;{L_WARNINGS}&nbsp;</th>
- <th>&nbsp;{L_LATEST_WARNING_TIME}&nbsp;</th>
- <th>&nbsp;</th>
-</tr>
-<!-- BEGIN highest -->
- <tr>
- <td class="row1" width="15%" valign="top"><span class="gen">{highest.USERNAME_FULL}</span></td>
- <td class="row2" width="15%" valign="top"><span class="gen">{highest.WARNINGS}</span></td>
- <td class="row1" width="15%" valign="top"><span class="gen">{highest.WARNING_TIME}</span></td>
- <td class="row2" width="15%" valign="top"><span class="gen"><a href="{highest.U_NOTES}">{L_VIEW_NOTES}</a></span></td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="4" align="center"><span class="gen">{L_NO_WARNINGS}</span></td>
- </tr>
-<!-- END highest -->
-</table>
-
-<br clear="all" /><br />
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <td class="row3" colspan="4" align="center"><b class="gen">{L_LATEST_WARNINGS}</b></td>
-</tr>
-<tr>
- <th>&nbsp;{L_USERNAME}&nbsp;</th>
- <th>&nbsp;{L_TIME}&nbsp;</th>
- <th>&nbsp;{L_TOTAL_WARNINGS}&nbsp;</th>
- <th>&nbsp;</th>
-</tr>
-<!-- BEGIN latest -->
- <tr>
- <td class="row1" width="15%" valign="top"><span class="gen">{latest.USERNAME_FULL}</span></td>
- <td class="row2" width="15%" valign="top"><span class="gen">{latest.WARNING_TIME}</span></td>
- <td class="row1" width="15%" valign="top"><span class="gen">{latest.WARNINGS}</span></td>
- <td class="row2" width="15%" valign="top"><span class="gen"><a href="{latest.U_NOTES}">{L_VIEW_NOTES}</a></span></td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="4" align="center"><span class="gen">{L_NO_WARNINGS}</span></td>
- </tr>
-<!-- END latest -->
-</table>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_warn_list.html b/phpBB/styles/subsilver2/template/mcp_warn_list.html
deleted file mode 100644
index 6e263b6403..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_warn_list.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <td class="row3" colspan="4" align="center"><b class="gen">{L_WARNED_USERS}</b></td>
-</tr>
-<tr>
- <th>&nbsp;{L_USERNAME}&nbsp;</th>
- <th>&nbsp;{L_WARNINGS}&nbsp;</th>
- <th>&nbsp;{L_LATEST_WARNING_TIME}&nbsp;</th>
- <th>&nbsp;</th>
-</tr>
-<!-- BEGIN user -->
- <tr>
- <td class="row1" width="15%" valign="top"><span class="gen">{user.USERNAME_FULL}</span></td>
- <td class="row2" width="15%" valign="top"><span class="gen">{user.WARNINGS}</span></td>
- <td class="row1" width="15%" valign="top"><span class="gen">{user.WARNING_TIME}</span></td>
- <td class="row2" width="15%" valign="top"><span class="gen"><a href="{user.U_NOTES}">{L_VIEW_NOTES}</a></span></td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="4" align="center"><span class="gen">{L_NO_WARNINGS}</span></td>
- </tr>
-<!-- END user -->
-<tr align="center">
- <td class="row3" colspan="4"><span class="gensmall">{L_DISPLAY_POSTS}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" value="{L_GO}" name="sort" /></td>
-</tr>
-</table>
-
-<table width="100%" cellspacing="0" cellpadding="0">
-<tr>
- <td class="pagination">{PAGE_NUMBER} [ {TOTAL_USERS} ]</td>
- <td align="{S_CONTENT_FLOW_END}"><span class="pagination"><!-- INCLUDE pagination.html --></span></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_warn_post.html b/phpBB/styles/subsilver2/template/mcp_warn_post.html
deleted file mode 100644
index 68715eff2d..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_warn_post.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th colspan="2" align="center">{L_POST}</th>
-</tr>
-<tr>
- <td class="row1" align="center">
- <table cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="center"><!-- IF USER_COLOR --><b style="color: #{USER_COLOR}"><!-- ELSE --><b><!-- ENDIF -->{USERNAME}</b></td>
- </tr>
- <!-- IF RANK_TITLE -->
- <tr>
- <td class="postdetails" align="center">{RANK_TITLE}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF RANK_IMG -->
- <tr>
- <td align="center">{RANK_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td align="center"><!-- IF AVATAR_IMG -->{AVATAR_IMG}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF --></td>
- </tr>
- </table>
- </td>
- <td class="row1">
- <span class="gen">{POST}</span>
- </td>
-</tr>
-</table>
-
-<br clear="all" /><br />
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<!-- EVENT mcp_warn_post_add_warning_field_before -->
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th align="center">{L_ADD_WARNING}</th>
-</tr>
-<tr>
- <td class="row3" align="center"><span class="genmed">{L_ADD_WARNING_EXPLAIN}</span></td>
-</tr>
-<tr>
- <td class="row1" align="center"><textarea name="warning" rows="10" cols="76">{L_WARNING_POST_DEFAULT}</textarea></td>
-</tr>
-<!-- IF S_CAN_NOTIFY -->
-<tr>
- <td class="row1" align="center"><input type="checkbox" class="radio" name="notify_user" checked="checked" /><span class="genmed">{L_NOTIFY_USER_WARN}</span></td>
-</tr>
-<!-- ENDIF -->
-<tr>
- <td class="cat" align="center"><input class="btnmain" type="submit" name="action[add_warning]" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" /></td>
-</tr>
-</table>
-
-<!-- EVENT mcp_warn_post_add_warning_field_after -->
-
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_warn_user.html b/phpBB/styles/subsilver2/template/mcp_warn_user.html
deleted file mode 100644
index 20b57c6837..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_warn_user.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th colspan="2" align="center">{USERNAME}</th>
-</tr>
-<tr>
- <td class="row1" align="center">
- <table cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="center"><b>{USERNAME_FULL}</b></td>
- </tr>
- <!-- IF RANK_TITLE -->
- <tr>
- <td class="postdetails" align="center">{RANK_TITLE}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF RANK_IMG -->
- <tr>
- <td align="center">{RANK_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td align="center"><!-- IF AVATAR_IMG -->{AVATAR_IMG}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF --></td>
- </tr>
- </table>
- </td>
- <td class="row1">
- <table width="100%" cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_JOINED}{L_COLON} </td>
- <td width="100%"><b class="gen">{JOINED}</b></td>
- </tr>
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_TOTAL_POSTS}{L_COLON} </td>
- <td><b class="gen">{POSTS}</b></td>
- </tr>
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_WARNINGS}{L_COLON} </td>
- <td><b class="gen">{WARNINGS}</b></td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
-
-<br clear="all" /><br />
-
-<form method="post" name="mcp" action="{U_POST_ACTION}">
-
-<!-- EVENT mcp_warn_user_add_warning_field_before -->
-
-<table width="100%" cellpadding="3" cellspacing="1" border="0" class="tablebg">
-<tr>
- <th align="center">{L_ADD_WARNING}</th>
-</tr>
-<tr>
- <td class="row3" align="center"><span class="genmed">{L_ADD_WARNING_EXPLAIN}</span></td>
-</tr>
-<tr>
- <td class="row1" align="center"><textarea name="warning" rows="10" cols="76"></textarea></td>
-</tr>
-<!-- IF S_CAN_NOTIFY -->
-<tr>
- <td class="row1" align="center"><input type="checkbox" class="radio" name="notify_user" checked="checked" /><span class="genmed">{L_NOTIFY_USER_WARN}</span></td>
-</tr>
-<!-- ENDIF -->
-<tr>
- <td class="cat" align="center"><input class="btnmain" type="submit" name="action[add_warning]" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" /></td>
-</tr>
-</table>
-
-<!-- EVENT mcp_warn_user_add_warning_field_after -->
-
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/mcp_whois.html b/phpBB/styles/subsilver2/template/mcp_whois.html
deleted file mode 100644
index 3e3b983059..0000000000
--- a/phpBB/styles/subsilver2/template/mcp_whois.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!-- INCLUDE mcp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th>{L_WHOIS}</th>
-</tr>
-<tr>
- <td class="row3" align="center"><span class="gensmall">{RETURN_POST}</span></td>
-</tr>
-<tr>
- <td class="row1"><pre>{WHOIS}</pre></td>
-</tr>
-</table>
-
-<!-- INCLUDE mcp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/memberlist_body.html b/phpBB/styles/subsilver2/template/memberlist_body.html
deleted file mode 100644
index 9044896bca..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_body.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!-- IF S_IN_SEARCH_POPUP -->
- <!-- INCLUDE simple_header.html -->
-<!-- ELSE -->
- <!-- INCLUDE overall_header.html -->
-<!-- ENDIF -->
-
-<!-- IF S_SEARCH_USER -->
- <!-- INCLUDE memberlist_search.html -->
-<!-- ENDIF -->
-
-<!-- IF S_SHOW_GROUP --><!-- INCLUDE memberlist_group.html --><!-- ENDIF -->
-
-<!-- IF not S_SHOW_GROUP -->
- <form method="post" name="charsearch" action="{S_MODE_ACTION}">
- <table width="100%" cellspacing="1">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}"><span class="genmed">{L_USERNAME_BEGINS_WITH}{L_COLON} </span>
- <select name="first_char" onchange="this.form.submit();">
- <!-- BEGIN first_char -->
- <option value="{first_char.VALUE}"<!-- IF first_char.S_SELECTED --> selected="selected"<!-- ENDIF -->>{first_char.DESC}</option>
- <!-- END first_char -->
- </select>&nbsp;<input type="submit" name="char" value="{L_DISPLAY}" class="btnlite" /></td>
- <!-- IF U_FIND_MEMBER and not S_SEARCH_USER -->
- <td class="genmed" align="{S_CONTENT_FLOW_END}"><a href="{U_FIND_MEMBER}">{L_FIND_USERNAME}</a></td>
- <!-- ELSEIF S_SEARCH_USER and U_HIDE_FIND_MEMBER and not S_IN_SEARCH_POPUP -->
- <td class="genmed" align="{S_CONTENT_FLOW_END}"><a href="{U_HIDE_FIND_MEMBER}">{L_HIDE_MEMBER_SEARCH}</a></td>
- <!-- ENDIF -->
- </tr>
- </table>
- {S_FORM_TOKEN}
- </form>
-<!-- ENDIF -->
-
-<!-- IF S_IN_SEARCH_POPUP -->
- <form method="post" name="results" action="{S_MODE_ACTION}" onsubmit="insert_marked(this.user);return false">
-<!-- ELSE -->
- <form method="post" action="{S_MODE_ACTION}">
-<!-- ENDIF -->
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th nowrap="nowrap">#</th>
- <th nowrap="nowrap" width="36%" align="{S_CONTENT_FLOW_BEGIN}"><a href="{U_SORT_USERNAME}">{L_USERNAME}</a></th>
- <th nowrap="nowrap" width="15%"><a href="{U_SORT_JOINED}">{L_JOINED}</a></th>
- <th nowrap="nowrap" width="10%"><a href="{U_SORT_POSTS}">{L_POSTS}</a></th>
- <th nowrap="nowrap" width="15%"><a href="{U_SORT_RANK}">{L_RANK}</a></th>
- <th nowrap="nowrap" width="11%"><a href="{U_SORT_EMAIL}">{L_EMAIL}</a></th>
- <!-- IF S_IN_SEARCH_POPUP and not S_SELECT_SINGLE --><th width="2%" nowrap="nowrap">{L_MARK}</th><!-- ENDIF -->
-</tr>
-<!-- BEGIN memberrow -->
-
- <!-- IF S_SHOW_GROUP -->
- <!-- IF memberrow.S_FIRST_ROW and memberrow.S_GROUP_LEADER -->
- <tr class="row3">
- <td colspan="7"><b class="gensmall">{L_GROUP_LEADER}</b></td>
- </tr>
- <!-- ELSEIF not memberrow.S_GROUP_LEADER and not $S_MEMBER_HEADER -->
- <tr class="row3">
- <td colspan="7"><b class="gensmall">{L_GROUP_MEMBERS}</b></td>
- </tr>
- <!-- DEFINE $S_MEMBER_HEADER = 1 -->
- <!-- ENDIF -->
- <!-- ENDIF -->
-
- <!-- IF memberrow.S_ROW_COUNT is even --><tr class="row2"><!-- ELSE --> <tr class="row1"><!-- ENDIF -->
-
- <td class="gen" align="center">&nbsp;{memberrow.ROW_NUMBER}&nbsp;</td>
- <td class="genmed" align="{S_CONTENT_FLOW_BEGIN}"><!-- EVENT memberlist_body_username_prepend -->{memberrow.USERNAME_FULL}<!-- IF memberrow.S_INACTIVE --> <em>({L_INACTIVE})</em><!-- ENDIF --><!-- EVENT memberlist_body_username_append --><!-- IF S_SELECT_SINGLE --> [&nbsp;<a href="#" onclick="insert_single('{memberrow.A_USERNAME}'); return false;">{L_SELECT}</a>&nbsp;]<!-- ENDIF --></td>
- <td class="genmed" align="center" nowrap="nowrap">&nbsp;{memberrow.JOINED}&nbsp;</td>
- <td class="gen" align="center">{memberrow.POSTS}</td>
- <td class="gen" align="center"><!-- EVENT memberlist_body_rank_prepend --><!-- IF memberrow.RANK_IMG -->{memberrow.RANK_IMG}<!-- ELSE -->{memberrow.RANK_TITLE}<!-- ENDIF --><!-- EVENT memberlist_body_rank_append --></td>
- <td class="gen" align="center">&nbsp;<!-- IF memberrow.U_EMAIL --><a href="{memberrow.U_EMAIL}" class="imageset">{EMAIL_IMG}</a><!-- ENDIF -->&nbsp;</td>
- <!-- IF memberrow.S_PROFILE_FIELD1 -->
- <!-- Use a construct like this to include admin defined profile fields. Replace FIELD1 with the name of your field. -->
- <td class="gen" align="center">&nbsp;{memberrow.PROFILE_FIELD1_VALUE}</td>
- <!-- ENDIF -->
- <!-- IF S_IN_SEARCH_POPUP and not S_SELECT_SINGLE --><td align="center"><input type="checkbox" class="radio" name="user" value="{memberrow.USERNAME}" /></td><!-- ENDIF -->
- </tr>
-
-<!-- BEGINELSE -->
-
- <tr>
- <td class="row1" colspan="<!-- IF S_IN_SEARCH_POPUP -->8<!-- ELSE -->7<!-- ENDIF -->" align="center">
- <span class="gen"><!-- IF S_SHOW_GROUP -->{L_NO_GROUP_MEMBERS}<!-- ELSE -->{L_NO_MEMBERS}<!-- ENDIF --></span>
- </td>
- </tr>
-
-<!-- END memberrow -->
-
-<tr>
- <td class="cat" colspan="<!-- IF S_IN_SEARCH_POPUP -->8<!-- ELSE -->7<!-- ENDIF -->" align="center"><!-- IF S_IN_SEARCH_POPUP and not S_SELECT_SINGLE --><input class="btnlite" type="submit" value="{L_SELECT_MARKED}" /><!-- ELSE --><span class="gensmall">{L_SELECT_SORT_METHOD}{L_COLON}</span>&nbsp;<select name="sk">{S_MODE_SELECT}</select>&nbsp; <span class="gensmall">{L_ORDER}</span>&nbsp;<select name="sd">{S_ORDER_SELECT}</select>&nbsp; <input type="submit" name="submit" value="{L_SUBMIT}" class="btnlite" /><!-- ENDIF --></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-
-</form>
-
-<table width="100%" cellspacing="0" cellpadding="0">
-<tr>
- <td class="pagination">{PAGE_NUMBER} [ {TOTAL_USERS} ]</td>
- <td align="{S_CONTENT_FLOW_END}"><!-- IF S_IN_SEARCH_POPUP and not S_SELECT_SINGLE --><b class="nav"><a href="#" onclick="marklist('results', 'user', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('results', 'user', false); return false;">{L_UNMARK_ALL}</a></b><br /><!-- ENDIF --><span class="pagination"><!-- INCLUDE pagination.html --></span></td>
-</tr>
-</table>
-
-
-
-<!-- IF S_IN_SEARCH_POPUP -->
- <!-- INCLUDE simple_footer.html -->
-<!-- ELSE -->
- <br clear="all" />
-
- <!-- INCLUDE breadcrumbs.html -->
-
- <br clear="all" />
-
- <div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
- <!-- INCLUDE overall_footer.html -->
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/memberlist_email.html b/phpBB/styles/subsilver2/template/memberlist_email.html
deleted file mode 100644
index 04f36b2244..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_email.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- EVENT memberlist_email_before -->
-
-<div id="pagecontent">
-
- <form action="{S_POST_ACTION}" method="post" name="postform">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <!-- IF S_CONTACT_ADMIN-->
- <th colspan="2">{L_CONTACT_ADMIN}</th>
- <!-- ELSEIF S_SEND_USER -->
- <th colspan="2">{L_SEND_EMAIL_USER}</th>
- <!-- ELSE -->
- <th colspan="2">{L_EMAIL_TOPIC}</th>
- <!-- ENDIF -->
- </tr>
- <!-- IF ERROR_MESSAGE -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="error">{ERROR_MESSAGE}</span></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF CONTACT_INFO -->
- <tr>
- <td class="row1" colspan="2">{CONTACT_INFO}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_SEND_USER -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_RECIPIENT}</b></td>
- <td class="row2" width="65%"><b class="genmed">{USERNAME}</b></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_SUBJECT}</b></td>
- <td class="row2"><input class="post" type="text" name="subject" size="50" tabindex="2" value="{SUBJECT}" /></td>
- </tr>
- <!-- ELSEIF S_CONTACT_ADMIN-->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_RECIPIENT}</b></td>
- <td class="row2" width="65%"><b class="genmed">{L_ADMINISTRATOR}</b></td>
- </tr>
- <!-- IF not S_IS_REGISTERED -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_SENDER_EMAIL_ADDRESS}</b></td>
- <td class="row2"><input class="post" type="text" name="email" size="50" maxlength="100" value="{EMAIL}" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_SENDER_NAME}</b></td>
- <td class="row2"><input class="post" type="text" name="name" size="50" value="{NAME}" /></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_SUBJECT}</b></td>
- <td class="row2"><input class="post" type="text" name="subject" size="50" tabindex="2" value="{SUBJECT}" /></td>
- </tr>
- <!-- ELSE -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_EMAIL_ADDRESS}</b></td>
- <td class="row2"><input class="post" type="email" name="email" size="50" maxlength="100" value="{EMAIL}" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_REAL_NAME}</b></td>
- <td class="row2"><input class="post" type="text" name="name" size="50" value="{NAME}" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_DEST_LANG}</b><br /><span class="gensmall">{L_DEST_LANG_EXPLAIN}</span></td>
- <td class="row2"><select name="lang">{S_LANG_OPTIONS}</select></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="row1" valign="top"><b class="genmed">{L_MESSAGE_BODY}</b><br /><span class="gensmall">{L_EMAIL_BODY_EXPLAIN}</span></td>
- <td class="row2"><textarea class="post" name="message" rows="15" cols="76" tabindex="3">{MESSAGE}</textarea></td>
- </tr>
- <!-- IF S_REGISTERED_USER -->
- <tr>
- <td class="row1" valign="top"><span class="gen"><b>{L_OPTIONS}</b></span></td>
- <td class="row2">
- <table cellspacing="0" cellpadding="1" border="0">
- <tr>
- <td><input type="checkbox" class="radio" name="cc_sender" value="1" checked="checked" /></td>
- <td class="gen">{L_CC_SENDER}</td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="cat" colspan="2" align="center"><input type="submit" tabindex="6" name="submit" class="btnmain" value="{L_SEND_EMAIL}" /></td>
- </tr>
- </table>
-
- {S_FORM_TOKEN}
-
- </form>
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div style="float: {S_CONTENT_FLOW_END};"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/memberlist_group.html b/phpBB/styles/subsilver2/template/memberlist_group.html
deleted file mode 100644
index ff8c96c120..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_group.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="3">{L_GROUP_INFORMATION}</th>
-</tr>
-<tr>
- <td class="row1" width="20%"><b class="genmed">{L_GROUP_NAME}{L_COLON}</b></td>
- <td class="row2"><b class="gen"<!-- IF GROUP_COLOR --> style="color:#{GROUP_COLOR}"<!-- ENDIF -->>{GROUP_NAME}</b> <!-- IF U_MANAGE --><a href="{U_MANAGE}">{L_MANAGE_GROUP}</a><!-- ENDIF --></td>
-<!-- IF AVATAR_IMG or RANK_IMG or GROUP_RANK or U_PM -->
- <td class="row1" width="33%" rowspan="2" align="center"><!-- IF AVATAR_IMG -->{AVATAR_IMG}<br /><!-- ENDIF --><!-- IF RANK_IMG -->{RANK_IMG}<!-- ENDIF --><!-- IF GROUP_RANK --><span class="gensmall">{GROUP_RANK}</span><br /><br /><!-- ENDIF --><!-- IF U_PM --><a href="{U_PM}" class="imageset">{PM_IMG}</a><!-- ENDIF --></td>
-<!-- ENDIF -->
-</tr>
-<tr>
- <td class="row1" width="20%"><b class="genmed">{L_GROUP_DESC}{L_COLON}</b></td>
- <td class="row2"><span class="gen">{GROUP_DESC}</span><p class="forumdesc">{GROUP_TYPE}</p></td>
-</tr>
-</table>
diff --git a/phpBB/styles/subsilver2/template/memberlist_im.html b/phpBB/styles/subsilver2/template/memberlist_im.html
deleted file mode 100644
index ecd9aca86f..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_im.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!-- INCLUDE simple_header.html -->
-
-<br clear="all" />
-
-<form method="post" action="{S_IM_ACTION}">
- <table class="tablebg" width="95%" cellspacing="1" cellpadding="4" border="0" align="center">
- <tr>
- <th colspan="2">{L_SEND_IM}</th>
- </tr>
- <!-- IF S_SENT_JABBER -->
- <tr>
- <td class="row1" colspan="2" align="center"><span class="gen">{L_IM_SENT_JABBER}</span></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_SEND_IM_EXPLAIN}</span></td>
- </tr>
- <tr>
- <td class="row1"><b class="genmed">{L_IM_RECIPIENT}{L_COLON} </b></td>
- <td class="row2"><span class="gen"><b>{USERNAME}</b><!-- IF S_NO_SEND_JABBER --> [ {IM_CONTACT} ]<!-- ENDIF --></span> <!-- IF PRESENCE_IMG -->{PRESENCE_IMG}<!-- ENDIF --></td>
- </tr>
-
- <!-- IF S_SEND_JABBER -->
- <tr>
- <td class="row1"><b class="genmed">{L_IM_MESSAGE}{L_COLON} </b></td>
- <td class="row2"><textarea class="post" name="message" rows="5" cols="45"></textarea></td>
- </tr>
- <tr>
- <td class="cat" colspan="2" align="center"><input class="btnmain" name="submit" type="submit" value="{L_IM_SEND}" /></td>
- </tr>
- <!-- ELSEIF S_NO_SEND_JABBER -->
- <tr>
- <td class="row1" colspan="2"><span class="genmed">{L_IM_NO_JABBER}</span></td>
- </tr>
- <!-- ENDIF -->
-
- </table>
-{S_FORM_TOKEN}
-</form>
-
-<a class="nav" href="#" onclick="window.close(); return false;">{L_CLOSE_WINDOW}</a>
-
-<!-- INCLUDE simple_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/memberlist_search.html b/phpBB/styles/subsilver2/template/memberlist_search.html
deleted file mode 100644
index 2096062607..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_search.html
+++ /dev/null
@@ -1,129 +0,0 @@
-<!-- You should retain this javascript in your own template! -->
-
-<!-- IF S_IN_SEARCH_POPUP -->
- <script type="text/javascript">
- // <![CDATA[
- function insert_user(user)
- {
- opener.document.forms['{S_FORM_NAME}'].{S_FIELD_NAME}.value = ( opener.document.forms['{S_FORM_NAME}'].{S_FIELD_NAME}.value.length && opener.document.forms['{S_FORM_NAME}'].{S_FIELD_NAME}.type == "textarea" ) ? opener.document.forms['{S_FORM_NAME}'].{S_FIELD_NAME}.value + "\n" + user : user;
- }
-
- function insert_marked(users)
- {
- if (typeof(users.length) == "undefined")
- {
- if (users.checked)
- {
- insert_user(users.value);
- }
- }
- else if (users.length > 0)
- {
- for (i = 0; i < users.length; i++)
- {
- if (users[i].checked)
- {
- insert_user(users[i].value);
- }
- }
- }
-
- self.close();
- }
-
- function insert_single(user)
- {
- opener.document.forms['{S_FORM_NAME}'].{S_FIELD_NAME}.value = user;
- self.close();
- }
-
- /**
- * Mark/unmark checklist
- * id = ID of parent container, name = name prefix, state = state [true/false]
- */
- function marklist(id, name, state)
- {
- var parent = document.getElementById(id) || document[id];
-
- if (!parent)
- {
- return;
- }
-
- var rb = parent.getElementsByTagName('input');
-
- for (var r = 0; r < rb.length; r++)
- {
- if (rb[r].name.substr(0, name.length) == name)
- {
- rb[r].checked = state;
- }
- }
- }
- // ]]>
- </script>
-<!-- ENDIF -->
-
-<form method="post" action="{S_MODE_ACTION}" name="search">
-
-<!-- EVENT memberlist_search_fields_before -->
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="4">{L_FIND_USERNAME}</th>
-</tr>
-<tr>
- <td class="row3" colspan="4"><span class="gensmall">{L_FIND_USERNAME_EXPLAIN}</span></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_USERNAME}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="text" name="username" value="{USERNAME}" /></td>
- <!-- IF S_EMAIL_SEARCH_ALLOWED -->
- <td class="row1"><b class="genmed">{L_EMAIL}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="email" name="email" value="{EMAIL}" /></td>
- <!-- ELSE -->
- <td colspan="2" class="row1">&nbsp;</td>
- <!-- ENDIF -->
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_JOINED}{L_COLON}</b></td>
- <td class="row2"><select name="joined_select">{S_JOINED_TIME_OPTIONS}</select> <input class="post" type="text" name="joined" value="{JOINED}" /></td>
- <td class="row1"><b class="genmed">{L_POSTS}{L_COLON}</b></td>
- <td class="row2"><select name="count_select">{S_COUNT_OPTIONS}</select> <input class="post" type="number" min="0" name="count" value="{COUNT}" /></td>
-</tr>
-<!-- IF S_VIEWONLINE -->
-<tr>
- <td class="row1"><b class="genmed">{L_LAST_ACTIVE}{L_COLON}</b></td>
- <td class="row2"><select name="active_select">{S_ACTIVE_TIME_OPTIONS}</select> <input class="post" type="text" name="active" value="{ACTIVE}" /></td>
- <!-- IF S_IP_SEARCH_ALLOWED -->
- <td class="row1"><b class="genmed">{L_POST_IP}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="text" name="ip" value="{IP}" /></td>
- <!-- ELSE -->
- <td colspan="2" class="row1">&nbsp;</td>
- <!-- ENDIF -->
-</tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1"><b class="genmed">{L_GROUP}{L_COLON}</b></td>
- <td class="row2" nowrap="nowrap"><select name="search_group_id">{S_GROUP_SELECT}</select></td>
- <!-- IF S_JABBER_ENABLED -->
- <td class="row1"><b class="genmed">{L_JABBER}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="text" name="jabber" value="{JABBER}" /></td>
- <!-- ELSE -->
- <td colspan="2" class="row1">&nbsp;</td>
- <!-- ENDIF -->
-</tr>
-<!-- EVENT memberlist_search_sorting_options_before -->
-<tr>
- <td class="row1"><b class="genmed">{L_SORT_BY}{L_COLON}</b></td>
- <td class="row2" nowrap="nowrap"><select name="sk">{S_SORT_OPTIONS}</select> <select name="sd">{S_ORDER_SELECT}</select>&nbsp;</td>
- <td colspan="2" class="row1">&nbsp;</td>
-</tr>
-<tr>
- <td class="cat" colspan="4" align="center"><input class="btnmain" type="submit" name="submit" value="{L_SEARCH}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" /></td>
-</tr>
-</table>
-<!-- EVENT memberlist_search_fields_after -->
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/memberlist_team.html b/phpBB/styles/subsilver2/template/memberlist_team.html
deleted file mode 100644
index 18995b6e50..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_team.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<form method="post" action="{S_MODE_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th nowrap="nowrap" width="20%">{L_USERNAME}</th>
- <!-- IF S_DISPLAY_MODERATOR_FORUMS --><th nowrap="nowrap" width="25%">{L_FORUMS}</th><!-- ENDIF -->
- <th nowrap="nowrap" width="20%">{L_PRIMARY_GROUP}</th>
- <th nowrap="nowrap" width="15%">{L_RANK}</th>
- <th nowrap="nowrap" width="11%">{L_SEND_MESSAGE}</th>
-</tr>
-<!-- BEGIN group -->
-<tr class="row3">
- <td colspan="5"><b class="gensmall"><!-- IF group.U_GROUP --><a href="{group.U_GROUP}">{group.GROUP_NAME}</a><!-- ELSE -->{group.GROUP_NAME}<!-- ENDIF --></b></td>
-</tr>
-<!-- BEGIN user -->
- <!-- IF group.user.S_ROW_COUNT is even --><tr class="row2"><!-- ELSE --><tr class="row1"><!-- ENDIF -->
-
- <td class="gen" align="center"><strong>{group.user.USERNAME_FULL}</strong><!-- IF group.user.S_INACTIVE --> <em>({L_INACTIVE})</em><!-- ENDIF --></td>
- <!-- IF S_DISPLAY_MODERATOR_FORUMS --><td class="gensmall" align="center"><!-- IF group.user.FORUM_OPTIONS --><select style="width: 100%;">{group.user.FORUMS}</select><!-- ELSEIF group.user.FORUMS -->{group.user.FORUMS}<!-- ELSE -->-<!-- ENDIF --></td><!-- ENDIF -->
- <td class="gensmall" align="center" nowrap="nowrap">&nbsp;
- <!-- IF group.user.U_GROUP -->
- <a<!-- IF group.user.GROUP_COLOR --> style="font-weight: bold; color:#{group.user.GROUP_COLOR}"<!-- ENDIF --> href="{group.user.U_GROUP}">{group.user.GROUP_NAME}</a>
- <!-- ELSE -->
- {group.user.GROUP_NAME}
- <!-- ENDIF -->
- &nbsp;</td>
- <td class="gen" align="center"><!-- IF group.user.RANK_IMG -->{group.user.RANK_IMG}<!-- ELSE -->{group.user.RANK_TITLE}<!-- ENDIF --></td>
- <td class="gen" align="center">&nbsp;<!-- IF group.user.U_PM --><a href="{group.user.U_PM}" class="imageset">{PM_IMG}</a><!-- ENDIF -->&nbsp;</td>
-</tr>
-<!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="5" align="center"><span class="gen">{L_NO_MEMBERS}</span></td>
- </tr>
-<!-- END user -->
-<!-- END group -->
-</table>
-
-</form>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div style="float: {S_CONTENT_FLOW_END};"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/memberlist_view.html b/phpBB/styles/subsilver2/template/memberlist_view.html
deleted file mode 100644
index 731d2c8bca..0000000000
--- a/phpBB/styles/subsilver2/template/memberlist_view.html
+++ /dev/null
@@ -1,207 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div id="pagecontent">
-
- <!-- EVENT memberlist_view_content_prepend -->
-
- <form method="post" action="{S_PROFILE_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="2" nowrap="nowrap">{L_VIEWING_PROFILE}</th>
- </tr>
- <tr>
- <td class="cat" width="40%" align="center"><h4>{L_USER_PRESENCE}</h4></td>
- <td class="cat" width="60%" align="center"><h4>{L_USER_FORUM}</h4></td>
- </tr>
- <tr>
- <td class="row1" align="center">
-
- <table cellspacing="1" cellpadding="2" border="0">
- <!-- IF S_USER_INACTIVE -->
- <tr>
- <td align="center"><b class="gen inactive">{L_USER_IS_INACTIVE}</b><br />{L_INACTIVE_REASON}{L_COLON} {USER_INACTIVE_REASON}<br /><br /></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td align="center"><!-- IF USER_COLOR --><b class="gen" style="color: {USER_COLOR}"><!-- ELSE --><b class="gen"><!-- ENDIF -->{USERNAME}</b><!-- IF U_USER_BAN --><span class="genmed"> [ <a href="{U_USER_BAN}">{L_USER_BAN}</a> ]</span><!-- ENDIF --><!-- IF U_USER_ADMIN --><span class="genmed"> [ <a href="{U_USER_ADMIN}">{L_USER_ADMIN}</a> ]</span><!-- ENDIF --></td>
- </tr>
- <!-- EVENT memberlist_view_rank_before -->
- <!-- IF RANK_TITLE -->
- <tr>
- <td class="postdetails" align="center">{RANK_TITLE}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF RANK_IMG -->
- <tr>
- <td align="center">{RANK_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT memberlist_view_rank_after -->
- <!-- IF AVATAR_IMG -->
- <tr>
- <td align="center">{AVATAR_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF ONLINE_IMG -->
- <tr>
- <td align="center">{ONLINE_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF U_SWITCH_PERMISSIONS -->
- <tr>
- <td class="genmed" align="center">[ <a href="{U_SWITCH_PERMISSIONS}">{L_USE_PERMISSIONS}</a> ]</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT memberlist_view_zebra_before -->
- <!-- IF S_USER_LOGGED_IN and S_ZEBRA -->
- <tr>
- <td class="genmed" align="center">[
- <!-- IF U_REMOVE_FRIEND -->
- <a href="{U_REMOVE_FRIEND}">{L_REMOVE_FRIEND}</a>
- <!-- ELSEIF U_REMOVE_FOE -->
- <a href="{U_REMOVE_FOE}">{L_REMOVE_FOE}</a>
- <!-- ELSE -->
- <!-- IF U_ADD_FRIEND --><a href="{U_ADD_FRIEND}">{L_ADD_FRIEND}</a><!-- ENDIF --><!-- IF U_ADD_FOE --><!-- IF U_ADD_FRIEND --> | <!-- ENDIF --><a href="{U_ADD_FOE}">{L_ADD_FOE}</a><!-- ENDIF -->
- <!-- ENDIF -->
- ]</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT memberlist_view_zebra_after -->
- </table>
- </td>
- <td class="row1">
- <table width="100%" cellspacing="1" cellpadding="2" border="0">
- <!-- EVENT memberlist_view_user_statistics_before -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_JOINED}{L_COLON} </td>
- <td width="100%"><b class="gen">{JOINED}</b></td>
- </tr>
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_LAST_ACTIVE}{L_COLON} </td>
- <td width="100%"><b class="gen">{LAST_ACTIVE}</b></td>
- </tr>
- <!-- IF S_WARNINGS -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_WARNINGS}{L_COLON} </td>
- <td width="100%"><b class="gen">{WARNINGS}</b><!-- IF U_NOTES or U_WARN --><br /><span class="genmed"> [ <!-- IF U_NOTES --><a href="{U_NOTES}">{L_VIEW_NOTES}</a><!-- ENDIF --> <!-- IF U_WARN --><!-- IF U_NOTES --> | <!-- ENDIF --><a href="{U_WARN}">{L_WARN_USER}</a><!-- ENDIF --> ]</span><!-- ENDIF --></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_TOTAL_POSTS}{L_COLON} </td>
- <td><b class="gen">{POSTS}</b><span class="genmed"><!-- IF POSTS_PCT --><br />[{POSTS_PCT} / {POSTS_DAY}]<!-- ENDIF -->
- <!-- IF POSTS_IN_QUEUE and U_MCP_QUEUE --><br />[<a href="{U_MCP_QUEUE}">{L_POSTS_IN_QUEUE}</a>]<!-- ELSEIF POSTS_IN_QUEUE --><br />[{L_POSTS_IN_QUEUE}]<!-- ENDIF -->
- <!-- IF S_DISPLAY_SEARCH --><br /><a href="{U_SEARCH_USER}">{L_SEARCH_USER_POSTS}</a><!-- ENDIF --></span></td>
- </tr>
- <!-- IF S_SHOW_ACTIVITY -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_ACTIVE_IN_FORUM}{L_COLON} </td>
- <td><!-- IF ACTIVE_FORUM != '' --><b><a class="gen" href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></b><br /><span class="genmed">[ {ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td>
- </tr>
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_ACTIVE_IN_TOPIC}{L_COLON} </td>
- <td><!-- IF ACTIVE_TOPIC != '' --><b><a class="gen" href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></b><br /><span class="genmed">[ {ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT memberlist_view_user_statistics_after -->
- </table>
- </td>
- </tr>
- <tr>
- <td class="cat" align="center"><h4>{L_CONTACT}</h4></td>
- <td class="cat" align="center"><h4>{L_ABOUT_USER}</h4></td>
- </tr>
- <!-- EVENT memberlist_view_contact_before -->
- <tr>
- <td class="row1">
- <table width="100%" cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_EMAIL_ADDRESS}{L_COLON} </td>
- <td width="100%"><!-- IF U_EMAIL --><a href="{U_EMAIL}" class="imageset">{EMAIL_IMG}</a><!-- ENDIF --></td>
- </tr>
- <!-- IF U_PM -->
- <tr>
- <td class="gen" nowrap="nowrap" align="{S_CONTENT_FLOW_END}">{L_PM}{L_COLON} </td>
- <td><a href="{U_PM}" class="imageset">{PM_IMG}</a></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_JABBER_ENABLED -->
- <tr>
- <td class="gen" nowrap="nowrap" align="{S_CONTENT_FLOW_END}">{L_JABBER}{L_COLON} </td>
- <td><!-- IF U_JABBER --><a href="{U_JABBER}" onclick="popup(this.href, 550, 320); return false" class="imageset">{JABBER_IMG}</a><!-- ELSEIF USER_JABBER -->{USER_JABBER_IMG}<!-- ENDIF --></td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT memberlist_view_contact_custom_fields_before -->
- <!-- BEGIN custom_fields -->
- <!-- IF custom_fields.S_PROFILE_CONTACT -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{custom_fields.PROFILE_FIELD_NAME}{L_COLON} </td>
- <!-- IF custom_fields.PROFILE_FIELD_CONTACT -->
- <td><a href="{custom_fields.PROFILE_FIELD_CONTACT}"><span class="imageset {custom_fields.PROFILE_FIELD_IDENT}-icon">{custom_fields.PROFILE_FIELD_DESC}</span></a></td>
- <!-- ELSE -->
- <td><b class="genmed">{custom_fields.PROFILE_FIELD_VALUE}</b></td>
- <!-- ENDIF -->
- </tr>
- <!-- ENDIF -->
- <!-- END custom_fields -->
- <!-- EVENT memberlist_view_contact_custom_fields_after -->
- </table>
- </td>
- <td class="row1">
- <table cellspacing="1" cellpadding="2" border="0">
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_USERGROUPS}{L_COLON} </td>
- <td><select name="g">{S_GROUP_OPTIONS}</select> <input class="btnlite" type="submit" name="submit" value="{L_GO}" /></td>
- </tr>
- <!-- IF AGE !== '' -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_AGE}{L_COLON} </td>
- <td><b class="genmed">{AGE}</b></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_PROFILE_FIELD1 -->
- <!-- Use a construct like this to include admin defined profile fields. Replace FIELD1 with the name of your field. -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{PROFILE_FIELD1_NAME}{L_COLON} </td>
- <td><b class="genmed">{PROFILE_FIELD1_VALUE}</b></td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT memberlist_view_non_contact_custom_fields_before -->
- <!-- BEGIN custom_fields -->
- <!-- IF not custom_fields.S_PROFILE_CONTACT -->
- <tr>
- <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{custom_fields.PROFILE_FIELD_NAME}{L_COLON} </td>
- <td><b class="genmed">{custom_fields.PROFILE_FIELD_VALUE}</b></td>
- </tr>
- <!-- ENDIF -->
- <!-- END custom_fields -->
- <!-- EVENT memberlist_view_non_contact_custom_fields_after -->
- </table>
- </td>
- </tr>
- <!-- EVENT memberlist_view_contact_after -->
- <!-- IF SIGNATURE -->
- <tr>
- <td class="cat" colspan="2" align="center"><h4>{L_SIGNATURE}</h4></td>
- </tr>
- <tr>
- <td class="row1" colspan="2"><div class="postbody" style="padding: 10px;">{SIGNATURE}</div></td>
- </tr>
- <!-- ENDIF -->
- </table>
-
- </form>
-
- <!-- EVENT memberlist_view_content_append -->
-
-</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div style="float: {S_CONTENT_FLOW_END};"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/message_body.html b/phpBB/styles/subsilver2/template/message_body.html
deleted file mode 100644
index b9b502a57f..0000000000
--- a/phpBB/styles/subsilver2/template/message_body.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th>{MESSAGE_TITLE}</th>
-</tr>
-<tr>
- <td class="row1" align="center"><br /><p class="gen">{MESSAGE_TEXT}</p><br /></td>
-</tr>
-</table>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html
deleted file mode 100644
index 176110c58d..0000000000
--- a/phpBB/styles/subsilver2/template/overall_footer.html
+++ /dev/null
@@ -1,29 +0,0 @@
- <!-- EVENT overall_footer_content_after -->
-
- <!-- IF not S_IS_BOT -->{RUN_CRON_TASK}<!-- ENDIF -->
-</div>
-
-<!-- EVENT overall_footer_page_body_after -->
-
-<div id="wrapfooter">
- <!-- IF U_ACP --><span class="gensmall">[ <a href="{U_ACP}">{L_ACP}</a> ]</span><br /><br /><!-- ENDIF -->
- <span class="copyright">
- <!-- EVENT overall_footer_copyright_prepend -->
- {CREDIT_LINE}
- <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF -->
- <!-- EVENT overall_footer_copyright_append -->
- <!-- IF DEBUG_OUTPUT --><br /><bdo dir="ltr">[ {DEBUG_OUTPUT} ]</bdo><!-- ENDIF --></span>
-</div>
-
-<script type="text/javascript" src="{T_JQUERY_LINK}"></script>
-<!-- IF S_ALLOW_CDN --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
-<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script>
-
-<!-- EVENT overall_footer_after -->
-
-{$SCRIPTS}
-
-<!-- EVENT overall_footer_body_after -->
-
-</body>
-</html>
diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html
deleted file mode 100644
index a4185785e3..0000000000
--- a/phpBB/styles/subsilver2/template/overall_header.html
+++ /dev/null
@@ -1,262 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8" />
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-{META}
-<title><!-- IF UNREAD_NOTIFICATIONS_COUNT -->({UNREAD_NOTIFICATIONS_COUNT}) <!-- ENDIF --><!-- IF not S_VIEWTOPIC and not S_VIEWFORUM -->{SITENAME} - <!-- ENDIF --><!-- IF S_IN_MCP -->{L_MCP} - <!-- ELSEIF S_IN_UCP -->{L_UCP} - <!-- ENDIF -->{PAGE_TITLE}<!-- IF S_VIEWTOPIC or S_VIEWFORUM --> - {SITENAME}<!-- ENDIF --></title>
-
-<!-- IF S_ENABLE_FEEDS -->
- <!-- IF S_ENABLE_FEEDS_OVERALL --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {SITENAME}" href="{U_FEED}" /><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_NEWS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_NEWS}" href="{U_FEED}?mode=news" /><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_FORUMS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_ALL_FORUMS}" href="{U_FEED}?mode=forums" /><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_TOPICS --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_TOPICS_NEW}" href="{U_FEED}?mode=topics" /><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_TOPICS_ACTIVE --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FEED_TOPICS_ACTIVE}" href="{U_FEED}?mode=topics_active" /><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_FORUM and S_FORUM_ID --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_FORUM} - {FORUM_NAME}" href="{U_FEED}?f={S_FORUM_ID}" /><!-- ENDIF -->
- <!-- IF S_ENABLE_FEEDS_TOPIC and S_TOPIC_ID --><link rel="alternate" type="application/atom+xml" title="{L_FEED} - {L_TOPIC} - {TOPIC_TITLE}" href="{U_FEED}?f={S_FORUM_ID}&amp;t={S_TOPIC_ID}" /><!-- ENDIF -->
- <!-- EVENT overall_header_feeds -->
-<!-- ENDIF -->
-
-<!-- IF U_CANONICAL -->
- <link rel="canonical" href="{U_CANONICAL}" />
-<!-- ENDIF -->
-
-<link rel="stylesheet" href="{T_STYLESHEET_LINK}" type="text/css" />
-<link rel="stylesheet" href="{T_STYLESHEET_LANG_LINK}" type="text/css" />
-
-<script type="text/javascript">
-// <![CDATA[
-
-function popup(url, width, height, name)
-{
- if (!name)
- {
- name = '_popup';
- }
-
- window.open(url.replace(/&amp;/g, '&'), name, 'height=' + height + ',resizable=yes,scrollbars=yes,width=' + width);
- return false;
-}
-
-function jumpto()
-{
- var page = prompt('{LA_JUMP_PAGE}{L_COLON}', '{CURRENT_PAGE}');
- var per_page = '{PER_PAGE}';
- var base_url = '{BASE_URL|e('js')}';
-
- if (page !== null && !isNaN(page) && page == Math.floor(page) && page > 0)
- {
- if (base_url.indexOf('?') == -1)
- {
- document.location.href = base_url + '?start=' + ((page - 1) * per_page);
- }
- else
- {
- document.location.href = base_url.replace(/&amp;/g, '&') + '&start=' + ((page - 1) * per_page);
- }
- }
-}
-
-/**
-* Find a member
-*/
-function find_username(url)
-{
- popup(url, 760, 570, '_usersearch');
- return false;
-}
-
-/**
-* Mark/unmark checklist
-* id = ID of parent container, name = name prefix, state = state [true/false]
-*/
-function marklist(id, name, state)
-{
- var parent = document.getElementById(id) || document[id];
-
- if (!parent)
- {
- return;
- }
-
- var rb = parent.getElementsByTagName('input');
-
- for (var r = 0; r < rb.length; r++)
- {
- if (rb[r].name.substr(0, name.length) == name)
- {
- rb[r].checked = state;
- }
- }
-}
-
-<!-- IF ._file -->
-
- /**
- * Play quicktime file by determining it's width/height
- * from the displayed rectangle area
- *
- * Only defined if there is a file block present.
- */
- function play_qt_file(obj)
- {
- var rectangle = obj.GetRectangle();
-
- if (rectangle)
- {
- rectangle = rectangle.split(',')
- var x1 = parseInt(rectangle[0]);
- var x2 = parseInt(rectangle[2]);
- var y1 = parseInt(rectangle[1]);
- var y2 = parseInt(rectangle[3]);
-
- var width = (x1 < 0) ? (x1 * -1) + x2 : x2 - x1;
- var height = (y1 < 0) ? (y1 * -1) + y2 : y2 - y1;
- }
- else
- {
- var width = 200;
- var height = 0;
- }
-
- obj.width = width;
- obj.height = height + 16;
-
- obj.SetControllerVisible(true);
-
- obj.Play();
- }
-<!-- ENDIF -->
-
-// ]]>
-</script>
-
-<!-- EVENT overall_header_head_append -->
-
-{$STYLESHEETS}
-
-<!-- EVENT overall_header_stylesheets_after -->
-
-</head>
-<body class="{S_CONTENT_DIRECTION} {BODY_CLASS}">
-
-<!-- EVENT overall_header_body_before -->
-
-<a name="top" class="anchor"></a>
-
-<div id="wrapheader">
-
- <div id="logodesc">
- <table width="100%" cellspacing="0">
- <tr>
- <td><a href="<!-- IF U_SITE_HOME -->{U_SITE_HOME}<!-- ELSE -->{U_INDEX}<!-- ENDIF -->" class="imageset">{SITE_LOGO_IMG}</a></td>
- <td width="100%" align="center"><h1>{SITENAME}</h1><span class="gen">{SITE_DESCRIPTION}</span></td>
- </tr>
- </table>
- </div>
- <!-- EVENT overall_header_navbar_before -->
- <div id="menubar">
- <table width="100%" cellspacing="0">
- <tr>
- <td class="genmed dropdown-container">
- <!-- IF S_NOTIFICATIONS_DISPLAY and not S_IS_BOT and S_USER_LOGGED_IN -->
- <a href="{U_VIEW_ALL_NOTIFICATIONS}" id="notification_list_button" class="dropdown-trigger">
- <img src="{T_THEME_PATH}/images/icon_mini_notification.gif" width="12" height="13" alt="*" />
- {L_NOTIFICATIONS} [<strong>{NOTIFICATIONS_COUNT}</strong>]
- </a>&nbsp;
- <div id="notification_list" class="notification_list dropdown">
- <div class="row1 header">
- {L_NOTIFICATIONS}
- <span class="header_settings"><a href="{U_NOTIFICATION_SETTINGS}">{L_SETTINGS}</a></span>
- </div>
-
- <div class="notification_scroll">
- <table class="tablebg" cellspacing="1">
- <!-- BEGIN notifications -->
- <tr class="row<!-- IF notifications.UNREAD -->2<!-- ELSE -->1<!-- ENDIF -->">
- <td width="50">
- <!-- IF notifications.AVATAR -->{notifications.AVATAR}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF -->
- </td>
- <td valign="top">
- <div class="notification_title">
- <!-- IF notifications.URL --><a href="<!-- IF notifications.UNREAD -->{notifications.U_MARK_READ}<!-- ELSE -->{notifications.URL}<!-- ENDIF -->"><!-- ENDIF -->
- {notifications.FORMATTED_TITLE}
- <!-- IF notifications.URL --></a><!-- ENDIF -->
-
- <!-- IF notifications.REFERENCE --><br /><span class="notification-reference">{notifications.REFERENCE}</span><!-- ENDIF -->
- <!-- IF notifications.FORUM --><br /><span class="notification-forum">{notifications.FORUM}</span><!-- ENDIF -->
- <!-- IF notifications.REASON --><br /><span class="notification-reason">{notifications.REASON}</span><!-- ENDIF -->
- <br /><span class="notification-time">{notifications.TIME}</span>
- <!-- IF not notifications.URL and notifications.UNREAD -->
- <br /><a href="{notifications.U_MARK_READ}">{L_MARK_READ}</a>
- <!-- ENDIF -->
- </div>
- </td>
- </tr>
- <!-- END notifications -->
- </table>
- </div>
-
- <div class="row1 footer">
- <a href="{U_VIEW_ALL_NOTIFICATIONS}"><span>{L_SEE_ALL}</span></a>
- </div>
- </div>
- <!-- ENDIF -->
- <!-- IF not S_IS_BOT -->
- <!-- IF S_USER_LOGGED_IN -->
- <!-- IF S_DISPLAY_PM --> &nbsp;<a href="{U_PRIVATEMSGS}"><img src="{T_THEME_PATH}/images/icon_mini_message.gif" width="12" height="13" alt="*" /> {L_PRIVATE_MESSAGES} [<strong>{PRIVATE_MESSAGE_COUNT}</strong>]</a><!-- ENDIF -->
- <!-- ELSEIF S_REGISTER_ENABLED and not (S_SHOW_COPPA or S_REGISTRATION) --> &nbsp;<a href="{U_REGISTER}"><img src="{T_THEME_PATH}/images/icon_mini_register.gif" width="12" height="13" alt="*" /> {L_REGISTER}</a>
- <!-- ENDIF -->
- <!-- ENDIF -->
- <!-- IF not S_IS_BOT --> &nbsp;<a href="{U_LOGIN_LOGOUT}"><img src="{T_THEME_PATH}/images/icon_mini_login.gif" width="12" height="13" alt="*" /> {L_LOGIN_LOGOUT}</a>&nbsp;<!-- ENDIF -->
- <!-- IF U_RESTORE_PERMISSIONS --> &nbsp;<a href="{U_RESTORE_PERMISSIONS}"><img src="{T_THEME_PATH}/images/icon_mini_login.gif" width="12" height="13" alt="*" /> {L_RESTORE_PERMISSIONS}</a><!-- ENDIF -->
- <!-- IF S_BOARD_DISABLED and S_USER_LOGGED_IN --> &nbsp;<span class="error">{L_BOARD_DISABLED}</span><!-- ENDIF -->
- </td>
- <td class="genmed" align="{S_CONTENT_FLOW_END}">
- <!-- EVENT overall_header_navigation_prepend -->
- <a href="{U_FAQ}" rel="help"><img src="{T_THEME_PATH}/images/icon_mini_faq.gif" width="12" height="13" alt="*" /> {L_FAQ}</a>
- <!-- IF S_DISPLAY_SEARCH -->&nbsp; &nbsp;<a href="{U_SEARCH}"><img src="{T_THEME_PATH}/images/icon_mini_search.gif" width="12" height="13" alt="*" /> {L_SEARCH}</a><!-- ENDIF -->
- <!-- IF not S_IS_BOT -->
- <!-- IF S_DISPLAY_MEMBERLIST -->&nbsp; &nbsp;<a href="{U_MEMBERLIST}"><img src="{T_THEME_PATH}/images/icon_mini_members.gif" width="12" height="13" alt="*" /> {L_MEMBERLIST}</a><!-- ENDIF -->
- <!-- IF S_USER_LOGGED_IN -->&nbsp; &nbsp;<a href="{U_PROFILE}"><img src="{T_THEME_PATH}/images/icon_mini_profile.gif" width="12" height="13" alt="*" /> {L_PROFILE}</a><!-- ENDIF -->
- <!-- ENDIF -->
- <!-- EVENT overall_header_navigation_append -->
- </td>
- </tr>
- </table>
- </div>
-
- <div id="datebar">
- <table width="100%" cellspacing="0">
- <tr>
- <td class="gensmall"><!-- IF S_USER_LOGGED_IN -->{LAST_VISIT_DATE}<!-- ENDIF --></td>
- <td class="gensmall" align="{S_CONTENT_FLOW_END}">{CURRENT_TIME}<br /></td>
- </tr>
- </table>
- </div>
-
-</div>
-
-<!-- EVENT overall_header_page_body_before -->
-
-<div id="wrapcentre">
-
- <!-- IF S_DISPLAY_SEARCH -->
- <p class="searchbar">
- <span style="float: {S_CONTENT_FLOW_BEGIN};"><a href="{U_SEARCH_UNANSWERED}">{L_SEARCH_UNANSWERED}</a> | <a href="{U_SEARCH_ACTIVE_TOPICS}">{L_SEARCH_ACTIVE_TOPICS}</a></span>
- <!-- IF S_USER_LOGGED_IN or S_LOAD_UNREADS -->
- <span style="float: {S_CONTENT_FLOW_END};"><!-- IF S_LOAD_UNREADS --><a href="{U_SEARCH_UNREAD}">{L_SEARCH_UNREAD}</a><!-- IF S_USER_LOGGED_IN --> | <!-- ENDIF --><!-- ENDIF --><!-- IF S_USER_LOGGED_IN --><a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a> | <a href="{U_SEARCH_SELF}">{L_SEARCH_SELF}</a><!-- ENDIF --></span>
- <!-- ENDIF -->
- </p>
- <!-- ENDIF -->
-
- <br style="clear: both;" />
-
- <!-- DEFINE $S_MICRODATA = 1 -->
- <!-- DEFINE $OVERALL_HEADER_BREADCRUMBS = 1 -->
- <!-- INCLUDE breadcrumbs.html -->
- <!-- UNDEFINE $OVERALL_HEADER_BREADCRUMBS -->
- <!-- DEFINE $S_MICRODATA = 0 -->
-
- <br />
- <!-- EVENT overall_header_content_before -->
diff --git a/phpBB/styles/subsilver2/template/pagination.html b/phpBB/styles/subsilver2/template/pagination.html
deleted file mode 100644
index b1c1d0e6c9..0000000000
--- a/phpBB/styles/subsilver2/template/pagination.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!-- IF .pagination -->
- <!-- IF BASE_URL --><b><a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE_CLICK}">{L_GOTO_PAGE}</a></b><!-- ENDIF -->
- <!-- BEGIN pagination -->
- <!-- IF pagination.S_IS_PREV --><a href="{pagination.PAGE_URL}">{L_PREVIOUS}</a>
- <!-- ELSEIF pagination.S_IS_CURRENT --><strong>{pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF pagination.S_IS_NEXT --><a href="{pagination.PAGE_URL}">{L_NEXT}</a>
- <!-- ELSE --><a href="{pagination.PAGE_URL}">{pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/posting_attach_body.html b/phpBB/styles/subsilver2/template/posting_attach_body.html
deleted file mode 100644
index 67b3aaf3ea..0000000000
--- a/phpBB/styles/subsilver2/template/posting_attach_body.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<tr>
- <th colspan="2">
- <script type="text/javascript">
- // <![CDATA[
- /**
- * Show upload progress bar
- */
- function popup_progress_bar()
- {
- close_waitscreen = 0;
- // no scrollbars
- popup('{UA_PROGRESS_BAR}', 400, 200, '_upload');
- }
- // ]]>
- </script>
-
- <!-- IF S_CLOSE_PROGRESS_WINDOW -->
- <script type="text/javascript">
- // <![CDATA[
- close_waitscreen = 1;
- // ]]>
- </script>
- <!-- ENDIF -->
-
- {L_ADD_ATTACHMENT}
- </th>
-</tr>
-<tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_ADD_ATTACHMENT_EXPLAIN}</span></td>
-</tr>
-
-<tr>
- <td class="row1"><b class="genmed">{L_FILENAME}</b></td>
- <td class="row2"><input type="file" name="fileupload" maxlength="{FILESIZE}" value="" class="btnfile" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_FILE_COMMENT}</b></td>
- <td class="row2">
- <table border="0" cellspacing="0" cellpadding="2">
- <tr>
- <td><textarea class="post" name="filecomment" rows="3" cols="35">{FILE_COMMENT}</textarea>&nbsp;</td>
- <td valign="top">
- <table border="0" cellspacing="4" cellpadding="0">
- <tr>
- <td><input class="btnlite" type="submit" style="width:150px" name="add_file" value="{L_ADD_FILE}" onclick="popup_progress_bar();" /></td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
-</tr>
-
-<!-- IF S_HAS_ATTACHMENTS -->
- <tr>
- <th colspan="2">{L_POSTED_ATTACHMENTS}</th>
- </tr>
-
- <!-- BEGIN attach_row -->
- <tr>
- <td class="row1"><b class="genmed">{L_FILENAME}</b></td>
- <td class="row2"><a class="genmed" href="{attach_row.U_VIEW_ATTACHMENT}" target="_blank">{attach_row.FILENAME}</a></td>
- </tr>
- <tr>
- <td class="row1"><b class="genmed">{L_FILE_COMMENT}</b></td>
- <td class="row2">{attach_row.S_HIDDEN}
- <table border="0" cellspacing="0" cellpadding="2">
- <tr>
- <td><textarea class="post" name="comment_list[{attach_row.ASSOC_INDEX}]" rows="3" cols="35" wrap="virtual">{attach_row.FILE_COMMENT}</textarea>&nbsp;</td>
- <td valign="top">
- <table border="0" cellspacing="4" cellpadding="0">
- <tr>
- <td><input class="btnlite" type="submit" style="width:150px" name="delete_file[{attach_row.ASSOC_INDEX}]" value="{L_DELETE_FILE}" /></td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- END attach_row -->
-
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/posting_body.html b/phpBB/styles/subsilver2/template/posting_body.html
deleted file mode 100644
index 95f817e838..0000000000
--- a/phpBB/styles/subsilver2/template/posting_body.html
+++ /dev/null
@@ -1,434 +0,0 @@
-<!-- IF S_PRIVMSGS -->
- <!-- INCLUDE ucp_header.html -->
-<!-- ELSE -->
- <!-- INCLUDE overall_header.html -->
-<!-- ENDIF -->
-
-<!-- IF S_FORUM_RULES -->
- <div class="forumrules<!-- IF U_FORUM_RULES --> rules-link<!-- ENDIF -->">
- <!-- IF U_FORUM_RULES -->
- <h3>{L_FORUM_RULES}</h3><br />
- <a href="{U_FORUM_RULES}"><b>{L_FORUM_RULES_LINK}</b></a>
- <!-- ELSE -->
- <h3>{L_FORUM_RULES}</h3><br />
- {FORUM_RULES}
- <!-- ENDIF -->
- </div>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<!-- IF not S_PRIVMSGS -->
- <div id="pageheader">
- <h2><!-- IF TOPIC_TITLE --><!-- EVENT posting_topic_title_before --><a class="titles" href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a><!-- EVENT posting_topic_title_after --><!-- ELSE --><a class="titles" href="{U_VIEW_FORUM}">{FORUM_NAME}</a><!-- ENDIF --></h2>
-
- <!-- IF MODERATORS -->
- <p class="moderators">{L_MODERATORS}{L_COLON} {MODERATORS}</p>
- <!-- ENDIF -->
- <!-- IF U_MCP or U_ACP -->
- <p class="linkmcp">[&nbsp;<!-- IF U_ACP --><a href="{U_ACP}">{L_ACP}</a><!-- IF U_MCP -->&nbsp;|&nbsp;<!-- ENDIF --><!-- ENDIF --><!-- IF U_MCP --><a href="{U_MCP}">{L_MCP}</a><!-- ENDIF -->&nbsp;]</p>
- <!-- ENDIF -->
- </div>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<!-- IF not S_SHOW_PM_BOX -->
- <form action="{S_POST_ACTION}" method="post" name="postform"{S_FORM_ENCTYPE}>
-<!-- ENDIF -->
-
-<!-- IF S_DRAFT_LOADED -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th align="center">{L_INFORMATION}</th>
- </tr>
- <tr>
- <td class="row1" align="center"><span class="gen"><!-- IF S_PRIVMSGS -->{L_DRAFT_LOADED_PM}<!-- ELSE -->{L_DRAFT_LOADED}<!-- ENDIF --></span></td>
- </tr>
- </table>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<!-- IF S_SHOW_DRAFTS -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="3" align="center">{L_LOAD_DRAFT}</th>
- </tr>
- <tr>
- <td class="row1" colspan="3" align="center"><span class="gen">{L_LOAD_DRAFT_EXPLAIN}</span></td>
- </tr>
- <tr>
- <th>{L_SAVE_DATE}</th>
- <th>{L_DRAFT_TITLE}</th>
- <th>{L_OPTIONS}</th>
- </tr>
- <!-- BEGIN draftrow -->
-
- <!-- IF draftrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td class="postdetails" style="padding: 4px;">{draftrow.DATE}</td>
- <td style="padding: 4px;"><b class="gen">{draftrow.DRAFT_SUBJECT}</b>
- <!-- IF draftrow.S_LINK_TOPIC --><br /><span class="gensmall">{L_TOPIC}{L_COLON} <a href="{draftrow.U_VIEW}">{draftrow.TITLE}</a></span>
- <!-- ELSEIF draftrow.S_LINK_FORUM --><br /><span class="gensmall">{L_FORUM}{L_COLON} <a href="{draftrow.U_VIEW}">{draftrow.TITLE}</a></span>
- <!-- ELSEIF draftrow.S_LINK_PM --><br /><span class="gensmall">{L_PRIVATE_MESSAGE}</span>
- <!-- ELSE --><br /><span class="gensmall">{L_NO_TOPIC_FORUM}</span><!-- ENDIF -->
- </td>
- <td style="padding: 4px;" align="center"><span class="gen"><a href="{draftrow.U_INSERT}">{L_LOAD_DRAFT}</a></span></td>
- </tr>
- <!-- END draftrow -->
- </table>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-
-<!-- IF S_POST_REVIEW --><!-- INCLUDE posting_review.html --><!-- ENDIF -->
-<!-- IF S_DISPLAY_PREVIEW --><!-- INCLUDE posting_preview.html --><!-- ENDIF -->
-
-
-<!-- IF not S_PRIVMSGS and S_UNGLOBALISE -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_MOVE}</th>
- </tr>
- <tr>
- <td class="spacer" colspan="2"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
- </tr>
- <tr>
- <td class="row2" align="center"><span class="gen">{L_UNGLOBALISE_EXPLAIN}<br /><br />{L_SELECT_DESTINATION_FORUM}&nbsp;&nbsp;</span><select name="to_forum_id">{S_FORUM_SELECT}</select><br /><br /><input class="btnmain" type="submit" name="post" value="{L_CONFIRM}" />&nbsp;&nbsp; <input class="btnlite" type="submit" name="cancel_unglobalise" value="{L_CANCEL}" /></td>
- </tr>
- </table>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2"><b>{L_POST_A}</b></th>
-</tr>
-
-<!-- IF ERROR -->
- <tr>
- <td class="row2" colspan="2" align="center"><span class="genmed error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_SHOW_TOPIC_ICONS or S_SHOW_PM_ICONS -->
- <tr>
- <td class="row1"><b class="genmed">{L_ICON}{L_COLON}</b></td>
- <td class="row2">
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td><input type="radio" class="radio" name="icon" value="0"{S_NO_ICON_CHECKED} tabindex="1" /><span class="genmed"><!-- IF S_SHOW_TOPIC_ICONS -->{L_NO_TOPIC_ICON}<!-- ELSE -->{L_NO_PM_ICON}<!-- ENDIF --></span> <!-- BEGIN topic_icon --><span style="white-space: nowrap;"><input type="radio" class="radio" name="icon" value="{topic_icon.ICON_ID}"{topic_icon.S_ICON_CHECKED} tabindex="1" /><img src="{topic_icon.ICON_IMG}" width="{topic_icon.ICON_WIDTH}" height="{topic_icon.ICON_HEIGHT}" alt="{topic_icon.ICON_NAME}" title="" hspace="2" vspace="2" /></span> <!-- END topic_icon --></td>
- </tr>
- </table>
- </td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF not S_PRIVMSGS and S_DISPLAY_USERNAME -->
- <tr>
- <td class="row1"><b class="genmed">{L_USERNAME}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="text" tabindex="1" name="username" size="25" value="{USERNAME}" /></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_PRIVMSGS -->
- <tr>
- <td class="row1"><b class="genmed">{L_TO}{L_COLON}</b></td>
- <td class="row2">
- {S_HIDDEN_ADDRESS_FIELD}
- <!-- BEGIN to_recipient -->
- <span style="display: block; float: {S_CONTENT_FLOW_BEGIN};" class="nowrap genmed"><strong>
- <!-- IF to_recipient.IS_GROUP --><a href="{to_recipient.U_VIEW}"><span class="sep">{to_recipient.NAME}</span></a><!-- ELSE -->{to_recipient.NAME_FULL}<!-- ENDIF --></strong>&nbsp;<!-- IF not S_EDIT_POST --><input class="post" type="submit" name="remove_{to_recipient.TYPE}[{to_recipient.UG_ID}]" value="{L_REMOVE}" />&nbsp;<!-- ENDIF -->
- </span>
- <!-- BEGINELSE -->
- <span class="genmed">{L_NO_TO_RECIPIENT}</span>
- <!-- END to_recipient -->
- </td>
- </tr>
- <!-- IF S_ALLOW_MASS_PM -->
- <tr>
- <td class="row1"><b class="genmed">{L_BCC}{L_COLON}</b></td>
- <td class="row2">
- <!-- BEGIN bcc_recipient -->
- <span class="genmed nowrap"><strong>
- <!-- IF bcc_recipient.IS_GROUP --><a href="{bcc_recipient.U_VIEW}"><span class="sep">{bcc_recipient.NAME}</span></a><!-- ELSE -->{bcc_recipient.NAME_FULL}<!-- ENDIF --></strong>&nbsp;<!-- IF not S_EDIT_POST --><input class="post" type="submit" name="remove_{bcc_recipient.TYPE}[{bcc_recipient.UG_ID}]" value="{L_REMOVE}" />&nbsp;<!-- ENDIF -->
- </span>
- <!-- BEGINELSE -->
- <span class="genmed">{L_NO_BCC_RECIPIENT}</span>
- <!-- END bcc_recipient -->
- </td>
- </tr>
- <!-- ENDIF -->
-<!-- ENDIF -->
-<!-- EVENT posting_editor_subject_before -->
-<tr>
- <td class="row1" width="22%"><b class="genmed">{L_SUBJECT}{L_COLON}</b></td>
- <td class="row2" width="78%">
- <!-- EVENT posting_editor_subject_prepend -->
- <input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}" />
- <!-- EVENT posting_editor_subject_append -->
- </td>
-</tr>
-<!-- EVENT posting_editor_subject_after -->
-<tr>
- <td class="row1" valign="top"><b class="genmed">{L_MESSAGE_BODY}{L_COLON}</b><br /><span class="gensmall">{L_MESSAGE_BODY_EXPLAIN}&nbsp;</span><br /><br />
- <!-- EVENT posting_editor_smilies_before -->
- <!-- IF S_SMILIES_ALLOWED -->
- <table width="100%" cellspacing="5" cellpadding="0" border="0" align="center">
- <tr>
- <td class="gensmall" align="center"><b>{L_SMILIES}</b></td>
- </tr>
- <tr>
- <td align="center">
- <!-- BEGIN smiley -->
- <a href="#" onclick="insert_text('{smiley.A_SMILEY_CODE}', true); return false;" style="line-height: 20px;"><img src="{smiley.SMILEY_IMG}" width="{smiley.SMILEY_WIDTH}" height="{smiley.SMILEY_HEIGHT}" alt="{smiley.SMILEY_CODE}" title="{smiley.SMILEY_DESC}" hspace="2" vspace="2" /></a>
- <!-- END smiley -->
- </td>
- </tr>
-
- <!-- IF S_SHOW_SMILEY_LINK -->
- <tr>
- <td align="center"><a class="nav" href="{U_MORE_SMILIES}" onclick="popup(this.href, 300, 350, '_phpbbsmilies'); return false;">{L_MORE_SMILIES}</a></td>
- </tr>
- <!-- ENDIF -->
-
- </table>
- <!-- ENDIF -->
- <!-- EVENT posting_editor_smilies_after -->
- </td>
- <td class="row2" valign="top">
- <script type="text/javascript">
- // <![CDATA[
- var form_name = 'postform';
- var text_name = 'message';
- // ]]>
- </script>
-
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <!-- INCLUDE posting_buttons.html -->
- <!-- EVENT posting_editor_message_before -->
- <tr>
- <td valign="top" style="width: 100%;"><textarea name="message" rows="15" cols="76" tabindex="3" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();" style="width: 700px; height: 270px; min-width: 98%; max-width: 98%;">{MESSAGE}</textarea></td>
- <!-- IF S_BBCODE_ALLOWED -->
- <td width="80" align="center" valign="top" id="color_palette_placeholder" data-orientation="v" data-width="11" data-height="10" data-bbcode="true">
- </td>
- <!-- ENDIF -->
- </tr>
- <!-- EVENT posting_editor_message_after -->
- </table>
- </td>
-</tr>
-
-<!-- IF S_INLINE_ATTACHMENT_OPTIONS -->
- <tr>
- <td class="row1"><b class="genmed">{L_ATTACHMENTS}{L_COLON}</b></td>
- <td class="row2"><select name="attachments">{S_INLINE_ATTACHMENT_OPTIONS}</select>&nbsp;<input type="button" class="btnbbcode" accesskey="a" value="{L_PLACE_INLINE}" name="attachinline" onclick="attach_form = document.forms[form_name].elements['attachments']; attachInline(attach_form.value, attach_form.options[attach_form.selectedIndex].text);" onmouseover="helpline('a')" onmouseout="helpline('tip')" />
- </td>
- </tr>
-<!-- ENDIF -->
-
-<tr>
- <td class="row1" valign="top"><b class="genmed">{L_OPTIONS}{L_COLON}</b><br />
- <table cellspacing="2" cellpadding="0" border="0">
- <tr>
- <td class="gensmall">{BBCODE_STATUS}</td>
- </tr>
- <!-- IF S_BBCODE_ALLOWED -->
- <tr>
- <td class="gensmall">{IMG_STATUS}</td>
- </tr>
- <tr>
- <td class="gensmall">{FLASH_STATUS}</td>
- </tr>
- <tr>
- <td class="gensmall">{URL_STATUS}</td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <td class="gensmall">{SMILIES_STATUS}</td>
- </tr>
- </table>
- </td>
- <!-- EVENT posting_editor_bbcode_status_after -->
- <td class="row2">
- <table cellpadding="1">
- <!-- EVENT posting_editor_options_prepend -->
- <!-- IF S_BBCODE_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="disable_bbcode"{S_BBCODE_CHECKED} /></td>
- <td class="gen">{L_DISABLE_BBCODE}</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF S_SMILIES_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="disable_smilies"{S_SMILIES_CHECKED} /></td>
- <td class="gen">{L_DISABLE_SMILIES}</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF S_LINKS_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="disable_magic_url"{S_MAGIC_URL_CHECKED} /></td>
- <td class="gen">{L_DISABLE_MAGIC_URL}</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF S_SIG_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="attach_sig"{S_SIGNATURE_CHECKED} /></td>
- <td class="gen">{L_ATTACH_SIG}</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF S_NOTIFY_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="notify"{S_NOTIFY_CHECKED} /></td>
- <td class="gen">{L_NOTIFY_REPLY}</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF not S_PRIVMSGS -->
- <!-- IF S_LOCK_TOPIC_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="lock_topic"{S_LOCK_TOPIC_CHECKED} /></td>
- <td class="gen">{L_LOCK_TOPIC}</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF S_LOCK_POST_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="lock_post"{S_LOCK_POST_CHECKED} /></td>
- <td class="gen">{L_LOCK_POST} [{L_LOCK_POST_EXPLAIN}]</td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF S_TYPE_TOGGLE -->
- <tr>
- <td></td>
- <td class="gen"><!-- IF S_EDIT_POST -->{L_CHANGE_TOPIC_TO}<!-- ELSE -->{L_POST_TOPIC_AS}<!-- ENDIF -->{L_COLON} <!-- BEGIN topic_type --><input type="radio" class="radio" name="topic_type" value="{topic_type.VALUE}"{topic_type.S_CHECKED} />{topic_type.L_TOPIC_TYPE}&nbsp;&nbsp;<!-- END topic_type --></td>
- </tr>
- <!-- ENDIF -->
- <!-- ENDIF -->
- </table>
- </td>
-</tr>
-
-<!-- IF S_SOFTDELETE_ALLOWED or S_DELETE_ALLOWED -->
- <tr>
- <td class="row1" valign="top"><b class="genmed">{L_DELETE_POST}{L_COLON}</b></td>
- <td class="row2">
- <table cellpadding="1">
- <tr>
- <td><input type="checkbox" class="radio" name="delete" /></td>
- <td class="gen">{L_DELETE_POST_WARN}</td>
- </tr>
- <!-- IF S_SOFTDELETE_ALLOWED and S_DELETE_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="delete_permanent" /></td>
- <td class="gen">{L_DELETE_POST_PERMANENTLY}</td>
- </tr>
- <!-- ENDIF -->
- </table>
- </td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_TOPIC_TYPE_ANNOUNCE or S_TOPIC_TYPE_STICKY -->
- <tr>
- <td class="row1"><b class="genmed">{L_STICK_TOPIC_FOR}{L_COLON}</b><br /><span class="gensmall">{L_STICKY_ANNOUNCE_TIME_LIMIT}</span></td>
- <td class="row2"><input class="post" type="number" min="0" max="999" name="topic_time_limit" value="{TOPIC_TIME_LIMIT}" />&nbsp;<b class="gen">{L_DAYS}</b> <span class="gensmall">{L_STICK_TOPIC_FOR_EXPLAIN}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_EDIT_REASON -->
- <tr>
- <td class="row1" valign="top"><b class="genmed">{L_EDIT_REASON}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="text" name="edit_reason" size="50" value="{EDIT_REASON}" /></td>
- </tr>
-<!-- ENDIF -->
-
- <!-- IF CAPTCHA_TEMPLATE and S_CONFIRM_CODE -->
- <!-- DEFINE $CAPTCHA_TAB_INDEX = 4 -->
- <!-- INCLUDE {CAPTCHA_TEMPLATE} -->
- <!-- ENDIF -->
-
-
-<!-- IF S_SHOW_ATTACH_BOX or S_SHOW_POLL_BOX -->
- <tr>
- <td class="cat" colspan="2" align="center">
- <input class="btnlite" type="submit" tabindex="5" name="preview" value="{L_PREVIEW}" />
- &nbsp; <input class="btnmain" type="submit" accesskey="s" tabindex="6" name="post" value="{L_SUBMIT}" />
- <!-- IF S_SAVE_ALLOWED -->&nbsp; <input class="btnlite" type="submit" accesskey="k" tabindex="7" name="save" value="{L_SAVE_DRAFT}" /><!-- ENDIF -->
- <!-- IF S_HAS_DRAFTS -->&nbsp; <input class="btnlite" type="submit" accesskey="d" tabindex="8" name="load" value="{L_LOAD_DRAFT}" /><!-- ENDIF -->
- &nbsp; <input class="btnlite" type="submit" accesskey="c" tabindex="9" name="cancel" value="{L_CANCEL}" />
- </td>
- </tr>
-
- <!-- IF S_SHOW_ATTACH_BOX --><!-- INCLUDE posting_attach_body.html --><!-- ENDIF -->
-
- <!-- IF S_SHOW_POLL_BOX -->
- <!-- INCLUDE posting_poll_body.html -->
- <!-- ELSEIF S_POLL_DELETE -->
- <tr>
- <td class="row1"><span class="genmed"><b>{L_POLL_DELETE}{L_COLON}</b></span></td>
- <td class="row2"><input type="checkbox" class="radio" name="poll_delete" /></td>
- </tr>
- <!-- ENDIF -->
-<!-- ENDIF -->
-
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}
- <input class="btnlite" type="submit" tabindex="10" name="preview" value="{L_PREVIEW}" />
- &nbsp; <input class="btnmain" type="submit" accesskey="s" tabindex="11" name="post" value="{L_SUBMIT}" />
- <!-- EVENT posting_editor_submit_buttons -->
- <!-- IF not S_SHOW_ATTACH_BOX and not S_SHOW_POLL_BOX -->
- <!-- IF S_SAVE_ALLOWED -->&nbsp; <input class="btnlite" type="submit" accesskey="k" tabindex="12" name="save" value="{L_SAVE_DRAFT}" /><!-- ENDIF -->
- <!-- IF S_HAS_DRAFTS -->&nbsp; <input class="btnlite" type="submit" accesskey="d" tabindex="13" name="load" value="{L_LOAD_DRAFT}" /><!-- ENDIF -->
- <!-- ENDIF -->
- &nbsp; <input class="btnlite" type="submit" accesskey="c" tabindex="14" name="cancel" value="{L_CANCEL}" />
- </td>
-</tr>
-</table>
-<!-- IF not S_PRIVMSGS -->
- {S_FORM_TOKEN}
- </form>
-<!-- ENDIF -->
-<br clear="all" />
-
-<!-- IF S_DISPLAY_REVIEW --><!-- INCLUDE posting_topic_review.html --><!-- ENDIF -->
-<!-- IF S_DISPLAY_HISTORY --><!-- INCLUDE ucp_pm_history.html --><!-- ENDIF -->
-
-<!-- IF S_PRIVMSGS -->
- <!-- INCLUDE ucp_footer.html -->
-<!-- ELSE -->
-
- <!-- INCLUDE breadcrumbs.html -->
-
-
- <!-- IF S_DISPLAY_ONLINE_LIST -->
- <br clear="all" />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat"><h4>{L_WHO_IS_ONLINE}</h4></td>
- </tr>
- <tr>
- <td class="row1"><span class="gensmall">{LOGGED_IN_USER_LIST}</span></td>
- </tr>
- </table>
- <!-- ENDIF -->
-
- <br clear="all" />
-
- <table width="100%" cellspacing="1">
- <tr>
- <td align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></td>
- </tr>
- </table>
-
- <!-- INCLUDE overall_footer.html -->
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/posting_buttons.html b/phpBB/styles/subsilver2/template/posting_buttons.html
deleted file mode 100644
index 516cd0922b..0000000000
--- a/phpBB/styles/subsilver2/template/posting_buttons.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<tr valign="middle" align="{S_CONTENT_FLOW_BEGIN}">
- <td colspan="2">
- <script type="text/javascript">
- // <![CDATA[
-
- // Define the bbCode tags
- var bbcode = new Array();
- var bbtags = new Array('[b]','[/b]','[i]','[/i]','[u]','[/u]','[quote]','[/quote]','[code]','[/code]','[list]','[/list]','[list=]','[/list]','[img]','[/img]','[url]','[/url]','[flash=]', '[/flash]','[size=]','[/size]'<!-- BEGIN custom_tags -->, {custom_tags.BBCODE_NAME}<!-- END custom_tags -->);
- var imageTag = false;
-
- // Helpline messages
- var help_line = {
- b: '{LA_BBCODE_B_HELP}',
- i: '{LA_BBCODE_I_HELP}',
- u: '{LA_BBCODE_U_HELP}',
- q: '{LA_BBCODE_Q_HELP}',
- c: '{LA_BBCODE_C_HELP}',
- l: '{LA_BBCODE_L_HELP}',
- e: '{LA_BBCODE_LISTITEM_HELP}',
- o: '{LA_BBCODE_O_HELP}',
- p: '{LA_BBCODE_P_HELP}',
- w: '{LA_BBCODE_W_HELP}',
- a: '{LA_BBCODE_A_HELP}',
- s: '{LA_BBCODE_S_HELP}',
- f: '{LA_BBCODE_F_HELP}',
- y: '{LA_BBCODE_Y_HELP}',
- d: '{LA_BBCODE_D_HELP}',
- tip: '{L_STYLES_TIP}'
- <!-- BEGIN custom_tags -->
- ,cb_{custom_tags.BBCODE_ID}: '{custom_tags.A_BBCODE_HELPLINE}'
- <!-- END custom_tags -->
- }
-
- // ]]>
- </script>
- <!-- INCLUDEJS {T_ASSETS_PATH}/javascript/editor.js -->
-
-<!-- IF S_BBCODE_ALLOWED -->
- <!-- EVENT posting_editor_buttons_before -->
- <div id="core-bbcode-buttons">
- <input type="button" class="btnbbcode bbcode-b" accesskey="b" name="addbbcode0" value=" B " style="font-weight:bold; width: 30px;" onclick="bbstyle(0)" onmouseover="helpline('b')" onmouseout="helpline('tip')" />
- <input type="button" class="btnbbcode bbcode-i" accesskey="i" name="addbbcode2" value=" i " style="font-style:italic; width: 30px;" onclick="bbstyle(2)" onmouseover="helpline('i')" onmouseout="helpline('tip')" />
- <input type="button" class="btnbbcode bbcode-u" accesskey="u" name="addbbcode4" value=" u " style="text-decoration: underline; width: 30px;" onclick="bbstyle(4)" onmouseover="helpline('u')" onmouseout="helpline('tip')" />
- <!-- IF S_BBCODE_QUOTE -->
- <input type="button" class="btnbbcode bbcode-quote" accesskey="q" name="addbbcode6" value="Quote" style="width: 50px" onclick="bbstyle(6)" onmouseover="helpline('q')" onmouseout="helpline('tip')" />
- <!-- ENDIF -->
- <input type="button" class="btnbbcode bbcode-code" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" onmouseover="helpline('c')" onmouseout="helpline('tip')" />
- <input type="button" class="btnbbcode bbcode-list" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" onmouseover="helpline('l')" onmouseout="helpline('tip')" />
- <input type="button" class="btnbbcode bbcode-list-" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" onmouseover="helpline('o')" onmouseout="helpline('tip')" />
- <input type="button" class="btnbbcode bbcode-asterisk" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('e')" onmouseout="helpline('tip')" />
- <!-- IF S_BBCODE_IMG -->
- <input type="button" class="btnbbcode bbcode-img" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" onmouseover="helpline('p')" onmouseout="helpline('tip')" />
- <!-- ENDIF -->
- <!-- IF S_LINKS_ALLOWED -->
- <input type="button" class="btnbbcode bbcode-url" accesskey="w" name="addbbcode16" value="URL" style="text-decoration: underline; width: 40px" onclick="bbstyle(16)" onmouseover="helpline('w')" onmouseout="helpline('tip')" />
- <!-- ENDIF -->
- <!-- IF S_BBCODE_FLASH -->
- <input type="button" class="btnbbcode bbcode-flash" accesskey="d" name="addbbcode18" value="Flash" onclick="bbstyle(18)" onmouseover="helpline('d')" onmouseout="helpline('tip')" />
- <!-- ENDIF -->
- <span class="genmed nowrap">{L_FONT_SIZE}{L_COLON} <select class="gensmall bbcode-size" name="addbbcode20" onchange="bbfontstyle('[size=' + this.form.addbbcode20.options[this.form.addbbcode20.selectedIndex].value + ']', '[/size]');this.form.addbbcode20.selectedIndex = 2;" onmouseover="helpline('f')" onmouseout="helpline('tip')">
- <option value="50">{L_FONT_TINY}</option>
- <option value="85">{L_FONT_SMALL}</option>
- <option value="100" selected="selected">{L_FONT_NORMAL}</option>
- <!-- IF not MAX_FONT_SIZE or MAX_FONT_SIZE >= 150 -->
- <option value="150">{L_FONT_LARGE}</option>
- <!-- IF not MAX_FONT_SIZE or MAX_FONT_SIZE >= 200 -->
- <option value="200">{L_FONT_HUGE}</option>
- <!-- ENDIF -->
- <!-- ENDIF -->
- </select></span>
- </div>
- <!-- EVENT posting_editor_buttons_custom_tags_before -->
- <!-- IF .custom_tags -->
- <div id="custom-bbcode-buttons">
- <!-- BEGIN custom_tags -->
- <input type="button" class="btnbbcode bbcode-{custom_tags.BBCODE_TAG_CLEAN}" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})"<!-- IF custom_tags.BBCODE_HELPLINE !== '' --> onmouseover="helpline('cb_{custom_tags.BBCODE_ID}')" onmouseout="helpline('tip')"<!-- ENDIF --> />
- <!-- END custom_tags -->
- </div>
- <!-- ENDIF -->
- <!-- EVENT posting_editor_buttons_after -->
-<!-- ENDIF -->
- </td>
-</tr>
-<!-- IF S_BBCODE_ALLOWED -->
-<tr>
- <td<!-- IF $S_SIGNATURE or S_EDIT_DRAFT --> colspan="2"<!-- ENDIF -->><input type="text" readonly="readonly" name="helpbox" style="width:100%" class="helpline" value="{L_STYLES_TIP}" /></td>
- <!-- IF not $S_SIGNATURE and not S_EDIT_DRAFT -->
- <td class="genmed" align="center">{L_FONT_COLOR}</td>
- <!-- ENDIF -->
-</tr>
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/posting_poll_body.html b/phpBB/styles/subsilver2/template/posting_poll_body.html
deleted file mode 100644
index a18f319c1c..0000000000
--- a/phpBB/styles/subsilver2/template/posting_poll_body.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-<tr>
- <th colspan="2">{L_ADD_POLL}</th>
-</tr>
-<tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_ADD_POLL_EXPLAIN}</span></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_POLL_QUESTION}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="text" name="poll_title" size="50" maxlength="255" value="{POLL_TITLE}" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_POLL_OPTIONS}{L_COLON}</b><br /><span class="gensmall">{L_POLL_OPTIONS_EXPLAIN}</span></td>
- <td class="row2"><textarea style="width:450px" name="poll_option_text" rows="5" cols="35">{POLL_OPTIONS}</textarea></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_POLL_MAX_OPTIONS}{L_COLON}</b><br /><span class="gensmall">{L_POLL_MAX_OPTIONS_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="number" min="0" max="999" name="poll_max_options" value="{POLL_MAX_OPTIONS}" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_POLL_FOR}{L_COLON}</b></td>
- <td class="row2"><input class="post" type="number" min="0" max="999" name="poll_length" value="{POLL_LENGTH}" />&nbsp;<b class="gen">{L_DAYS}</b> <span class="gensmall">{L_POLL_FOR_EXPLAIN}</span></td>
-</tr>
-<!-- IF S_POLL_VOTE_CHANGE -->
- <tr>
- <td class="row1"><b class="genmed">{L_POLL_VOTE_CHANGE}{L_COLON}</b><br /><span class="gensmall">{L_POLL_VOTE_CHANGE_EXPLAIN}</span></td>
- <td class="row2"><input type="checkbox" class="radio" name="poll_vote_change"{VOTE_CHANGE_CHECKED} /></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT posting_poll_body_options_after -->
-
-<!-- IF S_POLL_DELETE -->
- <tr>
- <td class="row1"><b class="genmed">{L_POLL_DELETE}{L_COLON}</b></td>
- <td class="row2"><input type="checkbox" class="radio" name="poll_delete"<!-- IF S_POLL_DELETE_CHECKED --> checked="checked"<!-- ENDIF --> /></td>
- </tr>
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/posting_preview.html b/phpBB/styles/subsilver2/template/posting_preview.html
deleted file mode 100644
index c451e4c871..0000000000
--- a/phpBB/styles/subsilver2/template/posting_preview.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th>{L_PREVIEW}</th>
-</tr>
-<tr>
- <td class="row1">{MINI_POST_IMG}<span class="postdetails">{L_POSTED}{L_COLON} {POST_DATE} &nbsp;&nbsp;&nbsp; {L_POST_SUBJECT}{L_COLON} {PREVIEW_SUBJECT}</span></td>
-</tr>
-<!-- IF S_HAS_POLL_OPTIONS -->
- <tr>
- <td class="row2" colspan="2" align="center"><br clear="all" />
- <table cellspacing="0" cellpadding="4" border="0" align="center">
- <tr>
- <td align="center"><span class="gen"><b>{POLL_QUESTION}</b></span><br /><span class="gensmall">{L_POLL_LENGTH}</span></td>
- </tr>
- <tr>
- <td align="center">
- <table cellspacing="0" cellpadding="2" border="0">
- <!-- BEGIN poll_option -->
- <tr>
- <td>
- <!-- IF S_IS_MULTI_CHOICE -->
- <input type="checkbox" class="radio" name="vote_id" value="" />
- <!-- ELSE -->
- <input type="radio" class="radio" name="vote_id" value="" />
- <!-- ENDIF -->
- </td>
- <td><span class="gen">{poll_option.POLL_OPTION_CAPTION}</span></td>
- </tr>
- <!-- END poll_option -->
- </table>
- </td>
- </tr>
- <tr>
- <td align="center"><span class="gensmall">{L_MAX_VOTES}</span></td>
- </tr>
- </table>
- </td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT posting_preview_poll_after -->
-<tr>
- <td class="row1">
- <table width="100%" border="0" cellspacing="0" cellpadding="0">
- <tr>
- <td><div class="postbody">{PREVIEW_MESSAGE}</div>
- <!-- IF .attachment -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <td class="row2">{attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
- <!-- IF PREVIEW_SIGNATURE --><span class="postbody"><br />_________________<br />{PREVIEW_SIGNATURE}</span><!-- ENDIF --></td>
- </tr>
- </table>
- </td>
-</tr>
-<tr>
- <td class="spacer"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
-</tr>
-</table>
-
-<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/posting_progress_bar.html b/phpBB/styles/subsilver2/template/posting_progress_bar.html
deleted file mode 100644
index f9decc506b..0000000000
--- a/phpBB/styles/subsilver2/template/posting_progress_bar.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!-- INCLUDE simple_header.html -->
-<script type="text/javascript">
-// <![CDATA[
- /**
- * Close upload popup
- */
- function close_popup()
- {
- if (opener != null)
- {
- if (opener.close_waitscreen != null)
- {
- if (opener.close_waitscreen == 1)
- {
- opener.close_waitscreen = 0;
- self.close();
- return 0;
- }
- }
- }
- setTimeout("close_popup()", 1000);
- return 0;
- }
-// ]]>
-</script>
-
-<table width="100%" border="0" cellspacing="0" cellpadding="10">
-<tr>
- <td>
- <table width="100%" border="0" cellspacing="1" cellpadding="4">
- <tr>
- <td valign="top" class="row1" align="center"><br /><span class="genmed">{L_UPLOAD_IN_PROGRESS}</span><br /><br /><div style="align:center">{PROGRESS_BAR}</div><br /><br /><span class="genmed"><a href="#" onclick="window.close(); return false;">{L_CLOSE_WINDOW}</a></span><br /><br /></td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
-
-<script type="text/javascript">
-// <![CDATA[
- close_popup();
-// ]]>
-</script>
-<!-- INCLUDE simple_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/posting_review.html b/phpBB/styles/subsilver2/template/posting_review.html
deleted file mode 100644
index c118499564..0000000000
--- a/phpBB/styles/subsilver2/template/posting_review.html
+++ /dev/null
@@ -1,99 +0,0 @@
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th align="center">{L_POST_REVIEW}</th>
-</tr>
-<tr>
- <td class="row1" align="center"><span class="gen">{L_POST_REVIEW_EXPLAIN}</span></td>
-</tr>
-<tr>
- <td class="spacer"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
-</tr>
-<tr>
- <td class="row1">
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th width="22%">{L_AUTHOR}</th>
- <th>{L_MESSAGE}</th>
- </tr>
- <!-- BEGIN post_review_row -->
-
- <!-- IF post_review_row.S_ROW_COUNT is even --> <tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <!-- IF post_review_row.S_IGNORE_POST -->
- <td colspan="2">{post_review_row.L_IGNORE_POST}</td>
- <!-- ELSE -->
-
- <td rowspan="2" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><a id="pr{post_review_row.POST_ID}" class="anchor"></a>
- <table width="150" cellspacing="0" cellpadding="4" border="0">
- <tr>
- <td align="center"><b class="postauthor">{post_review_row.POST_AUTHOR_FULL}</b></td>
- </tr>
- </table>
- </td>
- <td width="100%">
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td>&nbsp;</td>
- <td class="gensmall" valign="middle" nowrap="nowrap"><b>{L_POST_SUBJECT}{L_COLON}</b>&nbsp;</td>
- <td class="gensmall" width="100%" valign="middle">{post_review_row.POST_SUBJECT}</td>
- <td>&nbsp;</td>
- </tr>
- </table>
- </td>
- </tr>
-
- <!-- IF post_review_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td valign="top">
- <table width="100%" cellspacing="0">
- <tr>
- <td valign="top">
- <table width="100%" cellspacing="0" cellpadding="2">
- <tr>
- <td><div class="postbody">{post_review_row.MESSAGE}</div>
-
- <!-- IF post_review_row.S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <!-- IF post_review_row.attachment.S_ROW_COUNT is even --><td class="row2"><!-- ELSE --><td class="row1"><!-- ENDIF -->{post_review_row.attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td>
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr valign="middle">
- <td width="100%">&nbsp;</td>
- <td width="10" nowrap="nowrap"><!-- IF S_IS_BOT -->{post_review_row.MINI_POST_IMG}<!-- ELSE --><a href="{post_review_row.U_MINI_POST}" class="imageset">{post_review_row.MINI_POST_IMG}</a><!-- ENDIF --></td>
- <td class="gensmall" nowrap="nowrap"><b>{L_POSTED}{L_COLON}</b> {post_review_row.POST_DATE}</td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <!-- ENDIF -->
- </tr>
- <tr>
- <td class="spacer" colspan="2" height="1"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
- </tr>
- <!-- END post_review_row -->
- </table>
- </td>
-</tr>
-</table>
-
-<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/posting_smilies.html b/phpBB/styles/subsilver2/template/posting_smilies.html
deleted file mode 100644
index 7087414fa8..0000000000
--- a/phpBB/styles/subsilver2/template/posting_smilies.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!-- INCLUDE simple_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
- var form_name = opener.form_name;
- var text_name = opener.text_name;
-// ]]>
-</script>
-<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/editor.js -->
-
-<table width="100%" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <td>
- <table class="tablebg" width="95%" cellspacing="1" cellpadding="4" border="0">
- <tr>
- <th>{L_SMILIES}</th>
- </tr>
- <tr>
- <td class="row1" align="center" valign="middle"><!-- BEGIN smiley --> <a href="#" onclick="initInsertions(); insert_text('{smiley.A_SMILEY_CODE}', true, true); return false;"><img src="{smiley.SMILEY_IMG}" width="{smiley.SMILEY_WIDTH}" height="{smiley.SMILEY_HEIGHT}" alt="{smiley.SMILEY_CODE}" title="{smiley.SMILEY_DESC}" hspace="2" vspace="2" /></a> <!-- END smiley --><br />
- <!-- IF .pagination -->
- <b><a href="#" onclick="jumpto(); return false;" title="{L_JUMP_TO_PAGE_CLICK}">{L_GOTO_PAGE}</a>
- <!-- BEGIN pagination -->
- <!-- IF pagination.S_IS_PREV --><a href="{pagination.PAGE_URL}">{pagination.PAGE_NUMBER}</a>
- <!-- ELSEIF pagination.S_IS_CURRENT --><strong>{pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF pagination.S_IS_NEXT --><a href="{pagination.PAGE_URL}">{pagination.PAGE_NUMBER}</a>
- <!-- ELSE --><a href="{pagination.PAGE_URL}">{pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
- <br />
- <!-- ENDIF -->
- <a class="nav" href="#" onclick="window.close(); return false;">{L_CLOSE_WINDOW}</a></td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
-<!-- INCLUDE simple_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/posting_topic_review.html b/phpBB/styles/subsilver2/template/posting_topic_review.html
deleted file mode 100644
index 46329e19fa..0000000000
--- a/phpBB/styles/subsilver2/template/posting_topic_review.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<script type="text/javascript">
-// <![CDATA[
- bbcodeEnabled = {S_BBCODE_ALLOWED};
-// ]]>
-</script>
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th align="center">{L_TOPIC_REVIEW} - {TOPIC_TITLE}</th>
-</tr>
-<tr>
- <td class="row1"><div style="overflow: auto; width: 100%; height: 300px;">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th width="22%">{L_AUTHOR}</th>
- <th>{L_MESSAGE}</th>
- </tr>
- <!-- BEGIN topic_review_row -->
-
- <!-- EVENT posting_topic_review_row_post_details_before -->
- <!-- IF topic_review_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <!-- IF topic_review_row.S_IGNORE_POST -->
- <td colspan="2">{topic_review_row.L_IGNORE_POST}</td>
- <!-- ELSE -->
- <td rowspan="2" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><a id="pr{topic_review_row.POST_ID}" class="anchor"></a>
- <table width="150" cellspacing="0">
- <tr>
- <td align="center"><b class="postauthor"<!-- IF topic_review_row.POST_AUTHOR_COLOUR --> style="color: {topic_review_row.POST_AUTHOR_COLOUR}"<!-- ENDIF -->>{topic_review_row.POST_AUTHOR}</b></td>
- </tr>
- </table>
- </td>
- <td width="100%">
- <table width="100%" cellspacing="0">
- <tr>
- <td>&nbsp;</td>
- <td class="gensmall" valign="middle" nowrap="nowrap"><b>{L_POST_SUBJECT}{L_COLON}</b>&nbsp;</td>
- <td class="gensmall" width="100%" valign="middle">{topic_review_row.POST_SUBJECT}</td>
- <td valign="top" nowrap="nowrap">&nbsp;<!-- IF topic_review_row.POSTER_QUOTE and topic_review_row.DECODED_MESSAGE --><a href="#" onclick="addquote({topic_review_row.POST_ID},'{topic_review_row.POSTER_QUOTE}', '{LA_WROTE}'); return false;" class="imageset">{QUOTE_IMG}</a><!-- ENDIF --></td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- EVENT posting_topic_review_row_post_details_after -->
-
- <!-- IF topic_review_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td valign="top">
- <table width="100%" cellspacing="0">
- <tr>
- <td valign="top">
- <table width="100%" cellspacing="0" cellpadding="2">
- <tr>
- <td>
- <!-- IF topic_review_row.POST_ID == REPORTED_POST_ID -->
- <table width="100%" cellspacing="0">
- <tr>
- <span class="postreported">{REPORTED_IMG}</span>
- </tr>
- </table>
- <!-- ENDIF -->
- <div class="postbody">{topic_review_row.MESSAGE}</div>
-
- <!-- IF topic_review_row.S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <!-- IF topic_review_row.attachment.S_ROW_COUNT is even --><td class="row2"><!-- ELSE --><td class="row1"><!-- ENDIF -->{topic_review_row.attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- <!-- IF topic_review_row.POSTER_QUOTE and topic_review_row.DECODED_MESSAGE -->
- <div id="message_{topic_review_row.POST_ID}" style="display: none;">{topic_review_row.DECODED_MESSAGE}</div>
- <!-- ENDIF -->
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td>
- <table width="100%" cellspacing="0">
- <tr valign="middle">
- <td width="100%" align="{S_CONTENT_FLOW_BEGIN}"><span class="gensmall"><!-- IF topic_review_row.U_MCP_DETAILS -->[ <a href="{topic_review_row.U_MCP_DETAILS}">{L_POST_DETAILS}</a> ]<!-- ENDIF --></span></td>
- <td width="10" nowrap="nowrap"><!-- IF S_IS_BOT -->{topic_review_row.MINI_POST_IMG}<!-- ELSE --><a href="{topic_review_row.U_MINI_POST}" class="imageset">{topic_review_row.MINI_POST_IMG}</a><!-- ENDIF --></td>
- <td class="gensmall" nowrap="nowrap"><b>{L_POSTED}{L_COLON}</b> {topic_review_row.POST_DATE}</td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <!-- ENDIF -->
- </tr>
- <tr>
- <td class="spacer" colspan="2"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
- </tr>
- <!-- END topic_review_row -->
- </table>
- </div></td>
-</tr>
-</table>
-
-<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/profilefields/bool.html b/phpBB/styles/subsilver2/template/profilefields/bool.html
deleted file mode 100644
index f57bd4e4da..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/bool.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- BEGIN bool -->
- <!-- IF bool.FIELD_LENGTH eq 1 -->
- <!-- BEGIN options --><input type="radio" class="radio" name="{bool.FIELD_IDENT}" value="{bool.options.OPTION_ID}"{bool.options.CHECKED} /><span class="genmed">{bool.options.VALUE}</span>&nbsp; &nbsp;<!-- END options -->
- <!-- ELSE -->
- <input type="checkbox" class="radio" name="{bool.FIELD_IDENT}" value="1"<!-- IF bool.FIELD_VALUE eq 1 --> checked="checked"<!-- ENDIF --> />
- <!-- ENDIF -->
-<!-- END bool -->
diff --git a/phpBB/styles/subsilver2/template/profilefields/date.html b/phpBB/styles/subsilver2/template/profilefields/date.html
deleted file mode 100644
index e2da2463a5..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/date.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!-- BEGIN date -->
-<span class="genmed">{L_DAY}{L_COLON}</span> <select name="{date.FIELD_IDENT}_day">{date.S_DAY_OPTIONS}</select>
-<span class="genmed">{L_MONTH}{L_COLON}</span> <select name="{date.FIELD_IDENT}_month">{date.S_MONTH_OPTIONS}</select>
-<span class="genmed">{L_YEAR}{L_COLON}</span> <select name="{date.FIELD_IDENT}_year">{date.S_YEAR_OPTIONS}</select>
-<!-- END date -->
diff --git a/phpBB/styles/subsilver2/template/profilefields/dropdown.html b/phpBB/styles/subsilver2/template/profilefields/dropdown.html
deleted file mode 100644
index 16242da895..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/dropdown.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!-- BEGIN dropdown -->
-<select name="{dropdown.FIELD_IDENT}">
- <!-- BEGIN options --><option value="{dropdown.options.OPTION_ID}"{dropdown.options.SELECTED}>{dropdown.options.VALUE}</option><!-- END options -->
-</select>
-<!-- END dropdown -->
diff --git a/phpBB/styles/subsilver2/template/profilefields/int.html b/phpBB/styles/subsilver2/template/profilefields/int.html
deleted file mode 100644
index 067921e320..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/int.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!-- BEGIN int -->
- <input type="number" min="{int.FIELD_MINLEN}" max="{int.FIELD_MAXLEN}" class="post" name="{int.FIELD_IDENT}" size="{int.FIELD_LENGTH}" value="{int.FIELD_VALUE}" />
-<!-- END int -->
diff --git a/phpBB/styles/subsilver2/template/profilefields/string.html b/phpBB/styles/subsilver2/template/profilefields/string.html
deleted file mode 100644
index 5a98562e2a..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/string.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!-- BEGIN string -->
- <input type="text" class="post" name="{string.FIELD_IDENT}" size="{string.FIELD_LENGTH}" maxlength="{string.FIELD_MAXLEN}" value="{string.FIELD_VALUE}" />
-<!-- END string -->
diff --git a/phpBB/styles/subsilver2/template/profilefields/text.html b/phpBB/styles/subsilver2/template/profilefields/text.html
deleted file mode 100644
index df2474ad3e..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/text.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!-- BEGIN text -->
-<textarea name="{text.FIELD_IDENT}" rows="{text.FIELD_ROWS}" cols="{text.FIELD_COLS}">{text.FIELD_VALUE}</textarea>
-<!-- END text -->
diff --git a/phpBB/styles/subsilver2/template/profilefields/url.html b/phpBB/styles/subsilver2/template/profilefields/url.html
deleted file mode 100644
index 42805aa98d..0000000000
--- a/phpBB/styles/subsilver2/template/profilefields/url.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!-- BEGIN url -->
- <input type="url" class="post" name="{url.FIELD_IDENT}" id="{url.FIELD_IDENT}" size="{url.FIELD_LENGTH}" maxlength="{url.FIELD_MAXLEN}" value="{url.FIELD_VALUE}" />
-<!-- END url -->
diff --git a/phpBB/styles/subsilver2/template/quickreply_editor.html b/phpBB/styles/subsilver2/template/quickreply_editor.html
deleted file mode 100644
index a7614e841f..0000000000
--- a/phpBB/styles/subsilver2/template/quickreply_editor.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<form method="post" action="{U_QR_ACTION}">
-<!-- EVENT quickreply_editor_panel_before -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th align="center" colspan="2">{L_QUICKREPLY}</th>
- </tr>
- <!-- EVENT quickreply_editor_subject_before -->
- <tr>
- <td class="row1" width="22%"><b class="genmed">{L_SUBJECT}{L_COLON}</b></td>
- <td class="row2" width="78%"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="124" tabindex="2" value="{SUBJECT}" /></td>
- </tr>
- <!-- EVENT quickreply_editor_message_before -->
- <tr>
- <td class="row1" width="22%"><b class="genmed">{L_MESSAGE}{L_COLON}</b></td>
- <td class="row2" valign="top" align="left" width="78%"><textarea name="message" rows="7" cols="76" tabindex="3" style="width: 700px; height: 130px; min-width: 98%; max-width: 98%;"></textarea> </td>
- </tr>
- <!-- EVENT quickreply_editor_message_after -->
- <tr>
- <td class="cat" colspan="2" align="center">
- <input class="btnlite" type="submit" accesskey="f" tabindex="6" name="preview" value="{L_FULL_EDITOR}" />&nbsp;
- <input class="btnmain" type="submit" accesskey="s" tabindex="7" name="post" value="{L_SUBMIT}" />
-
- {S_FORM_TOKEN}
- {QR_HIDDEN_FIELDS}
- </td>
- </tr>
- </table>
-<!-- EVENT quickreply_editor_panel_after -->
-</form>
-<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/report_body.html b/phpBB/styles/subsilver2/template/report_body.html
deleted file mode 100644
index 906a957ef4..0000000000
--- a/phpBB/styles/subsilver2/template/report_body.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<form method="post" id="report" action="{S_REPORT_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2"><!-- IF S_REPORT_POST -->{L_REPORT_POST}<!-- ELSE -->{L_REPORT_MESSAGE}<!-- ENDIF --></th>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="genmed error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row3" colspan="2"><span class="gensmall"><!-- IF S_REPORT_POST -->{L_REPORT_POST_EXPLAIN}<!-- ELSE -->{L_REPORT_MESSAGE_EXPLAIN}<!-- ENDIF --></span></td>
-</tr>
-<tr>
- <td class="row1" width="22%"><b class="gen">{L_REASON}{L_COLON}</b></td>
- <td class="row2" width="78%"><select name="reason_id">
- <!-- BEGIN reason --><option value="{reason.ID}"<!-- IF reason.S_SELECTED --> selected="selected"<!-- ENDIF -->>{reason.TITLE} &raquo; {reason.DESCRIPTION}</option><!-- END reason -->
- </select></td>
-</tr>
-<!-- IF S_CAN_NOTIFY -->
- <tr>
- <td class="row1"><span class="gen"><b>{L_REPORT_NOTIFY}{L_COLON}</b></span><br /><span class="gensmall">{L_REPORT_NOTIFY_EXPLAIN}</span></td>
- <td class="row2"><span class="gen"><input type="radio" class="radio" name="notify" value="1"<!-- IF S_NOTIFY --> checked="checked"<!-- ENDIF --> />&nbsp; {L_YES} &nbsp;<input type="radio" class="radio" name="notify" value="0"<!-- IF not S_NOTIFY --> checked="checked"<!-- ENDIF --> />&nbsp; {L_NO}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1" valign="top"><span class="gen"><b>{L_MORE_INFO}{L_COLON}</b></span><br /><span class="gensmall">{L_CAN_LEAVE_BLANK}</span></td>
- <td class="row2"><textarea class="post" name="report_text" rows="10" cols="50">{REPORT_TEXT}</textarea></td>
-</tr>
-<!-- IF CAPTCHA_TEMPLATE -->
- <!-- INCLUDE {CAPTCHA_TEMPLATE} -->
-<!-- ENDIF -->
-<tr>
- <td class="cat" colspan="2" align="center"><input type="submit" name="submit" class="btnmain" value="{L_SUBMIT}" />&nbsp;<input type="submit" name="cancel" class="btnlite" value="{L_CANCEL}" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<div style="float: {S_CONTENT_FLOW_END};"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/search_body.html b/phpBB/styles/subsilver2/template/search_body.html
deleted file mode 100644
index 84ea73ea30..0000000000
--- a/phpBB/styles/subsilver2/template/search_body.html
+++ /dev/null
@@ -1,110 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div id="pagecontent">
-
- <!-- EVENT search_body_form_before -->
- <form method="get" action="{S_SEARCH_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <!-- DEFINE $COLSPAN = 4 -->
- <!-- EVENT search_body_search_query_before -->
- <tr>
- <th colspan="{$COLSPAN}">{L_SEARCH_QUERY}</th>
- </tr>
- <!-- EVENT search_body_search_query_prepend -->
- <tr>
- <td class="row1" colspan="2" width="50%"><b class="genmed">{L_SEARCH_KEYWORDS}{L_COLON} </b><br /><span class="gensmall">{L_SEARCH_KEYWORDS_EXPLAIN}</span></td>
- <td class="row2" colspan="2" valign="top"><input type="text" style="width: 300px" class="post" name="keywords" size="30" /><br /><input type="radio" class="radio" name="terms" value="all" checked="checked" /> <span class="genmed">{L_SEARCH_ALL_TERMS}</span><br /><input type="radio" class="radio" name="terms" value="any" /> <span class="genmed">{L_SEARCH_ANY_TERMS}</span></td>
- </tr>
- <tr>
- <td class="row1" colspan="2"><b class="genmed">{L_SEARCH_AUTHOR}{L_COLON}</b><br /><span class="gensmall">{L_SEARCH_AUTHOR_EXPLAIN}</span></td>
- <td class="row2" colspan="2" valign="middle"><input type="text" style="width: 300px" class="post" name="author" size="30" /></td>
- </tr>
- <tr>
- <td class="row1" colspan="2"><b class="genmed">{L_SEARCH_FORUMS}{L_COLON} </b><br /><span class="gensmall">{L_SEARCH_FORUMS_EXPLAIN}</span></td>
- <td class="row2" colspan="2"><select name="fid[]" multiple="multiple" size="5">{S_FORUM_OPTIONS}</select></td>
- </tr>
- <!-- EVENT search_body_search_query_append -->
- <!-- EVENT search_body_search_query_after -->
- <!-- EVENT search_body_search_options_before -->
- <tr>
- <th colspan="{$COLSPAN}">{L_SEARCH_OPTIONS}</th>
- </tr>
- <!-- EVENT search_body_search_options_prepend -->
- <tr>
- <td class="row1" width="25%" nowrap="nowrap"><b class="genmed">{L_SEARCH_SUBFORUMS}{L_COLON} </b></td>
- <td class="row2" width="25%" nowrap="nowrap"><input type="radio" class="radio" name="sc" value="1" checked="checked" /> <span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="sc" value="0" /> <span class="genmed">{L_NO}</span></td>
- <td class="row1" width="25%" nowrap="nowrap"><b class="genmed">{L_SEARCH_WITHIN}{L_COLON} </b></td>
- <td class="row2" width="25%" nowrap="nowrap"><input type="radio" class="radio" name="sf" value="all" checked="checked" /> <span class="genmed">{L_SEARCH_TITLE_MSG}</span><br /><input type="radio" class="radio" name="sf" value="msgonly" /> <span class="genmed">{L_SEARCH_MSG_ONLY}</span> <br /><input type="radio" class="radio" name="sf" value="titleonly" /> <span class="genmed">{L_SEARCH_TITLE_ONLY}</span> <br /><input type="radio" class="radio" name="sf" value="firstpost" /> <span class="genmed">{L_SEARCH_FIRST_POST}</span></td>
- </tr>
- <!-- EVENT search_body_search_options_append -->
- <!-- EVENT search_body_search_display_options_prepend -->
- <tr>
- <td class="row1"><b class="genmed">{L_RESULT_SORT}{L_COLON} </b></td>
- <td class="row2" nowrap="nowrap">{S_SELECT_SORT_KEY}<br /><input type="radio" class="radio" name="sd" value="a" /> <span class="genmed">{L_SORT_ASCENDING}</span><br /><input type="radio" class="radio" name="sd" value="d" checked="checked" /> <span class="genmed">{L_SORT_DESCENDING}</span></td>
- <td class="row1" nowrap="nowrap"><b class="genmed">{L_DISPLAY_RESULTS}{L_COLON} </b></td>
- <td class="row2" nowrap="nowrap"><input type="radio" class="radio" name="sr" value="posts" checked="checked" /> <span class="genmed">{L_POSTS}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="sr" value="topics" /> <span class="genmed">{L_TOPICS}</span></td>
- </tr>
- <tr>
- <td class="row1" width="25%"><b class="genmed">{L_RESULT_DAYS}{L_COLON} </b></td>
- <td class="row2" width="25%" nowrap="nowrap">{S_SELECT_SORT_DAYS}</td>
- <td class="row1" nowrap="nowrap"><b class="genmed">{L_RETURN_FIRST}{L_COLON} </b></td>
- <td class="row2" nowrap="nowrap"><select name="ch">{S_CHARACTER_OPTIONS}</select> <span class="genmed">{L_POST_CHARACTERS}</span></td>
- </tr>
- <!-- EVENT search_body_search_display_options_append -->
- <!-- EVENT search_body_search_options_after -->
- <tr>
- <td class="cat" colspan="{$COLSPAN}" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" name="submit" type="submit" value="{L_SEARCH}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" /></td>
- </tr>
- </table>
-
- </form>
- <!-- EVENT search_body_form_after -->
-
- <br clear="all" />
-
- <!-- EVENT search_body_recent_search_before -->
- <!-- IF .recentsearch -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="2">{L_RECENT_SEARCHES}</th>
- </tr>
- <!-- BEGIN recentsearch -->
- <!-- IF recentsearch.S_ROW_COUNT is even --><tr class="row2"><!-- ELSE --><tr class="row1"><!-- ENDIF -->
-
- <td class="genmed" style="padding: 4px;" width="70%"><a href="{recentsearch.U_KEYWORDS}">{recentsearch.KEYWORDS}</a></td>
- <td class="genmed" style="padding: 4px;" width="30%" align="center">{recentsearch.TIME}</td>
- </tr>
- <!-- END recentsearch -->
- </table>
-
- <br clear="all" />
- <!-- ENDIF -->
- <!-- EVENT search_body_recent_search_after -->
-
- </div>
-
- <!-- INCLUDE breadcrumbs.html -->
-
- <br clear="all" />
-
- <div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<script type="text/javascript">
-// <![CDATA[
- (function()
- {
- var elements = document.getElementsByName("keywords");
- for (var i = 0; i < elements.length; ++i)
- {
- if (elements[i].tagName.toLowerCase() == 'input')
- {
- elements[i].focus();
- break;
- }
- }
- })();
-// ]]>
-</script>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/search_results.html b/phpBB/styles/subsilver2/template/search_results.html
deleted file mode 100644
index 1ba8af7fe2..0000000000
--- a/phpBB/styles/subsilver2/template/search_results.html
+++ /dev/null
@@ -1,165 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- EVENT search_results_header_before -->
-
-<form method="post" action="{S_SEARCH_ACTION}">
-
-<table width="100%" cellspacing="1">
-<tr>
- <td colspan="2"><span class="titles"><!-- IF SEARCH_TITLE -->{SEARCH_TITLE}<!-- ELSE -->{SEARCH_MATCHES}<!-- ENDIF --></span><br /></td>
-</tr>
-<tr>
- <td class="genmed"><!-- IF SEARCH_TOPIC -->{L_SEARCHED_TOPIC}{L_COLON} <a href="{U_SEARCH_TOPIC}"><b>{SEARCH_TOPIC}</b></a><br /><!-- ENDIF --><!-- IF SEARCH_WORDS -->{L_SEARCHED_FOR}{L_COLON} <a href="{U_SEARCH_WORDS}"><b>{SEARCH_WORDS}</b></a><!-- ENDIF --><!-- IF IGNORED_WORDS --> {L_IGNORED_TERMS}{L_COLON} <b>{IGNORED_WORDS}</b><!-- ENDIF --></td>
- <td align="{S_CONTENT_FLOW_END}"><!-- EVENT search_results_searchbox_after --><!-- IF SEARCH_IN_RESULTS --><span class="genmed">{L_SEARCH_IN_RESULTS}{L_COLON} </span><input class="post" type="text" name="add_keywords" value="" /> <input class="btnlite" type="submit" name="submit" value="{L_GO}" /><!-- ENDIF --></td>
-</tr>
-</table>
-
-<!-- EVENT search_results_header_after -->
-
-<br clear="all" />
-
-<!-- IF S_SHOW_TOPICS -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th width="4%" nowrap="nowrap">&nbsp;</th>
- <th colspan="2" nowrap="nowrap">&nbsp;{L_TOPICS}&nbsp;</th>
- <th nowrap="nowrap">&nbsp;{L_AUTHOR}&nbsp;</th>
- <th nowrap="nowrap">&nbsp;{L_REPLIES}&nbsp;</th>
- <th nowrap="nowrap">&nbsp;{L_VIEWS}&nbsp;</th>
- <th nowrap="nowrap">&nbsp;{L_LAST_POST}&nbsp;</th>
- </tr>
- <!-- BEGIN searchresults -->
- <!-- EVENT search_results_topic_before -->
- <tr valign="middle">
- <td class="row1" width="25" align="center">{searchresults.TOPIC_FOLDER_IMG}</td>
- <td class="row1" width="25" align="center">
- <!-- IF searchresults.TOPIC_ICON_IMG -->
- <img src="{T_ICONS_PATH}{searchresults.TOPIC_ICON_IMG}" width="{searchresults.TOPIC_ICON_IMG_WIDTH}" height="{searchresults.TOPIC_ICON_IMG_HEIGHT}" alt="" title="" />
- <!-- ENDIF -->
- </td>
- <td class="row1">
- <!-- EVENT topiclist_row_prepend -->
- <!-- IF searchresults.S_UNREAD_TOPIC --><a href="{searchresults.U_NEWEST_POST}" class="imageset">{NEWEST_POST_IMG}</a><!-- ENDIF -->
- {searchresults.ATTACH_ICON_IMG} <a href="{searchresults.U_VIEW_TOPIC}" class="topictitle">{searchresults.TOPIC_TITLE}</a>
- <!-- IF searchresults.S_TOPIC_UNAPPROVED or searchresults.S_POSTS_UNAPPROVED -->
- <a href="{searchresults.U_MCP_QUEUE}" class="imageset">{searchresults.UNAPPROVED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF searchresults.S_TOPIC_DELETED -->
- <a href="{searchresults.U_MCP_QUEUE}" class="imageset">{DELETED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF searchresults.S_TOPIC_REPORTED -->
- <a href="{searchresults.U_MCP_REPORT}" class="imageset">{REPORTED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- EVENT topiclist_row_topic_title_after -->
- <!-- IF .searchresults.pagination -->
- <p class="gensmall"> [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON}
- <!-- BEGIN pagination -->
- <!-- IF searchresults.pagination.S_IS_PREV -->
- <!-- ELSEIF searchresults.pagination.S_IS_CURRENT --><strong>{searchresults.pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF searchresults.pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF searchresults.pagination.S_IS_NEXT -->
- <!-- ELSE --><a href="{searchresults.pagination.PAGE_URL}">{searchresults.pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
- ] </p>
- <!-- ENDIF -->
- <p class="gensmall">{L_IN} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a></p>
- <!-- EVENT topiclist_row_append -->
- </td>
- <td class="row2" width="100" align="center"><p class="topicauthor">{searchresults.TOPIC_AUTHOR_FULL}</p></td>
- <td class="row1" width="50" align="center"><p class="topicdetails">{searchresults.TOPIC_REPLIES}</p></td>
- <td class="row2" width="50" align="center"><p class="topicdetails">{searchresults.TOPIC_VIEWS}</p></td>
- <td class="row1" width="120" align="center">
- <p class="topicdetails">{searchresults.LAST_POST_TIME}</p>
- <p class="topicdetails">{searchresults.LAST_POST_AUTHOR_FULL}
- <a href="{searchresults.U_LAST_POST}" class="imageset">{LAST_POST_IMG}</a>
- </p>
- </td>
- </tr>
- <!-- EVENT search_results_topic_after -->
- <!-- BEGINELSE -->
- <tr valign="middle">
- <td colspan="7" class="row3" align="center">{L_NO_SEARCH_RESULTS}</td>
- </tr>
- <!-- END searchresults -->
- <tr>
- <td class="cat" colspan="7" valign="middle" align="center"><!-- IF S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY --><span class="gensmall">{L_DISPLAY_POSTS}{L_COLON}</span> {S_SELECT_SORT_DAYS}<!-- IF S_SELECT_SORT_KEY -->&nbsp;<span class="gensmall">{L_SORT_BY}{L_COLON}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}<!-- ENDIF -->&nbsp;<input class="btnlite" type="submit" value="{L_GO}" name="sort" /><!-- ENDIF --></td>
- </tr>
- </table>
-
-<!-- ELSE -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th width="150" nowrap="nowrap">{L_AUTHOR}</th>
- <th width="100%" nowrap="nowrap">{L_MESSAGE}</th>
- </tr>
-
- <!-- BEGIN searchresults -->
- <tr class="row2">
- <!-- EVENT search_results_post_before -->
- <!-- IF searchresults.S_IGNORE_POST -->
- <td class="gensmall" colspan="2" height="25" align="center">{searchresults.L_IGNORE_POST}</td>
- <!-- ELSE -->
- <td colspan="2" height="25"><p class="topictitle"><a name="p{searchresults.POST_ID}" id="p{searchresults.POST_ID}" class="anchor"></a>&nbsp;{L_FORUM}{L_COLON} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a> &nbsp; {L_TOPIC}{L_COLON} <a href="{searchresults.U_VIEW_TOPIC}">{searchresults.TOPIC_TITLE}</a> </p></td>
- </tr>
- <tr class="row1">
- <td width="150" align="center" valign="middle"><b class="postauthor">{searchresults.POST_AUTHOR_FULL}</b></td>
- <td height="25">
- <table width="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td class="gensmall">
- <div style="float: {S_CONTENT_FLOW_BEGIN};">
- <!-- IF searchresults.POST_SUBJECT neq "" -->
- &nbsp;<b>{L_POST_SUBJECT}{L_COLON}</b> <a href="{searchresults.U_VIEW_POST}">{searchresults.POST_SUBJECT}</a>
- <!-- ELSE -->
- [ <a href="{searchresults.U_VIEW_POST}">{L_JUMP_TO_POST}</a> ]
- <!-- ENDIF -->
- </div>
- <div style="float: {S_CONTENT_FLOW_END};"><b>{L_POSTED}{L_COLON}</b> {searchresults.POST_DATE}&nbsp;</div>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr class="row1">
- <td width="150" align="center" valign="top"><br /><span class="postdetails">{L_REPLIES}{L_COLON} <b>{searchresults.TOPIC_REPLIES}</b><br />{L_VIEWS}{L_COLON} <b>{searchresults.TOPIC_VIEWS}</b></span><br /><br /></td>
- <td valign="top">
- <table width="100%" cellspacing="5">
- <tr>
- <td class="postbody">{searchresults.MESSAGE}</td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT search_results_post_after -->
- <tr>
- <td class="spacer" colspan="2"><img src="images/spacer.gif" height="1" alt="" /></td>
- </tr>
- <!-- BEGINELSE -->
- <tr valign="middle">
- <td colspan="2" class="row3" align="center">{L_NO_SEARCH_RESULTS}</td>
- </tr>
- <!-- END searchresults -->
- <tr>
- <td class="cat" colspan="2" align="center"><!-- IF S_SELECT_SORT_KEY --><span class="gensmall">{L_SORT_BY}{L_COLON}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" name="sort" value="{L_GO}" /><!-- ENDIF --></td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-</form>
-
-<div class="gensmall" style="float: {S_CONTENT_FLOW_BEGIN};"><span class="nav">{PAGE_NUMBER}</span> [ {SEARCH_MATCHES} ]</div>
-<div class="nav" style="float: {S_CONTENT_FLOW_END};"><!-- INCLUDE pagination.html --></div>
-
-<br clear="all" /><br />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/searchbox.html b/phpBB/styles/subsilver2/template/searchbox.html
deleted file mode 100644
index 49de299ea2..0000000000
--- a/phpBB/styles/subsilver2/template/searchbox.html
+++ /dev/null
@@ -1 +0,0 @@
-<form method="get" name="search" action="{S_SEARCHBOX_ACTION}"><span class="gensmall">{L_SEARCH_FOR}{L_COLON}</span> <input class="post" type="text" name="keywords" size="20" /> <input class="btnlite" type="submit" value="{L_GO}" />{S_SEARCH_LOCAL_HIDDEN_FIELDS}</form>
diff --git a/phpBB/styles/subsilver2/template/simple_footer.html b/phpBB/styles/subsilver2/template/simple_footer.html
deleted file mode 100644
index d69c56fb8c..0000000000
--- a/phpBB/styles/subsilver2/template/simple_footer.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-</div>
-
-<div id="wrapfooter">
- <span class="copyright">{CREDIT_LINE}</span>
-</div>
-
-<script type="text/javascript" src="{T_JQUERY_LINK}"></script>
-<!-- IF S_ALLOW_CDN --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
-
-<!-- EVENT simple_footer_after -->
-
-{$SCRIPTS}
-</body>
-</html>
diff --git a/phpBB/styles/subsilver2/template/simple_header.html b/phpBB/styles/subsilver2/template/simple_header.html
deleted file mode 100644
index 2beeac2548..0000000000
--- a/phpBB/styles/subsilver2/template/simple_header.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8" />
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-{META}
-<title>{SITENAME} &bull; <!-- IF S_IN_MCP -->{L_MCP} &bull; <!-- ELSEIF S_IN_UCP -->{L_UCP} &bull; <!-- ENDIF -->{PAGE_TITLE}</title>
-
-<link rel="stylesheet" href="{T_STYLESHEET_LINK}" type="text/css" />
-<link rel="stylesheet" href="{T_STYLESHEET_LANG_LINK}" type="text/css" />
-
-<!-- EVENT simple_header_head_append -->
-
-{$STYLESHEETS}
-
-<!-- EVENT simple_header_stylesheets_after -->
-
-</head>
-
-<body class="{S_CONTENT_DIRECTION} {BODY_CLASS}">
-<!-- EVENT simple_header_body_before -->
-<a name="top" class="anchor"></a>
-<div id="wrapcentre">
diff --git a/phpBB/styles/subsilver2/template/timezone.js b/phpBB/styles/subsilver2/template/timezone.js
deleted file mode 100644
index c5829c0bb1..0000000000
--- a/phpBB/styles/subsilver2/template/timezone.js
+++ /dev/null
@@ -1,21 +0,0 @@
-(function($) { // Avoid conflicts with other libraries
-
-"use strict";
-
-$('#tz_date').change(function() {
- phpbb.timezoneSwitchDate(false);
-});
-
-$('#tz_select_date_suggest').click(function(){
- phpbb.timezonePreselectSelect(true);
-});
-
-$(document).ready(
- phpbb.timezoneEnableDateSelection
-);
-
-$(document).ready(
- phpbb.timezonePreselectSelect($('#tz_select_date_suggest').attr('timezone-preselect') == 'true')
-);
-
-})(jQuery); // Avoid conflicts with other libraries
diff --git a/phpBB/styles/subsilver2/template/timezone_option.html b/phpBB/styles/subsilver2/template/timezone_option.html
deleted file mode 100644
index 3fc7467d16..0000000000
--- a/phpBB/styles/subsilver2/template/timezone_option.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_BOARD_TIMEZONE}{L_COLON}</b></td>
- <td class="row2">
- <!-- IF .timezone_date -->
- <div id="tz_select_date" style="display: none;">
- <select name="tz_date" id="tz_date" class="autowidth tz_select">
- <option value="">{L_SELECT_CURRENT_TIME}</option>
- <!-- BEGIN timezone_date -->
- <option value="{timezone_date.VALUE}"<!-- IF timezone_date.SELECTED --> selected="selected"<!-- ENDIF -->>{timezone_date.TITLE}</option>
- <!-- END timezone_date -->
- </select><br />
- <input type="button" id="tz_select_date_suggest" class="btnlite" style="display: none;" timezone-preselect="<!-- IF S_TZ_PRESELECT -->true<!-- ELSE -->false<!-- ENDIF -->" data-l-suggestion="{L_TIMEZONE_DATE_SUGGESTION}" value="{L_TIMEZONE_DATE_SUGGESTION}" />
- </div>
- <!-- ENDIF -->
- <select name="tz" id="timezone" class="autowidth tz_select">
- <option value="">{L_SELECT_TIMEZONE}</option>
- <!-- BEGIN timezone_select -->
- <optgroup label="{timezone_select.LABEL}" data-tz-value="{timezone_select.VALUE}">
- <!-- BEGIN timezone_options -->
- <option title="{timezone_select.timezone_options.TITLE}" value="{timezone_select.timezone_options.VALUE}"<!-- IF timezone_select.timezone_options.SELECTED --> selected="selected"<!-- ENDIF -->>{timezone_select.timezone_options.LABEL}</option>
- <!-- END timezone_options -->
- </optgroup>
- <!-- END timezone_select -->
- </select>
-
- <!-- INCLUDEJS timezone.js -->
- </td>
-</tr>
diff --git a/phpBB/styles/subsilver2/template/ucp_agreement.html b/phpBB/styles/subsilver2/template/ucp_agreement.html
deleted file mode 100644
index fca7eb2368..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_agreement.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- IF S_SHOW_COPPA or S_REGISTRATION -->
-
-<!-- IF S_LANG_OPTIONS -->
-<script type="text/javascript">
-// <![CDATA[
- /**
- * Change language
- */
- function change_language(lang_iso)
- {
- document.cookie = '{COOKIE_NAME}_lang=' + lang_iso + '; path={COOKIE_PATH}';
- document.forms['register'].change_lang.value = lang_iso;
- document.forms['register'].submit();
- }
-
-// ]]>
-</script>
-
- <form method="post" action="{S_UCP_ACTION}" id="register">
- <table width="100%" cellspacing="0">
- <tr>
- <td class="gensmall" align="{S_CONTENT_FLOW_END}">{L_LANGUAGE}{L_COLON} <select name="lang" id="lang" onchange="change_language(this.value); return false;" title="{L_LANGUAGE}">{S_LANG_OPTIONS}</select></td>
- </tr>
- </table>
- {S_HIDDEN_FIELDS}
- </form>
-<!-- ENDIF -->
-
- <form method="post" action="{S_UCP_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th height="25">{SITENAME} - {L_REGISTRATION}</th>
- </tr>
- <tr>
- <td class="row1" align="center">
- <table width="90%" cellspacing="2" cellpadding="2" border="0" align="center">
- <tr>
- <!-- IF S_SHOW_COPPA -->
- <td class="gen" align="center"><br />{L_COPPA_BIRTHDAY}<br /><br /><a href="{U_COPPA_NO}">{L_COPPA_NO}</a> :: <a href="{U_COPPA_YES}">{L_COPPA_YES}</a><br /><br /></td>
- <!-- ELSE -->
- <td>
- <!-- EVENT ucp_agreement_terms_before -->
- <span class="genmed"><br />{L_TERMS_OF_USE}<br /><br /></span>
- <!-- EVENT ucp_agreement_terms_after -->
- <div align="center">
- <input class="btnlite" type="submit" id="agreed" name="agreed" value="{L_AGREE}" /><br /><br />
- <input class="btnlite" type="submit" name="not_agreed" value="{L_NOT_AGREE}" />
- </div>
- </td>
- <!-- ENDIF -->
- </tr>
- </table>
- </td>
- </tr>
- </table>
- {S_HIDDEN_FIELDS}
- {S_FORM_TOKEN}
- </form>
-
-<!-- ELSEIF S_AGREEMENT -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th height="25">{SITENAME} - {AGREEMENT_TITLE}</th>
- </tr>
- <tr>
- <td class="row1" align="center">
- <table width="90%" cellspacing="2" cellpadding="2" border="0" align="center">
- <tr>
- <td>
- <span class="genmed"><br />{AGREEMENT_TEXT}<br /><br /></span>
- <div align="center">
- <a href="{U_BACK}">{L_BACK}</a>
- </div>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
-
-<!-- ENDIF -->
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_attachments.html b/phpBB/styles/subsilver2/template/ucp_attachments.html
deleted file mode 100644
index c513f933c0..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_attachments.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<!-- IF S_ATTACHMENT_ROWS -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th nowrap="nowrap">#</th>
- <th nowrap="nowrap" width="15%"><a href="{U_SORT_FILENAME}">{L_FILENAME}</a></th>
- <th nowrap="nowrap" width="5%"><a href="{U_SORT_POST_TIME}">{L_POST_TIME}</a></th>
- <th nowrap="nowrap" width="5%"><a href="{U_SORT_FILESIZE}">{L_FILESIZE}</a></th>
- <th nowrap="nowrap" width="5%"><a href="{U_SORT_DOWNLOADS}">{L_DOWNLOADS}</a></th>
- <th width="2%" nowrap="nowrap">{L_DELETE}</th>
- </tr>
- <!-- IF TOTAL_ATTACHMENTS -->
- <tr>
- <td class="row3" colspan="6">
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {NUM_ATTACHMENTS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
- <!-- BEGIN attachrow -->
- <!-- IF attachrow.S_ROW_COUNT is even --><tr class="row2"><!-- ELSE --><tr class="row1"><!-- ENDIF -->
-
- <td class="genmed" style="padding: 4px;" align="center" width="2%">&nbsp;{attachrow.ROW_NUMBER}&nbsp;</td>
- <td style="padding: 4px;"><a class="gen" href="{attachrow.U_VIEW_ATTACHMENT}">{attachrow.FILENAME}</a><br /><span class="gensmall"><!-- IF attachrow.S_IN_MESSAGE --><b>{L_PM}{L_COLON} </b><!-- ELSE --><b>{L_TOPIC}{L_COLON} </b><!-- ENDIF --><a href="{attachrow.U_VIEW_TOPIC}">{attachrow.TOPIC_TITLE}</a></span></td>
- <td class="gensmall" style="padding: 4px;" align="center" valign="middle" nowrap="nowrap">&nbsp;{attachrow.POST_TIME}&nbsp;</td>
- <td class="genmed" style="padding: 4px;" align="center" valign="middle" nowrap="nowrap">{attachrow.SIZE}</td>
- <td class="genmed" style="padding: 4px;" align="center">{attachrow.DOWNLOAD_COUNT}</td>
- <td style="padding: 4px;" align="center" valign="middle"><input type="checkbox" class="radio" name="attachment[{attachrow.ATTACH_ID}]" value="1" /></td>
- </tr>
- <!-- END attachrow -->
- <tr>
- <td class="cat" colspan="6"><div style="float: {S_CONTENT_FLOW_BEGIN};"><span class="gensmall">{L_SORT_BY}{L_COLON} </span><select name="sk">{S_SORT_OPTIONS}</select> <select name="sd">{S_ORDER_SELECT}</select>&nbsp;<input class="btnlite" type="submit" name="sort" value="{L_SORT}" /></div><div style="float: {S_CONTENT_FLOW_END};"><input class="btnlite" type="submit" name="delete" value="{L_DELETE_MARKED}" />&nbsp;</div></td>
- </tr>
- </table>
-
- <div style="float: {S_CONTENT_FLOW_END};"><b class="gensmall"><a href="#" onclick="marklist('ucp', 'attachment', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('ucp', 'attachment', false); return false;">{L_UNMARK_ALL}</a></b></div>
-
-<!-- ELSE -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_TITLE}</th>
- </tr>
- <tr class="row1">
- <td align="center"><b class="genmed">{L_UCP_NO_ATTACHMENTS}</b></td>
- </tr>
- </table>
-
-<!-- ENDIF -->
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_auth_link.html b/phpBB/styles/subsilver2/template/ucp_auth_link.html
deleted file mode 100644
index 75e3133fcf..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_auth_link.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="4">{L_UCP_AUTH_LINK_TITLE}</th>
- </tr>
-
- <!-- IF ERROR -->
- <tr>
- <td class="row1" colspan="2" align="center"><span class="genmed error">{ERROR}</span></td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF PROVIDER_TEMPLATE_FILE -->
- <!-- INCLUDE {PROVIDER_TEMPLATE_FILE} -->
- <!-- ENDIF -->
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html b/phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html
deleted file mode 100644
index 80564d207b..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_auth_link_oauth.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!-- BEGIN oauth -->
- <tr>
- <th>{oauth.SERVICE_NAME}</th>
- </tr>
-
- <tr>
- <td class="row1">
- <form id="ucp" method="post" action="{S_UCP_ACTION}">
- <table>
- <!-- IF oauth.UNIQUE_ID -->
- <tr>
- <td class="row1">{L_UCP_AUTH_LINK_ID}{L_COLON}</td>
- <td class="row1">{oauth.UNIQUE_ID}</td>
- </tr>
- <tr>
- <td class="row1">&nbsp;</td>
- <td class="row1"><input type="submit" name="submit" tabindex="6" value="{L_UCP_AUTH_LINK_UNLINK}" class="button1" /></td>
- </tr>
- <!-- ELSE -->
- <tr>
- <td class="row1">{L_UCP_AUTH_LINK_ASK}</td>
- </tr>
- <tr>
- <td class="row1"><input type="submit" name="submit" tabindex="6" value="{L_UCP_AUTH_LINK_LINK}" class="button1" /></td>
- </tr>
- <!-- ENDIF -->
- </table>
- {oauth.HIDDEN_FIELDS}
- {S_HIDDEN_FIELDS}
- {S_FORM_TOKEN}
- </form>
- </td>
- </tr>
-<!-- END oauth -->
diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html
deleted file mode 100644
index 9fb3f0e754..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_avatar_options_gravatar.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_GRAVATAR_AVATAR_EMAIL}{L_COLON}</b><br /><span class="gensmall">{L_GRAVATAR_AVATAR_EMAIL_EXPLAIN}</span></td>
- <td class="row2"><input type="text" name="avatar_gravatar_email" id="avatar_gravatar_email" value="{AVATAR_GRAVATAR_EMAIL}" class="inputbox" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_GRAVATAR_AVATAR_SIZE}{L_COLON}</b><br /><span class="gensmall">{L_GRAVATAR_AVATAR_SIZE_EXPLAIN}</span></td>
- <td class="row2">
- <input type="number" name="avatar_gravatar_width" id="avatar_gravatar_width" min="{AVATAR_MIN_WIDTH}" max="{AVATAR_MAX_WIDTH}" value="{AVATAR_GRAVATAR_WIDTH}" class="inputbox autowidth" /> {L_PIXEL} &times;&nbsp;
- <input type="number" name="avatar_gravatar_height" id="avatar_gravatar_height" min="{AVATAR_MIN_HEIGHT}" max="{AVATAR_MAX_HEIGHT}" value="{AVATAR_GRAVATAR_HEIGHT}" class="inputbox autowidth" /> {L_PIXEL}
- </td>
- </tr>
-</table>
diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html
deleted file mode 100644
index 921126ba22..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<table class="tablebg" width="100%" cellspacing="1">
- <!-- IF .avatar_local_cats -->
- <tr>
- <td class="cat" colspan="2" align="center" valign="middle"><span class="genmed">{L_AVATAR_CATEGORY}{L_COLON} </span><select name="avatar_local_cat" id="category">
- <!-- BEGIN avatar_local_cats -->
- <option value="{avatar_local_cats.NAME}"<!-- IF avatar_local_cats.SELECTED --> selected="selected"<!-- ENDIF -->>{avatar_local_cats.NAME}</option>
- <!-- END avatar_local_cats -->
- </select>&nbsp; <input class="btnlite" tabindex="0" type="submit" value="{L_GO}" name="avatar_local_go" />
- </td>
- </tr>
- <tr>
- <td class="row1" colspan="2" align="center">
- <table cellspacing="1" cellpadding="4" border="0">
- <!-- BEGIN avatar_local_row -->
- <tr>
- <!-- BEGIN avatar_local_col -->
- <td class="row1" align="center" id="av-{avatar_local_row.S_ROW_COUNT}-{avatar_local_row.avatar_local_col.S_ROW_COUNT}"><img src="{avatar_local_row.avatar_local_col.AVATAR_IMAGE}" alt="{avatar_local_row.avatar_local_col.AVATAR_NAME}" title="{avatar_local_row.avatar_local_col.AVATAR_NAME}" /></td>
- <!-- END avatar_local_col -->
- </tr>
- <tr>
- <!-- BEGIN avatar_local_option -->
- <td class="row2" align="center"><input type="radio" class="radio" name="avatar_local_file"
- id="av-{avatar_local_row.S_ROW_COUNT}-{avatar_local_row.avatar_local_col.S_ROW_COUNT}"
- value="{avatar_local_row.avatar_local_option.S_OPTIONS_AVATAR}"
- <!-- IF avatar_local_row.avatar_local_option.CHECKED --> checked="checked"<!-- ENDIF --> />
- </td>
- <!-- END avatar_local_option -->
- </tr>
- <!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="2">{L_NO_AVATAR_CATEGORY}</td>
- </tr>
- <!-- END avatar_local_row -->
- </table>
- </td>
- </tr>
- <!-- ELSE -->
- <tr>
- <td class="row1" colspan="2"><strong>{L_NO_AVATARS}</strong></td>
- </tr>
- <!-- ENDIF -->
-</table>
diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html
deleted file mode 100644
index 309b3f9836..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_avatar_options_remote.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_LINK_REMOTE_AVATAR}{L_COLON} </b><br /><span class="gensmall">{L_LINK_REMOTE_AVATAR_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="text" name="avatar_remote_url" size="40" value="{AVATAR_REMOTE_URL}" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_LINK_REMOTE_SIZE}{L_COLON} </b><br /><span class="gensmall">{L_LINK_REMOTE_SIZE_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="number" name="avatar_remote_width" min="{AVATAR_MIN_WIDTH}" max="{AVATAR_MAX_WIDTH}" value="{AVATAR_REMOTE_WIDTH}" /> <span class="gen">{L_PIXEL} &times; </span> <input class="post" type="number" name="avatar_remote_height" min="{AVATAR_MIN_HEIGHT}" max="{AVATAR_MAX_HEIGHT}" value="{AVATAR_REMOTE_HEIGHT}" /> <span class="gen">{L_PIXEL}</span></td>
- </tr>
-</table>
diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html
deleted file mode 100644
index 6b813baeaa..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_avatar_options_upload.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_UPLOAD_AVATAR_FILE}{L_COLON} </b></td>
- <td class="row2"><input type="hidden" name="MAX_FILE_SIZE" value="{AVATAR_SIZE}" /><input class="post" type="file" name="avatar_upload_file" /></td>
- </tr>
-<!-- IF S_UPLOAD_AVATAR_URL -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_UPLOAD_AVATAR_URL}{L_COLON} </b><br /><span class="gensmall">{L_UPLOAD_AVATAR_URL_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="text" name="avatar_upload_url" size="40" value="" /></td>
- </tr>
-<!-- ENDIF -->
-</table>
diff --git a/phpBB/styles/subsilver2/template/ucp_footer.html b/phpBB/styles/subsilver2/template/ucp_footer.html
deleted file mode 100644
index 57adb2da97..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_footer.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
- <!-- IF not S_PRIVMSGS or S_SHOW_DRAFTS --> {S_FORM_TOKEN}</form><!-- ENDIF --></td>
-</tr>
-</table>
-<!-- IF (S_SHOW_PM_BOX or S_EDIT_POST) and S_POST_ACTION -->{S_FORM_TOKEN}</form><!-- ENDIF -->
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_groups_manage.html b/phpBB/styles/subsilver2/template/ucp_groups_manage.html
deleted file mode 100644
index 09d59c8ec0..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_groups_manage.html
+++ /dev/null
@@ -1,229 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<!-- IF S_EDIT -->
-
- <!-- IF S_ERROR -->
- <div class="errorbox">
- <h3>{L_WARNING}</h3>
- <p>{ERROR_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="2">{L_USERGROUPS}</th>
- </tr>
- <tr>
- <td class="row1" colspan="2"><span class="genmed">{L_GROUPS_EXPLAIN}</span></td>
- </tr>
-
- <tr>
- <th colspan="2">{L_GROUP_DETAILS}</th>
- </tr>
- <tr>
- <td class="row1" width="35%"><label<!-- IF not S_SPECIAL_GROUP --> for="group_name"<!-- ENDIF -->>{L_GROUP_NAME}{L_COLON}</label></td>
- <td class="row2"><!-- IF S_SPECIAL_GROUP --><b<!-- IF GROUP_COLOUR --> style="color: #{GROUP_COLOUR};"<!-- ENDIF -->>{GROUP_NAME}</b><!-- ENDIF --><input name="group_name" type="<!-- IF S_SPECIAL_GROUP -->hidden<!-- ELSE -->text<!-- ENDIF -->" id="group_name" value="{GROUP_INTERNAL_NAME}" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><label for="group_desc">{L_GROUP_DESC}{L_COLON}</label></td>
- <td class="row2"><textarea id="group_desc" name="group_desc" rows="5" cols="45">{GROUP_DESC}</textarea>
- <br /><input type="checkbox" class="radio" name="desc_parse_bbcode"<!-- IF S_DESC_BBCODE_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_BBCODE} &nbsp; <input type="checkbox" class="radio" name="desc_parse_smilies"<!-- IF S_DESC_SMILIES_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_SMILIES} &nbsp; <input type="checkbox" class="radio" name="desc_parse_urls"<!-- IF S_DESC_URLS_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_PARSE_URLS}
- </td>
- </tr>
- <!-- IF not S_SPECIAL_GROUP -->
- <tr>
- <td class="row1" width="35%"><label for="group_type">{L_GROUP_TYPE}{L_COLON}</label><br /><span>{L_GROUP_TYPE_EXPLAIN}</span></td>
- <td class="row2">
- <input name="group_type" type="radio" class="radio" id="group_type" value="{GROUP_TYPE_FREE}"{GROUP_FREE} /> {L_GROUP_OPEN} &nbsp;
- <input name="group_type" type="radio" class="radio" value="{GROUP_TYPE_OPEN}"{GROUP_OPEN} /> {L_GROUP_REQUEST} &nbsp;
- <input name="group_type" type="radio" class="radio" value="{GROUP_TYPE_CLOSED}"{GROUP_CLOSED} /> {L_GROUP_CLOSED} &nbsp;
- <input name="group_type" type="radio" class="radio" value="{GROUP_TYPE_HIDDEN}"{GROUP_HIDDEN} /> {L_GROUP_HIDDEN}
- </td>
- </tr>
- <!-- ELSE -->
- <tr style="display:none;"><td><input name="group_type" type="hidden" value="{GROUP_TYPE_SPECIAL}" /></td></tr>
- <!-- ENDIF -->
-
- <tr>
- <th colspan="2">{L_GROUP_SETTINGS_SAVE}</th>
- </tr>
- <tr>
- <td class="row1" width="35%"><label for="group_colour">{L_GROUP_COLOR}{L_COLON}</label><br /><span>{L_GROUP_COLOR_EXPLAIN}</span></td>
- <td class="row2">
- <input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" />&nbsp;&nbsp;
- <span>[ <a href="#" id="color_palette_toggle">{L_COLOUR_SWATCH}</a> ]</span>
- <div id="color_palette_placeholder" style="display: none;" data-orientation="h" data-height="12" data-width="15" data-target="#group_colour"></div>
- </td>
- </tr>
- <tr>
- <td class="row1" width="35%"><label for="group_rank">{L_GROUP_RANK}{L_COLON}</label></td>
- <td class="row2"><select name="group_rank" id="group_rank">{S_RANK_OPTIONS}</select></td>
- </tr>
- <tr>
- <th colspan="2">{L_GROUP_AVATAR}</th>
- </tr>
- <tr>
- <td class="row1" width="35%"><label>{L_CURRENT_IMAGE}{L_COLON}</label><br /><span>{L_AVATAR_EXPLAIN}</span></td>
- <td class="row2">{AVATAR_IMAGE}<br /><br /><input type="checkbox" class="radio" name="avatar_delete" />&nbsp;<span>{L_DELETE_AVATAR}</span></td>
- </tr>
-<!-- IF not S_AVATARS_ENABLED -->
- <tr>
- <td class="row3" colspan="2" align="center">{L_AVATAR_FEATURES_DISABLED}</td>
- </tr>
-<!-- ENDIF -->
- <tr>
- <th colspan="2">{L_AVATAR_SELECT}</th>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_AVATAR_TYPE}{L_COLON}</b></td>
- <td class="row2">
- <select name="avatar_driver" id="avatar_driver">
- <!-- BEGIN avatar_drivers -->
- <option value="{avatar_drivers.DRIVER}"<!-- IF avatar_drivers.SELECTED --> selected="selected"<!-- ENDIF -->>{avatar_drivers.L_TITLE}</option>
- <!-- END avatar_drivers -->
- </select></td>
- </tr>
-<!-- BEGIN avatar_drivers -->
- <tr class="avatar_option_{avatar_drivers.DRIVER}">
- <td class="row1" width="35%" colspan="2"><noscript><b class="genmed">{avatar_drivers.L_TITLE} </b><br /></noscript>{avatar_drivers.L_EXPLAIN}</span></td>
- </tr>
- <tr class="avatar_option_{avatar_drivers.DRIVER}">
- <td colspan="2" style="padding: 0">{avatar_drivers.OUTPUT}</td>
- </tr>
-<!-- END avatar_drivers -->
-
- <tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnlite" type="submit" id="submit" name="update" value="{L_SUBMIT}" />&nbsp;
- <input class="btnmain" type="reset" id="reset" name="reset" value="{L_RESET}" /></td>
- </tr>
- </table>
-
-<!-- INCLUDEJS avatars.js -->
-
-<!-- ELSEIF S_LIST -->
-
- <h1>{L_GROUP_MEMBERS}</h1>
-
- <p>{L_GROUP_MEMBERS_EXPLAIN}</p>
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_USERNAME}</th>
- <th>{L_GROUP_DEFAULT}</th>
- <th>{L_JOINED}</th>
- <th>{L_POSTS}</th>
- <th>{L_MARK}</th>
- </tr>
-
- <tr>
- <td class="row3" colspan="5"><b>{L_GROUP_LEAD}</b></td>
- </tr>
- <!-- BEGIN leader -->
- <!-- IF leader.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td>{leader.USERNAME_FULL}</td>
- <td style="text-align: center;"><!-- IF leader.S_GROUP_DEFAULT -->{L_YES}<!-- ELSE -->{L_NO}<!-- ENDIF --></td>
- <td style="text-align: center;">{leader.JOINED}</td>
- <td style="text-align: center;">{leader.USER_POSTS}</td>
- <td style="text-align: center;"></td>
- </tr>
- <!-- END leader -->
-
- <!-- BEGIN member -->
- <!-- IF member.S_PENDING -->
- <tr>
- <td class="row3" colspan="5"><b>{L_GROUP_PENDING}</b></td>
- </tr>
- <!-- ELSEIF member.S_APPROVED -->
- <tr>
- <td class="row3" colspan="5"><b>{L_GROUP_APPROVED}</b></td>
- </tr>
- <!-- ELSE -->
- <!-- IF member.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td>{member.USERNAME_FULL}</td>
- <td style="text-align: center;"><!-- IF member.S_GROUP_DEFAULT -->{L_YES}<!-- ELSE -->{L_NO}<!-- ENDIF --></td>
- <td style="text-align: center;">{member.JOINED}</td>
- <td style="text-align: center;">{member.USER_POSTS}</td>
- <td style="text-align: center;"><input type="checkbox" class="radio" name="mark[]" value="{member.USER_ID}" /></td>
- </tr>
- <!-- ENDIF -->
- <!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="5" style="text-align: center;">{L_GROUPS_NO_MEMBERS}</td>
- </tr>
- <!-- END member -->
- <tr>
- <td class="cat" colspan="5" align="center"><div style="float: {S_CONTENT_FLOW_END};"><span class="small"><a href="#" onclick="marklist('ucp', 'mark', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('ucp', 'mark', false); return false;">{L_UNMARK_ALL}</a></span></div><div style="float: {S_CONTENT_FLOW_BEGIN};"><select name="action"><option class="sep" value="">{L_SELECT_OPTION}</option>{S_ACTION_OPTIONS}</select> <input class="btnmain" type="submit" name="update" value="{L_SUBMIT}" /></div></td>
- </tr>
- </table>
-
- <div class="pagination" style="float: {S_CONTENT_FLOW_BEGIN};">
- <!-- IF .pagination -->
- <!-- INCLUDE pagination.html -->
- <!-- ELSE -->
- {PAGE_NUMBER}
- <!-- ENDIF -->
- </div>
-
- <br />
- <br />
-
- <h1>{L_ADD_USERS}</h1>
-
- <p>{L_ADD_USERS_UCP_EXPLAIN}</p>
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="2">{L_ADD_USERS}</th>
- </tr>
- <tr>
- <td class="row1"><label for="default">{L_USER_GROUP_DEFAULT}{L_COLON}</label><br /><span>{L_USER_GROUP_DEFAULT_EXPLAIN}</span></td>
- <td class="row2"><input name="default" type="radio" class="radio" value="1" /> {L_YES} &nbsp; <input name="default" type="radio" class="radio" id="default" value="0" checked="checked" /> {L_NO}</td>
- </tr>
- <tr>
- <td class="row1"><label for="usernames">{L_USERNAME}{L_COLON}</label><br /><span>{L_USERNAMES_EXPLAIN}</span></td>
- <td class="row2"><textarea id="usernames" name="usernames" cols="40" rows="5"></textarea><br />[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</td>
- </tr>
- <tr>
- <td class="cat" colspan="2" align="center"><input class="btnmain" type="submit" name="addusers" value="{L_SUBMIT}" /></td>
- </tr>
- </table>
-
-<!-- ELSE -->
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="3">{L_USERGROUPS}</th>
- </tr>
- <tr>
- <td class="row1" colspan="3"><span class="genmed">{L_GROUPS_EXPLAIN}</span></td>
- </tr>
-
- <tr>
- <th>{L_GROUP_DETAILS}</th>
- <th colspan="2">{L_OPTIONS}</th>
- </tr>
- <tr>
- <td class="row3" colspan="3"><b class="gensmall">{L_GROUP_LEADER}</b></td>
- </tr>
- <!-- BEGIN leader -->
- <!-- IF leader.S_ROW_COUNT is odd --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td><b class="genmed"<!-- IF leader.GROUP_COLOUR --> style="color: #{leader.GROUP_COLOUR};"<!-- ENDIF -->>{leader.GROUP_NAME}</b><!-- IF leader.GROUP_DESC --><p class="forumdesc">{leader.GROUP_DESC}</p><!-- ENDIF --></td>
- <td style="text-align: center;"><a href="{leader.U_EDIT}">{L_EDIT}</a></td>
- <td style="text-align: center;"><a href="{leader.U_LIST}">{L_GROUP_LIST}</a></td>
-
- </tr>
- <!-- BEGINELSE -->
- <tr>
- <td class="row2" align="center" colspan="3"><b class="genmed">{L_NO_LEADERS}</b></td>
- </tr>
- <!-- END leader -->
-
- <tr>
- <td class="cat" align="{S_CONTENT_FLOW_END}" colspan="3">&nbsp;</td>
- </tr>
- </table>
-
-<!-- ENDIF -->
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_groups_membership.html b/phpBB/styles/subsilver2/template/ucp_groups_membership.html
deleted file mode 100644
index 846d48007e..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_groups_membership.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="3">{L_USERGROUPS}</th>
-</tr>
-<tr>
- <td class="row1" colspan="3"><span class="genmed">{L_GROUPS_EXPLAIN}</span></td>
-</tr>
-
-<tr>
- <th colspan="2">{L_GROUP_DETAILS}</th>
- <th>{L_SELECT}</th>
-</tr>
-
-<!-- BEGIN leader -->
- <!-- IF leader.S_FIRST_ROW -->
- <tr>
- <td class="row3" colspan="3"><b class="gensmall">{L_GROUP_LEADER}</b></td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF leader.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td width="6%" align="center" nowrap="nowrap"><!-- IF S_CHANGE_DEFAULT --><input type="radio" class="radio" name="default"<!-- IF leader.S_GROUP_DEFAULT --> checked="checked"<!-- ENDIF --> value="{leader.GROUP_ID}" /><!-- ENDIF --></td>
- <td>
- <b class="genmed"><a href="{leader.U_VIEW_GROUP}"<!-- IF leader.GROUP_COLOUR --> style="color: #{leader.GROUP_COLOUR};"<!-- ENDIF -->>{leader.GROUP_NAME}</a></b>
- <!-- IF leader.GROUP_DESC --><br /><span class="genmed">{leader.GROUP_DESC}</span><!-- ENDIF -->
- <!-- IF not leader.GROUP_SPECIAL --><br /><i class="gensmall">{leader.GROUP_STATUS}</i><!-- ENDIF -->
- </td>
- <td width="6%" align="center" nowrap="nowrap"><!-- IF not leader.GROUP_SPECIAL --><input type="radio" class="radio" name="selected" value="{leader.GROUP_ID}" /><!-- ENDIF --></td>
- </tr>
-<!-- END leader -->
-
-<!-- BEGIN member -->
- <!-- IF member.S_FIRST_ROW -->
- <tr>
- <td class="row3" colspan="3"><b class="gensmall">{L_GROUP_MEMBER}</b></td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF member.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td width="6%" align="center" nowrap="nowrap"><!-- IF S_CHANGE_DEFAULT --><input type="radio" class="radio" name="default"<!-- IF member.S_GROUP_DEFAULT --> checked="checked"<!-- ENDIF --> value="{member.GROUP_ID}" /><!-- ENDIF --></td>
- <td>
- <b class="genmed"><a href="{member.U_VIEW_GROUP}"<!-- IF member.GROUP_COLOUR --> style="color: #{member.GROUP_COLOUR};"<!-- ENDIF -->>{member.GROUP_NAME}</a></b>
- <!-- IF member.GROUP_DESC --><br /><span class="genmed">{member.GROUP_DESC}</span><!-- ENDIF -->
- <!-- IF not member.GROUP_SPECIAL --><br /><i class="gensmall">{member.GROUP_STATUS}</i><!-- ENDIF -->
- </td>
- <td width="6%" align="center" nowrap="nowrap"><!-- IF not member.GROUP_SPECIAL --><input type="radio" class="radio" name="selected" value="{member.GROUP_ID}" /><!-- ENDIF --></td>
- </tr>
-<!-- END member -->
-
-<!-- BEGIN pending -->
- <!-- IF pending.S_FIRST_ROW -->
- <tr>
- <td class="row3" colspan="3"><b class="gensmall">{L_GROUP_PENDING}</b></td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF pending.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td width="6%" align="center" nowrap="nowrap">&nbsp;</td>
- <td>
- <b class="genmed"><a href="{pending.U_VIEW_GROUP}"<!-- IF pending.GROUP_COLOUR --> style="color: #{pending.GROUP_COLOUR};"<!-- ENDIF -->>{pending.GROUP_NAME}</a></b>
- <!-- IF pending.GROUP_DESC --><br /><span class="genmed">{pending.GROUP_DESC}</span><!-- ENDIF -->
- <!-- IF not pending.GROUP_SPECIAL --><br /><i class="gensmall">{pending.GROUP_STATUS}</i><!-- ENDIF -->
- </td>
- <td width="6%" align="center" nowrap="nowrap"><!-- IF not pending.GROUP_SPECIAL --><input type="radio" class="radio" name="selected" value="{pending.GROUP_ID}" /><!-- ENDIF --></td>
- </tr>
-<!-- END pending -->
-
-<!-- BEGIN nonmember -->
- <!-- IF nonmember.S_FIRST_ROW -->
- <tr>
- <td class="row3" colspan="3"><b class="gensmall">{L_GROUP_NONMEMBER}</b></td>
- </tr>
- <!-- ENDIF -->
-
- <!-- IF nonmember.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td width="6%" align="center" nowrap="nowrap">&nbsp;</td>
- <td>
- <b class="genmed"><a href="{nonmember.U_VIEW_GROUP}"<!-- IF nonmember.GROUP_COLOUR --> style="color: #{nonmember.GROUP_COLOUR};"<!-- ENDIF -->>{nonmember.GROUP_NAME}</a></b>
- <!-- IF nonmember.GROUP_DESC --><br /><span class="genmed">{nonmember.GROUP_DESC}</span><!-- ENDIF -->
- <!-- IF not nonmember.GROUP_SPECIAL --><br /><i class="gensmall">{nonmember.GROUP_STATUS}</i><!-- ENDIF -->
- </td>
- <td width="6%" align="center" nowrap="nowrap"><!-- IF nonmember.S_CAN_JOIN --><input type="radio" class="radio" name="selected" value="{nonmember.GROUP_ID}" /><!-- ENDIF --></td>
- </tr>
-<!-- END nonmember -->
-
-<tr>
- <td class="cat" colspan="3"><!-- IF S_CHANGE_DEFAULT --><div style="float: {S_CONTENT_FLOW_BEGIN};"><input class="btnlite" type="submit" name="change_default" value="{L_CHANGE_DEFAULT_GROUP}" /></div><!-- ENDIF --><div style="float: {S_CONTENT_FLOW_END};"><span class="genmed">{L_SELECT}{L_COLON} </span><select name="action"><option value="join">{L_JOIN_SELECTED}</option><option value="resign">{L_RESIGN_SELECTED}</option><option value="demote">{L_DEMOTE_SELECTED}</option></select>&nbsp;<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;</div></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_header.html b/phpBB/styles/subsilver2/template/ucp_header.html
deleted file mode 100644
index dff2841b54..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_header.html
+++ /dev/null
@@ -1,165 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-
-<!-- IF S_SHOW_PM_BOX and S_POST_ACTION -->
- <form action="{S_POST_ACTION}" method="post" name="postform"{S_FORM_ENCTYPE}>
-<!-- ENDIF -->
-<table width="100%" cellspacing="0" cellpadding="0" border="0">
-<tr>
- <td width="20%" valign="top">
-
-<!-- IF S_SHOW_PM_BOX and S_POST_ACTION -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_PM_TO}</th>
- </tr>
- <!-- IF not S_ALLOW_MASS_PM -->
- <tr>
- <td class="row1"><b class="genmed">{L_USERNAME}{L_COLON}</b><br />[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</td>
- </tr>
-
- <tr>
- <td class="row2"><input class="post" type="text" name="username_list" size="20" value="" />&nbsp;<input class="post" type="submit" name="add_to" value="{L_ADD}" /></td>
- </tr>
- <!-- ELSE -->
- <tr>
- <td class="row1"><b class="genmed">{L_USERNAMES}{L_COLON}</b></td>
- </tr>
- <!-- EVENT posting_pm_header_find_username_before -->
- <tr>
- <td class="row2"><textarea name="username_list" rows="5" cols="22" tabindex="1"></textarea><br />
- [ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]
- </td>
- </tr>
- <!-- EVENT posting_pm_header_find_username_after -->
- <!-- ENDIF -->
- <!-- IF S_GROUP_OPTIONS -->
- <tr>
- <td class="row1"><b class="genmed">{L_USERGROUPS}{L_COLON}</b></td>
- </tr>
- <tr>
- <td class="row2"><select name="group_list[]" multiple="multiple" size="5" style="width:150px">{S_GROUP_OPTIONS}</select></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_ALLOW_MASS_PM -->
- <tr>
- <td class="row1"><div style="float: {S_CONTENT_FLOW_BEGIN};">&nbsp;<input class="post" type="submit" name="add_bcc" value="{L_ADD_BCC}" tabindex="1" />&nbsp;</div><div style="float: {S_CONTENT_FLOW_END};">&nbsp;<input class="post" type="submit" name="add_to" value="{L_ADD_TO}" tabindex="1" />&nbsp;</div></td>
- </tr>
- <!-- ENDIF -->
- </table>
- <div style="padding: 2px;"></div>
-<!-- ENDIF -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th>{L_OPTIONS}</th>
-</tr>
-
-<!-- BEGIN l_block1 -->
- <tr>
- <!-- IF l_block1.S_SELECTED -->
- <td class="row1"><b class="nav">{l_block1.L_TITLE}</b>
-
- <!-- IF S_PRIVMSGS -->
-
- <!-- the ! at the beginning of the loop name forces the loop to be not a nested one of l_block1 (it gets parsed separately) -->
- <!-- BEGIN !folder -->
- <!-- IF folder.S_FIRST_ROW -->
- <ul class="nav" style="margin: 0; padding: 0; list-style-type: none; line-height: 175%;">
- <!-- ENDIF -->
-
- <!-- IF folder.S_CUR_FOLDER -->
- <li class="row2" style="padding: 1px 0;">&#187; <a href="{folder.U_FOLDER}">{folder.FOLDER_NAME}<!-- IF folder.S_UNREAD_MESSAGES --> ({folder.UNREAD_MESSAGES})<!-- ENDIF --></a></li>
- <!-- ELSE -->
- <li>&#187; <a href="{folder.U_FOLDER}">{folder.FOLDER_NAME}<!-- IF folder.S_UNREAD_MESSAGES --> ({folder.UNREAD_MESSAGES})<!-- ENDIF --></a></li>
- <!-- ENDIF -->
-
- <!-- IF folder.S_LAST_ROW -->
- </ul>
- <hr />
- <!-- ENDIF -->
- <!-- END !folder -->
-
- <!-- ENDIF -->
-
- <ul class="nav" style="margin: 0; padding: 0; list-style-type: none; line-height: 175%;">
- <!-- BEGIN l_block2 -->
- <li>&#187; <!-- IF l_block1.l_block2.S_SELECTED --><b>{l_block1.l_block2.L_TITLE}</b><!-- ELSE --><a href="{l_block1.l_block2.U_TITLE}">{l_block1.l_block2.L_TITLE}</a><!-- ENDIF --></li>
- <!-- END l_block2 -->
- </ul>
- <!-- ELSE -->
- <td class="row2" nowrap="nowrap" onmouseover="this.className='row1'" onmouseout="this.className='row2'" onclick="location.href=this.firstChild.href;"><a class="nav" href="{l_block1.U_TITLE}">{l_block1.L_TITLE}</a>
- <!-- ENDIF -->
- </td>
- </tr>
-<!-- END l_block1 -->
-</table>
-
-<div style="padding: 2px;"></div>
-
-<!-- IF S_SHOW_COLOUR_LEGEND -->
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
- <tr>
- <th colspan="2">{L_MESSAGE_COLOURS}</th>
- </tr>
- <!-- BEGIN pm_colour_info -->
- <tr>
- <!-- IF not pm_colour_info.IMG -->
- <td class="row1 {pm_colour_info.CLASS}" width="5"><img src="images/spacer.gif" width="5" alt="{pm_colour_info.LANG}" /></td>
- <!-- ELSE -->
- <td class="row1" width="25" align="center">{pm_colour_info.IMG}</td>
- <!-- ENDIF -->
- <td class="row1"><span class="genmed">{pm_colour_info.LANG}</span></td>
- </tr>
- <!-- END pm_colour_info -->
- </table>
-
- <div style="padding: 2px;"></div>
-<!-- ENDIF -->
-
-<!-- IF S_ZEBRA_ENABLED and S_ZEBRA_FRIENDS_ENABLED -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{L_FRIENDS}</th>
- </tr>
- <tr>
- <td class="row1" align="center">
-
- <b class="genmed online">{L_FRIENDS_ONLINE}</b>
-
- <ul class="nav" style="margin: 0; padding: 0; list-style-type: none; line-height: 175%;">
- <!-- BEGIN friends_online -->
- <li>{friends_online.USERNAME_FULL}
- <!-- IF S_SHOW_PM_BOX -->
- &nbsp;[ <input class="post" style="font-size: 90%;" type="submit" name="add_to[{friends_online.USER_ID}]" value="{L_ADD}" /> ]
- <!-- ENDIF -->
- </li>
- <!-- BEGINELSE -->
- <li>{L_NO_FRIENDS_ONLINE}</li>
- <!-- END friends_online -->
- </ul>
-
- <hr />
-
- <b class="genmed offline">{L_FRIENDS_OFFLINE}</b>
-
- <ul class="nav" style="margin: 0; padding: 0; list-style-type: none; line-height: 175%;">
- <!-- BEGIN friends_offline -->
- <li>{friends_offline.USERNAME_FULL}
- <!-- IF S_SHOW_PM_BOX -->
- &nbsp;[ <input class="post" style="font-size: 90%;" type="submit" name="add_to[{friends_offline.USER_ID}]" value="{L_ADD}" /> ]
- <!-- ENDIF -->
- </li>
- <!-- BEGINELSE -->
- <li>{L_NO_FRIENDS_OFFLINE}</li>
- <!-- END friends_offline -->
- </ul>
-
- </td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-</td>
-<td><img src="images/spacer.gif" width="4" alt="" /></td>
-<td width="80%" valign="top"><!-- IF not S_PRIVMSGS or S_SHOW_DRAFTS --><form name="ucp" id="ucp" method="post" action="{S_UCP_ACTION}"{S_FORM_ENCTYPE}><!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/ucp_login_link.html b/phpBB/styles/subsilver2/template/ucp_login_link.html
deleted file mode 100644
index 6db9890d8c..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_login_link.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th>{SITENAME} - {L_LOGIN_LINK}</th>
- </tr>
-
- <tr>
- <td class="row1" align="center"><span class="genmed">{L_LOGIN_LINK_EXPLAIN}</span></td>
- </tr>
-
- <!-- IF LOGIN_LINK_ERROR -->
- <tr>
- <td class="row1" align="center"><span class="genmed error">{LOGIN_LINK_ERROR}</span></td>
- </tr>
- <!-- ENDIF -->
-
- <tr>
- <td class="row1">
- <form action="{REGISTER_ACTION}" method="post" id="register">
- <table width="100%" cellspacing="1">
- <tr>
- <th colspan="2">{L_REGISTER}</th>
- </tr>
-
- <tr>
- <td>{S_HIDDEN_FIELDS}<input type="submit" name="register" tabindex="1" value="{L_REGISTER}" class="button1" /></td>
- </tr>
- </table>
- </form>
- </td>
- </tr>
-
- <tr>
- <td class="row1">
- <form action="{LOGIN_ACTION}" method="post" id="login">
- <table width="100%" cellspacing="1">
- <tr>
- <th colspan="2">{L_LOGIN}</th>
- </tr>
-
- <!-- IF LOGIN_ERROR -->
- <tr>
- <td class="row1" align="center" colspan="2"><span class="genmed error">{LOGIN_ERROR}</span></td>
- </tr>
- <!-- ENDIF -->
-
- <tr>
- <td><label for="{USERNAME_CREDENTIAL}">{L_USERNAME}{L_COLON}</label></td>
- <td><input type="text" tabindex="2" name="{USERNAME_CREDENTIAL}" id="{USERNAME_CREDENTIAL}" size="25" value="{LOGIN_USERNAME}" class="inputbox autowidth" /></td>
- </tr>
-
- <tr>
- <td><label for="{PASSWORD_CREDENTIAL}">{L_PASSWORD}{L_COLON}</label></td>
- <td><input type="password" tabindex="3" id="{PASSWORD_CREDENTIAL}" name="{PASSWORD_CREDENTIAL}" size="25" class="inputbox autowidth" autocomplete="off" /></td>
- </tr>
-
- <!-- IF CAPTCHA_TEMPLATE and S_CONFIRM_CODE -->
- <!-- DEFINE $CAPTCHA_TAB_INDEX = 4 -->
- <!-- INCLUDE {CAPTCHA_TEMPLATE} -->
- <!-- ENDIF -->
-
- {S_LOGIN_REDIRECT}
- <tr>
- <td>&nbsp;</td>
- <td>{S_HIDDEN_FIELDS}<input type="submit" name="login" tabindex="5" value="{L_LOGIN}" class="button1" /></td>
- </tr>
- </table>
- </form>
- </td>
- </tr>
-</table>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_main_bookmarks.html b/phpBB/styles/subsilver2/template/ucp_main_bookmarks.html
deleted file mode 100644
index e91417503f..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_main_bookmarks.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="4">{L_UCP}</th>
-</tr>
-<tr>
- <td class="row1" colspan="4" align="center"><span class="genmed">{L_BOOKMARKS_EXPLAIN}</span></td>
-</tr>
-<!-- IF .topicrow -->
-<tr>
- <th colspan="4">{L_BOOKMARKS}</th>
-</tr>
-<!-- ENDIF -->
-
-<!-- IF S_NO_DISPLAY_BOOKMARKS -->
- <tr class="row1">
- <td colspan="4" align="center"><b class="genmed">{L_BOOKMARKS_DISABLED}</b></td>
- </tr>
-<!-- ELSE -->
-
- <!-- IF TOTAL_TOPICS -->
- <tr>
- <td class="row3" colspan="4">
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {TOTAL_TOPICS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
-
- <!-- BEGIN topicrow -->
-
- <!-- IF topicrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td style="padding: 4px;" width="20" align="center" valign="middle">{topicrow.TOPIC_FOLDER_IMG}</td>
- <!-- IF topicrow.S_DELETED_TOPIC -->
- <td class="postdetails" style="padding: 4px" width="100%" colspan="2">{L_DELETED_TOPIC}</td>
- <!-- ELSE -->
- <td style="padding: 4px;" width="100%" valign="top">
- <p class="topictitle"><!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF -->{topicrow.ATTACH_ICON_IMG} <a href="{topicrow.U_VIEW_TOPIC}">{topicrow.TOPIC_TITLE}</a></p>
- <!-- IF topicrow.S_GLOBAL_TOPIC --><span class="gensmall">{L_GLOBAL_ANNOUNCEMENT}</span><!-- ELSE --><span class="gensmall"><b>{L_FORUM}{L_COLON} </b><a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a></span><!-- ENDIF -->
- <!-- IF .topicrow.pagination -->
- <p class="gensmall"> [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON}
- <!-- BEGIN pagination -->
- <!-- IF topicrow.pagination.S_IS_PREV -->
- <!-- ELSEIF topicrow.pagination.S_IS_CURRENT --><strong>{topicrow.pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF topicrow.pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF topicrow.pagination.S_IS_NEXT -->
- <!-- ELSE --><a href="{topicrow.pagination.PAGE_URL}">{topicrow.pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
- ] </p>
- <!-- ENDIF -->
- </td>
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap">
- <p class="topicdetails">{topicrow.LAST_POST_TIME}</p>
- <p class="topicdetails">{topicrow.LAST_POST_AUTHOR_FULL}
- <a href="{topicrow.U_LAST_POST}">{LAST_POST_IMG}</a>
- </p>
- </td>
- <!-- ENDIF -->
- <td style="padding: 4px;"> <input type="checkbox" class="radio" name="t[{topicrow.TOPIC_ID}]" /> </td>
- </tr>
- <!-- BEGINELSE -->
- <tr class="row1">
- <td colspan="4" align="center"><b class="genmed">{L_NO_BOOKMARKS}</b></td>
- </tr>
- <!-- END topicrow -->
-
- <!-- IF .topicrow -->
- <tr>
- <td class="cat" colspan="5" align="{S_CONTENT_FLOW_END}"><input class="btnlite" type="submit" name="unbookmark" value="{L_REMOVE_BOOKMARK_MARKED}" />&nbsp;</td>
- </tr>
- <!-- ENDIF -->
- <!-- ENDIF -->
-</table>
-
-<!-- IF not S_NO_DISPLAY_BOOKMARKS and .topicrow -->
- <div class="gensmall" style="float: {S_CONTENT_FLOW_END}; padding-top: 2px;"><b><a href="#" onclick="marklist('ucp', 't', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('ucp', 't', false); return false;">{L_UNMARK_ALL}</a></b></div>
-<!-- ENDIF -->
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_main_drafts.html b/phpBB/styles/subsilver2/template/ucp_main_drafts.html
deleted file mode 100644
index d63d678250..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_main_drafts.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="4">{L_UCP}</th>
-</tr>
-<tr>
- <td class="row1" colspan="4" align="center"><span class="genmed">{L_DRAFTS_EXPLAIN}</span></td>
-</tr>
-
-<!-- IF ERROR -->
- <tr>
- <td class="row1" colspan="2" align="center"><span class="genmed error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF not S_EDIT_DRAFT -->
-
- <!-- IF S_DRAFT_ROWS -->
- <tr>
- <th>{L_SAVE_DATE}</th>
- <th>{L_DRAFT_TITLE}</th>
- <th>{L_OPTIONS}</th>
- <th>{L_DELETE}</th>
- </tr>
- <!-- ENDIF -->
-
- <!-- BEGIN draftrow -->
-
- <!-- IF draftrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td class="postdetails" style="padding: 4px;" nowrap="nowrap">{draftrow.DATE}</td>
- <td style="padding: 4px;" valign="top" width="100%">
- <p class="topictitle">{draftrow.DRAFT_SUBJECT}</p>
- <!-- IF draftrow.S_LINK_TOPIC --><span class="gensmall">{L_TOPIC}{L_COLON} <a href="{draftrow.U_VIEW}">{draftrow.TITLE}</a></span>
- <!-- ELSEIF draftrow.S_LINK_FORUM --><span class="gensmall">{L_FORUM}{L_COLON} <a href="{draftrow.U_VIEW}">{draftrow.TITLE}</a></span>
- <!-- ELSEIF draftrow.S_LINK_PM --><span class="gensmall">{L_PRIVATE_MESSAGE}</span>
- <!-- ELSE --><span class="gensmall">{L_NO_TOPIC_FORUM}</span><!-- ENDIF -->
- </td>
- <td style="padding: 4px;" align="center" nowrap="nowrap"><span class="genmed"><!-- IF draftrow.U_INSERT --><a href="{draftrow.U_INSERT}">{L_LOAD_DRAFT}</a><br /><!-- ENDIF --><a href="{draftrow.U_VIEW_EDIT}">{L_VIEW_EDIT}</a></span></td>
- <td style="padding: 4px;" align="center"><input type="checkbox" class="radio" name="d[{draftrow.DRAFT_ID}]" /></td>
- </tr>
- <!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="4" align="center"><b class="genmed">{L_NO_SAVED_DRAFTS}</b></td>
- </tr>
- <!-- END draftrow -->
-
- <!-- IF S_DRAFT_ROWS -->
- <tr>
- <td class="cat" colspan="4" align="{S_CONTENT_FLOW_END}"><input class="btnlite" type="submit" name="delete" value="{L_DELETE_MARKED}" />&nbsp;</td>
- </tr>
- <!-- ENDIF -->
-
-<!-- ELSEIF S_EDIT_DRAFT -->
- <tr>
- <td class="row1" width="22%"><b class="genmed">{L_SUBJECT}{L_COLON}</b></td>
- <td class="row2"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="64" tabindex="2" value="{DRAFT_SUBJECT}" /></td>
- </tr>
- <tr>
- <td class="row1" width="22%"><b class="genmed">{L_MESSAGE}{L_COLON} </b><br /><span class="gensmall">{L_EDIT_DRAFT_EXPLAIN}</span></td>
- <td class="row2">
- <script type="text/javascript">
- // <![CDATA[
- var form_name = 'ucp';
- var text_name = 'message';
- // ]]>
- </script>
- <table cellspacing="0" cellpadding="2" border="0">
- <!-- INCLUDE posting_buttons.html -->
- <tr>
- <td colspan="9"><textarea class="post" name="message" rows="10" cols="70" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();">{DRAFT_MESSAGE}</textarea></td>
- </tr>
- <tr>
- <td colspan="9">
- <table cellspacing="0" cellpadding="0" border="0" width="100%">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" id="color_palette_placeholder" data-orientation="h" data-width="11" data-height="10" data-bbcode="true">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr class="row1">
- <td colspan="9" align="{S_CONTENT_FLOW_BEGIN}"><p class="topictitle"><a href="{S_UCP_ACTION}">{L_BACK_TO_DRAFTS}</a></p></td>
- </tr>
- <tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
- </tr>
-<!-- ENDIF -->
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_main_front.html b/phpBB/styles/subsilver2/template/ucp_main_front.html
deleted file mode 100644
index 7fc906a126..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_main_front.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="3">{L_UCP}</th>
-</tr>
-<tr>
- <td class="row1" colspan="3" align="center"><p class="genmed">{L_UCP_WELCOME}</p></td>
-</tr>
-<tr>
- <th colspan="3">{L_IMPORTANT_NEWS}</th>
-</tr>
-
-<!-- BEGIN topicrow -->
-
- <!-- IF topicrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td class="row1" width="25" align="center">{topicrow.TOPIC_FOLDER_IMG}</td>
- <td class="row1" width="100%">
- <p class="topictitle"><!-- IF topicrow.S_UNREAD --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF -->{topicrow.ATTACH_ICON_IMG} <a href="{topicrow.U_VIEW_TOPIC}">{topicrow.TOPIC_TITLE}</a></p><p class="gensmall">{topicrow.GOTO_PAGE}</p>
- </td>
- <td class="row1" width="120" align="center" nowrap="nowrap">
- <p class="topicdetails">{topicrow.LAST_POST_TIME}</p>
- <p class="topicdetails">{topicrow.LAST_POST_AUTHOR_FULL}
- <a href="{topicrow.U_LAST_POST}">{LAST_POST_IMG}</a>
- </p>
- </td>
- </tr>
-<!-- BEGINELSE -->
- <tr class="row1">
- <td align="center" colspan="3"><b class="gen">{L_NO_IMPORTANT_NEWS}</b></td>
- </tr>
-<!-- END topicrow -->
-
-<tr>
- <th colspan="3">{L_YOUR_DETAILS}</th>
-</tr>
-<tr>
-<!-- EVENT ucp_main_front_user_activity_before -->
- <td class="row1" colspan="3">
- <table width="100%" cellspacing="1" cellpadding="4">
- <tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="genmed">{L_JOINED}{L_COLON} </b></td>
- <td width="100%"><b class="gen">{JOINED}</b></td>
- </tr>
- <tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="genmed">{L_TOTAL_POSTS}{L_COLON} </b></td>
- <td><!-- IF POSTS_PCT --><b class="gen">{POSTS}</b><br /><span class="genmed">[{POSTS_PCT} / {POSTS_DAY}]<!-- IF S_DISPLAY_SEARCH --><br /><a href="{U_SEARCH_SELF}">{L_SEARCH_YOUR_POSTS}</a><!-- ENDIF --></span><!-- ELSE --><b class="gen">{POSTS}<b><!-- ENDIF --></td>
- </tr>
- <!-- IF S_SHOW_ACTIVITY -->
- <tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="genmed">{L_ACTIVE_IN_FORUM}{L_COLON} </b></td>
- <td><!-- IF ACTIVE_FORUM != '' --><b><a class="gen" href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></b><br /><span class="genmed">[ {ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td>
- </tr>
- <tr>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><b class="genmed">{L_ACTIVE_IN_TOPIC}{L_COLON} </b></td>
- <td><!-- IF ACTIVE_TOPIC != '' --><b><a class="gen" href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></b><br /><span class="genmed">[ {ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF WARNINGS -->
- <tr>
- <td align="{S_CONTENT_FLOW_END}" valign="middle" nowrap="nowrap"><b class="genmed">{L_YOUR_WARNINGS}{L_COLON} </b></td>
- <td class="genmed">{WARNING_IMG} [ <b>{WARNINGS}</b> ]</td>
- </tr>
- <!-- ENDIF -->
- </table>
- </td>
-<!-- EVENT ucp_main_front_user_activity_after -->
-</tr>
-<tr>
- <td class="cat" colspan="3">&nbsp;</td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_main_subscribed.html b/phpBB/styles/subsilver2/template/ucp_main_subscribed.html
deleted file mode 100644
index c6ae1b6cab..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_main_subscribed.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="4">{L_UCP}</th>
-</tr>
-<tr>
- <td class="row1" colspan="4" align="center"><span class="genmed">{L_WATCHED_EXPLAIN}</span></td>
-</tr>
-<!-- IF S_FORUM_NOTIFY -->
- <tr>
- <th colspan="4">{L_WATCHED_FORUMS}</th>
- </tr>
-
- <!-- BEGIN forumrow -->
-
- <!-- IF forumrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td style="padding: 4px;" width="20" align="center" valign="middle">{forumrow.FORUM_FOLDER_IMG}</td>
- <td style="padding: 4px;" width="100%"><p class="topictitle"><a href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a></p></td>
- <td class="gensmall" style="padding: 4px;" align="center" valign="middle" nowrap="nowrap"><!-- IF forumrow.LAST_POST_TIME -->{forumrow.LAST_POST_TIME}<br />{forumrow.LAST_POST_AUTHOR_FULL} <a href="{forumrow.U_LAST_POST}" class="imageset">{LAST_POST_IMG}</a><!-- ELSE -->{L_NO_POSTS}<!-- ENDIF --></td>
- <td style="padding: 4px;"> <input type="checkbox" class="radio" name="f[{forumrow.FORUM_ID}]" /> </td>
- </tr>
- <!-- BEGINELSE -->
- <tr class="row1">
- <td colspan="4" align="center"><b class="genmed">{L_NO_WATCHED_FORUMS}</b></td>
- </tr>
- <!-- END forumrow -->
-<!-- ENDIF -->
-<!-- IF S_TOPIC_NOTIFY -->
- <tr>
- <th colspan="4">{L_WATCHED_TOPICS}</th>
- </tr>
-
- <!-- IF TOTAL_TOPICS -->
- <tr>
- <td class="row3" colspan="4">
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {TOTAL_TOPICS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
-
- <!-- BEGIN topicrow -->
-
- <!-- IF topicrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td style="padding: 4px;" width="20" align="center" valign="middle">{topicrow.TOPIC_FOLDER_IMG}</td>
- <td style="padding: 4px;" width="100%" valign="top">
- <p class="topictitle">
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="imageset">{NEWEST_POST_IMG}</a> <!-- ENDIF -->{topicrow.ATTACH_ICON_IMG}<a href="{topicrow.U_VIEW_TOPIC}">{topicrow.TOPIC_TITLE}</a>
- </p>
- <!-- IF topicrow.S_GLOBAL_TOPIC --><span class="gensmall">{L_GLOBAL_ANNOUNCEMENT}</span><!-- ELSE --><span class="gensmall"><b>{L_FORUM}{L_COLON} </b><a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a></span><!-- ENDIF -->
- <!-- IF .topicrow.pagination -->
- <p class="gensmall"> [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON}
- <!-- BEGIN pagination -->
- <!-- IF topicrow.pagination.S_IS_PREV -->
- <!-- ELSEIF topicrow.pagination.S_IS_CURRENT --><strong>{topicrow.pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF topicrow.pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF topicrow.pagination.S_IS_NEXT -->
- <!-- ELSE --><a href="{topicrow.pagination.PAGE_URL}">{topicrow.pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
- ] </p>
- <!-- ENDIF -->
- </td>
- <td style="padding: 4px;" align="{S_CONTENT_FLOW_BEGIN}" valign="top" nowrap="nowrap">
- <p class="topicdetails">{topicrow.LAST_POST_TIME}</p>
- <p class="topicdetails">{topicrow.LAST_POST_AUTHOR_FULL}
- <a href="{topicrow.U_LAST_POST}" class="imageset">{LAST_POST_IMG}</a>
- </p>
- </td>
- <td style="padding: 4px;"> <input type="checkbox" class="radio" name="t[{topicrow.TOPIC_ID}]" /> </td>
- </tr>
- <!-- BEGINELSE -->
- <tr class="row1">
- <td colspan="4" align="center"><b class="genmed">{L_NO_WATCHED_TOPICS}</b></td>
- </tr>
- <!-- END topicrow -->
-<!-- ENDIF -->
-
-<!-- IF .topicrow or .forumrow -->
-<tr>
- <td class="cat" colspan="4" align="{S_CONTENT_FLOW_END}"><input class="btnlite" type="submit" name="unwatch" value="{L_UNWATCH_MARKED}" />&nbsp;</td>
-</tr>
-<!-- ENDIF -->
-</table>
-<!-- IF .topicrow or .forumrow -->
-<div class="gensmall" style="float: {S_CONTENT_FLOW_END}; padding-top: 2px;"><b><a href="#" onclick="marklist('ucp', 't', true); marklist('ucp', 'f', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('ucp', 't', false);marklist('ucp', 'f', false); return false;">{L_UNMARK_ALL}</a></b></div>
-<!-- ENDIF -->
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_notifications.html b/phpBB/styles/subsilver2/template/ucp_notifications.html
deleted file mode 100644
index b0d2925b68..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_notifications.html
+++ /dev/null
@@ -1,141 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<form id="ucp" method="post" action="{S_UCP_ACTION}"{S_FORM_ENCTYPE}>
-
-<!-- IF MODE == 'notification_options' -->
- <table width="100%" cellspacing="1">
- <tr>
- <th colspan="{NOTIFICATION_TYPES_COLS}">{TITLE}</th>
- </tr>
- <tr>
- <td class="row1" colspan="{NOTIFICATION_TYPES_COLS}" align="center"><span class="genmed">{TITLE_EXPLAIN}</span></td>
- </tr>
- <tr>
- <th>{L_NOTIFICATION_TYPE}</th>
- <th width="10%">{L_NOTIFICATIONS}</th>
- <!-- BEGIN notification_methods -->
- <th width="10%">{notification_methods.NAME}</th>
- <!-- END notification_methods -->
- </tr>
-
- <!-- BEGIN notification_types -->
- <!-- IF notification_types.GROUP_NAME -->
- <tr>
- <td class="row3" colspan="{NOTIFICATION_TYPES_COLS}">{notification_types.GROUP_NAME}</td>
- </tr>
- <!-- ELSE -->
- <!-- IF notification_types.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td>
- {notification_types.NAME}
- <!-- IF notification_types.EXPLAIN --><br />&nbsp; &nbsp;{notification_types.EXPLAIN}<!-- ENDIF -->
- </td>
- <td align="center"><input type="checkbox" name="{notification_types.TYPE}_notification"<!-- IF notification_types.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /></td>
- <!-- BEGIN notification_methods -->
- <td align="center"><input type="checkbox" name="{notification_types.TYPE}_{notification_methods.METHOD}"<!-- IF notification_methods.SUBSCRIBED --> checked="checked"<!-- ENDIF --> /></td>
- <!-- END notification_methods -->
- </tr>
- <!-- ENDIF -->
- <!-- END notification_types -->
- <tr>
- <td class="cat" colspan="{NOTIFICATION_TYPES_COLS}" align="center">
- <input type="hidden" name="form_time" value="{FORM_TIME}" />
- {S_HIDDEN_FIELDS}
- <input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;
- <input class="btnlite" type="reset" value="{L_RESET}" name="reset" />
- {S_FORM_TOKEN}
- </td>
- </tr>
- </table>
-<!-- ELSE -->
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
- <tr>
- <td class="row1">
- <table border="0" cellspacing="0" cellpadding="0" width="100%">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}">
- <!-- IF TOTAL_COUNT -->
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}</td>
- <td class="gensmall" nowrap="nowrap" width="100%">&nbsp;{L_NOTIFICATIONS} [ <b>{TOTAL_COUNT}</b> ]&nbsp;</td>
- </tr>
- </table>
- <!-- ENDIF -->
- </td>
- <td align="{S_CONTENT_FLOW_END}"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
-
- <div class="notification_list">
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat" colspan="3">
- <table width="100%" cellspacing="0">
- <tr class="nav">
- <td align="{S_CONTENT_FLOW_END}" valign="middle"><!-- IF U_MARK_ALL --><a href="{U_MARK_ALL}">{L_NOTIFICATIONS_MARK_ALL_READ}</a><!-- ENDIF --></td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <th colspan="2">{L_NOTIFICATIONS}</th>
- <th width="15%">{L_MARK_READ}</th>
- </tr>
- <!-- BEGIN notification_list -->
- <tr class="row<!-- IF notification_list.UNREAD -->3<!-- ELSEIF notification_list.S_ROW_COUNT is even -->1<!-- ELSE -->2<!-- ENDIF -->">
- <td width="50">
- <!-- IF notification_list.AVATAR -->{notification_list.AVATAR}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF -->
- </td>
- <td valign="top">
- <span class="gen">
- <!-- IF notification_list.URL --><a href="<!-- IF notification_list.UNREAD -->{notification_list.U_MARK_READ}<!-- ELSE -->{notification_list.URL}<!-- ENDIF -->"><!-- ENDIF -->
- {notification_list.FORMATTED_TITLE}<!-- IF notification_list.REFERENCE --> {notification_list.REFERENCE}<!-- ENDIF -->
- <!-- IF notification_list.URL --></a><!-- ENDIF --><br />
- <!-- IF notification_list.FORUM --><span class="notifications_forum">{notification_list.FORUM}</span><br /><!-- ENDIF -->
- <!-- IF notification_list.REASON --><span class="notifications_reason">{notification_list.REASON}</span><br /><!-- ENDIF -->
- <span class="notifications_time">{notification_list.TIME}</span>
- </span>
- </td>
- <td align="center">
- <input type="checkbox" name="mark[]" value="{notification_list.NOTIFICATION_ID}"<!-- IF not notification_list.UNREAD --> disabled="disabled"<!-- ENDIF --> />
- </td>
- </tr>
- <!-- END notification_list -->
- <tr>
- <td class="cat" colspan="3" align="center">
- <input type="hidden" name="form_time" value="{FORM_TIME}" />
- {S_HIDDEN_FIELDS}
- <input class="btnmain" type="submit" name="submit" value="{L_MARK_READ}" />
- {S_FORM_TOKEN}
- </td>
- </tr>
- </table>
- </div>
-
- <!-- IF .pagination -->
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
- <tr>
- <td class="row1">
- <table border="0" cellspacing="0" cellpadding="0" width="100%">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}">
- <!-- INCLUDE pagination.html -->
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- <!-- ENDIF -->
-<!-- ENDIF -->
-
-<!-- IF .notifications -->
-<div class="gensmall" style="float: {S_CONTENT_FLOW_END}; padding-top: 2px;"><b><a href="#" onclick="$('#ucp input:checkbox').prop('checked', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="$('#ucp input:checkbox').prop('checked', false); return false;">{L_UNMARK_ALL}</a></b></div>
-<!-- ENDIF -->
-
-</form>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_history.html b/phpBB/styles/subsilver2/template/ucp_pm_history.html
deleted file mode 100644
index b478431fa5..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_history.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!-- EVENT ucp_pm_history_review_before -->
-<script type="text/javascript">
-// <![CDATA[
- bbcodeEnabled = {S_BBCODE_ALLOWED};
-// ]]>
-</script>
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th align="center">{L_MESSAGE_HISTORY}</th>
-</tr>
-<tr>
- <td class="row1"><div style="overflow: auto; width: 100%; height: 300px;">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th width="22%">{L_AUTHOR}</th>
- <th>{L_MESSAGE}</th>
- </tr>
- <!-- BEGIN history_row -->
- <!-- IF history_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td rowspan="2" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><a name="{history_row.MSG_ID}" class="anchor"></a>
- <table width="150" cellspacing="0">
- <tr>
- <td align="center" colspan="2"><span class="postauthor">{history_row.MESSAGE_AUTHOR_FULL}</span></td>
- </tr>
- </table>
- </td>
- <td width="100%"<!-- IF history_row.S_CURRENT_MSG --> class="current"<!-- ENDIF -->>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_BEGIN};"><b>{L_PM_SUBJECT}{L_COLON}</b>&nbsp;{history_row.SUBJECT}</div><div class="gensmall" style="float: {S_CONTENT_FLOW_END};"><b>{L_FOLDER}{L_COLON}</b>&nbsp;{history_row.FOLDER}</div>
- </td>
- </tr>
-
- <!-- IF history_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td valign="top">
- <table width="100%" cellspacing="0">
- <tr>
- <td valign="top">
- <table width="100%" cellspacing="0" cellpadding="2">
- <tr>
- <td><div class="postbody"><!-- 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></td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td>
- <table width="100%" cellspacing="0">
- <tr valign="middle">
- <td width="100%">&nbsp;</td>
- <td width="10" nowrap="nowrap">{history_row.MINI_POST_IMG}</td>
- <td class="gensmall" nowrap="nowrap"><b>{L_SENT_AT}{L_COLON}</b> {history_row.SENT_DATE}</td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
-
- <!-- IF history_row.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td class="gensmall"><a href="{history_row.U_VIEW_MESSAGE}">{L_VIEW_PM}</a></td>
- <td>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_BEGIN};">
- &nbsp;<!-- IF history_row.U_PROFILE --><a href="{history_row.U_PROFILE}" class="imageset">{PROFILE_IMG}</a> <!-- ENDIF -->
- <!-- IF history_row.U_EMAIL --><a href="{history_row.U_EMAIL}" class="imageset">{EMAIL_IMG}</a> <!-- ENDIF -->&nbsp;
- </div>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_END};">
- <!-- EVENT ucp_pm_history_post_buttons_before -->
- <!-- IF history_row.U_QUOTE or history_row.MESSAGE_AUTHOR_QUOTE --> <a <!-- IF history_row.U_QUOTE -->href="{history_row.U_QUOTE}"<!-- ELSE -->href="#" onclick="addquote({history_row.MSG_ID}, '{history_row.MESSAGE_AUTHOR_QUOTE}', '{LA_WROTE}'); return false;"<!-- ENDIF --> class="imageset">{QUOTE_IMG}</a> <!-- ENDIF -->
- <!-- IF history_row.U_POST_REPLY_PM --><a href="{history_row.U_POST_REPLY_PM}" class="imageset">{REPLY_IMG}</a><!-- ENDIF -->&nbsp;
- <!-- EVENT ucp_pm_history_post_buttons_after -->
- </div>
- </td>
- </tr>
- <tr>
- <td class="spacer" colspan="2"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
- </tr>
- <!-- END history_row -->
- </table>
- </div></td>
-</tr>
-</table>
-<!-- EVENT ucp_pm_history_review_after -->
-
-<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_message_footer.html b/phpBB/styles/subsilver2/template/ucp_pm_message_footer.html
deleted file mode 100644
index 20c5c7fe9f..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_message_footer.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
-<!-- IF not S_VIEW_MESSAGE -->
- {S_FORM_TOKEN}
- </form>
-<!-- ENDIF -->
-
-<table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
-<tr>
- <td class="row1">
- <table border="0" cellspacing="0" cellpadding="0" width="100%">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}"><!-- INCLUDE pagination.html -->
- <!-- IF S_VIEW_MESSAGE -->
- <span class="gensmall">
- <!-- IF U_PRINT_PM --><a href="{U_PRINT_PM}" title="{L_PRINT_PM}">{L_PRINT_PM}</a><!-- IF U_FORWARD_PM --> | <!-- ENDIF --><!-- ENDIF -->
- <!-- IF U_FORWARD_PM --><a href="{U_FORWARD_PM}" title="{L_FORWARD_PM}">{L_FORWARD_PM}</a><!-- ENDIF -->
- <!-- IF U_POST_REPLY_PM and S_PM_RECIPIENTS gt 1 --><!-- IF U_PRINT_PM or U_FORWARD_PM --> | <!-- ENDIF --><a title="{L_REPLY_TO_ALL}" href="{U_POST_REPLY_ALL}">{L_REPLY_TO_ALL}</a><!-- ENDIF -->
- </span>
- <!-- ENDIF -->
- </td>
- <td align="{S_CONTENT_FLOW_END}" nowrap="nowrap">
- <!-- IF S_VIEW_MESSAGE -->
- <!-- IF not S_SPECIAL_FOLDER -->
- <form name="movepm" method="post" action="{S_PM_ACTION}" style="margin:0px">
- <input type="hidden" name="marked_msg_id[]" value="{MSG_ID}" />
- <input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
- <input type="hidden" name="p" value="{MSG_ID}" />
- <select name="dest_folder">{S_TO_FOLDER_OPTIONS}</select>&nbsp;<input class="btnlite" type="submit" name="move_pm" value="{L_MOVE_TO_FOLDER}" />
- {S_FORM_TOKEN}
- </form>
- <!-- ENDIF -->
- <!-- ELSE -->
- <form name="sortmsg" method="post" action="{S_PM_ACTION}" style="margin:0px">
- <span class="gensmall">{L_DISPLAY_MESSAGES}{L_COLON}</span> {S_SELECT_SORT_DAYS} <span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} <input class="btnlite" type="submit" name="sort" value="{L_GO}" />
- {S_FORM_TOKEN}
- </form>
- <!-- ENDIF -->
- </td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
-
-<!-- IF not S_VIEW_MESSAGE -->
- <div style="float: {S_CONTENT_FLOW_END};"><b class="gensmall"><a href="#" onclick="marklist('viewfolder', 'marked_msg_id', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('viewfolder', 'marked_msg_id', false); return false;">{L_UNMARK_ALL}</a></b></div>
-<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_message_header.html b/phpBB/styles/subsilver2/template/ucp_pm_message_header.html
deleted file mode 100644
index 370fa673dd..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_message_header.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-<table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
-<tr>
- <td class="row1">
- <table border="0" cellspacing="0" cellpadding="0" width="100%">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}">
- <!-- IF TOTAL_MESSAGES -->
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <!-- IF FOLDER_MAX_MESSAGES neq 0 -->
- <td class="gensmall" nowrap="nowrap" width="100%">&nbsp;[ <b>{FOLDER_CUR_MESSAGES}</b>/{FOLDER_MAX_MESSAGES} {L_MESSAGES} ({FOLDER_PERCENT}%) ]&nbsp;</td>
- <!-- ELSE -->
- <td class="gensmall" nowrap="nowrap" width="100%">&nbsp;[ <b>{FOLDER_CUR_MESSAGES}</b> {L_MESSAGES} ]&nbsp;</td>
- <!-- ENDIF -->
- </tr>
- </table>
- <!-- ENDIF -->
-
- <!-- IF S_VIEW_MESSAGE -->
- <span class="gensmall">
- <!-- IF S_DISPLAY_HISTORY -->
- <!-- IF U_VIEW_PREVIOUS_HISTORY --><a href="{U_VIEW_PREVIOUS_HISTORY}">{L_VIEW_PREVIOUS_HISTORY}</a> | <!-- ENDIF --><!-- IF U_VIEW_NEXT_HISTORY --><a href="{U_VIEW_NEXT_HISTORY}">{L_VIEW_NEXT_HISTORY}</a> | <!-- ENDIF -->
- <!-- ENDIF --><a href="{U_PREVIOUS_PM}">{L_VIEW_PREVIOUS_PM}</a> | <a href="{U_NEXT_PM}">{L_VIEW_NEXT_PM}</a>&nbsp;
- </span>
- <!-- ENDIF -->
- </td>
- <td align="{S_CONTENT_FLOW_END}"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_options.html b/phpBB/styles/subsilver2/template/ucp_pm_options.html
deleted file mode 100644
index beb867c75a..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_options.html
+++ /dev/null
@@ -1,192 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<!-- IF ERROR_MESSAGE or NOTIFICATION_MESSAGE -->
- <table border="0" cellspacing="0" cellpadding="0" width="100%">
- <tr>
- <td class="row3" align="center">
- <!-- IF ERROR_MESSAGE --><span class="genmed error">{ERROR_MESSAGE}</span><!-- ENDIF -->
- <!-- IF NOTIFICATION_MESSAGE --><span class="genmed error">{NOTIFICATION_MESSAGE}</span><!-- ENDIF -->
- </td>
- </tr>
- </table>
- <div style="padding: 2px;"></div>
-<!-- ENDIF -->
-
-<form name="ucp" method="post" action="{S_UCP_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="3">{L_ADD_NEW_RULE}</th>
-</tr>
-<!-- IF S_CHECK_DEFINED -->
- <tr>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><b class="gen">{L_IF}{L_COLON}</b></td>
- <td class="row2" align="center" valign="top"><!-- IF S_CHECK_SELECT --><select name="check_option">{S_CHECK_OPTIONS}</select><!-- ELSE --><b class="gen">{CHECK_CURRENT}</b><input type="hidden" name="check_option" value="{CHECK_OPTION}" /><!-- ENDIF --></td>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_END}" valign="top"><!-- IF S_CHECK_SELECT --><input type="submit" name="next" value="{L_NEXT_STEP}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- </tr>
-<!-- ENDIF -->
-<!-- IF S_RULE_DEFINED -->
- <tr>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><!-- IF S_RULE_SELECT --><input type="submit" name="back[rule]" value="{L_PREVIOUS_STEP}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- <td class="row2" align="center" valign="top"><!-- IF S_RULE_SELECT --><select name="rule_option">{S_RULE_OPTIONS}</select><!-- ELSE --><b class="gen">{RULE_CURRENT}</b><input type="hidden" name="rule_option" value="{RULE_OPTION}" /><!-- ENDIF --></td>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_END}" valign="top"><!-- IF S_RULE_SELECT --><input type="submit" name="next" value="{L_NEXT_STEP}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_COND_DEFINED -->
- <!-- IF S_COND_SELECT or COND_CURRENT -->
- <tr>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><!-- IF S_COND_SELECT --><input type="submit" name="back[cond]" value="{L_PREVIOUS_STEP}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- <td class="row2" align="center" valign="top">
- <!-- IF S_COND_SELECT -->
- <!-- IF S_TEXT_CONDITION -->
- <input type="text" name="rule_string" value="{CURRENT_STRING}" size="30" maxlength="250" class="post" />
- <!-- ELSEIF S_USER_CONDITION -->
- <input type="text" class="post" name="rule_string" value="{CURRENT_STRING}" size="20" />&nbsp;<span class="gensmall">[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</span>
- <!-- ELSEIF S_GROUP_CONDITION -->
- <input type="hidden" name="rule_string" value="{CURRENT_STRING}" /><!-- IF S_GROUP_OPTIONS --><select name="rule_group_id">{S_GROUP_OPTIONS}</select><!-- ELSE -->{L_NO_GROUPS}<!-- ENDIF -->
- <!-- ENDIF -->
- <!-- ELSE -->
- <b class="gen">{COND_CURRENT}</b>
- <input type="hidden" name="rule_string" value="{CURRENT_STRING}" /><input type="hidden" name="rule_user_id" value="{CURRENT_USER_ID}" /><input type="hidden" name="rule_group_id" value="{CURRENT_GROUP_ID}" />
- <!-- ENDIF -->
- </td>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_END}" valign="top"><!-- IF S_COND_SELECT --><input type="submit" name="next" value="{L_NEXT_STEP}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- </tr>
- <!-- ENDIF -->
- <input type="hidden" name="cond_option" value="{COND_OPTION}" />
-<!-- ENDIF -->
-
-<!-- IF NONE_CONDITION --><input type="hidden" name="cond_option" value="none" /><!-- ENDIF -->
-
-<!-- IF S_ACTION_DEFINED -->
- <tr>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_BEGIN}" valign="top"><!-- IF S_ACTION_SELECT --><input type="submit" name="back[action]" value="{L_PREVIOUS_STEP}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- <td class="row2" align="center" valign="top"><!-- IF S_ACTION_SELECT --><select name="action_option">{S_ACTION_OPTIONS}</select><!-- ELSE --><b class="gen">{ACTION_CURRENT}</b><input type="hidden" name="action_option" value="{ACTION_OPTION}" /><!-- ENDIF --></td>
- <td class="row1" width="50" align="{S_CONTENT_FLOW_END}" valign="top"><!-- IF S_ACTION_SELECT --><input type="submit" name="add_rule" value="{L_ADD_RULE}" class="btnlite" /><!-- ELSE -->&nbsp;<!-- ENDIF --></td>
- </tr>
-<!-- ENDIF -->
-</table>
-
-<div style="padding: 2px;"></div>
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="6">{L_DEFINED_RULES}</th>
-</tr>
-<!-- BEGIN rule -->
- <tr>
- <td class="row1" width="25" align="center"><span class="gen">#{rule.COUNT}</span></td>
- <td class="row2" width="120"><span class="gen"><strong>{L_IF}</strong> {rule.CHECK}</span></td>
- <td class="row1" width="120"><span class="gen">{rule.RULE}</span></td>
- <td class="row2" width="120"><span class="gen"><!-- IF rule.STRING -->{rule.STRING}<!-- ENDIF --></span></td>
- <td class="row1"><span class="gen">{rule.ACTION}<!-- IF rule.FOLDER --> -&gt; {rule.FOLDER}<!-- ENDIF --></span></td>
- <td class="row2" width="25"><input type="submit" name="delete_rule[{rule.RULE_ID}]" value="{L_DELETE_RULE}" class="btnlite" /></td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td colspan="6" class="row3" align="center"><span class="gen">{L_NO_RULES_DEFINED}</span></td>
- </tr>
-<!-- END rule -->
-</table>
-
-<div style="padding: 2px;"></div>
-
-<!-- IF S_FOLDER_OPTIONS -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="2">{L_RENAME_FOLDER}</th>
- </tr>
- <tr>
- <td class="row1" width="200"><b class="gen">{L_RENAME_FOLDER}{L_COLON} </b></td>
- <td class="row1"><select name="rename_folder_id">{S_FOLDER_OPTIONS}</select></td>
- </tr>
- <tr>
- <td class="row1" width="200"><b class="gen">{L_NEW_FOLDER_NAME}{L_COLON} </b></td>
- <td class="row1"><input type="text" class="post" name="new_folder_name" size="30" maxlength="30" /></td>
- </tr>
- <tr>
- <td class="row1" align="{S_CONTENT_FLOW_END}" colspan="2"><input class="btnlite" style="width:150px" type="submit" name="rename_folder" value="{L_RENAME}" /></td>
- </tr>
- </table>
-
- <div style="padding: 2px;"></div>
-<!-- ENDIF -->
-
-<!-- IF not S_MAX_FOLDER_ZERO -->
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2">{L_ADD_FOLDER}</th>
-</tr>
-<!-- IF S_MAX_FOLDER_REACHED -->
- <tr>
- <td colspan="2">{L_MAX_FOLDER_REACHED}</td>
- </tr>
-<!-- ELSE -->
- <tr>
- <td class="row1" width="200"><b class="gen">{L_ADD_FOLDER}{L_COLON} </b></td>
- <td class="row1"><input type="text" class="post" name="foldername" size="30" maxlength="30" /></td>
- </tr>
- <tr>
- <td class="row1" align="{S_CONTENT_FLOW_END}" colspan="2"><input class="btnlite" style="width:150px" type="submit" name="addfolder" value="{L_ADD}" /></td>
- </tr>
-<!-- ENDIF -->
-</table>
-<!-- ENDIF -->
-
-<div style="padding: 2px;"></div>
-
-<!-- IF S_FOLDER_OPTIONS -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <th colspan="3">{L_REMOVE_FOLDER}</th>
- </tr>
- <tr>
- <td class="row1" width="200"><b class="gen">{L_REMOVE_FOLDER}{L_COLON} </b></td>
- <td class="row1"><select name="remove_folder_id">{S_FOLDER_OPTIONS}</select></td>
- <td class="row1"><b class="genmed">{L_AND}</b></td>
- </tr>
- <tr>
- <td class="row2" width="200">&nbsp;</td>
- <td class="row2" colspan="2"><input type="radio" class="radio" name="remove_action" value="1" checked="checked" />&nbsp;<span class="genmed">{L_MOVE_DELETED_MESSAGES_TO} </span>&nbsp;<select name="move_to">{S_TO_FOLDER_OPTIONS}</select></td>
- </tr>
- <tr>
- <td class="row2" width="200">&nbsp;</td>
- <td class="row2" colspan="2"><input type="radio" class="radio" name="remove_action" value="2" />&nbsp;<span class="genmed">{L_DELETE_MESSAGES_IN_FOLDER}</span></td>
- </tr>
- <tr>
- <td class="row2" width="200">&nbsp;</td>
- <td class="row2" colspan="2" align="{S_CONTENT_FLOW_END}"><input class="btnlite" style="width:150px" type="submit" name="remove_folder" value="{L_REMOVE}" /></td>
- </tr>
- </table>
-
- <div style="padding: 2px;"></div>
-<!-- ENDIF -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2">{L_FOLDER_OPTIONS}</th>
-</tr>
-<tr>
- <td class="row1" width="200"><span><b class="genmed">{L_IF_FOLDER_FULL}{L_COLON} </b></span></td>
- <td class="row1"><input type="radio" class="radio" name="full_action" value="1"{S_DELETE_CHECKED} />&nbsp;<span class="genmed">{L_DELETE_OLDEST_MESSAGES}</span></td>
-</tr>
-<tr>
- <td class="row1" width="200">&nbsp;</td>
- <td class="row1"><input type="radio" class="radio" name="full_action" value="2"{S_MOVE_CHECKED} />&nbsp;<span class="genmed">{L_MOVE_TO_FOLDER}{L_COLON} </span><select name="full_move_to">{S_FULL_FOLDER_OPTIONS}</select></td>
-</tr>
-<tr>
- <td class="row1" width="200">&nbsp;</td>
- <td class="row1"><input type="radio" class="radio" name="full_action" value="3"{S_HOLD_CHECKED} />&nbsp;<span class="genmed">{L_HOLD_NEW_MESSAGES}</span></td>
-</tr>
-<tr>
- <td class="row2" width="200"><b class="genmed">{L_DEFAULT_ACTION}{L_COLON} </b><br /><span class="gensmall">{L_DEFAULT_ACTION_EXPLAIN}</span></td>
- <td class="row2"><span class="genmed">{DEFAULT_ACTION}</span></td>
-</tr>
-<tr>
- <td class="row1" colspan="2" align="{S_CONTENT_FLOW_END}"><input class="btnlite" style="width:150px" type="submit" name="fullfolder" value="{L_CHANGE}" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html b/phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html
deleted file mode 100644
index 6ab32df255..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_viewfolder.html
+++ /dev/null
@@ -1,131 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<div id="pagecontent">
-
-<!-- IF not PROMPT -->
- <!-- INCLUDE ucp_pm_message_header.html -->
-<!-- ENDIF -->
-
-<div style="padding: 2px;"></div>
-
-<!-- IF S_PM_ICONS -->
- <!-- DEFINE $COLSPAN = 6 -->
-<!-- ELSE -->
- <!-- DEFINE $COLSPAN = 5 -->
-<!-- ENDIF -->
-
-<form name="viewfolder" method="post" action="{S_PM_ACTION}" style="margin:0px">
-
-<!-- IF PROMPT -->
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="0" border="0">
- <tr>
- <th colspan="2" valign="middle">{L_OPTIONS}</th>
- </tr>
- <tr>
- <td class="row1" width="35%">{L_DELIMITER}{L_COLON} </td>
- <td class="row2"><input class="post" type="text" name="delimiter" value="," /></td>
- </tr>
- <tr>
- <td class="row1" width="35%">{L_ENCLOSURE}{L_COLON} </td>
- <td class="row2"><input class="post" type="text" name="enclosure" value="&#034;" /></td>
- </tr>
- <tr>
- <td class="cat" colspan="2" align="center"><input type="hidden" name="export_option" value="CSV" /><input class="btnmain" type="submit" name="submit_export" value="{L_EXPORT_FOLDER}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
- </tr>
- </table>
- {S_FORM_TOKEN}
-
-</form>
-<!-- ELSE -->
-
- <table class="tablebg" width="100%" cellspacing="1" cellpadding="0" border="0">
- <!-- IF NUM_NOT_MOVED or NUM_REMOVED -->
- <tr>
- <td class="row3" colspan="{$COLSPAN}" align="center"><span class="gen">
- <!-- IF NUM_REMOVED -->
- {RULE_REMOVED_MESSAGES}
- <!-- IF NUM_NOT_MOVED --><br /><!-- ENDIF -->
- <!-- ENDIF -->
- <!-- IF NUM_NOT_MOVED -->
- {NOT_MOVED_MESSAGES}<br />{RELEASE_MESSAGE_INFO}
- <!-- ENDIF -->
- </span></td>
- </tr>
- <!-- ENDIF -->
- <tr>
- <th colspan="<!-- IF S_PM_ICONS -->3<!-- ELSE -->2<!-- ENDIF -->">&nbsp;{L_SUBJECT}&nbsp;</th>
- <th>&nbsp;<!-- IF S_SHOW_RECIPIENTS -->{L_RECIPIENTS}<!-- ELSE -->{L_AUTHOR}<!-- ENDIF -->&nbsp;</th>
- <th>&nbsp;{L_SENT_AT}&nbsp;</th>
- <th>&nbsp;{L_MARK}&nbsp;</th>
- </tr>
-
- <!-- BEGIN messagerow -->
- <tr>
- <td class="row1" width="25" align="center" nowrap="nowrap">{messagerow.FOLDER_IMG}</td>
- <!-- IF S_PM_ICONS -->
- <td class="row1" width="25" align="center">{messagerow.PM_ICON_IMG}</td>
- <!-- ENDIF -->
-
- <!-- IF messagerow.S_PM_DELETED --><td class="row3"><!-- ELSE --><td class="row1"><!-- ENDIF -->
- <!-- IF not messagerow.PM_IMG and messagerow.PM_CLASS -->
- <span class="{messagerow.PM_CLASS}" style="float: {S_CONTENT_FLOW_BEGIN};"><img src="images/spacer.gif" width="10" height="10" alt="" /></span>&nbsp;
- <!-- ELSEIF messagerow.PM_IMG -->
- {messagerow.PM_IMG}&nbsp;
- <!-- ENDIF -->
-
- <span class="topictitle">
- {messagerow.ATTACH_ICON_IMG}
- <!-- IF messagerow.S_PM_DELETED -->
- {L_MESSAGE_REMOVED_FROM_OUTBOX}<br />
- <a href="{messagerow.U_REMOVE_PM}" style="float: {S_CONTENT_FLOW_END};">{L_DELETE_MESSAGE}</a>
- <!-- ELSE -->
- <a href="{messagerow.U_VIEW_PM}">{messagerow.SUBJECT}</a>
- <!-- ENDIF -->
- <!-- IF messagerow.S_PM_REPORTED -->
- <a href="{messagerow.U_MCP_REPORT}" class="imageset">{REPORTED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF messagerow.S_AUTHOR_DELETED -->
- <br /><em class="gensmall">{L_PM_FROM_REMOVED_AUTHOR}</em>
- <!-- ENDIF -->
- </span></td>
-
- <td class="row1" width="100" align="center"><p class="topicauthor"><!-- IF S_SHOW_RECIPIENTS -->{messagerow.RECIPIENTS}<!-- ELSE -->{messagerow.MESSAGE_AUTHOR_FULL}<!-- ENDIF --></p></td>
- <td class="row1" width="120" align="center"><p class="topicdetails">{messagerow.SENT_TIME}</p></td>
- <td class="row1" width="20" align="center"><p class="topicdetails"><input type="checkbox" class="radio" name="marked_msg_id[]" value="{messagerow.MESSAGE_ID}" /></p></td>
- </tr>
- <!-- BEGINELSE -->
- <tr>
- <td class="row1" colspan="{$COLSPAN}" height="30" align="center" valign="middle"><span class="gen">
- <!-- IF S_COMPOSE_PM_VIEW and S_NO_AUTH_SEND_MESSAGE -->
- <!-- IF S_USER_NEW -->{L_USER_NEW_PERMISSION_DISALLOWED}<!-- ELSE -->{L_NO_AUTH_SEND_MESSAGE}<!-- ENDIF -->
- <!-- ELSE -->
- {L_NO_MESSAGES}
- <!-- ENDIF -->
- </span></td>
- </tr>
- <!-- END messagerow -->
-</table>
-
-<input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
-
-<table border="0" cellspacing="0" cellpadding="0" width="100%">
-<tr>
- <td class="cat">
-<!-- IF .messagerow -->
- <div style="float: {S_CONTENT_FLOW_BEGIN};"><select name="export_option"><option value="CSV">{L_EXPORT_AS_CSV}</option><option value="CSV_EXCEL">{L_EXPORT_AS_CSV_EXCEL}</option><option value="XML">{L_EXPORT_AS_XML}</option></select>&nbsp;<input class="btnlite" type="submit" name="submit_export" value="{L_EXPORT_FOLDER}" /></div>
- <div style="float: {S_CONTENT_FLOW_END};"><select name="mark_option">{S_MARK_OPTIONS}{S_MOVE_MARKED_OPTIONS}</select>&nbsp;<input class="btnlite" type="submit" name="submit_mark" value="{L_GO}" />&nbsp;</div>
-<!-- ENDIF -->
- </td>
-</tr>
-</table>
-
-<div style="padding: 2px;"></div>
-<!-- INCLUDE ucp_pm_message_footer.html -->
-
-<!-- ENDIF -->
-
-<br clear="all" />
-
-</div>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html
deleted file mode 100644
index 9536b1f8c5..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage.html
+++ /dev/null
@@ -1,136 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<div id="pagecontent">
-
-<!-- INCLUDE ucp_pm_message_header.html -->
-<div style="padding: 2px;"></div>
-
-<table class="tablebg" width="100%" cellspacing="1" cellpadding="4">
-
-<tr class="row1">
- <td class="genmed" nowrap="nowrap" width="150"><b>{L_PM_SUBJECT}{L_COLON}</b></td>
- <td class="gen">{SUBJECT}</td>
-</tr>
-
-<tr class="row1">
- <td class="genmed" nowrap="nowrap" width="150"><b>{L_PM_FROM}{L_COLON}</b></td>
- <td class="gen">{MESSAGE_AUTHOR_FULL}</td>
-</tr>
-
-<tr class="row1">
- <td class="genmed" nowrap="nowrap" width="150"><b>{L_SENT_AT}{L_COLON}</b></td>
- <td class="gen">{SENT_DATE}</td>
-</tr>
-
-<!-- IF S_TO_RECIPIENT -->
- <tr class="row1">
- <td class="genmed" nowrap="nowrap" width="150"><b>{L_TO}{L_COLON}</b></td>
- <td class="gen">
- <!-- BEGIN to_recipient -->
- <!-- IF to_recipient.IS_GROUP --><span class="sep"><a href="{to_recipient.U_VIEW}">{to_recipient.NAME}</a></span><!-- ELSE -->{to_recipient.NAME_FULL}&nbsp;<!-- ENDIF -->
- <!-- END to_recipient -->
- </td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_BCC_RECIPIENT -->
- <tr class="row1">
- <td class="genmed" nowrap="nowrap" width="150"><b>{L_BCC}{L_COLON}</b></td>
- <td class="gen">
- <!-- BEGIN bcc_recipient -->
- <!-- IF bcc_recipient.IS_GROUP --><span class="sep"><a href="{bcc_recipient.U_VIEW}">{bcc_recipient.NAME}</a></span><!-- ELSE -->{bcc_recipient.NAME_FULL}&nbsp;<!-- ENDIF -->
- <!-- END bcc_recipient -->
- </td>
- </tr>
-<!-- ENDIF -->
-</table>
-
-<div style="padding: 2px;"></div>
-
-<table class="tablebg" width="100%" cellspacing="1" cellpadding="0">
-
-<tr>
- <th nowrap="nowrap">{L_MESSAGE}</th>
-</tr>
-
-<tr>
- <td class="spacer" height="1"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
-</tr>
-
-<tr class="row1">
- <td valign="top">
- <table width="100%" cellspacing="5">
- <tr>
- <td>
- <div class="postbody">{MESSAGE}</div>
-
- <!-- IF S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <td class="row2">{attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- <!-- IF S_DISPLAY_NOTICE -->
- <span class="gensmall error"><br /><br />{L_DOWNLOAD_NOTICE}</span>
- <!-- ENDIF -->
- <!-- IF SIGNATURE -->
- <span class="postbody"><br />_________________<br />{SIGNATURE}</span>
- <!-- ENDIF -->
- <!-- IF EDITED_MESSAGE -->
- <span class="gensmall">{EDITED_MESSAGE}</span>
- <!-- ENDIF -->
-
- <!-- IF not S_HAS_ATTACHMENTS --><br clear="all" /><br /><!-- ENDIF -->
-
- <table width="100%" cellspacing="0">
- <tr valign="middle">
- <td class="gensmall" align="{S_CONTENT_FLOW_END}"> <!-- IF U_REPORT --><a href="{U_REPORT}" class="imageset">{REPORT_IMG}</a> <!-- ENDIF --><!-- IF U_DELETE --><a href="{U_DELETE}" class="imageset">{DELETE_IMG}</a> <!-- ENDIF --></td>
- </tr>
- </table>
-
- </td>
- </tr>
- </table>
- </td>
-</tr>
-
-<tr class="row1">
- <td>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_BEGIN};">
- &nbsp;<!-- IF U_MESSAGE_AUTHOR --><a href="{U_MESSAGE_AUTHOR}" class="imageset">{PROFILE_IMG}</a> <!-- ENDIF -->
- <!-- IF U_EMAIL --><a href="{U_EMAIL}" class="imageset">{EMAIL_IMG}</a> <!-- ENDIF -->
- &nbsp;</div>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_END};">
- <!-- EVENT ucp_pm_viewmessage_post_buttons_before -->
- <!-- IF U_EDIT --><a href="{U_EDIT}" class="imageset">{EDIT_IMG}</a> <!-- ENDIF -->
- <!-- IF U_QUOTE --><a href="{U_QUOTE}" class="imageset">{QUOTE_IMG}</a> <!-- ENDIF -->
- <!-- IF U_POST_REPLY_PM --><a href="{U_POST_REPLY_PM}" class="imageset">{REPLY_IMG}</a><!-- ENDIF -->
- <!-- EVENT ucp_pm_viewmessage_post_buttons_after -->
- &nbsp;</div>
- </td>
-</tr>
-
-<tr>
- <td class="spacer" height="1"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
-</tr>
-</table>
-
-<div style="padding: 2px;"></div>
-<!-- INCLUDE ucp_pm_message_footer.html -->
-
-<br clear="all" />
-
-</div>
-
-<!-- IF S_DISPLAY_HISTORY --><!-- INCLUDE ucp_pm_history.html --><!-- ENDIF -->
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html
deleted file mode 100644
index 624a6ea8ef..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8" />
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-<meta name="robots" content="noindex" />
-<title>{SITENAME} :: {PAGE_TITLE}</title>
-
-<style type="text/css">
-<!--
-
-body {
- font-family: Verdana,serif;
- font-size: 10pt;
-}
-
-td {
- font-family: Verdana,serif;
- font-size: 10pt;
- line-height: 150%;
-}
-
-.code,
-.quote {
- font-size: smaller;
- border: black solid 1px;
-}
-
-.forum {
- font-family: Arial,Helvetica,sans-serif;
- font-weight: bold;
- font-size: 18pt;
-}
-
-.topic {
- font-family: Arial,Helvetica,sans-serif;
- font-size: 14pt;
- font-weight: bold;
-}
-
-.gensmall {
- font-size: 8pt;
-}
-
-hr {
- color: #888;
- height: 3px;
- border-style: solid;
-}
-
-hr.sep {
- color: #aaa;
- height: 1px;
- border-style: dashed;
-}
-//-->
-</style>
-<!-- EVENT ucp_pm_viewmessage_print_head_append -->
-</head>
-<body>
-
-<table width="85%" cellspacing="3" cellpadding="0" border="0" align="center">
-<tr>
- <td colspan="2" align="center"><span class="Forum">{SITENAME}</span><br /><span class="gensmall">{L_PRIVATE_MESSAGING}</span></td>
-</tr>
-<tr>
- <td colspan="2"><br /></td>
-</tr>
-<tr>
- <td><span class="topic">{SUBJECT}</span><br /></td>
- <td align="{S_CONTENT_FLOW_END}" valign="bottom"><span class="gensmall">{PAGE_NUMBER}</span></td>
-</tr>
-</table>
-
-<hr width="85%" />
-
-<table width="85%" cellspacing="3" cellpadding="0" border="0" align="center">
-<tr>
- <td width="10%" nowrap="nowrap">{L_PM_FROM}{L_COLON}&nbsp;</td>
- <td><b>{MESSAGE_AUTHOR}</b> [ {SENT_DATE} ]</td>
-</tr>
-
-<!-- IF S_TO_RECIPIENT -->
- <tr>
- <td width="10%" nowrap="nowrap">{L_TO}{L_COLON}</td>
- <td>
- <!-- BEGIN to_recipient -->
- <span<!-- IF to_recipient.IS_GROUP --> class="sep"<!-- ENDIF -->>{to_recipient.NAME}</span>&nbsp;
- <!-- END to_recipient -->
- </td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF S_BCC_RECIPIENT -->
- <tr>
- <td width="10%" nowrap="nowrap">{L_BCC}{L_COLON}</td>
- <td>
- <!-- BEGIN bcc_recipient -->
- <!-- IF bcc_recipient.COLOUR --><span style="color:{bcc_recipient.COLOUR}"><!-- ELSE --><span<!-- IF bcc_recipient.IS_GROUP --> class="sep"<!-- ENDIF -->><!-- ENDIF -->{bcc_recipient.NAME}</span>&nbsp;
- <!-- END bcc_recipient -->
- </td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td colspan="2"><hr class="sep" />{MESSAGE}</td>
-</tr>
-</table>
-
-<hr width="85%" />
-
-<table width="85%" cellspacing="3" cellpadding="0" border="0" align="center">
-<tr>
- <td><span class="gensmall">{PAGE_NUMBER}</span></td>
- <td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td>
-</tr>
-<tr>
- <td colspan="2" align="center"><span class="gensmall">Powered by phpBB&reg; Forum Software &copy; phpBB Limited<br />https://www.phpbb.com/</span></td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html b/phpBB/styles/subsilver2/template/ucp_prefs_personal.html
deleted file mode 100644
index 0dd50b8fa2..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
- var default_dateformat = '{A_DEFAULT_DATEFORMAT}';
-// ]]>
-</script>
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT ucp_prefs_personal_prepend -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_SHOW_EMAIL}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="viewemail" value="1"<!-- IF S_VIEW_EMAIL --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="viewemail" value="0"<!-- IF not S_VIEW_EMAIL --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_ADMIN_EMAIL}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="massemail" value="1"<!-- IF S_MASS_EMAIL --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="massemail" value="0"<!-- IF not S_MASS_EMAIL --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_ALLOW_PM}{L_COLON}</b><br /><span class="gensmall">{L_ALLOW_PM_EXPLAIN}</span></td>
- <td class="row2"><input type="radio" class="radio" name="allowpm" value="1"<!-- IF S_ALLOW_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="allowpm" value="0"<!-- IF not S_ALLOW_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
-</tr>
-<!-- IF S_CAN_HIDE_ONLINE -->
- <tr>
- <td class="row1" width="50%"><b class="genmed">{L_HIDE_ONLINE}{L_COLON}</b><br /><span class="gensmall">{L_HIDE_ONLINE_EXPLAIN}</span></td>
- <td class="row2"><input type="radio" class="radio" name="hideonline" value="1"<!-- IF S_HIDE_ONLINE --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="hideonline" value="0"<!-- IF not S_HIDE_ONLINE --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- IF S_SELECT_NOTIFY -->
- <tr>
- <td class="row1" width="50%"><b class="genmed">{L_NOTIFY_METHOD}{L_COLON}</b><br /><span class="gensmall">{L_NOTIFY_METHOD_EXPLAIN}</span></td>
- <td class="row2"><input type="radio" class="radio" name="notifymethod" value="0"<!-- IF S_NOTIFY_EMAIL --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NOTIFY_METHOD_EMAIL}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="notifymethod" value="1"<!-- IF S_NOTIFY_IM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NOTIFY_METHOD_IM}</span>&nbsp;&nbsp;<input type="radio" class="radio" name="notifymethod" value="2"<!-- IF S_NOTIFY_BOTH --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NOTIFY_METHOD_BOTH}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- IF S_MORE_LANGUAGES -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_BOARD_LANGUAGE}{L_COLON}</b></td>
- <td class="row2"><select name="lang">{S_LANG_OPTIONS}</select></td>
-</tr>
-<!-- ENDIF -->
-<!-- IF S_STYLE_OPTIONS and S_MORE_STYLES -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_BOARD_STYLE}{L_COLON}</b></td>
- <td class="row2"><select name="user_style">{S_STYLE_OPTIONS}</select></td>
-</tr>
-<!-- ENDIF -->
-<!-- INCLUDE timezone_option.html -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_BOARD_DATE_FORMAT}{L_COLON}</b><br /><span class="gensmall">{L_BOARD_DATE_FORMAT_EXPLAIN}</span></td>
- <td class="row2">
- <select name="dateoptions" id="dateoptions" onchange="if(this.value=='custom'){phpbb.toggleDisplay('custom_date',1);}else{phpbb.toggleDisplay('custom_date',-1);} if (this.value == 'custom') { document.getElementById('dateformat').value = default_dateformat; } else { document.getElementById('dateformat').value = this.value; }">
- {S_DATEFORMAT_OPTIONS}
- </select>
- <div id="custom_date"<!-- IF not S_CUSTOM_DATEFORMAT --> style="display:none;"<!-- ENDIF -->><input type="text" name="dateformat" id="dateformat" value="{DATE_FORMAT}" maxlength="64" class="post" style="margin-top: 3px;" /></div>
- </td>
-</tr>
-<!-- EVENT ucp_prefs_personal_append -->
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_post.html b/phpBB/styles/subsilver2/template/ucp_prefs_post.html
deleted file mode 100644
index 0a558b863c..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_prefs_post.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT ucp_prefs_post_prepend -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_DEFAULT_BBCODE}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="bbcode" value="1"<!-- IF S_BBCODE --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="bbcode" value="0"<!-- IF not S_BBCODE --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_DEFAULT_SMILIES}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="smilies" value="1"<!-- IF S_SMILIES --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="smilies" value="0"<!-- IF not S_SMILIES --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_DEFAULT_ADD_SIG}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="sig" value="1"<!-- IF S_SIG --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="sig" value="0"<!-- IF not S_SIG --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_DEFAULT_NOTIFY}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="notify" value="1"<!-- IF S_NOTIFY --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="notify" value="0"<!-- IF not S_NOTIFY --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<!-- EVENT ucp_prefs_post_append -->
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_view.html b/phpBB/styles/subsilver2/template/ucp_prefs_view.html
deleted file mode 100644
index c10c458627..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_prefs_view.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT ucp_prefs_view_radio_buttons_prepend -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_IMAGES}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="images" value="1"<!-- IF S_IMAGES --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="images" value="0"<!-- IF not S_IMAGES --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_FLASH}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="flash" value="1"<!-- IF S_FLASH --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="flash" value="0"<!-- IF not S_FLASH --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_SMILIES}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="smilies" value="1"<!-- IF S_SMILIES --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="smilies" value="0"<!-- IF not S_SMILIES --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_SIGS}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="sigs" value="1"<!-- IF S_SIGS --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="sigs" value="0"<!-- IF not S_SIGS --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_AVATARS}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="avatars" value="1"<!-- IF S_AVATARS --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="avatars" value="0"<!-- IF not S_AVATARS --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
-</tr>
-<!-- IF S_CHANGE_CENSORS -->
- <tr>
- <td class="row1" width="50%"><b class="genmed">{L_DISABLE_CENSORS}{L_COLON}</b></td>
- <td class="row2"><input type="radio" class="radio" name="wordcensor" value="1"<!-- IF S_DISABLE_CENSORS --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_YES}</span>&nbsp; &nbsp;<input type="radio" class="radio" name="wordcensor" value="0"<!-- IF not S_DISABLE_CENSORS --> checked="checked"<!-- ENDIF --> /><span class="gen">{L_NO}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT ucp_prefs_view_radio_buttons_append -->
-<tr>
- <td colspan="2" class="spacer"></td>
-</tr>
-<!-- EVENT ucp_prefs_view_select_menu_prepend -->
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_TOPICS_DAYS}{L_COLON}</b></td>
- <td class="row2">{S_TOPIC_SORT_DAYS}</td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_TOPICS_KEY}{L_COLON}</b></td>
- <td class="row2">{S_TOPIC_SORT_KEY}</td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_TOPICS_DIR}{L_COLON}</b></td>
- <td class="row2">{S_TOPIC_SORT_DIR}</td>
-</tr>
-<tr>
- <td colspan="2" class="spacer"></td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_POSTS_DAYS}{L_COLON}</b></td>
- <td class="row2">{S_POST_SORT_DAYS}</td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_POSTS_KEY}{L_COLON}</b></td>
- <td class="row2">{S_POST_SORT_KEY}</td>
-</tr>
-<tr>
- <td class="row1" width="50%"><b class="genmed">{L_VIEW_POSTS_DIR}{L_COLON}</b></td>
- <td class="row2">{S_POST_SORT_DIR}</td>
-</tr>
-<!-- EVENT ucp_prefs_view_select_menu_append -->
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html b/phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html
deleted file mode 100644
index 087ae89743..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_profile_autologin_keys.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="4">{L_TITLE}</th>
-</tr>
-
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="4" align="center"><span class="genmed error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<tr>
- <td colspan="4" class="row1">{L_PROFILE_AUTOLOGIN_KEYS}</td>
-</tr>
-<tr>
- <th>{L_LOGIN_KEY}</th>
- <th class="center">{L_IP}</th>
- <th class="center">{L_LOGIN_TIME}</th>
- <th class="center">{L_MARK}</th>
-</tr>
-<!-- BEGIN sessions -->
- <!-- IF sessions.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td class="genmed"><label for="{sessions.KEY}">{sessions.KEY}</label></td>
- <td class="genmed" style="text-align: center">{sessions.IP}</td>
- <td class="genmed" style="text-align: center">{sessions.LOGIN_TIME}</td>
- <td class="genmed" style="text-align: center"><input type="checkbox" name="keys[]" value="{sessions.KEY}" id="{sessions.KEY}"/></td>
- </tr>
-<!-- BEGINELSE -->
- <tr>
- <td colspan="4" class="row1" style="text-align: center">{L_PROFILE_NO_AUTOLOGIN_KEYS}</td>
- </tr>
-<!-- END sessions -->
-
-<!-- IF .sessions -->
- <tr>
- <td class="cat" colspan="4" align="{S_CONTENT_FLOW_END}">
- {S_HIDDEN_FIELDS}<input class="btnlite" type="submit" name="submit" value="{L_DELETE_MARKED}" />
- {S_FORM_TOKEN}
- </td>
- </tr>
-<!-- ENDIF -->
-</table>
-
-<!-- IF .sessions -->
- <div class="gensmall" style="float: {S_CONTENT_FLOW_END}; padding-top: 2px;"><b><a href="#" onclick="marklist('ucp', 'keys', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('ucp', 'keys', false); return false;">{L_UNMARK_ALL}</a></b></div>
-<!-- ENDIF -->
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_profile_avatar.html b/phpBB/styles/subsilver2/template/ucp_profile_avatar.html
deleted file mode 100644
index 8b1e8cffac..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_profile_avatar.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1" width="35%"><b class="genmed">{L_CURRENT_IMAGE}{L_COLON} </b><br /><span class="gensmall">{L_AVATAR_EXPLAIN}</span></td>
- <td class="row2" align="center"><br />
- <!-- IF AVATAR -->{AVATAR}<br /><br /><input type="checkbox" class="radio" name="avatar_delete" />&nbsp;<span class="gensmall">{L_DELETE_AVATAR}</span>
- <!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" />
- <!-- ENDIF --></td>
-</tr>
-<!-- IF not S_AVATARS_ENABLED -->
- <tr>
- <td class="row3" colspan="2" align="center">{L_AVATAR_FEATURES_DISABLED}</td>
- </tr>
-<!-- ENDIF -->
- <tr>
- <th colspan="2">{L_AVATAR_SELECT}</th>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_AVATAR_TYPE}{L_COLON}</b></td>
- <td class="row2">
- <select name="avatar_driver" id="avatar_driver" data-togglable-settings="true">
- <!-- BEGIN avatar_drivers -->
- <option value="{avatar_drivers.DRIVER}"<!-- IF avatar_drivers.SELECTED --> selected="selected"<!-- ENDIF --> data-toggle-setting=".avatar_option_{avatar_drivers.DRIVER}">{avatar_drivers.L_TITLE}</option>
- <!-- END avatar_drivers -->
- </select></td>
- </tr>
-<!-- BEGIN avatar_drivers -->
- <tr class="avatar_option_{avatar_drivers.DRIVER}">
- <td class="row1" width="35%" colspan="2"><noscript><b class="genmed">{avatar_drivers.L_TITLE} </b><br /></noscript>{avatar_drivers.L_EXPLAIN}</span></td>
- </tr>
- <tr class="avatar_option_{avatar_drivers.DRIVER}">
- <td colspan="2" style="padding: 0">{avatar_drivers.OUTPUT}</td>
- </tr>
-<!-- END avatar_drivers -->
-
- <tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<!-- IF S_IN_AVATAR_GALLERY --><input class="btnlite" type="submit" name="cancel" value="{L_CANCEL}" /><!-- ELSE --><input class="btnlite" type="reset" value="{L_RESET}" name="reset" /><!-- ENDIF --></td>
- </tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html b/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html
deleted file mode 100644
index bfc2dd0244..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1" colspan="2"><span class="gensmall">{L_PROFILE_INFO_NOTICE}</span></td>
-</tr>
-<!-- EVENT ucp_profile_profile_info_before -->
-<!-- IF S_JABBER_ENABLED -->
-<tr>
- <td class="row1" width="35%"><b class="genmed">{L_UCP_JABBER}{L_COLON} </b></td>
- <td class="row2"><input class="post" type="text" name="jabber" size="30" maxlength="255" value="{JABBER}" /></td>
-</tr>
-<!-- ENDIF -->
-<!-- IF S_BIRTHDAYS_ENABLED -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_BIRTHDAY}{L_COLON} </b><br /><span class="gensmall">{L_BIRTHDAY_EXPLAIN}</span></td>
- <td class="row2"><span class="genmed">{L_DAY}{L_COLON}</span> <select name="bday_day">{S_BIRTHDAY_DAY_OPTIONS}</select> <span class="genmed">{L_MONTH}{L_COLON}</span> <select name="bday_month">{S_BIRTHDAY_MONTH_OPTIONS}</select> <span class="genmed">{L_YEAR}{L_COLON}</span> <select name="bday_year">{S_BIRTHDAY_YEAR_OPTIONS}</select></td>
- </tr>
-<!-- ENDIF -->
-<!-- BEGIN profile_fields -->
- <tr>
- <td class="row1" width="35%">
- <b class="genmed">{profile_fields.LANG_NAME}{L_COLON} </b>
- <!-- IF profile_fields.S_REQUIRED --><b>*</b><!-- ENDIF -->
- <!-- IF profile_fields.LANG_EXPLAIN --><br /><span class="gensmall">{profile_fields.LANG_EXPLAIN}</span><!-- ENDIF -->
- </td>
- <td class="row2">{profile_fields.FIELD}<!-- IF profile_fields.ERROR --><br /><span class="gensmall error">{profile_fields.ERROR}</span><!-- ENDIF --></td>
- </tr>
-<!-- END profile_fields -->
-<!-- EVENT ucp_profile_profile_info_after -->
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html b/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html
deleted file mode 100644
index 862956a1d0..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- IF S_FORCE_PASSWORD -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{L_FORCE_PASSWORD_EXPLAIN}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT ucp_profile_register_details_before -->
-<tr>
- <td class="row1" width="35%"><b class="genmed">{L_USERNAME}{L_COLON} </b><br /><span class="gensmall">{L_USERNAME_EXPLAIN}</span></td>
- <td class="row2"><!-- IF S_CHANGE_USERNAME --><input type="text" class="post" name="username" size="30" value="{USERNAME}" /><!-- ELSE --><b class="gen">{USERNAME}</b><!-- ENDIF --></td>
-</tr>
-<tr>
- <td class="row1" width="35%"><b class="genmed">{L_EMAIL_ADDRESS}{L_COLON} </b></td>
- <td class="row2"><!-- IF S_CHANGE_EMAIL --><input type="email" class="post" name="email" size="30" maxlength="100" value="{EMAIL}" autocomplete="off" /><!-- ELSE --><b class="gen">{EMAIL}</b><!-- ENDIF --></td>
-</tr>
-<!-- IF S_CHANGE_PASSWORD -->
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_NEW_PASSWORD}{L_COLON} </b><br /><span class="gensmall">{L_CHANGE_PASSWORD_EXPLAIN}</span></td>
- <td class="row2"><input type="password" class="post" name="new_password" size="30" maxlength="255" value="{NEW_PASSWORD}" autocomplete="off" /></td>
- </tr>
- <tr>
- <td class="row1" width="35%"><b class="genmed">{L_CONFIRM_PASSWORD}{L_COLON} </b><br /><span class="gensmall">{L_CONFIRM_PASSWORD_EXPLAIN}</span></td>
- <td class="row2"><input type="password" class="post" name="password_confirm" size="30" maxlength="255" value="{PASSWORD_CONFIRM}" autocomplete="off" /></td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT ucp_profile_register_details_after -->
-<tr>
- <th colspan="2">{L_CONFIRM_CHANGES}</th>
-</tr>
-<tr>
- <td class="row1" width="35%"><b class="genmed">{L_CURRENT_PASSWORD}{L_COLON} </b><br /><span class="gensmall"><!-- IF S_CHANGE_PASSWORD -->{L_CURRENT_CHANGE_PASSWORD_EXPLAIN}<!-- ELSE -->{L_CURRENT_PASSWORD_EXPLAIN}<!-- ENDIF --></span></td>
- <td class="row2"><input type="password" class="post" name="cur_password" size="30" maxlength="255" value="{CUR_PASSWORD}" autocomplete="off" /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_profile_signature.html b/phpBB/styles/subsilver2/template/ucp_profile_signature.html
deleted file mode 100644
index 5a2690edda..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_profile_signature.html
+++ /dev/null
@@ -1,132 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
- var form_name = 'ucp';
- var text_name = 'signature';
-// ]]>
-</script>
-
-<!-- DEFINE $S_SIGNATURE = 1 -->
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2">{L_TITLE}</th>
-</tr>
-<!-- IF not S_SMILIES_ALLOWED -->
-<tr>
- <td colspan="2" class="row1">{L_SIGNATURE_EXPLAIN}</td>
-</tr>
-<!-- ENDIF -->
-
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="genmed error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<tr>
- <!-- IF S_SMILIES_ALLOWED -->
- <td class="row1" width="22%" valign="top">
- {L_SIGNATURE_EXPLAIN}
- <table width="100%" cellspacing="5" cellpadding="0" border="0" align="center">
- <tr>
- <td class="gensmall" align="center"><b>{L_SMILIES}</b></td>
- </tr>
- <tr>
- <td align="center">
- <!-- BEGIN smiley -->
- <a href="#" onclick="insert_text('{smiley.A_SMILEY_CODE}', true); return false;" style="line-height: 20px;"><img src="{smiley.SMILEY_IMG}" width="{smiley.SMILEY_WIDTH}" height="{smiley.SMILEY_HEIGHT}" alt="{smiley.SMILEY_CODE}" title="{smiley.SMILEY_DESC}" hspace="2" vspace="2" /></a>
- <!-- END smiley -->
- </td>
- </tr>
- <!-- IF S_SHOW_SMILEY_LINK -->
- <tr>
- <td align="center"><a class="nav" href="{U_MORE_SMILIES}" onclick="popup(this.href, 300, 350, '_phpbbsmilies'); return false;">{L_MORE_SMILIES}</a></td>
- </tr>
- <!-- ENDIF -->
- </table>
- </td>
- <td class="row2">
- <!-- ELSE -->
- <td class="row2" colspan="2">
- <!-- ENDIF -->
-
- <table cellspacing="0" cellpadding="2" border="0" width="99%">
- <!-- INCLUDE posting_buttons.html -->
- <tr>
- <td colspan="2"><textarea class="post" name="signature" rows="10" cols="76" style="width: 90%;" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();">{SIGNATURE}</textarea></td>
- </tr>
- <!-- IF S_BBCODE_ALLOWED -->
- <tr>
- <td colspan="2">
- <table cellspacing="0" cellpadding="0" border="0" width="100%">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" id="color_palette_placeholder" data-orientation="h" data-width="11" data-height="10">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- ENDIF -->
- </table>
- </td>
-</tr>
-<tr>
- <td class="row1" valign="top"><b class="genmed">{L_OPTIONS}</b><br />
- <table cellspacing="2" cellpadding="0" border="0">
- <tr>
- <td class="gensmall">{BBCODE_STATUS}</td>
- </tr>
- <tr>
- <td class="gensmall">{IMG_STATUS}</td>
- </tr>
- <tr>
- <td class="gensmall">{FLASH_STATUS}</td>
- </tr>
- <tr>
- <td class="gensmall">{URL_STATUS}</td>
- </tr>
- <tr>
- <td class="gensmall">{SMILIES_STATUS}</td>
- </tr>
- </table>
- </td>
- <td class="row2" valign="top">
- <table cellspacing="0" cellpadding="1" border="0">
- <!-- IF S_BBCODE_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="disable_bbcode"{S_BBCODE_CHECKED} /></td>
- <td class="gen">{L_DISABLE_BBCODE}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_SMILIES_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="disable_smilies"{S_SMILIES_CHECKED} /></td>
- <td class="gen">{L_DISABLE_SMILIES}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_LINKS_ALLOWED -->
- <tr>
- <td><input type="checkbox" class="radio" name="disable_magic_url"{S_MAGIC_URL_CHECKED} /></td>
- <td class="gen">{L_DISABLE_MAGIC_URL}</td>
- </tr>
- <!-- ENDIF -->
- </table>
- </td>
-</tr>
-
-<!-- IF SIGNATURE_PREVIEW != '' -->
- <tr>
- <th colspan="2" valign="middle">{L_SIGNATURE_PREVIEW}</th>
- </tr>
- <tr>
- <td class="row1" colspan="2"><div class="postbody" style="padding: 6px;">{SIGNATURE_PREVIEW}</div></td>
- </tr>
-<!-- ENDIF -->
-
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnlite" type="submit" name="preview" value="{L_PREVIEW}" />&nbsp;&nbsp;<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_register.html b/phpBB/styles/subsilver2/template/ucp_register.html
deleted file mode 100644
index 9b9e164df4..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_register.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
- /**
- * Change language
- */
- function change_language(lang_iso)
- {
- document.cookie = '{COOKIE_NAME}_lang=' + lang_iso + '; path={COOKIE_PATH}';
- document.forms['register'].change_lang.value = lang_iso;
- document.forms['register'].submit.click();
- }
-
-// ]]>
-</script>
-
-<form name="register" method="post" action="{S_UCP_ACTION}">
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_REGISTRATION}</th>
-</tr>
-
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- IF L_REG_COND -->
- <tr>
- <td class="row2" colspan="2"><span class="gensmall">{L_REG_COND}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<!-- EVENT ucp_register_credentials_before -->
-<tr>
- <td class="row1" width="38%"><b class="genmed">{L_USERNAME}{L_COLON} </b><br /><span class="gensmall">{L_USERNAME_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="text" name="username" size="25" value="{USERNAME}" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_EMAIL_ADDRESS}{L_COLON} </b></td>
- <td class="row2"><input class="post" type="email" name="email" size="25" maxlength="100" value="{EMAIL}" autocomplete="off" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_PASSWORD}{L_COLON} </b><br /><span class="gensmall">{L_PASSWORD_EXPLAIN}</span></td>
- <td class="row2"><input class="post" type="password" name="new_password" size="25" value="{PASSWORD}" autocomplete="off" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_CONFIRM_PASSWORD}{L_COLON} </b></td>
- <td class="row2"><input class="post" type="password" name="password_confirm" size="25" value="{PASSWORD_CONFIRM}" autocomplete="off" /></td>
-</tr>
-<!-- EVENT ucp_register_credentials_after -->
-<!-- EVENT ucp_register_options_before -->
-<tr>
- <td class="row1"><b class="genmed">{L_LANGUAGE}{L_COLON} </b></td>
- <td class="row2"><select name="lang" onchange="change_language(this.value); return false;">{S_LANG_OPTIONS}</select></td>
-</tr>
-
-<!-- INCLUDE timezone_option.html -->
-
-<!-- EVENT ucp_register_profile_fields_before -->
-<!-- IF .profile_fields -->
- <tr>
- <td class="row2" colspan="2"><span class="gensmall">{L_ITEMS_REQUIRED}</span></td>
- </tr>
-<!-- BEGIN profile_fields -->
- <tr>
- <td class="row1" width="35%">
- <b class="genmed">{profile_fields.LANG_NAME}{L_COLON} </b>
- <!-- IF profile_fields.S_REQUIRED --><b>*</b><!-- ENDIF -->
- <!-- IF profile_fields.LANG_EXPLAIN --><br /><span class="gensmall">{profile_fields.LANG_EXPLAIN}</span><!-- ENDIF -->
- </td>
- <td class="row2">{profile_fields.FIELD}<!-- IF profile_fields.ERROR --><br /><span class="gensmall error">{profile_fields.ERROR}</span><!-- ENDIF --></td>
- </tr>
-
-<!-- END profile_fields -->
-<!-- ENDIF -->
-<!-- EVENT ucp_register_profile_fields_after -->
- <!-- IF CAPTCHA_TEMPLATE -->
- <!-- INCLUDE {CAPTCHA_TEMPLATE} -->
- <!-- ENDIF -->
-
-<!-- IF S_COPPA -->
- <tr>
- <th colspan="2" valign="middle">{L_COPPA_COMPLIANCE}</th>
- </tr>
- <tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_COPPA_EXPLAIN}</span></td>
- </tr>
-<!-- ENDIF -->
-
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" id="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_remind.html b/phpBB/styles/subsilver2/template/ucp_remind.html
deleted file mode 100644
index f7fde4b3be..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_remind.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div align="center">
-
-<form action="{S_PROFILE_ACTION}" method="post">
-
-<table class="tablebg" width="50%" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <th colspan="2">{L_SEND_PASSWORD}</th>
-</tr>
-<tr>
- <td class="row1" width="38%"><b class="genmed">{L_USERNAME}{L_COLON} </b></td>
- <td class="row2"><input type="text" class="post" name="username" size="25" value="{USERNAME}" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_EMAIL_ADDRESS}{L_COLON} </b><br /><span class="gensmall">{L_EMAIL_REMIND}</span></td>
- <td class="row2"><input type="email" class="post" name="email" size="25" maxlength="100" value="{EMAIL}" /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input type="submit" name="submit" value="{L_SUBMIT}" class="btnmain" />&nbsp;&nbsp;<input type="reset" value="{L_RESET}" name="reset" class="btnlite" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-</form>
-
-</div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_resend.html b/phpBB/styles/subsilver2/template/ucp_resend.html
deleted file mode 100644
index 62e7e96d6b..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_resend.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<div align="center">
-
-<form action="{S_PROFILE_ACTION}" method="post">
-
-<table class="tablebg" width="50%" cellspacing="1" cellpadding="4" border="0">
-<tr>
- <th colspan="2">{L_UCP_RESEND}</th>
-</tr>
-<tr>
- <td class="row1" width="38%"><b class="genmed">{L_USERNAME}{L_COLON} </b></td>
- <td class="row2"><input type="text" class="post" name="username" size="25" value="{USERNAME}" /></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_EMAIL_ADDRESS}{L_COLON} </b><br /><span class="gensmall">{L_EMAIL_REMIND}</span></td>
- <td class="row2"><input type="email" class="post" name="email" size="25" maxlength="100" value="{EMAIL}" /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input type="submit" name="submit" value="{L_SUBMIT}" class="btnmain" />&nbsp;&nbsp;<input type="reset" value="{L_RESET}" name="reset" class="btnlite" /></td>
-</tr>
-</table>
-{S_FORM_TOKEN}
-
-</form>
-
-</div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_zebra_foes.html b/phpBB/styles/subsilver2/template/ucp_zebra_foes.html
deleted file mode 100644
index 6149a80e69..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_zebra_foes.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_FOES_EXPLAIN}</span></td>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1" width="40%"><b class="genmed">{L_YOUR_FOES}{L_COLON}</b><br /><span class="gensmall">{L_YOUR_FOES_EXPLAIN}</span></td>
- <td class="row2" align="center"><!-- IF S_USERNAME_OPTIONS --><select name="usernames[]" multiple="multiple" size="5">{S_USERNAME_OPTIONS}</select><!-- ELSE --><b class="genmed">{L_NO_FOES}</b><!-- ENDIF --></td>
-</tr>
-<tr>
- <td class="row1"><b class="genmed">{L_ADD_FOES}{L_COLON}</b><br /><span class="gensmall">{L_ADD_FOES_EXPLAIN} [ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</span></td>
- <td class="row2" align="center"><textarea name="add" rows="5" cols="30">{USERNAMES}</textarea><br /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/ucp_zebra_friends.html b/phpBB/styles/subsilver2/template/ucp_zebra_friends.html
deleted file mode 100644
index 3e18af9969..0000000000
--- a/phpBB/styles/subsilver2/template/ucp_zebra_friends.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- INCLUDE ucp_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th colspan="2" valign="middle">{L_TITLE}</th>
-</tr>
-<!-- EVENT ucp_friend_list_before -->
-<tr>
- <td class="row3" colspan="2"><span class="gensmall">{L_FRIENDS_EXPLAIN}</span></td>
-</tr>
-<!-- IF ERROR -->
- <tr>
- <td class="row3" colspan="2" align="center"><span class="gensmall error">{ERROR}</span></td>
- </tr>
-<!-- ENDIF -->
-<tr>
- <td class="row1" width="40%"><b class="genmed">{L_YOUR_FRIENDS}{L_COLON}</b><br /><span class="gensmall">{L_YOUR_FRIENDS_EXPLAIN}</span></td>
- <td class="row2" align="center"><!-- IF S_USERNAME_OPTIONS --><select name="usernames[]" multiple="multiple" size="5">{S_USERNAME_OPTIONS}</select><!-- ELSE --><b class="genmed">{L_NO_FRIENDS}</b><!-- ENDIF --></td>
-</tr>
-<!-- EVENT ucp_friend_list_after -->
-<tr>
- <td class="row1"><b class="genmed">{L_ADD_FRIENDS}{L_COLON}</b><br /><span class="gensmall">{L_ADD_FRIENDS_EXPLAIN} [ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</span></td>
- <td class="row2" align="center"><textarea name="add" rows="5" cols="30">{USERNAMES}</textarea><br /></td>
-</tr>
-<tr>
- <td class="cat" colspan="2" align="center">{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />&nbsp;&nbsp;<input class="btnlite" type="reset" value="{L_RESET}" name="reset" /></td>
-</tr>
-</table>
-
-<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/viewforum_body.html b/phpBB/styles/subsilver2/template/viewforum_body.html
deleted file mode 100644
index c76c081ba7..0000000000
--- a/phpBB/styles/subsilver2/template/viewforum_body.html
+++ /dev/null
@@ -1,381 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- IF S_FORUM_RULES -->
- <div class="forumrules<!-- IF U_FORUM_RULES --> rules-link<!-- ENDIF -->">
- <!-- IF U_FORUM_RULES -->
- <h3>{L_FORUM_RULES}</h3><br />
- <a href="{U_FORUM_RULES}"><b>{L_FORUM_RULES_LINK}</b></a>
- <!-- ELSE -->
- <h3>{L_FORUM_RULES}</h3><br />
- {FORUM_RULES}
- <!-- ENDIF -->
- </div>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<!-- IF S_DISPLAY_ACTIVE -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat" colspan="<!-- IF S_TOPIC_ICONS -->7<!-- ELSE -->6<!-- ENDIF -->"><span class="nav">{L_ACTIVE_TOPICS}</span></td>
- </tr>
-
- <tr>
- <!-- IF S_TOPIC_ICONS -->
- <th colspan="3">&nbsp;{L_TOPICS}&nbsp;</th>
- <!-- ELSE -->
- <th colspan="2">&nbsp;{L_TOPICS}&nbsp;</th>
- <!-- ENDIF -->
- <th>&nbsp;{L_AUTHOR}&nbsp;</th>
- <th>&nbsp;{L_REPLIES}&nbsp;</th>
- <th>&nbsp;{L_VIEWS}&nbsp;</th>
- <th>&nbsp;{L_LAST_POST}&nbsp;</th>
- </tr>
-
- <!-- EVENT viewforum_body_topic_row_before -->
-
- <!-- BEGIN topicrow -->
-
- <!-- EVENT viewforum_body_topicrow_row_before -->
- <tr>
- <!-- EVENT viewforum_body_topic_row_prepend -->
- <td class="row1" width="25" align="center">{topicrow.TOPIC_FOLDER_IMG}</td>
- <!-- IF S_TOPIC_ICONS -->
- <td class="row1" width="25" align="center"><!-- IF topicrow.TOPIC_ICON_IMG --><img src="{T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}" width="{topicrow.TOPIC_ICON_IMG_WIDTH}" height="{topicrow.TOPIC_ICON_IMG_HEIGHT}" alt="" title="" /><!-- ENDIF --></td>
- <!-- ENDIF -->
- <td class="row1">
- <!-- EVENT topiclist_row_prepend -->
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="imageset">{NEWEST_POST_IMG}</a><!-- ENDIF -->
- {topicrow.ATTACH_ICON_IMG} <!-- IF topicrow.S_HAS_POLL or topicrow.S_TOPIC_MOVED --><b>{topicrow.TOPIC_TYPE}</b> <!-- ENDIF --><a title="{L_POSTED}{L_COLON} {topicrow.FIRST_POST_TIME}" href="{topicrow.U_VIEW_TOPIC}"class="topictitle">{topicrow.TOPIC_TITLE}</a>
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED -->
- <a href="{topicrow.U_MCP_QUEUE}" class="imageset">{topicrow.UNAPPROVED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_DELETED -->
- <a href="{topicrow.U_MCP_QUEUE}" class="imageset">{DELETED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED -->
- <a href="{topicrow.U_MCP_REPORT}" class="imageset">{REPORTED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- EVENT topiclist_row_topic_title_after -->
- <!-- IF .topicrow.pagination -->
- <p class="gensmall"> [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON}
- <!-- BEGIN pagination -->
- <!-- IF topicrow.pagination.S_IS_PREV -->
- <!-- ELSEIF topicrow.pagination.S_IS_CURRENT --><strong>{topicrow.pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF topicrow.pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF topicrow.pagination.S_IS_NEXT -->
- <!-- ELSE --><a href="{topicrow.pagination.PAGE_URL}">{topicrow.pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
- ] </p>
- <!-- ENDIF -->
- <!-- EVENT topiclist_row_append -->
- </td>
- <td class="row2" width="130" align="center"><p class="topicauthor">{topicrow.TOPIC_AUTHOR_FULL}</p></td>
- <td class="row1" width="50" align="center"><p class="topicdetails">{topicrow.REPLIES}</p></td>
- <td class="row2" width="50" align="center"><p class="topicdetails">{topicrow.VIEWS}</p></td>
- <td class="row1" width="140" align="center">
- <p class="topicdetails" style="white-space: nowrap;">{topicrow.LAST_POST_TIME}</p>
- <p class="topicdetails">{topicrow.LAST_POST_AUTHOR_FULL}
- <!-- IF not S_IS_BOT --><a href="{topicrow.U_LAST_POST}" class="imageset">{LAST_POST_IMG}</a><!-- ENDIF -->
- </p>
- </td>
- <!-- EVENT viewforum_body_topic_row_append -->
- </tr>
- <!-- EVENT viewforum_body_topic_row_after -->
-
- <!-- BEGINELSE -->
-
- <tr>
- <!-- IF S_TOPIC_ICONS -->
- <td class="row1" colspan="7" height="30" align="center" valign="middle"><span class="gen"><!-- IF not S_SORT_DAYS -->{L_NO_TOPICS}<!-- ELSE -->{L_NO_TOPICS_TIME_FRAME}<!-- ENDIF --></span></td>
- <!-- ELSE -->
- <td class="row1" colspan="6" height="30" align="center" valign="middle"><span class="gen"><!-- IF not S_SORT_DAYS -->{L_NO_TOPICS}<!-- ELSE -->{L_NO_TOPICS_TIME_FRAME}<!-- ENDIF --></span></td>
- <!-- ENDIF -->
- </tr>
- <!-- END topicrow -->
-
- <tr align="center">
- <td class="cat" colspan="<!-- IF S_TOPIC_ICONS -->7<!-- ELSE -->6<!-- ENDIF -->">&nbsp;</td>
- </tr>
- </table>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<!-- IF S_HAS_SUBFORUM -->
- <!-- INCLUDE forumlist_body.html -->
- <br clear="all" />
-<!-- ENDIF -->
-
-<!-- IF S_IS_POSTABLE or S_NO_READ_ACCESS -->
- <div id="pageheader">
- <!-- EVENT viewforum_forum_title_before -->
- <h2><!-- EVENT viewforum_forum_name_prepend --><a class="titles" href="{U_VIEW_FORUM}">{FORUM_NAME}</a><!-- EVENT viewforum_forum_name_append --></h2>
- <!-- EVENT viewforum_forum_title_after -->
- <!-- IF MODERATORS -->
- <p class="moderators"><!-- IF S_SINGLE_MODERATOR -->{L_MODERATOR}<!-- ELSE -->{L_MODERATORS}<!-- ENDIF -->{L_COLON} {MODERATORS}</p>
- <!-- ENDIF -->
- <!-- IF U_MCP -->
- <p class="linkmcp">[&nbsp;<!-- IF U_ACP --><a href="{U_ACP}">{L_ACP}</a><!-- IF U_MCP -->&nbsp;|&nbsp;<!-- ENDIF --><!-- ENDIF --><!-- IF U_MCP --><a href="{U_MCP}">{L_MCP}</a><!-- ENDIF -->&nbsp;]</p>
- <!-- ENDIF -->
- </div>
-
- <br clear="all" /><br />
-<!-- ENDIF -->
-
-<div id="pagecontent">
-
-<!-- IF S_NO_READ_ACCESS -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row1" height="30" align="center" valign="middle"><span class="gen">{L_NO_READ_ACCESS}</span></td>
- </tr>
- </table>
-
- <!-- IF not S_USER_LOGGED_IN and not S_IS_BOT -->
-
- <br /><br />
-
- <form method="post" action="{S_LOGIN_ACTION}">
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat"><h4><a href="{U_LOGIN_LOGOUT}">{L_LOGIN_LOGOUT}</a></h4></td>
- </tr>
- <tr>
- <td class="row1" align="center"><span class="genmed">{L_USERNAME}{L_COLON}</span> <input class="post" type="text" name="username" size="10" />&nbsp; <span class="genmed">{L_PASSWORD}{L_COLON}</span> <input class="post" type="password" name="password" size="10" autocomplete="off" /><!-- IF S_AUTOLOGIN_ENABLED -->&nbsp; <span class="gensmall">{L_LOG_ME_IN}</span> <input type="checkbox" class="radio" name="autologin" /><!-- ENDIF -->&nbsp; <input type="submit" class="btnmain" name="login" value="{L_LOGIN}" /></td>
- </tr>
- </table>
- {S_LOGIN_REDIRECT}
- </form>
-
- <!-- ENDIF -->
-
- <br clear="all" />
-<!-- ENDIF -->
-
- <!-- IF S_DISPLAY_POST_INFO or TOTAL_TOPICS -->
- <table width="100%" cellspacing="1">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" valign="middle" nowrap="nowrap">
- <!-- EVENT viewforum_buttons_top_before -->
-
- <!-- IF S_DISPLAY_POST_INFO and not S_IS_BOT -->
- <a href="{U_POST_NEW_TOPIC}" class="imageset">{POST_IMG}</a>
- <!-- ENDIF -->
-
- <!-- EVENT viewforum_buttons_top_after -->
- </td>
-
- <!-- IF TOTAL_TOPICS -->
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {TOTAL_TOPICS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- <!-- ENDIF -->
- </tr>
- </table>
- <!-- ENDIF -->
-
- <!-- IF not S_DISPLAY_ACTIVE and (S_IS_POSTABLE or .topicrow) -->
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat" colspan="<!-- IF S_TOPIC_ICONS -->7<!-- ELSE -->6<!-- ENDIF -->">
- <table width="100%" cellspacing="0">
- <tr class="nav">
- <td valign="middle">&nbsp;<!-- IF U_WATCH_FORUM_LINK and not S_IS_BOT --><a href="{U_WATCH_FORUM_LINK}">{S_WATCH_FORUM_TITLE}</a><!-- ENDIF --></td>
- <td align="{S_CONTENT_FLOW_END}" valign="middle"><!-- IF not S_IS_BOT and U_MARK_TOPICS and .topicrow --><a href="{U_MARK_TOPICS}">{L_MARK_TOPICS_READ}</a><!-- ENDIF -->&nbsp;</td>
- </tr>
- </table>
- </td>
- </tr>
-
- <tr>
- <!-- IF S_TOPIC_ICONS -->
- <th colspan="3">&nbsp;{L_TOPICS}&nbsp;</th>
- <!-- ELSE -->
- <th colspan="2">&nbsp;{L_TOPICS}&nbsp;</th>
- <!-- ENDIF -->
- <th>&nbsp;{L_AUTHOR}&nbsp;</th>
- <th>&nbsp;{L_REPLIES}&nbsp;</th>
- <th>&nbsp;{L_VIEWS}&nbsp;</th>
- <th>&nbsp;{L_LAST_POST}&nbsp;</th>
- </tr>
-
- <!-- BEGIN topicrow -->
-
- <!-- IF topicrow.S_TOPIC_TYPE_SWITCH eq 1 -->
- <tr>
- <td class="row3" colspan="<!-- IF S_TOPIC_ICONS -->7<!-- ELSE -->6<!-- ENDIF -->"><b class="gensmall">{L_ANNOUNCEMENTS}</b></td>
- </tr>
- <!-- ELSEIF topicrow.S_TOPIC_TYPE_SWITCH eq 0 -->
- <tr>
- <td class="row3" colspan="<!-- IF S_TOPIC_ICONS -->7<!-- ELSE -->6<!-- ENDIF -->"><b class="gensmall">{L_TOPICS}</b></td>
- </tr>
- <!-- ENDIF -->
-
- <tr>
- <td class="row1" width="25" align="center">{topicrow.TOPIC_FOLDER_IMG}</td>
- <!-- IF S_TOPIC_ICONS -->
- <td class="row1" width="25" align="center"><!-- IF topicrow.TOPIC_ICON_IMG --><img src="{T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}" width="{topicrow.TOPIC_ICON_IMG_WIDTH}" height="{topicrow.TOPIC_ICON_IMG_HEIGHT}" alt="" title="" /><!-- ENDIF --></td>
- <!-- ENDIF -->
- <td class="row1">
- <!-- EVENT topiclist_row_prepend -->
- <!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="imageset">{NEWEST_POST_IMG}</a><!-- ENDIF -->
- {topicrow.ATTACH_ICON_IMG} <!-- IF topicrow.S_HAS_POLL or topicrow.S_TOPIC_MOVED --><b>{topicrow.TOPIC_TYPE}</b> <!-- ENDIF -->
- <a title="{L_POSTED}{L_COLON} {topicrow.FIRST_POST_TIME}" href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
- <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED -->
- <a href="{topicrow.U_MCP_QUEUE}" class="imageset">{topicrow.UNAPPROVED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_DELETED -->
- <a href="{topicrow.U_MCP_QUEUE}" class="imageset">{DELETED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF topicrow.S_TOPIC_REPORTED -->
- <a href="{topicrow.U_MCP_REPORT}" class="imageset">{REPORTED_IMG}</a>&nbsp;
- <!-- ENDIF -->
- <!-- IF .topicrow.pagination -->
- <p class="gensmall"> [ {GOTO_PAGE_IMG}{L_GOTO_PAGE}{L_COLON}
- <!-- BEGIN pagination -->
- <!-- IF topicrow.pagination.S_IS_PREV -->
- <!-- ELSEIF topicrow.pagination.S_IS_CURRENT --><strong>{topicrow.pagination.PAGE_NUMBER}</strong>
- <!-- ELSEIF topicrow.pagination.S_IS_ELLIPSIS --> {L_ELLIPSIS}
- <!-- ELSEIF topicrow.pagination.S_IS_NEXT -->
- <!-- ELSE --><a href="{topicrow.pagination.PAGE_URL}">{topicrow.pagination.PAGE_NUMBER}</a>
- <!-- ENDIF -->
- <!-- END pagination -->
- ] </p>
- <!-- ENDIF -->
- <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --><p class="gensmall">{L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a></p><!-- ENDIF -->
- <!-- EVENT topiclist_row_append -->
- </td>
- <td class="row2" width="130" align="center"><p class="topicauthor">{topicrow.TOPIC_AUTHOR_FULL}</p></td>
- <td class="row1" width="50" align="center"><p class="topicdetails">{topicrow.REPLIES}</p></td>
- <td class="row2" width="50" align="center"><p class="topicdetails">{topicrow.VIEWS}</p></td>
- <td class="row1" width="140" align="center">
- <p class="topicdetails" style="white-space: nowrap;">{topicrow.LAST_POST_TIME}</p>
- <p class="topicdetails">{topicrow.LAST_POST_AUTHOR_FULL}
- <!-- IF not S_IS_BOT --><a href="{topicrow.U_LAST_POST}" class="imageset">{LAST_POST_IMG}</a><!-- ENDIF -->
- </p>
- </td>
- </tr>
-
- <!-- BEGINELSE -->
- <!-- IF S_IS_POSTABLE -->
- <tr>
- <!-- IF S_TOPIC_ICONS -->
- <td class="row1" colspan="7" height="30" align="center" valign="middle"><span class="gen"><!-- IF not S_SORT_DAYS -->{L_NO_TOPICS}<!-- ELSE -->{L_NO_TOPICS_TIME_FRAME}<!-- ENDIF --></span></td>
- <!-- ELSE -->
- <td class="row1" colspan="6" height="30" align="center" valign="middle"><span class="gen"><!-- IF not S_SORT_DAYS -->{L_NO_TOPICS}<!-- ELSE -->{L_NO_TOPICS_TIME_FRAME}<!-- ENDIF --></span></td>
- <!-- ENDIF -->
- </tr>
- <!-- ENDIF -->
- <!-- END topicrow -->
-
- <!-- IF not S_IS_BOT -->
- <tr align="center">
- <!-- IF S_TOPIC_ICONS -->
- <td class="cat" colspan="7">
- <!-- ELSE -->
- <td class="cat" colspan="6">
- <!-- ENDIF -->
- <form method="post" action="{S_FORUM_ACTION}"><span class="gensmall">{L_DISPLAY_TOPICS}{L_COLON}</span>&nbsp;{S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" name="sort" value="{L_GO}" /></form>
- </td>
- </tr>
- <!-- ENDIF -->
- </table>
- <!-- ENDIF -->
-
- <!-- IF S_DISPLAY_POST_INFO or TOTAL_TOPICS -->
- <table width="100%" cellspacing="1">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" valign="middle" nowrap="nowrap">
- <!-- EVENT viewforum_buttons_bottom_before -->
-
- <!-- IF S_DISPLAY_POST_INFO and not S_IS_BOT -->
- <a href="{U_POST_NEW_TOPIC}" class="imageset">{POST_IMG}</a>
- <!-- ENDIF -->
-
- <!-- EVENT viewforum_buttons_bottom_after -->
- </td>
-
- <!-- IF TOTAL_TOPICS -->
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {TOTAL_TOPICS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- <!-- ENDIF -->
- </tr>
- </table>
- <!-- ENDIF -->
-
- <br clear="all" />
-</div>
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<!-- IF S_DISPLAY_ONLINE_LIST -->
- <br clear="all" />
-
- <table class="tablebg stat-block online-list" width="100%" cellspacing="1">
- <tr>
- <td class="cat"><h4>{L_WHO_IS_ONLINE}</h4></td>
- </tr>
- <tr>
- <td class="row1"><p class="gensmall">{LOGGED_IN_USER_LIST}</p></td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-<!-- IF S_DISPLAY_POST_INFO -->
- <br clear="all" />
-
- <table width="100%" cellspacing="0">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" valign="top">
- <table cellspacing="3" cellpadding="0" border="0">
- <tr>
- <td width="20" style="text-align: center;">{FOLDER_UNREAD_IMG}</td>
- <td class="gensmall">{L_UNREAD_POSTS}</td>
- <td>&nbsp;&nbsp;</td>
- <td width="20" style="text-align: center;">{FOLDER_IMG}</td>
- <td class="gensmall">{L_NO_UNREAD_POSTS}</td>
- <td>&nbsp;&nbsp;</td>
- <td width="20" style="text-align: center;">{FOLDER_ANNOUNCE_IMG}</td>
- <td class="gensmall">{L_ICON_ANNOUNCEMENT}</td>
- </tr>
- <tr>
- <td style="text-align: center;">{FOLDER_HOT_UNREAD_IMG}</td>
- <td class="gensmall">{L_UNREAD_POSTS_HOT}</td>
- <td>&nbsp;&nbsp;</td>
- <td style="text-align: center;">{FOLDER_HOT_IMG}</td>
- <td class="gensmall">{L_NO_UNREAD_POSTS_HOT}</td>
- <td>&nbsp;&nbsp;</td>
- <td style="text-align: center;">{FOLDER_STICKY_IMG}</td>
- <td class="gensmall">{L_ICON_STICKY}</td>
- </tr>
- <tr>
- <td style="text-align: center;">{FOLDER_LOCKED_UNREAD_IMG}</td>
- <td class="gensmall">{L_UNREAD_POSTS_LOCKED}</td>
- <td>&nbsp;&nbsp;</td>
- <td style="text-align: center;">{FOLDER_LOCKED_IMG}</td>
- <td class="gensmall">{L_NO_UNREAD_POSTS_LOCKED}</td>
- <td>&nbsp;&nbsp;</td>
- <td style="text-align: center;">{FOLDER_MOVED_IMG}</td>
- <td class="gensmall">{L_TOPIC_MOVED}</td>
- </tr>
- </table>
- </td>
- <td align="{S_CONTENT_FLOW_END}"><span class="gensmall"><!-- BEGIN rules -->{rules.RULE}<br /><!-- END rules --></span></td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-<br clear="all" />
-
-<table width="100%" cellspacing="0">
-<tr>
- <td><!-- IF S_DISPLAY_SEARCHBOX --><!-- INCLUDE searchbox.html --><!-- ENDIF --></td>
- <td align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></td>
-</tr>
-</table>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/viewonline_body.html b/phpBB/styles/subsilver2/template/viewonline_body.html
deleted file mode 100644
index 70b8b52efa..0000000000
--- a/phpBB/styles/subsilver2/template/viewonline_body.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<h4>{TOTAL_REGISTERED_USERS_ONLINE}</h4>
-<h4>{TOTAL_GUEST_USERS_ONLINE}<!-- IF S_SWITCH_GUEST_DISPLAY --> [ <a href="{U_SWITCH_GUEST_DISPLAY}">{L_SWITCH_GUEST_DISPLAY}</a> ]<!-- ENDIF --></h4>
-<br />
-
-<!-- IF .pagination -->
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th width="40%"><a href="{U_SORT_USERNAME}">{L_USERNAME}</a></th>
- <th width="20%"><a href="{U_SORT_UPDATED}">{L_LAST_UPDATED}</a></th>
- <th width="40%"><a href="{U_SORT_LOCATION}">{L_FORUM_LOCATION}</a></th>
-</tr>
-<!-- BEGIN user_row -->
- <tr>
- <td class="row1"><p class="gen">{user_row.USERNAME_FULL}</p><!-- IF user_row.USER_IP --><p class="gensmall">{L_IP}{L_COLON} <a href="{user_row.U_USER_IP}">{user_row.USER_IP}</a> &#187; <a href="{user_row.U_WHOIS}" onclick="popup(this.href, 750, 500); return false;">{L_WHOIS}</a></p><!-- ENDIF -->
- <!-- IF user_row.USER_BROWSER -->{user_row.USER_BROWSER}<!-- ENDIF --></td>
- <td class="row2" align="center" nowrap="nowrap"><p class="genmed">&nbsp;{user_row.LASTUPDATE}</p></td>
- <td class="row1"><p class="genmed"><a href="{user_row.U_FORUM_LOCATION}">{user_row.FORUM_LOCATION}</a></p></td>
- </tr>
-<!-- END user_row -->
-
-<!-- IF LEGEND -->
- <tr>
- <td class="row1" colspan="3"><b class="gensmall">{L_LEGEND} :: {LEGEND}</b></td>
- </tr>
-<!-- ENDIF -->
-</table>
-
-<!-- IF .pagination -->
- <table width="100%" cellspacing="1">
- <tr>
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-<div class="gensmall" align="{S_CONTENT_FLOW_END}">{L_ONLINE_EXPLAIN}</div>
-
-<br clear="all" />
-
-<!-- INCLUDE breadcrumbs.html -->
-
-<br clear="all" />
-
-<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/viewonline_whois.html b/phpBB/styles/subsilver2/template/viewonline_whois.html
deleted file mode 100644
index ca5b326df8..0000000000
--- a/phpBB/styles/subsilver2/template/viewonline_whois.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!-- INCLUDE simple_header.html -->
-
-<table class="tablebg" width="100%" cellspacing="1">
-<tr>
- <th>{L_WHOIS}</th>
-</tr>
-<tr>
- <td class="row1"><pre>{WHOIS}</pre><br /><a class="nav" href="#" onclick="window.close(); return false;">{L_CLOSE_WINDOW}</a></td>
-</tr>
-</table>
-
-<!-- INCLUDE simple_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/viewtopic_body.html b/phpBB/styles/subsilver2/template/viewtopic_body.html
deleted file mode 100644
index e340334cf8..0000000000
--- a/phpBB/styles/subsilver2/template/viewtopic_body.html
+++ /dev/null
@@ -1,462 +0,0 @@
-<!-- INCLUDE overall_header.html -->
-
-<!-- IF S_FORUM_RULES -->
- <div class="forumrules<!-- IF U_FORUM_RULES --> rules-link<!-- ENDIF -->">
- <!-- IF U_FORUM_RULES -->
- <h3>{L_FORUM_RULES}</h3><br />
- <a href="{U_FORUM_RULES}"><b>{L_FORUM_RULES_LINK}</b></a>
- <!-- ELSE -->
- <h3>{L_FORUM_RULES}</h3><br />
- {FORUM_RULES}
- <!-- ENDIF -->
- </div>
-
- <br clear="all" />
-<!-- ENDIF -->
-
-<div id="pageheader">
- <h2><!-- EVENT viewtopic_topic_title_prepend --><a class="titles" href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a><!-- EVENT viewtopic_topic_title_append --></h2>
- <!-- EVENT viewtopic_topic_title_after -->
-
-<!-- IF MODERATORS -->
- <p class="moderators"><!-- IF S_SINGLE_MODERATOR -->{L_MODERATOR}<!-- ELSE -->{L_MODERATORS}<!-- ENDIF -->{L_COLON} {MODERATORS}</p>
-<!-- ENDIF -->
-<!-- IF U_MCP -->
- <p class="linkmcp">[&nbsp;<!-- IF U_ACP --><a href="{U_ACP}">{L_ACP}</a><!-- IF U_MCP -->&nbsp;|&nbsp;<!-- ENDIF --><!-- ENDIF --><!-- IF U_MCP --><a href="{U_MCP}">{L_MCP}</a><!-- ENDIF -->&nbsp;]</p>
-<!-- ENDIF -->
-</div>
-
-<br clear="all" /><br />
-
-<div id="pagecontent">
-
- <table width="100%" cellspacing="1">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" valign="middle" nowrap="nowrap">
- <!-- EVENT viewtopic_buttons_top_before -->
-
- <!-- IF not S_IS_BOT -->
- <!-- IF S_DISPLAY_POST_INFO --><a href="{U_POST_NEW_TOPIC}" class="imageset">{POST_IMG}</a>&nbsp;<!-- ENDIF -->
- <!-- IF S_DISPLAY_REPLY_INFO --><a href="{U_POST_REPLY_TOPIC}" class="imageset">{REPLY_IMG}</a><!-- ENDIF -->
- <!-- ENDIF -->
-
- <!-- EVENT viewtopic_buttons_top_after -->
- </td>
- <!-- IF TOTAL_POSTS -->
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {TOTAL_POSTS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --><!-- EVENT viewtopic_body_pagination_top_after --></td>
- <!-- ENDIF -->
- </tr>
- </table>
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="cat">
- <table width="100%" cellspacing="0">
- <tr>
- <td class="nav" nowrap="nowrap">&nbsp;
- <!-- IF not S_IS_BOT -->
- <!-- IF U_WATCH_TOPIC --><a href="{U_WATCH_TOPIC}" title="{S_WATCH_TOPIC_TITLE}">{S_WATCH_TOPIC_TITLE}</a><!-- IF U_PRINT_TOPIC or U_EMAIL_TOPIC or U_BUMP_TOPIC or U_BOOKMARK_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
- <!-- IF U_BOOKMARK_TOPIC --><a href="{U_BOOKMARK_TOPIC}" title="{S_BOOKMARK_TOPIC}">{S_BOOKMARK_TOPIC}</a><!-- IF U_PRINT_TOPIC or U_EMAIL_TOPIC or U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
- <!-- IF U_PRINT_TOPIC --><a href="{U_PRINT_TOPIC}" title="{L_PRINT_TOPIC}">{L_PRINT_TOPIC}</a><!-- IF U_EMAIL_TOPIC or U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
- <!-- IF U_EMAIL_TOPIC --><a href="{U_EMAIL_TOPIC}" title="{L_EMAIL_TOPIC}">{L_EMAIL_TOPIC}</a><!-- IF U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
- <!-- IF U_BUMP_TOPIC --><a href="{U_BUMP_TOPIC}" title="{L_BUMP_TOPIC}">{L_BUMP_TOPIC}</a><!-- ENDIF -->
- <!-- ENDIF -->
- </td>
- <td class="nav" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><a href="{U_VIEW_OLDER_TOPIC}">{L_VIEW_PREVIOUS_TOPIC}</a><!-- IF U_VIEW_UNREAD_POST and not S_IS_BOT --> | <a href="{U_VIEW_UNREAD_POST}">{L_VIEW_UNREAD_POST}</a><!-- ENDIF --> | <a href="{U_VIEW_NEWER_TOPIC}">{L_VIEW_NEXT_TOPIC}</a>&nbsp;</td>
- </tr>
- </table>
- </td>
- </tr>
-<!-- EVENT viewtopic_body_poll_before -->
-<!-- IF S_HAS_POLL -->
- <tr>
- <td class="row2" colspan="2" align="center"><br clear="all" />
-
- <form method="post" action="{S_POLL_ACTION}">
-
- <table cellspacing="0" cellpadding="4" border="0" align="center">
- <tr>
- <td align="center"><span class="gen"><!-- EVENT viewtopic_body_poll_question_prepend --><b>{POLL_QUESTION}</b><!-- EVENT viewtopic_body_poll_question_append --></span><br /><span class="gensmall">{L_POLL_LENGTH}</span></td>
- </tr>
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}">
- <table cellspacing="0" cellpadding="2" border="0">
- <!-- BEGIN poll_option -->
- <tr>
- <!-- EVENT viewtopic_body_poll_option_before -->
- <!-- IF S_CAN_VOTE -->
- <td<!-- IF poll_option.POLL_OPTION_MOST_VOTES --> class="most-votes"<!-- ENDIF -->>
- <!-- IF S_IS_MULTI_CHOICE -->
- <input type="checkbox" class="radio" name="vote_id[]" value="{poll_option.POLL_OPTION_ID}"<!-- IF poll_option.POLL_OPTION_VOTED --> checked="checked"<!-- ENDIF --> />
- <!-- ELSE -->
- <input type="radio" class="radio" name="vote_id[]" value="{poll_option.POLL_OPTION_ID}"<!-- IF poll_option.POLL_OPTION_VOTED --> checked="checked"<!-- ENDIF --> />
- <!-- ENDIF -->
- </td>
- <!-- ENDIF -->
- <td><span class="gen">{poll_option.POLL_OPTION_CAPTION}</span></td>
- <!-- IF S_DISPLAY_RESULTS -->
- <td dir="ltr">{POLL_LEFT_CAP_IMG}<span class="imageset poll_center" style="width: {poll_option.POLL_OPTION_WIDTH}px; background-repeat: repeat-x;">{poll_option.POLL_OPTION_PERCENT}</span>{POLL_RIGHT_CAP_IMG}</td>
- <td class="gen" align="{S_CONTENT_FLOW_END}"><b>&nbsp;{poll_option.POLL_OPTION_PERCENT}&nbsp;</b></td>
- <td class="gen" align="center">[ {poll_option.POLL_OPTION_RESULT} ]</td>
- <!-- IF poll_option.POLL_OPTION_VOTED -->
- <td class="gensmall" valign="top"><b title="{L_POLL_VOTED_OPTION}">x</b></td>
- <!-- ENDIF -->
- <!-- ENDIF -->
- <!-- EVENT viewtopic_body_poll_option_after -->
- </tr>
- <!-- END poll_option -->
- </table>
- </td>
- </tr>
- <!-- IF S_CAN_VOTE -->
- <tr>
- <td align="center"><span class="gensmall">{L_MAX_VOTES}</span><br /><br /><input type="submit" name="update" value="{L_SUBMIT_VOTE}" class="btnlite" /></td>
- </tr>
- <!-- ENDIF -->
- <!-- IF S_DISPLAY_RESULTS -->
- <tr>
- <td class="gensmall" colspan="4" align="center"><b>{L_TOTAL_VOTES}{L_COLON} {TOTAL_VOTES}</b></td>
- </tr>
- <!-- ELSE -->
- <tr>
- <td align="center"><span class="gensmall"><b><a href="{U_VIEW_RESULTS}">{L_VIEW_RESULTS}</a></b></span></td>
- </tr>
- <!-- ENDIF -->
- </table>
- {S_HIDDEN_FIELDS}
- {S_FORM_TOKEN}
- </form>
-
- </td>
- </tr>
-<!-- ENDIF -->
-<!-- EVENT viewtopic_body_poll_after -->
- </table>
-
-<!-- BEGIN postrow -->
- <!-- EVENT viewtopic_body_postrow_post_before -->
- <table class="tablebg" width="100%" cellspacing="1">
- <!-- IF postrow.S_FIRST_ROW -->
- <tr>
- <th>{L_AUTHOR}</th>
- <th>{L_MESSAGE}</th>
- </tr>
- <!-- ENDIF -->
- <!-- IF postrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <!-- IF postrow.S_POST_HIDDEN -->
- <td class="gensmall" colspan="2" height="25" align="center">
- <!-- IF postrow.S_FIRST_UNREAD --><a id="unread" class="anchor" data-url="{postrow.U_MINI_POST}"></a><!-- ENDIF -->
- <a name="p{postrow.POST_ID}" class="anchor"></a>
- <!-- IF postrow.S_POST_HIDDEN -->
- <!-- IF postrow.S_POST_DELETED -->
- {postrow.L_POST_DELETED_MESSAGE}
- <!-- ELSEIF postrow.S_IGNORE_POST -->
- {postrow.L_IGNORE_POST}
- <!-- ENDIF -->
- <br />{postrow.L_POST_DISPLAY}
- <!-- ENDIF -->
- </td>
- <!-- ELSE -->
-
- <td align="center" valign="middle">
- <!-- IF postrow.S_FIRST_UNREAD -->
- <a id="unread" class="anchor"<!-- IF S_UNREAD_VIEW --> data-url="{postrow.U_MINI_POST}"<!-- ENDIF -->></a>
- <!-- ENDIF -->
- <a name="p{postrow.POST_ID}" class="anchor"></a>
- <!-- EVENT viewtopic_body_post_author_before -->
- <b class="postauthor"<!-- IF postrow.POST_AUTHOR_COLOUR --> style="color: {postrow.POST_AUTHOR_COLOUR}"<!-- ENDIF -->>{postrow.POST_AUTHOR}</b>
- <!-- EVENT viewtopic_body_post_author_after -->
- </td>
- <!-- EVENT viewtopic_body_postrow_post_details_before -->
- <!-- EVENT viewtopic_body_post_subject_before -->
- <td width="100%" height="25">
- <table width="100%" cellspacing="0">
- <tr>
- <!-- IF postrow.POST_ICON_IMG -->
- <td><img src="{T_ICONS_PATH}{postrow.POST_ICON_IMG}" width="{postrow.POST_ICON_IMG_WIDTH}" height="{postrow.POST_ICON_IMG_HEIGHT}" alt="" title="" /></td>
- <!-- ENDIF -->
- <td class="gensmall" width="100%"><div style="float: {S_CONTENT_FLOW_BEGIN};">&nbsp;<b>{L_POST_SUBJECT}{L_COLON}</b> <a href="#p{postrow.POST_ID}">{postrow.POST_SUBJECT}</a></div><div style="float: {S_CONTENT_FLOW_END};"><!-- IF S_IS_BOT -->{postrow.MINI_POST_IMG}<!-- ELSE --><a href="{postrow.U_MINI_POST}" class="imageset">{postrow.MINI_POST_IMG}</a><!-- ENDIF --><b>{L_POSTED}{L_COLON}</b> {postrow.POST_DATE}&nbsp;</div></td>
- </tr>
- </table>
- </td>
- <!-- EVENT viewtopic_body_postrow_post_details_after -->
- </tr>
-
- <!-- IF postrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <td valign="top" class="profile">
- <table cellspacing="4" align="center" width="150">
- <!-- IF postrow.ONLINE_IMG -->
- <tr>
- <td>{postrow.ONLINE_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT viewtopic_body_postrow_rank_before -->
- <!-- IF postrow.RANK_TITLE -->
- <tr>
- <td class="postdetails">{postrow.RANK_TITLE}</td>
- </tr>
- <!-- ENDIF -->
- <!-- IF postrow.RANK_IMG -->
- <tr>
- <td>{postrow.RANK_IMG}</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT viewtopic_body_postrow_rank_after -->
-
- <!-- EVENT viewtopic_body_avatar_before -->
- <!-- IF postrow.POSTER_AVATAR -->
- <tr>
- <td>{postrow.POSTER_AVATAR}</td>
- </tr>
- <!-- ENDIF -->
- <!-- EVENT viewtopic_body_avatar_after -->
-
- <!-- IF not (postrow.ONLINE_IMG or postrow.RANK_TITLE or postrow.RANK_IMG or postrow.POSTER_AVATAR) -->
- <tr>
- <td></td>
- </tr>
- <!-- ENDIF -->
- </table>
-
- <span class="postdetails">
- <!-- IF postrow.POSTER_JOINED --><br /><b>{L_JOINED}{L_COLON}</b> {postrow.POSTER_JOINED}<!-- ENDIF -->
- <!-- IF postrow.POSTER_POSTS != '' --><br /><b>{L_POSTS}{L_COLON}</b> {postrow.POSTER_POSTS}<!-- ENDIF -->
- <!-- IF postrow.POSTER_WARNINGS --><br /><b>{L_WARNINGS}{L_COLON}</b> {postrow.POSTER_WARNINGS}<!-- ENDIF -->
-
- <!-- IF postrow.S_PROFILE_FIELD1 -->
- <!-- Use a construct like this to include admin defined profile fields. Replace FIELD1 with the name of your field. -->
- <br /><b>{postrow.PROFILE_FIELD1_NAME}{L_COLON}</b> {postrow.PROFILE_FIELD1_VALUE}
- <!-- ENDIF -->
-
- <!-- EVENT viewtopic_body_postrow_custom_fields_before -->
- <!-- BEGIN custom_fields -->
- <!-- IF not postrow.custom_fields.S_PROFILE_CONTACT -->
- <br /><b>{postrow.custom_fields.PROFILE_FIELD_NAME}{L_COLON}</b> {postrow.custom_fields.PROFILE_FIELD_VALUE}
- <!-- ENDIF -->
- <!-- END custom_fields -->
- <!-- EVENT viewtopic_body_postrow_custom_fields_after -->
- </span>
-
- </td>
- <td valign="top">
- <table width="100%" cellspacing="5">
- <tr>
- <td>
- <!-- IF postrow.S_POST_UNAPPROVED or postrow.S_POST_DELETED or postrow.S_POST_REPORTED -->
- <table width="100%" cellspacing="0">
- <tr>
- <td class="gensmall">
- <!-- IF postrow.S_POST_UNAPPROVED --><span class="postapprove">{UNAPPROVED_IMG} <a href="{postrow.U_MCP_APPROVE}">{L_POST_UNAPPROVED}</a></span><br /> <!-- ENDIF -->
- <!-- IF postrow.S_POST_DELETED --><span class="postapprove">{DELETED_IMG} <a href="{postrow.U_MCP_RESTORE}">{L_POST_DELETED}</a></span><br /> <!-- ENDIF -->
- <!-- IF postrow.S_POST_REPORTED --><span class="postreported">{REPORTED_IMG} <a href="{postrow.U_MCP_REPORT}">{L_POST_REPORTED}</a></span><!-- ENDIF -->
- </td>
- </tr>
- </table>
-
- <br clear="all" />
- <!-- ENDIF -->
-
- <div class="postbody">{postrow.MESSAGE}</div>
-
- <!-- IF postrow.S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <!-- IF postrow.attachment.S_ROW_COUNT is even --><td class="row2"><!-- ELSE --><td class="row1"><!-- ENDIF -->{postrow.attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- <!-- IF postrow.S_DISPLAY_NOTICE -->
- <span class="gensmall error"><br /><br />{L_DOWNLOAD_NOTICE}</span>
- <!-- ENDIF -->
- <!-- IF postrow.SIGNATURE -->
- <div class="postbody"><br />_________________<br />{postrow.SIGNATURE}</div>
- <!-- ENDIF -->
-
- <!-- EVENT viewtopic_body_postrow_post_notices_before -->
- <!-- IF postrow.DELETED_MESSAGE or postrow.DELETE_REASON -->
- <!-- IF postrow.DELETE_REASON -->
- <br /><br />
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><span class="gensmall">{postrow.DELETED_MESSAGE}</span></td>
- </tr>
- <tr>
- <td class="row2"><span class="genmed">{postrow.DELETE_REASON}</span></td>
- </tr>
- </table>
- <!-- ELSE -->
- <br /><br />
- <span class="gensmall">{postrow.DELETED_MESSAGE}</span>
- <!-- ENDIF -->
- <!-- ELSEIF postrow.EDITED_MESSAGE or postrow.EDIT_REASON -->
- <!-- IF postrow.EDIT_REASON -->
- <br /><br />
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td class="row3"><span class="gensmall">{postrow.EDITED_MESSAGE}</span></td>
- </tr>
- <tr>
- <td class="row2"><span class="genmed">{postrow.EDIT_REASON}</span></td>
- </tr>
- </table>
- <!-- ELSE -->
- <br /><br />
- <span class="gensmall">{postrow.EDITED_MESSAGE}</span>
- <!-- ENDIF -->
- <!-- ENDIF -->
-
- <!-- IF postrow.BUMPED_MESSAGE -->
- <span class="gensmall"><br /><br />{postrow.BUMPED_MESSAGE}</span>
- <!-- ENDIF -->
- <!-- EVENT viewtopic_body_postrow_post_notices_after -->
-
- <!-- EVENT viewtopic_body_postrow_post_content_footer -->
-
- <!-- IF not postrow.S_HAS_ATTACHMENTS --><br clear="all" /><br /><!-- ENDIF -->
-
- <table width="100%" cellspacing="0">
- <tr valign="middle">
- <td class="gensmall" align="{S_CONTENT_FLOW_END}">
- <!-- IF not S_IS_BOT -->
- <!-- IF postrow.U_REPORT --><a href="{postrow.U_REPORT}" class="imageset">{REPORT_IMG}</a> <!-- ENDIF -->
- <!-- IF postrow.U_INFO --><a href="{postrow.U_INFO}" class="imageset">{INFO_IMG}</a> <!-- ENDIF -->
- <!-- IF postrow.U_WARN --><a href="{postrow.U_WARN}" class="imageset">{WARN_IMG}</a> <!-- ENDIF -->
- <!-- IF postrow.U_DELETE --><a href="{postrow.U_DELETE}" class="imageset">{DELETE_IMG}</a> <!-- ENDIF -->
- <!-- ENDIF -->
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
-
- <!-- IF postrow.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
-
- <!-- EVENT viewtopic_body_postrow_back2top_before -->
- <td class="profile"><!-- EVENT viewtopic_body_postrow_back2top_prepend --><strong><a href="#wrapheader">{L_BACK_TO_TOP}</a></strong><!-- EVENT viewtopic_body_postrow_back2top_append --></td>
- <!-- EVENT viewtopic_body_postrow_back2top_after -->
- <td>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_BEGIN};">
- &nbsp;<!-- IF postrow.U_POST_AUTHOR --><a href="{postrow.U_POST_AUTHOR}" class="imageset">{PROFILE_IMG}</a><!-- ENDIF -->
- <!-- IF postrow.U_PM --><a href="{postrow.U_PM}" class="imageset">{PM_IMG}</a><!-- ENDIF -->
- <!-- IF postrow.U_EMAIL --><a href="{postrow.U_EMAIL}" class="imageset">{EMAIL_IMG}</a><!-- ENDIF -->
- &nbsp;</div>
- <div class="gensmall" style="float: {S_CONTENT_FLOW_END};">
- <!-- EVENT viewtopic_body_post_buttons_before -->
- <!-- IF not S_IS_BOT -->
- <!-- IF postrow.U_EDIT --><a href="{postrow.U_EDIT}" class="imageset">{EDIT_IMG}</a><!-- ENDIF -->
- <!-- IF postrow.U_QUOTE --><a href="{postrow.U_QUOTE}" class="imageset">{QUOTE_IMG}</a><!-- ENDIF -->
- <!-- ENDIF -->
- <!-- EVENT viewtopic_body_post_buttons_after -->
- &nbsp;</div>
- </td>
- <!-- ENDIF -->
- </tr>
-
- <tr>
- <td class="spacer" colspan="2" height="1"><img src="images/spacer.gif" alt="" width="1" height="1" /></td>
- </tr>
- </table>
- <!-- EVENT viewtopic_body_postrow_post_after -->
-<!-- END postrow -->
-
- <!-- IF not S_IS_BOT -->
- <table width="100%" cellspacing="1" class="tablebg">
- <tr align="center">
- <td class="cat"><form name="viewtopic" method="post" action="{S_TOPIC_ACTION}"><span class="gensmall">{L_DISPLAY_POSTS}{L_COLON}</span> {S_SELECT_SORT_DAYS}&nbsp;<span class="gensmall">{L_SORT_BY}</span> {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR}&nbsp;<input class="btnlite" type="submit" value="{L_GO}" name="sort" /></form></td>
- </tr>
- </table>
- <!-- ENDIF -->
-
- <!-- EVENT viewtopic_body_topic_actions_before -->
-
- <table width="100%" cellspacing="1">
- <tr>
- <td align="{S_CONTENT_FLOW_BEGIN}" valign="middle" nowrap="nowrap">
- <!-- EVENT viewtopic_buttons_bottom_before -->
-
- <!-- IF not S_IS_BOT -->
- <!-- IF S_DISPLAY_POST_INFO --><a href="{U_POST_NEW_TOPIC}" class="imageset">{POST_IMG}</a>&nbsp;<!-- ENDIF -->
- <!-- IF S_DISPLAY_REPLY_INFO --><a href="{U_POST_REPLY_TOPIC}" class="imageset">{REPLY_IMG}</a><!-- ENDIF -->
- <!-- ENDIF -->
-
- <!-- EVENT viewtopic_buttons_bottom_after -->
- </td>
- <!-- IF TOTAL_POSTS -->
- <td class="nav" valign="middle" nowrap="nowrap">&nbsp;{PAGE_NUMBER}<br /></td>
- <td class="gensmall" nowrap="nowrap">&nbsp;[ {TOTAL_POSTS} ]&nbsp;</td>
- <td class="gensmall" width="100%" align="{S_CONTENT_FLOW_END}" nowrap="nowrap"><!-- INCLUDE pagination.html --></td>
- <!-- ENDIF -->
- </tr>
- </table>
-
-</div>
-
-<div id="pagefooter"></div>
-
-<br clear="all" />
-<!-- IF S_QUICK_REPLY -->
-<!-- INCLUDE quickreply_editor.html -->
-<!-- ENDIF -->
-
-<!-- EVENT viewtopic_body_footer_before -->
-<!-- INCLUDE breadcrumbs.html -->
-
-<!-- IF S_DISPLAY_ONLINE_LIST -->
- <br clear="all" />
-
- <table class="tablebg stat-block online-list" width="100%" cellspacing="1">
- <tr>
- <td class="cat"><h4>{L_WHO_IS_ONLINE}</h4></td>
- </tr>
- <tr>
- <td class="row1"><p class="gensmall">{LOGGED_IN_USER_LIST}</p></td>
- </tr>
- </table>
-<!-- ENDIF -->
-
-<br clear="all" />
-
-<table width="100%" cellspacing="1">
-<tr>
- <td width="40%" valign="top" nowrap="nowrap" align="{S_CONTENT_FLOW_BEGIN}">
- <!-- IF .quickmod -->
- <form method="post" action="{S_MOD_ACTION}">
- <span class="gensmall">{L_QUICK_MOD}{L_COLON}</span>
- <select name="action" id="quick-mod-select">
- <!-- BEGIN quickmod -->
- <option value="{quickmod.VALUE}">{quickmod.TITLE}</option>
- <!-- END quickmod -->
- </select>
- <input class="btnlite" type="submit" value="{L_GO}" />
- </form>
- <!-- ENDIF -->
- </td>
- <td align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap"><span class="gensmall"><!-- BEGIN rules -->{rules.RULE}<br /><!-- END rules --></span></td>
-</tr>
-</table>
-
-<br clear="all" />
-
-<table width="100%" cellspacing="0">
-<tr>
- <td><!-- IF S_DISPLAY_SEARCHBOX --><!-- INCLUDE searchbox.html --><!-- ENDIF --></td>
- <td align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></td>
-</tr>
-</table>
-
-<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/viewtopic_print.html b/phpBB/styles/subsilver2/template/viewtopic_print.html
deleted file mode 100644
index 53b38f414e..0000000000
--- a/phpBB/styles/subsilver2/template/viewtopic_print.html
+++ /dev/null
@@ -1,136 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8" />
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-<meta name="robots" content="noindex" />
-<title>{SITENAME} :: {PAGE_TITLE}</title>
-
-<style type="text/css">
-<!--
-
-body {
- font-family: Verdana,serif;
- font-size: 10pt;
-}
-
-img {
- border: 0;
-}
-
-td {
- font-family: Verdana,serif;
- font-size: 10pt;
- line-height: 150%;
-}
-
-.code, .codecontent,
-.quote, .quotecontent {
- margin: 0 5px 0 5px;
- padding: 5px;
- font-size: smaller;
- border: black solid 1px;
-}
-
-.quotetitle {
- color: black;
- display : block;
- font-weight: bold;
-}
-
-.forum {
- font-family: Arial,Helvetica,sans-serif;
- font-weight: bold;
- font-size: 18pt;
-}
-
-.topic {
- font-family: Arial,Helvetica,sans-serif;
- font-size: 14pt;
- font-weight: bold;
-}
-
-.gensmall {
- font-size: 8pt;
-}
-
-hr {
- color: #888;
- height: 3px;
- border-style: solid;
-}
-
-hr.sep {
- color: #aaa;
- height: 1px;
- border-style: dashed;
-}
-//-->
-</style>
-<!-- EVENT viewtopic_print_head_append -->
-</head>
-<body>
-
-<table width="85%" cellspacing="3" cellpadding="0" border="0" align="center">
-<tr>
- <td colspan="2" align="center"><span class="Forum">{SITENAME}</span><br /><span class="gensmall"><a href="{U_FORUM}">{U_FORUM}</a></span></td>
-</tr>
-<tr>
- <td colspan="2"><br /></td>
-</tr>
-<tr>
- <td><span class="topic">{TOPIC_TITLE}</span><br /><span class="gensmall"><a href="{U_TOPIC}">{U_TOPIC}</a></span></td>
- <td align="{S_CONTENT_FLOW_END}" valign="bottom"><span class="gensmall">{PAGE_NUMBER}</span></td>
-</tr>
-</table>
-
-<!-- BEGIN postrow -->
-
- <hr width="85%" />
-
- <table width="85%" cellspacing="3" cellpadding="0" border="0" align="center">
- <tr>
- <td width="10%" nowrap="nowrap">{L_AUTHOR}{L_COLON}&nbsp;</td>
- <td><b>{postrow.POST_AUTHOR}</b> [ {postrow.POST_DATE} ]</td>
- </tr>
- <tr>
- <td width="10%" nowrap="nowrap">{L_POST_SUBJECT}{L_COLON}&nbsp;</td>
- <td><b>{postrow.POST_SUBJECT}</b></td>
- </tr>
- <tr>
- <td colspan="2"><hr class="sep" />{postrow.MESSAGE}
-
- <!-- IF postrow.S_HAS_ATTACHMENTS -->
- <br clear="all" /><br />
-
- <table class="tablebg" width="100%" cellspacing="1">
- <tr>
- <td><b class="genmed">{L_ATTACHMENTS}{L_COLON} </b></td>
- </tr>
- <!-- BEGIN attachment -->
- <tr>
- <td>{postrow.attachment.DISPLAY_ATTACHMENT}</td>
- </tr>
- <!-- END attachment -->
- </table>
- <!-- ENDIF -->
-
- </td>
- </tr>
- </table>
-<!-- END postrow -->
-
-<hr width="85%" />
-
-<table width="85%" cellspacing="3" cellpadding="0" border="0" align="center">
-<tr>
- <td><span class="gensmall">{PAGE_NUMBER}</span></td>
- <td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td>
-</tr>
-<tr>
- <td colspan="2" align="center"><span class="gensmall">Powered by phpBB&reg; Forum Software &copy; phpBB Limited<br />https://www.phpbb.com/</span></td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/phpBB/styles/subsilver2/theme/en/button_pm_new.gif b/phpBB/styles/subsilver2/theme/en/button_pm_new.gif
deleted file mode 100644
index 07df748d3a..0000000000
--- a/phpBB/styles/subsilver2/theme/en/button_pm_new.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/button_pm_reply.gif b/phpBB/styles/subsilver2/theme/en/button_pm_reply.gif
deleted file mode 100644
index c476f06a44..0000000000
--- a/phpBB/styles/subsilver2/theme/en/button_pm_reply.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/button_topic_locked.gif b/phpBB/styles/subsilver2/theme/en/button_topic_locked.gif
deleted file mode 100644
index 124a2d4a7d..0000000000
--- a/phpBB/styles/subsilver2/theme/en/button_topic_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/button_topic_new.gif b/phpBB/styles/subsilver2/theme/en/button_topic_new.gif
deleted file mode 100644
index 66e1007129..0000000000
--- a/phpBB/styles/subsilver2/theme/en/button_topic_new.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/button_topic_reply.gif b/phpBB/styles/subsilver2/theme/en/button_topic_reply.gif
deleted file mode 100644
index e8fe5115a0..0000000000
--- a/phpBB/styles/subsilver2/theme/en/button_topic_reply.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_aim.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_aim.gif
deleted file mode 100644
index c6533e2817..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_aim.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_email.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_email.gif
deleted file mode 100644
index f126a1960d..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_email.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_icq.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_icq.gif
deleted file mode 100644
index ba3fa12436..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_icq.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gif
deleted file mode 100644
index be2e53f9c2..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_jabber.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_msnm.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_msnm.gif
deleted file mode 100644
index 1bf681e9a2..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_msnm.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_pm.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_pm.gif
deleted file mode 100644
index 26ac558c2f..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_pm.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_www.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_www.gif
deleted file mode 100644
index 14a33b36a5..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_www.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_contact_yahoo.gif b/phpBB/styles/subsilver2/theme/en/icon_contact_yahoo.gif
deleted file mode 100644
index d11711789f..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_contact_yahoo.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_delete.gif b/phpBB/styles/subsilver2/theme/en/icon_post_delete.gif
deleted file mode 100644
index e008e5ff9f..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_post_delete.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_edit.gif b/phpBB/styles/subsilver2/theme/en/icon_post_edit.gif
deleted file mode 100644
index 1511ee34d3..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_post_edit.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_info.gif b/phpBB/styles/subsilver2/theme/en/icon_post_info.gif
deleted file mode 100644
index 166de2724f..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_post_info.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_quote.gif b/phpBB/styles/subsilver2/theme/en/icon_post_quote.gif
deleted file mode 100644
index 4cf103280c..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_post_quote.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_post_report.gif b/phpBB/styles/subsilver2/theme/en/icon_post_report.gif
deleted file mode 100644
index 9a3f65b1e3..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_post_report.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_offline.gif b/phpBB/styles/subsilver2/theme/en/icon_user_offline.gif
deleted file mode 100644
index 3065f4d7fe..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_user_offline.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_online.gif b/phpBB/styles/subsilver2/theme/en/icon_user_online.gif
deleted file mode 100644
index b950612c57..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_user_online.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_profile.gif b/phpBB/styles/subsilver2/theme/en/icon_user_profile.gif
deleted file mode 100644
index d9cf7f4c4a..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_user_profile.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_search.gif b/phpBB/styles/subsilver2/theme/en/icon_user_search.gif
deleted file mode 100644
index 46475fbf4c..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_user_search.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/icon_user_warn.gif b/phpBB/styles/subsilver2/theme/en/icon_user_warn.gif
deleted file mode 100644
index 44cbcc953a..0000000000
--- a/phpBB/styles/subsilver2/theme/en/icon_user_warn.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/en/stylesheet.css b/phpBB/styles/subsilver2/theme/en/stylesheet.css
deleted file mode 100644
index 57f9fce26d..0000000000
--- a/phpBB/styles/subsilver2/theme/en/stylesheet.css
+++ /dev/null
@@ -1,116 +0,0 @@
-/* EN Language Pack */
-.imageset.phpbb_aol-icon, .imageset.icon_contact_aim {
- background-image: url("./icon_contact_aim.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_contact_email {
- background-image: url("./icon_contact_email.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_icq-icon, .imageset.icon_contact_icq {
- background-image: url("./icon_contact_icq.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_contact_jabber {
- background-image: url("./icon_contact_jabber.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_wlm-icon, .imageset.icon_contact_msnm {
- background-image: url("./icon_contact_msnm.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_contact_pm {
- background-image: url("./icon_contact_pm.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_yahoo-icon, .imageset.icon_contact_yahoo {
- background-image: url("./icon_contact_yahoo.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_website-icon, .imageset.icon_contact_www {
- background-image: url("./icon_contact_www.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_post_delete {
- background-image: url("./icon_post_delete.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_edit {
- background-image: url("./icon_post_edit.gif");
- padding-left: 90px;
- padding-top: 20px;
-}
-.imageset.icon_post_info {
- background-image: url("./icon_post_info.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_quote {
- background-image: url("./icon_post_quote.gif");
- padding-left: 90px;
- padding-top: 20px;
-}
-.imageset.icon_post_report {
- background-image: url("./icon_post_report.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_user_online {
- background-image: url("./icon_user_online.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_offline {
- background-image: url("./icon_user_offline.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_profile {
- background-image: url("./icon_user_profile.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_search {
- background-image: url("./icon_user_search.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_warn {
- background-image: url("./icon_user_warn.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.button_pm_new {
- background-image: url("./button_pm_new.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-.imageset.button_pm_reply {
- background-image: url("./button_pm_reply.gif");
- padding-left: 90px;
- padding-top: 20px;
-}
-.imageset.button_topic_locked {
- background-image: url("./button_topic_locked.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-.imageset.button_topic_new {
- background-image: url("./button_topic_new.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-.imageset.button_topic_reply {
- background-image: url("./button_topic_reply.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
diff --git a/phpBB/styles/subsilver2/theme/images/announce_read.gif b/phpBB/styles/subsilver2/theme/images/announce_read.gif
deleted file mode 100644
index 0589feb14f..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_read.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_read_locked.gif b/phpBB/styles/subsilver2/theme/images/announce_read_locked.gif
deleted file mode 100644
index a738616e06..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_read_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gif
deleted file mode 100644
index f7ffe7f8dd..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_read_locked_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_read_mine.gif b/phpBB/styles/subsilver2/theme/images/announce_read_mine.gif
deleted file mode 100644
index 636d353867..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_read_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread.gif b/phpBB/styles/subsilver2/theme/images/announce_unread.gif
deleted file mode 100644
index 56b2702b17..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/announce_unread_locked.gif
deleted file mode 100644
index 37033da653..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_unread_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gif
deleted file mode 100644
index d91f2520ca..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_unread_locked_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/announce_unread_mine.gif b/phpBB/styles/subsilver2/theme/images/announce_unread_mine.gif
deleted file mode 100644
index e1dd23a0bf..0000000000
--- a/phpBB/styles/subsilver2/theme/images/announce_unread_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/background.gif b/phpBB/styles/subsilver2/theme/images/background.gif
deleted file mode 100644
index 5c731e4fc2..0000000000
--- a/phpBB/styles/subsilver2/theme/images/background.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/cellpic.gif b/phpBB/styles/subsilver2/theme/images/cellpic.gif
deleted file mode 100644
index 47457ef5f7..0000000000
--- a/phpBB/styles/subsilver2/theme/images/cellpic.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/cellpic1.gif b/phpBB/styles/subsilver2/theme/images/cellpic1.gif
deleted file mode 100644
index 715b8d4aa8..0000000000
--- a/phpBB/styles/subsilver2/theme/images/cellpic1.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/cellpic2.jpg b/phpBB/styles/subsilver2/theme/images/cellpic2.jpg
deleted file mode 100644
index a0ca7e89d3..0000000000
--- a/phpBB/styles/subsilver2/theme/images/cellpic2.jpg
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/cellpic2_rtl.jpg b/phpBB/styles/subsilver2/theme/images/cellpic2_rtl.jpg
deleted file mode 100644
index 201e063725..0000000000
--- a/phpBB/styles/subsilver2/theme/images/cellpic2_rtl.jpg
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/cellpic3.gif b/phpBB/styles/subsilver2/theme/images/cellpic3.gif
deleted file mode 100644
index ecf70e1fd1..0000000000
--- a/phpBB/styles/subsilver2/theme/images/cellpic3.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/created_by.jpg b/phpBB/styles/subsilver2/theme/images/created_by.jpg
deleted file mode 100644
index f27472781e..0000000000
--- a/phpBB/styles/subsilver2/theme/images/created_by.jpg
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_link.gif b/phpBB/styles/subsilver2/theme/images/forum_link.gif
deleted file mode 100644
index d5e86d47d7..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_link.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_read.gif b/phpBB/styles/subsilver2/theme/images/forum_read.gif
deleted file mode 100644
index 9b2bc47c67..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_read.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_read_locked.gif b/phpBB/styles/subsilver2/theme/images/forum_read_locked.gif
deleted file mode 100644
index 436f3d21c8..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_read_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_read_subforum.gif b/phpBB/styles/subsilver2/theme/images/forum_read_subforum.gif
deleted file mode 100644
index 9179303e7f..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_read_subforum.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_unread.gif b/phpBB/styles/subsilver2/theme/images/forum_unread.gif
deleted file mode 100644
index 5eec565b38..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/forum_unread_locked.gif
deleted file mode 100644
index 58a79c376c..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_unread_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/forum_unread_subforum.gif b/phpBB/styles/subsilver2/theme/images/forum_unread_subforum.gif
deleted file mode 100644
index af3c93b1a1..0000000000
--- a/phpBB/styles/subsilver2/theme/images/forum_unread_subforum.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_faq.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_faq.gif
deleted file mode 100644
index fc50e7ca30..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_faq.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_groups.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_groups.gif
deleted file mode 100644
index a4d1c7bb70..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_groups.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_login.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_login.gif
deleted file mode 100644
index c7590a423f..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_login.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_members.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_members.gif
deleted file mode 100644
index d636089b38..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_members.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_message.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_message.gif
deleted file mode 100644
index b8aea1eafb..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_message.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_notification.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_notification.gif
deleted file mode 100644
index f165d3cb27..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_notification.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_profile.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_profile.gif
deleted file mode 100644
index 1ec7c649e9..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_profile.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_register.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_register.gif
deleted file mode 100644
index b49ac31ec9..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_register.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_mini_search.gif b/phpBB/styles/subsilver2/theme/images/icon_mini_search.gif
deleted file mode 100644
index 2bd1a648c0..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_mini_search.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_post_target.gif b/phpBB/styles/subsilver2/theme/images/icon_post_target.gif
deleted file mode 100644
index d172abb060..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_post_target.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gif b/phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gif
deleted file mode 100644
index 8ec44a1787..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_post_target_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_attach.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_attach.gif
deleted file mode 100644
index 1c9c89bc70..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_topic_attach.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_deleted.png b/phpBB/styles/subsilver2/theme/images/icon_topic_deleted.png
deleted file mode 100644
index 494b4fb563..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_topic_deleted.png
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_latest.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_latest.gif
deleted file mode 100644
index b45e57aedb..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_topic_latest.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_newest.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_newest.gif
deleted file mode 100644
index eca2861836..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_topic_newest.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_reported.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_reported.gif
deleted file mode 100644
index 026092854a..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_topic_reported.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/icon_topic_unapproved.gif b/phpBB/styles/subsilver2/theme/images/icon_topic_unapproved.gif
deleted file mode 100644
index 2ccaf19c23..0000000000
--- a/phpBB/styles/subsilver2/theme/images/icon_topic_unapproved.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/index.htm b/phpBB/styles/subsilver2/theme/images/index.htm
deleted file mode 100644
index 957f68a803..0000000000
--- a/phpBB/styles/subsilver2/theme/images/index.htm
+++ /dev/null
@@ -1,16 +0,0 @@
-<html>
-<head>
-<title>subSilver created by subBlue Design</title>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-</head>
-
-<body bgcolor="#FFFFFF" text="#000000">
-
-<table width="100%" height="100%" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td align="center" valign="middle"><a href="http://www.subblue.com/" target="_new"><img src="created_by.jpg" width="400" height="300" alt="Created by subBlue Design" /></a></td>
- </tr>
-</table>
-
-</body>
-</html> \ No newline at end of file
diff --git a/phpBB/styles/subsilver2/theme/images/no_avatar.gif b/phpBB/styles/subsilver2/theme/images/no_avatar.gif
deleted file mode 100644
index ad73330e71..0000000000
--- a/phpBB/styles/subsilver2/theme/images/no_avatar.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/poll_center.gif b/phpBB/styles/subsilver2/theme/images/poll_center.gif
deleted file mode 100644
index 99473151ec..0000000000
--- a/phpBB/styles/subsilver2/theme/images/poll_center.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/poll_left.gif b/phpBB/styles/subsilver2/theme/images/poll_left.gif
deleted file mode 100644
index 269088b81d..0000000000
--- a/phpBB/styles/subsilver2/theme/images/poll_left.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/poll_right.gif b/phpBB/styles/subsilver2/theme/images/poll_right.gif
deleted file mode 100644
index f9584e23a1..0000000000
--- a/phpBB/styles/subsilver2/theme/images/poll_right.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/site_logo.gif b/phpBB/styles/subsilver2/theme/images/site_logo.gif
deleted file mode 100644
index abce3cd51d..0000000000
--- a/phpBB/styles/subsilver2/theme/images/site_logo.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/spacer.gif b/phpBB/styles/subsilver2/theme/images/spacer.gif
deleted file mode 100644
index 5bfd67a2d6..0000000000
--- a/phpBB/styles/subsilver2/theme/images/spacer.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read.gif b/phpBB/styles/subsilver2/theme/images/sticky_read.gif
deleted file mode 100644
index 09861a996c..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_read.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read_locked.gif b/phpBB/styles/subsilver2/theme/images/sticky_read_locked.gif
deleted file mode 100644
index 24bca303d6..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_read_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/sticky_read_locked_mine.gif
deleted file mode 100644
index 3fd04ec3a9..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_read_locked_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_read_mine.gif b/phpBB/styles/subsilver2/theme/images/sticky_read_mine.gif
deleted file mode 100644
index 381634c364..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_read_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_unread.gif b/phpBB/styles/subsilver2/theme/images/sticky_unread.gif
deleted file mode 100644
index dd2e366543..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gif
deleted file mode 100644
index 608f4822e3..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_unread_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gif
deleted file mode 100644
index fe5e115312..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_unread_locked_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/sticky_unread_mine.gif b/phpBB/styles/subsilver2/theme/images/sticky_unread_mine.gif
deleted file mode 100644
index b5fc3b3627..0000000000
--- a/phpBB/styles/subsilver2/theme/images/sticky_unread_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_moved.gif b/phpBB/styles/subsilver2/theme/images/topic_moved.gif
deleted file mode 100644
index fe758f02ca..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_moved.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_read.gif b/phpBB/styles/subsilver2/theme/images/topic_read.gif
deleted file mode 100644
index c16bfa75d5..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_read.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_hot.gif b/phpBB/styles/subsilver2/theme/images/topic_read_hot.gif
deleted file mode 100644
index a7a7e8fc78..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_read_hot.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gif
deleted file mode 100644
index 853452a74b..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_read_hot_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_locked.gif b/phpBB/styles/subsilver2/theme/images/topic_read_locked.gif
deleted file mode 100644
index 10eb776972..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_read_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gif
deleted file mode 100644
index 3f24928b48..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_read_locked_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_read_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_read_mine.gif
deleted file mode 100644
index 560927aa06..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_read_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread.gif b/phpBB/styles/subsilver2/theme/images/topic_unread.gif
deleted file mode 100644
index 4e56157dce..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_unread.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_hot.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_hot.gif
deleted file mode 100644
index ceef4919d5..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_unread_hot.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gif
deleted file mode 100644
index 1c748f708a..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_unread_hot_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_locked.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_locked.gif
deleted file mode 100644
index 720e210289..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_unread_locked.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_locked_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_locked_mine.gif
deleted file mode 100644
index 90873431ef..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_unread_locked_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/topic_unread_mine.gif b/phpBB/styles/subsilver2/theme/images/topic_unread_mine.gif
deleted file mode 100644
index 34fd2ec179..0000000000
--- a/phpBB/styles/subsilver2/theme/images/topic_unread_mine.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/upload_bar.gif b/phpBB/styles/subsilver2/theme/images/upload_bar.gif
deleted file mode 100644
index 75cf61c59e..0000000000
--- a/phpBB/styles/subsilver2/theme/images/upload_bar.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/images/whosonline.gif b/phpBB/styles/subsilver2/theme/images/whosonline.gif
deleted file mode 100644
index b450927432..0000000000
--- a/phpBB/styles/subsilver2/theme/images/whosonline.gif
+++ /dev/null
Binary files differ
diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css
deleted file mode 100644
index 8f0bbffdda..0000000000
--- a/phpBB/styles/subsilver2/theme/stylesheet.css
+++ /dev/null
@@ -1,1256 +0,0 @@
-/* phpBB3 Style Sheet
- --------------------------------------------------------------
- Style name: subsilver2
- Based on style: subSilver (the default phpBB 2.0.x style)
- Original author: Tom Beddard ( http://www.subblue.com/ )
- Modified by: phpBB Limited ( https://www.phpbb.com/ )
- --------------------------------------------------------------
-*/
-
-/* Layout
- ------------ */
-* {
- /* Reset browsers default margin, padding and font sizes */
- margin: 0;
- padding: 0;
-}
-
-abbr {
- text-decoration: none;
-}
-
-html {
- font-size: 100%;
-}
-
-body {
- /* Text-Sizing with ems: http://www.clagnut.com/blog/348/ */
- font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
- color: #323D4F;
- background-color: #FFFFFF;
- font-size: 62.5%; /* This sets the default font size to be equivalent to 10px */
- margin: 0;
-}
-
-#wrapheader {
- height: auto !important;
- padding: 0;
-}
-
-#wrapcentre {
- margin: 15px 25px 0 25px;
-}
-
-#wrapfooter {
- text-align: center;
- clear: both;
-}
-
-#wrapnav {
- width: 100%;
- margin: 0;
- background-color: #ECECEC;
- border-width: 1px;
- border-style: solid;
- border-color: #A9B8C2;
-}
-
-#logodesc {
- background-color: #C1CAD2;
- background-image: url('./images/background.gif');
- background-repeat: repeat-x;
- background-position: center bottom;
- padding: 0 25px 15px 25px;
-}
-
-#menubar {
- margin: 0 25px;
-}
-
-#datebar {
- margin: 10px 25px 0 25px;
-}
-
-#findbar {
- width: 100%;
- margin: 0;
- padding: 0;
- border: 0;
-}
-
-.forumrules {
- background-color: #F9CC79;
- border-width: 1px;
- border-style: solid;
- border-color: #BB9860;
- padding: 4px;
- font-weight: normal;
- font-size: 1.1em;
- font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
-}
-
-.forumrules h3 {
- color: red;
-}
-
-#pageheader { }
-#pagecontent { }
-#pagefooter { }
-
-#poll { }
-#postrow { }
-#postdata { }
-
-
-/* Text
- --------------------- */
-h1 {
- color: black;
- font-family: "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
- font-weight: bold;
- font-size: 1.8em;
- text-decoration: none;
-}
-
-h2 {
- font-family: Arial, Helvetica, sans-serif;
- font-weight: bold;
- font-size: 1.5em;
- text-decoration: none;
- line-height: 120%;
-}
-
-h3 {
- font-size: 1.3em;
- font-weight: bold;
- font-family: Arial, Helvetica, sans-serif;
- line-height: 120%;
-}
-
-h4 {
- margin: 0;
- font-size: 1.1em;
- font-weight: bold;
-}
-
-p {
- font-size: 1.1em;
-}
-
-p.moderators {
- margin: 0;
- float: left;
- color: black;
- font-weight: bold;
-}
-
-.rtl p.moderators {
- float: right;
-}
-
-p.linkmcp {
- margin: 0;
- float: right;
- white-space: nowrap;
-}
-
-.rtl p.linkmcp {
- float: left;
-}
-
-p.breadcrumbs {
- margin: 0;
- float: left;
- color: black;
- font-weight: bold;
- white-space: normal;
- font-size: 1em;
-}
-
-.rtl p.breadcrumbs {
- float: right;
-}
-
-p.datetime {
- margin: 0;
- float: right;
- white-space: nowrap;
- font-size: 1em;
-}
-
-.rtl p.datetime {
- float: left;
-}
-
-p.searchbar {
- padding: 2px 0;
- white-space: nowrap;
-}
-
-p.searchbarreg {
- margin: 0;
- float: right;
- white-space: nowrap;
-}
-
-.rtl p.searchbarreg {
- float: left;
-}
-
-p.forumdesc {
- padding-bottom: 4px;
-}
-
-p.topicauthor {
- margin: 1px 0;
-}
-
-p.topicdetails {
- margin: 1px 0;
-}
-
-.postreported, .postreported a:link, .postreported a:visited, .postreported a:hover, .postreported a:active {
- margin: 1px 0;
- color: red;
- font-weight:bold;
-}
-
-.postapprove, .postapprove a:link, .postapprove a:visited, .postapprove a:hover, .postapprove a:active {
- color: green;
- font-weight:bold;
-}
-
-.postapprove img, .postreported img {
- vertical-align: bottom;
- padding-top: 5px;
-}
-
-.postauthor {
- color: #000000;
-}
-
-.postdetails {
- color: #000000;
-}
-
-.postbody {
- font-size: 1.3em;
- line-height: 1.4em;
- font-family: "Lucida Grande", "Trebuchet MS", Helvetica, Arial, sans-serif;
-}
-
-.postbody li, ol, ul {
- margin: 0 0 0 1.5em;
-}
-
-.rtl .postbody li, .rtl ol, .rtl ul {
- margin: 0 1.5em 0 0;
-}
-
-.posthilit {
- background-color: yellow;
-}
-
-.nav {
- margin: 0;
- color: black;
- font-weight: bold;
-}
-
-.pagination {
- padding: 4px;
- color: black;
- font-size: 1em;
- font-weight: bold;
-}
-
-.cattitle {
-
-}
-
-.gen {
- margin: 1px 1px;
- font-size: 1.2em;
-}
-
-.genmed {
- margin: 1px 1px;
- font-size: 1.1em;
-}
-
-.gensmall {
- margin: 1px 1px;
- font-size: 1em;
-}
-
-.copyright {
- color: #444;
- font-weight: normal;
- font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
-}
-
-.titles {
- font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
- font-weight: bold;
- font-size: 1.3em;
- text-decoration: none;
-}
-
-.online {
- color: green;
-}
-
-.offline, .error, .inactive {
- color: red;
-}
-
-
-/* Tables
- ------------ */
-#color_palette_placeholder table {
- border-collapse: separate;
- border-spacing: 1px;
-}
-
-#color_palette_placeholder td {
- padding: 0;
-}
-
-th {
- color: #FFA34F;
- font-size: 1.1em;
- font-weight: bold;
- background-color: #006699;
- background-image: url('./images/cellpic3.gif');
- white-space: nowrap;
- padding: 7px 5px;
-}
-
-th.center {
- text-align: center;
-}
-
-td {
- padding: 2px;
-}
-td.profile {
- padding: 4px;
-}
-
-.tablebg {
- background-color: #A9B8C2;
-}
-
-.catdiv {
- height: 28px;
- margin: 0;
- padding: 0;
- border: 0;
- background: white url('./images/cellpic2.jpg') repeat-y scroll top left;
-}
-.rtl .catdiv {
- background: white url('./images/cellpic2_rtl.jpg') repeat-y scroll top right;
-}
-
-.cat {
- height: 28px;
- margin: 0;
- padding: 0;
- border: 0;
- background-color: #C7D0D7;
- background-image: url('./images/cellpic1.gif');
- text-indent: 4px;
-}
-
-.row1 {
- background-color: #ECECEC;
- padding: 4px;
-}
-
-.row2 {
- background-color: #DCE1E5;
- padding: 4px;
-}
-
-.row3 {
- background-color: #C0C8D0;
- padding: 4px;
-}
-
-.spacer {
- background-color: #D1D7DC;
-}
-
-.current {
- background-color: lightblue;
-}
-
-hr {
- height: 1px;
- border-width: 0;
- background-color: #D1D7DC;
- color: #D1D7DC;
-}
-
-.legend {
- text-align:center;
- margin: 0 auto;
-}
-
-/* Links
- ------------ */
-
-/* Links adjustment to correctly display an order of rtl/ltr mixed content */
-.rtl a {
- direction: rtl;
- unicode-bidi: embed;
-}
-
-/* CSS spec requires a:link, a:visited, a:hover and a:active rules to be specified in this order. */
-/* See http://www.phpbb.com/bugs/phpbb3/59685 */
-a:link {
- color: #006597;
- text-decoration: none;
-}
-
-a:visited {
- color: #005784;
- text-decoration: none;
-}
-
-a:hover {
- color: #D46400;
- text-decoration: underline;
-}
-
-a:active {
- color: #005784;
- text-decoration: none;
-}
-
-a.forumlink {
- color: #069;
- font-weight: bold;
- font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
- font-size: 1.2em;
-}
-
-a.topictitle {
- margin: 1px 0;
- font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
- font-weight: bold;
- font-size: 1.2em;
-}
-
-a.topictitle:visited {
- color: #5493B4;
- text-decoration: none;
-}
-
-a.lastsubject {
- font-weight: bold;
- text-decoration: none;
-}
-
-a.lastsubject:hover {
- text-decoration: underline;
-}
-
-th a,
-th a:visited {
- color: #FFA34F !important;
- text-decoration: none;
-}
-
-th a:hover {
- text-decoration: underline;
-}
-
-a.anchor {
- display: block;
-}
-
-
-/* Form Elements
- ------------ */
-form {
- margin: 0;
- padding: 0;
- border: 0;
-}
-
-input {
- color: #333333;
- font-family: "Lucida Grande", Verdana, Helvetica, sans-serif;
- font-size: 1.1em;
- font-weight: normal;
- padding: 1px;
- border: 1px solid #A9B8C2;
- background-color: #FAFAFA;
-}
-
-textarea {
- background-color: #FAFAFA;
- color: #333333;
- font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
- font-size: 1.3em;
- line-height: 1.4em;
- font-weight: normal;
- border: 1px solid #A9B8C2;
- padding: 2px;
-}
-
-select {
- color: #333333;
- background-color: #FAFAFA;
- font-family: "Lucida Grande", Verdana, Helvetica, sans-serif;
- font-size: 1.1em;
- font-weight: normal;
- border: 1px solid #A9B8C2;
- padding: 1px;
-}
-
-option {
- padding: 0 1em 0 0;
-}
-
-option.disabled-option {
- color: graytext;
-}
-
-.rtl option {
- padding: 0 0 0 1em;
-}
-
-input.radio {
- border: none;
- background-color: transparent;
-}
-
-.post {
- background-color: white;
- border-style: solid;
- border-width: 1px;
-}
-
-.btnbbcode {
- color: #000000;
- font-weight: normal;
- font-size: 1.1em;
- font-family: "Lucida Grande", Verdana, Helvetica, sans-serif;
- background-color: #EFEFEF;
- border: 1px solid #666666;
-}
-
-.btnmain {
- font-weight: bold;
- background-color: #ECECEC;
- border: 1px solid #A9B8C2;
- cursor: pointer;
- padding: 1px 5px;
- font-size: 1.1em;
-}
-
-.btnlite {
- font-weight: normal;
- background-color: #ECECEC;
- border: 1px solid #A9B8C2;
- cursor: pointer;
- padding: 1px 5px;
- font-size: 1.1em;
-}
-
-.btnfile {
- font-weight: normal;
- background-color: #ECECEC;
- border: 1px solid #A9B8C2;
- padding: 1px 5px;
- font-size: 1.1em;
-}
-
-.helpline {
- background-color: #DEE3E7;
- border-style: none;
-}
-
-input:focus, select:focus, textarea:focus {
- outline-style: none;
-}
-
-/* BBCode
- ------------ */
-.quotetitle, .attachtitle {
- margin: 10px 5px 0 5px;
- padding: 4px;
- border-width: 1px 1px 0 1px;
- border-style: solid;
- border-color: #A9B8C2;
- color: #333333;
- background-color: #A9B8C2;
- font-size: 0.85em;
- font-weight: bold;
-}
-
-.quotetitle .quotetitle {
- font-size: 1em;
-}
-
-.quotecontent, .attachcontent {
- margin: 0 5px 10px 5px;
- padding: 5px;
- border-color: #A9B8C2;
- border-width: 0 1px 1px 1px;
- border-style: solid;
- font-weight: normal;
- font-size: 1em;
- line-height: 1.4em;
- font-family: "Lucida Grande", "Trebuchet MS", Helvetica, Arial, sans-serif;
- background-color: #FAFAFA;
- color: #4B5C77;
-}
-
-.attachcontent {
- font-size: 0.85em;
-}
-
-.codetitle {
- margin: 10px 5px 0 5px;
- padding: 2px 4px;
- border-width: 1px 1px 0 1px;
- border-style: solid;
- border-color: #A9B8C2;
- color: #333333;
- background-color: #A9B8C2;
- font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
- font-size: 0.8em;
-}
-
-.codecontent {
- direction: ltr;
- margin: 0 5px 10px 5px;
- padding: 5px;
- border-color: #A9B8C2;
- border-width: 0 1px 1px 1px;
- border-style: solid;
- font-weight: normal;
- color: #006600;
- font-size: 0.85em;
- font-family: Monaco, 'Courier New', monospace;
- background-color: #FAFAFA;
-}
-
-.postimage {
- max-width: 100%;
-}
-
-.syntaxbg {
- color: #FFFFFF;
-}
-
-.syntaxcomment {
- color: #FF8000;
-}
-
-.syntaxdefault {
- color: #0000BB;
-}
-
-.syntaxhtml {
- color: #000000;
-}
-
-.syntaxkeyword {
- color: #007700;
-}
-
-.syntaxstring {
- color: #DD0000;
-}
-
-
-/* Private messages
- ------------------ */
-.pm_marked_colour {
- background-color: #000000;
-}
-
-.pm_replied_colour {
- background-color: #A9B8C2;
-}
-
-.pm_friend_colour {
- background-color: #007700;
-}
-
-.pm_foe_colour {
- background-color: #DD0000;
-}
-
-
-/* Misc
- ------------ */
-img {
- border: none;
-}
-
-.sep {
- color: black;
- background-color: #FFA34F;
-}
-
-table.colortable td {
- padding: 0;
-}
-
-pre {
- font-size: 1.1em;
- font-family: Monaco, 'Courier New', monospace;
-}
-
-.nowrap {
- white-space: nowrap;
-}
-
-.username-coloured {
- font-weight: bold;
-}
-
-
-/* Former imageset */
-span.imageset {
- display: inline-block;
- background: transparent none 0 0 no-repeat;
- margin: 0;
- padding: 0;
- width: 0;
- height: 0;
- overflow: hidden;
-}
-a.imageset {
- text-decoration: none !important;
-}
-
-/* Global imageset items */
-.imageset.site_logo {
- background-image: url("./images/site_logo.gif");
- padding-left: 170px;
- padding-top: 94px;
-}
-.imageset.upload_bar {
- background-image: url("./images/upload_bar.gif");
- padding-left: 280px;
- padding-top: 16px;
-}
-.imageset.poll_left {
- background-image: url("./images/poll_left.gif");
- padding-left: 4px;
- padding-top: 12px;
-}
-.imageset.poll_center {
- background-image: url("./images/poll_center.gif");
- padding-left: 1px;
- padding-top: 12px;
-}
-.imageset.poll_right {
- background-image: url("./images/poll_right.gif");
- padding-left: 4px;
- padding-top: 12px;
-}
-.imageset.forum_link {
- background-image: url("./images/forum_link.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.forum_read {
- background-image: url("./images/forum_read.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.forum_read_locked {
- background-image: url("./images/forum_read_locked.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.forum_read_subforum {
- background-image: url("./images/forum_read_subforum.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.forum_unread {
- background-image: url("./images/forum_unread.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.forum_unread_locked {
- background-image: url("./images/forum_unread_locked.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.forum_unread_subforum {
- background-image: url("./images/forum_unread_subforum.gif");
- padding-left: 46px;
- padding-top: 25px;
-}
-.imageset.topic_moved {
- background-image: url("./images/topic_moved.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_read {
- background-image: url("./images/topic_read.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_read_mine {
- background-image: url("./images/topic_read_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_read_hot {
- background-image: url("./images/topic_read_hot.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_read_hot_mine {
- background-image: url("./images/topic_read_hot_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_read_locked {
- background-image: url("./images/topic_read_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_read_locked_mine {
- background-image: url("./images/topic_read_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_unread {
- background-image: url("./images/topic_unread.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_unread_mine {
- background-image: url("./images/topic_unread_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_unread_hot {
- background-image: url("./images/topic_unread_hot.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_unread_hot_mine {
- background-image: url("./images/topic_unread_hot_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_unread_locked {
- background-image: url("./images/topic_unread_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.topic_unread_locked_mine {
- background-image: url("./images/topic_unread_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_read {
- background-image: url("./images/sticky_read.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_read_mine {
- background-image: url("./images/sticky_read_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_read_locked {
- background-image: url("./images/sticky_read_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_read_locked_mine {
- background-image: url("./images/sticky_read_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_unread {
- background-image: url("./images/sticky_unread.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_unread_mine {
- background-image: url("./images/sticky_unread_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_unread_locked {
- background-image: url("./images/sticky_unread_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.sticky_unread_locked_mine {
- background-image: url("./images/sticky_unread_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_read {
- background-image: url("./images/announce_read.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_read_mine {
- background-image: url("./images/announce_read_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_read_locked {
- background-image: url("./images/announce_read_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_read_locked_mine {
- background-image: url("./images/announce_read_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_unread {
- background-image: url("./images/announce_unread.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_unread_mine {
- background-image: url("./images/announce_unread_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_unread_locked {
- background-image: url("./images/announce_unread_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.announce_unread_locked_mine {
- background-image: url("./images/announce_unread_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_read {
- background-image: url("./images/announce_read.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_read_mine {
- background-image: url("./images/announce_read_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_read_locked {
- background-image: url("./images/announce_read_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_read_locked_mine {
- background-image: url("./images/announce_read_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_unread {
- background-image: url("./images/announce_unread.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_unread_mine {
- background-image: url("./images/announce_unread_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_unread_locked {
- background-image: url("./images/announce_unread_locked.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.global_unread_locked_mine {
- background-image: url("./images/announce_unread_locked_mine.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.pm_read {
- background-image: url("./images/topic_read.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.pm_unread {
- background-image: url("./images/topic_unread.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.icon_post_target {
- background-image: url("./images/icon_post_target.gif");
- padding-left: 12px;
- padding-top: 9px;
-}
-.imageset.icon_post_target_unread {
- background-image: url("./images/icon_post_target_unread.gif");
- padding-left: 12px;
- padding-top: 9px;
-}
-.imageset.icon_topic_attach {
- background-image: url("./images/icon_topic_attach.gif");
- padding-left: 14px;
- padding-top: 18px;
-}
-.imageset.icon_topic_latest {
- background-image: url("./images/icon_topic_latest.gif");
- padding-left: 18px;
- padding-top: 9px;
-}
-.imageset.icon_topic_newest {
- background-image: url("./images/icon_topic_newest.gif");
- padding-left: 18px;
- padding-top: 9px;
-}
-.imageset.icon_topic_reported {
- background-image: url("./images/icon_topic_reported.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.icon_topic_unapproved {
- background-image: url("./images/icon_topic_unapproved.gif");
- padding-left: 19px;
- padding-top: 18px;
-}
-.imageset.icon_topic_deleted {
- background-image: url("./images/icon_topic_deleted.png");
- padding-left: 14px;
- padding-top: 14px;
-}
-
-
-/* English images for fallback */
-.imageset.phpbb_aol-icon, .imageset.icon_contact_aim {
- background-image: url("./en/icon_contact_aim.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_contact_email {
- background-image: url("./en/icon_contact_email.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_icq-icon, .imageset.icon_contact_icq {
- background-image: url("./en/icon_contact_icq.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_contact_jabber {
- background-image: url("./en/icon_contact_jabber.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_wlm-icon, .imageset.icon_contact_msnm {
- background-image: url("./en/icon_contact_msnm.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_contact_pm {
- background-image: url("./en/icon_contact_pm.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_yahoo-icon, .imageset.icon_contact_yahoo {
- background-image: url("./en/icon_contact_yahoo.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.phpbb_website-icon, .imageset.icon_contact_www {
- background-image: url("./en/icon_contact_www.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_post_delete {
- background-image: url("./en/icon_post_delete.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_edit {
- background-image: url("./en/icon_post_edit.gif");
- padding-left: 90px;
- padding-top: 20px;
-}
-.imageset.icon_post_info {
- background-image: url("./en/icon_post_info.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_post_quote {
- background-image: url("./en/icon_post_quote.gif");
- padding-left: 90px;
- padding-top: 20px;
-}
-.imageset.icon_post_report {
- background-image: url("./en/icon_post_report.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.icon_user_online {
- background-image: url("./en/icon_user_online.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_offline {
- background-image: url("./en/icon_user_offline.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_profile {
- background-image: url("./en/icon_user_profile.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_search {
- background-image: url("./en/icon_user_search.gif");
- padding-left: 72px;
- padding-top: 20px;
-}
-.imageset.icon_user_warn {
- background-image: url("./en/icon_user_warn.gif");
- padding-left: 20px;
- padding-top: 20px;
-}
-.imageset.button_pm_new {
- background-image: url("./en/button_pm_new.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-.imageset.button_pm_reply {
- background-image: url("./en/button_pm_reply.gif");
- padding-left: 90px;
- padding-top: 20px;
-}
-.imageset.button_topic_locked {
- background-image: url("./en/button_topic_locked.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-.imageset.button_topic_new {
- background-image: url("./en/button_topic_new.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-.imageset.button_topic_reply {
- background-image: url("./en/button_topic_reply.gif");
- padding-left: 97px;
- padding-top: 27px;
-}
-
-/* RTL imageset entries */
-.rtl .imageset.site_logo {
- padding-right: 170px;
- padding-left: 0;
-}
-.rtl .imageset.upload_bar {
- padding-right: 280px;
- padding-left: 0;
-}
-.rtl .imageset.poll_left, .rtl .imageset.poll_right {
- padding-right: 4px;
- padding-left: 0;
-}
-.rtl .imageset.poll_center {
- padding-right: 1px;
- padding-left: 0;
-}
-.rtl .imageset.forum_link, .rtl .imageset.forum_read, .rtl .imageset.forum_read_locked, .rtl .imageset.forum_read_subforum, .rtl .imageset.forum_unread, .rtl .imageset.forum_unread_locked, .rtl .imageset.forum_unread_subforum {
- padding-right: 46px;
- padding-left: 0;
-}
-.rtl .imageset.topic_moved, .rtl .imageset.topic_read, .rtl .imageset.topic_read_mine, .rtl .imageset.topic_read_hot, .rtl .imageset.topic_read_hot_mine, .rtl .imageset.topic_read_locked, .rtl .imageset.topic_read_locked_mine, .rtl .imageset.topic_unread, .rtl .imageset.topic_unread_mine, .rtl .imageset.topic_unread_hot, .rtl .imageset.topic_unread_hot_mine, .rtl .imageset.topic_unread_locked, .rtl .imageset.topic_unread_locked_mine, .rtl .imageset.sticky_read, .rtl .imageset.sticky_read_mine, .rtl .imageset.sticky_read_locked, .rtl .imageset.sticky_read_locked_mine, .rtl .imageset.sticky_unread, .rtl .imageset.sticky_unread_mine, .rtl .imageset.sticky_unread_locked, .rtl .imageset.sticky_unread_locked_mine, .rtl .imageset.announce_read, .rtl .imageset.announce_read_mine, .rtl .imageset.announce_read_locked, .rtl .imageset.announce_read_locked_mine, .rtl .imageset.announce_unread, .rtl .imageset.announce_unread_mine, .rtl .imageset.announce_unread_locked, .rtl .imageset.announce_unread_locked_mine, .rtl .imageset.global_read, .rtl .imageset.global_read_mine, .rtl .imageset.global_read_locked, .rtl .imageset.global_read_locked_mine, .rtl .imageset.global_unread, .rtl .imageset.global_unread_mine, .rtl .imageset.global_unread_locked, .rtl .imageset.global_unread_locked_mine, .rtl .imageset.pm_read, .rtl .imageset.pm_unread, .rtl .imageset.icon_topic_reported, .rtl .imageset.icon_topic_unapproved {
- padding-right: 19px;
- padding-left: 0;
-}
-.rtl .imageset.icon_post_target, .rtl .imageset.icon_post_target_unread {
- padding-right: 12px;
- padding-left: 0;
-}
-.rtl .imageset.icon_topic_attach {
- padding-right: 14px;
- padding-left: 0;
-}
-.rtl .imageset.icon_topic_latest, .rtl .imageset.icon_topic_newest {
- padding-right: 18px;
- padding-left: 0;
-}
-
-#notification_list {
- display: none;
- position: absolute;
- width: 310px;
- z-index: 1;
- box-shadow: 3px 3px 5px darkgray;
-}
-
-#notification_list .notification_scroll {
- max-height: 350px;
- overflow-y: auto;
- overflow-x: hidden;
-}
-
-#notification_list table {
- width: 100%;
-}
-
-#notification_list .notification_title {
- padding: 3px;
-}
-
-#notification_list .notification_title:after {
- clear: both;
- content: '';
- display: block;
-}
-
-#notification_list .header {
- padding: 5px;
- font-weight: bold;
- border: 1px solid #A9B8C2;
- border-bottom: 0;
-}
-
-#notification_list > .header > .header_settings {
- float: right;
- font-weight: normal;
- text-transform: none;
-}
-
-#notification_list .header:after {
- content: '';
- display: table;
- clear: both;
-}
-
-#notification_list .footer {
- text-align: center;
- font-size: 1.2em;
- border: 1px solid #A9B8C2;
- border-top: 0;
-}
-
-.notification_list img {
- max-width: 50px;
- max-height: 50px;
-}
-
-#notification_list .footer > a {
- display: block;
-}
-
-#notification_list .notification-time {
- font-size: 0.9em;
- float: right;
-}
-
-.notification_list .notifications_time {
- font-size: 0.8em;
-}
diff --git a/phpBB/ucp.php b/phpBB/ucp.php
index 8c74ca1f3c..720b56ae8b 100644
--- a/phpBB/ucp.php
+++ b/phpBB/ucp.php
@@ -22,8 +22,8 @@ require($phpbb_root_path . 'includes/functions_user.' . $phpEx);
require($phpbb_root_path . 'includes/functions_module.' . $phpEx);
// Basic parameter data
-$id = request_var('i', '');
-$mode = request_var('mode', '');
+$id = $request->variable('i', '');
+$mode = $request->variable('mode', '');
if (in_array($mode, array('login', 'login_link', 'logout', 'confirm', 'sendpassword', 'activate')))
{
@@ -81,7 +81,7 @@ switch ($mode)
redirect(append_sid("{$phpbb_root_path}index.$phpEx"));
}
- login_box(request_var('redirect', "index.$phpEx"));
+ login_box($request->variable('redirect', "index.$phpEx"));
break;
case 'login_link':
@@ -212,7 +212,7 @@ switch ($mode)
case 'switch_perm':
- $user_id = request_var('u', 0);
+ $user_id = $request->variable('u', 0);
$sql = 'SELECT *
FROM ' . USERS_TABLE . '
@@ -221,7 +221,7 @@ switch ($mode)
$user_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if (!$auth->acl_get('a_switchperm') || !$user_row || $user_id == $user->data['user_id'] || !check_link_hash(request_var('hash', ''), 'switchperm'))
+ if (!$auth->acl_get('a_switchperm') || !$user_row || $user_id == $user->data['user_id'] || !check_link_hash($request->variable('hash', ''), 'switchperm'))
{
redirect(append_sid("{$phpbb_root_path}index.$phpEx"));
}
@@ -234,7 +234,7 @@ switch ($mode)
redirect(append_sid("{$phpbb_root_path}index.$phpEx"));
}
- add_log('admin', 'LOG_ACL_TRANSFER_PERMISSIONS', $user_row['username']);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_TRANSFER_PERMISSIONS', false, array($user_row['username']));
$message = sprintf($user->lang['PERMISSIONS_TRANSFERRED'], $user_row['username']) . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>');
trigger_error($message);
@@ -257,7 +257,7 @@ switch ($mode)
$username = $db->sql_fetchfield('username');
$db->sql_freeresult($result);
- add_log('admin', 'LOG_ACL_RESTORE_PERMISSIONS', $username);
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ACL_RESTORE_PERMISSIONS', false, array($username));
$message = $user->lang['PERMISSIONS_RESTORED'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>');
trigger_error($message);
@@ -285,7 +285,7 @@ if (!$user->data['is_registered'])
if ($id == 'pm' && $mode == 'view' && isset($_GET['p']))
{
- $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx?i=pm&p=" . request_var('p', 0));
+ $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx?i=pm&p=" . $request->variable('p', 0));
login_box($redirect_url, $user->lang['LOGIN_EXPLAIN_UCP']);
}
diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php
index e0cc9ba512..cdffe69155 100644
--- a/phpBB/viewforum.php
+++ b/phpBB/viewforum.php
@@ -25,18 +25,19 @@ $user->session_begin();
$auth->acl($user->data);
// Start initial var setup
-$forum_id = request_var('f', 0);
-$mark_read = request_var('mark', '');
-$start = request_var('start', 0);
+$forum_id = $request->variable('f', 0);
+$mark_read = $request->variable('mark', '');
+$start = $request->variable('start', 0);
$default_sort_days = (!empty($user->data['user_topic_show_days'])) ? $user->data['user_topic_show_days'] : 0;
$default_sort_key = (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't';
$default_sort_dir = (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd';
-$sort_days = request_var('st', $default_sort_days);
-$sort_key = request_var('sk', $default_sort_key);
-$sort_dir = request_var('sd', $default_sort_dir);
+$sort_days = $request->variable('st', $default_sort_days);
+$sort_key = $request->variable('sk', $default_sort_key);
+$sort_dir = $request->variable('sd', $default_sort_dir);
+/* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
// Check if the user has actually sent a forum ID with his/her request
@@ -90,6 +91,7 @@ if (!$auth->acl_gets('f_list', 'f_read', $forum_id) || ($forum_data['forum_type'
{
if ($user->data['user_id'] != ANONYMOUS)
{
+ send_status_line(403, 'Forbidden');
trigger_error('SORRY_AUTH_READ');
}
@@ -146,6 +148,7 @@ else
}
}
+/* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
// Dump out the page header and load viewforum template
@@ -184,10 +187,10 @@ if (!$auth->acl_get('f_read', $forum_id))
// Handle marking posts
if ($mark_read == 'topics')
{
- $token = request_var('hash', '');
+ $token = $request->variable('hash', '');
if (check_link_hash($token, 'global'))
{
- markread('topics', array($forum_id), false, request_var('mark_time', 0));
+ markread('topics', array($forum_id), false, $request->variable('mark_time', 0));
}
$redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
meta_refresh(3, $redirect_url);
@@ -218,6 +221,7 @@ if ($forum_data['forum_topics_per_page'])
// Do the forum Prune thang - cron type job ...
if (!$config['use_system_cron'])
{
+ /* @var $cron \phpbb\cron\manager */
$cron = $phpbb_container->get('cron.manager');
$task = $cron->find_task('cron.task.core.prune_forum');
diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php
index 8bfa422e26..85eb653b5a 100644
--- a/phpBB/viewonline.php
+++ b/phpBB/viewonline.php
@@ -25,25 +25,29 @@ $auth->acl($user->data);
$user->setup('memberlist');
// Get and set some variables
-$mode = request_var('mode', '');
-$session_id = request_var('s', '');
-$start = request_var('start', 0);
-$sort_key = request_var('sk', 'b');
-$sort_dir = request_var('sd', 'd');
-$show_guests = ($config['load_online_guests']) ? request_var('sg', 0) : 0;
+$mode = $request->variable('mode', '');
+$session_id = $request->variable('s', '');
+$start = $request->variable('start', 0);
+$sort_key = $request->variable('sk', 'b');
+$sort_dir = $request->variable('sd', 'd');
+$show_guests = ($config['load_online_guests']) ? $request->variable('sg', 0) : 0;
// Can this user view profiles/memberlist?
if (!$auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel'))
{
if ($user->data['user_id'] != ANONYMOUS)
{
+ send_status_line(403, 'Forbidden');
trigger_error('NO_VIEW_USERS');
}
login_box('', $user->lang['LOGIN_EXPLAIN_VIEWONLINE']);
}
+/* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
+
+/* @var $viewonline_helper \phpbb\viewonline_helper */
$viewonline_helper = $phpbb_container->get('viewonline_helper');
$sort_key_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_JOINED'], 'c' => $user->lang['SORT_LOCATION']);
@@ -123,7 +127,6 @@ if (!$show_guests)
{
switch ($db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
$sql = 'SELECT COUNT(session_ip) as num_guests
FROM (
@@ -178,6 +181,12 @@ $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary));
$prev_id = $prev_ip = $user_list = array();
$logged_visible_online = $logged_hidden_online = $counter = 0;
+/** @var \phpbb\controller\helper $controller_helper */
+$controller_helper = $phpbb_container->get('controller.helper');
+
+/** @var \phpbb\group\helper $group_helper */
+$group_helper = $phpbb_container->get('group_helper');
+
while ($row = $db->sql_fetchrow($result))
{
if ($row['user_id'] != ANONYMOUS && !isset($prev_id[$row['user_id']]))
@@ -302,11 +311,6 @@ while ($row = $db->sql_fetchrow($result))
$location_url = append_sid("{$phpbb_root_path}search.$phpEx");
break;
- case 'faq':
- $location = $user->lang['VIEWING_FAQ'];
- $location_url = append_sid("{$phpbb_root_path}faq.$phpEx");
- break;
-
case 'viewonline':
$location = $user->lang['VIEWING_ONLINE'];
$location_url = append_sid("{$phpbb_root_path}viewonline.$phpEx");
@@ -372,6 +376,13 @@ while ($row = $db->sql_fetchrow($result))
default:
$location = $user->lang['INDEX'];
$location_url = append_sid("{$phpbb_root_path}index.$phpEx");
+
+ if ($row['session_page'] === 'app.' . $phpEx . '/help/faq' ||
+ $row['session_page'] === 'app.' . $phpEx . '/help/bbcode')
+ {
+ $location = $user->lang['VIEWING_FAQ'];
+ $location_url = $controller_helper->route('phpbb_help_faq_controller');
+ }
break;
}
@@ -461,7 +472,7 @@ while ($row = $db->sql_fetchrow($result))
}
else
{
- $legend .= (($legend != '') ? ', ' : '') . '<a style="color:#' . $row['group_colour'] . '" href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $row['group_id']) . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</a>';
+ $legend .= (($legend != '') ? ', ' : '') . '<a style="color:#' . $row['group_colour'] . '" href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $row['group_id']) . '">' . $group_helper->get_name($row['group_name']) . '</a>';
}
}
$db->sql_freeresult($result);
diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php
index 780e43e09b..4325fafb43 100644
--- a/phpBB/viewtopic.php
+++ b/phpBB/viewtopic.php
@@ -27,34 +27,35 @@ $user->session_begin();
$auth->acl($user->data);
// Initial var setup
-$forum_id = request_var('f', 0);
-$topic_id = request_var('t', 0);
-$post_id = request_var('p', 0);
-$voted_id = request_var('vote_id', array('' => 0));
+$forum_id = $request->variable('f', 0);
+$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;
-$start = request_var('start', 0);
-$view = request_var('view', '');
+$start = $request->variable('start', 0);
+$view = $request->variable('view', '');
$default_sort_days = (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0;
$default_sort_key = (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't';
$default_sort_dir = (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a';
-$sort_days = request_var('st', $default_sort_days);
-$sort_key = request_var('sk', $default_sort_key);
-$sort_dir = request_var('sd', $default_sort_dir);
+$sort_days = $request->variable('st', $default_sort_days);
+$sort_key = $request->variable('sk', $default_sort_key);
+$sort_dir = $request->variable('sd', $default_sort_dir);
-$update = request_var('update', false);
+$update = $request->variable('update', false);
+/* @var $pagination \phpbb\pagination */
$pagination = $phpbb_container->get('pagination');
$s_can_vote = false;
/**
* @todo normalize?
*/
-$hilit_words = request_var('hilit', '', true);
+$hilit_words = $request->variable('hilit', '', true);
// Do we have a topic or post id?
if (!$topic_id && !$post_id)
@@ -62,6 +63,7 @@ if (!$topic_id && !$post_id)
trigger_error('NO_TOPIC');
}
+/* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
// Find topic id if user requested a newer or older topic
@@ -374,6 +376,7 @@ if (!$overrides_f_read_check && !$auth->acl_get('f_read', $forum_id))
{
if ($user->data['user_id'] != ANONYMOUS)
{
+ send_status_line(403, 'Forbidden');
trigger_error('SORRY_AUTH_READ');
}
@@ -496,9 +499,9 @@ if ($config['allow_topic_notify'])
}
// Bookmarks
-if ($config['allow_bookmarks'] && $user->data['is_registered'] && request_var('bookmark', 0))
+if ($config['allow_bookmarks'] && $user->data['is_registered'] && $request->variable('bookmark', 0))
{
- if (check_link_hash(request_var('hash', ''), "topic_$topic_id"))
+ if (check_link_hash($request->variable('hash', ''), "topic_$topic_id"))
{
if (!$topic_data['bookmarked'])
{
@@ -581,10 +584,10 @@ $quickmod_array = array(
'merge' => array('MERGE_POSTS', $auth->acl_get('m_merge', $forum_id)),
'merge_topic' => array('MERGE_TOPIC', $auth->acl_get('m_merge', $forum_id)),
'fork' => array('FORK_TOPIC', $auth->acl_get('m_move', $forum_id)),
- 'make_normal' => array('MAKE_NORMAL', ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', $forum_id) && $topic_data['topic_type'] != POST_NORMAL)),
+ 'make_normal' => array('MAKE_NORMAL', ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', 'f_announce_global', $forum_id) && $topic_data['topic_type'] != POST_NORMAL)),
'make_sticky' => array('MAKE_STICKY', ($allow_change_type && $auth->acl_get('f_sticky', $forum_id) && $topic_data['topic_type'] != POST_STICKY)),
'make_announce' => array('MAKE_ANNOUNCE', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_ANNOUNCE)),
- 'make_global' => array('MAKE_GLOBAL', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL)),
+ 'make_global' => array('MAKE_GLOBAL', ($allow_change_type && $auth->acl_get('f_announce_global', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL)),
'topic_logs' => array('VIEW_TOPIC_LOGS', $auth->acl_get('m_', $forum_id)),
);
@@ -1431,6 +1434,7 @@ $db->sql_freeresult($result);
// Load custom profile fields
if ($config['load_cpf_viewtopic'])
{
+ /* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
// Grab all profile fields from users in id cache for later use - similar to the poster cache
@@ -1621,6 +1625,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
{
$parse_flags = ($user_cache[$poster_id]['sig_bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
$user_cache[$poster_id]['sig'] = generate_text_for_display($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$poster_id]['sig_bbcode_bitfield'], $parse_flags, true);
+ $user_cache[$poster_id]['sig_parsed'] = true;
}
// Parse the message and subject
@@ -1918,6 +1923,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
'POST_ICON_IMG' => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['img'] : '',
'POST_ICON_IMG_WIDTH' => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['width'] : '',
'POST_ICON_IMG_HEIGHT' => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['height'] : '',
+ 'POST_ICON_IMG_ALT' => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['alt'] : '',
'ONLINE_IMG' => ($poster_id == ANONYMOUS || !$config['load_onlinetrack']) ? '' : (($user_cache[$poster_id]['online']) ? $user->img('icon_user_online', 'ONLINE') : $user->img('icon_user_offline', 'OFFLINE')),
'S_ONLINE' => ($poster_id == ANONYMOUS || !$config['load_onlinetrack']) ? false : (($user_cache[$poster_id]['online']) ? true : false),
@@ -1932,7 +1938,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
'U_JABBER' => $user_cache[$poster_id]['jabber'],
'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&amp;p={$row['post_id']}&amp;f=$forum_id&amp;redirect=" . urlencode(str_replace('&amp;', '&', $viewtopic_url . '&amp;p=' . $row['post_id'] . '#p' . $row['post_id']))),
- 'U_REPORT' => ($auth->acl_get('f_report', $forum_id)) ? append_sid("{$phpbb_root_path}report.$phpEx", 'f=' . $forum_id . '&amp;p=' . $row['post_id']) : '',
+ 'U_REPORT' => ($auth->acl_get('f_report', $forum_id)) ? $phpbb_container->get('controller.helper')->route('phpbb_report_post_controller', array('id' => $row['post_id'])) : '',
'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
'U_MCP_APPROVE' => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
'U_MCP_RESTORE' => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=' . (($topic_data['topic_visibility'] != ITEM_DELETED) ? 'deleted_posts' : 'deleted_topics') . '&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
@@ -1945,6 +1951,8 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
'POST_ID' => $row['post_id'],
'POST_NUMBER' => $i + $start + 1,
'POSTER_ID' => $poster_id,
+ 'MINI_POST' => ($post_unread) ? $user->lang['UNREAD_POST'] : $user->lang['POST'],
+
'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false,
'S_MULTIPLE_ATTACHMENTS' => !empty($attachments[$row['post_id']]) && sizeof($attachments[$row['post_id']]) > 1,
@@ -2226,13 +2234,13 @@ if ($s_can_vote || $s_quick_reply)
// We overwrite $_REQUEST['f'] if there is no forum specified
// to be able to display the correct online list.
// One downside is that the user currently viewing this topic/post is not taken into account.
-if (!request_var('f', 0))
+if (!$request->variable('f', 0))
{
$request->overwrite('f', $forum_id);
}
// We need to do the same with the topic_id. See #53025.
-if (!request_var('t', 0) && !empty($topic_id))
+if (!$request->variable('t', 0) && !empty($topic_id))
{
$request->overwrite('t', $topic_id);
}
diff --git a/tests/RUNNING_TESTS.md b/tests/RUNNING_TESTS.md
index afd7caa709..b082197166 100644
--- a/tests/RUNNING_TESTS.md
+++ b/tests/RUNNING_TESTS.md
@@ -120,8 +120,9 @@ directory (above phpBB):
Slow tests
--------------
-Certain tests, such as the UTF-8 normalizer or the DNS tests tend to be slow.
-Thus these tests are in the `slow` group, which is excluded by default. If you
+Certain tests, such as the DNS tests tend to be slow.
+Thus these tests are in the `slow` group, which is excluded by default. You can
+enable slow tests by copying the phpunit.xml.all file to phpunit.xml. If you
only want the slow tests, run:
$ phpBB/vendor/bin/phpunit --group slow
diff --git a/tests/attachment/delete_test.php b/tests/attachment/delete_test.php
new file mode 100644
index 0000000000..f1835dd37a
--- /dev/null
+++ b/tests/attachment/delete_test.php
@@ -0,0 +1,127 @@
+<?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.
+*
+*/
+
+require_once(dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php');
+
+class phpbb_attachment_delete_test extends \phpbb_database_test_case
+{
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\filesystem\filesystem */
+ protected $filesystem;
+
+ /** @var \phpbb\attachment\resync */
+ protected $resync;
+
+ /** @var \phpbb\attachment\delete */
+ protected $attachment_delete;
+
+ protected $phpbb_root_path;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/resync.xml');
+ }
+
+ public function setUp()
+ {
+ global $db, $phpbb_root_path;
+
+ parent::setUp();
+
+ $this->config = new \phpbb\config\config(array());
+ $this->db = $this->new_dbal();
+ $db = $this->db;
+ $this->resync = new \phpbb\attachment\resync($this->db);
+ $this->filesystem = $this->getMock('\phpbb\filesystem\filesystem', array('remove', 'exists'));
+ $this->filesystem->expects($this->any())
+ ->method('remove')
+ ->willReturn(false);
+ $this->filesystem->expects($this->any())
+ ->method('exists')
+ ->willReturn(true);
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->dispatcher = new \phpbb_mock_event_dispatcher();
+ $this->attachment_delete = new \phpbb\attachment\delete($this->config, $this->db, $this->dispatcher, $this->filesystem, $this->resync, $phpbb_root_path);
+ }
+
+ public function data_attachment_delete()
+ {
+ return array(
+ array('attach', '', false, false),
+ array('meh', 5, false, 0),
+ array('attach', array(5), false, 0),
+ array('attach', array(1,2), false, 2),
+ array('attach', array(1,2), true, 2),
+ array('post', 5, false, 0),
+ array('topic', 5, false, 0),
+ array('topic', 1, true, 3),
+ array('user', 1, false, 0),
+ );
+ }
+
+ /**
+ * @dataProvider data_attachment_delete
+ */
+ public function test_attachment_delete($mode, $ids, $resync, $expected)
+ {
+ // We need to reset the attachment ID sequence to properly test this
+ if ($this->db->get_sql_layer() === 'postgres')
+ {
+ $sql = 'ALTER SEQUENCE phpbb_attachments_seq RESTART WITH 1';
+ $this->db->sql_query($sql);
+ }
+
+ $this->assertSame($expected, $this->attachment_delete->delete($mode, $ids, $resync));
+ }
+
+ public function data_attachment_unlink()
+ {
+ return array(
+ array(true, true, true),
+ array(true, false, false),
+ array(true, true, false, true),
+ );
+ }
+
+ /**
+ * @dataProvider data_attachment_unlink
+ */
+ public function test_attachment_delete_success($remove_success, $exists_success, $expected, $throw_exception = false)
+ {
+ $this->filesystem = $this->getMock('\phpbb\filesystem\filesystem', array('remove', 'exists'));
+ if ($throw_exception)
+ {
+ $this->filesystem->expects($this->any())
+ ->method('remove')
+ ->willThrowException(new \phpbb\filesystem\exception\filesystem_exception);;
+ }
+ else
+ {
+ $this->filesystem->expects($this->any())
+ ->method('remove')
+ ->willReturn($remove_success);
+ }
+
+ $this->filesystem->expects($this->any())
+ ->method('exists')
+ ->willReturn($exists_success);
+
+ $this->attachment_delete = new \phpbb\attachment\delete($this->config, $this->db, $this->dispatcher, $this->filesystem, $this->resync, $this->phpbb_root_path);
+ $this->assertSame($expected, $this->attachment_delete->unlink_attachment('foobar'));
+ }
+}
diff --git a/tests/attachment/fixtures/resync.xml b/tests/attachment/fixtures/resync.xml
new file mode 100644
index 0000000000..6e2cc62f68
--- /dev/null
+++ b/tests/attachment/fixtures/resync.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_attachments">
+ <column>post_msg_id</column>
+ <column>topic_id</column>
+ <column>in_message</column>
+ <column>is_orphan</column>
+ <column>attach_comment</column>
+ <column>physical_filename</column>
+ <column>thumbnail</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value>0</value>
+ <value>foo</value>
+ <value>foo</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value>foo2</value>
+ <value>foo2</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value>foo2</value>
+ <value>foo2</value>
+ <value>1</value>
+ </row>
+ </table>
+ <table name="phpbb_extensions">
+ <column>extension</column>
+ <column>group_id</column>
+ <row>
+ <value>jpg</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>png</value>
+ <value>1</value>
+ </row>
+ </table>
+ <table name="phpbb_extension_groups">
+ <column>cat_id</column>
+ <column>group_id</column>
+ <column>download_mode</column>
+ <column>upload_icon</column>
+ <column>max_filesize</column>
+ <column>allow_group</column>
+ <column>allow_in_pm</column>
+ <column>allowed_forums</column>
+ <column>group_name</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value> </value>
+ <value>1000</value>
+ <value>1</value>
+ <value>1</value>
+ <value>a:1:{i:0;i:1;}</value>
+ <value>Images</value>
+ </row>
+ </table>
+ <table name="phpbb_posts">
+ <column>post_id</column>
+ <column>post_text</column>
+ <column>poster_id</column>
+ <column>post_attachment</column>
+ <row>
+ <value>1</value>
+ <value>foo</value>
+ <value>1</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>foo</value>
+ <value>1</value>
+ <value>1</value>
+ </row>
+ </table>
+ <table name="phpbb_privmsgs">
+ <column>msg_id</column>
+ <column>message_text</column>
+ <column>message_attachment</column>
+ <column>to_address</column>
+ <column>bcc_address</column>
+ <row>
+ <value>1</value>
+ <value>foo</value>
+ <value>1</value>
+ <value>2</value>
+ <value>2</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>foo</value>
+ <value>1</value>
+ <value>2</value>
+ <value>2</value>
+ </row>
+ </table>
+ <table name="phpbb_topics">
+ <column>topic_id</column>
+ <column>forum_id</column>
+ <column>topic_title</column>
+ <column>topic_attachment</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>foo</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ <value>bar</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/attachment/manager_test.php b/tests/attachment/manager_test.php
new file mode 100644
index 0000000000..47d7f38b1d
--- /dev/null
+++ b/tests/attachment/manager_test.php
@@ -0,0 +1,131 @@
+<?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.
+ *
+ */
+
+class phpbb_attachment_manager_test extends \phpbb_test_case
+{
+ protected $delete;
+ protected $resync;
+ protected $upload;
+
+ public function setUp()
+ {
+ $this->delete = $this->getMockBuilder('\phpbb\attachment\delete')
+ ->disableOriginalConstructor()
+ ->setMethods(['delete', 'unlink_attachment'])
+ ->getMock();
+ $this->resync = $this->getMockBuilder('\phpbb\attachment\resync')
+ ->disableOriginalConstructor()
+ ->setMethods(['resync'])
+ ->getMock();
+ $this->upload = $this->getMockBuilder('\phpbb\attachment\upload')
+ ->disableOriginalConstructor()
+ ->setMethods(['upload'])
+ ->getMock();
+ }
+
+ protected function get_manager()
+ {
+ return new \phpbb\attachment\manager($this->delete, $this->resync, $this->upload);
+ }
+
+ public function data_manager()
+ {
+ return array(
+ array(
+ 'delete',
+ 'unlink_attachment',
+ 'unlink',
+ ['foo'],
+ ['foo', 'file', false],
+ true,
+ true,
+ ),
+ array(
+ 'delete',
+ 'unlink_attachment',
+ 'unlink',
+ ['foo', 'bar'],
+ ['foo', 'bar', false],
+ true,
+ true,
+ ),
+ array(
+ 'delete',
+ 'unlink_attachment',
+ 'unlink',
+ ['foo', 'bar', true],
+ ['foo', 'bar', true],
+ true,
+ true,
+ ),
+ array(
+ 'delete',
+ 'delete',
+ 'delete',
+ ['foo', [1, 2, 3]],
+ ['foo', [1, 2, 3], true],
+ 5,
+ 5,
+ ),
+ array(
+ 'delete',
+ 'delete',
+ 'delete',
+ ['foo', [1, 2, 3], false],
+ ['foo', [1, 2, 3], false],
+ 2,
+ 2,
+ ),
+ array(
+ 'resync',
+ 'resync',
+ 'resync',
+ ['foo', [1, 2, 3]],
+ ['foo', [1, 2, 3]],
+ true,
+ null,
+ ),
+ array(
+ 'upload',
+ 'upload',
+ 'upload',
+ ['foo', 1],
+ ['foo', 1, false, '', false, []],
+ true,
+ true,
+ ),
+ array(
+ 'upload',
+ 'upload',
+ 'upload',
+ ['foo', 1, true, 'bar', true, ['filename' => 'foobar']],
+ ['foo', 1, true, 'bar', true, ['filename' => 'foobar']],
+ true,
+ true,
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider data_manager
+ */
+ public function test_manager($class, $method_class, $method_manager, $input_manager, $input_method, $return, $output)
+ {
+ $mock = call_user_func_array([$this->{$class}, 'expects'], [$this->atLeastOnce()]);
+ $mock = $mock->method($method_class);
+ $mock = call_user_func_array([$mock, 'with'], $input_method);
+ $mock->willReturn($return);
+ $manager = $this->get_manager();
+ $this->assertSame($output, call_user_func_array([$manager, $method_manager], $input_manager));
+ }
+}
diff --git a/tests/attachment/resync_test.php b/tests/attachment/resync_test.php
new file mode 100644
index 0000000000..f882af9ae5
--- /dev/null
+++ b/tests/attachment/resync_test.php
@@ -0,0 +1,74 @@
+<?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.
+*
+*/
+
+class phpbb_attachment_resync_test extends \phpbb_database_test_case
+{
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\attachment\resync */
+ protected $resync;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/resync.xml');
+ }
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->db = $this->new_dbal();
+ $this->resync = new \phpbb\attachment\resync($this->db);
+ }
+
+ public function data_resync()
+ {
+ return array(
+ array('', array(1), 'post_id', POSTS_TABLE, array('post_attachment' => '1'), array('post_attachment' => '1')),
+ array('post', array(1), 'post_id', POSTS_TABLE, array('post_attachment' => '1'), array('post_attachment' => '1')),
+ array('post', array(2), 'post_id', POSTS_TABLE, array('post_attachment' => '1'), array('post_attachment' => '0')),
+ array('topic', array(1), 'topic_id', TOPICS_TABLE, array('topic_attachment' => '1'), array('topic_attachment' => '1')),
+ array('topic', array(2), 'topic_id', TOPICS_TABLE, array('topic_attachment' => '1'), array('topic_attachment' => '0')),
+ array('message', array(1), 'msg_id', PRIVMSGS_TABLE, array('message_attachment' => '1'), array('message_attachment' => '1')),
+ array('message', array(2), 'msg_id', PRIVMSGS_TABLE, array('message_attachment' => '1'), array('message_attachment' => '0')),
+ );
+ }
+
+ /**
+ * @dataProvider data_resync
+ */
+ public function test_resync($type, $ids, $sql_id, $exist_table, $exist_data, $resync_data)
+ {
+ $sql_prefix = ($type) ?: 'post';
+ $sql = 'SELECT ' . $sql_prefix . '_attachment
+ FROM ' . $exist_table . '
+ WHERE ' . $sql_id . ' = ' . $ids[0];
+ $result = $this->db->sql_query($sql);
+ $data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->assertEquals($exist_data, $data);
+
+ $this->resync->resync($type, $ids);
+
+ $sql = 'SELECT ' . $sql_prefix . '_attachment
+ FROM ' . $exist_table . '
+ WHERE ' . $sql_id . ' = ' . $ids[0];
+ $result = $this->db->sql_query($sql);
+ $data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $this->assertEquals($resync_data, $data);
+ }
+}
diff --git a/tests/attachment/upload_test.php b/tests/attachment/upload_test.php
new file mode 100644
index 0000000000..235ecd082a
--- /dev/null
+++ b/tests/attachment/upload_test.php
@@ -0,0 +1,429 @@
+<?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.
+*
+*/
+
+require_once(dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php');
+
+class phpbb_attachment_upload_test extends \phpbb_database_test_case
+{
+ /** @var \phpbb\auth\auth */
+ protected $auth;
+
+ /** @var \phpbb\cache\service */
+ protected $cache;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \phpbb\files\upload */
+ protected $files_upload;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\mimetype\guesser */
+ protected $mimetype_guesser;
+
+ /** @var \phpbb\event\dispatcher */
+ protected $phpbb_dispatcher;
+
+ /** @var \phpbb\plupload\plupload */
+ protected $plupload;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ /** @var \phpbb\attachment\upload */
+ protected $upload;
+
+ private $filesystem;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/resync.xml');
+ }
+
+ public function setUp()
+ {
+ global $config, $phpbb_root_path, $phpEx;
+
+ parent::setUp();
+
+ $this->auth = new \phpbb\auth\auth();
+ $this->config = new \phpbb\config\config(array(
+ 'upload_path' => '',
+ 'img_create_thumbnail' => true,
+ ));
+ $config = $this->config;
+ $this->db = $this->new_dbal();
+ $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), $this->config, $this->db, $phpbb_root_path, $phpEx);
+ $this->request = $this->getMock('\phpbb\request\request');
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+ $guessers = array(
+ new \Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser(),
+ new \Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser(),
+ new \phpbb\mimetype\content_guesser(),
+ new \phpbb\mimetype\extension_guesser(),
+ );
+ $guessers[2]->set_priority(-2);
+ $guessers[3]->set_priority(-2);
+ $this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers);
+ $this->plupload = new \phpbb\plupload\plupload($phpbb_root_path, $this->config, $this->request, new \phpbb\user($this->language, '\phpbb\datetime'), $this->php_ini, $this->mimetype_guesser);
+ $factory_mock = $this->getMockBuilder('\phpbb\files\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory_mock->expects($this->any())
+ ->method('get')
+ ->willReturn(new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $this->phpbb_root_path,
+ $this->mimetype_guesser
+ ));
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->container->set('files.types.form', new \phpbb\files\types\form(
+ $factory_mock,
+ $this->language,
+ $this->php_ini,
+ $this->plupload,
+ $this->request
+ ));
+ $this->container->set('files.types.local', new \phpbb\files\types\local(
+ $factory_mock,
+ $this->language,
+ $this->php_ini,
+ $this->request
+ ));
+ $this->factory = new \phpbb\files\factory($this->container);
+ $this->files_upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $this->phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $this->user = new \phpbb\user($this->language, '\phpbb\datetime');
+
+
+ $this->upload = new \phpbb\attachment\upload(
+ $this->auth,
+ $this->cache,
+ $this->config,
+ $this->files_upload,
+ $this->language,
+ $this->mimetype_guesser,
+ $this->phpbb_dispatcher,
+ $this->plupload,
+ $this->user,
+ $this->phpbb_root_path
+ );
+ }
+
+ public function data_upload()
+ {
+ return array(
+ array('foobar', 1, false,
+ array(),
+ array(
+ 'error' => array(
+ 'Upload initiated but no valid file upload form found.',
+ ),
+ 'post_attach' => false,
+ )
+ ),
+ array('foobar', 1, true,
+ array(
+ 'realname' => 'foobar.jpg',
+ 'type' => 'jpg',
+ 'size' => 100,
+ ),
+ array(
+ 'error' => array(
+ 'NOT_UPLOADED',
+ 'The image file you tried to attach is invalid.',
+ ),
+ 'post_attach' => false,
+ 'thumbnail' => 1,
+ )
+ ),
+ array('foobar', 1, true,
+ array(),
+ array(
+ 'error' => array(
+ 'NOT_UPLOADED',
+ ),
+ 'post_attach' => false,
+ 'thumbnail' => 0,
+ )
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider data_upload
+ */
+ public function test_upload($form_name, $forum_id, $local, $filedata, $expected)
+ {
+ $filedata = $this->upload->upload($form_name, $forum_id, $local, '', false, $filedata);
+
+ $this->assertSame($expected, $filedata);
+ }
+
+ public function test_init_error()
+ {
+ $filespec = $this->getMockBuilder('\phpbb\files\filespec')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $filespec->expects($this->any())
+ ->method('init_error')
+ ->willReturn(true);
+ $filespec->expects($this->any())
+ ->method('set_upload_namespace')
+ ->willReturnSelf();
+ $filespec->expects($this->any())
+ ->method('set_upload_ary')
+ ->willReturnSelf();
+ $this->container->set('files.filespec', $filespec);
+ $factory_mock = $this->getMockBuilder('\phpbb\files\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory_mock->expects($this->any())
+ ->method('get')
+ ->willReturn($filespec);
+ $this->container->set('files.types.local', new \phpbb\files\types\local(
+ $factory_mock,
+ $this->language,
+ $this->php_ini,
+ $this->request
+ ));
+
+ $this->upload = new \phpbb\attachment\upload(
+ $this->auth,
+ $this->cache,
+ $this->config,
+ $this->files_upload,
+ $this->language,
+ $this->mimetype_guesser,
+ $this->phpbb_dispatcher,
+ $this->plupload,
+ $this->user,
+ $this->phpbb_root_path
+ );
+
+ $filedata = $this->upload->upload('foobar', 1, true);
+
+ $this->assertSame(array(
+ 'error' => array(),
+ 'post_attach' => false,
+ ), $filedata);
+ }
+
+ public function data_image_upload()
+ {
+ return array(
+ array(false, false, array(),
+ array(
+ 'error' => array('The image file you tried to attach is invalid.'),
+ 'post_attach' => false,
+ 'thumbnail' => 1,
+ )
+ ),
+ array(false, true, array(),
+ array(
+ 'error' => array('The image file you tried to attach is invalid.'),
+ 'post_attach' => false,
+ 'thumbnail' => 1,
+ )
+ ),
+ array(true, false, array(),
+ array(
+ 'error' => array(),
+ 'post_attach' => true,
+ // thumbnail gets reset to 0 as creation was not possible
+ 'thumbnail' => 0,
+ 'filesize' => 100,
+ 'mimetype' => 'jpg',
+ 'extension' => 'jpg',
+ 'real_filename' => 'foobar.jpg',
+ )
+ ),
+ array(true, false,
+ array(
+ 'check_attachment_content' => true,
+ 'mime_triggers' => '',
+ ),
+ array(
+ 'error' => array(),
+ 'post_attach' => true,
+ // thumbnail gets reset to 0 as creation was not possible
+ 'thumbnail' => 0,
+ 'filesize' => 100,
+ 'mimetype' => 'jpg',
+ 'extension' => 'jpg',
+ 'real_filename' => 'foobar.jpg',
+ )
+ ),
+ array(true, false,
+ array(
+ 'attachment_quota' => 150,
+ ),
+ array(
+ 'error' => array(),
+ 'post_attach' => true,
+ // thumbnail gets reset to 0 as creation was not possible
+ 'thumbnail' => 0,
+ 'filesize' => 100,
+ 'mimetype' => 'jpg',
+ 'extension' => 'jpg',
+ 'real_filename' => 'foobar.jpg',
+ )
+ ),
+ array(true, false,
+ array(
+ 'attachment_quota' => 50,
+ ),
+ array(
+ 'error' => array(
+ 'ATTACH_QUOTA_REACHED',
+ ),
+ 'post_attach' => false,
+ 'thumbnail' => 1,
+ 'filesize' => 100,
+ 'mimetype' => 'jpg',
+ 'extension' => 'jpg',
+ 'real_filename' => 'foobar.jpg',
+ )
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider data_image_upload
+ */
+ public function test_image_upload($is_image, $plupload_active, $config_data, $expected)
+ {
+ $filespec = $this->getMock('\phpbb\files\filespec',
+ array(
+ 'init_error',
+ 'is_image',
+ 'move_file',
+ 'is_uploaded',
+ ),
+ array(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $this->phpbb_root_path,
+ $this->mimetype_guesser,
+ $this->plupload
+ ));
+ foreach ($config_data as $key => $value)
+ {
+ $this->config[$key] = $value;
+ }
+ $filespec->set_upload_namespace($this->files_upload);
+ $filespec->expects($this->any())
+ ->method('init_error')
+ ->willReturn(false);
+ $filespec->expects($this->any())
+ ->method('is_image')
+ ->willReturn($is_image);
+ $filespec->expects($this->any())
+ ->method('is_uploaded')
+ ->willReturn(true);
+ $filespec->expects($this->any())
+ ->method('move_file')
+ ->willReturn(false);
+ $this->container->set('files.filespec', $filespec);
+ $factory_mock = $this->getMockBuilder('\phpbb\files\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory_mock->expects($this->any())
+ ->method('get')
+ ->willReturn($filespec);
+ $this->container->set('files.types.local', new \phpbb\files\types\local(
+ $factory_mock,
+ $this->language,
+ $this->php_ini,
+ $this->request
+ ));
+
+ $plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $plupload->expects($this->any())
+ ->method('is_active')
+ ->willReturn($plupload_active);
+ if ($plupload_active)
+ {
+ $plupload->expects($this->once())
+ ->method('emit_error')
+ ->with(104, 'ATTACHED_IMAGE_NOT_IMAGE')
+ ->willReturn(false);
+ }
+ $this->upload = new \phpbb\attachment\upload(
+ $this->auth,
+ $this->cache,
+ $this->config,
+ $this->files_upload,
+ $this->language,
+ $this->mimetype_guesser,
+ $this->phpbb_dispatcher,
+ $plupload,
+ $this->user,
+ $this->phpbb_root_path
+ );
+
+ $filedata = $this->upload->upload('foobar', 1, true, '', false, array(
+ 'realname' => 'foobar.jpg',
+ 'type' => 'jpg',
+ 'size' => 100,
+ ));
+
+ foreach ($expected as $key => $entry)
+ {
+ $this->assertEquals($entry, $filedata[$key]);
+ }
+
+ // Reset config data
+ foreach ($config_data as $key => $value)
+ {
+ $this->config->delete($key);
+ }
+ }
+}
diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php
index 68ad7b2c19..7d77d763fb 100644
--- a/tests/auth/provider_apache_test.php
+++ b/tests/auth/provider_apache_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_auth_provider_apache_test extends phpbb_database_test_case
{
protected $provider;
@@ -28,8 +25,10 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case
$db = $this->new_dbal();
$config = new \phpbb\config\config(array());
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
$this->request = $this->getMock('\phpbb\request\request');
- $this->user = new \phpbb\user('\phpbb\datetime');
+ $this->user = new \phpbb\user($lang, '\phpbb\datetime');
$driver_helper = new \phpbb\passwords\driver\helper($config);
$passwords_drivers = array(
'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper),
diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php
index 09ca0816bf..6ff77da564 100644
--- a/tests/auth/provider_db_test.php
+++ b/tests/auth/provider_db_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_auth_provider_db_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -38,8 +35,10 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case
'ip_login_limit_use_forwarded' => 0,
'max_login_attempts' => 0,
));
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
$request = $this->getMock('\phpbb\request\request');
- $user = new \phpbb\user('\phpbb\datetime');
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$driver_helper = new \phpbb\passwords\driver\helper($config);
$passwords_drivers = array(
'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper),
diff --git a/tests/auth/provider_oauth_token_storage_test.php b/tests/auth/provider_oauth_token_storage_test.php
index 71b49ff439..ae5de6aa7e 100644
--- a/tests/auth/provider_oauth_token_storage_test.php
+++ b/tests/auth/provider_oauth_token_storage_test.php
@@ -22,6 +22,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
protected $session_id;
protected $token_storage;
protected $token_storage_table;
+ protected $state_table;
protected $user;
protected function setup()
@@ -31,9 +32,12 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
global $phpbb_root_path, $phpEx;
$this->db = $this->new_dbal();
- $this->user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $this->user = new \phpbb\user($lang, '\phpbb\datetime');
$this->service_name = 'auth.provider.oauth.service.testing';
$this->token_storage_table = 'phpbb_oauth_tokens';
+ $this->state_table = 'phpbb_oauth_states';
// Give the user a session_id that we will remember
$this->session_id = '12345';
@@ -42,7 +46,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
// Set the user id to anonymous
$this->user->data['user_id'] = ANONYMOUS;
- $this->token_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table);
+ $this->token_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);
}
public function getDataSet()
@@ -96,7 +100,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
$expected_token = new StdOAuth2Token('access', 'refresh', StdOAuth2Token::EOL_NEVER_EXPIRES);
// Store a token in the database
- $temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table);
+ $temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);
$temp_storage->storeAccessToken($this->service_name, $expected_token);
unset($temp_storage);
@@ -127,7 +131,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c
$expected_token = new StdOAuth2Token('access', 'refresh', StdOAuth2Token::EOL_NEVER_EXPIRES);
// Store a token in the database
- $temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table);
+ $temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);
$temp_storage->storeAccessToken($this->service_name, $expected_token);
unset($temp_storage);
diff --git a/tests/avatar/driver/barfoo.php b/tests/avatar/driver/barfoo.php
index 0bf30b8a91..067bb3ef97 100644
--- a/tests/avatar/driver/barfoo.php
+++ b/tests/avatar/driver/barfoo.php
@@ -1,26 +1,26 @@
-<?php
-
-namespace phpbb\avatar\driver;
-
-class barfoo extends \phpbb\avatar\driver\driver
-{
- public function get_data($row)
- {
- return array();
- }
-
- public function prepare_form($request, $template, $user, $row, &$error)
- {
- return false;
- }
-
- public function process_form($request, $template, $user, $row, &$error)
- {
- return false;
- }
-
- public function get_template_name()
- {
- return 'barfoo.html';
- }
-}
+<?php
+
+namespace phpbb\avatar\driver;
+
+class barfoo extends \phpbb\avatar\driver\driver
+{
+ public function get_data($row)
+ {
+ return array();
+ }
+
+ public function prepare_form($request, $template, $user, $row, &$error)
+ {
+ return false;
+ }
+
+ public function process_form($request, $template, $user, $row, &$error)
+ {
+ return false;
+ }
+
+ public function get_template_name()
+ {
+ return 'barfoo.html';
+ }
+}
diff --git a/tests/avatar/driver/foobar.php b/tests/avatar/driver/foobar.php
index aabdaf5ac4..16d50ccad4 100644
--- a/tests/avatar/driver/foobar.php
+++ b/tests/avatar/driver/foobar.php
@@ -1,26 +1,26 @@
-<?php
-
-namespace phpbb\avatar\driver;
-
-class foobar extends \phpbb\avatar\driver\driver
-{
- public function get_data($row)
- {
- return array();
- }
-
- public function prepare_form($request, $template, $user, $row, &$error)
- {
- return false;
- }
-
- public function process_form($request, $template, $user, $row, &$error)
- {
- return false;
- }
-
- public function get_template_name()
- {
- return 'foobar.html';
- }
-}
+<?php
+
+namespace phpbb\avatar\driver;
+
+class foobar extends \phpbb\avatar\driver\driver
+{
+ public function get_data($row)
+ {
+ return array();
+ }
+
+ public function prepare_form($request, $template, $user, $row, &$error)
+ {
+ return false;
+ }
+
+ public function process_form($request, $template, $user, $row, &$error)
+ {
+ return false;
+ }
+
+ public function get_template_name()
+ {
+ return 'foobar.html';
+ }
+}
diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php
index 344eef38ff..924f1319a2 100644
--- a/tests/avatar/manager_test.php
+++ b/tests/avatar/manager_test.php
@@ -35,6 +35,8 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
->method('get')
->will($this->returnArgument(0));
+ $filesystem = new \phpbb\filesystem\filesystem();
+
// Prepare dependencies for avatar manager and driver
$this->config = new \phpbb\config\config(array());
$cache = $this->getMock('\phpbb\cache\driver\driver_interface');
@@ -42,7 +44,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ $filesystem,
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
$phpEx
@@ -55,11 +57,12 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
new \phpbb\mimetype\content_guesser,
);
$guesser = new \phpbb\mimetype\guesser($guessers);
+ $imagesize = new \FastImageSize\FastImageSize();
$dispatcher = new phpbb_mock_event_dispatcher();
// $this->avatar_foobar will be needed later on
- $this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache));
+ $this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache));
$this->avatar_foobar->expects($this->any())
->method('get_name')
->will($this->returnValue('avatar.driver.foobar'));
@@ -73,15 +76,17 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
->will($this->returnValue('barfoo'));
$avatar_drivers = array($this->avatar_foobar, $this->avatar_barfoo);
+ $files_factory = new \phpbb\files\factory($phpbb_container);
+
foreach ($this->avatar_drivers() as $driver)
{
if ($driver !== 'upload')
{
- $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache));
+ $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache));
}
else
{
- $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $guesser, $dispatcher, $cache));
+ $cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $filesystem, $path_helper, $dispatcher, $files_factory, $cache));
}
$cur_avatar->expects($this->any())
->method('get_name')
@@ -96,7 +101,9 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
// Set up avatar manager
$this->manager = new \phpbb\avatar\manager($this->config, $avatar_drivers, $phpbb_container);
$this->db = $this->new_dbal();
- $this->user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $this->user = new \phpbb\user($lang, '\phpbb\datetime');
}
protected function avatar_drivers()
@@ -279,7 +286,12 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
public function test_localize_errors()
{
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime')
+ );
$lang_array = array(
array('FOOBAR_OFF', 'foobar_off'),
array('FOOBAR_EXPLAIN', 'FOOBAR_EXPLAIN %s'),
diff --git a/tests/bbcode/parser_test.php b/tests/bbcode/parser_test.php
index 14736627f3..5677e49636 100644
--- a/tests/bbcode/parser_test.php
+++ b/tests/bbcode/parser_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/bbcode.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/message_parser.php';
diff --git a/tests/bbcode/url_bbcode_test.php b/tests/bbcode/url_bbcode_test.php
index 83176abe4c..3f8ad6022f 100644
--- a/tests/bbcode/url_bbcode_test.php
+++ b/tests/bbcode/url_bbcode_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/bbcode.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/message_parser.php';
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 0e81f4372a..18977bac88 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -12,14 +12,21 @@
*/
define('IN_PHPBB', true);
+define('PHPBB_ENVIRONMENT', 'test');
+
$phpbb_root_path = 'phpBB/';
$phpEx = 'php';
+
+global $table_prefix;
require_once $phpbb_root_path . 'includes/startup.php';
$table_prefix = 'phpbb_';
require_once $phpbb_root_path . 'includes/constants.php';
require_once $phpbb_root_path . 'phpbb/class_loader.' . $phpEx;
-require_once($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
+require_once $phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx;
+require_once $phpbb_root_path . 'includes/functions.' . $phpEx;
+require_once $phpbb_root_path . 'includes/functions_content.' . $phpEx;
+require_once $phpbb_root_path . 'includes/functions_compatibility.' . $phpEx;
$phpbb_class_loader_mock = new \phpbb\class_loader('phpbb_mock_', $phpbb_root_path . '../tests/mock/', "php");
$phpbb_class_loader_mock->register();
diff --git a/tests/cache/apc_driver_test.php b/tests/cache/apc_driver_test.php
index 10130b465b..706f274448 100644
--- a/tests/cache/apc_driver_test.php
+++ b/tests/cache/apc_driver_test.php
@@ -34,14 +34,14 @@ class phpbb_cache_apc_driver_test extends phpbb_cache_common_test_case
self::markTestSkipped('APC extension is not loaded');
}
- $php_ini = new \phpbb\php\ini;
+ $php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
- if (!$php_ini->get_bool('apc.enabled'))
+ if (!$php_ini->getBool('apc.enabled'))
{
self::markTestSkipped('APC is not enabled. Make sure apc.enabled=1 in php.ini');
}
- if (PHP_SAPI == 'cli' && !$php_ini->get_bool('apc.enable_cli'))
+ if (PHP_SAPI == 'cli' && !$php_ini->getBool('apc.enable_cli'))
{
self::markTestSkipped('APC is not enabled for CLI. Set apc.enable_cli=1 in php.ini');
}
diff --git a/tests/cache/dummy_driver_test.php b/tests/cache/dummy_driver_test.php
new file mode 100644
index 0000000000..6cb6b73729
--- /dev/null
+++ b/tests/cache/dummy_driver_test.php
@@ -0,0 +1,77 @@
+<?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.
+*
+*/
+
+class phpbb_cache_dummy_driver_test extends phpbb_database_test_case
+{
+ protected $driver;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml');
+ }
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->driver = new \phpbb\cache\driver\dummy;
+ }
+
+ public function test_get_put()
+ {
+ $this->assertSame(false, $this->driver->get('key'));
+
+ $this->driver->put('key', 'value');
+
+ // null driver does not cache
+ $this->assertSame(false, $this->driver->get('key'));
+ }
+
+ public function test_purge()
+ {
+ $this->assertNull($this->driver->purge());
+ }
+
+ public function test_destroy()
+ {
+ $this->assertNull($this->driver->destroy('foo'));
+ }
+
+ public function test_cache_sql()
+ {
+ global $db, $cache, $phpbb_root_path, $phpEx;
+ $config = new phpbb\config\config(array());
+ $db = $this->new_dbal();
+ $cache = new \phpbb\cache\service($this->driver, $config, $db, $phpbb_root_path, $phpEx);
+
+ $sql = "SELECT * FROM phpbb_config
+ WHERE config_name = 'foo'";
+ $result = $db->sql_query($sql, 300);
+ $first_result = $db->sql_fetchrow($result);
+ $expected = array('config_name' => 'foo', 'config_value' => '23', 'is_dynamic' => 0);
+ $this->assertEquals($expected, $first_result);
+
+ $sql = 'DELETE FROM phpbb_config';
+ $result = $db->sql_query($sql);
+
+ // As null cache driver does not actually cache,
+ // this should return no results
+ $sql = "SELECT * FROM phpbb_config
+ WHERE config_name = 'foo'";
+ $result = $db->sql_query($sql, 300);
+
+ $this->assertSame(false, $db->sql_fetchrow($result));
+
+ $db->sql_close();
+ }
+}
diff --git a/tests/cache/null_driver_test.php b/tests/cache/null_driver_test.php
deleted file mode 100644
index b9f96732f5..0000000000
--- a/tests/cache/null_driver_test.php
+++ /dev/null
@@ -1,77 +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.
-*
-*/
-
-class phpbb_cache_null_driver_test extends phpbb_database_test_case
-{
- protected $driver;
-
- public function getDataSet()
- {
- return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml');
- }
-
- protected function setUp()
- {
- parent::setUp();
-
- $this->driver = new \phpbb\cache\driver\null;
- }
-
- public function test_get_put()
- {
- $this->assertSame(false, $this->driver->get('key'));
-
- $this->driver->put('key', 'value');
-
- // null driver does not cache
- $this->assertSame(false, $this->driver->get('key'));
- }
-
- public function test_purge()
- {
- $this->assertNull($this->driver->purge());
- }
-
- public function test_destroy()
- {
- $this->assertNull($this->driver->destroy('foo'));
- }
-
- public function test_cache_sql()
- {
- global $db, $cache, $phpbb_root_path, $phpEx;
- $config = new phpbb\config\config(array());
- $db = $this->new_dbal();
- $cache = new \phpbb\cache\service($this->driver, $config, $db, $phpbb_root_path, $phpEx);
-
- $sql = "SELECT * FROM phpbb_config
- WHERE config_name = 'foo'";
- $result = $db->sql_query($sql, 300);
- $first_result = $db->sql_fetchrow($result);
- $expected = array('config_name' => 'foo', 'config_value' => '23', 'is_dynamic' => 0);
- $this->assertEquals($expected, $first_result);
-
- $sql = 'DELETE FROM phpbb_config';
- $result = $db->sql_query($sql);
-
- // As null cache driver does not actually cache,
- // this should return no results
- $sql = "SELECT * FROM phpbb_config
- WHERE config_name = 'foo'";
- $result = $db->sql_query($sql, 300);
-
- $this->assertSame(false, $db->sql_fetchrow($result));
-
- $db->sql_close();
- }
-}
diff --git a/tests/captcha/qa_test.php b/tests/captcha/qa_test.php
index 1f2f9f3070..7ec4be69f5 100644
--- a/tests/captcha/qa_test.php
+++ b/tests/captcha/qa_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_captcha_qa_test extends \phpbb_database_test_case
{
protected $request;
@@ -27,14 +25,16 @@ class phpbb_captcha_qa_test extends \phpbb_database_test_case
public function setUp()
{
- global $db;
+ global $db, $request, $phpbb_container;
$db = $this->new_dbal();
parent::setUp();
- $this->request = new \phpbb_mock_request();
- request_var(false, false, false, false, $this->request);
+ $request = new \phpbb_mock_request();
+ $phpbb_container = new \phpbb_mock_container_builder();
+ $factory = new \phpbb\db\tools\factory();
+ $phpbb_container->set('dbal.tools', $factory->get($db));
$this->qa = new \phpbb\captcha\plugins\qa('phpbb_captcha_questions', 'phpbb_captcha_answers', 'phpbb_qa_confirm');
}
@@ -87,7 +87,8 @@ class phpbb_captcha_qa_test extends \phpbb_database_test_case
*/
public function test_acp_get_question_input($value, $expected)
{
- $this->request->overwrite('answers', $value);
+ global $request;
+ $request->overwrite('answers', $value);
$this->assertEquals($expected, $this->qa->acp_get_question_input());
}
diff --git a/tests/composer.json b/tests/composer.json
deleted file mode 100644
index 057e0115a5..0000000000
--- a/tests/composer.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "require-dev": {
- "facebook/webdriver": "~1.1"
- }
-}
diff --git a/tests/composer.lock b/tests/composer.lock
deleted file mode 100644
index f172de4669..0000000000
--- a/tests/composer.lock
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "_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",
- "This file is @generated automatically"
- ],
- "hash": "25ad22c35c19f2b0a2331640fb6b5577",
- "content-hash": "617c33144bd2877c3c9a78f167a871b6",
- "packages": [],
- "packages-dev": [
- {
- "name": "facebook/webdriver",
- "version": "1.1.2",
- "source": {
- "type": "git",
- "url": "https://github.com/facebook/php-webdriver.git",
- "reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/0b889d7de7461439f8a3bbcca46e0f696cb27986",
- "reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986",
- "shasum": ""
- },
- "require": {
- "ext-curl": "*",
- "php": ">=5.3.19"
- },
- "require-dev": {
- "phpunit/phpunit": "4.6.*"
- },
- "suggest": {
- "phpdocumentor/phpdocumentor": "2.*"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Facebook\\WebDriver\\": "lib/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "Apache-2.0"
- ],
- "description": "A PHP client for WebDriver",
- "homepage": "https://github.com/facebook/php-webdriver",
- "keywords": [
- "facebook",
- "php",
- "selenium",
- "webdriver"
- ],
- "time": "2016-06-04 00:02:34"
- }
- ],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": [],
- "platform-dev": []
-}
diff --git a/tests/compress/compress_test.php b/tests/compress/compress_test.php
index 56c406b206..c071a049a8 100644
--- a/tests/compress/compress_test.php
+++ b/tests/compress/compress_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compress.php';
diff --git a/tests/console/cache/purge_test.php b/tests/console/cache/purge_test.php
index 96988c1028..6c92660580 100644
--- a/tests/console/cache/purge_test.php
+++ b/tests/console/cache/purge_test.php
@@ -32,6 +32,8 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case
protected function setUp()
{
+ global $phpbb_root_path, $phpEx;
+
if (file_exists($this->cache_dir))
{
// cache directory possibly left after aborted
@@ -45,7 +47,10 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case
$this->db = $this->getMock('\phpbb\db\driver\driver_interface');
$this->config = new \phpbb\config\config(array('assets_version' => 1));
- $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime')
+ );
}
public function test_purge()
@@ -86,7 +91,7 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case
public function get_command_tester()
{
$application = new Application();
- $application->add(new purge($this->user, $this->cache, $this->db, $this->getMock('\phpbb\auth\auth'), new \phpbb\log\null(), $this->config));
+ $application->add(new purge($this->user, $this->cache, $this->db, $this->getMock('\phpbb\auth\auth'), new \phpbb\log\dummy(), $this->config));
$command = $application->find('cache:purge');
$this->command_name = $command->getName();
diff --git a/tests/console/config/config_test.php b/tests/console/config/config_test.php
index 7c098af004..076316217d 100644
--- a/tests/console/config/config_test.php
+++ b/tests/console/config/config_test.php
@@ -22,9 +22,14 @@ class phpbb_console_command_config_test extends phpbb_test_case
public function setUp()
{
+ global $phpbb_root_path, $phpEx;
+
$this->config = new \phpbb\config\config(array());
- $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime')
+ );
$this->user->method('lang')->will($this->returnArgument(0));
}
diff --git a/tests/console/cron/cron_list_test.php b/tests/console/cron/cron_list_test.php
index 22423304be..3bbe2078ba 100644
--- a/tests/console/cron/cron_list_test.php
+++ b/tests/console/cron/cron_list_test.php
@@ -32,7 +32,12 @@ class phpbb_console_command_cron_list_test extends phpbb_test_case
protected function setUp()
{
- $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$this->user->method('lang')->will($this->returnArgument(0));
}
diff --git a/tests/console/cron/run_test.php b/tests/console/cron/run_test.php
index f76e967484..b4a0203325 100644
--- a/tests/console/cron/run_test.php
+++ b/tests/console/cron/run_test.php
@@ -16,7 +16,6 @@ use Symfony\Component\Console\Tester\CommandTester;
use phpbb\console\command\cron\run;
require_once dirname(__FILE__) . '/tasks/simple.php';
-require_once dirname(__FILE__) . '/../../../phpBB/includes/functions.php';
class phpbb_console_command_cron_run_test extends phpbb_database_test_case
{
@@ -39,10 +38,12 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case
$db = $this->db = $this->new_dbal();
$config = $this->config = new \phpbb\config\config(array('cron_lock' => '0'));
- set_config(null, null, null, $this->config);
$this->lock = new \phpbb\lock\db('cron_lock', $this->config, $this->db);
- $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$this->user->method('lang')->will($this->returnArgument(0));
$this->task = new phpbb_cron_task_simple();
@@ -76,6 +77,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case
$this->assertSame(false, $this->lock->owns_lock());
}
+ /**
+ * @expectedException \phpbb\exception\runtime_exception
+ * @expectedExceptionMessage CRON_LOCK_ERROR
+ */
public function test_error_lock()
{
$this->lock->acquire();
@@ -124,6 +129,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case
$this->assertSame(false, $this->lock->owns_lock());
}
+ /**
+ * @expectedException \phpbb\exception\runtime_exception
+ * @expectedExceptionMessage CRON_NO_SUCH_TASK
+ */
public function test_arg_invalid()
{
$command_tester = $this->get_command_tester();
diff --git a/tests/console/fixtures/png.png b/tests/console/fixtures/png.png
new file mode 100644
index 0000000000..c143a26a06
--- /dev/null
+++ b/tests/console/fixtures/png.png
Binary files differ
diff --git a/tests/console/fixtures/thumbnail.xml b/tests/console/fixtures/thumbnail.xml
new file mode 100644
index 0000000000..8037523633
--- /dev/null
+++ b/tests/console/fixtures/thumbnail.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_attachments">
+ <column>attach_id</column>
+ <column>physical_filename</column>
+ <column>real_filename</column>
+ <column>thumbnail</column>
+ <column>extension</column>
+ <column>mimetype</column>
+ <column>attach_comment</column>
+
+ <row>
+ <value>1</value>
+ <value>test_png_1</value>
+ <value>real_test.png</value>
+ <value>0</value>
+ <value>png</value>
+ <value>image/png</value>
+ <value></value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>test_png_2</value>
+ <value>real_test.png</value>
+ <value>1</value>
+ <value>png</value>
+ <value>image/png</value>
+ <value></value>
+ </row>
+ <row>
+ <value>10</value>
+ <value>test_txt</value>
+ <value>real_test.txt</value>
+ <value>0</value>
+ <value>txt</value>
+ <value>text/plain</value>
+ <value></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/console/fixtures/txt.txt b/tests/console/fixtures/txt.txt
new file mode 100644
index 0000000000..a78c858f5c
--- /dev/null
+++ b/tests/console/fixtures/txt.txt
@@ -0,0 +1,2 @@
+<HTML>mime trigger</HTML>
+The HTML tags should remain uppercase so that case-insensitivity can be checked.
diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php
new file mode 100644
index 0000000000..439e3623fa
--- /dev/null
+++ b/tests/console/thumbnail_test.php
@@ -0,0 +1,122 @@
+<?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.
+*
+*/
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use phpbb\console\command\thumbnail\generate;
+use phpbb\console\command\thumbnail\delete;
+use phpbb\console\command\thumbnail\recreate;
+
+class phpbb_console_command_thumbnail_test extends phpbb_database_test_case
+{
+ protected $db;
+ protected $config;
+ protected $cache;
+ protected $user;
+ protected $phpEx;
+ protected $phpbb_root_path;
+ protected $application;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/thumbnail.xml');
+ }
+
+ public function setUp()
+ {
+ global $config, $phpbb_root_path, $phpEx, $phpbb_filesystem;
+
+ if (!@extension_loaded('gd'))
+ {
+ $this->markTestSkipped('Thumbnail tests require gd extension.');
+ }
+
+ parent::setUp();
+
+ $config = $this->config = new \phpbb\config\config(array(
+ 'img_min_thumb_filesize' => 2,
+ 'img_max_thumb_width' => 2,
+ 'img_imagick' => '',
+ ));
+
+ $this->db = $this->db = $this->new_dbal();
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime')
+ );
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->phpEx = $phpEx;
+
+ $this->cache = $this->getMock('\phpbb\cache\service', array(), array(new phpbb_mock_cache(), $this->config, $this->db, $this->phpbb_root_path, $this->phpEx));
+ $this->cache->expects(self::any())->method('obtain_attach_extensions')->will(self::returnValue(array(
+ 'png' => array('display_cat' => ATTACHMENT_CATEGORY_IMAGE),
+ 'txt' => array('display_cat' => ATTACHMENT_CATEGORY_NONE),
+ )));
+
+ $this->application = new Application();
+ $this->application->add(new generate($this->user, $this->db, $this->cache, $this->phpbb_root_path, $this->phpEx));
+ $this->application->add(new delete($this->user, $this->db, $this->phpbb_root_path));
+ $this->application->add(new recreate($this->user));
+
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
+
+ copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_1');
+ copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_2');
+ copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/thumb_test_png_2');
+ copy(dirname(__FILE__) . '/fixtures/txt.txt', $this->phpbb_root_path . 'files/test_txt');
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+
+ unlink($this->phpbb_root_path . 'files/test_png_1');
+ unlink($this->phpbb_root_path . 'files/test_png_2');
+ unlink($this->phpbb_root_path . 'files/test_txt');
+ unlink($this->phpbb_root_path . 'files/thumb_test_png_1');
+ unlink($this->phpbb_root_path . 'files/thumb_test_png_2');
+ }
+
+ public function test_thumbnails()
+ {
+ $command_tester = $this->get_command_tester('thumbnail:generate');
+ $exit_status = $command_tester->execute(array('command' => 'thumbnail:generate'));
+
+ self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1'));
+ self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2'));
+ self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt'));
+ self::assertSame(0, $exit_status);
+
+ $command_tester = $this->get_command_tester('thumbnail:delete');
+ $exit_status = $command_tester->execute(array('command' => 'thumbnail:delete'));
+
+ self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1'));
+ self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2'));
+ self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt'));
+ self::assertSame(0, $exit_status);
+
+ $command_tester = $this->get_command_tester('thumbnail:recreate');
+ $exit_status = $command_tester->execute(array('command' => 'thumbnail:recreate'));
+
+ self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1'));
+ self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2'));
+ self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt'));
+ self::assertSame(0, $exit_status);
+ }
+
+ public function get_command_tester($command_name)
+ {
+ $command = $this->application->find($command_name);
+ return new CommandTester($command);
+ }
+}
diff --git a/tests/console/user/activate_test.php b/tests/console/user/activate_test.php
new file mode 100644
index 0000000000..1588a76e47
--- /dev/null
+++ b/tests/console/user/activate_test.php
@@ -0,0 +1,86 @@
+<?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.
+*
+*/
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use phpbb\console\command\user\activate;
+
+require_once dirname(__FILE__) . '/base.php';
+
+class phpbb_console_user_activate_test extends phpbb_console_user_base
+{
+ protected $notifications;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->notifications = $this->getMockBuilder('\phpbb\notification\manager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function get_command_tester()
+ {
+ $application = new Application();
+ $application->add(new activate(
+ $this->user,
+ $this->db,
+ $this->config,
+ $this->language,
+ $this->log,
+ $this->notifications,
+ $this->user_loader,
+ $this->phpbb_root_path,
+ $this->php_ext
+ ));
+
+ $command = $application->find('user:activate');
+ $this->command_name = $command->getName();
+
+ return new CommandTester($command);
+ }
+
+ public function activate_test_data()
+ {
+ return array(
+ // Test an inactive user
+ array('Test', false, 'USER_ADMIN_ACTIVATED'),
+ array('Test', true, 'CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE'),
+
+ // Test an active user
+ array('Test 2', false, 'CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE'),
+ array('Test 2', true, 'USER_ADMIN_DEACTIVED'),
+
+ // Test a non existent user
+ array('Foo', false, 'NO_USER'),
+ array('Foo', true, 'NO_USER'),
+ );
+ }
+
+ /**
+ * @dataProvider activate_test_data
+ */
+ public function test_activate($username, $deactivate, $expected)
+ {
+ $command_tester = $this->get_command_tester();
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ 'username' => $username,
+ '--deactivate' => $deactivate,
+ ));
+
+ $this->assertContains($expected, $command_tester->getDisplay());
+ }
+}
diff --git a/tests/console/user/add_test.php b/tests/console/user/add_test.php
new file mode 100644
index 0000000000..8641bf87b6
--- /dev/null
+++ b/tests/console/user/add_test.php
@@ -0,0 +1,92 @@
+<?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.
+*
+*/
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use phpbb\console\command\user\add;
+
+require_once dirname(__FILE__) . '/base.php';
+
+class phpbb_console_user_add_test extends phpbb_console_user_base
+{
+ public function get_command_tester()
+ {
+ $application = new Application();
+ $application->add(new add(
+ $this->user,
+ $this->db,
+ $this->config,
+ $this->language,
+ $this->passwords_manager,
+ $this->phpbb_root_path,
+ $this->php_ext
+ ));
+
+ $command = $application->find('user:add');
+ $this->command_name = $command->getName();
+ $this->question = $command->getHelper('question');
+ return new CommandTester($command);
+ }
+
+ public function test_add_no_dialog()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $this->assertEquals(2, $this->get_user_id('Admin'));
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ '--username' => 'foo',
+ '--password' => 'bar',
+ '--email' => 'foo@test.com'
+ ));
+
+ $this->assertNotEquals(null, $this->get_user_id('foo'));
+ $this->assertContains('CLI_USER_ADD_SUCCESS', $command_tester->getDisplay());
+ }
+
+ public function test_add_dialog()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $this->assertEquals(2, $this->get_user_id('Admin'));
+
+ $this->question->setInputStream($this->getInputStream("bar\npassword\npassword\nbar@test.com\n"));
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ ));
+
+ $this->assertNotEquals(null, $this->get_user_id('bar'));
+ $this->assertContains('CLI_USER_ADD_SUCCESS', $command_tester->getDisplay());
+
+ }
+
+ public function test_add_no_dialog_invalid()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $this->assertEquals(3, $this->get_user_id('Test'));
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ '--username' => 'Test',
+ '--password' => '1',
+ '--email' => 'foo'
+ ));
+
+ $this->assertContains('USERNAME_TAKEN', $command_tester->getDisplay());
+ $this->assertContains('TOO_SHORT', $command_tester->getDisplay());
+ $this->assertContains('EMAIL_INVALID', $command_tester->getDisplay());
+ }
+}
diff --git a/tests/console/user/base.php b/tests/console/user/base.php
new file mode 100644
index 0000000000..b84c0bb267
--- /dev/null
+++ b/tests/console/user/base.php
@@ -0,0 +1,121 @@
+<?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.
+*
+*/
+
+abstract class phpbb_console_user_base extends phpbb_database_test_case
+{
+ protected $db;
+ protected $config;
+ protected $user;
+ protected $language;
+ protected $log;
+ protected $passwords_manager;
+ protected $command_name;
+ protected $question;
+ protected $user_loader;
+ protected $phpbb_root_path;
+ protected $php_ext;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml');
+ }
+
+ public function setUp()
+ {
+ global $auth, $db, $cache, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path, $phpEx;
+
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $phpbb_container = new phpbb_mock_container_builder();
+ $phpbb_container->set('cache.driver', new phpbb_mock_cache());
+ $phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
+
+ $auth = $this->getMock('\phpbb\auth\auth');
+
+ $cache = $phpbb_container->get('cache.driver');
+
+ $config = $this->config = new \phpbb\config\config(array(
+ 'board_timezone' => 'UTC',
+ 'default_lang' => 'en',
+ 'email_enable' => false,
+ 'min_name_chars' => 3,
+ 'max_name_chars' => 10,
+ 'min_pass_chars' => 3,
+ 'max_pass_chars' => 10,
+ 'pass_complex' => 'PASS_TYPE_ANY',
+ ));
+
+ $db = $this->db = $this->new_dbal();
+
+ $this->language = $this->getMockBuilder('\phpbb\language\language')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->language->expects($this->any())
+ ->method('lang')
+ ->will($this->returnArgument(0));
+ $user = $this->user = $this->getMock('\phpbb\user', array(), array(
+ $this->language,
+ '\phpbb\datetime'
+ ));
+
+ $this->user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
+
+ $driver_helper = new \phpbb\passwords\driver\helper($this->config);
+ $passwords_drivers = array(
+ 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($this->config, $driver_helper),
+ 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($this->config, $driver_helper),
+ 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($this->config, $driver_helper),
+ 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($this->config, $driver_helper),
+ );
+
+ $passwords_helper = new \phpbb\passwords\helper;
+ $this->passwords_manager = new \phpbb\passwords\manager($this->config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers));
+
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $phpEx;
+
+ $this->log = $this->getMockBuilder('\phpbb\log\log')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $phpbb_container->set('auth.provider.db', new phpbb_mock_auth_provider());
+ $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config);
+ $provider_collection->add('auth.provider.db');
+ $phpbb_container->set(
+ 'auth.provider_collection',
+ $provider_collection
+ );
+
+ parent::setUp();
+ }
+
+ public function get_user_id($username)
+ {
+ $sql = 'SELECT user_id
+ FROM ' . USERS_TABLE . '
+ WHERE ' . 'username = ' . "'" . $username . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ return $row['user_id'];
+ }
+
+ public function getInputStream($input)
+ {
+ $stream = fopen('php://memory', 'r+', false);
+ fputs($stream, $input);
+ rewind($stream);
+
+ return $stream;
+ }
+}
diff --git a/tests/console/user/delete_test.php b/tests/console/user/delete_test.php
new file mode 100644
index 0000000000..88f91afab1
--- /dev/null
+++ b/tests/console/user/delete_test.php
@@ -0,0 +1,93 @@
+<?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.
+*
+*/
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use phpbb\console\command\user\delete;
+
+require_once dirname(__FILE__) . '/base.php';
+
+class phpbb_console_user_delete_test extends phpbb_console_user_base
+{
+ public function get_command_tester()
+ {
+ $application = new Application();
+ $application->add(new delete(
+ $this->user,
+ $this->db,
+ $this->language,
+ $this->log,
+ $this->user_loader,
+ $this->phpbb_root_path,
+ $this->php_ext
+ ));
+
+ $command = $application->find('user:delete');
+ $this->command_name = $command->getName();
+ $this->question = $command->getHelper('question');
+
+ return new CommandTester($command);
+ }
+
+ public function test_delete()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $this->assertEquals(3, $this->get_user_id('Test'));
+
+ $this->question->setInputStream($this->getInputStream("yes\n"));
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ 'username' => 'Test',
+ '--delete-posts' => false,
+ ));
+
+ $this->assertNull($this->get_user_id('Test'));
+ $this->assertContains('USER_DELETED', $command_tester->getDisplay());
+ }
+
+ public function test_delete_non_user()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $this->assertNull($this->get_user_id('Foo'));
+
+ $this->question->setInputStream($this->getInputStream("yes\n"));
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ 'username' => 'Foo',
+ '--delete-posts' => false,
+ ));
+
+ $this->assertContains('NO_USER', $command_tester->getDisplay());
+ }
+
+ public function test_delete_cancel()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $this->assertEquals(3, $this->get_user_id('Test'));
+
+ $this->question->setInputStream($this->getInputStream("no\n"));
+
+ $command_tester->execute(array(
+ 'command' => $this->command_name,
+ 'username' => 'Test',
+ '--delete-posts' => false,
+ ));
+
+ $this->assertNotNull($this->get_user_id('Test'));
+ }
+}
diff --git a/tests/console/user/fixtures/config.xml b/tests/console/user/fixtures/config.xml
new file mode 100644
index 0000000000..a988ba463f
--- /dev/null
+++ b/tests/console/user/fixtures/config.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_users">
+ <column>user_id</column>
+ <column>user_permissions</column>
+ <column>username</column>
+ <column>username_clean</column>
+ <column>user_sig</column>
+ <column>user_type</column>
+ <row>
+ <value>1</value>
+ <value></value>
+ <value>Guest</value>
+ <value>guest</value>
+ <value></value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value></value>
+ <value>Admin</value>
+ <value>admin</value>
+ <value></value>
+ <value>3</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value></value>
+ <value>Test</value>
+ <value>test</value>
+ <value></value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value></value>
+ <value>Test 2</value>
+ <value>test 2</value>
+ <value></value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value></value>
+ <value>Test Unclean</value>
+ <value>Test Unclean</value>
+ <value></value>
+ <value>0</value>
+ </row>
+ </table>
+ <table name="phpbb_groups">
+ <column>group_id</column>
+ <column>group_name</column>
+ <column>group_type</column>
+ <column>group_desc</column>
+ <row>
+ <value>1</value>
+ <value>REGISTERED</value>
+ <value>3</value>
+ <value>foobar</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/console/user/reclean_test.php b/tests/console/user/reclean_test.php
new file mode 100644
index 0000000000..1bf0b8ef5a
--- /dev/null
+++ b/tests/console/user/reclean_test.php
@@ -0,0 +1,49 @@
+<?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.
+*
+*/
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use phpbb\console\command\user\reclean;
+
+require_once dirname(__FILE__) . '/base.php';
+
+class phpbb_console_user_reclean_test extends phpbb_console_user_base
+{
+ public function get_command_tester()
+ {
+ $application = new Application();
+ $application->add(new reclean(
+ $this->user,
+ $this->db,
+ $this->language
+ ));
+
+ $command = $application->find('user:reclean');
+ $this->command_name = $command->getName();
+
+ return new CommandTester($command);
+ }
+
+ public function test_reclean()
+ {
+ $command_tester = $this->get_command_tester();
+
+ $exit_status = $command_tester->execute(array('command' => $this->command_name));
+ $this->assertSame(0, $exit_status);
+
+ $result = $this->db->sql_query('SELECT user_id FROM ' . USERS_TABLE . " WHERE username_clean = 'test unclean'");
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ $this->assertNotNull($row['user_id']);
+ }
+}
diff --git a/tests/content_visibility/delete_post_test.php b/tests/content_visibility/delete_post_test.php
index 6ad6351a0c..4ea95b0a96 100644
--- a/tests/content_visibility/delete_post_test.php
+++ b/tests/content_visibility/delete_post_test.php
@@ -11,11 +11,8 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
require_once dirname(__FILE__) . '/../mock/search.php';
class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case
@@ -292,12 +289,14 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case
{
global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
- $config['search_type'] = 'phpbb_mock_search';
+ $config = new \phpbb\config\config(array(
+ 'num_posts' => 3,
+ 'num_topics' => 1,
+ 'search_type' => 'phpbb_mock_search',
+ ));
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $phpbb_config = new \phpbb\config\config(array('num_posts' => 3, 'num_topics' => 1));
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- set_config_count(null, null, null, $phpbb_config);
// Create auth mock
$auth = $this->getMock('\phpbb\auth\auth');
@@ -307,13 +306,18 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case
->will($this->returnValueMap(array(
array('m_approve', 1, true),
)));
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $attachment_delete = new \phpbb\attachment\delete($config, $db, new \phpbb_mock_event_dispatcher(), new \phpbb\filesystem\filesystem(), new \phpbb\attachment\resync($db), $phpbb_root_path);
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
- $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $phpbb_config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE));
+ $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE));
+ // Works as a workaround for tests
+ $phpbb_container->set('attachment.manager', $attachment_delete);
delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $reason);
diff --git a/tests/content_visibility/get_forums_visibility_sql_test.php b/tests/content_visibility/get_forums_visibility_sql_test.php
index 28e463ecb5..6c5066119e 100644
--- a/tests/content_visibility/get_forums_visibility_sql_test.php
+++ b/tests/content_visibility/get_forums_visibility_sql_test.php
@@ -134,7 +134,9 @@ class phpbb_content_visibility_get_forums_visibility_sql_test extends phpbb_data
->method('acl_getf')
->with($this->stringContains('_'), $this->anything())
->will($this->returnValueMap($permissions));
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$config = new phpbb\config\config(array());
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE);
diff --git a/tests/content_visibility/get_global_visibility_sql_test.php b/tests/content_visibility/get_global_visibility_sql_test.php
index 586bae8668..9ae4182673 100644
--- a/tests/content_visibility/get_global_visibility_sql_test.php
+++ b/tests/content_visibility/get_global_visibility_sql_test.php
@@ -134,7 +134,9 @@ class phpbb_content_visibility_get_global_visibility_sql_test extends phpbb_data
->method('acl_getf')
->with($this->stringContains('_'), $this->anything())
->will($this->returnValueMap($permissions));
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$config = new phpbb\config\config(array());
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE);
diff --git a/tests/content_visibility/get_visibility_sql_test.php b/tests/content_visibility/get_visibility_sql_test.php
index 9ae2d2fdc4..aaaf64330e 100644
--- a/tests/content_visibility/get_visibility_sql_test.php
+++ b/tests/content_visibility/get_visibility_sql_test.php
@@ -81,7 +81,9 @@ class phpbb_content_visibility_get_visibility_sql_test extends phpbb_database_te
->method('acl_get')
->with($this->stringContains('_'), $this->anything())
->will($this->returnValueMap($permissions));
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$config = new phpbb\config\config(array());
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE);
diff --git a/tests/content_visibility/set_post_visibility_test.php b/tests/content_visibility/set_post_visibility_test.php
index 36ebf58374..e33a1f30d5 100644
--- a/tests/content_visibility/set_post_visibility_test.php
+++ b/tests/content_visibility/set_post_visibility_test.php
@@ -11,11 +11,8 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_test_case
{
@@ -124,7 +121,9 @@ class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_t
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
$auth = $this->getMock('\phpbb\auth\auth');
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$config = new phpbb\config\config(array());
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE);
@@ -175,7 +174,9 @@ class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_t
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
$auth = $this->getMock('\phpbb\auth\auth');
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$config = new phpbb\config\config(array());
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE);
diff --git a/tests/content_visibility/set_topic_visibility_test.php b/tests/content_visibility/set_topic_visibility_test.php
index 6c34f42167..78431396c3 100644
--- a/tests/content_visibility/set_topic_visibility_test.php
+++ b/tests/content_visibility/set_topic_visibility_test.php
@@ -11,11 +11,8 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
class phpbb_content_visibility_set_topic_visibility_test extends phpbb_database_test_case
{
@@ -88,7 +85,9 @@ class phpbb_content_visibility_set_topic_visibility_test extends phpbb_database_
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
$auth = $this->getMock('\phpbb\auth\auth');
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$config = new phpbb\config\config(array());
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE);
diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php
index ea77a289c9..367c15a667 100644
--- a/tests/controller/common_helper_route.php
+++ b/tests/controller/common_helper_route.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
abstract class phpbb_controller_common_helper_route extends phpbb_test_case
@@ -27,6 +25,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
private $provider;
private $filesystem;
private $phpbb_path_helper;
+ private $helper;
+ private $router;
+ private $routing_helper;
public function setUp()
{
@@ -44,10 +45,6 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
);
$this->generate_route_objects();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher;
- $this->user = new \phpbb\user('\phpbb\datetime');
-
- $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0'));
- $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $this->user, new \phpbb\template\context());
}
protected function get_phpbb_root_path()
@@ -91,7 +88,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
$this->symfony_request = new \phpbb\symfony_request(
$this->request
);
- $this->filesystem = new \phpbb\filesystem();
+ $this->filesystem = new \phpbb\filesystem\filesystem();
$this->phpbb_path_helper = new \phpbb\path_helper(
$this->symfony_request,
$this->filesystem,
@@ -100,15 +97,50 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
$phpEx
);
- $finder = new \phpbb\finder(
- new \phpbb\filesystem(),
+ $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0'));
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $this->user = new \phpbb\user($lang, '\phpbb\datetime');;
+
+ $container = new phpbb_mock_container_builder();
+ $container->setParameter('core.environment', PHPBB_ENVIRONMENT);
+ $cache_path = $phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader($this->filesystem, '');
+ $twig = new \phpbb\template\twig\environment(
+ $this->config,
+ $this->filesystem,
+ $this->phpbb_path_helper,
+ $cache_path,
+ null,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
+ $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)));
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
+
+ $this->extension_manager = new phpbb_mock_extension_manager(
dirname(__FILE__) . '/',
- new phpbb_mock_cache()
+ array(
+ 'vendor2/foo' => array(
+ 'ext_name' => 'vendor2/foo',
+ 'ext_active' => '1',
+ 'ext_path' => 'ext/vendor2/foo/',
+ ),
+ )
+ );
+
+ $loader = new \Symfony\Component\Routing\Loader\YamlFileLoader(
+ new \phpbb\routing\file_locator($this->filesystem, dirname(__FILE__) . '/')
);
- $finder->set_extensions(array_keys($this->extension_manager->all_enabled()));
- $this->provider = new \phpbb\controller\provider();
- $this->provider->find_routing_files($finder);
- $this->provider->find(dirname(__FILE__) . '/');
+ $resources_locator = new \phpbb\routing\resources_locator\default_resources_locator(dirname(__FILE__) . '/', PHPBB_ENVIRONMENT, $this->extension_manager);
+ $this->router = new phpbb_mock_router($container, $resources_locator, $loader, dirname(__FILE__) . '/', 'php');
+
// Set correct current phpBB root path
$this->root_path = $this->get_phpbb_root_path();
}
@@ -140,6 +172,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, '/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, '/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, '/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, '/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -148,8 +183,10 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
*/
public function test_helper_url_no_rewrite($route, $params, $is_amp, $session_id, $expected, $description)
{
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id), $description);
+ $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0'));
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description);
}
public function helper_url_data_with_rewrite()
@@ -179,6 +216,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, '/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, '/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, '/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, '/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -188,8 +228,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
public function test_helper_url_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)
{
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id), $description);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description);
}
public function helper_url_data_absolute()
@@ -219,6 +260,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -228,8 +272,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
public function test_helper_url_absolute($route, $params, $is_amp, $session_id, $expected, $description)
{
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description);
}
public function helper_url_data_relative_path()
@@ -259,6 +304,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, 'app.php/foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, 'app.php/foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, 'app.php/foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -268,8 +316,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
public function test_helper_url_relative_path($route, $params, $is_amp, $session_id, $expected, $description)
{
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description);
}
public function helper_url_data_network()
@@ -299,6 +348,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -308,10 +360,11 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
public function test_helper_url_network($route, $params, $is_amp, $session_id, $expected, $description)
{
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description);
}
-//TODO
+
public function helper_url_data_absolute_with_rewrite()
{
return array(
@@ -339,6 +392,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -348,8 +404,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
public function test_helper_url_absolute_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)
{
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description);
}
public function helper_url_data_relative_path_with_rewrite()
@@ -388,8 +445,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
public function test_helper_url_relative_path_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)
{
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description);
}
public function helper_url_data_network_with_rewrite()
@@ -419,6 +477,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array('controller2', array(), true, false, '//localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),
array('controller2', array(), false, false, '//localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),
array('controller3', array('p' => 3), true, false, '//localhost/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'),
+
+ // Resolves DI parameters
+ array('controller4', array(), true, false, '//localhost/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'),
);
}
@@ -427,9 +488,10 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
*/
public function test_helper_url_network_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)
{
- $this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1'));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description);
+ $this->config = new \phpbb\config\config(['enable_mod_rewrite' => '1']);
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description);
}
public function helper_url_data_force_server_vars()
@@ -442,8 +504,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
array(false, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::ABSOLUTE_PATH, '/my/board/app.php/foo'),
array(true, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::ABSOLUTE_PATH, '/my/board/foo'),
array(false, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::RELATIVE_PATH, 'app.php/foo'),
- array(true, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::RELATIVE_PATH, 'foo'),
- );
+ array(true, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::RELATIVE_PATH, 'foo'), );
}
/**
@@ -460,8 +521,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case
'server_protocol' => $server_protocol,
));
- $helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/');
- static::assertEquals($expected, $helper->route('controller1', array(), false, false, $type));
-
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper);
+ static::assertEquals($expected, $this->helper->route('controller1', array(), false, false, $type));
}
}
diff --git a/tests/controller/config/routing.yml b/tests/controller/config/test/routing/environment.yml
index 1e7df02684..1e7df02684 100644
--- a/tests/controller/config/routing.yml
+++ b/tests/controller/config/test/routing/environment.yml
diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php
index 62feee3fed..d921d0eade 100644
--- a/tests/controller/controller_test.php
+++ b/tests/controller/controller_test.php
@@ -11,7 +11,8 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+include_once(__DIR__ . '/ext/vendor2/foo/controller.php');
+include_once(__DIR__.'/phpbb/controller/foo.php');
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Config\FileLocator;
@@ -30,14 +31,25 @@ class phpbb_controller_controller_test extends phpbb_test_case
'ext_active' => '1',
'ext_path' => 'ext/vendor2/foo/',
),
+ 'vendor2/bar' => array(
+ 'ext_name' => 'vendor2/bar',
+ 'ext_active' => '1',
+ 'ext_path' => 'ext/vendor2/bar/',
+ ),
));
}
- public function test_provider()
+ public function test_router_default_loader()
{
- $provider = new \phpbb\controller\provider();
- $provider->find_routing_files($this->extension_manager->get_finder());
- $routes = $provider->find(__DIR__)->get_routes();
+ $container = new phpbb_mock_container_builder();
+ $container->setParameter('core.environment', PHPBB_ENVIRONMENT);
+
+ $loader = new \Symfony\Component\Routing\Loader\YamlFileLoader(
+ new \phpbb\routing\file_locator(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/')
+ );
+ $resources_locator = new \phpbb\routing\resources_locator\default_resources_locator(dirname(__FILE__) . '/', PHPBB_ENVIRONMENT, $this->extension_manager);
+ $router = new phpbb_mock_router($container, $resources_locator, $loader, dirname(__FILE__) . '/', 'php');
+ $routes = $router->get_routes();
// This will need to be updated if any new routes are defined
$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('core_controller'));
@@ -49,10 +61,13 @@ class phpbb_controller_controller_test extends phpbb_test_case
$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('controller2'));
$this->assertEquals('/foo/bar', $routes->get('controller2')->getPath());
+ $this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('controller3'));
+ $this->assertEquals('/bar', $routes->get('controller3')->getPath());
+
$this->assertNull($routes->get('controller_noroute'));
}
- public function test_controller_resolver()
+ protected function get_foo_container()
{
$container = new ContainerBuilder();
// YamlFileLoader only uses one path at a time, so we need to loop
@@ -63,26 +78,59 @@ class phpbb_controller_controller_test extends phpbb_test_case
$loader->load('services.yml');
}
- // Autoloading classes within the tests folder does not work
- // so I'll include them manually.
- if (!class_exists('vendor2\\foo\\controller'))
- {
- include(__DIR__ . '/ext/vendor2/foo/controller.php');
- }
- if (!class_exists('phpbb\\controller\\foo'))
- {
- include(__DIR__.'/phpbb/controller/foo.php');
- }
+ return $container;
+ }
- $resolver = new \phpbb\controller\resolver(new \phpbb\user('\phpbb\datetime'), $container, dirname(__FILE__) . '/');
+ public function test_controller_resolver()
+ {
+ $container = $this->get_foo_container();
+
+ $resolver = new \phpbb\controller\resolver($container, dirname(__FILE__) . '/');
$symfony_request = new Request();
$symfony_request->attributes->set('_controller', 'foo.controller:handle');
$this->assertEquals($resolver->getController($symfony_request), array(new foo\controller, 'handle'));
+ $this->assertEquals(array('foo'), $resolver->getArguments($symfony_request, $resolver->getController($symfony_request)));
$symfony_request = new Request();
$symfony_request->attributes->set('_controller', 'core_foo.controller:bar');
$this->assertEquals($resolver->getController($symfony_request), array(new phpbb\controller\foo, 'bar'));
+ $this->assertEquals(array(), $resolver->getArguments($symfony_request, $resolver->getController($symfony_request)));
+ }
+
+ public function data_get_arguments()
+ {
+ return array(
+ array(array(new foo\controller(), 'handle2'), array('foo', 0)),
+ array(array(new foo\controller(), 'handle_fail'), array('default'), array('no_default' => 'default')),
+ array(new foo\controller(), array(), array()),
+ array(array(new foo\controller(), 'handle_fail'), array(), array(), '\phpbb\controller\exception', 'CONTROLLER_ARGUMENT_VALUE_MISSING'),
+ array('', array(), array(), '\ReflectionException', 'Function () does not exist'),
+ array(new phpbb\controller\foo, array(), array(), '\ReflectionException', 'Method __invoke does not exist'),
+ );
+ }
+
+ /**
+ * @dataProvider data_get_arguments
+ */
+ public function test_get_arguments($input, $expected, $set_attributes = array(), $exception = '', $exception_message = '')
+ {
+ $container = $this->get_foo_container();
+
+ $resolver = new \phpbb\controller\resolver($container, dirname(__FILE__) . '/');
+ $symfony_request = new Request();
+
+ foreach ($set_attributes as $name => $value)
+ {
+ $symfony_request->attributes->set($name, $value);
+ }
+
+ if (!empty($exception))
+ {
+ $this->setExpectedException($exception, $exception_message);
+ }
+
+ $this->assertEquals($expected, $resolver->getArguments($symfony_request, $input));
}
}
diff --git a/tests/controller/ext/vendor2/bar/config/services.yml b/tests/controller/ext/vendor2/bar/config/services.yml
new file mode 100644
index 0000000000..05a8a1994d
--- /dev/null
+++ b/tests/controller/ext/vendor2/bar/config/services.yml
@@ -0,0 +1,3 @@
+services:
+ bar.controller:
+ class: bar\controller
diff --git a/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml b/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml
new file mode 100644
index 0000000000..5696ecb180
--- /dev/null
+++ b/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml
@@ -0,0 +1,3 @@
+controller3:
+ path: /bar
+ defaults: { _controller: bar.controller:handle }
diff --git a/tests/controller/ext/vendor2/bar/controller.php b/tests/controller/ext/vendor2/bar/controller.php
new file mode 100644
index 0000000000..ad35f5a051
--- /dev/null
+++ b/tests/controller/ext/vendor2/bar/controller.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace bar;
+
+use Symfony\Component\HttpFoundation\Response;
+
+class controller
+{
+ /**
+ * Handle method
+ *
+ * @return null
+ */
+ public function handle()
+ {
+ return new Response('Test', 200);
+ }
+}
diff --git a/tests/controller/ext/vendor2/foo/config/routing.yml b/tests/controller/ext/vendor2/foo/config/routing.yml
index e3e8ee5f98..7d4ac7be93 100644
--- a/tests/controller/ext/vendor2/foo/config/routing.yml
+++ b/tests/controller/ext/vendor2/foo/config/routing.yml
@@ -5,3 +5,7 @@ controller1:
include_controller2:
resource: "routing_2.yml"
prefix: /foo
+
+controller4:
+ path: /foo/%core.environment%
+ defaults: { _controller: foo.controller:handle }
diff --git a/tests/controller/ext/vendor2/foo/controller.php b/tests/controller/ext/vendor2/foo/controller.php
index ce2233b3c9..cabcae042b 100644
--- a/tests/controller/ext/vendor2/foo/controller.php
+++ b/tests/controller/ext/vendor2/foo/controller.php
@@ -11,8 +11,23 @@ class controller
*
* @return null
*/
- public function handle()
+ public function handle($optional = 'foo')
{
return new Response('Test', 200);
}
+
+ public function handle2($foo = 'foo', $very_optional = 0)
+ {
+ return new Response('Test2', 200);
+ }
+
+ public function handle_fail($no_default)
+ {
+ return new Response('Test_fail', 200);
+ }
+
+ public function __invoke()
+ {
+ $this->handle();
+ }
}
diff --git a/tests/controller/helper_route_adm_subdir_test.php b/tests/controller/helper_route_adm_subdir_test.php
index f27ac81b04..a1bf1b8805 100644
--- a/tests/controller/helper_route_adm_subdir_test.php
+++ b/tests/controller/helper_route_adm_subdir_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/common_helper_route.php';
class phpbb_controller_helper_route_adm_subdir_test extends phpbb_controller_common_helper_route
diff --git a/tests/controller/helper_route_adm_test.php b/tests/controller/helper_route_adm_test.php
index 86dc36ef1f..6ee394eaaa 100644
--- a/tests/controller/helper_route_adm_test.php
+++ b/tests/controller/helper_route_adm_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/common_helper_route.php';
class phpbb_controller_helper_route_adm_test extends phpbb_controller_common_helper_route
diff --git a/tests/controller/helper_route_root_test.php b/tests/controller/helper_route_root_test.php
index 63a2f2f8f7..12462e076d 100644
--- a/tests/controller/helper_route_root_test.php
+++ b/tests/controller/helper_route_root_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/common_helper_route.php';
class phpbb_controller_helper_route_test extends phpbb_controller_common_helper_route
diff --git a/tests/controller/helper_route_slash_test.php b/tests/controller/helper_route_slash_test.php
index 3db5ec19e5..c781a6943e 100644
--- a/tests/controller/helper_route_slash_test.php
+++ b/tests/controller/helper_route_slash_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/common_helper_route.php';
class phpbb_controller_helper_route_slash_test extends phpbb_controller_common_helper_route
diff --git a/tests/controller/helper_route_unclean_path_test.php b/tests/controller/helper_route_unclean_path_test.php
index 9d8b62bc1c..80f1a99fff 100644
--- a/tests/controller/helper_route_unclean_path_test.php
+++ b/tests/controller/helper_route_unclean_path_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/common_helper_route.php';
class phpbb_controller_helper_route_unclean_path_test extends phpbb_controller_common_helper_route
diff --git a/tests/datetime/from_format_test.php b/tests/datetime/from_format_test.php
index 8968619bb5..7ecb546768 100644
--- a/tests/datetime/from_format_test.php
+++ b/tests/datetime/from_format_test.php
@@ -37,7 +37,11 @@ class phpbb_datetime_from_format_test extends phpbb_test_case
*/
public function test_from_format($timezone, $format, $expected)
{
- $user = new \phpbb\user('\phpbb\datetime');
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->timezone = new DateTimeZone($timezone);
$user->lang['datetime'] = array(
'TODAY' => 'Today',
@@ -107,7 +111,11 @@ class phpbb_datetime_from_format_test extends phpbb_test_case
*/
public function test_relative_format_date($timestamp, $forcedate, $expected)
{
- $user = new \phpbb\user('\phpbb\datetime');
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->timezone = new DateTimeZone('UTC');
$user->lang['datetime'] = array(
'TODAY' => 'Today',
diff --git a/tests/dbal/auto_increment_test.php b/tests/dbal/auto_increment_test.php
index 1ed8ea29e3..950a4fc8f7 100644
--- a/tests/dbal/auto_increment_test.php
+++ b/tests/dbal/auto_increment_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_auto_increment_test extends phpbb_database_test_case
{
protected $db;
@@ -30,7 +28,8 @@ class phpbb_dbal_auto_increment_test extends phpbb_database_test_case
parent::setUp();
$this->db = $this->new_dbal();
- $this->tools = new \phpbb\db\tools($this->db);
+ $factory = new \phpbb\db\tools\factory();
+ $this->tools = $factory->get($this->db);
$this->table_data = array(
'COLUMNS' => array(
diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php
new file mode 100644
index 0000000000..c69f60a1a8
--- /dev/null
+++ b/tests/dbal/boolean_processor_test.php
@@ -0,0 +1,321 @@
+<?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.
+*
+*/
+
+class phpbb_boolean_processor_test extends phpbb_database_test_case
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml');
+ }
+
+ public function test_single_not_like()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ ),
+ 'WHERE' => array('u.username_clean', 'NOT_LIKE', 'gr' . $db->get_any_char()),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('user_id' => '1'),
+ array('user_id' => '2'),
+ array('user_id' => '3'),
+ array('user_id' => '6'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+
+ public function test_single_like()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ ),
+ 'WHERE' => array('u.username_clean', 'LIKE', 'gr' . $db->get_any_char()),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('user_id' => '4'),
+ array('user_id' => '5'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+
+ public function test_single_not_in()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ ),
+ 'WHERE' => array('u.user_id', 'NOT_IN', array(3,4,5)),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('user_id' => '1'),
+ array('user_id' => '2'),
+ array('user_id' => '6'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+
+ public function test_single_in()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ ),
+ 'WHERE' => array('u.user_id', 'IN', array(3,4,5)),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('user_id' => '3'),
+ array('user_id' => '4'),
+ array('user_id' => '5'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+
+ public function test_and_of_or_of_and()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ 'phpbb_user_group' => 'ug',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(
+ 'phpbb_banlist' => 'b',
+ ),
+ 'ON' => 'u.user_id = b.ban_userid',
+ ),
+ ),
+ 'WHERE' => array('AND',
+ array(
+ array('OR',
+ array(
+ array('AND',
+ array(
+ array('ug.user_id', 'IN', array(1, 2, 3, 4)),
+ array('ug.group_id', '=', 2),
+ ),
+ ),
+ array('AND',
+ array(
+ array('ug.group_id', '=', 1),
+ array('b.ban_id', 'IS_NOT', NULL),
+ ),
+ ),
+ ),
+ ),
+ array('u.user_id', '=', 'ug.user_id'),
+ ),
+ ),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('user_id' => '2'),
+ array('user_id' => '4'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+
+ public function test_triple_and_with_in()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ 'phpbb_user_group' => 'ug',
+ ),
+ 'WHERE' => array('AND',
+ array(
+ array('ug.user_id', 'IN', array(1, 2, 3, 4)),
+ array('ug.group_id', '=', 1),
+ array('u.user_id', '=', 'ug.user_id'),
+ ),
+ ),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('user_id' => '1'),
+ array('user_id' => '2'),
+ array('user_id' => '3'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+
+ }
+
+ public function test_double_and_with_not_of_or()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ 'phpbb_user_group' => 'ug',
+ ),
+ 'WHERE' => array('AND',
+ array(
+ array('NOT',
+ array(
+ array('OR',
+ array(
+ array('ug.group_id', '=', 1),
+ array('ug.group_id', '=', 2),
+ ),
+ ),
+ ),
+ ),
+ array('u.user_id', '=', 'ug.user_id'),
+ ),
+ ),
+ 'ORDER_BY' => 'u.user_id',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+
+ public function test_triple_and_with_is_null()
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $sql_ary = array(
+ 'SELECT' => 'u.username',
+ 'FROM' => array(
+ 'phpbb_users' => 'u',
+ 'phpbb_user_group' => 'ug',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(
+ 'phpbb_banlist' => 'b',
+ ),
+ 'ON' => 'u.user_id = b.ban_userid',
+ ),
+ ),
+ 'WHERE' => array('AND',
+ array(
+ array('ug.group_id', '=', 1),
+ array('u.user_id', '=', 'ug.user_id'),
+ array('b.ban_id', 'IS', NULL),
+ ),
+ ),
+ 'ORDER_BY' => 'u.username',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals(array(
+ array('username' => 'helper'),
+ array('username' => 'mass email'),
+ ), $db->sql_fetchrowset($result),
+ ($result === false) ?
+ "SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() :
+ var_export($sql, true) . ' ' . var_export($result, true)
+ );
+ }
+}
diff --git a/tests/dbal/connect_test.php b/tests/dbal/connect_test.php
index 1ae34bd2b6..3933dab798 100644
--- a/tests/dbal/connect_test.php
+++ b/tests/dbal/connect_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_connect_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -22,7 +20,9 @@ class phpbb_dbal_connect_test extends phpbb_database_test_case
public function test_failing_connect()
{
- global $phpbb_root_path, $phpEx;
+ global $phpbb_root_path, $phpEx, $phpbb_filesystem;
+
+ $phpbb_filesystem = new phpbb\filesystem\filesystem();
$config = $this->get_database_config();
diff --git a/tests/dbal/cross_join_test.php b/tests/dbal/cross_join_test.php
index 7ba937ccc6..be9258c58b 100644
--- a/tests/dbal/cross_join_test.php
+++ b/tests/dbal/cross_join_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_dbal_cross_join_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php
index 5832b966d8..b884b4ab95 100644
--- a/tests/dbal/db_tools_test.php
+++ b/tests/dbal/db_tools_test.php
@@ -11,13 +11,11 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_db_tools_test extends phpbb_database_test_case
{
/** @var \phpbb\db\driver\driver_interface */
protected $db;
- /** @var \phpbb\db\tools */
+ /** @var \phpbb\db\tools\tools_interface */
protected $tools;
protected $table_exists;
protected $table_data;
@@ -32,7 +30,8 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
parent::setUp();
$this->db = $this->new_dbal();
- $this->tools = new \phpbb\db\tools($this->db);
+ $factory = new \phpbb\db\tools\factory();
+ $this->tools = $factory->get($this->db);
$this->table_data = array(
'COLUMNS' => array(
@@ -340,7 +339,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
public function test_perform_schema_changes_drop_tables()
{
- $db_tools = $this->getMock('\phpbb\db\tools', array(
+ $db_tools = $this->getMock('\phpbb\db\tools\tools', array(
'sql_table_exists',
'sql_table_drop',
), array(&$this->db));
@@ -366,7 +365,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case
public function test_perform_schema_changes_drop_columns()
{
- $db_tools = $this->getMock('\phpbb\db\tools', array(
+ $db_tools = $this->getMock('\phpbb\db\tools\tools', array(
'sql_column_exists',
'sql_column_remove',
), array(&$this->db));
diff --git a/tests/dbal/fixtures/boolean_processor.xml b/tests/dbal/fixtures/boolean_processor.xml
new file mode 100644
index 0000000000..c5da677116
--- /dev/null
+++ b/tests/dbal/fixtures/boolean_processor.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_banlist">
+ <column>ban_id</column>
+ <column>ban_userid</column>
+ <row>
+ <value>1</value>
+ <value>2</value>
+ </row>
+ </table>
+ <table name="phpbb_users">
+ <column>user_id</column>
+ <column>username</column>
+ <column>username_clean</column>
+ <column>user_permissions</column>
+ <column>user_sig</column>
+ <row>
+ <value>1</value>
+ <value>mass email</value>
+ <value>mass email</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>banned</value>
+ <value>banned</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>helper</value>
+ <value>helper</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>GroupBPal</value>
+ <value>groupbpal</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>GroupBPal2</value>
+ <value>groupBPal2</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>not in group</value>
+ <value>not in group</value>
+ <value></value>
+ <value></value>
+ </row>
+ </table>
+ <table name="phpbb_user_group">
+ <column>user_id</column>
+ <column>group_id</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>2</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>2</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/dbal/migrator_test.php b/tests/dbal/migrator_test.php
index 798200eef1..f7275a4bbe 100644
--- a/tests/dbal/migrator_test.php
+++ b/tests/dbal/migrator_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/migration/dummy.php';
require_once dirname(__FILE__) . '/migration/unfulfillable.php';
require_once dirname(__FILE__) . '/migration/if.php';
@@ -38,7 +37,8 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
parent::setUp();
$this->db = $this->new_dbal();
- $this->db_tools = new \phpbb\db\tools($this->db);
+ $factory = new \phpbb\db\tools\factory();
+ $this->db_tools = $factory->get($this->db);
$this->config = new \phpbb\config\db($this->db, new phpbb_mock_cache, 'phpbb_config');
@@ -62,14 +62,12 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
);
$container->set('migrator', $this->migrator);
$container->set('dispatcher', new phpbb_mock_event_dispatcher());
- $user = new \phpbb\user('\phpbb\datetime');
$this->extension_manager = new \phpbb\extension\manager(
$container,
$this->db,
$this->config,
- new phpbb\filesystem(),
- $user,
+ new phpbb\filesystem\filesystem(),
'phpbb_ext',
dirname(__FILE__) . '/../../phpBB/',
'php',
diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php
index bbe543f347..29b21166b6 100644
--- a/tests/dbal/migrator_tool_module_test.php
+++ b/tests/dbal/migrator_tool_module_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -27,19 +25,24 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case
parent::setup();
- // Force add_log function to not be used
+ // Disable the logs
$skip_add_log = true;
$db = $this->db = $this->new_dbal();
- $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx);
- $user = $this->user = new \phpbb\user('\phpbb\user');
+ $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx);
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = $this->user = new \phpbb\user($lang, '\phpbb\datetime');
$cache = new phpbb_mock_cache;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$auth = $this->getMock('\phpbb\auth\auth');
$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
- $this->tool = new \phpbb\db\migration\tool\module($this->db, $this->cache, $this->user, $phpbb_root_path, $phpEx, 'phpbb_modules');
+ $phpbb_extension_manager = new phpbb_mock_extension_manager($phpbb_root_path);
+ $module_manager = new \phpbb\module\module_manager($cache, $this->db, $phpbb_extension_manager, MODULES_TABLE, $phpbb_root_path, $phpEx);
+
+ $this->tool = new \phpbb\db\migration\tool\module($this->db, $this->cache, $this->user, $module_manager, $phpbb_root_path, $phpEx, 'phpbb_modules');
}
public function exists_data_acp()
diff --git a/tests/dbal/migrator_tool_permission_test.php b/tests/dbal/migrator_tool_permission_test.php
index 2d673864f7..d84f6a68ff 100644
--- a/tests/dbal/migrator_tool_permission_test.php
+++ b/tests/dbal/migrator_tool_permission_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_migrator_tool_permission_test extends phpbb_database_test_case
{
public $group_ids = array(
@@ -34,7 +32,7 @@ class phpbb_dbal_migrator_tool_permission_test extends phpbb_database_test_case
parent::setup();
$db = $this->db = $this->new_dbal();
- $cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx);
+ $cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx);
$this->auth = new \phpbb\auth\auth();
$this->tool = new \phpbb\db\migration\tool\permission($this->db, $this->cache, $this->auth, $phpbb_root_path, $phpEx);
diff --git a/tests/dbal/schema_test.php b/tests/dbal/schema_test.php
index f13c7ce032..59965655ad 100644
--- a/tests/dbal/schema_test.php
+++ b/tests/dbal/schema_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_schema_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/dbal/select_test.php b/tests/dbal/select_test.php
index b7074552ba..0dac66fc46 100644
--- a/tests/dbal/select_test.php
+++ b/tests/dbal/select_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_dbal_select_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/dbal/write_sequence_test.php b/tests/dbal/write_sequence_test.php
index a1b589c578..a2d5921797 100644
--- a/tests/dbal/write_sequence_test.php
+++ b/tests/dbal/write_sequence_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_write_sequence_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/dbal/write_test.php b/tests/dbal/write_test.php
index 2426f2b0be..98709fb043 100644
--- a/tests/dbal/write_test.php
+++ b/tests/dbal/write_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_dbal_write_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php
index 4ae6017989..aba7a3560b 100644
--- a/tests/di/create_container_test.php
+++ b/tests/di/create_container_test.php
@@ -13,7 +13,7 @@
namespace
{
- require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+ require_once dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/di/extension.php';
class phpbb_di_container_test extends \phpbb_test_case
{
@@ -30,7 +30,8 @@ namespace
{
$this->phpbb_root_path = dirname(__FILE__) . '/';
$this->config_php = new \phpbb\config_php_file($this->phpbb_root_path . 'fixtures/', 'php');
- $this->builder = new phpbb_mock_phpbb_di_container_builder($this->config_php, $this->phpbb_root_path . 'fixtures/', 'php');
+ $this->builder = new phpbb_mock_phpbb_di_container_builder($this->phpbb_root_path . 'fixtures/', 'php');
+ $this->builder->with_config($this->config_php);
$this->filename = $this->phpbb_root_path . '../tmp/container.php';
if (is_file($this->filename))
@@ -57,6 +58,9 @@ namespace
// Checks use_extensions
$this->assertTrue($container->hasParameter('enabled'));
+ $this->assertTrue($container->hasParameter('enabled_2'));
+ $this->assertTrue($container->hasParameter('enabled_3'));
+ $this->assertTrue($container->hasParameter('enabled_4'));
$this->assertFalse($container->hasParameter('disabled'));
$this->assertFalse($container->hasParameter('available'));
@@ -69,14 +73,12 @@ namespace
// Checks the construction of a dumped container
$container = $this->builder->get_container();
$this->assertInstanceOf('phpbb_cache_container', $container);
- $this->assertFalse($container->isFrozen());
- $container->getParameterBag(); // needed, otherwise the container is not marked as frozen
$this->assertTrue($container->isFrozen());
}
- public function test_dump_container()
+ public function test_without_cache()
{
- $this->builder->set_dump_container(false);
+ $this->builder->without_cache();
$container = $this->builder->get_container();
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
@@ -90,9 +92,9 @@ namespace
$this->assertTrue($container->isFrozen());
}
- public function test_use_extensions()
+ public function test_without_extensions()
{
- $this->builder->set_use_extensions(false);
+ $this->builder->without_extensions();
$container = $this->builder->get_container();
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
@@ -105,9 +107,9 @@ namespace
$this->assertFalse($container->hasParameter('available'));
}
- public function test_compile_container()
+ public function test_without_compiled_container()
{
- $this->builder->set_compile_container(false);
+ $this->builder->without_compiled_container();
$container = $this->builder->get_container();
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
@@ -115,19 +117,9 @@ namespace
$this->assertFalse($container->isFrozen());
}
- public function test_inject_config()
- {
- $this->builder->set_inject_config(false);
- $container = $this->builder->get_container();
- $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
-
- // Checks inject_config
- $this->assertFalse($container->hasParameter('dbal.dbhost'));
- }
-
- public function test_set_config_path()
+ public function test_with_config_path()
{
- $this->builder->set_config_path($this->phpbb_root_path . 'fixtures/other_config/');
+ $this->builder->with_config_path($this->phpbb_root_path . 'fixtures/other_config/');
$container = $this->builder->get_container();
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
@@ -135,70 +127,32 @@ namespace
$this->assertFalse($container->hasParameter('core'));
}
- public function test_set_custom_parameters()
+ public function test_with_custom_parameters()
{
- $this->builder->set_custom_parameters(array('my_parameter' => true));
+ $this->builder->with_custom_parameters(array('my_parameter' => true));
$container = $this->builder->get_container();
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
$this->assertTrue($container->hasParameter('my_parameter'));
- $this->assertFalse($container->hasParameter('core.root_path'));
}
}
}
-namespace phpbb\db\driver
+namespace phpbb\extension
{
- class container_mock extends \phpbb\db\driver\driver
+ class manager_mock extends \phpbb\extension\manager
{
- public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
- {
- }
-
- public function sql_query($query = '', $cache_ttl = 0)
- {
- }
-
- public function sql_fetchrow($query_id = false)
- {
- }
-
- public function sql_freeresult($query_id = false)
- {
- }
-
- function sql_server_info($raw = false, $use_cache = true)
- {
- }
-
- function sql_affectedrows()
- {
- }
-
- function sql_rowseek($rownum, &$query_id)
- {
- }
-
- function sql_nextid()
- {
- }
-
- function sql_escape($msg)
- {
- }
-
- function sql_like_expression($expression)
- {
- }
-
- function sql_not_like_expression($expression)
+ public function __construct()
{
}
- function sql_fetchrowset($query_id = false)
+ public function all_enabled($phpbb_relative = true)
{
return array(
- array('ext_name' => 'vendor/enabled'),
+ 'vendor/enabled' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled/',
+ 'vendor/enabled-2' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled-2/',
+ 'vendor/enabled-3' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled-3/',
+ 'vendor/enabled_4' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/',
);
}
}
diff --git a/tests/di/fixtures/config.php b/tests/di/fixtures/config.php
index 04e20f63d8..1e9207d924 100644
--- a/tests/di/fixtures/config.php
+++ b/tests/di/fixtures/config.php
@@ -1,11 +1,11 @@
<?php
// phpBB 3.1.x auto-generated configuration file
// Do not change anything in this file!
-$dbms = 'container_mock';
+$dbms = 'mysql';
$dbhost = '127.0.0.1';
$dbport = '';
$dbname = 'phpbb';
$dbuser = 'root';
$dbpasswd = '';
$table_prefix = 'phpbb_';
-$acm_type = '\phpbb\cache\driver\null';
+$acm_type = '\phpbb\cache\driver\dummy';
diff --git a/tests/di/fixtures/config/production/config.yml b/tests/di/fixtures/config/production/config.yml
new file mode 100644
index 0000000000..fcfa84f68b
--- /dev/null
+++ b/tests/di/fixtures/config/production/config.yml
@@ -0,0 +1,2 @@
+core:
+ require_dev_dependencies: true
diff --git a/tests/di/fixtures/config/production/container/environment.yml b/tests/di/fixtures/config/production/container/environment.yml
new file mode 100644
index 0000000000..4216b187cc
--- /dev/null
+++ b/tests/di/fixtures/config/production/container/environment.yml
@@ -0,0 +1,29 @@
+parameters:
+ core: true
+
+services:
+ config.php:
+ synthetic: true
+
+ dbal.conn:
+ class: phpbb\db\driver\factory
+ arguments:
+ - '@service_container'
+
+ dispatcher:
+ class: phpbb\db\driver\container_mock
+
+ ext.manager:
+ class: phpbb\extension\manager_mock
+
+ template.twig.environment:
+ class: Exception
+ arguments:
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - []
diff --git a/tests/di/fixtures/config/services.yml b/tests/di/fixtures/config/services.yml
deleted file mode 100644
index f2a22ae109..0000000000
--- a/tests/di/fixtures/config/services.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-parameters:
- core: true
-
-services:
- config.php:
- synthetic: true
-
- dbal.conn:
- class: phpbb\db\driver\factory
- arguments:
- - @service_container
-
- dispatcher:
- class: phpbb\db\driver\container_mock
diff --git a/tests/di/fixtures/config/test/config.yml b/tests/di/fixtures/config/test/config.yml
new file mode 100644
index 0000000000..fcfa84f68b
--- /dev/null
+++ b/tests/di/fixtures/config/test/config.yml
@@ -0,0 +1,2 @@
+core:
+ require_dev_dependencies: true
diff --git a/tests/di/fixtures/config/test/container/environment.yml b/tests/di/fixtures/config/test/container/environment.yml
new file mode 100644
index 0000000000..7d528fed19
--- /dev/null
+++ b/tests/di/fixtures/config/test/container/environment.yml
@@ -0,0 +1,26 @@
+parameters:
+ core: true
+
+services:
+ config.php:
+ synthetic: true
+
+ dbal.conn:
+ class: phpbb\db\driver\factory
+ arguments:
+ - '@service_container'
+
+ dispatcher:
+ class: phpbb\db\driver\container_mock
+
+ template.twig.environment:
+ class: Exception
+ arguments:
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - []
diff --git a/tests/di/fixtures/ext/vendor/disabled/config/services.yml b/tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml
index 31ada384bf..31ada384bf 100644
--- a/tests/di/fixtures/ext/vendor/disabled/config/services.yml
+++ b/tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml
diff --git a/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml b/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml
new file mode 100644
index 0000000000..feeb5a7a2d
--- /dev/null
+++ b/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml
@@ -0,0 +1,2 @@
+parameters:
+ enabled_2: true
diff --git a/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml b/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml
new file mode 100644
index 0000000000..0dae35d2bd
--- /dev/null
+++ b/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml
@@ -0,0 +1,2 @@
+parameters:
+ enabled_3: true
diff --git a/tests/di/fixtures/ext/vendor/enabled/config/services.yml b/tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml
index 88a7919ed1..88a7919ed1 100644
--- a/tests/di/fixtures/ext/vendor/enabled/config/services.yml
+++ b/tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml
diff --git a/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php
new file mode 100644
index 0000000000..8e5ed6c52c
--- /dev/null
+++ b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php
@@ -0,0 +1,32 @@
+<?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 vendor\enabled_4\di;
+
+use phpbb\extension\di\extension_base;
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+
+/**
+* Container core extension
+*/
+class extension extends extension_base
+{
+ protected function load_services(ContainerBuilder $container)
+ {
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($this->ext_path)));
+ $loader->load('environment.yml');
+ }
+}
diff --git a/tests/di/fixtures/ext/vendor/enabled_4/environment.yml b/tests/di/fixtures/ext/vendor/enabled_4/environment.yml
new file mode 100644
index 0000000000..d0affe4fd6
--- /dev/null
+++ b/tests/di/fixtures/ext/vendor/enabled_4/environment.yml
@@ -0,0 +1,2 @@
+parameters:
+ enabled_4: true
diff --git a/tests/di/fixtures/other_config/production/config.yml b/tests/di/fixtures/other_config/production/config.yml
new file mode 100644
index 0000000000..fcfa84f68b
--- /dev/null
+++ b/tests/di/fixtures/other_config/production/config.yml
@@ -0,0 +1,2 @@
+core:
+ require_dev_dependencies: true
diff --git a/tests/di/fixtures/other_config/production/container/environment.yml b/tests/di/fixtures/other_config/production/container/environment.yml
new file mode 100644
index 0000000000..1170145b66
--- /dev/null
+++ b/tests/di/fixtures/other_config/production/container/environment.yml
@@ -0,0 +1,29 @@
+parameters:
+ other_config: true
+
+services:
+ config.php:
+ synthetic: true
+
+ dbal.conn:
+ class: phpbb\db\driver\factory
+ arguments:
+ - '@service_container'
+
+ dispatcher:
+ class: phpbb\db\driver\container_mock
+
+ ext.manager:
+ class: phpbb\extension\manager_mock
+
+ template.twig.environment:
+ class: Exception
+ arguments:
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - []
diff --git a/tests/di/fixtures/other_config/services.yml b/tests/di/fixtures/other_config/services.yml
deleted file mode 100644
index c299bfc648..0000000000
--- a/tests/di/fixtures/other_config/services.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-parameters:
- other_config: true
-
-services:
- config.php:
- synthetic: true
-
- dbal.conn:
- class: phpbb\db\driver\factory
- arguments:
- - @service_container
-
- dispatcher:
- class: phpbb\db\driver\container_mock
diff --git a/tests/di/fixtures/other_config/test/config.yml b/tests/di/fixtures/other_config/test/config.yml
new file mode 100644
index 0000000000..fcfa84f68b
--- /dev/null
+++ b/tests/di/fixtures/other_config/test/config.yml
@@ -0,0 +1,2 @@
+core:
+ require_dev_dependencies: true
diff --git a/tests/di/fixtures/other_config/test/container/environment.yml b/tests/di/fixtures/other_config/test/container/environment.yml
new file mode 100644
index 0000000000..6c36977d4d
--- /dev/null
+++ b/tests/di/fixtures/other_config/test/container/environment.yml
@@ -0,0 +1,26 @@
+parameters:
+ other_config: true
+
+services:
+ config.php:
+ synthetic: true
+
+ dbal.conn:
+ class: phpbb\db\driver\factory
+ arguments:
+ - '@service_container'
+
+ dispatcher:
+ class: phpbb\db\driver\container_mock
+
+ template.twig.environment:
+ class: Exception
+ arguments:
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - ~
+ - []
diff --git a/tests/di/ordered_service_collection_test.php b/tests/di/ordered_service_collection_test.php
new file mode 100644
index 0000000000..47e6d23744
--- /dev/null
+++ b/tests/di/ordered_service_collection_test.php
@@ -0,0 +1,51 @@
+<?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.
+ *
+ */
+
+class phpbb_ordered_service_collection_test extends \phpbb_test_case
+{
+ /**
+ * @var \phpbb\di\ordered_service_collection
+ */
+ protected $service_collection;
+
+ public function setUp()
+ {
+ $container = new phpbb_mock_container_builder();
+ $container->set('foo', new StdClass);
+ $container->set('bar', new StdClass);
+ $container->set('foobar', new StdClass);
+ $container->set('barfoo', new StdClass);
+
+ $this->service_collection = new \phpbb\di\ordered_service_collection($container);
+ $this->service_collection->add('foo', 7);
+ $this->service_collection->add('bar', 3);
+ $this->service_collection->add('barfoo', 5);
+ $this->service_collection->add('foobar', 2);
+
+ parent::setUp();
+ }
+
+ public function test_service_collection()
+ {
+ $service_names = array();
+
+ // Test the iterator
+ foreach ($this->service_collection as $name => $service)
+ {
+ $service_names[] = $name;
+ $this->assertInstanceOf('StdClass', $service);
+ }
+
+ $this->assertSame(array('foobar', 'bar', 'barfoo', 'foo'), $service_names);
+ }
+}
diff --git a/tests/di/service_collection_test.php b/tests/di/service_collection_test.php
new file mode 100644
index 0000000000..5b51254a4a
--- /dev/null
+++ b/tests/di/service_collection_test.php
@@ -0,0 +1,47 @@
+<?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.
+ *
+ */
+
+class phpbb_service_collection_test extends \phpbb_test_case
+{
+ /**
+ * @var \phpbb\di\service_collection
+ */
+ protected $service_collection;
+
+ public function setUp()
+ {
+ $container = new phpbb_mock_container_builder();
+ $container->set('foo', new StdClass);
+ $container->set('bar', new StdClass);
+
+ $this->service_collection = new \phpbb\di\service_collection($container);
+ $this->service_collection->add('foo');
+ $this->service_collection->add('bar');
+
+ parent::setUp();
+ }
+
+ public function test_service_collection()
+ {
+ $service_names = array();
+
+ // Test the iterator
+ foreach ($this->service_collection as $name => $service)
+ {
+ $service_names[] = $name;
+ $this->assertInstanceOf('StdClass', $service);
+ }
+
+ $this->assertSame(array('foo', 'bar'), $service_names);
+ }
+}
diff --git a/tests/download/http_byte_range_test.php b/tests/download/http_byte_range_test.php
index f920299048..8975ec1799 100644
--- a/tests/download/http_byte_range_test.php
+++ b/tests/download/http_byte_range_test.php
@@ -45,24 +45,72 @@ class phpbb_download_http_byte_range_test extends phpbb_test_case
public function parse_range_request_data()
{
return array(
- // Does not read until the end of file.
+ // Valid request
array(
array('3-4'),
10,
- false,
+ array(
+ 'byte_pos_start' => 3,
+ 'byte_pos_end' => 4,
+ 'bytes_requested' => 2,
+ 'bytes_total' => 10,
+ ),
),
- // Valid request, handle second range.
+ // Get the beginning
array(
- array('0-0', '120-125'),
- 125,
+ array('-5'),
+ 10,
array(
- 'byte_pos_start' => 120,
- 'byte_pos_end' => 124,
+ 'byte_pos_start' => 0,
+ 'byte_pos_end' => 5,
+ 'bytes_requested' => 6,
+ 'bytes_total' => 10,
+ ),
+ ),
+
+ // Get the end
+ array(
+ array('5-'),
+ 10,
+ array(
+ 'byte_pos_start' => 5,
+ 'byte_pos_end' => 9,
'bytes_requested' => 5,
+ 'bytes_total' => 10,
+ ),
+ ),
+
+ // Overlong request
+ array(
+ array('3-20'),
+ 10,
+ array(
+ 'byte_pos_start' => 3,
+ 'byte_pos_end' => 9,
+ 'bytes_requested' => 7,
+ 'bytes_total' => 10,
+ ),
+ ),
+
+ // Multiple, contiguous range
+ array(
+ array('10-20', '21-30'),
+ 125,
+ array(
+ 'byte_pos_start' => 10,
+ 'byte_pos_end' => 30,
+ 'bytes_requested' => 21,
'bytes_total' => 125,
)
),
+
+ // We don't do multiple, non-contiguous range
+ array(
+ array('0-0', '120-125'),
+ 125,
+ false,
+ ),
);
}
}
diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php
new file mode 100644
index 0000000000..351a38514f
--- /dev/null
+++ b/tests/email/email_parsing_test.php
@@ -0,0 +1,149 @@
+<?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.
+ *
+ */
+
+class phpbb_email_parsing_test extends phpbb_test_case
+{
+ /** @var \messenger */
+ protected $messenger;
+
+ /** @var \ReflectionProperty */
+ protected $reflection_template_property;
+
+ public function setUp()
+ {
+ global $phpbb_container, $config, $phpbb_root_path, $phpEx, $request, $user;
+
+ $phpbb_container = new phpbb_mock_container_builder;
+
+ $config = new \phpbb\config\config(array(
+ 'board_email_sig' => '-- Thanks, The Management',
+ 'sitename' => 'yourdomain.com',
+ 'default_lang' => 'en',
+ ));
+ $phpbb_container->set('config', $config);
+
+ $request = new phpbb_mock_request;
+ $symfony_request = new \phpbb\symfony_request(
+ $request
+ );
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $phpbb_path_helper = new \phpbb\path_helper(
+ $symfony_request,
+ $filesystem,
+ $request,
+ $phpbb_root_path,
+ $phpEx
+ );
+ $phpbb_container->set('path_helper', $phpbb_path_helper);
+ $phpbb_container->set('filesystem', $filesystem);
+
+ $cache_path = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/twig';
+ $phpbb_container->setParameter('core.template.cache_path', $cache_path);
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $phpbb_container->set('user', $user);
+ $extension_manager = new phpbb_mock_extension_manager(
+ dirname(__FILE__) . '/',
+ array(
+ 'vendor2/foo' => array(
+ 'ext_name' => 'vendor2/foo',
+ 'ext_active' => '1',
+ 'ext_path' => 'ext/vendor2/foo/',
+ ),
+ )
+ );
+ $phpbb_container->set('ext.manager', $extension_manager);
+
+ $context = new \phpbb\template\context();
+ $twig_extension = new \phpbb\template\twig\extension($context, $lang);
+ $phpbb_container->set('template.twig.extensions.phpbb', $twig_extension);
+
+ $twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container);
+ $twig_extensions_collection->add('template.twig.extensions.phpbb');
+ $phpbb_container->set('template.twig.extensions.collection', $twig_extensions_collection);
+
+ $twig = new \phpbb\template\twig\environment(
+ $config,
+ $filesystem,
+ $phpbb_path_helper,
+ $cache_path,
+ null,
+ new \phpbb\template\twig\loader($filesystem, ''),
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
+ $twig->addExtension($twig_extension);
+ $phpbb_container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig));
+
+ if (!class_exists('messenger'))
+ {
+ include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
+ }
+
+ $this->messenger = new \messenger();
+
+ $reflection = new ReflectionObject($this->messenger);
+ $this->reflection_template_property = $reflection->getProperty('template');
+ $this->reflection_template_property->setAccessible(true);
+ }
+
+ public function email_parsing_data()
+ {
+ return array(
+ array('Author username', 'Any forum', 'The topic title', 'Dear user'),
+ array('0', 'Any forum', 'The topic title', 'Dear user'),
+ );
+ }
+
+ /**
+ * @dataProvider email_parsing_data
+ */
+ public function test_email_parsing($author_name, $forum_name, $topic_title, $username)
+ {
+ global $config, $phpEx, $user;
+
+ $this->messenger->set_addresses($user->data);
+
+ $this->messenger->assign_vars(array(
+ 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])),
+ 'SITENAME' => htmlspecialchars_decode($config['sitename']),
+
+ 'AUTHOR_NAME' => $author_name,
+ 'FORUM_NAME' => $forum_name,
+ 'TOPIC_TITLE' => $topic_title,
+ 'USERNAME' => $username,
+
+ 'U_FORUM' => generate_board_url() . "/viewforum.{$phpEx}?f=1",
+ 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.{$phpEx}?uid=2&f=1&unwatch=forum",
+ ));
+ $this->messenger->template('newtopic_notify', $user->data['user_lang'], '', '');
+
+ $reflection_template = $this->reflection_template_property->getValue($this->messenger);
+ $msg = trim($reflection_template->assign_display('body'));
+
+ $this->assertContains($author_name, $msg);
+ $this->assertContains($forum_name, $msg);
+ $this->assertContains($topic_title, $msg);
+ $this->assertContains($username, $msg);
+ $this->assertContains(htmlspecialchars_decode($config['sitename']), $msg);
+ $this->assertContains(str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])), $msg);
+ $this->assertNotContains('EMAIL_SIG', $msg);
+ $this->assertNotContains('U_STOP_WATCHING_FORUM', $msg);
+ }
+}
diff --git a/tests/error_collector_test.php b/tests/error_collector_test.php
index b92c4fa6bb..273284c8fc 100644
--- a/tests/error_collector_test.php
+++ b/tests/error_collector_test.php
@@ -11,10 +11,17 @@
*
*/
-require_once dirname(__FILE__) . '/../phpBB/includes/functions.php';
-
class phpbb_error_collector_test extends phpbb_test_case
{
+ public function setUp()
+ {
+ parent::setUp();
+
+ global $phpbb_filesystem;
+
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
+ }
+
public function test_collection()
{
$collector = new \phpbb\error_collector(E_ALL | E_STRICT); // php set_error_handler() default
diff --git a/tests/event/exception_listener_test.php b/tests/event/exception_listener_test.php
index 4d3453cd83..08679a3ed8 100644
--- a/tests/event/exception_listener_test.php
+++ b/tests/event/exception_listener_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class exception_listener extends phpbb_test_case
{
public function phpbb_exception_data()
@@ -79,10 +77,12 @@ class exception_listener extends phpbb_test_case
->disableOriginalConstructor()
->getMock();
- $user = new \phpbb\user('\phpbb\datetime');
- $user->add_lang('common');
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
- $exception_listener = new \phpbb\event\kernel_exception_subscriber($template, $user);
+ $exception_listener = new \phpbb\event\kernel_exception_subscriber($template, $lang);
$event = new \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, \Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST, $exception);
$exception_listener->on_kernel_exception($event);
diff --git a/tests/event/md_exporter_test.php b/tests/event/md_exporter_test.php
index 1a51204cbe..607f442fdf 100644
--- a/tests/event/md_exporter_test.php
+++ b/tests/event/md_exporter_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_event_md_exporter_test extends phpbb_test_case
{
static public function crawl_eventsmd_data()
@@ -23,7 +21,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case
'event' => 'acp_bbcodes_actions_append',
'files' => array(
'prosilver' => array(),
- 'subsilver2' => array(),
'adm' => array('acp_bbcodes.html'),
),
'since' => '3.1.0-a3',
@@ -36,7 +33,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case
'event' => 'acp_bbcodes_actions_prepend',
'files' => array(
'prosilver' => array(),
- 'subsilver2' => array(),
'adm' => array('acp_bbcodes.html'),
),
'since' => '3.1.0-a5',
@@ -47,7 +43,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case
'event' => 'acp_bbcodes_actions_prepend2',
'files' => array(
'prosilver' => array(),
- 'subsilver2' => array(),
'adm' => array('acp_bbcodes.html'),
),
'since' => '3.1.0-a4',
@@ -63,7 +58,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case
'event' => 'acp_bbcodes_actions_prepend',
'files' => array(
'prosilver' => array(),
- 'subsilver2' => array(),
'adm' => array('acp_bbcodes.html'),
),
'since' => '3.1.0-a5',
@@ -74,7 +68,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case
'event' => 'acp_bbcodes_actions_prepend2',
'files' => array(
'prosilver' => array(),
- 'subsilver2' => array(),
'adm' => array('acp_bbcodes.html'),
),
'since' => '3.1.0-a4',
@@ -130,7 +123,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case
$styles = array(
'adm/style/' => 'adm',
'styles/prosilver/template/' => 'styles',
- 'styles/subsilver2/template/' => 'styles',
);
foreach ($styles as $path => $filter)
{
diff --git a/tests/extension/ext/vendor2/bar/acp/a_info.php b/tests/extension/ext/vendor2/bar/acp/a_info.php
index 8132df587f..8268006f9f 100644
--- a/tests/extension/ext/vendor2/bar/acp/a_info.php
+++ b/tests/extension/ext/vendor2/bar/acp/a_info.php
@@ -9,7 +9,6 @@ class a_info
return array(
'filename' => 'vendor2\\bar\\acp\\a_module',
'title' => 'Bar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')),
),
diff --git a/tests/extension/ext/vendor2/bar/migrations/bar.php b/tests/extension/ext/vendor2/bar/migrations/bar.php
new file mode 100644
index 0000000000..ea5ddb6b8b
--- /dev/null
+++ b/tests/extension/ext/vendor2/bar/migrations/bar.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace vendor2\foo\migrations;
+
+class bar
+{
+}
diff --git a/tests/extension/ext/vendor2/bar/migrations/foo.php b/tests/extension/ext/vendor2/bar/migrations/foo.php
new file mode 100644
index 0000000000..d727c2f954
--- /dev/null
+++ b/tests/extension/ext/vendor2/bar/migrations/foo.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace vendor2\foo\migrations;
+
+class foo implements \phpbb\db\migration\migration_interface
+{
+ /**
+ * {@inheritdoc}
+ */
+ static public function depends_on()
+ {
+ return array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function effectively_installed()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_schema()
+ {
+ return array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function revert_schema()
+ {
+ return array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_data()
+ {
+ return array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function revert_data()
+ {
+ return array();
+ }
+}
diff --git a/tests/extension/ext/vendor2/foo/acp/a_info.php b/tests/extension/ext/vendor2/foo/acp/a_info.php
index e1eaa340b7..48ab4cf8e7 100644
--- a/tests/extension/ext/vendor2/foo/acp/a_info.php
+++ b/tests/extension/ext/vendor2/foo/acp/a_info.php
@@ -9,7 +9,6 @@ class a_info
return array(
'filename' => 'vendor2\\foo\\acp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')),
),
diff --git a/tests/extension/ext/vendor2/foo/acp/fail_info.php b/tests/extension/ext/vendor2/foo/acp/fail_info.php
index d9b4353957..78479fee70 100644
--- a/tests/extension/ext/vendor2/foo/acp/fail_info.php
+++ b/tests/extension/ext/vendor2/foo/acp/fail_info.php
@@ -13,7 +13,6 @@ class foo_info
return array(
'filename' => 'vendor2\foo\acp\fail_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')),
),
diff --git a/tests/extension/ext/vendor2/foo/mcp/a_info.php b/tests/extension/ext/vendor2/foo/mcp/a_info.php
index b5599fde65..2532e44b12 100644
--- a/tests/extension/ext/vendor2/foo/mcp/a_info.php
+++ b/tests/extension/ext/vendor2/foo/mcp/a_info.php
@@ -9,7 +9,6 @@ class a_info
return array(
'filename' => 'vendor2\\foo\\mcp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')),
),
diff --git a/tests/extension/extension_base_test.php b/tests/extension/extension_base_test.php
index eee38186db..e0c2e6d549 100644
--- a/tests/extension/extension_base_test.php
+++ b/tests/extension/extension_base_test.php
@@ -10,7 +10,9 @@
* the docs/CREDITS.txt file.
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+require_once dirname(__FILE__) . '/ext/vendor2/bar/migrations/bar.php';
+require_once dirname(__FILE__) . '/ext/vendor2/bar/migrations/foo.php';
+require_once dirname(__FILE__) . '/ext/vendor2/bar/migrations/migration.php';
class phpbb_extension_extension_base_test extends phpbb_test_case
{
@@ -61,9 +63,7 @@ class phpbb_extension_extension_base_test extends phpbb_test_case
return array(
array(
'vendor2/bar',
- array(
- '\vendor2\bar\migrations\migration',
- ),
+ array('\vendor2\bar\migrations\migration'),
),
);
}
@@ -74,6 +74,8 @@ class phpbb_extension_extension_base_test extends phpbb_test_case
public function test_suffix_get_classes($extension_name, $expected)
{
$extension = $this->extension_manager->get_extension($extension_name);
- $this->assertEquals($expected, self::$reflection_method_get_migration_file_list->invoke($extension));
+ $migration_classes = self::$reflection_method_get_migration_file_list->invoke($extension);
+ sort($migration_classes);
+ $this->assertEquals($expected, $migration_classes);
}
}
diff --git a/tests/extension/finder_test.php b/tests/extension/finder_test.php
index 2116cc057b..71de2c2fc5 100644
--- a/tests/extension/finder_test.php
+++ b/tests/extension/finder_test.php
@@ -10,7 +10,6 @@
* the docs/CREDITS.txt file.
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_extension_finder_test extends phpbb_test_case
{
@@ -244,7 +243,7 @@ class phpbb_extension_finder_test extends phpbb_test_case
public function test_get_classes_create_cache()
{
$cache = new phpbb_mock_cache;
- $finder = new \phpbb\finder(new \phpbb\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name');
+ $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name');
$finder->set_extensions(array_keys($this->extension_manager->all_enabled()));
$files = $finder->suffix('_class.php')->get_files();
@@ -284,7 +283,7 @@ class phpbb_extension_finder_test extends phpbb_test_case
);
$finder = new \phpbb\finder(
- new \phpbb\filesystem(),
+ new \phpbb\filesystem\filesystem(),
dirname(__FILE__) . '/',
new phpbb_mock_cache(array(
'_ext_finder' => array(
diff --git a/tests/extension/includes/acp/info/acp_foobar.php b/tests/extension/includes/acp/info/acp_foobar.php
index 870225ba4f..8ca1afa1c6 100644
--- a/tests/extension/includes/acp/info/acp_foobar.php
+++ b/tests/extension/includes/acp/info/acp_foobar.php
@@ -18,7 +18,6 @@ class acp_foobar_info
return array(
'filename' => 'acp_foobar',
'title' => 'ACP Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'test' => array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')),
),
diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php
index 0eeb060936..a24b0cf178 100644
--- a/tests/extension/manager_test.php
+++ b/tests/extension/manager_test.php
@@ -150,11 +150,11 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
$config = new \phpbb\config\config(array('version' => PHPBB_VERSION));
$db = $this->new_dbal();
- $db_tools = new \phpbb\db\tools($db);
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($db);
$phpbb_root_path = __DIR__ . './../../phpBB/';
$php_ext = 'php';
$table_prefix = 'phpbb_';
- $user = new \phpbb\user('\phpbb\user');
$container = new phpbb_mock_container_builder();
@@ -176,8 +176,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case
$container,
$db,
$config,
- new \phpbb\filesystem(),
- $user,
+ new \phpbb\filesystem\filesystem(),
'phpbb_ext',
dirname(__FILE__) . '/',
$php_ext,
diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php
index 2a746d3792..19b99ee0ce 100644
--- a/tests/extension/metadata_manager_test.php
+++ b/tests/extension/metadata_manager_test.php
@@ -41,25 +41,39 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
'version' => '3.1.0',
));
$this->db = $this->new_dbal();
- $this->db_tools = new \phpbb\db\tools($this->db);
+ $factory = new \phpbb\db\tools\factory();
+ $this->db_tools = $factory->get($this->db);
$this->phpbb_root_path = dirname(__FILE__) . '/';
$this->phpEx = 'php';
- $this->user = new \phpbb\user('\phpbb\datetime');
$this->table_prefix = 'phpbb_';
- $this->template = new \phpbb\template\twig\twig(
- new \phpbb\path_helper(
- new \phpbb\symfony_request(
- new phpbb_mock_request()
- ),
- new \phpbb\filesystem(),
- $this->getMock('\phpbb\request\request'),
- $this->phpbb_root_path,
- $this->phpEx
+ $container = new phpbb_mock_container_builder();
+ $cache_path = $this->phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), '');
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $phpbb_path_helper = new \phpbb\path_helper(
+ new \phpbb\symfony_request(
+ new phpbb_mock_request()
),
+ $filesystem,
+ $this->getMock('\phpbb\request\request'),
+ $this->phpbb_root_path,
+ $this->phpEx
+ );
+ $twig = new \phpbb\template\twig\environment(
$this->config,
- $this->user,
- new \phpbb\template\context()
+ $filesystem,
+ $phpbb_path_helper,
+ $cache_path,
+ null,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
);
$container = new phpbb_mock_container_builder();
@@ -82,13 +96,22 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$container,
$this->db,
$this->config,
- new \phpbb\filesystem(),
- $this->user,
+ new \phpbb\filesystem\filesystem(),
'phpbb_ext',
$this->phpbb_root_path,
$this->phpEx,
$this->cache
);
+
+ global $phpbb_root_path;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $this->phpEx);
+ $lang_loader->set_extension_manager($this->extension_manager);
+ $lang = new \phpbb\language\language($lang_loader);
+ $this->user = new \phpbb\user($lang, '\phpbb\datetime');
+
+ $this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)));
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
}
// Should fail from missing composer.json
@@ -104,7 +127,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
}
catch (\phpbb\extension\exception $e)
{
- $this->assertEquals((string) $e, $this->user->lang('FILE_NOT_FOUND', $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json'));
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ $this->assertEquals($message, $this->user->lang('FILE_NOT_FOUND', $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json'));
}
}
@@ -121,7 +145,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
}
catch (\phpbb\extension\exception $e)
{
- $this->fail($e);
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ $this->fail($message);
}
$json = json_decode(file_get_contents($this->phpbb_root_path . 'ext/vendor2/foo/composer.json'), true);
@@ -151,9 +176,10 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$manager->validate($field_name);
$this->fail('Exception not triggered');
}
- catch(\phpbb\extension\exception $e)
+ catch (\phpbb\extension\exception $e)
{
- $this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', $field_name));
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', $field_name));
}
}
@@ -167,7 +193,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
}
catch (\phpbb\extension\exception $e)
{
- $this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', 'authors'));
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', 'authors'));
}
$manager->merge_metadata(array(
@@ -183,7 +210,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
}
catch (\phpbb\extension\exception $e)
{
- $this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', 'author name'));
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ $this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', 'author name'));
}
}
@@ -214,9 +242,10 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$manager->validate($field_name);
$this->fail('Exception not triggered');
}
- catch(\phpbb\extension\exception $e)
+ catch (\phpbb\extension\exception $e)
{
- $this->assertEquals((string) $e, $this->user->lang('META_FIELD_INVALID', $field_name));
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
+ $this->assertEquals($message, $this->user->lang('META_FIELD_INVALID', $field_name));
}
}
@@ -238,9 +267,9 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
{
$this->assertEquals(true, $manager->validate('enable'));
}
- catch(\phpbb\extension\exception $e)
+ catch (\phpbb\extension\exception $e)
{
- $this->fail($e);
+ $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
}
}
@@ -336,7 +365,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$this->config,
$this->extension_manager,
$this->template,
- $this->user,
$this->phpbb_root_path
);
}
diff --git a/tests/extension/modules_test.php b/tests/extension/modules_test.php
index 21f1c6aca5..88634bc6ba 100644
--- a/tests/extension/modules_test.php
+++ b/tests/extension/modules_test.php
@@ -22,6 +22,7 @@ class phpbb_extension_modules_test extends phpbb_test_case
{
protected $extension_manager;
protected $finder;
+ protected $module_manager;
public function setUp()
{
@@ -43,7 +44,14 @@ class phpbb_extension_modules_test extends phpbb_test_case
));
$phpbb_extension_manager = $this->extension_manager;
- $this->acp_modules = new acp_modules();
+ $this->module_manager = new \phpbb\module\module_manager(
+ new \phpbb\cache\driver\dummy(),
+ $this->getMock('\phpbb\db\driver\driver_interface'),
+ $this->extension_manager,
+ MODULES_TABLE,
+ dirname(__FILE__) . '/',
+ 'php'
+ );
}
public function test_get_module_infos()
@@ -56,13 +64,11 @@ class phpbb_extension_modules_test extends phpbb_test_case
$phpbb_root_path = dirname(__FILE__) . '/';
// Find acp module info files
- $this->acp_modules->module_class = 'acp';
- $acp_modules = $this->acp_modules->get_module_infos();
+ $acp_modules = $this->module_manager->get_module_infos('acp');
$this->assertEquals(array(
'vendor2\\foo\\acp\\a_module' => array(
'filename' => 'vendor2\\foo\\acp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')),
),
@@ -70,7 +76,6 @@ class phpbb_extension_modules_test extends phpbb_test_case
'acp_foobar' => array(
'filename' => 'acp_foobar',
'title' => 'ACP Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'test' => array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')),
),
@@ -78,13 +83,11 @@ class phpbb_extension_modules_test extends phpbb_test_case
), $acp_modules);
// Find mcp module info files
- $this->acp_modules->module_class = 'mcp';
- $acp_modules = $this->acp_modules->get_module_infos();
+ $acp_modules = $this->module_manager->get_module_infos('mcp');
$this->assertEquals(array(
'vendor2\\foo\\mcp\\a_module' => array(
'filename' => 'vendor2\\foo\\mcp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')),
),
@@ -92,27 +95,11 @@ class phpbb_extension_modules_test extends phpbb_test_case
), $acp_modules);
// Find a specific module info file (mcp_a_module)
- $this->acp_modules->module_class = 'mcp';
- $acp_modules = $this->acp_modules->get_module_infos('mcp_a_module');
- $this->assertEquals(array(
- 'vendor2\\foo\\mcp\\a_module' => array(
- 'filename' => 'vendor2\\foo\\mcp\\a_module',
- 'title' => 'Foobar',
- 'version' => '3.1.0-dev',
- 'modes' => array(
- 'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')),
- ),
- ),
- ), $acp_modules);
-
- // Find a specific module info file (mcp_a_module) with passing the module_class
- $this->acp_modules->module_class = '';
- $acp_modules = $this->acp_modules->get_module_infos('mcp_a_module', 'mcp');
+ $acp_modules = $this->module_manager->get_module_infos('mcp', 'mcp_a_module');
$this->assertEquals(array(
'vendor2\\foo\\mcp\\a_module' => array(
'filename' => 'vendor2\\foo\\mcp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('MCP_MAIN')),
),
@@ -120,23 +107,19 @@ class phpbb_extension_modules_test extends phpbb_test_case
), $acp_modules);
// The mcp module info file we're looking for shouldn't exist
- $this->acp_modules->module_class = 'mcp';
- $acp_modules = $this->acp_modules->get_module_infos('mcp_a_fail');
+ $acp_modules = $this->module_manager->get_module_infos('mcp', 'mcp_a_fail');
$this->assertEquals(array(), $acp_modules);
// As there are no ucp modules we shouldn't find any
- $this->acp_modules->module_class = 'ucp';
- $acp_modules = $this->acp_modules->get_module_infos();
+ $acp_modules = $this->module_manager->get_module_infos('ucp');
$this->assertEquals(array(), $acp_modules);
// Get module info of specified extension module
- $this->acp_modules->module_class = 'acp';
- $acp_modules = $this->acp_modules->get_module_infos('foo_acp_a_module');
+ $acp_modules = $this->module_manager->get_module_infos('acp', 'foo_acp_a_module');
$this->assertEquals(array(
'vendor2\\foo\\acp\\a_module' => array (
'filename' => 'vendor2\\foo\\acp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array (
'config' => array ('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array ('ACP_MODS')),
),
@@ -144,23 +127,20 @@ class phpbb_extension_modules_test extends phpbb_test_case
), $acp_modules);
// No specific module and module class set to an incorrect name
- $acp_modules = $this->acp_modules->get_module_infos('', 'wcp', true);
+ $acp_modules = $this->module_manager->get_module_infos('wcp', '', true);
$this->assertEquals(array(), $acp_modules);
// No specific module, no module_class set in the function parameter, and an incorrect module class
- $this->acp_modules->module_class = 'wcp';
- $acp_modules = $this->acp_modules->get_module_infos();
+ $acp_modules = $this->module_manager->get_module_infos('wcp');
$this->assertEquals(array(), $acp_modules);
// No specific module, module class set to false (will default to the above acp)
// Setting $use_all_available will cause get_module_infos() to also load not enabled extensions (vendor2/bar)
- $this->acp_modules->module_class = 'acp';
- $acp_modules = $this->acp_modules->get_module_infos('', false, true);
+ $acp_modules = $this->module_manager->get_module_infos('acp', '', true);
$this->assertEquals(array(
'vendor2\\foo\\acp\\a_module' => array(
'filename' => 'vendor2\\foo\\acp\\a_module',
'title' => 'Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')),
),
@@ -168,7 +148,6 @@ class phpbb_extension_modules_test extends phpbb_test_case
'acp_foobar' => array(
'filename' => 'acp_foobar',
'title' => 'ACP Foobar',
- 'version' => '3.1.0-dev',
'modes' => array(
'test' => array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')),
),
@@ -176,7 +155,6 @@ class phpbb_extension_modules_test extends phpbb_test_case
'vendor2\\bar\\acp\\a_module' => array(
'filename' => 'vendor2\\bar\\acp\\a_module',
'title' => 'Bar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')),
),
@@ -184,12 +162,11 @@ class phpbb_extension_modules_test extends phpbb_test_case
), $acp_modules);
// Specific module set to disabled extension
- $acp_modules = $this->acp_modules->get_module_infos('vendor2_bar_acp_a_module', 'acp', true);
+ $acp_modules = $this->module_manager->get_module_infos('acp', 'vendor2_bar_acp_a_module', true);
$this->assertEquals(array(
'vendor2\\bar\\acp\\a_module' => array(
'filename' => 'vendor2\\bar\\acp\\a_module',
'title' => 'Bar',
- 'version' => '3.1.0-dev',
'modes' => array(
'config' => array('title' => 'Config', 'auth' => '', 'cat' => array('ACP_MODS')),
),
diff --git a/tests/files/type_foo.php b/tests/files/type_foo.php
new file mode 100644
index 0000000000..95940b9d2f
--- /dev/null
+++ b/tests/files/type_foo.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\files\types;
+
+class foo extends \phpbb\files\types\remote
+{
+ static public $tempnam_path;
+}
+
+function tempnam($one, $two)
+{
+ if (empty(foo::$tempnam_path))
+ {
+ return \tempnam($one, $two);
+ }
+ else
+ {
+ return foo::$tempnam_path;
+ }
+}
diff --git a/tests/files/types_base_test.php b/tests/files/types_base_test.php
new file mode 100644
index 0000000000..e630bf8c48
--- /dev/null
+++ b/tests/files/types_base_test.php
@@ -0,0 +1,93 @@
+<?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.
+ *
+ */
+
+class phpbb_files_types_base_test extends phpbb_test_case
+{
+ private $path;
+
+ private $filesystem;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ protected function setUp()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $this->request = $this->getMock('\phpbb\request\request');
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->factory = new \phpbb\files\factory($this->container);
+
+ $this->path = __DIR__ . '/fixture/';
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function data_check_upload_size()
+ {
+ return array(
+ array('foo', '500KB', array()),
+ array('none', '500KB', array('PHP_SIZE_OVERRUN')),
+ array('none', '', array('PHP_SIZE_NA')),
+ );
+ }
+
+ /**
+ * @dataProvider data_check_upload_size
+ */
+ public function test_check_upload_size($filename, $max_filesize, $expected)
+ {
+ $php_ini = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper');
+ $php_ini->expects($this->any())
+ ->method('getString')
+ ->willReturn($max_filesize);
+ $type_form = new \phpbb\files\types\local($this->factory, $this->language, $php_ini, $this->request);
+ $file = $this->getMockBuilder('\phpbb\files\filespec')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $file->expects($this->any())
+ ->method('get')
+ ->willReturn($filename);
+ $type_form->check_upload_size($file);
+
+ $this->assertSame($expected, $file->error);
+ }
+}
diff --git a/tests/files/types_form_test.php b/tests/files/types_form_test.php
new file mode 100644
index 0000000000..925babb47f
--- /dev/null
+++ b/tests/files/types_form_test.php
@@ -0,0 +1,172 @@
+<?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.
+ *
+ */
+
+class phpbb_files_types_form_test extends phpbb_test_case
+{
+ private $path;
+
+ private $filesystem;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var \phpbb\plupload\plupload */
+ protected $plupload;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ protected function setUp()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $this->request = $this->getMock('\phpbb\request\request');
+ $this->request->expects($this->any())
+ ->method('file')
+ ->willReturn(array());
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->factory = new \phpbb\files\factory($this->container);
+ $this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->plupload->expects($this->any())
+ ->method('handle_upload')
+ ->willReturn(array());
+
+ $this->path = __DIR__ . '/fixture/';
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function data_upload_form()
+ {
+ return array(
+ array(
+ array(),
+ array(''),
+ ),
+ array(
+ array(
+ 'tmp_name' => 'foo',
+ 'name' => 'foo',
+ 'size' => 500,
+ 'type' => 'image/png',
+ 'error' => UPLOAD_ERR_PARTIAL,
+ ),
+ array('PARTIAL_UPLOAD'),
+ ),
+ array(
+ array(
+ 'tmp_name' => 'foo',
+ 'name' => 'foo',
+ 'size' => 500,
+ 'type' => 'image/png',
+ 'error' => -9,
+ ),
+ array('NOT_UPLOADED'),
+ ),
+ array(
+ array(
+ 'tmp_name' => 'foo',
+ 'name' => 'foo',
+ 'size' => 0,
+ 'type' => 'image/png',
+ ),
+ array('EMPTY_FILEUPLOAD'),
+ ),
+ array(
+ array(
+ 'tmp_name' => 'none',
+ 'name' => 'none',
+ 'size' => 50,
+ 'type' => 'image/png',
+ ),
+ array('PHP_SIZE_OVERRUN'),
+ ),
+ array(
+ array(
+ 'tmp_name' => 'tests/upload/fixture/png',
+ 'name' => 'foo.png',
+ 'size' => 500,
+ 'type' => 'image/png',
+ 'local_mode' => true,
+ ),
+ array(),
+ array('local_mode' => true),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider data_upload_form
+ */
+ public function test_upload_form($upload, $expected, $plupload = array())
+ {
+ $this->request = $this->getMock('\phpbb\request\request');
+ $this->request->expects($this->any())
+ ->method('file')
+ ->willReturn($upload);
+ $filespec = new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $this->phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ )));
+ $this->container->set('files.filespec', $filespec);
+ $this->factory = new \phpbb\files\factory($this->container);
+ $this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->plupload->expects($this->any())
+ ->method('handle_upload')
+ ->willReturn($plupload);
+
+ $type_form = new \phpbb\files\types\form($this->factory, $this->language, $this->php_ini, $this->plupload, $this->request);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('png'));
+ $type_form->set_upload($upload);
+
+
+ $file = $type_form->upload('foobar');
+ $this->assertSame($expected, $file->error);
+ $this->assertInstanceOf('\phpbb\files\filespec', $file);
+ }
+}
diff --git a/tests/files/types_local_test.php b/tests/files/types_local_test.php
new file mode 100644
index 0000000000..31070de107
--- /dev/null
+++ b/tests/files/types_local_test.php
@@ -0,0 +1,161 @@
+<?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.
+ *
+ */
+
+class phpbb_files_types_local_test extends phpbb_test_case
+{
+ private $path;
+
+ private $filesystem;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var \phpbb\plupload\plupload */
+ protected $plupload;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ protected function setUp()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $this->request = $this->getMock('\phpbb\request\request');
+ $this->request->expects($this->any())
+ ->method('file')
+ ->willReturn(array());
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->factory = new \phpbb\files\factory($this->container);
+ $this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->plupload->expects($this->any())
+ ->method('handle_upload')
+ ->willReturn(array());
+
+ $this->path = __DIR__ . '/fixture/';
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function test_upload_init_error()
+ {
+ $filespec = $this->getMockBuilder('\phpbb\files\filespec')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $filespec->expects($this->any())
+ ->method('init_error')
+ ->willReturn(true);
+ $filespec->expects($this->any())
+ ->method('set_upload_ary')
+ ->willReturnSelf();
+ $filespec->expects($this->any())
+ ->method('set_upload_namespace')
+ ->willReturnSelf();
+ $this->container->set('files.filespec', $filespec);
+ $this->factory = new \phpbb\files\factory($this->container);
+
+ $type_local = new \phpbb\files\types\local($this->factory, $this->language, $this->php_ini, $this->request);
+
+
+ $file = $type_local->upload('foo', false);
+ $this->assertSame(array(''), $file->error);
+ $this->assertInstanceOf('\phpbb\files\filespec', $file);
+ }
+
+ public function data_upload_form()
+ {
+ return array(
+ array(
+ 'foo',
+ array(
+ 'tmp_name' => 'foo',
+ 'size' => 500,
+ 'type' => 'image/png',
+ ),
+ array('NOT_UPLOADED'),
+ ),
+ array(
+ 'none',
+ false,
+ array('PHP_SIZE_OVERRUN'),
+ ),
+ array(
+ 'tests/upload/fixture/png',
+ array(
+ 'realname' => 'foo.png',
+ 'size' => 500,
+ 'type' => 'image/png',
+ 'local_mode' => true,
+ ),
+ array(),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider data_upload_form
+ */
+ public function test_upload_form($filename, $upload_ary, $expected)
+ {
+ $filespec = new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $this->phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ )));
+ $filespec_local = new ReflectionProperty($filespec, 'local');
+ $filespec_local->setAccessible(true);
+ $filespec_local->setValue($filespec, true);
+ $this->container->set('files.filespec', $filespec);
+ $this->factory = new \phpbb\files\factory($this->container);
+
+ $type_local = new \phpbb\files\types\local($this->factory, $this->language, $this->php_ini, $this->request);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('png'));
+ $type_local->set_upload($upload);
+
+
+ $file = $type_local->upload($filename, $upload_ary);
+ $this->assertSame($expected, $file->error);
+ $this->assertInstanceOf('\phpbb\files\filespec', $file);
+ }
+}
diff --git a/tests/files/types_remote_test.php b/tests/files/types_remote_test.php
new file mode 100644
index 0000000000..d103771c04
--- /dev/null
+++ b/tests/files/types_remote_test.php
@@ -0,0 +1,132 @@
+<?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.
+ *
+ */
+
+require_once dirname(__FILE__) . '/type_foo.php';
+
+class phpbb_files_types_remote_test extends phpbb_test_case
+{
+ private $path;
+
+ private $filesystem;
+
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ protected function setUp()
+ {
+ global $config, $phpbb_root_path, $phpEx;
+
+ $config = new \phpbb\config\config(array());
+ $this->config = $config;
+ $this->config->set('remote_upload_verify', 0);
+ $this->request = $this->getMock('\phpbb\request\request');
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->factory = new \phpbb\files\factory($this->container);
+
+ $this->path = __DIR__ . '/fixture/';
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function test_upload_fsock_fail()
+ {
+ $type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('png'));
+ $type_remote->set_upload($upload);
+
+ $file = $type_remote->upload('https://bärföö.com/foo.png');
+
+ $this->assertSame(array('NOT_UPLOADED'), $file->error);
+ }
+
+ public function data_get_max_file_size()
+ {
+ return array(
+ array('', 'http://example.com/foo/bar.png'),
+ array('2k', 'http://example.com/foo/bar.png'),
+ array('500k', 'http://example.com/foo/bar.png'),
+ array('500M', 'http://example.com/foo/bar.png'),
+ array('500m', 'http://example.com/foo/bar.png'),
+ array('500k', 'http://google.com/?.png', array('DISALLOWED_EXTENSION', 'DISALLOWED_CONTENT')),
+ array('1', 'http://google.com/?.png', array('WRONG_FILESIZE')),
+ array('500g', 'http://example.com/foo/bar.png'),
+ array('foobar', 'http://example.com/foo/bar.png'),
+ array('-5k', 'http://example.com/foo/bar.png'),
+ );
+ }
+
+ /**
+ * @dataProvider data_get_max_file_size
+ */
+ public function test_get_max_file_size($max_file_size, $link, $expected = array('URL_NOT_FOUND'))
+ {
+ $php_ini = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper', array('getString'));
+ $php_ini->expects($this->any())
+ ->method('getString')
+ ->willReturn($max_file_size);
+ $type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->language, $php_ini, $this->request, $this->phpbb_root_path);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('png'));
+ $type_remote->set_upload($upload);
+
+ $file = $type_remote->upload($link);
+
+ $this->assertSame($expected, $file->error);
+ }
+
+ public function test_upload_wrong_path()
+ {
+ $type_remote = new \phpbb\files\types\foo($this->config, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('png'));
+ $type_remote->set_upload($upload);
+ $type_remote::$tempnam_path = $this->phpbb_root_path . 'cache/wrong/path';
+
+ $file = $type_remote->upload('http://google.com/?.png');
+
+ $this->assertSame(array('NOT_UPLOADED'), $file->error);
+ $type_remote::$tempnam_path = '';
+ }
+}
diff --git a/tests/files/upload_test.php b/tests/files/upload_test.php
new file mode 100644
index 0000000000..c41204a0d5
--- /dev/null
+++ b/tests/files/upload_test.php
@@ -0,0 +1,128 @@
+<?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.
+ *
+ */
+
+class phpbb_files_upload_test extends phpbb_test_case
+{
+ private $path;
+
+ private $filesystem;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ protected function setUp()
+ {
+ // Global $config required by unique_id
+ global $config, $phpbb_root_path, $phpEx;
+
+ if (!is_array($config))
+ {
+ $config = array();
+ }
+
+ $config['rand_seed'] = '';
+ $config['rand_seed_last_update'] = time() + 600;
+
+ $this->request = $this->getMock('\phpbb\request\request');
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->factory = new \phpbb\files\factory($this->container);
+
+ $this->path = __DIR__ . '/fixture/';
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function test_reset_vars()
+ {
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_max_filesize(500);
+ $this->assertEquals(500, $upload->max_filesize);
+ $upload->reset_vars();
+ $this->assertEquals(0, $upload->max_filesize);
+ }
+
+ public function test_set_disallowed_content()
+ {
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $disallowed_content = new ReflectionProperty($upload, 'disallowed_content');
+ $disallowed_content->setAccessible(true);
+
+ $upload->set_disallowed_content(array('foo'));
+ $this->assertEquals(array('foo'), $disallowed_content->getValue($upload));
+ $upload->set_disallowed_content(array('foo', 'bar', 'meh'));
+ $this->assertEquals(array('foo', 'bar', 'meh'), $disallowed_content->getValue($upload));
+ $upload->set_disallowed_content('');
+ $this->assertEquals(array('foo', 'bar', 'meh'), $disallowed_content->getValue($upload));
+ $this->assertINstanceOf('\phpbb\files\upload', $upload->set_disallowed_content(array()));
+ $this->assertEquals(array(), $disallowed_content->getValue($upload));
+ $upload->reset_vars();
+ $this->assertEquals(array(), $disallowed_content->getValue($upload));
+ }
+
+ public function test_is_valid()
+ {
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $this->assertFalse($upload->is_valid('foobar'));
+ }
+
+ public function data_internal_error()
+ {
+ return array(
+ array(UPLOAD_ERR_INI_SIZE, 'PHP_SIZE_OVERRUN'),
+ array(UPLOAD_ERR_FORM_SIZE, 'WRONG_FILESIZE'),
+ array(UPLOAD_ERR_PARTIAL, 'PARTIAL_UPLOAD'),
+ array(UPLOAD_ERR_NO_FILE, 'NOT_UPLOADED'),
+ array(UPLOAD_ERR_NO_TMP_DIR, 'NO_TEMP_DIR'),
+ array(UPLOAD_ERR_CANT_WRITE, 'NO_TEMP_DIR'),
+ array(UPLOAD_ERR_EXTENSION, 'PHP_UPLOAD_STOPPED'),
+ array(9, false),
+ );
+ }
+
+ /**
+ * @dataProvider data_internal_error
+ */
+ public function test_assign_internal_error($error_code, $expected)
+ {
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $this->assertSame($expected, $upload->assign_internal_error($error_code));
+ }
+}
diff --git a/tests/filesystem/clean_path_test.php b/tests/filesystem/clean_path_test.php
index c585b17155..d2dec424b4 100644
--- a/tests/filesystem/clean_path_test.php
+++ b/tests/filesystem/clean_path_test.php
@@ -18,7 +18,7 @@ class phpbb_filesystem_clean_path_test extends phpbb_test_case
public function setUp()
{
parent::setUp();
- $this->filesystem = new \phpbb\filesystem();
+ $this->filesystem = new \phpbb\filesystem\filesystem();
}
public function clean_path_data()
diff --git a/tests/filesystem/is_absolute_test.php b/tests/filesystem/is_absolute_test.php
new file mode 100644
index 0000000000..7a50989b74
--- /dev/null
+++ b/tests/filesystem/is_absolute_test.php
@@ -0,0 +1,68 @@
+<?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.
+ *
+ */
+
+class phpbb_filesystem_is_absolute_test extends phpbb_test_case
+{
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ }
+
+ static public function is_absolute_data()
+ {
+ return array(
+ // Empty
+ array('', false),
+
+ // Absolute unix style
+ array('/etc/phpbb', true),
+ // Unix does not support \ so that is not an absolute path
+ array('\etc\phpbb', false),
+
+ // Absolute windows style
+ array('c:\windows', true),
+ array('C:\Windows', true),
+ array('c:/windows', true),
+ array('C:/Windows', true),
+
+ // Executable
+ array('etc/phpbb', false),
+ array('explorer.exe', false),
+
+ // Relative subdir
+ array('Windows\System32', false),
+ array('Windows\System32\explorer.exe', false),
+ array('Windows/System32', false),
+ array('Windows/System32/explorer.exe', false),
+
+ // Relative updir
+ array('..\Windows\System32', false),
+ array('..\Windows\System32\explorer.exe', false),
+ array('../Windows/System32', false),
+ array('../Windows/System32/explorer.exe', false),
+ );
+ }
+
+ /**
+ * @dataProvider is_absolute_data
+ */
+ public function test_is_absolute($path, $expected)
+ {
+ $this->assertEquals($expected, $this->filesystem->is_absolute_path($path));
+ }
+}
diff --git a/tests/filesystem/realpath_test.php b/tests/filesystem/realpath_test.php
new file mode 100644
index 0000000000..d994935f94
--- /dev/null
+++ b/tests/filesystem/realpath_test.php
@@ -0,0 +1,90 @@
+<?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.
+ *
+ */
+
+class phpbb_filesystem_realpath_test extends phpbb_test_case
+{
+ static protected $filesystem_own_realpath;
+
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ static public function setUpBeforeClass()
+ {
+ parent::setUpBeforeClass();
+
+ $reflection_class = new ReflectionClass('\phpbb\filesystem\filesystem');
+ self::$filesystem_own_realpath = $reflection_class->getMethod('phpbb_own_realpath');
+ self::$filesystem_own_realpath->setAccessible(true);
+ }
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ }
+
+ public function realpath_resolve_absolute_without_symlinks_data()
+ {
+ return array(
+ // Constant data
+ array(__DIR__, __DIR__),
+ array(__DIR__ . '/../filesystem/../filesystem', __DIR__),
+ array(__DIR__ . '/././', __DIR__),
+ array(__DIR__ . '/non_existent', false),
+
+ array(__FILE__, __FILE__),
+ array(__FILE__ . '../', false),
+ );
+ }
+
+ public function realpath_resolve_relative_without_symlinks_data()
+ {
+ if (!function_exists('getcwd'))
+ {
+ return array();
+ }
+
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $relative_path = $filesystem->make_path_relative(__DIR__, getcwd());
+
+ return array(
+ array($relative_path, __DIR__),
+ array($relative_path . '../filesystem/../filesystem', __DIR__),
+ array($relative_path . '././', __DIR__),
+
+ array($relative_path . 'realpath_test.php', __FILE__),
+ );
+ }
+
+ /**
+ * @dataProvider realpath_resolve_absolute_without_symlinks_data
+ */
+ public function test_realpath_absolute_without_links($path, $expected)
+ {
+ $this->assertEquals($expected, self::$filesystem_own_realpath->invoke($this->filesystem, $path));
+ }
+
+ /**
+ * @dataProvider realpath_resolve_relative_without_symlinks_data
+ */
+ public function test_realpath_relative_without_links($path, $expected)
+ {
+ if (!function_exists('getcwd'))
+ {
+ $this->markTestSkipped('phpbb_own_realpath() cannot be tested with relative paths: getcwd is not available.');
+ }
+
+ $this->assertEquals($expected, self::$filesystem_own_realpath->invoke($this->filesystem, $path));
+ }
+}
diff --git a/tests/functional/browse_test.php b/tests/functional/browse_test.php
index b9e74a280f..280e814c06 100644
--- a/tests/functional/browse_test.php
+++ b/tests/functional/browse_test.php
@@ -34,9 +34,21 @@ class phpbb_functional_browse_test extends phpbb_functional_test_case
$this->assertGreaterThan(0, $crawler->filter('.postbody')->count());
}
+ public function test_help_faq()
+ {
+ $crawler = self::request('GET', 'app.php/help/faq');
+ $this->assertGreaterThan(0, $crawler->filter('h2.faq-title')->count());
+ }
+
+ public function test_help_bbcode()
+ {
+ $crawler = self::request('GET', 'app.php/help/bbcode');
+ $this->assertGreaterThan(0, $crawler->filter('h2.faq-title')->count());
+ }
+
public function test_feed()
{
- $crawler = self::request('GET', 'feed.php', array(), false);
+ $crawler = self::request('GET', 'app.php/feed', array(), false);
self::assert_response_xml();
$this->assertGreaterThan(0, $crawler->filter('entry')->count());
}
diff --git a/tests/functional/controllers_compatibility_test.php b/tests/functional/controllers_compatibility_test.php
new file mode 100644
index 0000000000..9499888a1a
--- /dev/null
+++ b/tests/functional/controllers_compatibility_test.php
@@ -0,0 +1,56 @@
+<?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.
+*
+*/
+
+/**
+* @group functional
+*/
+
+class phpbb_functional_controllers_compatibility_test extends phpbb_functional_test_case
+{
+ public function test_report_compatibility()
+ {
+ $this->assert301('report.php?f=1&p=1', 'app.php/post/1/report');
+ $this->assert301('report.php?p=1', 'app.php/post/1/report');
+ $this->assert301('report.php?pm=1', 'app.php/pm/1/report');
+ }
+
+ public function test_feed_compatibility()
+ {
+ $this->assert301('feed.php', 'app.php/feed');
+ $this->assert301('feed.php?mode=foobar', 'app.php/feed/foobar');
+ $this->assert301('feed.php?mode=news', 'app.php/feed/news');
+ $this->assert301('feed.php?mode=topics', 'app.php/feed/topics');
+ $this->assert301('feed.php?mode=topics_news', 'app.php/feed/topics_news');
+ $this->assert301('feed.php?mode=topics_active', 'app.php/feed/topics_active');
+ $this->assert301('feed.php?mode=forums', 'app.php/feed/forums');
+ $this->assert301('feed.php?f=1', 'app.php/feed/forum/1');
+ $this->assert301('feed.php?t=1', 'app.php/feed/topic/1');
+ }
+
+ protected function assert301($from, $to)
+ {
+ self::$client->followRedirects(false);
+ self::request('GET', $from, array(), false);
+
+ // Fix sid issues
+ $location = self::$client->getResponse()->getHeader('Location');
+ $location = preg_replace('#sid=[^&]+(&(amp;)?)?#', '', $location);
+ if (substr($location, -1) === '?')
+ {
+ $location = substr($location, 0, -1);
+ }
+
+ $this->assertEquals(301, self::$client->getResponse()->getStatus());
+ $this->assertStringEndsWith($to, $location);
+ }
+}
diff --git a/tests/functional/download_test.php b/tests/functional/download_test.php
index 1e863210e6..e2f1d065be 100644
--- a/tests/functional/download_test.php
+++ b/tests/functional/download_test.php
@@ -11,10 +11,7 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
/**
* @group functional
diff --git a/tests/functional/extension_module_test.php b/tests/functional/extension_module_test.php
index ee084720e4..95107665cd 100644
--- a/tests/functional/extension_module_test.php
+++ b/tests/functional/extension_module_test.php
@@ -49,8 +49,9 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case
$this->phpbb_extension_manager = $this->get_extension_manager();
$this->phpbb_extension_manager->enable('foo/bar');
- $modules = new acp_modules();
$db = $this->get_db();
+ $cache = $this->get_cache_driver();
+ $modules = new \phpbb\module\module_manager($cache, $db, $this->phpbb_extension_manager, MODULES_TABLE, dirname(__FILE__) . '/../../phpBB/', 'php');
$sql = 'SELECT module_id
FROM ' . MODULES_TABLE . "
@@ -70,7 +71,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case
'module_mode' => '',
'module_auth' => '',
);
- $modules->update_module_data($parent_data, true);
+ $modules->update_module_data($parent_data);
$module_data = array(
'module_basename' => 'foo\\bar\\acp\\main_module',
@@ -82,7 +83,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case
'module_mode' => 'mode',
'module_auth' => '',
);
- $modules->update_module_data($module_data, true);
+ $modules->update_module_data($module_data);
$parent_data = array(
'module_basename' => '',
@@ -94,7 +95,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case
'module_mode' => '',
'module_auth' => '',
);
- $modules->update_module_data($parent_data, true);
+ $modules->update_module_data($parent_data);
$module_data = array(
'module_basename' => 'foo\\bar\\ucp\\main_module',
@@ -106,7 +107,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case
'module_mode' => 'mode',
'module_auth' => '',
);
- $modules->update_module_data($module_data, true);
+ $modules->update_module_data($module_data);
$this->purge_cache();
}
diff --git a/tests/functional/feed_test.php b/tests/functional/feed_test.php
index e48dfc043a..3792b0a23c 100644
--- a/tests/functional/feed_test.php
+++ b/tests/functional/feed_test.php
@@ -30,9 +30,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
{
parent::__construct($name, $data, $dataName);
- $this->backupStaticAttributesBlacklist += array(
- 'phpbb_functional_feed_test' => array('init_values'),
- );
+ $this->backupStaticAttributesBlacklist['phpbb_functional_feed_test'] = array('init_values');
+
+ $this->purge_cache();
}
public function test_setup_config_before_state()
@@ -61,66 +61,64 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form->setValues($values);
$crawler = self::submit($form);
- $this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());
+ self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());
// Special config (Guest can't see attachments)
$this->add_lang('acp/permissions');
$crawler = self::request('GET', "adm/index.php?i=acp_permissions&sid={$this->sid}&icat=16&mode=setting_group_global&group_id[0]=1");
- $this->assertContains($this->lang('ACL_SET'), $crawler->filter('h1')->eq(1)->text());
+ self::assertContains($this->lang('ACL_SET'), $crawler->filter('h1')->eq(1)->text());
$form = $crawler->selectButton($this->lang('APPLY_PERMISSIONS'))->form();
$form['setting[1][0][u_download]']->select(-1);
$crawler = self::submit($form);
- $this->assertContainsLang('AUTH_UPDATED', $crawler->filter('.successbox')->text());
+ self::assertContainsLang('AUTH_UPDATED', $crawler->filter('.successbox')->text());
}
public function test_dump_board_state()
{
- $crawler = self::request('GET', 'feed.php?mode=forums', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/forums', array(), false);
self::assert_response_xml();
self::$init_values['disapprove_user']['forums_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=overall', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/overall', array(), false);
self::assert_response_xml();
self::$init_values['disapprove_user']['overall_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=topics', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/topics', array(), false);
self::assert_response_xml();
self::$init_values['disapprove_user']['topics_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=topics_new', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/topics_new', array(), false);
self::assert_response_xml();
self::$init_values['disapprove_user']['topics_new_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=topics_active', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/topics_active', array(), false);
self::assert_response_xml();
self::$init_values['disapprove_user']['topics_active_value'] = $crawler->filterXPath('//entry')->count();
$this->login();
- $crawler = self::request('GET', 'feed.php?mode=forums', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/forums', array(), false);
self::assert_response_xml();
self::$init_values['admin']['forums_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=overall', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/overall', array(), false);
self::assert_response_xml();
self::$init_values['admin']['overall_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=topics', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/topics', array(), false);
self::assert_response_xml();
self::$init_values['admin']['topics_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=topics_new', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/topics_new', array(), false);
self::assert_response_xml();
self::$init_values['admin']['topics_new_value'] = $crawler->filterXPath('//entry')->count();
- $crawler = self::request('GET', 'feed.php?mode=topics_active', array(), false);
+ $crawler = self::request('GET', 'app.php/feed/topics_active', array(), false);
self::assert_response_xml();
self::$init_values['admin']['topics_active_value'] = $crawler->filterXPath('//entry')->count();
-
-
}
public function test_setup_forums()
@@ -138,7 +136,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form = $crawler->selectButton('update')->form(array(
'forum_perm_from' => 2,
));
- $crawler = self::submit($form);
+ self::submit($form);
$this->load_ids(array(
'forums' => array(
@@ -155,7 +153,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form = $crawler->selectButton('update')->form(array(
'forum_perm_from' => 2,
));
- $crawler = self::submit($form);
+ self::submit($form);
// 'Feeds #news' will be used for feed.php?mode=news
$crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}");
@@ -166,9 +164,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form = $crawler->selectButton('update')->form(array(
'forum_perm_from' => 2,
));
- $crawler = self::submit($form);
+ self::submit($form);
- // 'Feeds #exclude' will not be displayed on feed.php?mode=forums
+ // 'Feeds #exclude' will not be displayed on app.php/feed/forums
$crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}");
$form = $crawler->selectButton('addforum')->form(array(
'forum_name' => 'Feeds #exclude',
@@ -177,7 +175,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form = $crawler->selectButton('update')->form(array(
'forum_perm_from' => 2,
));
- $crawler = self::submit($form);
+ self::submit($form);
}
public function test_setup_config_after_forums()
@@ -201,7 +199,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form['feed_exclude_id']->select(array($this->data['forums']['Feeds #exclude']));
$crawler = self::submit($form);
- $this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());
+ self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());
}
public function test_feeds_empty()
@@ -272,6 +270,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
'id' => $this->data['forums']['Feeds #exclude'],
'contents_lang' => array('NO_FEED'),
'invalid' => true,
+ 'response_code' => 404,
),
),
't' => array(
@@ -279,6 +278,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
'id' => $this->data['topics']['Feeds #exclude - Topic #1'],
'contents_lang' => array('NO_FEED'),
'invalid' => true,
+ 'response_code' => 404,
),
),
'overall' => array(
@@ -331,7 +331,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$post = $this->create_topic($this->data['forums']['Feeds #news'], 'Feeds #news - Topic #2', 'This is a test topic posted by the testing framework.');
$crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}");
- $this->assertContains('Feeds #news - Topic #2', $crawler->filter('html')->text());
+ self::assertContains('Feeds #news - Topic #2', $crawler->filter('html')->text());
$this->data['topics']['Feeds #news - Topic #2'] = (int) $post['topic_id'];
$this->data['posts']['Feeds #news - Topic #2'] = (int) $this->get_parameter_from_link($crawler->filter('.post')->selectLink($this->lang('POST', '', ''))->link()->getUri(), 'p');
@@ -339,7 +339,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$post2 = $this->create_post($this->data['forums']['Feeds #news'], $post['topic_id'], 'Re: Feeds #news - Topic #2', 'This is a test post posted by the testing framework.');
$crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}");
- $this->assertContains('Re: Feeds #news - Topic #2', $crawler->filter('html')->text());
+ self::assertContains('Re: Feeds #news - Topic #2', $crawler->filter('html')->text());
$this->data['posts']['Re: Feeds #news - Topic #2'] = (int) $post2['post_id'];
}
@@ -495,7 +495,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$post2 = $this->create_post($this->data['forums']['Feeds #1'], $post['topic_id'], 'Re: Feeds #1 - Topic #2', 'This is a test post posted by the testing framework.');
$crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}");
- $this->assertContains('Re: Feeds #1 - Topic #2', $crawler->filter('html')->text());
+ self::assertContains('Re: Feeds #1 - Topic #2', $crawler->filter('html')->text());
$this->data['posts']['Re: Feeds #1 - Topic #2'] = (int) $post2['post_id'];
}
@@ -516,14 +516,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$this->add_lang('posting');
$crawler = self::request('GET', "posting.php?mode=delete&f={$this->data['forums']['Feeds #1']}&p={$this->data['posts']['Re: Feeds #1 - Topic #2']}&sid={$this->sid}");
- $this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text());
+ self::assertContainsLang('DELETE_PERMANENTLY', $crawler->text());
$form = $crawler->selectButton('Yes')->form();
$crawler = self::submit($form);
- $this->assertContainsLang('POST_DELETED', $crawler->text());
+ self::assertContainsLang('POST_DELETED', $crawler->text());
$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1 - Topic #2']}&sid={$this->sid}");
- $this->assertContains($this->lang('POST_DISPLAY', '', ''), $crawler->text());
+ self::assertContains($this->lang('POST_DISPLAY', '', ''), $crawler->text());
}
public function test_feeds_softdeleted_post_admin()
@@ -615,15 +615,15 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$this->add_lang('posting');
$crawler = $this->get_quickmod_page($this->data['topics']['Feeds #1 - Topic #2'], 'DELETE_TOPIC');
- $this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text());
+ self::assertContainsLang('DELETE_PERMANENTLY', $crawler->text());
$this->add_lang('mcp');
$form = $crawler->selectButton('Yes')->form();
$crawler = self::submit($form);
- $this->assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text());
+ self::assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text());
$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1 - Topic #2']}&sid={$this->sid}");
- $this->assertContains('Feeds #1 - Topic #2', $crawler->filter('h2')->text());
+ self::assertContains('Feeds #1 - Topic #2', $crawler->filter('h2')->text());
}
public function test_feeds_softdeleted_topic_admin()
@@ -716,8 +716,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
't' => array(
array(
'id' => $this->data['topics']['Feeds #1 - Topic #2'],
- 'contents_lang' => array('SORRY_AUTH_READ'),
+ 'contents_lang' => array('SORRY_AUTH_READ_TOPIC'),
'invalid' => true,
+ 'response_code' => 403,
),
),
'overall' => array(
@@ -758,10 +759,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
// Test creating a reply
$this->login('disapprove_user');
- $post2 = $this->create_post($this->data['forums']['Feeds #1.1'], $post['topic_id'], 'Re: Feeds #1.1 - Topic #2', 'This is a test post posted by the testing framework.', array(), 'POST_STORED_MOD');
+ $this->create_post($this->data['forums']['Feeds #1.1'], $post['topic_id'], 'Re: Feeds #1.1 - Topic #2', 'This is a test post posted by the testing framework.', array(), 'POST_STORED_MOD');
$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1.1 - Topic #2']}&sid={$this->sid}");
- $this->assertNotContains('Re: Feeds #1.1 - Topic #2', $crawler->filter('html')->text());
+ self::assertNotContains('Re: Feeds #1.1 - Topic #2', $crawler->filter('html')->text());
}
public function test_feeds_unapproved_post_admin()
@@ -853,7 +854,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$this->data['topics']['Feeds #1 - Topic #3'] = (int) $post['topic_id'];
$crawler = self::request('GET', "viewforum.php?f={$this->data['forums']['Feeds #1.1']}&sid={$this->sid}");
- $this->assertNotContains('Feeds #1.1 - Topic #3', $crawler->filter('html')->text());
+ self::assertNotContains('Feeds #1.1 - Topic #3', $crawler->filter('html')->text());
$this->logout();
$this->set_flood_interval(15);
@@ -869,10 +870,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$form = $crawler->selectButton('Submit')->form();
$values = $form->getValues();
- $values["config[flood_interval]"] = $flood_interval;
+ $values['config[flood_interval]'] = $flood_interval;
$form->setValues($values);
$crawler = self::submit($form);
- $this->assertGreaterThan(0, $crawler->filter('.successbox')->count());
+ self::assertGreaterThan(0, $crawler->filter('.successbox')->count());
$this->logout();
}
@@ -964,8 +965,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
't' => array(
array(
'id' => $this->data['topics']['Feeds #1.1 - Topic #3'],
- 'contents_lang' => array('SORRY_AUTH_READ'),
+ 'contents_lang' => array('SORRY_AUTH_READ_TOPIC'),
'invalid' => true,
+ 'response_code' => 403,
),
),
'overall' => array(
@@ -1004,7 +1006,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$post = $this->create_topic($this->data['forums']['Feeds #1'], 'Feeds #1 - Topic #3', 'This is a test topic posted by the testing framework. [attachment=0]Attachment #0[/attachment]', array('upload_files' => 1));
$crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}");
- $this->assertContains('Feeds #1 - Topic #3', $crawler->filter('html')->text());
+ self::assertContains('Feeds #1 - Topic #3', $crawler->filter('html')->text());
$this->data['topics']['Feeds #1 - Topic #3'] = (int) $post['topic_id'];
}
@@ -1222,7 +1224,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$post2 = $this->create_post($this->data['forums']['Feeds #1'], $this->data['topics']['Feeds #1 - Topic #3'], 'Re: Feeds #1 - Topic #3-1', 'This is a test post posted by the testing framework. [attachment=0]Attachment #0[/attachment]');
$crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}");
- $this->assertContains('Re: Feeds #1 - Topic #3-1', $crawler->filter('html')->text());
+ self::assertContains('Re: Feeds #1 - Topic #3-1', $crawler->filter('html')->text());
$this->data['posts']['Re: Feeds #1 - Topic #3-1'] = (int) $post2['post_id'];
}
@@ -1322,9 +1324,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
{
foreach ($feeds as $feed_data)
{
- if ($mode === 'f' || $mode === 't')
+ if ($mode === 'f')
+ {
+ $params = "/forum/{$feed_data['id']}";
+ $this->assert_feed($params, $feed_data);
+ }
+ else if ($mode === 't')
{
- $params = "?{$mode}={$feed_data['id']}";
+ $params = "/topic/{$feed_data['id']}";
$this->assert_feed($params, $feed_data);
}
else
@@ -1348,10 +1355,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
case 'news':
break;
default:
- $this->fail('Unsupported feed mode: ' . $mode);
+ self::fail('Unsupported feed mode: ' . $mode);
}
- $params = "?mode={$mode}";
+ $params = "/{$mode}";
$this->assert_feed($params, $feed_data);
}
}
@@ -1360,19 +1367,19 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
protected function assert_feed($params, $data)
{
- $crawler = self::request('GET', 'feed.php' . $params, array(), false);
+ $crawler = self::request('GET', 'app.php/feed' . $params, array(), false);
if (empty($data['invalid']))
{
self::assert_response_xml();
- $this->assertEquals($data['nb_entries'], $crawler->filter('entry')->count(), "Tested feed : 'feed.php{$params}'");
+ self::assertEquals($data['nb_entries'], $crawler->filter('entry')->count(), "Tested feed : 'app.php/feed{$params}'");
if (!empty($data['xpath']))
{
foreach($data['xpath'] as $xpath => $count_expected)
{
- $this->assertCount($count_expected, $crawler->filterXPath($xpath), "Tested feed : 'feed.php{$params}', Search for {$xpath}");
+ self::assertCount($count_expected, $crawler->filterXPath($xpath), "Tested feed : 'app.php/feed{$params}', Search for {$xpath}");
}
}
@@ -1381,7 +1388,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
foreach($data['contents'] as $entry_id => $string)
{
$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();
- $this->assertContains($string, $content, "Tested feed : 'feed.php{$params}'");
+ self::assertContains($string, $content, "Tested feed : 'app.php/feed{$params}'");
}
}
@@ -1390,7 +1397,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
foreach($data['contents_lang'] as $entry_id => $string)
{
$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();
- $this->assertContainsLang($string, $content, "Tested feed : 'feed.php{$params}'");
+ self::assertContainsLang($string, $content, "Tested feed : 'app.php/feed{$params}'");
}
}
@@ -1398,21 +1405,21 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
{
foreach($data['attachments'] as $entry_id => $attachments)
{
+ $content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();
foreach ($attachments as $i => $attachment)
{
- $content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();
$url = self::$root_url . "download/file.php?id={$attachment['id']}";
$string = "Attachment #{$i}";
if ($attachment['displayed'])
{
- $this->assertContains($url, $content, "Tested feed : 'feed.php{$params}'");
- $this->assertNotContains($string, $content, "Tested feed : 'feed.php{$params}'");
+ self::assertContains($url, $content, "Tested feed : 'app.php/feed{$params}'");
+ self::assertNotContains($string, $content, "Tested feed : 'app.php/feed{$params}'");
}
else
{
- $this->assertContains($string, $content, "Tested feed : 'feed.php{$params}'");
- $this->assertNotContains($url, $content, "Tested feed : 'feed.php{$params}'");
+ self::assertContains($string, $content, "Tested feed : 'app.php/feed{$params}'");
+ self::assertNotContains($url, $content, "Tested feed : 'app.php/feed{$params}'");
}
}
}
@@ -1420,14 +1427,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
}
else
{
- self::assert_response_html();
+ self::assert_response_html($data['response_code'] ?: 202);
if (!empty($data['contents_lang']))
{
+ $content = $crawler->filter('html')->text();
foreach($data['contents_lang'] as $string)
{
- $content = $crawler->filter('html')->text();
- $this->assertContainsLang($string, $content, "Tested feed : 'feed.php{$params}'");
+ self::assertContainsLang($string, $content, "Tested feed : 'app.php/feed{$params}'");
}
}
}
@@ -1445,7 +1452,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- if (in_array($row['forum_name'], $data['forums']))
+ if (in_array($row['forum_name'], $data['forums'], false))
{
$this->data['forums'][$row['forum_name']] = (int) $row['forum_id'];
}
@@ -1461,7 +1468,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- if (in_array($row['topic_title'], $data['topics']))
+ if (in_array($row['topic_title'], $data['topics'], false))
{
$this->data['topics'][$row['topic_title']] = (int) $row['topic_id'];
}
@@ -1478,7 +1485,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
- if (in_array($row['post_subject'], $data['posts']))
+ if (in_array($row['post_subject'], $data['posts'], false))
{
$this->data['posts'][$row['post_subject']] = (int) $row['post_id'];
$post_ids[] = (int) $row['post_id'];
diff --git a/tests/functional/fileupload_remote_test.php b/tests/functional/fileupload_remote_test.php
index 6ece150b23..b70d49cddd 100644
--- a/tests/functional/fileupload_remote_test.php
+++ b/tests/functional/fileupload_remote_test.php
@@ -11,13 +11,29 @@
*
*/
-require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';
-
/**
* @group functional
*/
class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
{
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
public function setUp()
{
parent::setUp();
@@ -25,19 +41,28 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
// URL
// Global $config required by unique_id
- // Global $user required by fileupload::remote_upload
- global $config, $user;
+ global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
- $config = array();
+ $config = new \phpbb\config\config(array());
}
$config['rand_seed'] = '';
$config['rand_seed_last_update'] = time() + 600;
+ $config['remote_upload_verify'] = 0;
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $this->request = $this->getMock('\phpbb\request\request');
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
- $user = new phpbb_mock_user();
- $user->lang = new phpbb_mock_lang();
+ $container = new phpbb_mock_container_builder();
+ $container->set('files.filespec', new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path));
+ $this->factory = new \phpbb\files\factory($container);
+ $container->set('files.factory', $this->factory);
+ $container->set('files.types.remote', new \phpbb\files\types\remote($config, $this->factory, $this->language, $this->php_ini, $this->request, $phpbb_root_path));
+ $this->phpbb_root_path = $phpbb_root_path;
}
public function tearDown()
@@ -49,30 +74,47 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
public function test_invalid_extension()
{
- $upload = new fileupload('', array('jpg'), 100);
- $file = $upload->remote_upload(self::$root_url . 'develop/blank.gif');
+ /** @var \phpbb\files\upload $upload */
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_error_prefix('')
+ ->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(100);
+ $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/blank.gif');
$this->assertEquals('URL_INVALID', $file->error[0]);
}
public function test_empty_file()
{
- $upload = new fileupload('', array('jpg'), 100);
- $file = $upload->remote_upload(self::$root_url . 'develop/blank.jpg');
+ /** @var \phpbb\files\upload $upload */
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_error_prefix('')
+ ->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(100);
+ $file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/blank.jpg');
$this->assertEquals('EMPTY_REMOTE_DATA', $file->error[0]);
}
public function test_successful_upload()
{
- $upload = new fileupload('', array('gif'), 1000);
- $file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
+ /** @var \phpbb\files\upload $upload */
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_error_prefix('')
+ ->set_allowed_extensions(array('gif'))
+ ->set_max_filesize(1000);
+ $file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
$this->assertEquals(0, sizeof($file->error));
- $this->assertTrue(file_exists($file->filename));
+ $this->assertTrue(file_exists($file->get('filename')));
+ $this->assertTrue($file->is_uploaded());
}
public function test_too_large()
{
- $upload = new fileupload('', array('gif'), 100);
- $file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
+ /** @var \phpbb\files\upload $upload */
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_error_prefix('')
+ ->set_allowed_extensions(array('gif'))
+ ->set_max_filesize(100);
+ $file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
$this->assertEquals(1, sizeof($file->error));
$this->assertEquals('WRONG_FILESIZE', $file->error[0]);
}
diff --git a/tests/functional/fixtures/ext/foo/bar/acp/main_info.php b/tests/functional/fixtures/ext/foo/bar/acp/main_info.php
index ec378e0e75..371ab7c967 100644
--- a/tests/functional/fixtures/ext/foo/bar/acp/main_info.php
+++ b/tests/functional/fixtures/ext/foo/bar/acp/main_info.php
@@ -28,7 +28,6 @@ class main_info
return array(
'filename' => 'foo\bar\acp\main_module',
'title' => 'ACP_FOOBAR_TITLE',
- 'version' => '1.0.0',
'modes' => array(
'mode' => array('title' => 'ACP_FOOBAR_MODE', 'auth' => '', 'cat' => array('ACP_FOOBAR_TITLE')),
),
diff --git a/tests/functional/fixtures/ext/foo/bar/config/services.yml b/tests/functional/fixtures/ext/foo/bar/config/services.yml
index d35be7955a..495c775a1f 100644
--- a/tests/functional/fixtures/ext/foo/bar/config/services.yml
+++ b/tests/functional/fixtures/ext/foo/bar/config/services.yml
@@ -2,13 +2,13 @@ services:
foo_bar.controller:
class: foo\bar\controller\controller
arguments:
- - @controller.helper
- - @path_helper
- - @template
- - @config
- - @user
- - %core.root_path%
- - %core.php_ext%
+ - '@controller.helper'
+ - '@path_helper'
+ - '@template'
+ - '@config'
+ - '@user'
+ - '%core.root_path%'
+ - '%core.php_ext%'
foo_bar.listener.permission:
class: foo\bar\event\permission
diff --git a/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php b/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php
index d34244f800..4c74442639 100644
--- a/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php
+++ b/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php
@@ -20,7 +20,6 @@ class main_info
return array(
'filename' => '\foo\bar\ucp\main_module',
'title' => 'ACP_FOOBAR_TITLE',
- 'version' => '1.0.0',
'modes' => array(
'mode' => array('title' => 'ACP_FOOBAR_MODE', 'auth' => '', 'cat' => array('ACP_FOOBAR_TITLE')),
),
diff --git a/tests/functional/forum_style_test.php b/tests/functional/forum_style_test.php
index 65be94f4d0..b3c1115b7f 100644
--- a/tests/functional/forum_style_test.php
+++ b/tests/functional/forum_style_test.php
@@ -16,16 +16,28 @@
*/
class phpbb_functional_forum_style_test extends phpbb_functional_test_case
{
+ public function test_font_awesome_style()
+ {
+ $crawler = self::request('GET', 'viewtopic.php?t=1&f=2');
+ $this->assertContains('font-awesome.min', $crawler->filter('head > link[rel=stylesheet]')->eq(0)->attr('href'));
+
+ $crawler = self::request('GET', 'viewtopic.php?t=1');
+ $this->assertContains('font-awesome.min', $crawler->filter('head > link[rel=stylesheet]')->eq(0)->attr('href'));
+
+ $crawler = self::request('GET', 'viewtopic.php?t=1&view=next');
+ $this->assertContains('font-awesome.min', $crawler->filter('head > link[rel=stylesheet]')->eq(0)->attr('href'));
+ }
+
public function test_default_forum_style()
{
$crawler = self::request('GET', 'viewtopic.php?t=1&f=2');
- $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
+ $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1');
- $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
+ $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1&view=next');
- $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
+ $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));
}
public function test_custom_forum_style()
@@ -35,13 +47,13 @@ class phpbb_functional_forum_style_test extends phpbb_functional_test_case
$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 2 WHERE forum_id = 2');
$crawler = self::request('GET', 'viewtopic.php?t=1&f=2');
- $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
+ $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1');
- $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
+ $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1&view=next');
- $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
+ $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));
$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 0 WHERE forum_id = 2');
$this->delete_style(2, 'test_style');
diff --git a/tests/functional/notification_test.php b/tests/functional/notification_test.php
index d4c61cc062..8751de8016 100644
--- a/tests/functional/notification_test.php
+++ b/tests/functional/notification_test.php
@@ -21,15 +21,15 @@ class phpbb_functional_notification_test extends phpbb_functional_test_case
return array(
// Rows inserted by phpBB/install/schemas/schema_data.sql
// Also see PHPBB3-11460
- array('notification.type.post_notification', true),
- array('notification.type.topic_notification', true),
+ array('notification.type.post_notification.method.board', true),
+ array('notification.type.topic_notification.method.board', true),
array('notification.type.post_notification.method.email', true),
array('notification.type.topic_notification.method.email', true),
// Default behaviour for in-board notifications:
// If user did not opt-out, in-board notifications are on.
- array('notification.type.bookmark_notification', true),
- array('notification.type.quote_notification', true),
+ array('notification.type.bookmark_notification.method.board', true),
+ array('notification.type.quote_notification.method.board', true),
// Default behaviour for email notifications:
// If user did not opt-in, email notifications are off.
diff --git a/tests/functional/permission_roles_test.php b/tests/functional/permission_roles_test.php
new file mode 100644
index 0000000000..e6506fb37c
--- /dev/null
+++ b/tests/functional/permission_roles_test.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.
+*
+*/
+
+/**
+* @group functional
+*/
+class functional_permission_roles_test extends phpbb_functional_test_case
+{
+ public function data_permission_roles()
+ {
+ return array(
+ array(
+ array(0, 14),
+ array(17, 17),
+ array(
+ 'role[5][1]' => 14,
+ )
+ ),
+ array(
+ array(14, 14),
+ array(17, 17),
+ array(
+ 'role[5][1]' => 0,
+ )
+ ),
+ array(
+ array(0, 14),
+ array(17, 17)
+ ),
+ );
+ }
+ /**
+ * @dataProvider data_permission_roles
+ */
+ public function test_permission_roles($admin_roles, $guest_roles, $set_values = array())
+ {
+ $this->login();
+ $this->admin_login();
+ $this->add_lang('acp/permissions');
+ $crawler = self::request('GET', 'adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid);
+
+ // Select forums
+ $form = $crawler->filter('form[id=select_victim]')->form();
+ $form['forum_id']->setValue(array(1,2));
+ $crawler = self::$client->submit($form);
+
+ // Select administrators and guests
+ $groups_form = $crawler->filter('form[id=groups]')->form();
+ $groups_form['group_id']->setValue(array(1,5));
+
+ $crawler = self::submit($groups_form);
+ $form = $crawler->filter('form')->form();
+ $values = $form->getValues();
+
+ // Check default settings
+ $this->assertEquals($admin_roles[0], $values['role[5][1]']);
+ $this->assertEquals($admin_roles[1], $values['role[5][2]']);
+ $this->assertEquals($guest_roles[0], $values['role[1][1]']);
+ $this->assertEquals($guest_roles[1], $values['role[1][2]']);
+
+ // Set admin to full access on category
+ foreach ($set_values as $key => $value)
+ {
+ $form[$key]->setValue($value);
+ }
+
+ $form_values = $form->getValues();
+ $form_values['action[apply_all_permissions]'] = true;
+ $crawler = self::request('POST', 'adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid, $form_values);
+ $this->assertContainsLang('AUTH_UPDATED', $crawler->text());
+
+ $this->logout();
+ }
+}
diff --git a/tests/functional/plupload_test.php b/tests/functional/plupload_test.php
index d358681ad1..9d284a7e57 100644
--- a/tests/functional/plupload_test.php
+++ b/tests/functional/plupload_test.php
@@ -107,11 +107,11 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case
if ($i < self::CHUNKS - 1)
{
- $this->assertContains('{"jsonrpc":"2.0","id":"id","result":null}', self::$client->getResponse()->getContent());
+ $this->assertContains('{"jsonrpc":"2.0","id":"id","result":null}', self::get_content());
}
else
{
- $response = json_decode(self::$client->getResponse()->getContent(), true);
+ $response = json_decode(self::get_content(), true);
$this->assertEquals('valid.jpg', $response['data'][0]['real_filename']);
}
@@ -134,7 +134,8 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case
'error' => UPLOAD_ERR_OK,
);
- $crawler = self::$client->request(
+ self::$client->setServerParameter('HTTP_X_PHPBB_USING_PLUPLOAD', '1');
+ self::$client->request(
'POST',
$url . '&sid=' . $this->sid,
array(
@@ -144,11 +145,10 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case
'real_filename' => 'valid.jpg',
'add_file' => $this->lang('ADD_FILE'),
),
- array('fileupload' => $file),
- array('X-PHPBB-USING-PLUPLOAD' => '1')
+ array('fileupload' => $file)
);
- $response = json_decode(self::$client->getResponse()->getContent(), true);
+ $response = json_decode(self::get_content(), true);
$this->assertEquals('valid.jpg', $response['data'][0]['real_filename']);
}
}
diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php
index 914233240e..9dd8a1dc91 100644
--- a/tests/functional/posting_test.php
+++ b/tests/functional/posting_test.php
@@ -45,14 +45,6 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case
self::create_post(2,
1,
- 'Unsupported characters',
- "This is a test with these weird characters: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6",
- array(),
- 'Your message contains the following unsupported characters'
- );
-
- self::create_post(2,
- 1,
"Unsupported: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6",
'This is a test with emoji characters in the topic title.',
array(),
@@ -60,6 +52,40 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case
);
}
+ public function test_supported_unicode_characters()
+ {
+ $this->login();
+
+ $post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.');
+ $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', "This is a test with these weird characters: \xF0\x9F\x84\x90 \xF0\x9F\x84\x91");
+ $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}");
+ $this->assertContains("\xF0\x9F\x84\x90 \xF0\x9F\x84\x91", $crawler->text());
+ }
+
+ public function test_html_entities()
+ {
+ $this->login();
+
+ $post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.');
+ $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', '&#128512;');
+ $crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}");
+ $this->assertContains('&#128512;', $crawler->text());
+ }
+
+ public function test_quote()
+ {
+ $text = 'Test post </textarea>"\' &&amp;amp;';
+ $expected = "(\\[quote=admin[^\\]]*\\]\n" . preg_quote($text) . "\n\\[/quote\\])";
+
+ $this->login();
+ $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic');
+ $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text);
+
+ $crawler = self::request('GET', "posting.php?mode=quote&f=2&t={$post['topic_id']}&p={$post['post_id']}&sid={$this->sid}");
+
+ $this->assertRegexp($expected, $crawler->filter('textarea#message')->text());
+ }
+
/**
* @testdox max_quote_depth is applied to the text populating the posting form
*/
@@ -67,10 +93,10 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case
{
$text = '0[quote]1[quote]2[/quote]1[/quote]0';
$expected = array(
- 0 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]',
- 1 => '[quote="admin"]00[/quote]',
- 2 => '[quote="admin"]0[quote]11[/quote]0[/quote]',
- 3 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]',
+ 0 => '0[quote]1[quote]2[/quote]1[/quote]0',
+ 1 => '00',
+ 2 => '0[quote]11[/quote]0',
+ 3 => '0[quote]1[quote]2[/quote]1[/quote]0',
);
$this->login();
@@ -83,7 +109,10 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case
{
$this->set_quote_depth($quote_depth);
$crawler = self::request('GET', $quote_url);
- $this->assertContains($expected_text, $crawler->filter('textarea#message')->text());
+ $this->assertRegexp(
+ "(\\[quote=admin[^\\]]*\\]\n?" . preg_quote($expected_text) . "\n?\\[/quote\\])",
+ $crawler->filter('textarea#message')->text()
+ );
}
}
@@ -156,4 +185,65 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case
$crawler = self::submit($form);
$this->assertEquals(1, $crawler->filter('.successbox')->count());
}
+
+ public function test_ticket_8420()
+ {
+ $text = '[b][url=http://example.org] :arrow: here[/url][/b]';
+
+ $this->login();
+ $crawler = self::request('GET', 'posting.php?mode=post&f=2');
+ $form = $crawler->selectButton('Preview')->form(array(
+ 'subject' => 'Test subject',
+ 'message' => $text
+ ));
+ $crawler = self::submit($form);
+ $this->assertEquals($text, $crawler->filter('#message')->text());
+ }
+
+ public function test_old_signature_in_preview()
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_sig = '[b:2u8sdcwb]My signature[/b:2u8sdcwb]',
+ user_sig_bbcode_uid = '2u8sdcwb',
+ user_sig_bbcode_bitfield = 'QA=='
+ WHERE user_id = 2";
+ $this->get_db()->sql_query($sql);
+
+ $this->login();
+ $crawler = self::request('GET', 'posting.php?mode=post&f=2');
+ $form = $crawler->selectButton('Preview')->form(array(
+ 'subject' => 'Test subject',
+ 'message' => 'My post',
+ ));
+ $crawler = self::submit($form);
+ $this->assertContains(
+ '<span style="font-weight: bold">My signature</span>',
+ $crawler->filter('#preview .signature')->html()
+ );
+ }
+
+ /**
+ * @ticket PHPBB3-10628
+ */
+ public function test_www_links_preview()
+ {
+ $text = 'www.example.org';
+ $url = 'http://' . $text;
+
+ $this->add_lang('posting');
+ $this->login();
+
+ $crawler = self::request('GET', 'posting.php?mode=post&f=2');
+ $form = $crawler->selectButton('Preview')->form(array(
+ 'subject' => 'Test subject',
+ 'message' => $text
+ ));
+ $crawler = self::submit($form);
+
+ // Test that the textarea remains unchanged
+ $this->assertEquals($text, $crawler->filter('#message')->text());
+
+ // Test that the preview contains the correct link
+ $this->assertEquals($url, $crawler->filter('#preview a')->attr('href'));
+ }
}
diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php
index 1f6dc3a979..7fda26fb49 100644
--- a/tests/functional/private_messages_test.php
+++ b/tests/functional/private_messages_test.php
@@ -66,4 +66,45 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case
$crawler = self::submit($form);
$this->assertContains($this->lang('CONFIG_UPDATED'), $crawler->filter('.successbox')->text());
}
+
+ public function test_quote_post()
+ {
+ $text = 'Test post';
+
+ $this->login();
+ $topic = $this->create_topic(2, 'Test Topic 1', 'Test topic');
+ $post = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text);
+
+ $expected = '(\\[quote=admin post_id=' . $post['post_id'] . ' time=\\d+ user_id=2\\]' . $text . '\\[/quote\\])';
+
+ $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quotepost&p=' . $post['post_id'] . '&sid=' . $this->sid);
+
+ $this->assertRegexp($expected, $crawler->filter('textarea#message')->text());
+ }
+
+ public function test_quote_pm()
+ {
+ $text = 'This is a test private message sent by the testing framework.';
+ $expected = "(\\[quote=admin time=\\d+ user_id=2\\]\n" . $text . "\n\\[/quote\\])";
+
+ $this->login();
+ $message_id = $this->create_private_message('Test', $text, array(2));
+
+ $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quote&p=' . $message_id . '&sid=' . $this->sid);
+
+ $this->assertRegexp($expected, $crawler->filter('textarea#message')->text());
+ }
+
+ public function test_quote_forward()
+ {
+ $text = 'This is a test private message sent by the testing framework.';
+ $expected = "[quote=admin]\n" . $text . "\n[/quote]";
+
+ $this->login();
+ $message_id = $this->create_private_message('Test', $text, array(2));
+
+ $crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=forward&f=0&p=' . $message_id . '&sid=' . $this->sid);
+
+ $this->assertContains($expected, $crawler->filter('textarea#message')->text());
+ }
}
diff --git a/tests/functional/report_post_captcha_test.php b/tests/functional/report_post_captcha_test.php
index 93a03bd931..36a1a9ee4d 100644
--- a/tests/functional/report_post_captcha_test.php
+++ b/tests/functional/report_post_captcha_test.php
@@ -18,12 +18,13 @@ class phpbb_functional_report_post_captcha_test extends phpbb_functional_test_ca
{
public function test_guest_report_post()
{
- $crawler = self::request('GET', 'report.php?f=2&p=1');
+ $crawler = self::request('GET', 'app.php/post/1/report', array(), false);
+ $this->assert_response_html(403);
$this->add_lang('mcp');
$this->assertContains($this->lang('USER_CANNOT_REPORT'), $crawler->filter('html')->text());
$this->set_reporting_guest(1);
- $crawler = self::request('GET', 'report.php?f=2&p=1');
+ $crawler = self::request('GET', 'app.php/post/1/report');
$this->assertContains($this->lang('CONFIRM_CODE'), $crawler->filter('html')->text());
$this->set_reporting_guest(-1);
}
@@ -31,7 +32,7 @@ class phpbb_functional_report_post_captcha_test extends phpbb_functional_test_ca
public function test_user_report_post()
{
$this->login();
- $crawler = self::request('GET', 'report.php?f=2&p=1');
+ $crawler = self::request('GET', 'app.php/post/1/report');
$this->assertNotContains($this->lang('CONFIRM_CODE'), $crawler->filter('html')->text());
$this->add_lang('mcp');
diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php
index f1e9b517d4..48c444fb76 100644
--- a/tests/functional/search/base.php
+++ b/tests/functional/search/base.php
@@ -36,6 +36,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->login();
$this->admin_login();
+ $this->create_search_index('\phpbb\search\fulltext_native');
+
$post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.');
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=settings&sid=' . $this->sid);
@@ -58,6 +60,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->delete_topic($post['topic_id']);
$this->markTestSkipped("Search backend is not supported/running");
}
+
$this->create_search_index();
}
@@ -72,7 +75,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->delete_topic($post['topic_id']);
}
- protected function create_search_index()
+ protected function create_search_index($backend = null)
{
$this->add_lang('acp/search');
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid);
@@ -80,7 +83,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$form_values = $form->getValues();
$form_values = array_merge($form_values,
array(
- 'search_type' => $this->search_backend,
+ 'search_type' => ( ($backend === null) ? $this->search_backend : $backend ),
'action' => 'create',
)
);
diff --git a/tests/functional/visit_installer_test.php b/tests/functional/visit_installer_test.php
new file mode 100644
index 0000000000..b4a75c0b51
--- /dev/null
+++ b/tests/functional/visit_installer_test.php
@@ -0,0 +1,30 @@
+<?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.
+*
+*/
+
+/**
+* @group functional
+*/
+class phpbb_functional_visit_installer_test extends phpbb_functional_test_case
+{
+ public function test_visit_installer()
+ {
+ self::request('GET', 'install/', [], false);
+ $this->assertContains('<meta http-equiv="refresh" content="0; url=./app.php" />', $this->get_content());
+
+ self::request('GET', 'install/index.html', [], false);
+ $this->assertContains('<meta http-equiv="refresh" content="0; url=./app.php" />', $this->get_content());
+
+ self::request('GET', 'install/app.php');
+ $this->assertContains('installation system', $this->get_content());
+ }
+}
diff --git a/tests/functions/build_hidden_fields_for_query_params_test.php b/tests/functions/build_hidden_fields_for_query_params_test.php
index 14cb4b9a94..aee7a569d4 100644
--- a/tests/functions/build_hidden_fields_for_query_params_test.php
+++ b/tests/functions/build_hidden_fields_for_query_params_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_build_hidden_fields_for_query_params_test extends phpbb_test_case
{
public function build_hidden_fields_for_query_params_test_data()
diff --git a/tests/functions/build_url_test.php b/tests/functions/build_url_test.php
index a59b94c744..91a4a9ec66 100644
--- a/tests/functions/build_url_test.php
+++ b/tests/functions/build_url_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_build_url_test extends phpbb_test_case
{
protected function setUp()
@@ -29,7 +27,7 @@ class phpbb_build_url_test extends phpbb_test_case
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ new \phpbb\filesystem\filesystem(),
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
'php'
diff --git a/tests/functions/convert_30_dbms_to_31_test.php b/tests/functions/convert_30_dbms_to_31_test.php
index 729c0a82f0..456eb64461 100644
--- a/tests/functions/convert_30_dbms_to_31_test.php
+++ b/tests/functions/convert_30_dbms_to_31_test.php
@@ -11,21 +11,17 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_convert_30_dbms_to_31_test extends phpbb_test_case
{
public function convert_30_dbms_to_31_data()
{
return array(
- array('mssql'),
array('mssql_odbc'),
array('mssqlnative'),
array('mysql'),
array('mysqli'),
array('oracle'),
array('postgres'),
- array('sqlite'),
);
}
diff --git a/tests/functions/generate_string_list.php b/tests/functions/generate_string_list.php
index cd1e37618a..6eddb1395e 100644
--- a/tests/functions/generate_string_list.php
+++ b/tests/functions/generate_string_list.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_generate_string_list_test extends phpbb_test_case
{
public $user;
@@ -22,7 +19,12 @@ class phpbb_generate_string_list_test extends phpbb_test_case
{
parent::setUp();
- $this->user = new \phpbb\user('\phpbb\datetime');
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $this->user = $user;
$this->user->data = array('user_lang' => 'en');
$this->user->add_lang('common');
}
@@ -36,7 +38,7 @@ class phpbb_generate_string_list_test extends phpbb_test_case
),
array(
array('A'),
- 'A',
+ 'A',
),
array(
array(2 => 'A', 3 => 'B'),
diff --git a/tests/functions/get_formatted_filesize_test.php b/tests/functions/get_formatted_filesize_test.php
index 635753d737..290515b64f 100644
--- a/tests/functions/get_formatted_filesize_test.php
+++ b/tests/functions/get_formatted_filesize_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_get_formatted_filesize_test extends phpbb_test_case
{
public function get_formatted_filesize_test_data()
diff --git a/tests/functions/get_preg_expression_test.php b/tests/functions/get_preg_expression_test.php
index e74017d315..b8254b03ea 100644
--- a/tests/functions/get_preg_expression_test.php
+++ b/tests/functions/get_preg_expression_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_functions_get_preg_expression_test extends phpbb_test_case
{
public function data_path_remove_dot_trailing_slash()
diff --git a/tests/functions/get_remote_file_test.php b/tests/functions/get_remote_file_test.php
index 612d82273e..1550aa37e6 100644
--- a/tests/functions/get_remote_file_test.php
+++ b/tests/functions/get_remote_file_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';
-
/**
* @group slow
*/
diff --git a/tests/functions/is_absolute_test.php b/tests/functions/is_absolute_test.php
deleted file mode 100644
index afa4b9b59f..0000000000
--- a/tests/functions/is_absolute_test.php
+++ /dev/null
@@ -1,60 +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.
-*
-*/
-
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
-class phpbb_functions_is_absolute_test extends phpbb_test_case
-{
- static public function is_absolute_data()
- {
- return array(
- // Empty
- array('', false),
-
- // Absolute unix style
- array('/etc/phpbb', true),
- // Unix does not support \ so that is not an absolute path
- array('\etc\phpbb', false),
-
- // Absolute windows style
- array('c:\windows', true),
- array('C:\Windows', true),
- array('c:/windows', true),
- array('C:/Windows', true),
-
- // Executable
- array('etc/phpbb', false),
- array('explorer.exe', false),
-
- // Relative subdir
- array('Windows\System32', false),
- array('Windows\System32\explorer.exe', false),
- array('Windows/System32', false),
- array('Windows/System32/explorer.exe', false),
-
- // Relative updir
- array('..\Windows\System32', false),
- array('..\Windows\System32\explorer.exe', false),
- array('../Windows/System32', false),
- array('../Windows/System32/explorer.exe', false),
- );
- }
-
- /**
- * @dataProvider is_absolute_data
- */
- public function test_is_absolute($path, $expected)
- {
- $this->assertEquals($expected, phpbb_is_absolute($path));
- }
-}
diff --git a/tests/functions/language_select_test.php b/tests/functions/language_select_test.php
index 6762ead5a1..2d1296d72f 100644
--- a/tests/functions/language_select_test.php
+++ b/tests/functions/language_select_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_functions_language_select_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/functions/make_clickable_email_test.php b/tests/functions/make_clickable_email_test.php
index 4c802d0487..f32b4339a8 100644
--- a/tests/functions/make_clickable_email_test.php
+++ b/tests/functions/make_clickable_email_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_functions_make_clickable_email_test extends phpbb_test_case
{
protected function setUp()
diff --git a/tests/functions/make_clickable_test.php b/tests/functions/make_clickable_test.php
index 63beeb06b2..48fc2c19fb 100644
--- a/tests/functions/make_clickable_test.php
+++ b/tests/functions/make_clickable_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_functions_make_clickable_test extends phpbb_test_case
{
/**
diff --git a/tests/functions/obtain_online_test.php b/tests/functions/obtain_online_test.php
index e793a4eb82..778753e5d2 100644
--- a/tests/functions/obtain_online_test.php
+++ b/tests/functions/obtain_online_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_functions_obtain_online_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/functions/parse_cfg_file_test.php b/tests/functions/parse_cfg_file_test.php
index b47e25fbc1..017a931f28 100644
--- a/tests/functions/parse_cfg_file_test.php
+++ b/tests/functions/parse_cfg_file_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_functions_parse_cfg_file extends phpbb_test_case
{
public function parse_cfg_file_data()
diff --git a/tests/functions/quoteattr_test.php b/tests/functions/quoteattr_test.php
index 6e191f9610..dbad7a99d8 100644
--- a/tests/functions/quoteattr_test.php
+++ b/tests/functions/quoteattr_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_quoteattr_test extends phpbb_test_case
{
public function quoteattr_test_data()
diff --git a/tests/functions/style_select_test.php b/tests/functions/style_select_test.php
index a918f83155..27f0e68c88 100644
--- a/tests/functions/style_select_test.php
+++ b/tests/functions/style_select_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_functions_style_select_test extends phpbb_database_test_case
{
public function getDataSet()
diff --git a/tests/functions/user_delete_test.php b/tests/functions/user_delete_test.php
index c224323273..db9b6e0c90 100644
--- a/tests/functions/user_delete_test.php
+++ b/tests/functions/user_delete_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
class phpbb_functions_user_delete_test extends phpbb_database_test_case
@@ -28,10 +27,12 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case
{
parent::setUp();
- global $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user;
+ global $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx;
$this->db = $db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$phpbb_container = new phpbb_mock_container_builder();
$config = new \phpbb\config\config(array(
@@ -39,8 +40,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case
'auth_oauth_google_key' => 'foo',
'auth_oauth_google_secret' => 'bar',
));
- set_config_count('foobar', 0, false, $config);
- $cache = new \phpbb\cache\driver\null();
+ $cache = new \phpbb\cache\driver\dummy();
$request = new phpbb_mock_request();
$notification_manager = new phpbb_mock_notification_manager();
$provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config);
@@ -67,6 +67,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case
$request,
$user,
'phpbb_oauth_tokens',
+ 'phpbb_oauth_states',
'phpbb_oauth_accounts',
$oauth_provider_collection,
'phpbb_users',
diff --git a/tests/functions/validate_email_test.php b/tests/functions/validate_email_test.php
index b46509fda7..7f8b2679d4 100644
--- a/tests/functions/validate_email_test.php
+++ b/tests/functions/validate_email_test.php
@@ -7,7 +7,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
require_once dirname(__FILE__) . '/../mock/user.php';
require_once dirname(__FILE__) . '/validate_data_helper.php';
diff --git a/tests/functions/validate_password_test.php b/tests/functions/validate_password_test.php
index c5942e79bf..5e34c8baba 100644
--- a/tests/functions/validate_password_test.php
+++ b/tests/functions/validate_password_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
require_once dirname(__FILE__) . '/validate_data_helper.php';
diff --git a/tests/functions/validate_string_test.php b/tests/functions/validate_string_test.php
index 24026e4c9f..7aca14c334 100644
--- a/tests/functions/validate_string_test.php
+++ b/tests/functions/validate_string_test.php
@@ -12,7 +12,6 @@
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
require_once dirname(__FILE__) . '/validate_data_helper.php';
class phpbb_functions_validate_string_test extends phpbb_test_case
diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php
index 951d5794e6..8dcec88103 100644
--- a/tests/functions/validate_user_email_test.php
+++ b/tests/functions/validate_user_email_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
require_once dirname(__FILE__) . '/../mock/user.php';
require_once dirname(__FILE__) . '/validate_data_helper.php';
diff --git a/tests/functions/validate_username_test.php b/tests/functions/validate_username_test.php
index 4fa5af7ff3..d310f58036 100644
--- a/tests/functions/validate_username_test.php
+++ b/tests/functions/validate_username_test.php
@@ -11,9 +11,7 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
require_once dirname(__FILE__) . '/../mock/cache.php';
require_once dirname(__FILE__) . '/validate_data_helper.php';
diff --git a/tests/functions_acp/validate_config_vars_test.php b/tests/functions_acp/validate_config_vars_test.php
index 32738e4351..5c31888291 100644
--- a/tests/functions_acp/validate_config_vars_test.php
+++ b/tests/functions_acp/validate_config_vars_test.php
@@ -12,7 +12,6 @@
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
class phpbb_functions_acp_validate_config_vars_test extends phpbb_test_case
{
diff --git a/tests/functions_acp/validate_range_test.php b/tests/functions_acp/validate_range_test.php
index 6408e29a26..9e9154a43c 100644
--- a/tests/functions_acp/validate_range_test.php
+++ b/tests/functions_acp/validate_range_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';
class phpbb_functions_acp_validate_range_test extends phpbb_test_case
diff --git a/tests/functions_content/get_username_string_test.php b/tests/functions_content/get_username_string_test.php
index 01ec97f6a4..e79342d05d 100644
--- a/tests/functions_content/get_username_string_test.php
+++ b/tests/functions_content/get_username_string_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_functions_content_get_username_string_test extends phpbb_test_case
{
public function setUp()
diff --git a/tests/functions_content/phpbb_clean_search_string_test.php b/tests/functions_content/phpbb_clean_search_string_test.php
index abd107097c..34ae0575c5 100644
--- a/tests/functions_content/phpbb_clean_search_string_test.php
+++ b/tests/functions_content/phpbb_clean_search_string_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_functions_content_phpbb_clean_search_string_test extends phpbb_test_case
{
public function phpbb_clean_search_string_data()
diff --git a/tests/functions_install/ignore_new_file_on_update_test.php b/tests/functions_install/ignore_new_file_on_update_test.php
deleted file mode 100644
index 822c5e6789..0000000000
--- a/tests/functions_install/ignore_new_file_on_update_test.php
+++ /dev/null
@@ -1,45 +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.
-*
-*/
-
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php';
-
-class phpbb_functions_install_ignore_new_file_on_update_test extends phpbb_test_case
-{
- static public function ignore_new_file_on_update_data()
- {
- return array(
- array('willneverexist.php', false),
- array('includes/dirwillneverexist/newfile.php', false),
-
- array('language/en/email/short/bookmark.txt', false),
- array('language/languagewillneverexist/email/short/bookmark.txt', true),
-
- array('styles/prosilver/template/bbcode.html', false),
- array('styles/stylewillneverexist/template/bbcode.html', true),
-
- array('styles/prosilver/theme/en/icon_user_online.gif', false),
- array('styles/prosilver/theme/languagewillneverexist/icon_user_online.gif', true),
-
- array('styles/prosilver/theme/imageset.css', false),
- );
- }
-
- /**
- * @dataProvider ignore_new_file_on_update_data
- */
- public function test_ignore_new_file_on_update($file, $expected)
- {
- global $phpbb_root_path;
- $this->assertEquals($expected, phpbb_ignore_new_file_on_update($phpbb_root_path, $file));
- }
-}
diff --git a/tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml b/tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml
new file mode 100644
index 0000000000..c78d63f7cb
--- /dev/null
+++ b/tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_groups">
+ <column>group_id</column>
+ <column>group_desc</column>
+ <column>group_message_limit</column>
+ <column>group_max_recipients</column>
+ <row>
+ <value>1</value>
+ <value></value>
+ <value>1</value>
+ <value>3</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value></value>
+ <value>2</value>
+ <value>4</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value></value>
+ <value>0</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value></value>
+ <value>0</value>
+ <value>5</value>
+ </row>
+ </table>
+ <table name="phpbb_user_group">
+ <column>user_id</column>
+ <column>group_id</column>
+ <column>user_pending</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>2</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>3</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>2</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>3</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>4</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>3</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>2</value>
+ <value>0</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/functions_privmsgs/get_max_setting_from_group_test.php b/tests/functions_privmsgs/get_max_setting_from_group_test.php
new file mode 100644
index 0000000000..3eb7866802
--- /dev/null
+++ b/tests/functions_privmsgs/get_max_setting_from_group_test.php
@@ -0,0 +1,64 @@
+<?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.
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions_privmsgs.php';
+
+class phpbb_functions_privmsgs_get_max_setting_from_group_test extends phpbb_database_test_case
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/get_max_setting_from_group.xml');
+ }
+
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->db = $this->new_dbal();
+ }
+
+ static public function get_max_setting_from_group_data()
+ {
+ return array(
+ array(1, 0, 'message_limit'),
+ array(2, 2, 'message_limit'),
+ array(3, 0, 'message_limit'),
+ array(4, 0, 'message_limit'),
+ array(5, 2, 'message_limit'),
+ array(1, 0, 'max_recipients'),
+ array(2, 4, 'max_recipients'),
+ array(3, 0, 'max_recipients'),
+ array(4, 5, 'max_recipients'),
+ array(5, 4, 'max_recipients'),
+ );
+ }
+
+ /**
+ * @dataProvider get_max_setting_from_group_data
+ */
+ public function test_get_max_setting_from_group($user_id, $expected, $setting)
+ {
+ $this->assertEquals($expected, phpbb_get_max_setting_from_group($this->db, $user_id, $setting));
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function test_get_max_setting_from_group_throws()
+ {
+ phpbb_get_max_setting_from_group($this->db, ANONYMOUS, 'not_a_setting');
+ }
+}
diff --git a/tests/functions_user/delete_user_test.php b/tests/functions_user/delete_user_test.php
index 7db69e332c..25042d9f1b 100644
--- a/tests/functions_user/delete_user_test.php
+++ b/tests/functions_user/delete_user_test.php
@@ -7,9 +7,7 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
class phpbb_functions_user_delete_user_test extends phpbb_database_test_case
{
@@ -25,19 +23,19 @@ class phpbb_functions_user_delete_user_test extends phpbb_database_test_case
{
parent::setUp();
- global $cache, $config, $db, $phpbb_dispatcher, $phpbb_container;
+ global $cache, $config, $db, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path;
$db = $this->db = $this->new_dbal();
$config = new \phpbb\config\config(array(
'load_online_time' => 5,
'search_type' => '\phpbb\search\fulltext_mysql',
));
- set_config(false, false, false, $config);
- set_config_count(false, false, false, $config);
$cache = new phpbb_mock_null_cache();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
+ // Works as a workaround for tests
+ $phpbb_container->set('attachment.manager', new \phpbb\attachment\delete($config, $db, new \phpbb_mock_event_dispatcher(), new \phpbb\filesystem\filesystem(), new \phpbb\attachment\resync($db), $phpbb_root_path));
$phpbb_container->set(
'auth.provider.db',
new phpbb_mock_auth_provider()
diff --git a/tests/functions_user/group_user_attributes_test.php b/tests/functions_user/group_user_attributes_test.php
index 99a15b32bf..3124d57ba0 100644
--- a/tests/functions_user/group_user_attributes_test.php
+++ b/tests/functions_user/group_user_attributes_test.php
@@ -11,9 +11,7 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
class phpbb_functions_user_group_user_attributes_test extends phpbb_database_test_case
{
@@ -139,7 +137,7 @@ class phpbb_functions_user_group_user_attributes_test extends phpbb_database_tes
$auth = $this->getMock('\phpbb\auth\auth');
$auth->expects($this->any())
->method('acl_clear_prefetch');
- $cache_driver = new \phpbb\cache\driver\null();
+ $cache_driver = new \phpbb\cache\driver\dummy();
$phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$phpbb_container
->expects($this->any())
diff --git a/tests/group/helper_test.php b/tests/group/helper_test.php
new file mode 100644
index 0000000000..2377a6f47c
--- /dev/null
+++ b/tests/group/helper_test.php
@@ -0,0 +1,68 @@
+<?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.
+ *
+ */
+
+class phpbb_group_helper_test extends phpbb_test_case
+{
+ /** @var \phpbb\group\helper */
+ protected $group_helper;
+
+ public function setUp()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ // Set up language service
+ $lang = new \phpbb\language\language(
+ new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)
+ );
+
+ // Set up language data for testing
+ $reflection_class = new ReflectionClass('\phpbb\language\language');
+
+ // Set default language files loaded flag to true
+ $loaded_flag = $reflection_class->getProperty('common_language_files_loaded');
+ $loaded_flag->setAccessible(true);
+ $loaded_flag->setValue($lang, true);
+
+ // Set up test language data
+ $lang_array = $reflection_class->getProperty('lang');
+ $lang_array->setAccessible(true);
+ $lang_array->setValue($lang, $this->get_test_language_data_set());
+
+ // Set up group helper
+ $this->group_helper = new \phpbb\group\helper($lang);
+ }
+
+ public function test_get_name()
+ {
+ // They should be totally fine
+ $this->assertEquals('Bots', $this->group_helper->get_name('Bots'));
+ $this->assertEquals('Some new group', $this->group_helper->get_name('new_group'));
+ $this->assertEquals('Should work', $this->group_helper->get_name('group_with_ümlauts'));
+
+ // This should fail (obviously)
+ $this->assertNotEquals('They key does not contain uppercase letters', $this->group_helper->get_name('not_uppercase'));
+
+ // The key doesn't exist so just return group name...
+ $this->assertEquals('Awesome group', $this->group_helper->get_name('Awesome group'));
+ }
+
+ protected function get_test_language_data_set()
+ {
+ return array(
+ 'G_BOTS' => 'Bots',
+ 'G_NEW_GROUP' => 'Some new group',
+ 'G_not_uppercase' => 'The key does not contain uppercase letters',
+ 'G_GROUP_WITH_ÃœMLAUTS' => 'Should work',
+ );
+ }
+}
diff --git a/tests/groupposition/legend_test.php b/tests/groupposition/legend_test.php
index fe003e93a7..02ddb7cbce 100644
--- a/tests/groupposition/legend_test.php
+++ b/tests/groupposition/legend_test.php
@@ -11,7 +11,6 @@
*
*/
-
class phpbb_groupposition_legend_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -33,11 +32,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
*/
public function test_get_group_value($group_id, $expected, $throws_exception)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
if ($throws_exception)
@@ -51,11 +52,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
public function test_get_group_count()
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\legend($db, $user);
@@ -91,11 +94,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
*/
public function test_add_group($group_id, $expected_added, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\legend($db, $user);
@@ -179,11 +184,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
*/
public function test_delete_group($group_id, $skip_group, $expected_deleted, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\legend($db, $user);
@@ -234,11 +241,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
*/
public function test_move_up($group_id, $excepted_moved, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\legend($db, $user);
@@ -289,11 +298,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
*/
public function test_move_down($group_id, $excepted_moved, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\legend($db, $user);
@@ -387,11 +398,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case
*/
public function test_move($group_id, $increment, $excepted_moved, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\legend($db, $user);
diff --git a/tests/groupposition/teampage_test.php b/tests/groupposition/teampage_test.php
index 1e61e3ebfb..3b916670f7 100644
--- a/tests/groupposition/teampage_test.php
+++ b/tests/groupposition/teampage_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_groupposition_teampage_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -35,11 +32,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_get_group_value($group_id, $expected, $throws_exception)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
if ($throws_exception)
@@ -53,11 +52,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
public function test_get_group_count()
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
@@ -137,11 +138,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_add_group_teampage($group_id, $parent_id, $expected_added, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
@@ -180,11 +183,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_add_category_teampage($group_name, $expected_added, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
@@ -247,11 +252,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_delete_group($group_id, $expected_deleted, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
@@ -299,11 +306,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_delete_teampage($teampage_id, $expected_deleted, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
@@ -462,11 +471,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_move($group_id, $move_delta, $excepted_moved, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
@@ -625,11 +636,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case
*/
public function test_move_teampage($teampage_id, $move_delta, $excepted_moved, $expected)
{
- global $cache;
+ global $cache, $phpbb_root_path, $phpEx;
$cache = new phpbb_mock_cache;
$db = $this->new_dbal();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = array();
$test_class = new \phpbb\groupposition\teampage($db, $user, $cache);
diff --git a/tests/help/manager_test.php b/tests/help/manager_test.php
new file mode 100644
index 0000000000..68534d9a32
--- /dev/null
+++ b/tests/help/manager_test.php
@@ -0,0 +1,184 @@
+<?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.
+ *
+ */
+
+class phpbb_help_manager_test extends phpbb_test_case
+{
+ /** @var \phpbb\help\manager */
+ protected $manager;
+ /** @var \phpbb\template\template */
+ protected $template;
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ public function setUp()
+ {
+ $this->template = $this->getMockBuilder('\phpbb\template\template')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->language = $this->getMockBuilder('\phpbb\language\language')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->manager = new \phpbb\help\manager(
+ new \phpbb_mock_event_dispatcher(),
+ $this->language,
+ $this->template
+ );
+ }
+
+ public function add_block_data()
+ {
+ return array(
+ array('abc', false, array(), false),
+ array('def', true, array(), true),
+ array(
+ 'abc',
+ false,
+ array(
+ 'question1' => 'answer1',
+ 'question2' => 'answer2',
+ 'question3' => 'answer3',
+ ),
+ false
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider add_block_data
+ *
+ * @param string $block_name
+ * @param bool $switch
+ * @param array $questions
+ * @param bool $switch_expected
+ */
+ public function test_add_block($block_name, $switch, $questions, $switch_expected)
+ {
+ $this->language->expects($this->at(0))
+ ->method('lang')
+ ->with($block_name)
+ ->willReturn(strtoupper($block_name));
+ $lang_call_count = 1;
+ foreach ($questions as $question => $answer)
+ {
+ $this->language->expects($this->at($lang_call_count))
+ ->method('lang')
+ ->with($question)
+ ->willReturn(strtoupper($question));
+ $lang_call_count++;
+
+ $this->language->expects($this->at($lang_call_count))
+ ->method('lang')
+ ->with($answer)
+ ->willReturn(strtoupper($answer));
+ $lang_call_count++;
+ }
+
+ $this->template->expects($this->at(0))
+ ->method('assign_block_vars')
+ ->with('faq_block', array(
+ 'BLOCK_TITLE' => strtoupper($block_name),
+ 'SWITCH_COLUMN' => $switch_expected,
+ ));
+ $template_call_count = 1;
+ foreach ($questions as $question => $answer)
+ {
+ $this->template->expects($this->at($template_call_count))
+ ->method('assign_block_vars')
+ ->with('faq_block.faq_row', array(
+ 'FAQ_QUESTION' => strtoupper($question),
+ 'FAQ_ANSWER' => strtoupper($answer),
+ ));
+ $template_call_count++;
+ }
+
+ $this->manager->add_block($block_name, $switch, $questions);
+
+ $this->assertEquals($switch_expected, $this->manager->switched_column());
+ }
+
+ public function add_question_data()
+ {
+ return array(
+ array('abc', false, false),
+ array('def', true, true),
+ );
+ }
+
+ /**
+ * @dataProvider add_question_data
+ *
+ * @param string $question
+ * @param string $answer
+ */
+ public function test_add_question($question, $answer)
+ {
+ $this->language->expects($this->at(0))
+ ->method('lang')
+ ->with($question)
+ ->willReturn(strtoupper($question));
+ $this->language->expects($this->at(1))
+ ->method('lang')
+ ->with($answer)
+ ->willReturn(strtoupper($answer));
+
+ $this->template->expects($this->once())
+ ->method('assign_block_vars')
+ ->with('faq_block.faq_row', array(
+ 'FAQ_QUESTION' => strtoupper($question),
+ 'FAQ_ANSWER' => strtoupper($answer),
+ ));
+
+ $this->manager->add_question($question, $answer);
+ }
+
+ public function test_add_block_double_switch()
+ {
+ $block_name = 'abc';
+ $switch_expected = true;
+
+ $this->language->expects($this->at(0))
+ ->method('lang')
+ ->with($block_name)
+ ->willReturn(strtoupper($block_name));
+
+ $this->template->expects($this->at(0))
+ ->method('assign_block_vars')
+ ->with('faq_block', array(
+ 'BLOCK_TITLE' => strtoupper($block_name),
+ 'SWITCH_COLUMN' => $switch_expected,
+ ));
+
+ $this->manager->add_block($block_name, true);
+ $this->assertTrue($this->manager->switched_column());
+
+ // Add a second block with switch
+ $block_name = 'def';
+ $switch_expected = false;
+
+ $this->language->expects($this->at(0))
+ ->method('lang')
+ ->with($block_name)
+ ->willReturn(strtoupper($block_name));
+
+ $this->template->expects($this->at(0))
+ ->method('assign_block_vars')
+ ->with('faq_block', array(
+ 'BLOCK_TITLE' => strtoupper($block_name),
+ 'SWITCH_COLUMN' => $switch_expected,
+ ));
+
+ $this->manager->add_block($block_name, true);
+ $this->assertTrue($this->manager->switched_column());
+ }
+}
diff --git a/tests/installer/database_helper_test.php b/tests/installer/database_helper_test.php
new file mode 100644
index 0000000000..ed355884f6
--- /dev/null
+++ b/tests/installer/database_helper_test.php
@@ -0,0 +1,157 @@
+<?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.
+ *
+ */
+
+class phpbb_installer_database_helper_test extends phpbb_test_case
+{
+ /**
+ * @var phpbb\install\helper\database
+ */
+ private $database_helper;
+
+ public function setUp()
+ {
+ $filesystem = new \phpbb\filesystem\filesystem();
+ $phpbb_root_path = '';
+ $this->database_helper = new \phpbb\install\helper\database($filesystem, $phpbb_root_path);
+ }
+
+ /**
+ * @param string $input
+ * @param string $expected
+ *
+ * @dataProvider comment_string_provider
+ */
+ public function test_remove_comments($input, $expected)
+ {
+ $this->assertEquals($expected, $this->database_helper->remove_comments($input));
+ }
+
+ /**
+ * @param array $expected
+ * @param string $sql
+ * @param string $delimiter
+ *
+ * @dataProvider sql_file_string_provider
+ */
+ public function test_split_sql($expected, $sql, $delimiter)
+ {
+ $this->assertEquals($expected, $this->database_helper->split_sql_file($sql, $delimiter));
+ }
+
+ /**
+ * @param bool|array $expected
+ * @param string $test_string
+ *
+ * @dataProvider prefix_test_case_provider
+ */
+ public function test_validate_table_prefix($expected, $test_string)
+ {
+ $db_helper_mock = $this->getMockBuilder('\phpbb\install\helper\database')
+ ->setMethods(array('get_available_dbms'))
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $db_helper_mock->method('get_available_dbms')
+ ->willReturn(array('sqlite3' => array(
+ 'LABEL' => 'SQLite3',
+ 'SCHEMA' => 'sqlite',
+ 'MODULE' => 'sqlite3',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\sqlite3',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ )));
+
+ $this->assertEquals($expected, $db_helper_mock->validate_table_prefix('sqlite3', $test_string));
+ }
+
+ // Data provider for the remove comments function
+ public function comment_string_provider()
+ {
+ return array(
+ array(
+ 'abc',
+ 'abc',
+ ),
+ array(
+ 'abc /* asdf */',
+ "abc \n",
+ ),
+ array(
+ 'abc /* asdf */ f',
+ "abc \n f",
+ ),
+ array(
+ '# abc',
+ "\n",
+ ),
+ );
+ }
+
+ // Data provider for the sql file splitter function
+ public function sql_file_string_provider()
+ {
+ return array(
+ array(
+ array(
+ 'abcd "efgh"' . "\n" . 'qwerty',
+ 'SELECT * FROM table',
+ ),
+ 'abcd "efgh"' . "\n" .
+ 'qwerty;' . "\n" .
+ 'SELECT * FROM table',
+ ';',
+ ),
+ );
+ }
+
+ // Test data for prefix test
+ public function prefix_test_case_provider()
+ {
+ return array(
+ array(
+ true,
+ 'phpbb_',
+ ),
+ array(
+ true,
+ 'phpbb',
+ ),
+ array(
+ array(
+ array('title' => 'INST_ERR_DB_INVALID_PREFIX'),
+ ),
+ '1hpbb_',
+ ),
+ array(
+ array(
+ array('title' => 'INST_ERR_DB_INVALID_PREFIX'),
+ ),
+ '?hpbb_',
+ ),
+ array(
+ array(
+ array('title' => array('INST_ERR_PREFIX_TOO_LONG', 200)),
+ ),
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
+ ),
+ array(
+ array(
+ array('title' => 'INST_ERR_DB_INVALID_PREFIX'),
+ array('title' => array('INST_ERR_PREFIX_TOO_LONG', 200)),
+ ),
+ '_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
+ ),
+ );
+ }
+}
diff --git a/tests/installer/installer_config_test.php b/tests/installer/installer_config_test.php
new file mode 100644
index 0000000000..13ac325a79
--- /dev/null
+++ b/tests/installer/installer_config_test.php
@@ -0,0 +1,80 @@
+<?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.
+ *
+ */
+
+use phpbb\install\helper\config;
+
+class phpbb_installer_config_test extends phpbb_test_case
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ private $config;
+
+ public function setUp()
+ {
+ $phpbb_root_path = __DIR__ . './../../phpBB/';
+ $filesystem = $this->getMock('\phpbb\filesystem\filesystem');
+ $php_ini = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper')
+ ->getMock();
+ $php_ini->method('getInt')
+ ->willReturn(-1);
+ $php_ini->method('getBytes')
+ ->willReturn(-1);
+
+ $this->config = new config($filesystem, $php_ini, $phpbb_root_path);
+ }
+
+ public function test_set_get_var()
+ {
+ $this->config->set('foo', 'bar');
+ $this->assertEquals('bar', $this->config->get('foo'));
+ }
+
+ public function test_get_time_remaining()
+ {
+ $this->assertGreaterThan(0, $this->config->get_time_remaining());
+ }
+
+ public function test_get_memory_remaining()
+ {
+ $this->assertGreaterThan(0, $this->config->get_memory_remaining());
+ }
+
+ public function test_progress_tracking()
+ {
+ $this->config->set_finished_task(0);
+ $this->config->set_active_module('bar', 5);
+ $this->config->set_task_progress_count(10);
+ $this->config->increment_current_task_progress();
+
+ $progress_data = $this->config->get_progress_data();
+ $this->assertEquals(1, $progress_data['current_task_progress']);
+
+ $this->config->increment_current_task_progress(2);
+
+ // We only want to check these values
+ $result = $this->config->get_progress_data();
+ $expected_result = array(
+ 'last_task_module_name' => 'bar',
+ 'last_task_module_index' => 5,
+ 'last_task_index' => 0,
+ 'max_task_progress' => 10,
+ 'current_task_progress' => 3,
+ );
+
+ foreach ($expected_result as $key => $value)
+ {
+ $this->assertEquals($value, $result[$key]);
+ }
+ }
+}
diff --git a/tests/installer/mocks/test_installer_module.php b/tests/installer/mocks/test_installer_module.php
new file mode 100644
index 0000000000..e6ebbba263
--- /dev/null
+++ b/tests/installer/mocks/test_installer_module.php
@@ -0,0 +1,20 @@
+<?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.
+ *
+ */
+
+class test_installer_module extends \phpbb\install\module_base
+{
+ public function get_navigation_stage_path()
+ {
+ return array();
+ }
+}
diff --git a/tests/installer/mocks/test_installer_task_mock.php b/tests/installer/mocks/test_installer_task_mock.php
new file mode 100644
index 0000000000..ccd62b3bf4
--- /dev/null
+++ b/tests/installer/mocks/test_installer_task_mock.php
@@ -0,0 +1,44 @@
+<?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.
+ *
+ */
+
+class test_installer_task_mock extends \phpbb\install\task_base
+{
+ private $task_was_runned;
+
+ public function __construct()
+ {
+ $this->task_was_runned = false;
+
+ parent::__construct();
+ }
+
+ public function run()
+ {
+ $this->task_was_runned = true;
+ }
+
+ public function was_task_runned()
+ {
+ return $this->task_was_runned;
+ }
+
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+
+ public static function get_step_count()
+ {
+ return 2;
+ }
+}
diff --git a/tests/installer/module_base_test.php b/tests/installer/module_base_test.php
new file mode 100644
index 0000000000..9578010047
--- /dev/null
+++ b/tests/installer/module_base_test.php
@@ -0,0 +1,65 @@
+<?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.
+ *
+ */
+
+require_once __DIR__ . '/mocks/test_installer_task_mock.php';
+require_once __DIR__ . '/mocks/test_installer_module.php';
+
+class module_base_test extends phpbb_test_case
+{
+ /**
+ * @var \phpbb\install\module_interface
+ */
+ protected $module;
+
+ /**
+ * @var phpbb_mock_container_builder
+ */
+ protected $container;
+
+ public function setUp()
+ {
+ // DI container mock
+ $this->container = new phpbb_mock_container_builder();
+ $this->container->set('task_one', new test_installer_task_mock());
+ $this->container->set('task_two', new test_installer_task_mock());
+
+ // the collection
+ $module_collection = new \phpbb\di\ordered_service_collection($this->container);
+ $module_collection->add('task_one');
+ $module_collection->add('task_two');
+ $module_collection->add_service_class('task_one', 'test_installer_task_mock');
+ $module_collection->add_service_class('task_two', 'test_installer_task_mock');
+
+ $this->module = new test_installer_module($module_collection, true, false);
+
+ $iohandler = $this->getMock('\phpbb\install\helper\iohandler\iohandler_interface');
+ $config = new \phpbb\install\helper\config(new \phpbb\filesystem\filesystem(), new \bantu\IniGetWrapper\IniGetWrapper(), '', 'php');
+ $this->module->setup($config, $iohandler);
+ }
+
+ public function test_run()
+ {
+ $this->module->run();
+
+ $task = $this->container->get('task_one');
+ $this->assertTrue($task->was_task_runned());
+
+ $task = $this->container->get('task_two');
+ $this->assertTrue($task->was_task_runned());
+ }
+
+ public function test_step_count()
+ {
+ $this->assertEquals(4, $this->module->get_step_count());
+ }
+}
diff --git a/tests/installer/navigation_provider_test.php b/tests/installer/navigation_provider_test.php
new file mode 100644
index 0000000000..ea39af66cd
--- /dev/null
+++ b/tests/installer/navigation_provider_test.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.
+ *
+ */
+
+class phpbb_installer_navigation_provider_test extends phpbb_test_case
+{
+ public function test_navigation()
+ {
+ // Mock nav interface
+ $nav_stub = $this->getMockBuilder('\phpbb\install\helper\navigation\navigation_interface')
+ ->getMock();
+ $nav_stub->method('get')
+ ->willReturn(array('foo' => 'bar'));
+
+ // Set up dependencies
+ $container = new phpbb_mock_container_builder();
+ $container->set('foo', $nav_stub);
+ $nav_collection = new \phpbb\di\service_collection($container);
+ $nav_collection->add('foo');
+
+ // Let's test
+ $nav_provider = new \phpbb\install\helper\navigation\navigation_provider($nav_collection);
+ $this->assertEquals(array('foo' => 'bar'), $nav_provider->get());
+ }
+}
diff --git a/tests/language/language_test.php b/tests/language/language_test.php
new file mode 100644
index 0000000000..29b4873dcb
--- /dev/null
+++ b/tests/language/language_test.php
@@ -0,0 +1,243 @@
+<?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.
+ *
+ */
+
+class phpbb_language_test extends phpbb_test_case
+{
+ /** @var \phpbb\language\language */
+ protected $lang;
+
+ public function setUp()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ // Set up language service
+ $this->lang = new \phpbb\language\language(
+ new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)
+ );
+
+ // Set up language data for testing
+ $reflection_class = new ReflectionClass('\phpbb\language\language');
+
+ // Set default language files loaded flag to true
+ $loaded_flag = $reflection_class->getProperty('common_language_files_loaded');
+ $loaded_flag->setAccessible(true);
+ $loaded_flag->setValue($this->lang, true);
+
+ // Set up test language data
+ $lang_array = $reflection_class->getProperty('lang');
+ $lang_array->setAccessible(true);
+ $lang_array->setValue($this->lang, $this->get_test_data_set());
+ }
+
+ public function test_is_set()
+ {
+ // Check for non-existing key
+ $this->assertFalse($this->lang->is_set('VALUE'));
+ $this->assertFalse($this->lang->is_set(array('dateformat', 'MAYBE')));
+
+ // Check for existing key
+ $this->assertTrue($this->lang->is_set('FOO'));
+ $this->assertTrue($this->lang->is_set(array('dateformat', 'AGO')));
+
+ // Array doesn't exist at all...
+ $this->assertFalse($this->lang->is_set(array('PHPBB', 'PHP')));
+ }
+
+ public function test_lang_raw()
+ {
+ $this->assertEquals($this->lang->lang_raw('FOO'), 'BAR');
+ $this->assertEquals($this->lang->lang_raw('VOID'), 'VOID');
+ $this->assertEquals($this->lang->lang_raw('ARRY'), array(
+ 0 => 'No posts', // 0
+ 1 => '1 post', // 1
+ 2 => '%d posts', // 2+
+ ));
+ }
+
+ public function test_lang_array()
+ {
+ $this->assertEquals($this->lang->lang_array('FOO'), 'BAR');
+ $this->assertEquals($this->lang->lang_array('VOID'), 'VOID');
+ $this->assertEquals($this->lang->lang_array('ARRY', [0]), 'No posts');
+ $this->assertEquals($this->lang->lang_array('FOO', [2, 3, 'BARZ']), 'BAR');
+ }
+
+ public function test_lang()
+ {
+ // No param
+ $this->assertEquals($this->lang->lang('FOO'), 'BAR');
+ $this->assertEquals($this->lang->lang('EMPTY'), '');
+ $this->assertEquals($this->lang->lang('ZERO'), '0');
+
+ // Invalid index
+ $this->assertEquals($this->lang->lang('VOID'), 'VOID');
+
+ // Unnecessary param
+ $this->assertEquals($this->lang->lang('FOO', 2), 'BAR');
+ $this->assertEquals($this->lang->lang('FOO', 2, 3), 'BAR');
+ $this->assertEquals($this->lang->lang('FOO', 2, 3, 'BARZ'), 'BAR');
+
+ // String
+ $this->assertEquals($this->lang->lang('STR', 24, 'x', 42), '24 x, 42 topics');
+ $this->assertEquals($this->lang->lang('STR2', 64), '64 foos');
+
+ // Array
+ $this->assertEquals($this->lang->lang('ARRY', 0), 'No posts');
+ $this->assertEquals($this->lang->lang('ARRY', 1), '1 post');
+ $this->assertEquals($this->lang->lang('ARRY', 2), '2 posts');
+ $this->assertEquals($this->lang->lang('ARRY', 123), '123 posts');
+
+ // Empty array returns the language key
+ $this->assertEquals($this->lang->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY');
+
+ // No 0 key defined
+ $this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 0), '0 posts');
+ $this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 1), '1 post');
+ $this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 2), '2 posts');
+
+ // Array with missing keys
+ $this->assertEquals($this->lang->lang('ARRY_MISSING', 2), '2 post');
+
+ // Floats as array key
+ $this->assertEquals($this->lang->lang('ARRY_FLOAT', 1.3), '1 post');
+ $this->assertEquals($this->lang->lang('ARRY_FLOAT', 2.0), '2.0 posts');
+ $this->assertEquals($this->lang->lang('ARRY_FLOAT', 2.51), '2.5 posts');
+
+ // Use sub key, if first paramenter is an array
+ $this->assertEquals($this->lang->lang(array('dateformat', 'AGO'), 2), '2 seconds');
+
+ // ticket PHPBB3-9949 - use first int to determinate the plural-form to use
+ $this->assertEquals($this->lang->lang('ARRY', 1, 2), '1 post');
+ $this->assertEquals($this->lang->lang('ARRY', 1, 's', 2), '1 post');
+ }
+
+ public function test_lang_plural_rules()
+ {
+ $this->assertEquals($this->lang->lang('PLURAL_ARRY', 0), '0 is 0');
+ $this->assertEquals($this->lang->lang('PLURAL_ARRY', 1), '1 is 1');
+ $this->assertEquals($this->lang->lang('PLURAL_ARRY', 103), '103 ends with 01-10');
+ $this->assertEquals($this->lang->lang('PLURAL_ARRY', 15), '15 ends with 11-19');
+ $this->assertEquals($this->lang->lang('PLURAL_ARRY', 300), '300 is part of the last rule');
+ }
+
+ public function test_lang_bc()
+ {
+ $user = new \phpbb\user($this->lang, '\phpbb\datetime');
+
+ // Test lang array access
+ $this->assertEquals($user->lang['FOO'], 'BAR');
+
+ // No param
+ $this->assertEquals($user->lang('FOO'), 'BAR');
+ $this->assertEquals($user->lang('EMPTY'), '');
+ $this->assertEquals($user->lang('ZERO'), '0');
+
+ // Invalid index
+ $this->assertEquals($user->lang('VOID'), 'VOID');
+
+ // Unnecessary param
+ $this->assertEquals($user->lang('FOO', 2), 'BAR');
+ $this->assertEquals($user->lang('FOO', 2, 3), 'BAR');
+ $this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR');
+
+ // String
+ $this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics');
+ $this->assertEquals($user->lang('STR2', 64), '64 foos');
+
+ // Array
+ $this->assertEquals($user->lang('ARRY', 0), 'No posts');
+ $this->assertEquals($user->lang('ARRY', 1), '1 post');
+ $this->assertEquals($user->lang('ARRY', 2), '2 posts');
+ $this->assertEquals($user->lang('ARRY', 123), '123 posts');
+
+ // Empty array returns the language key
+ $this->assertEquals($user->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY');
+
+ // No 0 key defined
+ $this->assertEquals($user->lang('ARRY_NO_ZERO', 0), '0 posts');
+ $this->assertEquals($user->lang('ARRY_NO_ZERO', 1), '1 post');
+ $this->assertEquals($user->lang('ARRY_NO_ZERO', 2), '2 posts');
+
+ // Array with missing keys
+ $this->assertEquals($user->lang('ARRY_MISSING', 2), '2 post');
+
+ // Floats as array key
+ $this->assertEquals($user->lang('ARRY_FLOAT', 1.3), '1 post');
+ $this->assertEquals($user->lang('ARRY_FLOAT', 2.0), '2.0 posts');
+ $this->assertEquals($user->lang('ARRY_FLOAT', 2.51), '2.5 posts');
+
+ // Use sub key, if first paramenter is an array
+ $this->assertEquals($user->lang(array('dateformat', 'AGO'), 2), '2 seconds');
+
+ // ticket PHPBB3-9949 - use first int to determinate the plural-form to use
+ $this->assertEquals($user->lang('ARRY', 1, 2), '1 post');
+ $this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post');
+ }
+
+ public function test_lang_plural_rules_bc()
+ {
+ $user = new \phpbb\user($this->lang, '\phpbb\datetime');
+
+ // ticket PHPBB3-10345 - different plural rules, not just 0/1/2+
+ $this->assertEquals($user->lang('PLURAL_ARRY', 0), '0 is 0');
+ $this->assertEquals($user->lang('PLURAL_ARRY', 1), '1 is 1');
+ $this->assertEquals($user->lang('PLURAL_ARRY', 103), '103 ends with 01-10');
+ $this->assertEquals($user->lang('PLURAL_ARRY', 15), '15 ends with 11-19');
+ $this->assertEquals($user->lang('PLURAL_ARRY', 300), '300 is part of the last rule');
+ }
+
+ protected function get_test_data_set()
+ {
+ return array(
+ 'FOO' => 'BAR',
+ 'BARZ' => 'PENG',
+ 'EMPTY' => '',
+ 'ZERO' => '0',
+ 'STR' => '%d %s, %d topics',
+ 'STR2' => '%d foos',
+ 'ARRY' => array(
+ 0 => 'No posts', // 0
+ 1 => '1 post', // 1
+ 2 => '%d posts', // 2+
+ ),
+ 'ARRY_NO_ZERO' => array(
+ 1 => '1 post', // 1
+ 2 => '%d posts', // 0, 2+
+ ),
+ 'ARRY_MISSING' => array(
+ 1 => '%d post', // 1
+ //Missing second plural
+ ),
+ 'ARRY_FLOAT' => array(
+ 1 => '1 post', // 1.x
+ 2 => '%1$.1f posts', // 0.x, 2+.x
+ ),
+ 'ARRY_EMPTY' => array(
+ ),
+ 'dateformat' => array(
+ 'AGO' => array(
+ 1 => '%d second',
+ 2 => '%d seconds',
+ ),
+ ),
+ 'PLURAL_RULE' => 13,
+ 'PLURAL_ARRY' => array(
+ 0 => '%d is 0', // 0
+ 1 => '%d is 1', // 1
+ 2 => '%d ends with 01-10', // ending with 01-10
+ 3 => '%d ends with 11-19', // ending with 11-19
+ 4 => '%d is part of the last rule', // everything else
+ ),
+ );
+ }
+}
diff --git a/tests/lock/db_test.php b/tests/lock/db_test.php
index 6fc813cb38..5fbfa26554 100644
--- a/tests/lock/db_test.php
+++ b/tests/lock/db_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_lock_db_test extends phpbb_database_test_case
{
private $db;
@@ -30,7 +28,6 @@ class phpbb_lock_db_test extends phpbb_database_test_case
$db = $this->db = $this->new_dbal();
$config = $this->config = new \phpbb\config\config(array('rand_seed' => '', 'rand_seed_last_update' => '0'));
- set_config(null, null, null, $this->config);
$this->lock = new \phpbb\lock\db('test_lock', $this->config, $this->db);
}
diff --git a/tests/log/add_test.php b/tests/log/add_test.php
index 29d3adaeb6..604c8364dc 100644
--- a/tests/log/add_test.php
+++ b/tests/log/add_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_log_add_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -27,7 +25,9 @@ class phpbb_log_add_test extends phpbb_database_test_case
$db = $this->new_dbal();
$cache = new phpbb_mock_cache;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$auth = $this->getMock('\phpbb\auth\auth');
$log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
@@ -56,7 +56,9 @@ class phpbb_log_add_test extends phpbb_database_test_case
$db = $this->new_dbal();
$cache = new phpbb_mock_cache;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$auth = $this->getMock('\phpbb\auth\auth');
$log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
diff --git a/tests/log/delete_test.php b/tests/log/delete_test.php
index ec43182a0c..e8b75d01d9 100644
--- a/tests/log/delete_test.php
+++ b/tests/log/delete_test.php
@@ -11,10 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_log_delete_test extends phpbb_database_test_case
{
protected $log;
@@ -30,7 +26,9 @@ class phpbb_log_delete_test extends phpbb_database_test_case
$db = $this->new_dbal();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->data['user_id'] = 1;
$auth = $this->getMock('\phpbb\auth\auth');
diff --git a/tests/log/fixtures/delete_log.xml b/tests/log/fixtures/delete_log.xml
index 4b2402102e..393c686f0c 100644
--- a/tests/log/fixtures/delete_log.xml
+++ b/tests/log/fixtures/delete_log.xml
@@ -6,6 +6,7 @@
<column>user_id</column>
<column>forum_id</column>
<column>topic_id</column>
+ <column>post_id</column>
<column>reportee_id</column>
<column>log_ip</column>
<column>log_time</column>
@@ -18,6 +19,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_INSTALL_INSTALLED</value>
@@ -30,6 +32,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_KEY_NOT_EXISTS</value>
@@ -42,6 +45,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_CRITICAL</value>
@@ -54,6 +58,7 @@
<value>12</value>
<value>34</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD</value>
@@ -66,6 +71,7 @@
<value>12</value>
<value>45</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD</value>
@@ -78,6 +84,7 @@
<value>23</value>
<value>56</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD</value>
@@ -90,6 +97,7 @@
<value>12</value>
<value>45</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD2</value>
@@ -101,6 +109,7 @@
<value>1</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>2</value>
<value>127.0.0.1</value>
<value>1</value>
@@ -113,6 +122,7 @@
<value>1</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>1</value>
<value>127.0.0.1</value>
<value>1</value>
@@ -126,6 +136,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_SINGULAR_PLURAL</value>
@@ -138,6 +149,7 @@
<value>15</value>
<value>3</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD3</value>
@@ -150,6 +162,7 @@
<value>13</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value></value>
@@ -162,6 +175,7 @@
<value>14</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value></value>
@@ -174,6 +188,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value></value>
@@ -186,6 +201,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value></value>
diff --git a/tests/log/fixtures/empty_log.xml b/tests/log/fixtures/empty_log.xml
index 261b6a622a..47fd639b17 100644
--- a/tests/log/fixtures/empty_log.xml
+++ b/tests/log/fixtures/empty_log.xml
@@ -6,6 +6,7 @@
<column>user_id</column>
<column>forum_id</column>
<column>topic_id</column>
+ <column>post_id</column>
<column>reportee_id</column>
<column>log_ip</column>
<column>log_time</column>
diff --git a/tests/log/fixtures/full_log.xml b/tests/log/fixtures/full_log.xml
index ef35884444..5b9ded9ffb 100644
--- a/tests/log/fixtures/full_log.xml
+++ b/tests/log/fixtures/full_log.xml
@@ -6,6 +6,7 @@
<column>user_id</column>
<column>forum_id</column>
<column>topic_id</column>
+ <column>post_id</column>
<column>reportee_id</column>
<column>log_ip</column>
<column>log_time</column>
@@ -18,6 +19,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_INSTALL_INSTALLED</value>
@@ -30,6 +32,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_KEY_NOT_EXISTS</value>
@@ -42,6 +45,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_CRITICAL</value>
@@ -54,6 +58,7 @@
<value>12</value>
<value>34</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD</value>
@@ -66,6 +71,7 @@
<value>12</value>
<value>45</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD</value>
@@ -78,6 +84,7 @@
<value>23</value>
<value>56</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD</value>
@@ -90,6 +97,7 @@
<value>12</value>
<value>45</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD2</value>
@@ -101,6 +109,7 @@
<value>1</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>2</value>
<value>127.0.0.1</value>
<value>1</value>
@@ -113,6 +122,7 @@
<value>1</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>1</value>
<value>127.0.0.1</value>
<value>1</value>
@@ -126,6 +136,7 @@
<value>0</value>
<value>0</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_SINGULAR_PLURAL</value>
@@ -138,6 +149,7 @@
<value>15</value>
<value>3</value>
<value>0</value>
+ <value>0</value>
<value>127.0.0.1</value>
<value>1</value>
<value>LOG_MOD3</value>
diff --git a/tests/log/function_add_log_test.php b/tests/log/function_add_log_test.php
index 63e468498e..3b5537fc13 100644
--- a/tests/log/function_add_log_test.php
+++ b/tests/log/function_add_log_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_log_function_add_log_test extends phpbb_database_test_case
{
public function getDataSet()
@@ -161,7 +159,10 @@ class phpbb_log_function_add_log_test extends phpbb_database_test_case
$db = $this->new_dbal();
$cache = new phpbb_mock_cache;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$auth = $this->getMock('\phpbb\auth\auth');
$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
diff --git a/tests/log/function_view_log_test.php b/tests/log/function_view_log_test.php
index 02e0b3912f..ee9c3e5893 100644
--- a/tests/log/function_view_log_test.php
+++ b/tests/log/function_view_log_test.php
@@ -11,10 +11,7 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
require_once dirname(__FILE__) . '/../mock/user.php';
require_once dirname(__FILE__) . '/../mock/cache.php';
@@ -46,6 +43,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 0,
'topic_id' => 0,
+ 'post_id' => 0,
'viewforum' => '',
'action' => 'LOG_INSTALL_INSTALLED 3.1.0-dev',
@@ -65,6 +63,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 0,
'topic_id' => 0,
+ 'post_id' => 0,
'viewforum' => '',
'action' => '{LOG KEY NOT EXISTS}<br />additional_data',
@@ -84,6 +83,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 0,
'topic_id' => 0,
+ 'post_id' => 0,
'viewforum' => '',
'action' => '{LOG CRITICAL}<br />critical data',
@@ -103,10 +103,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 12,
'topic_id' => 34,
+ 'post_id' => 0,
'viewforum' => '',
'action' => '{LOG MOD}',
'viewtopic' => '',
+ 'viewpost' => '',
'viewlogs' => '',
),
5 => array(
@@ -124,10 +126,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 12,
'topic_id' => 45,
+ 'post_id' => 0,
'viewforum' => '',
'action' => '{LOG MOD}',
'viewtopic' => '',
+ 'viewpost' => '',
'viewlogs' => '',
),
6 => array(
@@ -145,10 +149,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 23,
'topic_id' => 56,
+ 'post_id' => 0,
'viewforum' => append_sid("phpBB/viewforum.$phpEx", 'f=23'),
'action' => '{LOG MOD}',
'viewtopic' => append_sid("phpBB/viewtopic.$phpEx", 'f=23&amp;t=56'),
+ 'viewpost' => '',
'viewlogs' => append_sid("phpBB/mcp.$phpEx", 'i=logs&amp;mode=topic_logs&amp;t=56'),
),
7 => array(
@@ -166,10 +172,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 12,
'topic_id' => 45,
+ 'post_id' => 0,
'viewforum' => '',
'action' => 'LOG_MOD2',
'viewtopic' => '',
+ 'viewpost' => '',
'viewlogs' => '',
),
8 => array(
@@ -187,6 +195,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 0,
'topic_id' => 0,
+ 'post_id' => 0,
'viewforum' => '',
'action' => 'LOG_USER admin',
@@ -206,6 +215,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 0,
'topic_id' => 0,
+ 'post_id' => 0,
'viewforum' => '',
'action' => 'LOG_USER guest',
@@ -225,6 +235,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 0,
'topic_id' => 0,
+ 'post_id' => 0,
'viewforum' => '',
'action' => 'LOG_SINGULAR_PLURAL 2',
@@ -244,10 +255,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case
'time' => 1,
'forum_id' => 15,
'topic_id' => 3,
+ 'post_id' => 0,
'viewforum' => '',
'action' => 'LOG_MOD3 guest ',
'viewtopic' => '',
+ 'viewpost' => '',
'viewlogs' => '',
),
);
diff --git a/tests/migrator/convert_timezones_test.php b/tests/migrator/convert_timezones_test.php
index 7501ed2ed0..f8d780da0c 100644
--- a/tests/migrator/convert_timezones_test.php
+++ b/tests/migrator/convert_timezones_test.php
@@ -18,7 +18,8 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case
public function getDataSet()
{
$this->db = $this->new_dbal();
- $db_tools = new \phpbb\db\tools($this->db);
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($this->db);
// user_dst doesn't exist anymore, must re-add it to test this
$db_tools->sql_column_add('phpbb_users', 'user_dst', array('BOOL', 1));
@@ -55,11 +56,12 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case
global $phpbb_root_path, $phpEx;
$this->db = $this->new_dbal();
+ $factory = new \phpbb\db\tools\factory();
$this->migration = new \phpbb\db\migration\data\v310\timezone(
new \phpbb\config\config(array()),
$this->db,
- new \phpbb\db\tools($this->db),
+ $factory->get($this->db),
$phpbb_root_path,
$phpEx,
'phpbb_'
@@ -90,7 +92,8 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case
}
$this->db->sql_freeresult($result);
- $db_tools = new \phpbb\db\tools($this->db);
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($this->db);
// Remove the user_dst field again
$db_tools->sql_column_remove('phpbb_users', 'user_dst');
diff --git a/tests/migrator/schema_generator_test.php b/tests/migrator/schema_generator_test.php
index 9adf518a5d..1996d207ea 100644
--- a/tests/migrator/schema_generator_test.php
+++ b/tests/migrator/schema_generator_test.php
@@ -29,8 +29,9 @@ class schema_generator_test extends phpbb_test_case
parent::setUp();
$this->config = new \phpbb\config\config(array());
- $this->db = new \phpbb\db\driver\sqlite();
- $this->db_tools = new \phpbb\db\tools($this->db);
+ $this->db = new \phpbb\db\driver\sqlite3();
+ $factory = new \phpbb\db\tools\factory();
+ $this->db_tools = $factory->get($this->db);
$this->table_prefix = 'phpbb_';
}
diff --git a/tests/mock/container_builder.php b/tests/mock/container_builder.php
index 297e3a65e6..134589b0b8 100644
--- a/tests/mock/container_builder.php
+++ b/tests/mock/container_builder.php
@@ -52,7 +52,15 @@ class phpbb_mock_container_builder implements ContainerInterface
{
if ($this->has($id))
{
- return $this->services[$id];
+ $service = $this->services[$id];
+ if (is_array($service) && is_callable($service[0]))
+ {
+ return call_user_func_array($service[0], $service[1]);
+ }
+ else
+ {
+ return $service;
+ }
}
throw new Exception('Could not find service: ' . $id);
@@ -180,4 +188,9 @@ class phpbb_mock_container_builder implements ContainerInterface
public function isScopeActive($name)
{
}
+
+ public function isFrozen()
+ {
+ return false;
+ }
}
diff --git a/tests/mock/controller_helper.php b/tests/mock/controller_helper.php
index ae3e7bf432..0116dced49 100644
--- a/tests/mock/controller_helper.php
+++ b/tests/mock/controller_helper.php
@@ -13,20 +13,6 @@
class phpbb_mock_controller_helper extends \phpbb\controller\helper
{
- public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext)
- {
- $this->template = $template;
- $this->user = $user;
- $this->config = $config;
- $this->symfony_request = $symfony_request;
- $this->request = $request;
- $this->filesystem = $filesystem;
- $this->phpbb_root_path = $phpbb_root_path;
- $this->php_ext = $php_ext;
- $provider->find_routing_files($manager->get_finder());
- $this->route_collection = $provider->find($phpbb_root_path_ext)->get_routes();
- }
-
public function get_current_url()
{
return '';
diff --git a/tests/mock/extension_manager.php b/tests/mock/extension_manager.php
index 3b759fbbc2..2ce61c5149 100644
--- a/tests/mock/extension_manager.php
+++ b/tests/mock/extension_manager.php
@@ -18,7 +18,7 @@ class phpbb_mock_extension_manager extends \phpbb\extension\manager
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = 'php';
$this->extensions = $extensions;
- $this->filesystem = new \phpbb\filesystem();
+ $this->filesystem = new \phpbb\filesystem\filesystem();
$this->container = $container;
}
}
diff --git a/tests/mock/fileupload.php b/tests/mock/fileupload.php
index 8cc4d77ea1..5a0afc6cd3 100644
--- a/tests/mock/fileupload.php
+++ b/tests/mock/fileupload.php
@@ -19,9 +19,10 @@ class phpbb_mock_fileupload
{
public $max_filesize = 100;
public $error_prefix = '';
+ public $valid_dimensions = true;
public function valid_dimensions($filespec)
{
- return true;
+ return $this->valid_dimensions;
}
}
diff --git a/tests/mock/migrator.php b/tests/mock/migrator.php
index 293f115335..4d1aca0a0a 100644
--- a/tests/mock/migrator.php
+++ b/tests/mock/migrator.php
@@ -21,10 +21,6 @@ class phpbb_mock_migrator extends \phpbb\db\migrator
{
}
- public function set_migrations($class_names)
- {
- }
-
public function update()
{
}
diff --git a/tests/mock/notification_manager.php b/tests/mock/notification_manager.php
index 6a590bc0ca..952c0db489 100644
--- a/tests/mock/notification_manager.php
+++ b/tests/mock/notification_manager.php
@@ -32,19 +32,18 @@ class phpbb_mock_notification_manager
);
}
- public function mark_notifications_read()
+ public function mark_notifications()
{
}
- public function mark_notifications_read_by_parent()
+ public function mark_notifications_by_parent()
{
}
- public function mark_notifications_read_by_id()
+ public function mark_notifications_by_id()
{
}
-
public function add_notifications()
{
return array();
diff --git a/tests/mock/notification_type_post.php b/tests/mock/notification_type_post.php
index 6d8f6dc504..4116fecf5e 100644
--- a/tests/mock/notification_type_post.php
+++ b/tests/mock/notification_type_post.php
@@ -21,11 +21,12 @@ if (!defined('IN_PHPBB'))
class phpbb_mock_notification_type_post extends \phpbb\notification\type\post
{
- public function __construct($user_loader, $db, $cache, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ public function __construct($user_loader, $db, $cache, $language, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table)
{
$this->user_loader = $user_loader;
$this->db = $db;
$this->cache = $cache;
+ $this->language = $language;
$this->user = $user;
$this->auth = $auth;
$this->config = $config;
@@ -34,7 +35,6 @@ class phpbb_mock_notification_type_post extends \phpbb\notification\type\post
$this->php_ext = $php_ext;
$this->notification_types_table = $notification_types_table;
- $this->notifications_table = $notifications_table;
- $this->user_notifications_table = $user_notifications_table;
+ $this->user_notifications_table = $user_notifications_table;
}
}
diff --git a/tests/mock/phpbb_di_container_builder.php b/tests/mock/phpbb_di_container_builder.php
index 59cdf0bb2b..23dc3d1e8b 100644
--- a/tests/mock/phpbb_di_container_builder.php
+++ b/tests/mock/phpbb_di_container_builder.php
@@ -17,4 +17,14 @@ class phpbb_mock_phpbb_di_container_builder extends \phpbb\di\container_builder
{
return $this->phpbb_root_path . '../../tmp/container.' . $this->php_ext;
}
+
+ /**
+ * Get the filename under which the dumped extensions autoloader will be stored.
+ *
+ * @return string Path for dumped extensions autoloader
+ */
+ protected function get_autoload_filename()
+ {
+ return $this->phpbb_root_path . '../../tmp/autoload.' . $this->php_ext;
+ }
}
diff --git a/tests/mock/router.php b/tests/mock/router.php
new file mode 100644
index 0000000000..01faa338c5
--- /dev/null
+++ b/tests/mock/router.php
@@ -0,0 +1,27 @@
+<?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.
+*
+*/
+
+class phpbb_mock_router extends \phpbb\routing\router
+{
+ public function get_matcher()
+ {
+ $this->create_new_url_matcher();
+ return parent::get_matcher();
+ }
+
+ public function get_generator()
+ {
+ $this->create_new_url_generator();
+ return parent::get_generator();
+ }
+}
diff --git a/tests/mock/session_testable.php b/tests/mock/session_testable.php
index 29dd2a5bff..2f24978ba8 100644
--- a/tests/mock/session_testable.php
+++ b/tests/mock/session_testable.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
/**
* Extends the session class to overwrite the setting of cookies.
*
diff --git a/tests/network/checkdnsrr_test.php b/tests/network/checkdnsrr_test.php
index a3852b2656..6503a4c40b 100644
--- a/tests/network/checkdnsrr_test.php
+++ b/tests/network/checkdnsrr_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
/**
* @group slow
*/
diff --git a/tests/network/ftp_fsock_pasv_epsv_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php
index 6ed9d61dc0..4ec21b6f75 100644
--- a/tests/network/ftp_fsock_pasv_epsv_test.php
+++ b/tests/network/ftp_fsock_pasv_epsv_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php';
/**
diff --git a/tests/network/inet_ntop_pton_test.php b/tests/network/inet_ntop_pton_test.php
index fae40ad74e..dbd58ce783 100644
--- a/tests/network/inet_ntop_pton_test.php
+++ b/tests/network/inet_ntop_pton_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_network_inet_ntop_pton_test extends phpbb_test_case
{
public function data_provider()
diff --git a/tests/network/ip_normalise_test.php b/tests/network/ip_normalise_test.php
index 1acfd4521d..52e594e115 100644
--- a/tests/network/ip_normalise_test.php
+++ b/tests/network/ip_normalise_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_network_ip_normalise_test extends phpbb_test_case
{
public function data_provider()
diff --git a/tests/notification/base.php b/tests/notification/base.php
index 162feae557..b64e25cf8c 100644
--- a/tests/notification/base.php
+++ b/tests/notification/base.php
@@ -11,6 +11,10 @@
*
*/
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+
require_once dirname(__FILE__) . '/manager_helper.php';
abstract class phpbb_tests_notification_base extends phpbb_database_test_case
@@ -39,6 +43,13 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case
);
}
+ protected function get_notification_methods()
+ {
+ return array(
+ 'notification.method.board',
+ );
+ }
+
protected function setUp()
{
parent::setUp();
@@ -55,55 +66,83 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case
'allow_bookmarks' => true,
'allow_topic_notify' => true,
'allow_forum_notify' => true,
+ 'allow_board_notifications' => true,
));
- $user = $this->user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $this->user = $user;
$this->user_loader = new \phpbb\user_loader($this->db, $phpbb_root_path, $phpEx, 'phpbb_users');
$auth = $this->auth = new phpbb_mock_notifications_auth();
+ $cache_driver = new \phpbb\cache\driver\dummy();
$cache = $this->cache = new \phpbb\cache\service(
- new \phpbb\cache\driver\null(),
+ $cache_driver,
$this->config,
$this->db,
$phpbb_root_path,
$phpEx
);
-
+
$this->phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $phpbb_container = $this->container = new phpbb_mock_container_builder();
+ $phpbb_container = $this->container = new ContainerBuilder();
+ $loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__ . '/fixtures'));
+ $loader->load('services_notification.yml');
+ $phpbb_container->set('user_loader', $this->user_loader);
+ $phpbb_container->set('user', $user);
+ $phpbb_container->set('language', $lang);
+ $phpbb_container->set('config', $this->config);
+ $phpbb_container->set('dbal.conn', $this->db);
+ $phpbb_container->set('auth', $auth);
+ $phpbb_container->set('cache.driver', $cache_driver);
+ $phpbb_container->set('cache', $cache);
+ $phpbb_container->set('text_formatter.utils', new \phpbb\textformatter\s9e\utils());
+ $phpbb_container->set('dispatcher', $this->phpbb_dispatcher);
+ $phpbb_container->setParameter('core.root_path', $phpbb_root_path);
+ $phpbb_container->setParameter('core.php_ext', $phpEx);
+ $phpbb_container->setParameter('tables.notifications', 'phpbb_notifications');
+ $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications');
+ $phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types');
$this->notifications = new phpbb_notification_manager_helper(
array(),
array(),
$this->container,
$this->user_loader,
- $this->config,
$this->phpbb_dispatcher,
$this->db,
$this->cache,
+ $lang,
$this->user,
- $phpbb_root_path,
- $phpEx,
'phpbb_notification_types',
- 'phpbb_notifications',
'phpbb_user_notifications'
);
$phpbb_container->set('notification_manager', $this->notifications);
+ $phpbb_container->compile();
$this->notifications->setDependencies($this->auth, $this->config);
$types = array();
foreach ($this->get_notification_types() as $type)
{
- $type_parts = explode('.', $type);
- $class = $this->build_type('phpbb\notification\type\\' . array_pop($type_parts));
+ $class = $this->build_type($type);
$types[$type] = $class;
- $this->container->set($type, $class);
}
$this->notifications->set_var('notification_types', $types);
+ $methods = array();
+ foreach ($this->get_notification_methods() as $method)
+ {
+ $class = $this->container->get($method);
+
+ $methods[$method] = $class;
+ }
+
+ $this->notifications->set_var('notification_methods', $methods);
+
$this->db->sql_query('DELETE FROM phpbb_notification_types');
$this->db->sql_query('DELETE FROM phpbb_notifications');
$this->db->sql_query('DELETE FROM phpbb_user_notifications');
@@ -111,14 +150,14 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case
protected function build_type($type)
{
- global $phpbb_root_path, $phpEx;
+ $instance = $this->container->get($type);
- return new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications');
+ return $instance;
}
protected function assert_notifications($expected, $options = array())
{
- $notifications = $this->notifications->load_notifications(array_merge(array(
+ $notifications = $this->notifications->load_notifications('notification.method.board', array_merge(array(
'count_unread' => true,
'order_by' => 'notification_time',
'order_dir' => 'ASC',
diff --git a/tests/notification/convert_test.php b/tests/notification/convert_test.php
index 32ab34c9bc..4a7fd89409 100644
--- a/tests/notification/convert_test.php
+++ b/tests/notification/convert_test.php
@@ -28,11 +28,12 @@ class phpbb_notification_convert_test extends phpbb_database_test_case
global $phpbb_root_path, $phpEx;
$this->db = $this->new_dbal();
+ $factory = new \phpbb\db\tools\factory();
$this->migration = new \phpbb\db\migration\data\v310\notification_options_reconvert(
new \phpbb\config\config(array()),
$this->db,
- new \phpbb\db\tools($this->db),
+ $factory->get($this->db),
$phpbb_root_path,
$phpEx,
'phpbb_'
diff --git a/tests/notification/ext/test/notification/type/test.php b/tests/notification/ext/test/notification/type/test.php
index b02a563f06..7f3b4a4ef1 100644
--- a/tests/notification/ext/test/notification/type/test.php
+++ b/tests/notification/ext/test/notification/type/test.php
@@ -47,12 +47,13 @@ class test extends \phpbb\notification\type\base
{
$this->notification_time = $post['post_time'];
- return parent::create_insert_array($post, $pre_create_data);
+ parent::create_insert_array($post, $pre_create_data);
}
public function create_update_array($type_data)
{
- $data = $this->create_insert_array($type_data);
+ $this->create_insert_array($type_data);
+ $data = $this->get_insert_array();
// Unset data unique to each row
unset(
diff --git a/tests/notification/fixtures/services_notification.yml b/tests/notification/fixtures/services_notification.yml
new file mode 100644
index 0000000000..6e68cccff6
--- /dev/null
+++ b/tests/notification/fixtures/services_notification.yml
@@ -0,0 +1,76 @@
+imports:
+ - { resource: ../../../phpBB/config/default/container/services_notification.yml }
+
+services:
+ notification_manager:
+ synthetic: true
+
+ user_loader:
+ synthetic: true
+
+ user:
+ synthetic: true
+
+ config:
+ synthetic: true
+
+ dbal.conn:
+ synthetic: true
+
+ language:
+ synthetic: true
+
+ auth:
+ synthetic: true
+
+ cache.driver:
+ synthetic: true
+
+ group_helper:
+ synthetic: true
+
+ path_helper:
+ synthetic: true
+
+ groupposition.legend:
+ synthetic: true
+
+ groupposition.teampage:
+ synthetic: true
+
+ groupposition.teampage:
+ synthetic: true
+
+ text_formatter.s9e.factory:
+ synthetic: true
+
+ text_formatter.s9e.quote_helper:
+ synthetic: true
+
+ text_formatter.parser:
+ synthetic: true
+
+ text_formatter.s9e.parser:
+ synthetic: true
+
+ text_formatter.renderer:
+ synthetic: true
+
+ text_formatter.s9e.renderer:
+ synthetic: true
+
+ text_formatter.utils:
+ synthetic: true
+
+ text_formatter.s9e.utils:
+ synthetic: true
+
+ text_formatter.data_access:
+ synthetic: true
+
+ test:
+ class: phpbb\notification\type\test
+ scope: prototype
+ parent: notification.type.base
+ tags:
+ - { name: notification.type }
diff --git a/tests/notification/fixtures/submit_post_notification.type.bookmark.xml b/tests/notification/fixtures/submit_post_notification.type.bookmark.xml
index a1413e2cf8..7f069abc59 100644
--- a/tests/notification/fixtures/submit_post_notification.type.bookmark.xml
+++ b/tests/notification/fixtures/submit_post_notification.type.bookmark.xml
@@ -126,35 +126,35 @@
<value>notification.type.bookmark</value>
<value>0</value>
<value>2</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.bookmark</value>
<value>0</value>
<value>3</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.bookmark</value>
<value>0</value>
<value>4</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.bookmark</value>
<value>0</value>
<value>5</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.bookmark</value>
<value>0</value>
<value>6</value>
- <value></value>
+ <value>notification.method.board</value>
<value>0</value>
</row>
</table>
diff --git a/tests/notification/fixtures/submit_post_notification.type.post.xml b/tests/notification/fixtures/submit_post_notification.type.post.xml
index ed75787c70..a4bf9d3ee4 100644
--- a/tests/notification/fixtures/submit_post_notification.type.post.xml
+++ b/tests/notification/fixtures/submit_post_notification.type.post.xml
@@ -156,49 +156,49 @@
<value>notification.type.post</value>
<value>0</value>
<value>2</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.post</value>
<value>0</value>
<value>3</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.post</value>
<value>0</value>
<value>4</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.post</value>
<value>0</value>
<value>5</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.post</value>
<value>0</value>
<value>6</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.post</value>
<value>0</value>
<value>7</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.post</value>
<value>0</value>
<value>8</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
</table>
diff --git a/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml b/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml
index 2dea8e34dd..0a955c48d2 100644
--- a/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml
+++ b/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml
@@ -110,49 +110,49 @@
<value>notification.type.needs_approval</value>
<value>0</value>
<value>2</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.needs_approval</value>
<value>0</value>
<value>3</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.needs_approval</value>
<value>0</value>
<value>4</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.needs_approval</value>
<value>0</value>
<value>5</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.needs_approval</value>
<value>0</value>
<value>6</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.needs_approval</value>
<value>0</value>
<value>7</value>
- <value></value>
+ <value>notification.method.board</value>
<value>0</value>
</row>
<row>
<value>notification.type.needs_approval</value>
<value>0</value>
<value>9</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
</table>
diff --git a/tests/notification/fixtures/submit_post_notification.type.quote.xml b/tests/notification/fixtures/submit_post_notification.type.quote.xml
index dd5bc620cd..c66830fbf5 100644
--- a/tests/notification/fixtures/submit_post_notification.type.quote.xml
+++ b/tests/notification/fixtures/submit_post_notification.type.quote.xml
@@ -98,35 +98,35 @@
<value>notification.type.quote</value>
<value>0</value>
<value>2</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.quote</value>
<value>0</value>
<value>3</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.quote</value>
<value>0</value>
<value>4</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.quote</value>
<value>0</value>
<value>5</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.quote</value>
<value>0</value>
<value>6</value>
- <value></value>
+ <value>notification.method.board</value>
<value>0</value>
</row>
</table>
diff --git a/tests/notification/fixtures/submit_post_notification.type.topic.xml b/tests/notification/fixtures/submit_post_notification.type.topic.xml
index 1ba8d05699..e0f6583f48 100644
--- a/tests/notification/fixtures/submit_post_notification.type.topic.xml
+++ b/tests/notification/fixtures/submit_post_notification.type.topic.xml
@@ -106,28 +106,28 @@
<value>notification.type.topic</value>
<value>0</value>
<value>2</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.topic</value>
<value>0</value>
<value>6</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.topic</value>
<value>0</value>
<value>7</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
<row>
<value>notification.type.topic</value>
<value>0</value>
<value>8</value>
- <value></value>
+ <value>notification.method.board</value>
<value>1</value>
</row>
</table>
diff --git a/tests/notification/group_request_test.php b/tests/notification/group_request_test.php
index 0d1bda95ce..92e758a336 100644
--- a/tests/notification/group_request_test.php
+++ b/tests/notification/group_request_test.php
@@ -12,7 +12,6 @@
*/
require_once dirname(__FILE__) . '/base.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_notification_group_request_test extends phpbb_tests_notification_base
{
@@ -40,8 +39,6 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas
include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
include_once($phpbb_root_path . 'includes/functions_content.' . $phpEx);
- set_config(false, false, false, $this->config);
-
$this->container->set('groupposition.legend', new \phpbb\groupposition\legend(
$this->db,
$this->user
@@ -51,8 +48,14 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas
$this->user,
$this->cache->get_driver()
));
+ $this->container->set('group_helper', new \phpbb\group\helper(
+ new \phpbb\language\language(
+ new phpbb\language\language_file_loader($phpbb_root_path, $phpEx)
+ )
+ ));
$phpbb_dispatcher = new phpbb_mock_event_dispatcher;
- $phpbb_log = new \phpbb\log\null();
+ $phpbb_log = new \phpbb\log\dummy();
+ $this->get_test_case_helpers()->set_s9e_services();
// Now on to the actual test
diff --git a/tests/notification/manager_helper.php b/tests/notification/manager_helper.php
index 75b7275d3a..2e8699e1e0 100644
--- a/tests/notification/manager_helper.php
+++ b/tests/notification/manager_helper.php
@@ -37,35 +37,4 @@ class phpbb_notification_manager_helper extends \phpbb\notification\manager
$this->auth = $auth;
$this->config = $config;
}
-
- /**
- * Helper to get the notifications item type class and set it up
- */
- public function get_item_type_class($item_type, $data = array())
- {
- $item_parts = explode('.', $item_type);
- $item_type = 'phpbb\notification\type\\' . array_pop($item_parts);
-
- $item = new $item_type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table);
-
- $item->set_notification_manager($this);
-
- $item->set_initial_data($data);
-
- return $item;
- }
-
- /**
- * Helper to get the notifications method class and set it up
- */
- public function get_method_class($method_name)
- {
- $method_name = 'phpbb\notification\method\\' . $method_name;
-
- $method = new $method_name($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table);
-
- $method->set_notification_manager($this);
-
- return $method;
- }
}
diff --git a/tests/notification/notification_test.php b/tests/notification/notification_test.php
index 79fa5338c4..ec42aa193c 100644
--- a/tests/notification/notification_test.php
+++ b/tests/notification/notification_test.php
@@ -29,7 +29,7 @@ class phpbb_notification_test extends phpbb_tests_notification_base
$quote_type_id = $this->notifications->get_notification_type_id('notification.type.quote');
$test_type_id = $this->notifications->get_notification_type_id('test');
- $this->assertEquals(array(
+ self::assertEquals(array(
'test' => $test_type_id,
'notification.type.quote' => $quote_type_id,
'notification.type.post' => $post_type_id,
@@ -40,13 +40,13 @@ class phpbb_notification_test extends phpbb_tests_notification_base
'notification.type.post',
)
));
- $this->assertEquals($quote_type_id, $this->notifications->get_notification_type_id('notification.type.quote'));
+ self::assertEquals($quote_type_id, $this->notifications->get_notification_type_id('notification.type.quote'));
try
{
- $this->assertEquals(false, $this->notifications->get_notification_type_id('fail'));
+ self::assertEquals(false, $this->notifications->get_notification_type_id('fail'));
- $this->fail('Non-existent type should throw an exception');
+ self::fail('Non-existent type should throw an exception');
}
catch (Exception $e) {}
}
@@ -55,15 +55,15 @@ class phpbb_notification_test extends phpbb_tests_notification_base
{
$subscription_types = $this->notifications->get_subscription_types();
- $this->assertArrayHasKey('NOTIFICATION_GROUP_MISCELLANEOUS', $subscription_types);
- $this->assertArrayHasKey('NOTIFICATION_GROUP_POSTING', $subscription_types);
+ self::assertArrayHasKey('NOTIFICATION_GROUP_MISCELLANEOUS', $subscription_types);
+ self::assertArrayHasKey('NOTIFICATION_GROUP_POSTING', $subscription_types);
- $this->assertArrayHasKey('notification.type.bookmark', $subscription_types['NOTIFICATION_GROUP_POSTING']);
- $this->assertArrayHasKey('notification.type.post', $subscription_types['NOTIFICATION_GROUP_POSTING']);
- $this->assertArrayHasKey('notification.type.quote', $subscription_types['NOTIFICATION_GROUP_POSTING']);
- $this->assertArrayHasKey('notification.type.topic', $subscription_types['NOTIFICATION_GROUP_POSTING']);
+ self::assertArrayHasKey('notification.type.bookmark', $subscription_types['NOTIFICATION_GROUP_POSTING']);
+ self::assertArrayHasKey('notification.type.post', $subscription_types['NOTIFICATION_GROUP_POSTING']);
+ self::assertArrayHasKey('notification.type.quote', $subscription_types['NOTIFICATION_GROUP_POSTING']);
+ self::assertArrayHasKey('notification.type.topic', $subscription_types['NOTIFICATION_GROUP_POSTING']);
- $this->assertArrayHasKey('notification.type.pm', $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']);
+ self::assertArrayHasKey('notification.type.pm', $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']);
//get_subscription_types
//get_subscription_methods
@@ -72,33 +72,33 @@ class phpbb_notification_test extends phpbb_tests_notification_base
public function test_subscriptions()
{
$expected_subscriptions = array(
- 'notification.type.post' => array(''),
- 'notification.type.topic' => array(''),
- 'notification.type.quote' => array(''),
- 'notification.type.bookmark' => array(''),
- 'test' => array(''),
- 'notification.type.pm' => array(''),
+ 'notification.type.post' => array('notification.method.board'),
+ 'notification.type.topic' => array('notification.method.board'),
+ 'notification.type.quote' => array('notification.method.board'),
+ 'notification.type.bookmark' => array('notification.method.board'),
+ 'test' => array('notification.method.board'),
+ 'notification.type.pm' => array('notification.method.board'),
);
$subscriptions = $this->notifications->get_global_subscriptions(2);
-
foreach ($expected_subscriptions as $item_type => $methods)
{
+ self::assertArrayHasKey($item_type, $subscriptions);
$this->assert_array_content_equals($methods, $subscriptions[$item_type]);
}
foreach ($subscriptions as $item_type => $methods)
{
- $this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]);
+ $this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]);
}
- $this->notifications->delete_subscription('notification.type.post', 0, '', 2);
+ $this->notifications->delete_subscription('notification.type.post', 0, 'notification.method.board', 2);
- $this->assertArrayNotHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2));
+ self::assertArrayNotHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2));
- $this->notifications->add_subscription('notification.type.post', 0, '', 2);
+ $this->notifications->add_subscription('notification.type.post', 0, 'notification.method.board', 2);
- $this->assertArrayHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2));
+ self::assertArrayHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2));
}
public function test_notifications()
@@ -124,11 +124,11 @@ class phpbb_notification_test extends phpbb_tests_notification_base
'user_id' => 0,
)));
- $this->assertEquals(array(
+ self::assertEquals(array(
'notifications' => array(),
'unread_count' => 0,
'total_count' => 0,
- ), $this->notifications->load_notifications(array(
+ ), $this->notifications->load_notifications('notification.method.board', array(
'count_unread' => true,
)));
diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php
index 5e770f71c9..21559c42a5 100644
--- a/tests/notification/submit_post_base.php
+++ b/tests/notification/submit_post_base.php
@@ -11,10 +11,11 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
abstract class phpbb_notification_submit_post_base extends phpbb_database_test_case
{
@@ -50,7 +51,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
{
parent::setUp();
- global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path;
+ global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $lang, $user, $request, $phpEx, $phpbb_root_path, $user_loader;
// Database
$this->db = $this->new_dbal();
@@ -69,12 +70,15 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
)));
// Config
- $config = new \phpbb\config\config(array('num_topics' => 1,'num_posts' => 1,));
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
+ $config = new \phpbb\config\config(array(
+ 'num_topics' => 1,
+ 'num_posts' => 1,
+ 'allow_board_notifications' => true,
+ ));
+ $cache_driver = new \phpbb\cache\driver\dummy();
$cache = new \phpbb\cache\service(
- new \phpbb\cache\driver\null(),
+ $cache_driver,
$config,
$db,
$phpbb_root_path,
@@ -84,8 +88,14 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
// Event dispatcher
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ // Language
+ $lang = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+
// User
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $user = $this->getMock('\phpbb\user', array(), array(
+ $lang,
+ '\phpbb\datetime'
+ ));
$user->ip = '';
$user->data = array(
'user_id' => 2,
@@ -98,34 +108,47 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
$type_cast_helper = $this->getMock('\phpbb\request\type_cast_helper_interface');
$request = $this->getMock('\phpbb\request\request');
- // Container
- $phpbb_container = new phpbb_mock_container_builder();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE));
-
$user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
+ // Container
+ $phpbb_container = new ContainerBuilder();
+ $loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__ . '/fixtures'));
+ $loader->load('services_notification.yml');
+ $phpbb_container->set('user_loader', $user_loader);
+ $phpbb_container->set('user', $user);
+ $phpbb_container->set('language', $lang);
+ $phpbb_container->set('config', $config);
+ $phpbb_container->set('dbal.conn', $db);
+ $phpbb_container->set('auth', $auth);
+ $phpbb_container->set('cache.driver', $cache_driver);
+ $phpbb_container->set('cache', $cache);
+ $phpbb_container->set('text_formatter.utils', new \phpbb\textformatter\s9e\utils());
+ $phpbb_container->set('dispatcher', $phpbb_dispatcher);
+ $phpbb_container->setParameter('core.root_path', $phpbb_root_path);
+ $phpbb_container->setParameter('core.php_ext', $phpEx);
+ $phpbb_container->setParameter('tables.notifications', 'phpbb_notifications');
+ $phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications');
+ $phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types');
+ $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE));
+ $phpbb_container->compile();
+
// Notification Types
$notification_types = array('quote', 'bookmark', 'post', 'post_in_queue', 'topic', 'topic_in_queue', 'approve_topic', 'approve_post');
$notification_types_array = array();
foreach ($notification_types as $type)
{
- $class_name = '\phpbb\notification\type\\' . $type;
- $class = new $class_name(
- $user_loader, $db, $cache->get_driver(), $user, $auth, $config,
- $phpbb_root_path, $phpEx,
- NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE);
-
- $phpbb_container->set('notification.type.' . $type, $class);
-
+ $class = $phpbb_container->get('notification.type.' . $type);
$notification_types_array['notification.type.' . $type] = $class;
}
+ // Methods Types
+ $notification_methods_array = array('notification.method.board' => $phpbb_container->get('notification.method.board'));
+
// Notification Manager
- $phpbb_notifications = new \phpbb\notification\manager($notification_types_array, array(),
- $phpbb_container, $user_loader, $config, $phpbb_dispatcher, $db, $cache, $user,
- $phpbb_root_path, $phpEx,
- NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE);
+ $phpbb_notifications = new \phpbb\notification\manager($notification_types_array, $notification_methods_array,
+ $phpbb_container, $user_loader, $phpbb_dispatcher, $db, $cache, $lang, $user,
+ NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE);
$phpbb_container->set('notification_manager', $phpbb_notifications);
}
diff --git a/tests/notification/submit_post_type_quote_test.php b/tests/notification/submit_post_type_quote_test.php
index 61e3840773..3fab8c05ba 100644
--- a/tests/notification/submit_post_type_quote_test.php
+++ b/tests/notification/submit_post_type_quote_test.php
@@ -51,6 +51,9 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_
*/
public function submit_post_data()
{
+ // The new mock container is needed because the data providers may be executed before phpunit call setUp()
+ $parser = $this->get_test_case_helpers()->set_s9e_services(new phpbb_mock_container_builder())->get('text_formatter.parser');
+
return array(
/**
* Normal post
@@ -65,15 +68,15 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_
*/
array(
array(
- 'message' => implode(' ', array(
- '[quote=&quot;poster&quot;:uid]poster should not be notified[/quote:uid]',
- '[quote=&quot;test&quot;:uid]test should be notified[/quote:uid]',
- '[quote=&quot;unauthorized&quot;:uid]unauthorized to read, should not receive a notification[/quote:uid]',
- '[quote=&quot;notified&quot;:uid]already notified, should not receive a new notification[/quote:uid]',
- '[quote=&quot;disabled&quot;:uid]option disabled, should not receive a notification[/quote:uid]',
- '[quote=&quot;default&quot;:uid]option set to default, should receive a notification[/quote:uid]',
- '[quote=&quot;doesn\'t exist&quot;:uid]user does not exist, should not receive a notification[/quote:uid]',
- )),
+ 'message' => $parser->parse(implode(' ', array(
+ '[quote="poster"]poster should not be notified[/quote]',
+ '[quote="test"]test should be notified[/quote]',
+ '[quote="unauthorized"]unauthorized to read, should not receive a notification[/quote]',
+ '[quote="notified"]already notified, should not receive a new notification[/quote]',
+ '[quote="disabled"]option disabled, should not receive a notification[/quote]',
+ '[quote="default"]option set to default, should receive a notification[/quote]',
+ '[quote="doesn\'t exist"]user does not exist, should not receive a notification[/quote]',
+ ))),
'bbcode_uid' => 'uid',
),
array(
@@ -94,15 +97,15 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_
*/
array(
array(
- 'message' => implode(' ', array(
- '[quote=&quot;poster&quot;:uid]poster should not be notified[/quote:uid]',
- '[quote=&quot;test&quot;:uid]test should be notified[/quote:uid]',
- '[quote=&quot;unauthorized&quot;:uid]unauthorized to read, should not receive a notification[/quote:uid]',
- '[quote=&quot;notified&quot;:uid]already notified, should not receive a new notification[/quote:uid]',
- '[quote=&quot;disabled&quot;:uid]option disabled, should not receive a notification[/quote:uid]',
- '[quote=&quot;default&quot;:uid]option set to default, should receive a notification[/quote:uid]',
- '[quote=&quot;doesn\'t exist&quot;:uid]user does not exist, should not receive a notification[/quote:uid]',
- )),
+ 'message' => $parser->parse(implode(' ', array(
+ '[quote="poster"]poster should not be notified[/quote]',
+ '[quote="test"]test should be notified[/quote]',
+ '[quote="unauthorized"]unauthorized to read, should not receive a notification[/quote]',
+ '[quote="notified"]already notified, should not receive a new notification[/quote]',
+ '[quote="disabled"]option disabled, should not receive a notification[/quote]',
+ '[quote="default"]option set to default, should receive a notification[/quote]',
+ '[quote="doesn\'t exist"]user does not exist, should not receive a notification[/quote]',
+ ))),
'bbcode_uid' => 'uid',
'force_approved_state' => false,
),
diff --git a/tests/notification/submit_post_type_topic_test.php b/tests/notification/submit_post_type_topic_test.php
index c095fbc4ba..f14f305517 100644
--- a/tests/notification/submit_post_type_topic_test.php
+++ b/tests/notification/submit_post_type_topic_test.php
@@ -42,7 +42,7 @@ class phpbb_notification_submit_post_type_topic_test extends phpbb_notification_
),
)));
- $phpbb_log = $this->getMock('\phpbb\log\null');
+ $phpbb_log = $this->getMock('\phpbb\log\dummy');
}
/**
diff --git a/tests/notification/user_list_trim_test.php b/tests/notification/user_list_trim_test.php
index c43eff729c..7d4dff6024 100644
--- a/tests/notification/user_list_trim_test.php
+++ b/tests/notification/user_list_trim_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
{
protected $notification;
@@ -33,11 +30,9 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
$db = $this->new_dbal();
$config = new \phpbb\config\config(array());
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
$cache = new \phpbb\cache\service(
- new \phpbb\cache\driver\null(),
+ new \phpbb\cache\driver\dummy(),
$config,
$db,
$phpbb_root_path,
@@ -53,15 +48,17 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
array('u_viewprofile', 1, false),
)));
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->data = array('user_lang' => 'en');
- $user->add_lang('common');
+ $lang->add_lang('common');
$user_loader = new phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
$user_loader->load_users(array(2, 3, 4, 5, 6));
$this->notification = new phpbb_mock_notification_type_post(
- $user_loader, null, null, $user, null, null, $phpbb_root_path, $phpEx, null, null, null
+ $user_loader, null, null, $lang, $user, null, null, $phpbb_root_path, $phpEx, null, null
);
}
@@ -73,7 +70,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
'topic_title' => 'Test',
'poster_id' => 2,
'post_username' => 'A',
- 'responders' => null,
+ 'responders' => null,
),
'<strong>Reply</strong> from A in topic:',
),
@@ -84,7 +81,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
'post_username' => 'A',
'responders' => array(
array('username' => '', 'poster_id' => 3),
- ),
+ ),
),
'<strong>Reply</strong> from A and <span class="username">B</span> in topic:',
),
@@ -96,7 +93,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
'responders' => array(
array('username' => '', 'poster_id' => 3),
array('username' => '', 'poster_id' => 4),
- ),
+ ),
),
'<strong>Reply</strong> from A, <span class="username">B</span>, and <span class="username">C</span> in topic:',
),
@@ -109,7 +106,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
array('username' => '', 'poster_id' => 3),
array('username' => '', 'poster_id' => 4),
array('username' => '', 'poster_id' => 5),
- ),
+ ),
),
'<strong>Reply</strong> from A, <span class="username">B</span>, <span class="username">C</span>, and <span class="username">D</span> in topic:',
),
@@ -123,7 +120,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
array('username' => '', 'poster_id' => 4),
array('username' => '', 'poster_id' => 5),
array('username' => '', 'poster_id' => 6),
- ),
+ ),
),
'<strong>Reply</strong> from A, <span class="username">B</span>, <span class="username">C</span>, and 2 others in topic:',
),
diff --git a/tests/pagination/config/routing.yml b/tests/pagination/config/test/routing/environment.yml
index 2ce082c9d1..2ce082c9d1 100644
--- a/tests/pagination/config/routing.yml
+++ b/tests/pagination/config/test/routing/environment.yml
diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php
index ea6dd999c3..024b6fc02d 100644
--- a/tests/pagination/pagination_test.php
+++ b/tests/pagination/pagination_test.php
@@ -26,27 +26,27 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case
{
parent::setUp();
- global $phpbb_dispatcher;
+ global $phpbb_dispatcher, $phpbb_root_path, $phpEx;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$this->user->expects($this->any())
->method('lang')
->will($this->returnCallback(array($this, 'return_callback_implode')));
- $filesystem = new \phpbb\filesystem();
+ $filesystem = new \phpbb\filesystem\filesystem();
$manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array());
- $finder = new \phpbb\finder(
- $filesystem,
- dirname(__FILE__) . '/',
- new phpbb_mock_cache()
- );
- $finder->set_extensions(array_keys($manager->all_enabled()));
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1'));
- $provider = new \phpbb\controller\provider();
- $provider->find_routing_files($finder);
- $provider->find(dirname(__FILE__) . '/');
+
+ $loader = new \Symfony\Component\Routing\Loader\YamlFileLoader(
+ new \phpbb\routing\file_locator($filesystem, dirname(__FILE__) . '/')
+ );
+ $resources_locator = new \phpbb\routing\resources_locator\default_resources_locator(dirname(__FILE__) . '/', PHPBB_ENVIRONMENT, $manager);
+ $router = new phpbb_mock_router(new phpbb_mock_container_builder(), $resources_locator, $loader, dirname(__FILE__) . '/', 'php');
$request = new phpbb_mock_request();
$request->overwrite('SCRIPT_NAME', '/app.php', \phpbb\request\request_interface::SERVER);
@@ -57,7 +57,8 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case
$request
);
- $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $provider, $manager, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/');
+ $this->routing_helper = new \phpbb\routing\helper($this->config, $router, $symfony_request, $request, $filesystem, '', 'php');
+ $this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $symfony_request, $request, $this->routing_helper);
$this->pagination = new \phpbb\pagination($this->template, $this->user, $this->helper, $phpbb_dispatcher);
}
diff --git a/tests/path_helper/path_helper_test.php b/tests/path_helper/path_helper_test.php
index 73f0e6bafc..49dd40fbec 100644
--- a/tests/path_helper/path_helper_test.php
+++ b/tests/path_helper/path_helper_test.php
@@ -21,14 +21,14 @@ class phpbb_path_helper_test extends phpbb_test_case
{
parent::setUp();
- $filesystem = new \phpbb\filesystem();
+ $filesystem = new \phpbb\filesystem\filesystem();
$this->set_phpbb_root_path($filesystem);
$this->path_helper = new \phpbb\path_helper(
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ new \phpbb\filesystem\filesystem(),
$this->getMock('\phpbb\request\request'),
$this->phpbb_root_path,
'php'
@@ -56,7 +56,7 @@ class phpbb_path_helper_test extends phpbb_test_case
public function basic_update_web_root_path_data()
{
- $filesystem = new \phpbb\filesystem();
+ $filesystem = new \phpbb\filesystem\filesystem();
$this->set_phpbb_root_path($filesystem);
return array(
@@ -90,7 +90,7 @@ class phpbb_path_helper_test extends phpbb_test_case
public function update_web_root_path_data()
{
- $this->set_phpbb_root_path(new \phpbb\filesystem());
+ $this->set_phpbb_root_path(new \phpbb\filesystem\filesystem());
return array(
array(
@@ -135,6 +135,43 @@ class phpbb_path_helper_test extends phpbb_test_case
'/phpbb3-fork/phpBB/app.php',
'./../',
),
+
+ // No correction if the path is already prepend by the web root path
+ array(
+ './../' . $this->phpbb_root_path . 'test.php',
+ '//',
+ null,
+ null,
+ '',
+ ),
+ array(
+ './../' . $this->phpbb_root_path . 'test.php',
+ '//',
+ 'foo/bar.php',
+ 'bar.php',
+ '',
+ ),
+ array(
+ './../../' . $this->phpbb_root_path . 'test.php',
+ '/foo/template',
+ '/phpbb3-fork/phpBB/app.php/foo/template',
+ '/phpbb3-fork/phpBB/app.php',
+ '',
+ ),
+ array(
+ './../' . $this->phpbb_root_path . 'test.php',
+ '/foo/template',
+ '/phpbb3-fork/phpBB/foo/template',
+ '/phpbb3-fork/phpBB/app.php',
+ '',
+ ),
+ array(
+ './../'.$this->phpbb_root_path . 'test.php',
+ '/',
+ '/phpbb3-fork/phpBB/app.php/',
+ '/phpbb3-fork/phpBB/app.php',
+ '',
+ ),
);
}
@@ -158,7 +195,7 @@ class phpbb_path_helper_test extends phpbb_test_case
$path_helper = new \phpbb\path_helper(
$symfony_request,
- new \phpbb\filesystem(),
+ new \phpbb\filesystem\filesystem(),
$this->getMock('\phpbb\request\request'),
$this->phpbb_root_path,
'php'
diff --git a/tests/plupload/plupload_test.php b/tests/plupload/plupload_test.php
index 2f47bf2b39..3312f4d0a0 100644
--- a/tests/plupload/plupload_test.php
+++ b/tests/plupload/plupload_test.php
@@ -34,6 +34,10 @@ class phpbb_plupload_test extends phpbb_test_case
*/
public function test_generate_resize_string($config_width, $config_height, $expected)
{
+ global $phpbb_root_path, $phpEx;
+
+ $lang = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+
$config = new \phpbb\config\config(array(
'img_max_width' => $config_width,
'img_max_height' => $config_height,
@@ -43,8 +47,8 @@ class phpbb_plupload_test extends phpbb_test_case
'',
$config,
new phpbb_mock_request,
- new \phpbb\user('\phpbb\datetime'),
- new \phpbb\php\ini,
+ new \phpbb\user($lang, '\phpbb\datetime'),
+ new \bantu\IniGetWrapper\IniGetWrapper,
new \phpbb\mimetype\guesser(array(new \phpbb\mimetype\extension_guesser))
);
diff --git a/tests/privmsgs/delete_user_pms_test.php b/tests/privmsgs/delete_user_pms_test.php
index 0f061e9784..9d6ba7a917 100644
--- a/tests/privmsgs/delete_user_pms_test.php
+++ b/tests/privmsgs/delete_user_pms_test.php
@@ -85,12 +85,14 @@ class phpbb_privmsgs_delete_user_pms_test extends phpbb_database_test_case
*/
public function test_delete_user_pms($delete_user, $remaining_privmsgs, $remaining_privmsgs_to)
{
- global $db, $phpbb_container;
+ global $db, $phpbb_container, $phpbb_root_path;
$db = $this->new_dbal();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
+ // Works as a workaround for tests
+ $phpbb_container->set('attachment.manager', new \phpbb\attachment\delete(new \phpbb\config\config(array()), $db, new \phpbb_mock_event_dispatcher(), new \phpbb\filesystem\filesystem(), new \phpbb\attachment\resync($db), $phpbb_root_path));
phpbb_delete_user_pms($delete_user);
diff --git a/tests/profilefields/type_bool_test.php b/tests/profilefields/type_bool_test.php
index 41c40ddb4b..10239172c3 100644
--- a/tests/profilefields/type_bool_test.php
+++ b/tests/profilefields/type_bool_test.php
@@ -25,7 +25,12 @@ class phpbb_profilefield_type_bool_test extends phpbb_test_case
*/
public function setUp()
{
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$user->expects($this->any())
->method('lang')
->will($this->returnCallback(array($this, 'return_callback_implode')));
diff --git a/tests/profilefields/type_date_test.php b/tests/profilefields/type_date_test.php
index 123955198e..e0807b2f9b 100644
--- a/tests/profilefields/type_date_test.php
+++ b/tests/profilefields/type_date_test.php
@@ -25,7 +25,12 @@ class phpbb_profilefield_type_date_test extends phpbb_test_case
*/
public function setUp()
{
- $this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $this->user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$this->user->expects($this->any())
->method('lang')
->will($this->returnCallback(array($this, 'return_callback_implode')));
diff --git a/tests/profilefields/type_dropdown_test.php b/tests/profilefields/type_dropdown_test.php
index 3845a8e96b..ab02353fb9 100644
--- a/tests/profilefields/type_dropdown_test.php
+++ b/tests/profilefields/type_dropdown_test.php
@@ -25,7 +25,12 @@ class phpbb_profilefield_type_dropdown_test extends phpbb_test_case
*/
public function setUp()
{
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$user->expects($this->any())
->method('lang')
->will($this->returnCallback(array($this, 'return_callback_implode')));
diff --git a/tests/profilefields/type_googleplus_test.php b/tests/profilefields/type_googleplus_test.php
index f3db6ef01f..9222362214 100644
--- a/tests/profilefields/type_googleplus_test.php
+++ b/tests/profilefields/type_googleplus_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_profilefield_type_googleplus_test extends phpbb_test_case
{
protected $field;
@@ -21,7 +19,11 @@ class phpbb_profilefield_type_googleplus_test extends phpbb_test_case
{
parent::setUp();
- $user = new \phpbb\user('\phpbb\datetime');
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->add_lang('ucp');
$request = $this->getMock('\phpbb\request\request');
$template = $this->getMock('\phpbb\template\template');
diff --git a/tests/profilefields/type_int_test.php b/tests/profilefields/type_int_test.php
index 07b22525e2..33f3f575c8 100644
--- a/tests/profilefields/type_int_test.php
+++ b/tests/profilefields/type_int_test.php
@@ -24,7 +24,12 @@ class phpbb_profilefield_type_int_test extends phpbb_test_case
*/
public function setUp()
{
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$user->expects($this->any())
->method('lang')
->will($this->returnCallback(array($this, 'return_callback_implode')));
diff --git a/tests/profilefields/type_string_test.php b/tests/profilefields/type_string_test.php
index 0417afbfab..7c7fa3f3e6 100644
--- a/tests/profilefields/type_string_test.php
+++ b/tests/profilefields/type_string_test.php
@@ -11,10 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_profilefield_type_string_test extends phpbb_test_case
{
protected $cp;
@@ -28,9 +24,12 @@ class phpbb_profilefield_type_string_test extends phpbb_test_case
*/
public function setUp()
{
- global $request, $user, $cache;
+ global $request, $user, $cache, $phpbb_root_path, $phpEx;
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$cache = new phpbb_mock_cache;
$user->expects($this->any())
->method('lang')
diff --git a/tests/profilefields/type_url_test.php b/tests/profilefields/type_url_test.php
index cc37f04f30..1d90e2c34c 100644
--- a/tests/profilefields/type_url_test.php
+++ b/tests/profilefields/type_url_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_profilefield_type_url_test extends phpbb_test_case
{
protected $cp;
@@ -26,7 +24,12 @@ class phpbb_profilefield_type_url_test extends phpbb_test_case
*/
public function setUp()
{
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ global $phpbb_root_path, $phpEx;
+
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$user->expects($this->any())
->method('lang')
->will($this->returnCallback(array($this, 'return_callback_implode')));
diff --git a/tests/random/gen_rand_string_test.php b/tests/random/gen_rand_string_test.php
index 1d12d0622c..a9d1ea20de 100644
--- a/tests/random/gen_rand_string_test.php
+++ b/tests/random/gen_rand_string_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_random_gen_rand_string_test extends phpbb_test_case
{
const TEST_COUNT = 100;
diff --git a/tests/regex/censor_test.php b/tests/regex/censor_test.php
index 50c6778c8c..5a516b71de 100644
--- a/tests/regex/censor_test.php
+++ b/tests/regex/censor_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_regex_censor_test extends phpbb_test_case
{
public function censor_test_data()
@@ -37,18 +35,8 @@ class phpbb_regex_censor_test extends phpbb_test_case
*/
public function test_censor_unicode($pattern, $subject)
{
- $regex = get_censor_preg_expression($pattern, true);
-
- $this->assertRegExp($regex, $subject);
- }
-
- /**
- * @dataProvider censor_test_data
- */
- public function test_censor_no_unicode($pattern, $subject)
- {
- $regex = get_censor_preg_expression($pattern, false);
+ $regex = get_censor_preg_expression($pattern);
$this->assertRegExp($regex, $subject);
}
-} \ No newline at end of file
+}
diff --git a/tests/regex/email_test.php b/tests/regex/email_test.php
index ede35c49bc..5187b8bda6 100644
--- a/tests/regex/email_test.php
+++ b/tests/regex/email_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_regex_email_test extends phpbb_test_case
{
protected $regex;
diff --git a/tests/regex/ipv4_test.php b/tests/regex/ipv4_test.php
index 62c2567517..e21a2d77fa 100644
--- a/tests/regex/ipv4_test.php
+++ b/tests/regex/ipv4_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_regex_ipv4_test extends phpbb_test_case
{
protected $regex;
diff --git a/tests/regex/ipv6_test.php b/tests/regex/ipv6_test.php
index 41039c819d..223161df7f 100644
--- a/tests/regex/ipv6_test.php
+++ b/tests/regex/ipv6_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_regex_ipv6_test extends phpbb_test_case
{
protected $regex;
diff --git a/tests/regex/password_complexity_test.php b/tests/regex/password_complexity_test.php
index 8a1a9edd41..933dc1ac91 100644
--- a/tests/regex/password_complexity_test.php
+++ b/tests/regex/password_complexity_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
class phpbb_password_complexity_test extends phpbb_test_case
diff --git a/tests/regex/table_prefix_test.php b/tests/regex/table_prefix_test.php
index c593085b25..bf7b59ccc6 100644
--- a/tests/regex/table_prefix_test.php
+++ b/tests/regex/table_prefix_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_regex_table_prefix_test extends phpbb_test_case
{
public function table_prefix_test_data()
diff --git a/tests/regex/url_test.php b/tests/regex/url_test.php
index e5d7c3256a..5e2a22bf73 100644
--- a/tests/regex/url_test.php
+++ b/tests/regex/url_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_regex_url_test extends phpbb_test_case
{
public function url_test_data()
diff --git a/tests/request/request_var_test.php b/tests/request/request_var_test.php
index 67712eb6c8..84c81c4e84 100644
--- a/tests/request/request_var_test.php
+++ b/tests/request/request_var_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_request_var_test extends phpbb_test_case
{
/**
diff --git a/tests/request/type_cast_helper_test.php b/tests/request/type_cast_helper_test.php
index d6ee1dc728..143c05aa9c 100644
--- a/tests/request/type_cast_helper_test.php
+++ b/tests/request/type_cast_helper_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_type_cast_helper_test extends phpbb_test_case
{
private $type_cast_helper;
diff --git a/tests/security/base.php b/tests/security/base.php
index 330408b448..d2abdbc362 100644
--- a/tests/security/base.php
+++ b/tests/security/base.php
@@ -46,10 +46,12 @@ abstract class phpbb_security_test_base extends phpbb_test_case
$request = new phpbb_mock_request(array(), array(), array(), $this->server);
$symfony_request = new \phpbb\symfony_request($request);
- $phpbb_filesystem = new \phpbb\filesystem();
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
// Set no user and trick a bit to circumvent errors
- $user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->lang = true;
$user->browser = $this->server['HTTP_USER_AGENT'];
$user->referer = '';
diff --git a/tests/security/extract_current_page_test.php b/tests/security/extract_current_page_test.php
index 767b901a43..f764449eca 100644
--- a/tests/security/extract_current_page_test.php
+++ b/tests/security/extract_current_page_test.php
@@ -13,7 +13,6 @@
require_once dirname(__FILE__) . '/base.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_security_extract_current_page_test extends phpbb_security_test_base
{
diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php
index 0494c55c6d..84d4fcf479 100644
--- a/tests/security/hash_test.php
+++ b/tests/security/hash_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compatibility.php';
-
class phpbb_security_hash_test extends phpbb_test_case
{
public function setUp()
diff --git a/tests/security/redirect_test.php b/tests/security/redirect_test.php
index a88fc63858..40cb7d2f04 100644
--- a/tests/security/redirect_test.php
+++ b/tests/security/redirect_test.php
@@ -13,7 +13,6 @@
require_once dirname(__FILE__) . '/base.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_security_redirect_test extends phpbb_security_test_base
{
@@ -67,7 +66,7 @@ class phpbb_security_redirect_test extends phpbb_security_test_base
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ new \phpbb\filesystem\filesystem(),
$this->getMock('\phpbb\request\request'),
$this->phpbb_root_path,
'php'
diff --git a/tests/session/append_sid_test.php b/tests/session/append_sid_test.php
index 2a1d94514f..4e5a238644 100644
--- a/tests/session/append_sid_test.php
+++ b/tests/session/append_sid_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_session_append_sid_test extends phpbb_test_case
{
diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php
index 561b7faf49..04da5f08b9 100644
--- a/tests/session/check_ban_test.php
+++ b/tests/session/check_ban_test.php
@@ -42,7 +42,10 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case
parent::setUp();
// Get session here so that config is mocked correctly
$this->session = $this->session_factory->get_session($this->db);
- global $cache, $config, $phpbb_root_path, $phpEx;
+ global $cache, $config, $phpbb_root_path, $phpEx, $phpbb_filesystem;
+
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
+
$this->backup_cache = $cache;
// Change the global cache object for this test because
// the mock cache object does not hit the database as is needed
diff --git a/tests/session/extract_page_test.php b/tests/session/extract_page_test.php
index f0d1cdb60e..88eb7b2c1a 100644
--- a/tests/session/extract_page_test.php
+++ b/tests/session/extract_page_test.php
@@ -12,7 +12,6 @@
*/
require_once dirname(__FILE__) . '/../test_framework/phpbb_session_test_case.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_session_extract_page_test extends phpbb_session_test_case
{
@@ -145,7 +144,7 @@ class phpbb_session_extract_page_test extends phpbb_session_test_case
{
global $symfony_request, $request, $phpbb_filesystem;
- $phpbb_filesystem = new \phpbb\filesystem();
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
$server['HTTP_HOST'] = 'localhost';
$server['SERVER_NAME'] = 'localhost';
diff --git a/tests/session/garbage_collection_test.php b/tests/session/garbage_collection_test.php
index 3fad81c68b..3dc591a328 100644
--- a/tests/session/garbage_collection_test.php
+++ b/tests/session/garbage_collection_test.php
@@ -12,7 +12,6 @@
*/
require_once dirname(__FILE__) . '/../test_framework/phpbb_session_test_case.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_session_garbage_collection_test extends phpbb_session_test_case
{
diff --git a/tests/session/session_key_test.php b/tests/session/session_key_test.php
index bf3dfcaa3c..2499ea1d55 100644
--- a/tests/session/session_key_test.php
+++ b/tests/session/session_key_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../test_framework/phpbb_session_test_case.php';
class phpbb_session_login_keys_test extends phpbb_session_test_case
diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php
index 3e25286480..6f8b49122b 100644
--- a/tests/session/testable_factory.php
+++ b/tests/session/testable_factory.php
@@ -73,7 +73,7 @@ class phpbb_session_testable_factory
public function get_session(\phpbb\db\driver\driver_interface $dbal)
{
// set up all the global variables used by session
- global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container;
+ global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container, $phpbb_root_path;
$request = $this->request = new phpbb_mock_request(
array(),
@@ -81,10 +81,8 @@ class phpbb_session_testable_factory
$this->cookies,
$this->server_data
);
- request_var(null, null, null, null, $request);
$config = $this->config = new \phpbb\config\config($this->get_config_data());
- set_config(null, null, null, $config);
$db = $dbal;
@@ -96,6 +94,8 @@ class phpbb_session_testable_factory
'auth.provider.db',
new phpbb_mock_auth_provider()
);
+ $phpbb_container->setParameter('core.environment', PHPBB_ENVIRONMENT);
+ $phpbb_container->setParameter('core.cache_dir', $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/');
$provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config);
$provider_collection->add('auth.provider.db');
$phpbb_container->set(
diff --git a/tests/template/asset_test.php b/tests/template/asset_test.php
new file mode 100644
index 0000000000..3d2fdd8959
--- /dev/null
+++ b/tests/template/asset_test.php
@@ -0,0 +1,49 @@
+<?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.
+*
+*/
+
+use phpbb\template\asset;
+
+class phpbb_template_asset_test extends phpbb_test_case
+{
+ public function set_path_data()
+ {
+ return array(
+ // array(phpbb_root_path, given path, expected path),
+ array('.', 'foo/bar', 'foo/bar'),
+ array('../', 'foo/bar', 'foo/bar'),
+ array('./phpBB/', 'foo/bar', 'foo/bar'),
+ array('../', __DIR__ . '/foo/bar', '../' . basename(dirname(dirname(__DIR__))) . '/tests/template/foo/bar'),
+ array('./', __DIR__ . '/foo/bar', './tests/template/foo/bar'),
+ array('./phpBB/', __DIR__ . '/foo/bar', 'tests/template/foo/bar'),
+ );
+ }
+
+ /**
+ * @dataProvider set_path_data
+ */
+ public function test_set_path($phpbb_root_path, $path, $expected)
+ {
+ $path_helper = $this->getMockBuilder('\phpbb\path_helper')
+ ->disableOriginalConstructor()
+ ->setMethods(array())
+ ->getMock();
+
+ $path_helper->method('get_phpbb_root_path')
+ ->willReturn($phpbb_root_path);
+
+ $asset = new asset('', $path_helper, new phpbb\filesystem\filesystem());
+
+ $asset->set_path($path, true);
+ $this->assertEquals($expected, $asset->get_path());
+ }
+}
diff --git a/tests/template/includephp_test.php b/tests/template/includephp_test.php
index fdddbef4f2..722e10e42d 100644
--- a/tests/template/includephp_test.php
+++ b/tests/template/includephp_test.php
@@ -39,8 +39,9 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case
{
global $phpbb_root_path;
+ $filesystem = new \phpbb\filesystem\filesystem();
$path_to_php = str_replace('\\', '/', dirname(__FILE__)) . '/templates/_dummy_include.php.inc';
- $this->assertTrue(phpbb_is_absolute($path_to_php));
+ $this->assertTrue($filesystem->is_absolute_path($path_to_php));
$template_text = "Path is absolute.\n<!-- INCLUDEPHP $path_to_php -->";
$cache_dir = $phpbb_root_path . 'cache/';
diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php
index b4ad84e9c3..9a0a42fabd 100644
--- a/tests/template/template_allfolder_test.php
+++ b/tests/template/template_allfolder_test.php
@@ -28,13 +28,18 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case
$defaults = $this->config_defaults();
$config = new \phpbb\config\config(array_merge($defaults, $new_config));
- $this->user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $this->user = $user;
+
+ $filesystem = new \phpbb\filesystem\filesystem();
$path_helper = new \phpbb\path_helper(
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ $filesystem,
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
$phpEx
@@ -51,9 +56,29 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case
)
);
+ $container = new phpbb_mock_container_builder();
+ $cache_path = $phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), '');
+ $twig = new \phpbb\template\twig\environment(
+ $config,
+ $filesystem,
+ $path_helper,
+ $cache_path,
+ $this->extension_manager,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
+ $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager);
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
+
$this->template_path = $this->test_path . '/templates';
$this->ext_template_path = 'tests/extension/ext/vendor4/bar/styles/all/template';
- $this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, new \phpbb\template\context(), $this->extension_manager);
$this->template->set_custom_style('all', array($this->template_path, $this->ext_template_path));
}
}
diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php
index c415c969fe..e245c90aee 100644
--- a/tests/template/template_events_test.php
+++ b/tests/template/template_events_test.php
@@ -138,16 +138,39 @@ Zeta test event in all',
$this->extension_manager = new phpbb_mock_filesystem_extension_manager(
dirname(__FILE__) . "/datasets/$dataset/"
);
+
+ $filesystem = new \phpbb\filesystem\filesystem();
$path_helper = new \phpbb\path_helper(
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ new \phpbb\filesystem\filesystem(),
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
$phpEx
);
- $this->template = new \phpbb\template\twig\twig($path_helper, $config, $user, new \phpbb\template\context, $this->extension_manager);
+
+ $container = new phpbb_mock_container_builder();
+ $cache_path = $phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), '');
+ $twig = new \phpbb\template\twig\environment(
+ $config,
+ $filesystem,
+ $path_helper,
+ $cache_path,
+ $this->extension_manager,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
+ $this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager);
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
+
$this->template->set_custom_style(((!empty($style_names)) ? $style_names : 'silver'), array($this->template_path));
}
}
diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php
index b025cd21d5..764652c9c2 100644
--- a/tests/template/template_includecss_test.php
+++ b/tests/template/template_includecss_test.php
@@ -15,6 +15,12 @@ require_once dirname(__FILE__) . '/template_test_case_with_tree.php';
class phpbb_template_template_includecss_test extends phpbb_template_template_test_case_with_tree
{
+ /** @var \phpbb\path_helper */
+ protected $phpbb_path_helper;
+
+ /** @var string */
+ protected $parent_template_path;
+
protected function setup_engine(array $new_config = array())
{
global $phpbb_root_path, $phpEx, $user;
@@ -22,11 +28,13 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
$defaults = $this->config_defaults();
$config = new \phpbb\config\config(array_merge($defaults, $new_config));
+ $filesystem = new \phpbb\filesystem\filesystem();
+
$this->phpbb_path_helper = new \phpbb\path_helper(
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ $filesystem,
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
$phpEx
@@ -34,11 +42,32 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
$this->template_path = $this->test_path . '/templates';
$this->parent_template_path = $this->test_path . '/parent_templates';
+ $container = new phpbb_mock_container_builder();
+ $cache_path = $phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), '');
+ $twig = new \phpbb\template\twig\environment(
+ $config,
+ $filesystem,
+ $this->phpbb_path_helper,
+ $cache_path,
+ null,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
$this->template = new phpbb\template\twig\twig(
$this->phpbb_path_helper,
$config,
- $user,
- new phpbb\template\context(),
+ $context,
+ $twig,
+ $cache_path,
+ $this->user,
+ array(new \phpbb\template\twig\extension($context, $this->user)),
new phpbb_mock_extension_manager(
dirname(__FILE__) . '/',
array(
@@ -50,6 +79,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te
)
)
);
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path));
}
diff --git a/tests/template/template_parser_test.php b/tests/template/template_parser_test.php
index d32fe78391..938b1bc8b8 100644
--- a/tests/template/template_parser_test.php
+++ b/tests/template/template_parser_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/template_test_case.php';
class phpbb_template_template_parser_test extends phpbb_template_template_test_case
diff --git a/tests/template/template_test.php b/tests/template/template_test.php
index 0bbfe3848d..63e7cb869a 100644
--- a/tests/template/template_test.php
+++ b/tests/template/template_test.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/template_test_case.php';
class phpbb_template_template_test extends phpbb_template_template_test_case
@@ -130,6 +129,34 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1",
),
array(
+ 'loop_twig.html',
+ array(),
+ array(),
+ array(),
+ "noloop\nnoloop",
+ ),
+ array(
+ 'loop_twig.html',
+ array(),
+ array('test_loop' => array(array())),
+ array(),
+ "loop\nloop",
+ ),
+ array(
+ 'loop_twig.html',
+ array(),
+ array('test_loop' => array(array(), array()), 'test_loop.block' => array(array())),
+ array(),
+ "loop\nloop\nloop\nloop",
+ ),
+ array(
+ 'loop_twig.html',
+ array(),
+ array('test_loop' => array(array(), array()), 'test_loop.block' => array(array()), 'block' => array(array(), array())),
+ array(),
+ "loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1",
+ ),
+ array(
'loop_vars.html',
array(),
array('test_loop' => array(array('VARIABLE' => 'x'))),
@@ -151,6 +178,27 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner",
),
array(
+ 'loop_vars_twig.html',
+ array(),
+ array('test_loop' => array(array('VARIABLE' => 'x'))),
+ array(),
+ "first\n0 - a\nx - b\nset\nlast",
+ ),
+ array(
+ 'loop_vars_twig.html',
+ array(),
+ array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y'))),
+ array(),
+ "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast",
+ ),
+ array(
+ 'loop_vars_twig.html',
+ array(),
+ array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'test_loop.inner' => array(array(), array())),
+ array(),
+ "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner",
+ ),
+ array(
'loop_advanced.html',
array(),
array('test_loop' => array(array(), array(), array(), array(), array(), array(), array())),
@@ -158,6 +206,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561",
),
array(
+ 'loop_advanced_twig.html',
+ array(),
+ array('test_loop' => array(array(), array(), array(), array(), array(), array(), array())),
+ array(),
+ "101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561",
+ ),
+ array(
'loop_nested2.html',
array(),
array('outer' => array(array(), array()), 'outer.middle' => array(array(), array())),
@@ -165,6 +220,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"o0o1m01m11",
),
array(
+ 'loop_nested2_twig.html',
+ array(),
+ array('outer' => array(array(), array()), 'outer.middle' => array(array(), array())),
+ array(),
+ "o0o1m01m11",
+ ),
+ array(
'define.html',
array(),
array('test_loop' => array(array(), array(), array(), array(), array(), array(), array()), 'test' => array(array()), 'test.deep' => array(array()), 'test.deep.defines' => array(array())),
@@ -244,6 +306,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
'',
),
array(
+ 'loop_vars_twig.html',
+ array(),
+ array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'test_loop.inner' => array(array(), array())),
+ array('test_loop'),
+ '',
+ ),
+ array(
'include_define_variable.html',
array('VARIABLE' => 'variable.html'),
array(),
@@ -275,6 +344,15 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"noloop\nnoloop",
),
array(
+ // Just like a regular loop but the name begins
+ // with an underscore
+ 'loop_underscore_twig.html',
+ array(),
+ array(),
+ array(),
+ "noloop\nnoloop",
+ ),
+ array(
'lang.html',
array(),
array(),
@@ -286,7 +364,7 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
array(),
array(),
array(),
- "Value'\n1 O'Clock\nValue\'\n1 O\'Clock",
+ "Value'\n1 O'Clock\nValue\\x27\n1\\x20O\\x27Clock",
array('VARIABLE' => "Value'", '1_VARIABLE' => "1 O'Clock"),
),
array(
@@ -297,6 +375,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"top-level content",
),
array(
+ 'loop_nested_multilevel_ref_twig.html',
+ array(),
+ array(),
+ array(),
+ "top-level content",
+ ),
+ array(
'loop_nested_multilevel_ref.html',
array(),
array('outer' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'outer.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))),
@@ -304,6 +389,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz",
),
array(
+ 'loop_nested_multilevel_ref_twig.html',
+ array(),
+ array('outer' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'outer.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))),
+ array(),
+ "top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz",
+ ),
+ array(
'loop_nested_deep_multilevel_ref.html',
array(),
array('outer' => array(array()), 'outer.middle' => array(array()), 'outer.middle.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))),
@@ -311,6 +403,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz",
),
array(
+ 'loop_nested_deep_multilevel_ref_twig.html',
+ array(),
+ array('outer' => array(array()), 'outer.middle' => array(array()), 'outer.middle.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))),
+ array(),
+ "top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz",
+ ),
+ array(
'loop_size.html',
array(),
array('test_loop' => array(array()), 'empty_loop' => array()),
@@ -318,6 +417,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop",
),
array(
+ 'loop_size_twig.html',
+ array(),
+ array('test_loop' => array(array()), 'empty_loop' => array()),
+ array(),
+ "nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop",
+ ),
+ array(
'loop_include.html',
array(),
array('test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1'))),
@@ -325,6 +431,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"barbarbar1bar1",
),
array(
+ 'loop_include_twig.html',
+ array(),
+ array('test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1'))),
+ array(),
+ "barbarbar1bar1",
+ ),
+ array(
'loop_nested_include.html',
array(),
array(
@@ -335,6 +448,17 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
"[bar|[bar|]][bar1|[bar1|[bar1|works]]]",
array(),
),
+ array(
+ 'loop_nested_include_twig.html',
+ array(),
+ array(
+ 'test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1')),
+ 'test_loop.inner' => array(array('myinner' => 'works')),
+ ),
+ array(),
+ "[bar|[bar|]][bar1|[bar1|[bar1|works]]]",
+ array(),
+ ),
/* Does not pass with the current implementation.
array(
'loop_reuse.html',
@@ -343,8 +467,15 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
array(),
// Not entirely sure what should be outputted but the current output of "a" is most certainly wrong
"a\nb\nc\nd",
+ ),*/
+ array(
+ 'loop_reuse_twig.html',
+ array(),
+ array('one' => array(array('VAR' => 'a'), array('VAR' => 'b')), 'one.one' => array(array('VAR' => 'c'), array('VAR' => 'd'))),
+ array(),
+ // Not entirely sure what should be outputted but the current output of "a" is most certainly wrong
+ "a\nb\nc\nd",
),
- */
array(
'twig.html',
array('VARIABLE' => 'FOObar',),
@@ -359,6 +490,27 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
array(),
'inner_value',
),
+ array(
+ 'loop_expressions.html',
+ array(),
+ array('loop' => array(array(),array(),array(),array(),array(),array()),),
+ array(),
+ 'yesnononoyesnoyesnonoyesnono',
+ ),
+ array(
+ 'loop_expressions_twig.html',
+ array(),
+ array('loop' => array(array(),array(),array(),array(),array(),array()),),
+ array(),
+ 'yesnononoyesnoyesnonoyesnono',
+ ),
+ array(
+ 'loop_expressions_twig2.html',
+ array('loop' => array(array(),array(),array(),array(),array(),array()),),
+ array(),
+ array(),
+ 'yesnononoyesnoyesnonoyesnono',
+ ),
);
}
diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php
index 1250397401..e52d3b76dd 100644
--- a/tests/template/template_test_case.php
+++ b/tests/template/template_test_case.php
@@ -11,10 +11,9 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_template_template_test_case extends phpbb_test_case
{
+ protected $lang;
protected $template;
protected $template_path;
protected $user;
@@ -24,6 +23,17 @@ class phpbb_template_template_test_case extends phpbb_test_case
// Keep the contents of the cache for debugging?
const PRESERVE_CACHE = true;
+ static protected $language_reflection_lang;
+
+ static public function setUpBeforeClass()
+ {
+ parent::setUpBeforeClass();
+
+ $reflection = new ReflectionClass('\phpbb\language\language');
+ self::$language_reflection_lang = $reflection->getProperty('lang');
+ self::$language_reflection_lang->setAccessible(true);
+ }
+
protected function display($handle)
{
ob_start();
@@ -65,20 +75,45 @@ class phpbb_template_template_test_case extends phpbb_test_case
$defaults = $this->config_defaults();
$config = new \phpbb\config\config(array_merge($defaults, $new_config));
- $this->user = new \phpbb\user('\phpbb\datetime');
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $this->lang = $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $this->user = $user;
+
+ $filesystem = new \phpbb\filesystem\filesystem();
$path_helper = new \phpbb\path_helper(
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ $filesystem,
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
$phpEx
);
$this->template_path = $this->test_path . '/templates';
- $this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, new \phpbb\template\context());
+
+ $container = new phpbb_mock_container_builder();
+ $cache_path = $phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), '');
+ $twig = new \phpbb\template\twig\environment(
+ $config,
+ $filesystem,
+ $path_helper,
+ $cache_path,
+ null,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
+ $this->template = new phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)));
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template->set_custom_style('tests', $this->template_path);
}
@@ -88,6 +123,10 @@ class phpbb_template_template_test_case extends phpbb_test_case
$this->setup_engine();
$this->template->clear_cache();
+
+ global $phpbb_filesystem;
+
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
}
protected function tearDown()
@@ -121,12 +160,16 @@ class phpbb_template_template_test_case extends phpbb_test_case
{
foreach ($lang_vars as $name => $value)
{
- $this->user->lang[$name] = $value;
+ self::$language_reflection_lang->setValue($this->lang, array_merge(
+ self::$language_reflection_lang->getValue($this->lang),
+ array($name => $value)
+ ));
}
}
$expected = str_replace(array("\n", "\r", "\t"), '', $expected);
$output = str_replace(array("\n", "\r", "\t"), '', $this->display('test'));
+
$this->assertEquals($expected, $output, "Testing $file");
}
}
diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php
index 68ecc4b706..ff35d16120 100644
--- a/tests/template/template_test_case_with_tree.php
+++ b/tests/template/template_test_case_with_tree.php
@@ -22,11 +22,13 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
$defaults = $this->config_defaults();
$config = new \phpbb\config\config(array_merge($defaults, $new_config));
+ $filesystem = new \phpbb\filesystem\filesystem();
+
$this->phpbb_path_helper = new \phpbb\path_helper(
new \phpbb\symfony_request(
new phpbb_mock_request()
),
- new \phpbb\filesystem(),
+ $filesystem,
$this->getMock('\phpbb\request\request'),
$phpbb_root_path,
$phpEx
@@ -34,7 +36,27 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
$this->template_path = $this->test_path . '/templates';
$this->parent_template_path = $this->test_path . '/parent_templates';
- $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $user, new phpbb\template\context());
+
+ $container = new phpbb_mock_container_builder();
+ $cache_path = $phpbb_root_path . 'cache/twig';
+ $context = new \phpbb\template\context();
+ $loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), '');
+ $twig = new \phpbb\template\twig\environment(
+ $config,
+ $filesystem,
+ $this->phpbb_path_helper,
+ $cache_path,
+ null,
+ $loader,
+ array(
+ 'cache' => false,
+ 'debug' => false,
+ 'auto_reload' => true,
+ 'autoescape' => false,
+ )
+ );
+ $this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)));
+ $twig->setLexer(new \phpbb\template\twig\lexer($twig));
$this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path));
}
}
diff --git a/tests/template/templates/loop_advanced_twig.html b/tests/template/templates/loop_advanced_twig.html
new file mode 100644
index 0000000000..fd9fcae045
--- /dev/null
+++ b/tests/template/templates/loop_advanced_twig.html
@@ -0,0 +1,19 @@
+{% for test_loop_inner in test_loop %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(0) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(0,-1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(1,1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(0,1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(2,4) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(0,-7) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(-2,6) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
+x
+{% for test_loop_inner in test_loop|subset(-2,-1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %}
diff --git a/tests/template/templates/loop_expressions.html b/tests/template/templates/loop_expressions.html
index 6bff53f388..ddb9fd52fa 100644
--- a/tests/template/templates/loop_expressions.html
+++ b/tests/template/templates/loop_expressions.html
@@ -1,11 +1,11 @@
<!-- BEGIN loop -->
-<!-- IF loop.S_ROW_NUM is even by 4 -->on<!-- ELSE -->off<!-- ENDIF -->
+<!-- IF loop.S_ROW_NUM is divisible by(4) -->yes<!-- ELSE -->no<!-- ENDIF -->
<!-- END loop -->
<!-- BEGIN loop -->
-<!-- IF loop.S_ROW_NUM is odd by 3 -->on<!-- ELSE -->off<!-- ENDIF -->
+<!-- IF loop.S_ROW_NUM is divisible by(3) -->yes<!-- ELSE -->no<!-- ENDIF -->
<!-- END loop -->
diff --git a/tests/template/templates/loop_expressions_twig.html b/tests/template/templates/loop_expressions_twig.html
new file mode 100644
index 0000000000..5ca8cc3601
--- /dev/null
+++ b/tests/template/templates/loop_expressions_twig.html
@@ -0,0 +1,11 @@
+{% for loop_inner in loop %}
+
+{% if loop_inner.S_ROW_NUM is divisible by(4) %}yes{% else %}no{% endif %}
+
+{% endfor %}
+
+{% for loop_inner in loop %}
+
+{% if loop_inner.S_ROW_NUM is divisible by(3) %}yes{% else %}no{% endif %}
+
+{% endfor %}
diff --git a/tests/template/templates/loop_expressions_twig2.html b/tests/template/templates/loop_expressions_twig2.html
new file mode 100644
index 0000000000..16159ead4c
--- /dev/null
+++ b/tests/template/templates/loop_expressions_twig2.html
@@ -0,0 +1,11 @@
+{% for loop_inner in loop %}
+
+{% if loop.index0 is divisible by(4) %}yes{% else %}no{% endif %}
+
+{% endfor %}
+
+{% for loop_inner in loop %}
+
+{% if loop.index0 is divisible by(3) %}yes{% else %}no{% endif %}
+
+{% endfor %}
diff --git a/tests/template/templates/loop_include1_twig.html b/tests/template/templates/loop_include1_twig.html
new file mode 100644
index 0000000000..2ff9f61b02
--- /dev/null
+++ b/tests/template/templates/loop_include1_twig.html
@@ -0,0 +1 @@
+{{ test_loop_inner.foo }}
diff --git a/tests/template/templates/loop_include_twig.html b/tests/template/templates/loop_include_twig.html
new file mode 100644
index 0000000000..1a534e2dbc
--- /dev/null
+++ b/tests/template/templates/loop_include_twig.html
@@ -0,0 +1,4 @@
+{% for test_loop_inner in test_loop %}
+ {{ test_loop_inner.foo }}
+ {% INCLUDE 'loop_include1_twig.html' %}
+{% endfor %}
diff --git a/tests/template/templates/loop_nested2_twig.html b/tests/template/templates/loop_nested2_twig.html
new file mode 100644
index 0000000000..cf802dc69f
--- /dev/null
+++ b/tests/template/templates/loop_nested2_twig.html
@@ -0,0 +1,6 @@
+{% for outer_inner in outer %}
+ o{{ outer_inner.S_ROW_COUNT }}
+ {% for middle in outer_inner.middle %}
+ m{{ middle.S_ROW_COUNT }}{{ outer_inner.S_ROW_COUNT }}
+ {% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html b/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html
new file mode 100644
index 0000000000..9bc68e6e2e
--- /dev/null
+++ b/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html
@@ -0,0 +1,13 @@
+top-level content
+{% for outer_inner in outer %}
+ outer
+ {% for middle in outer_inner.middle %}
+ {{ middle.S_BLOCK_NAME }}
+ {% for inner in middle.inner %}
+ inner {{ inner.VARIABLE }}
+ {% if inner.S_FIRST_ROW %}
+ first row of {{ inner.S_NUM_ROWS }} in {{ inner.S_BLOCK_NAME }}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_nested_include1_twig.html b/tests/template/templates/loop_nested_include1_twig.html
new file mode 100644
index 0000000000..4c2ebb5f15
--- /dev/null
+++ b/tests/template/templates/loop_nested_include1_twig.html
@@ -0,0 +1,5 @@
+[{{ test_loop_inner.foo }}|
+{% for inner in test_loop_inner.inner %}
+ [{{ test_loop_inner.foo }}|
+ {{ inner.myinner }}]
+{% endfor %}]
diff --git a/tests/template/templates/loop_nested_include_twig.html b/tests/template/templates/loop_nested_include_twig.html
new file mode 100644
index 0000000000..c92ac922d1
--- /dev/null
+++ b/tests/template/templates/loop_nested_include_twig.html
@@ -0,0 +1,4 @@
+{% for test_loop_inner in test_loop %}
+ [{{ test_loop_inner.foo }}
+ |{% INCLUDE 'loop_nested_include1_twig.html' %}]
+{% endfor %}
diff --git a/tests/template/templates/loop_nested_multilevel_ref_twig.html b/tests/template/templates/loop_nested_multilevel_ref_twig.html
new file mode 100644
index 0000000000..336a57d0bc
--- /dev/null
+++ b/tests/template/templates/loop_nested_multilevel_ref_twig.html
@@ -0,0 +1,10 @@
+top-level content
+{% for outer_inner in outer %}
+ outer {{ outer_inner.VARIABLE }}
+ {% for inner in outer_inner.inner %}
+ inner {{ inner.VARIABLE }}
+ {% if inner.S_FIRST_ROW %}
+ first row
+ {% endif %}
+ {% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_nested_twig.html b/tests/template/templates/loop_nested_twig.html
new file mode 100644
index 0000000000..b294226b3a
--- /dev/null
+++ b/tests/template/templates/loop_nested_twig.html
@@ -0,0 +1,6 @@
+{% for outer_inner in outer %}
+outer - {{ outer_inner.S_ROW_COUNT }}{% if outer_inner.VARIABLE %} - {{ outer_inner.VARIABLE }}{% endif %}{% if TEST_MORE %}[{{ outer_inner.S_BLOCK_NAME }}|{{ outer_inner.S_NUM_ROWS }}]{% endif %}
+{% for middle in outer_inner.middle %}
+middle - {{ middle.S_ROW_COUNT }}{% if middle.VARIABLE %} - {{ middle.VARIABLE }}{% endif %}{% if TEST_MORE %}[{{ middle.S_BLOCK_NAME }}|{{ middle.S_NUM_ROWS }}]{% endif %}
+{% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_reuse_twig.html b/tests/template/templates/loop_reuse_twig.html
new file mode 100644
index 0000000000..67452a737f
--- /dev/null
+++ b/tests/template/templates/loop_reuse_twig.html
@@ -0,0 +1,6 @@
+{% for one_inner in one %}
+ {{ one_inner.VAR }}
+ {% for one_one_inner in one_inner.one %}
+ {{ one_one_inner.VAR }}
+ {% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_size_twig.html b/tests/template/templates/loop_size_twig.html
new file mode 100644
index 0000000000..f6d2571e11
--- /dev/null
+++ b/tests/template/templates/loop_size_twig.html
@@ -0,0 +1,39 @@
+{% if nonexistent_loop|length %}
+nonexistent
+{% endif %}
+
+{% if nonexistent_loop|length == 0 %}
+nonexistent = 0
+{% endif %}
+
+{% if ! nonexistent_loop|length %}
+! nonexistent
+{% endif %}
+
+{% if empty_loop|length %}
+empty
+{% endif %}
+
+{% if empty_loop|length == 0 %}
+empty = 0
+{% endif %}
+
+{% if ! empty_loop|length %}
+! empty
+{% endif %}
+
+{% if test_loop|length %}
+loop
+{% endif %}
+
+{% if test_loop|length == 0 %}
+loop = 0
+{% endif %}
+
+{% if ! test_loop|length %}
+! loop
+{% endif %}
+
+{% for test_loop_inner in test_loop %}
+in loop
+{% endfor %}
diff --git a/tests/template/templates/loop_twig.html b/tests/template/templates/loop_twig.html
new file mode 100644
index 0000000000..fb24f331b3
--- /dev/null
+++ b/tests/template/templates/loop_twig.html
@@ -0,0 +1,21 @@
+{% for test_loop_inner in test_loop %}
+loop
+{% else %}
+noloop
+{% endfor %}
+
+{% if test_loop|length %}
+loop
+{% else %}
+noloop
+{% endif %}
+
+{% if test_loop|length == 2 %}
+loop
+{% endif %}
+
+{% for test_loop_inner in test_loop %}
+{% for block_inner in block %}
+loop#{{ test_loop_inner.S_ROW_COUNT }}-block#{{ block_inner.S_ROW_COUNT }}
+{% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_underscore_twig.html b/tests/template/templates/loop_underscore_twig.html
new file mode 100644
index 0000000000..44b095c882
--- /dev/null
+++ b/tests/template/templates/loop_underscore_twig.html
@@ -0,0 +1,21 @@
+{% for _underscore_loop_inner in _underscore_loop %}
+loop
+{% else %}
+noloop
+{% endfor %}
+
+{% if _underscore_loop|length %}
+loop
+{% else %}
+noloop
+{% endif %}
+
+{% if _underscore_loop|length == 2 %}
+loop
+{% endif %}
+
+{% for _underscore_loop_inner in _underscore_loop %}
+{% for block_inner in block %}
+loop#{{ loop.S_ROW_COUNT }}-block#{{ block_inner.S_ROW_COUNT }}
+{% endfor %}
+{% endfor %}
diff --git a/tests/template/templates/loop_vars_twig.html b/tests/template/templates/loop_vars_twig.html
new file mode 100644
index 0000000000..af6c63d8e3
--- /dev/null
+++ b/tests/template/templates/loop_vars_twig.html
@@ -0,0 +1,13 @@
+{% for test_loop_inner in test_loop %}
+{% if test_loop_inner.S_FIRST_ROW %}first{% endif %}
+{{ test_loop_inner.S_ROW_NUM }} - a
+{{ test_loop_inner.VARIABLE }} - b
+{% if test_loop_inner.VARIABLE %}set{% endif %}
+{% if test_loop_inner.S_LAST_ROW %}
+last
+{% endif %}
+{% for inner_inner in test_loop_inner.inner %}
+{{ inner_inner.S_ROW_NUM }} - c
+{% if inner_inner.S_LAST_ROW and inner_inner.S_ROW_COUNT and inner_inner.S_NUM_ROWS %}last inner{% endif %}
+{% endfor %}
+{% endfor %}
diff --git a/tests/test_framework/mock/phpbb_mock_null_installer_task.php b/tests/test_framework/mock/phpbb_mock_null_installer_task.php
new file mode 100644
index 0000000000..c1b880d967
--- /dev/null
+++ b/tests/test_framework/mock/phpbb_mock_null_installer_task.php
@@ -0,0 +1,30 @@
+<?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.
+ *
+ */
+
+class phpbb_mock_null_installer_task extends \phpbb\install\task_base
+{
+ public function run()
+ {
+
+ }
+
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php
index fc1a3632f4..b7386e9a3e 100644
--- a/tests/test_framework/phpbb_database_test_case.php
+++ b/tests/test_framework/phpbb_database_test_case.php
@@ -58,7 +58,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
$setup_extensions = static::setup_extensions();
- $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx);
+ $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx);
$finder->core_path('phpbb/db/migration/data/');
if (!empty($setup_extensions))
{
@@ -76,8 +76,11 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
global $table_prefix;
- $db = new \phpbb\db\driver\sqlite();
- $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix);
+ $db = new \phpbb\db\driver\sqlite3();
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($db, true);
+
+ $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);
file_put_contents(self::$schema_file, json_encode($schema_generator->get_schema()));
}
diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php
index 3b5bab749e..147029d699 100644
--- a/tests/test_framework/phpbb_database_test_connection_manager.php
+++ b/tests/test_framework/phpbb_database_test_connection_manager.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php';
require_once dirname(__FILE__) . '/phpbb_database_connection_odbc_pdo_wrapper.php';
class phpbb_database_test_connection_manager
@@ -56,7 +55,6 @@ class phpbb_database_test_connection_manager
switch ($this->dbms['PDO'])
{
- case 'sqlite2':
case 'sqlite': // SQLite3 driver
$dsn .= $this->config['dbhost'];
break;
@@ -194,7 +192,6 @@ class phpbb_database_test_connection_manager
{
switch ($this->config['dbms'])
{
- case 'phpbb\db\driver\sqlite':
case 'phpbb\db\driver\sqlite3':
$this->connect();
// Drop all of the tables
@@ -270,12 +267,6 @@ class phpbb_database_test_connection_manager
$sql = 'SHOW TABLES';
break;
- case 'phpbb\db\driver\sqlite':
- $sql = 'SELECT name
- FROM sqlite_master
- WHERE type = "table"';
- break;
-
case 'phpbb\db\driver\sqlite3':
$sql = 'SELECT name
FROM sqlite_master
@@ -351,10 +342,13 @@ class phpbb_database_test_connection_manager
if (file_exists($filename))
{
+ global $phpbb_root_path;
+
$queries = file_get_contents($filename);
- $sql = phpbb_remove_comments($queries);
- $sql = split_sql_file($sql, $this->dbms['DELIM']);
+ $db_helper = new \phpbb\install\helper\database(new \phpbb\filesystem\filesystem(), $phpbb_root_path);
+ $sql = $db_helper->remove_comments($queries);
+ $sql = $db_helper->split_sql_file($sql, $this->dbms['DELIM']);
foreach ($sql as $query)
{
@@ -372,16 +366,20 @@ class phpbb_database_test_connection_manager
{
global $phpbb_root_path, $phpEx, $table_prefix;
- $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx);
+ $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx);
$classes = $finder->core_path('phpbb/db/migration/data/')
->get_classes();
- $db = new \phpbb\db\driver\sqlite();
- $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix);
+ $db = new \phpbb\db\driver\sqlite3();
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($db, true);
+
+ $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);
$db_table_schema = $schema_generator->get_schema();
}
- $db_tools = new \phpbb\db\tools($db, true);
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($db, true);
foreach ($db_table_schema as $table_name => $table_data)
{
$queries = $db_tools->sql_create_table(
@@ -448,11 +446,6 @@ class phpbb_database_test_connection_manager
'DELIM' => ';',
'PDO' => 'pgsql',
),
- 'phpbb\db\driver\sqlite' => array(
- 'SCHEMA' => 'sqlite',
- 'DELIM' => ';',
- 'PDO' => 'sqlite2',
- ),
'phpbb\db\driver\sqlite3' => array(
'SCHEMA' => 'sqlite',
'DELIM' => ';',
diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php
index 8107e45dc7..20b89aba4e 100644
--- a/tests/test_framework/phpbb_functional_test_case.php
+++ b/tests/test_framework/phpbb_functional_test_case.php
@@ -12,13 +12,15 @@
*/
use Symfony\Component\BrowserKit\CookieJar;
-require_once __DIR__ . '/../../phpBB/includes/functions_install.php';
+require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php';
class phpbb_functional_test_case extends phpbb_test_case
{
+ /** @var \Goutte\Client */
static protected $client;
static protected $cookieJar;
static protected $root_url;
+ static protected $install_success = false;
protected $cache = null;
protected $db = null;
@@ -77,13 +79,15 @@ class phpbb_functional_test_case extends phpbb_test_case
{
parent::setUp();
+ if (!self::$install_success)
+ {
+ $this->fail('Installing phpBB has failed.');
+ }
+
$this->bootstrap();
self::$cookieJar = new CookieJar;
self::$client = new Goutte\Client(array(), null, self::$cookieJar);
- // Reset the curl handle because it is 0 at this point and not a valid
- // resource
- self::$client->getClient()->getCurlMulti()->reset(true);
// Clear the language array so that things
// that were added in other tests are gone
@@ -169,7 +173,7 @@ class phpbb_functional_test_case extends phpbb_test_case
*/
static public function get_content()
{
- return self::$client->getResponse()->getContent();
+ return (string) self::$client->getResponse()->getContent();
}
// bootstrap, called after board is set up
@@ -205,6 +209,12 @@ class phpbb_functional_test_case extends phpbb_test_case
{
if (!$this->cache)
{
+ global $phpbb_container, $phpbb_root_path;
+
+ $phpbb_container = new phpbb_mock_container_builder();
+ $phpbb_container->setParameter('core.environment', PHPBB_ENVIRONMENT);
+ $phpbb_container->setParameter('core.cache_dir', $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/');
+
$this->cache = new \phpbb\cache\driver\file;
}
@@ -226,7 +236,8 @@ class phpbb_functional_test_case extends phpbb_test_case
$config = new \phpbb\config\config(array());
$db = $this->get_db();
- $db_tools = new \phpbb\db\tools($db);
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($db);
$container = new phpbb_mock_container_builder();
$migrator = new \phpbb\db\migrator(
@@ -243,14 +254,12 @@ class phpbb_functional_test_case extends phpbb_test_case
);
$container->set('migrator', $migrator);
$container->set('dispatcher', new phpbb_mock_event_dispatcher());
- $user = new \phpbb\user('\phpbb\datetime');
$extension_manager = new \phpbb\extension\manager(
$container,
$db,
$config,
- new phpbb\filesystem(),
- $user,
+ new phpbb\filesystem\filesystem(),
self::$config['table_prefix'] . 'ext',
dirname(__FILE__) . '/',
$phpEx,
@@ -282,120 +291,111 @@ class phpbb_functional_test_case extends phpbb_test_case
}
}
- self::$cookieJar = new CookieJar;
- self::$client = new Goutte\Client(array(), null, self::$cookieJar);
- // Set client manually so we can increase the cURL timeout
- self::$client->setClient(new Guzzle\Http\Client('', array(
- Guzzle\Http\Client::DISABLE_REDIRECTS => true,
- 'curl.options' => array(
- CURLOPT_TIMEOUT => 120,
- ),
- )));
-
- // Reset the curl handle because it is 0 at this point and not a valid
- // resource
- self::$client->getClient()->getCurlMulti()->reset(true);
+ $container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $container = $container_builder
+ ->with_environment('installer')
+ ->without_extensions()
+ ->without_cache()
+ ->with_custom_parameters([
+ 'core.disable_super_globals' => false,
+ 'installer.create_config_file.options' => [
+ 'debug' => true,
+ 'environment' => 'test',
+ ],
+ 'cache.driver.class' => 'phpbb\cache\driver\file'
+ ])
+ ->without_compiled_container()
+ ->get_container();
+
+ $container->register('installer.install_finish.notify_user')->setSynthetic(true);
+ $container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task());
+ $container->compile();
+
+ $language = $container->get('language');
+ $language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
+
+ $iohandler_factory = $container->get('installer.helper.iohandler_factory');
+ $iohandler_factory->set_environment('cli');
+ $iohandler = $iohandler_factory->get();
$parseURL = parse_url(self::$config['phpbb_functional_url']);
- $crawler = self::request('GET', 'install/index.php?mode=install&language=en');
- self::assertContains('Welcome to Installation', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // install/index.php?mode=install&sub=requirements
- $crawler = self::submit($form);
- self::assertContains('Installation compatibility', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // install/index.php?mode=install&sub=database
- $crawler = self::submit($form);
- self::assertContains('Database configuration', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form(array(
- // Installer uses 3.0-style dbms name
- 'dbms' => str_replace('phpbb\db\driver\\', '', self::$config['dbms']),
- 'dbhost' => self::$config['dbhost'],
- 'dbport' => self::$config['dbport'],
- 'dbname' => self::$config['dbname'],
- 'dbuser' => self::$config['dbuser'],
- 'dbpasswd' => self::$config['dbpasswd'],
- 'table_prefix' => self::$config['table_prefix'],
- ));
+ $output = new \Symfony\Component\Console\Output\NullOutput();
+ $style = new \Symfony\Component\Console\Style\SymfonyStyle(
+ new \Symfony\Component\Console\Input\ArrayInput(array()),
+ $output
+ );
+ $iohandler->set_style($style, $output);
+
+ $installer = $container->get('installer.installer.install');
+ $installer->set_iohandler($iohandler);
+
+ // Set data
+ $iohandler->set_input('admin_name', 'admin');
+ $iohandler->set_input('admin_pass1', 'adminadmin');
+ $iohandler->set_input('admin_pass2', 'adminadmin');
+ $iohandler->set_input('board_email', 'nobody@example.com');
+ $iohandler->set_input('submit_admin', 'submit');
+
+ $iohandler->set_input('default_lang', 'en');
+ $iohandler->set_input('board_name', 'yourdomain.com');
+ $iohandler->set_input('board_description', 'A short text to describe your forum');
+ $iohandler->set_input('submit_board', 'submit');
+
+ $iohandler->set_input('dbms', str_replace('phpbb\db\driver\\', '', self::$config['dbms']));
+ $iohandler->set_input('dbhost', self::$config['dbhost']);
+ $iohandler->set_input('dbport', self::$config['dbport']);
+ $iohandler->set_input('dbuser', self::$config['dbuser']);
+ $iohandler->set_input('dbpasswd', self::$config['dbpasswd']);
+ $iohandler->set_input('dbname', self::$config['dbname']);
+ $iohandler->set_input('table_prefix', self::$config['table_prefix']);
+ $iohandler->set_input('submit_database', 'submit');
+
+ $iohandler->set_input('email_enable', true);
+ $iohandler->set_input('smtp_delivery', '1');
+ $iohandler->set_input('smtp_host', 'nxdomain.phpbb.com');
+ $iohandler->set_input('smtp_auth', 'PLAIN');
+ $iohandler->set_input('smtp_user', 'nxuser');
+ $iohandler->set_input('smtp_pass', 'nxpass');
+ $iohandler->set_input('submit_email', 'submit');
+
+ $iohandler->set_input('cookie_secure', '0');
+ $iohandler->set_input('server_protocol', '0');
+ $iohandler->set_input('force_server_vars', $parseURL['scheme'] . '://');
+ $iohandler->set_input('server_name', $parseURL['host']);
+ $iohandler->set_input('server_port', isset($parseURL['port']) ? (int) $parseURL['port'] : 80);
+ $iohandler->set_input('script_path', $parseURL['path']);
+ $iohandler->set_input('submit_server', 'submit');
+
+ $installer->run();
- // install/index.php?mode=install&sub=database
- $crawler = self::submit($form);
- self::assertContains('Successful connection', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
+ copy($config_file, $config_file_test);
- // install/index.php?mode=install&sub=administrator
- $crawler = self::submit($form);
- self::assertContains('Administrator configuration', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form(array(
- 'default_lang' => 'en',
- 'admin_name' => 'admin',
- 'admin_pass1' => 'adminadmin',
- 'admin_pass2' => 'adminadmin',
- 'board_email' => 'nobody@example.com',
- ));
+ self::$install_success = true;
- // install/index.php?mode=install&sub=administrator
- $crawler = self::submit($form);
- self::assertContains('Tests passed', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // We have to skip install/index.php?mode=install&sub=config_file
- // because that step will create a config.php file if phpBB has the
- // permission to do so. We have to create the config file on our own
- // in order to get the DEBUG constants defined.
- $config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true);
- $config_created = file_put_contents($config_file, $config_php_data) !== false;
- if (!$config_created)
+ if (file_exists($phpbb_root_path . 'store/install_config.php'))
{
- self::markTestSkipped("Could not write $config_file file.");
+ self::$install_success = false;
+ @unlink($phpbb_root_path . 'store/install_config.php');
}
- // We also have to create a install lock that is normally created by
- // the installer. The file will be removed by the final step of the
- // installer.
- $install_lock_file = $phpbb_root_path . 'cache/install_lock';
- $lock_created = file_put_contents($install_lock_file, '') !== false;
- if (!$lock_created)
+ if (file_exists($phpbb_root_path . 'cache/install_lock'))
{
- self::markTestSkipped("Could not create $lock_created file.");
+ @unlink($phpbb_root_path . 'cache/install_lock');
}
- @chmod($install_lock_file, 0666);
-
- // install/index.php?mode=install&sub=advanced
- $form_data = $form->getValues();
- unset($form_data['submit']);
-
- $crawler = self::request('POST', 'install/index.php?mode=install&sub=advanced', $form_data);
- self::assertContains('The settings on this page are only necessary to set if you know that you require something different from the default.', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form(array(
- 'email_enable' => true,
- 'smtp_delivery' => true,
- 'smtp_host' => 'nxdomain.phpbb.com',
- 'smtp_auth' => 'PLAIN',
- 'smtp_user' => 'nxuser',
- 'smtp_pass' => 'nxpass',
- 'cookie_secure' => false,
- 'force_server_vars' => false,
- 'server_protocol' => $parseURL['scheme'] . '://',
- 'server_name' => 'localhost',
- 'server_port' => isset($parseURL['port']) ? (int) $parseURL['port'] : 80,
- 'script_path' => $parseURL['path'],
- ));
- // install/index.php?mode=install&sub=create_table
- $crawler = self::submit($form);
- self::assertContains('The database tables used by phpBB', $crawler->filter('#main')->text());
- self::assertContains('have been created and populated with some initial data.', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
+ global $phpbb_container;
+ $phpbb_container->reset();
- // install/index.php?mode=install&sub=final
- $crawler = self::submit($form);
- self::assertContains('You have successfully installed', $crawler->text());
+ $blacklist = ['phpbb_class_loader_mock', 'phpbb_class_loader_ext', 'phpbb_class_loader'];
- copy($config_file, $config_file_test);
+ foreach (array_keys($GLOBALS) as $key)
+ {
+ if (is_object($GLOBALS[$key]) && !in_array($key, $blacklist, true))
+ {
+ unset($GLOBALS[$key]);
+ }
+ }
}
public function install_ext($extension)
@@ -490,7 +490,7 @@ class phpbb_functional_test_case extends phpbb_test_case
));
$db->sql_query($sql);
- if ($style_path != 'prosilver' && $style_path != 'subsilver2')
+ if ($style_path != 'prosilver')
{
@mkdir($phpbb_root_path . 'styles/' . $style_path, 0777);
@mkdir($phpbb_root_path . 'styles/' . $style_path . '/template', 0777);
@@ -529,7 +529,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$db->sql_query('DELETE FROM ' . STYLES_TEMPLATE_TABLE . ' WHERE template_id = ' . $style_id);
$db->sql_query('DELETE FROM ' . STYLES_THEME_TABLE . ' WHERE theme_id = ' . $style_id);
- if ($style_path != 'prosilver' && $style_path != 'subsilver2')
+ if ($style_path != 'prosilver')
{
@rmdir($phpbb_root_path . 'styles/' . $style_path . '/template');
@rmdir($phpbb_root_path . 'styles/' . $style_path);
@@ -571,7 +571,7 @@ class phpbb_functional_test_case extends phpbb_test_case
}
$cache = new phpbb_mock_null_cache;
- $cache_driver = new \phpbb\cache\driver\null();
+ $cache_driver = new \phpbb\cache\driver\dummy();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('cache.driver', $cache_driver);
$phpbb_notifications = new phpbb_mock_notification_manager();
@@ -585,8 +585,7 @@ class phpbb_functional_test_case extends phpbb_test_case
{
require_once(__DIR__ . '/../../phpBB/includes/functions_user.php');
}
- set_config(null, null, null, $config);
- set_config_count(null, null, null, $config);
+
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$passwords_manager = $this->get_passwords_manager();
@@ -612,13 +611,16 @@ class phpbb_functional_test_case extends phpbb_test_case
$db = $this->get_db();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$auth = $this->getMock('\phpbb\auth\auth');
$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
$cache = new phpbb_mock_null_cache;
- $cache_driver = new \phpbb\cache\driver\null();
+ $cache_driver = new \phpbb\cache\driver\dummy();
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('cache.driver', $cache_driver);
$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
@@ -651,13 +653,16 @@ class phpbb_functional_test_case extends phpbb_test_case
$db = $this->get_db();
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
- $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $user = $this->getMock('\phpbb\user', array(), array(
+ new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ '\phpbb\datetime'
+ ));
$auth = $this->getMock('\phpbb\auth\auth');
$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
$cache = new phpbb_mock_null_cache;
- $cache_driver = new \phpbb\cache\driver\null();
+ $cache_driver = new \phpbb\cache\driver\dummy();
$phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$phpbb_container
->expects($this->any())
@@ -856,7 +861,7 @@ class phpbb_functional_test_case extends phpbb_test_case
static public function assert_response_html($status_code = 200)
{
// Any output before the doc type means there was an error
- $content = self::$client->getResponse()->getContent();
+ $content = self::get_content();
self::assertNotContains('[phpBB Debug]', $content);
self::assertStringStartsWith('<!DOCTYPE', trim($content), 'Output found before DOCTYPE specification.');
@@ -877,7 +882,7 @@ class phpbb_functional_test_case extends phpbb_test_case
static public function assert_response_xml($status_code = 200)
{
// Any output before the xml opening means there was an error
- $content = self::$client->getResponse()->getContent();
+ $content = self::get_content();
self::assertNotContains('[phpBB Debug]', $content);
self::assertStringStartsWith('<?xml', trim($content), 'Output found before XML specification.');
@@ -948,8 +953,7 @@ class phpbb_functional_test_case extends phpbb_test_case
*/
public function assert_checkbox_is_unchecked($crawler, $name, $message = '')
{
- $this->assertSame(
- '',
+ $this->assertNull(
$this->assert_find_one_checkbox($crawler, $name)->attr('checked'),
$message ?: "Failed asserting that checkbox $name is unchecked."
);
diff --git a/tests/test_framework/phpbb_session_test_case.php b/tests/test_framework/phpbb_session_test_case.php
index 1bf0277fe0..b3d7780d14 100644
--- a/tests/test_framework/phpbb_session_test_case.php
+++ b/tests/test_framework/phpbb_session_test_case.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../session/testable_factory.php';
require_once dirname(__FILE__) . '/../session/testable_facade.php';
@@ -34,7 +33,7 @@ abstract class phpbb_session_test_case extends phpbb_database_test_case
$symfony_request = new \phpbb\symfony_request(
new phpbb_mock_request()
);
- $phpbb_filesystem = new \phpbb\filesystem();
+ $phpbb_filesystem = new \phpbb\filesystem\filesystem();
$phpbb_path_helper = new \phpbb\path_helper(
$symfony_request,
$phpbb_filesystem,
diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php
index dee70ad016..7fb9a740b8 100644
--- a/tests/test_framework/phpbb_test_case_helpers.php
+++ b/tests/test_framework/phpbb_test_case_helpers.php
@@ -11,6 +11,8 @@
*
*/
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
class phpbb_test_case_helpers
{
protected $expectedTriggerError = false;
@@ -120,17 +122,6 @@ class phpbb_test_case_helpers
'dbpasswd' => '',
));
}
- else if (extension_loaded('sqlite'))
- {
- $config = array_merge($config, array(
- 'dbms' => 'phpbb\db\driver\sqlite',
- 'dbhost' => dirname(__FILE__) . '/../phpbb_unit_tests.sqlite2', // filename
- 'dbport' => '',
- 'dbname' => '',
- 'dbuser' => '',
- 'dbpasswd' => '',
- ));
- }
if (isset($_SERVER['PHPBB_TEST_CONFIG']))
{
@@ -298,4 +289,295 @@ class phpbb_test_case_helpers
}
}
}
+
+ /**
+ * Set working instances of the text_formatter.* services
+ *
+ * If no container is passed, the global $phpbb_container will be used and/or
+ * created if applicable
+ *
+ * @param ContainerInterface $container Service container
+ * @param string $fixture Path to the XML fixture
+ * @param string $styles_path Path to the styles dir
+ * @return ContainerInterface
+ */
+ public function set_s9e_services(ContainerInterface $container = null, $fixture = null, $styles_path = null)
+ {
+ static $first_run;
+ global $config, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx, $request, $user;
+
+ $cache_dir = __DIR__ . '/../tmp/';
+
+ // Remove old cache files on first run
+ if (!isset($first_run))
+ {
+ $first_run = 1;
+
+ array_map('unlink', array_merge(
+ glob($cache_dir . 'data_s9e_*'),
+ glob($cache_dir . 's9e_*')
+ ));
+ }
+
+ if (!isset($container))
+ {
+ if (!isset($phpbb_container))
+ {
+ $phpbb_container = new phpbb_mock_container_builder;
+ }
+
+ $container = $phpbb_container;
+ }
+
+ if (!isset($fixture))
+ {
+ $fixture = __DIR__ . '/../text_formatter/s9e/fixtures/default_formatting.xml';
+ }
+
+ if (!isset($styles_path))
+ {
+ $styles_path = $phpbb_root_path . 'styles/';
+ }
+
+ $dataset = new DOMDocument;
+ $dataset->load($fixture);
+
+ $tables = array(
+ 'phpbb_bbcodes' => array(),
+ 'phpbb_smilies' => array(),
+ 'phpbb_styles' => array(),
+ 'phpbb_words' => array()
+ );
+ foreach ($dataset->getElementsByTagName('table') as $table)
+ {
+ $name = $table->getAttribute('name');
+ $columns = array();
+
+ foreach ($table->getElementsByTagName('column') as $column)
+ {
+ $columns[] = $column->textContent;
+ }
+
+ foreach ($table->getElementsByTagName('row') as $row)
+ {
+ $values = array();
+
+ foreach ($row->getElementsByTagName('value') as $value)
+ {
+ $values[] = $value->textContent;
+ }
+
+ $tables[$name][] = array_combine($columns, $values);
+ }
+ }
+
+ // Set up a default style if there's none set
+ if (empty($tables['phpbb_styles']))
+ {
+ $tables['phpbb_styles'][] = array(
+ 'style_id' => 1,
+ 'style_path' => 'prosilver',
+ 'bbcode_bitfield' => 'kNg='
+ );
+ }
+
+ // Mock the DAL, make it return data from the fixture
+ $mb = $this->test_case->getMockBuilder('phpbb\\textformatter\\data_access');
+ $mb->setMethods(array('get_bbcodes', 'get_censored_words', 'get_smilies', 'get_styles'));
+ $mb->setConstructorArgs(array(
+ $this->test_case->getMock('phpbb\\db\\driver\\driver'),
+ 'phpbb_bbcodes',
+ 'phpbb_smilies',
+ 'phpbb_styles',
+ 'phpbb_words',
+ $styles_path
+ ));
+
+ $dal = $mb->getMock();
+ $container->set('text_formatter.data_access', $dal);
+
+ $dal->expects($this->test_case->any())
+ ->method('get_bbcodes')
+ ->will($this->test_case->returnValue($tables['phpbb_bbcodes']));
+ $dal->expects($this->test_case->any())
+ ->method('get_smilies')
+ ->will($this->test_case->returnValue($tables['phpbb_smilies']));
+ $dal->expects($this->test_case->any())
+ ->method('get_styles')
+ ->will($this->test_case->returnValue($tables['phpbb_styles']));
+ $dal->expects($this->test_case->any())
+ ->method('get_censored_words')
+ ->will($this->test_case->returnValue($tables['phpbb_words']));
+
+ // Cache the parser and renderer with a key based on this method's arguments
+ $cache = new \phpbb\cache\driver\file($cache_dir);
+ $prefix = '_s9e_' . md5(serialize(func_get_args()));
+ $cache_key_parser = $prefix . '_parser';
+ $cache_key_renderer = $prefix . '_renderer';
+ $container->set('cache.driver', $cache);
+
+ if (!$container->isFrozen())
+ {
+ $container->setParameter('cache.dir', $cache_dir);
+ }
+
+ // Create a path_helper
+ if (!$container->has('path_helper') || $container->getDefinition('path_helper')->isSynthetic())
+ {
+ $path_helper = $this->test_case->getMockBuilder('phpbb\\path_helper')
+ ->disableOriginalConstructor()
+ ->setMethods(array('get_web_root_path'))
+ ->getMock();
+ $path_helper->expects($this->test_case->any())
+ ->method('get_web_root_path')
+ ->will($this->test_case->returnValue('phpBB/'));
+
+ $container->set('path_helper', $path_helper);
+ }
+ else
+ {
+ $path_helper = $container->get('path_helper');
+ }
+
+ // Create an event dispatcher
+ if ($container->has('dispatcher'))
+ {
+ $dispatcher = $container->get('dispatcher');
+ }
+ else if (isset($phpbb_dispatcher))
+ {
+ $dispatcher = $phpbb_dispatcher;
+ }
+ else
+ {
+ $dispatcher = new phpbb_mock_event_dispatcher;
+ }
+ if (!isset($phpbb_dispatcher))
+ {
+ $phpbb_dispatcher = $dispatcher;
+ }
+
+ // Set up the a minimum config
+ if ($container->has('config'))
+ {
+ $config = $container->get('config');
+ }
+ elseif (!isset($config))
+ {
+ $config = new \phpbb\config\config(array());
+ }
+ $default_config = array(
+ 'allow_nocensors' => false,
+ 'allowed_schemes_links' => 'http,https,ftp',
+ 'script_path' => '/phpbb',
+ 'server_name' => 'localhost',
+ 'server_port' => 80,
+ 'server_protocol' => 'http://',
+ 'smilies_path' => 'images/smilies',
+ );
+ foreach ($default_config as $config_name => $config_value)
+ {
+ if (!isset($config[$config_name]))
+ {
+ $config[$config_name] = $config_value;
+ }
+ }
+
+ // Create a fake request
+ if (!isset($request))
+ {
+ $request = new phpbb_mock_request;
+ }
+
+ // Create and register the text_formatter.s9e.factory service
+ $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $config, new \phpbb\textformatter\s9e\link_helper, $cache_dir, $cache_key_parser, $cache_key_renderer);
+ $container->set('text_formatter.s9e.factory', $factory);
+
+ // Create a user if none was provided, and add the common lang strings
+ if ($container->has('user'))
+ {
+ $user = $container->get('user');
+ }
+ else
+ {
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+
+ $user = $this->test_case->getMockBuilder('\phpbb\user')
+ ->setConstructorArgs(array($lang, '\phpbb\datetime'))
+ ->setMethods(array('format_date'))
+ ->getMock();
+ $user->expects($this->test_case->any())
+ ->method('format_date')
+ ->will($this->test_case->returnCallback(__CLASS__ . '::format_date'));
+
+ $user->date_format = 'Y-m-d H:i:s';
+ $user->optionset('viewcensors', true);
+ $user->optionset('viewflash', true);
+ $user->optionset('viewimg', true);
+ $user->optionset('viewsmilies', true);
+ $user->timezone = new \DateTimeZone('UTC');
+ $container->set('user', $user);
+ }
+ $user->add_lang('common');
+
+ if (!isset($user->style))
+ {
+ $user->style = array('style_id' => 1);
+ }
+
+ // Create and register a quote_helper
+ $quote_helper = new \phpbb\textformatter\s9e\quote_helper(
+ $container->get('user'),
+ $phpbb_root_path,
+ $phpEx
+ );
+ $container->set('text_formatter.s9e.quote_helper', $quote_helper);
+
+ // Create and register the text_formatter.s9e.parser service and its alias
+ $parser = new \phpbb\textformatter\s9e\parser(
+ $cache,
+ $cache_key_parser,
+ $factory,
+ $dispatcher
+ );
+ $container->set('text_formatter.parser', $parser);
+ $container->set('text_formatter.s9e.parser', $parser);
+
+ // Create and register the text_formatter.s9e.renderer service and its alias
+ $renderer = new \phpbb\textformatter\s9e\renderer(
+ $cache,
+ $cache_dir,
+ $cache_key_renderer,
+ $factory,
+ $dispatcher
+ );
+
+ // Calls configured in services.yml
+ $auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth;
+ $renderer->configure_quote_helper($quote_helper);
+ $renderer->configure_smilies_path($config, $path_helper);
+ $renderer->configure_user($user, $config, $auth);
+
+ $container->set('text_formatter.renderer', $renderer);
+ $container->set('text_formatter.s9e.renderer', $renderer);
+
+ // Create and register the text_formatter.s9e.utils service and its alias
+ $utils = new \phpbb\textformatter\s9e\utils;
+ $container->set('text_formatter.utils', $utils);
+ $container->set('text_formatter.s9e.utils', $utils);
+
+ return $container;
+ }
+
+ /**
+ * Mocked replacement for \phpbb\user::format_date()
+ *
+ * @param integer $gmepoch unix timestamp
+ * @return string
+ */
+ static public function format_date($gmepoch)
+ {
+ return gmdate('Y-m-d H:i:s', $gmepoch);
+ }
}
diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php
index e8b230ecbe..e3f636679c 100644
--- a/tests/test_framework/phpbb_ui_test_case.php
+++ b/tests/test_framework/phpbb_ui_test_case.php
@@ -16,7 +16,7 @@ use Facebook\WebDriver\Exception\WebDriverCurlException;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
-require_once __DIR__ . '/../../phpBB/includes/functions_install.php';
+require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php';
class phpbb_ui_test_case extends phpbb_test_case
{
@@ -32,7 +32,6 @@ class phpbb_ui_test_case extends phpbb_test_case
static protected $root_url;
static protected $already_installed = false;
static protected $install_success = false;
-
protected $cache = null;
protected $db = null;
protected $extension_manager = null;
@@ -191,90 +190,111 @@ class phpbb_ui_test_case extends phpbb_test_case
}
}
+ $container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $container = $container_builder
+ ->with_environment('installer')
+ ->without_extensions()
+ ->without_cache()
+ ->with_custom_parameters([
+ 'core.disable_super_globals' => false,
+ 'installer.create_config_file.options' => [
+ 'debug' => true,
+ 'environment' => 'test',
+ ],
+ 'cache.driver.class' => 'phpbb\cache\driver\file'
+ ])
+ ->without_compiled_container()
+ ->get_container();
+
+ $container->register('installer.install_finish.notify_user')->setSynthetic(true);
+ $container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task());
+ $container->compile();
+
+ $language = $container->get('language');
+ $language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
+
+ $iohandler_factory = $container->get('installer.helper.iohandler_factory');
+ $iohandler_factory->set_environment('cli');
+ $iohandler = $iohandler_factory->get();
+
$parseURL = parse_url(self::$config['phpbb_functional_url']);
- self::visit('install/index.php?mode=install&language=en');
- self::assertContains('Welcome to Installation', self::find_element('id', 'main')->getText());
-
- // install/index.php?mode=install&sub=requirements
- self::submit();
- self::assertContains('Installation compatibility', self::find_element('id', 'main')->getText());
-
- // install/index.php?mode=install&sub=database
- self::submit();
- self::assertContains('Database configuration', self::find_element('id', 'main')->getText());
-
- self::find_element('id','dbms')->sendKeys(str_replace('phpbb\db\driver\\', '', self::$config['dbms']));
- self::find_element('id','dbhost')->sendKeys(self::$config['dbhost']);
- self::find_element('id','dbport')->sendKeys(self::$config['dbport']);
- self::find_element('id','dbname')->sendKeys(self::$config['dbname']);
- self::find_element('id','dbuser')->sendKeys(self::$config['dbuser']);
- self::find_element('id','dbpasswd')->sendKeys(self::$config['dbpasswd']);
-
- // Need to clear default phpbb_ prefix
- self::find_element('id','table_prefix')->clear();
- self::find_element('id','table_prefix')->sendKeys(self::$config['table_prefix']);
-
- // install/index.php?mode=install&sub=database
- self::submit();
- self::assertContains('Successful connection', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=administrator
- self::submit();
- self::assertContains('Administrator configuration', self::find_element('id','main')->getText());
-
- self::find_element('id','admin_name')->sendKeys('admin');
- self::find_element('id','admin_pass1')->sendKeys('adminadmin');
- self::find_element('id','admin_pass2')->sendKeys('adminadmin');
- self::find_element('id','board_email')->sendKeys('nobody@example.com');
-
- // install/index.php?mode=install&sub=administrator
- self::submit();
- self::assertContains('Tests passed', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=config_file
- self::submit();
-
- // Installer has created a config.php file, we will overwrite it with a
- // config file of our own in order to get the DEBUG constants defined
- $config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true);
- $config_created = file_put_contents($config_file, $config_php_data) !== false;
- if (!$config_created)
+ $output = new \Symfony\Component\Console\Output\NullOutput();
+ $style = new \Symfony\Component\Console\Style\SymfonyStyle(
+ new \Symfony\Component\Console\Input\ArrayInput(array()),
+ $output
+ );
+ $iohandler->set_style($style, $output);
+
+ $installer = $container->get('installer.installer.install');
+ $installer->set_iohandler($iohandler);
+
+ // Set data
+ $iohandler->set_input('admin_name', 'admin');
+ $iohandler->set_input('admin_pass1', 'adminadmin');
+ $iohandler->set_input('admin_pass2', 'adminadmin');
+ $iohandler->set_input('board_email', 'nobody@example.com');
+ $iohandler->set_input('submit_admin', 'submit');
+
+ $iohandler->set_input('default_lang', 'en');
+ $iohandler->set_input('board_name', 'yourdomain.com');
+ $iohandler->set_input('board_description', 'A short text to describe your forum');
+ $iohandler->set_input('submit_board', 'submit');
+
+ $iohandler->set_input('dbms', str_replace('phpbb\db\driver\\', '', self::$config['dbms']));
+ $iohandler->set_input('dbhost', self::$config['dbhost']);
+ $iohandler->set_input('dbport', self::$config['dbport']);
+ $iohandler->set_input('dbuser', self::$config['dbuser']);
+ $iohandler->set_input('dbpasswd', self::$config['dbpasswd']);
+ $iohandler->set_input('dbname', self::$config['dbname']);
+ $iohandler->set_input('table_prefix', self::$config['table_prefix']);
+ $iohandler->set_input('submit_database', 'submit');
+
+ $iohandler->set_input('email_enable', true);
+ $iohandler->set_input('smtp_delivery', '1');
+ $iohandler->set_input('smtp_host', 'nxdomain.phpbb.com');
+ $iohandler->set_input('smtp_auth', 'PLAIN');
+ $iohandler->set_input('smtp_user', 'nxuser');
+ $iohandler->set_input('smtp_pass', 'nxpass');
+ $iohandler->set_input('submit_email', 'submit');
+
+ $iohandler->set_input('cookie_secure', '0');
+ $iohandler->set_input('server_protocol', '0');
+ $iohandler->set_input('force_server_vars', $parseURL['scheme'] . '://');
+ $iohandler->set_input('server_name', $parseURL['host']);
+ $iohandler->set_input('server_port', isset($parseURL['port']) ? (int) $parseURL['port'] : 80);
+ $iohandler->set_input('script_path', $parseURL['path']);
+ $iohandler->set_input('submit_server', 'submit');
+
+ $installer->run();
+
+ copy($config_file, $config_file_test);
+
+ self::$install_success = true;
+
+ if (file_exists($phpbb_root_path . 'store/install_config.php'))
{
- self::markTestSkipped("Could not write $config_file file.");
+ self::$install_success = false;
+ @unlink($phpbb_root_path . 'store/install_config.php');
}
- if (strpos(self::find_element('id','main')->getText(), 'The configuration file has been written') === false)
+ if (file_exists($phpbb_root_path . 'cache/install_lock'))
{
- self::submit('id', 'dldone');
+ @unlink($phpbb_root_path . 'cache/install_lock');
}
- self::assertContains('The configuration file has been written', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=advanced
- self::submit();
- self::assertContains('The settings on this page are only necessary to set if you know that you require something different from the default.', self::find_element('id','main')->getText());
-
- self::find_element('id','smtp_delivery')->sendKeys('1');
- self::find_element('id','smtp_host')->sendKeys('nxdomain.phpbb.com');
- self::find_element('id','smtp_user')->sendKeys('nxuser');
- self::find_element('id','smtp_pass')->sendKeys('nxpass');
- self::find_element('id','server_protocol')->sendKeys($parseURL['scheme'] . '://');
- self::find_element('id','server_name')->sendKeys('localhost');
- self::find_element('id','server_port')->sendKeys(isset($parseURL['port']) ? $parseURL['port'] : 80);
- self::find_element('id','script_path')->sendKeys($parseURL['path']);
-
- // install/index.php?mode=install&sub=create_table
- self::submit();
- self::assertContains('The database tables used by phpBB', self::find_element('id','main')->getText());
- self::assertContains('have been created and populated with some initial data.', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=final
- self::submit();
- self::assertContains('You have successfully installed', self::find_element('id', 'main')->getText());
- copy($config_file, $config_file_test);
+ global $phpbb_container;
+ $phpbb_container->reset();
- self::$install_success = true;
+ $blacklist = ['phpbb_class_loader_mock', 'phpbb_class_loader_ext', 'phpbb_class_loader'];
+
+ foreach (array_keys($GLOBALS) as $key)
+ {
+ if (is_object($GLOBALS[$key]) && !in_array($key, $blacklist, true))
+ {
+ unset($GLOBALS[$key]);
+ }
+ }
}
public function install_ext($extension)
diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php
new file mode 100644
index 0000000000..e25c3246b5
--- /dev/null
+++ b/tests/text_formatter/s9e/default_formatting_test.php
@@ -0,0 +1,313 @@
+<?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.
+*
+*/
+
+class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case
+{
+ public function test_bbcode_code_lang_is_saved()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $parser = $container->get('text_formatter.parser');
+
+ $original = '[code]...[/code][code=php]...[/code]';
+ $expected = '<r><CODE><s>[code]</s>...<e>[/code]</e></CODE><CODE lang="php"><s>[code=php]</s>...<e>[/code]</e></CODE></r>';
+
+ $this->assertXmlStringEqualsXmlString($expected, $parser->parse($original));
+ }
+
+ /**
+ * @dataProvider get_default_formatting_tests
+ */
+ public function test_default_formatting($original, $expected, $setup = null)
+ {
+ $fixture = __DIR__ . '/fixtures/default_formatting.xml';
+ $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture);
+
+ $parser = $container->get('text_formatter.parser');
+ $renderer = $container->get('text_formatter.renderer');
+
+ if (isset($setup))
+ {
+ call_user_func($setup, $container);
+ }
+
+ $parsed_text = $parser->parse($original);
+
+ $this->assertSame($expected, $renderer->render($parsed_text));
+ }
+
+ public function get_default_formatting_tests()
+ {
+ return array(
+ array(
+ '[b]bold[/b]',
+ '<span style="font-weight: bold">bold</span>'
+ ),
+ array(
+ '[u]underlined[/u]',
+ '<span style="text-decoration: underline">underlined</span>'
+ ),
+ array(
+ '[i]italic[/i]',
+ '<span style="font-style: italic">italic</span>'
+ ),
+ array(
+ '[color=#FF0000]colored[/color]',
+ '<span style="color: #FF0000">colored</span>'
+ ),
+ array(
+ '[color=red]colored[/color]',
+ '<span style="color: red">colored</span>'
+ ),
+ array(
+ '[size=75]smaller[/size]',
+ '<span style="font-size: 75%; line-height: normal">smaller</span>'
+ ),
+ array(
+ '[quote]quoted[/quote]',
+ '<blockquote class="uncited"><div>quoted</div></blockquote>'
+ ),
+ array(
+ '[quote="username"]quoted[/quote]',
+ '<blockquote><div><cite>username wrote:</cite>quoted</div></blockquote>'
+ ),
+ array(
+ '[code]unparsed code[/code]',
+ '<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>unparsed code</code></pre></div>'
+ ),
+ array(
+ '[list]no item[/list]',
+ '<ul><li>no item</li></ul>'
+ ),
+ array(
+ '[*]unparsed',
+ '[*]unparsed'
+ ),
+ array(
+ '[list][*]item[/list]',
+ '<ul><li>item</li></ul>'
+ ),
+ array(
+ '[list][*]item[/*][/list]',
+ '<ul><li>item</li></ul>'
+ ),
+ array(
+ '[list=1][*]item[/list]',
+ '<ol style="list-style-type: decimal"><li>item</li></ol>'
+ ),
+ array(
+ '[list=a][*]item[/list]',
+ '<ol style="list-style-type: lower-alpha"><li>item</li></ol>'
+ ),
+ array(
+ '[list=i][*]item[/list]',
+ '<ol style="list-style-type: lower-roman"><li>item</li></ol>'
+ ),
+ array(
+ '[list=I][*]item[/list]',
+ '<ol style="list-style-type: upper-roman"><li>item</li></ol>'
+ ),
+ array(
+ '[list=disc][*]item[/list]',
+ '<ul style="list-style-type: disc"><li>item</li></ul>'
+ ),
+ array(
+ '[list=circle][*]item[/list]',
+ '<ul style="list-style-type: circle"><li>item</li></ul>'
+ ),
+ array(
+ '[list=square][*]item[/list]',
+ '<ul style="list-style-type: square"><li>item</li></ul>'
+ ),
+ array(
+ '[img]https://area51.phpbb.com/images/area51.png[/img]',
+ '<img src="https://area51.phpbb.com/images/area51.png" class="postimage" alt="Image">'
+ ),
+ array(
+ '[url]https://area51.phpbb.com/[/url]',
+ '<a href="https://area51.phpbb.com/" class="postlink">https://area51.phpbb.com/</a>'
+ ),
+ array(
+ '[url=https://area51.phpbb.com/]Area51[/url]',
+ '<a href="https://area51.phpbb.com/" class="postlink">Area51</a>'
+ ),
+ array(
+ '[email]bbcode-test@phpbb.com[/email]',
+ '<a href="mailto:bbcode-test@phpbb.com">bbcode-test@phpbb.com</a>'
+ ),
+ array(
+ '[email=bbcode-test@phpbb.com]Email[/email]',
+ '<a href="mailto:bbcode-test@phpbb.com">Email</a>'
+ ),
+ array(
+ '[attachment=0]filename[/attachment]',
+ '<div class="inline-attachment"><!-- ia0 -->filename<!-- ia0 --></div>'
+ ),
+ array(
+ // PHPBB3-1401 - correct: parsed
+ '[quote="[test]test"]test [ test[/quote]',
+ '<blockquote><div><cite>[test]test wrote:</cite>test [ test</div></blockquote>'
+ ),
+ array(
+ // PHPBB3-6117 - correct: parsed
+ '[quote]test[/quote] test ] and [ test [quote]test[/quote]',
+ '<blockquote class="uncited"><div>test</div></blockquote> test ] and [ test <blockquote class="uncited"><div>test</div></blockquote>'
+ ),
+ array(
+ // PHPBB3-6200 - correct: parsed
+ '[quote="["]test[/quote]',
+ '<blockquote><div><cite>[ wrote:</cite>test</div></blockquote>'
+ ),
+ array(
+ // PHPBB3-9364 - quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted
+ '[quote]test[/[/b]quote] test [/quote][/quote] test',
+ '<blockquote class="uncited"><div>test[/[/b]quote] test </div></blockquote>[/quote] test'
+ ),
+ array(
+ // PHPBB3-8096 - first quote tag parsed, second quote tag unparsed
+ '[quote="a"]a[/quote][quote="a]a[/quote]',
+ '<blockquote><div><cite>a wrote:</cite>a</div></blockquote>[quote="a]a[/quote]'
+ ),
+ array(
+ // Allow textual bbcodes in textual bbcodes
+ '[b]bold [i]bold + italic[/i][/b]',
+ '<span style="font-weight: bold">bold <span style="font-style: italic">bold + italic</span></span>'
+ ),
+ array(
+ // Allow textual bbcodes in url with description
+ '[url=https://area51.phpbb.com/]Area51 [i]italic[/i][/url]',
+ '<a href="https://area51.phpbb.com/" class="postlink">Area51 <span style="font-style: italic">italic</span></a>'
+ ),
+ array(
+ // Allow url with description in textual bbcodes
+ '[i]italic [url=https://area51.phpbb.com/]Area51[/url][/i]',
+ '<span style="font-style: italic">italic <a href="https://area51.phpbb.com/" class="postlink">Area51</a></span>'
+ ),
+ array(
+ // Do not parse textual bbcodes in code
+ '[code]unparsed code [b]bold [i]bold + italic[/i][/b][/code]',
+ '<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>unparsed code [b]bold [i]bold + italic[/i][/b]</code></pre></div>'
+ ),
+ array(
+ // Do not parse quote bbcodes in code
+ '[code]unparsed code [quote="username"]quoted[/quote][/code]',
+ '<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>unparsed code [quote="username"]quoted[/quote]</code></pre></div>'
+ ),
+ array(
+ // Textual bbcode nesting into textual bbcode
+ '[b]bold [i]bold + italic[/b] italic[/i]',
+ '<span style="font-weight: bold">bold <span style="font-style: italic">bold + italic</span></span><span style="font-style: italic"> italic</span>'
+ ),
+ array(
+ "[code]\tline1\n line2[/code]",
+ '<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>' . "\tline1\n line2</code></pre></div>"
+ ),
+ array(
+ "[code]\n\tline1\n line2[/code]",
+ '<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>' . "\tline1\n line2</code></pre></div>"
+ ),
+ array(
+ '... http://example.org ...',
+ '... <a href="http://example.org" class="postlink">http://example.org</a> ...'
+ ),
+ array(
+ '... www.example.org ...',
+ '... <a href="http://www.example.org" class="postlink">www.example.org</a> ...'
+ ),
+ array(
+ // From make_clickable_test.php
+ 'www.phpbb.com/community/?',
+ '<a href="http://www.phpbb.com/community/" class="postlink">www.phpbb.com/community/</a>?'
+ ),
+ array(
+ // From make_clickable_test.php
+ 'http://www.phpbb.com/community/path/to/long/url/file.ext#section',
+ '<a href="http://www.phpbb.com/community/path/to/long/url/file.ext#section" class="postlink">http://www.phpbb.com/community/path/to/ ... xt#section</a>'
+ ),
+ array(
+ 'http://localhost/ http://localhost/phpbb/ http://localhost/phpbb/viewforum.php?f=1',
+ '<a href="http://localhost/" class="postlink">http://localhost/</a> <a href="http://localhost/phpbb/" class="postlink">http://localhost/phpbb/</a> <a href="http://localhost/phpbb/viewforum.php?f=1" class="postlink">viewforum.php?f=1</a>'
+ ),
+ array(
+ 'http://localhost/phpbb/viewforum.php?f=1#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+ '<a href="http://localhost/phpbb/viewforum.php?f=1#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" class="postlink">viewforum.php?f=1#xxxxxxxxxxxxxxxxxxxxx ... xxxxxxxxxx</a>'
+ ),
+ array(
+ '[url]http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0[/url]',
+ '<a href="http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0" class="postlink">http://example.org/0xxxxxxxxxxxxxxxxxxx ... xxxxxxxxx0</a>'
+ ),
+ array(
+ '[URL]http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0[/url]',
+ '<a href="http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0" class="postlink">http://example.org/0xxxxxxxxxxxxxxxxxxx ... xxxxxxxxx0</a>'
+ ),
+ array(
+ '[url=http://example.org/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[/url]',
+ '<a href="http://example.org/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" class="postlink">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</a>'
+ ),
+ array(
+ '[quote="[url=http://example.org]xxx[/url]"]...[/quote]',
+ '<blockquote><div><cite><a href="http://example.org" class="postlink">xxx</a> wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ '[quote="[url]http://example.org[/url]"]...[/quote]',
+ '<blockquote><div><cite><a href="http://example.org" class="postlink">http://example.org</a> wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ '[quote=http://example.org]...[/quote]',
+ '<blockquote><div><cite><a href="http://example.org" class="postlink">http://example.org</a> wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ "[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]\n\nFollowed by a reply",
+ "<blockquote class=\"uncited\"><div>\nThis is a long quote that is definitely going to exceed 80 characters\n</div></blockquote>\n\nFollowed by a reply"
+ ),
+ array(
+ '[quote=Username post_id=123]...[/quote]',
+ '<blockquote><div><cite>Username wrote: <a href="phpBB/viewtopic.php?p=123#p123" data-post-id="123" onclick="if(document.getElementById(hash.substr(1)))href=hash">↑</a></cite>...</div></blockquote>'
+ ),
+ array(
+ // Users are not allowed to submit their own URL for the post
+ '[quote="Username" post_url="http://fake.example.org"]...[/quote]',
+ '<blockquote><div><cite>Username wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ '[quote=Username time=58705871]...[/quote]',
+ '<blockquote><div><cite>Username wrote:<div class="responsive-hide">1971-11-11 11:11:11</div></cite>...</div></blockquote>'
+ ),
+ array(
+ '[quote=Username user_id=123]...[/quote]',
+ '<blockquote><div><cite><a href="phpBB/memberlist.php?mode=viewprofile&amp;u=123">Username</a> wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ // Users are not allowed to submit their own URL for the profile
+ '[quote=Username profile_url=http://fake.example.org]...[/quote]',
+ '<blockquote><div><cite>Username wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ // From phpbb_textformatter_s9e_utils_test::test_generate_quote()
+ '[quote=\'[quote="foo"]\']...[/quote]',
+ '<blockquote><div><cite>[quote="foo"] wrote:</cite>...</div></blockquote>'
+ ),
+ array(
+ "Emoji: \xF0\x9F\x98\x80",
+ 'Emoji: <img alt="' . "\xF0\x9F\x98\x80" . '" class="smilies" draggable="false" width="18" height="18" src="//cdn.jsdelivr.net/emojione/assets/svg/1f600.svg">'
+ ),
+ array(
+ "Emoji: \xF0\x9F\x98\x80",
+ "Emoji: \xF0\x9F\x98\x80",
+ function ($container)
+ {
+ $container->get('text_formatter.renderer')->set_viewsmilies(false);
+ }
+ ),
+ );
+ }
+}
diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php
new file mode 100644
index 0000000000..368b8a4f4b
--- /dev/null
+++ b/tests/text_formatter/s9e/factory_test.php
@@ -0,0 +1,263 @@
+<?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.
+*
+*/
+
+require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php';
+
+class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case
+{
+ public function setUp()
+ {
+ $this->cache = new phpbb_mock_cache;
+ $this->dispatcher = new phpbb_mock_event_dispatcher;
+ parent::setUp();
+ }
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/factory.xml');
+ }
+
+ public function get_cache_dir()
+ {
+ return __DIR__ . '/../../tmp/';
+ }
+
+ public function get_factory()
+ {
+ global $config, $phpbb_root_path, $request, $user;
+ $this->cache = new phpbb_mock_cache;
+ $dal = new \phpbb\textformatter\data_access(
+ $this->new_dbal(),
+ 'phpbb_bbcodes',
+ 'phpbb_smilies',
+ 'phpbb_styles',
+ 'phpbb_words',
+ $phpbb_root_path . 'styles/'
+ );
+ $factory = new \phpbb\textformatter\s9e\factory(
+ $dal,
+ $this->cache,
+ $this->dispatcher,
+ new \phpbb\config\config(array('allowed_schemes_links' => 'http,https,ftp')),
+ new \phpbb\textformatter\s9e\link_helper,
+ $this->get_cache_dir(),
+ '_foo_parser',
+ '_foo_renderer'
+ );
+
+ // Global objects required by generate_board_url()
+ $config = new \phpbb\config\config(array(
+ 'script_path' => '/phpbb',
+ 'server_name' => 'localhost',
+ 'server_port' => 80,
+ 'server_protocol' => 'http://',
+ ));
+ $request = new phpbb_mock_request;
+ $user = new phpbb_mock_user;
+
+ return $factory;
+ }
+
+ public function test_get_configurator()
+ {
+ $configurator = $this->get_factory()->get_configurator();
+
+ $this->assertInstanceOf('s9e\\TextFormatter\\Configurator', $configurator);
+
+ $this->assertTrue(isset($configurator->plugins['Autoemail']));
+ $this->assertTrue(isset($configurator->plugins['Autolink']));
+
+ $this->assertTrue(isset($configurator->BBCodes['B']));
+ $this->assertTrue(isset($configurator->BBCodes['CODE']));
+ $this->assertTrue(isset($configurator->BBCodes['COLOR']));
+ $this->assertTrue(isset($configurator->BBCodes['EMAIL']));
+ $this->assertTrue(isset($configurator->BBCodes['FLASH']));
+ $this->assertTrue(isset($configurator->BBCodes['I']));
+ $this->assertTrue(isset($configurator->BBCodes['IMG']));
+ $this->assertTrue(isset($configurator->BBCodes['LIST']));
+ $this->assertTrue(isset($configurator->BBCodes['*']));
+ $this->assertTrue(isset($configurator->BBCodes['QUOTE']));
+ $this->assertTrue(isset($configurator->BBCodes['SIZE']));
+ $this->assertTrue(isset($configurator->BBCodes['U']));
+ $this->assertTrue(isset($configurator->BBCodes['URL']));
+
+ // This custom BBCode should be set
+ $this->assertTrue(isset($configurator->BBCodes['CUSTOM']));
+
+ $this->assertTrue(isset($configurator->Emoticons[':D']));
+ }
+
+ public function test_regenerate()
+ {
+ extract($this->get_factory()->regenerate());
+
+ $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser);
+ $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer);
+
+ $renderer_data = $this->cache->get('_foo_renderer');
+ $this->assertEquals($parser, $this->cache->get('_foo_parser'), 'The parser was not cached');
+ $this->assertEquals(get_class($renderer), $renderer_data['class']);
+ $this->assertInstanceOf('s9e\\TextFormatter\\Plugins\\Censor\\Helper', $renderer_data['censor']);
+
+ $file = $this->get_cache_dir() . get_class($renderer) . '.php';
+ $this->assertFileExists($file);
+ unlink($file);
+ }
+
+ public function test_tidy()
+ {
+ $factory = $this->get_factory();
+
+ // Create a fake "old" cache file
+ $old_file = $this->get_cache_dir() . 's9e_foo.php';
+ touch($old_file);
+
+ // Create a current renderer
+ extract($factory->regenerate());
+ $new_file = $this->get_cache_dir() . get_class($renderer) . '.php';
+
+ // Tidy the cache
+ $factory->tidy();
+
+ $this->assertFileExists($new_file, 'The current renderer has been deleted');
+ $this->assertFileNotExists($old_file, 'The old renderer has not been deleted');
+
+ unlink($new_file);
+ }
+
+ public function test_local_url()
+ {
+ global $config, $user, $request;
+ $config = new \phpbb\config\config(array(
+ 'force_server_vars' => true,
+ 'server_protocol' => 'http://',
+ 'server_name' => 'path',
+ 'server_port' => 80,
+ 'script_path' => '/to',
+ 'cookie_secure' => false
+ ));
+ $user = new phpbb_mock_user;
+ $request = new phpbb_mock_request;
+
+ $fixture = __DIR__ . '/fixtures/local_url.xml';
+ $renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer');
+
+ $this->assertSame(
+ '<a href="http://path/to/foo">http://path/to/foo</a>',
+ $renderer->render('<r><LOCAL content="foo"><s>[local]</s>foo<e>[/local]</e></LOCAL></r>')
+ );
+ }
+
+ public function test_smilies_special_chars()
+ {
+ // Use a smiley that contains every special chars in every field
+ $fixture = __DIR__ . '/fixtures/smilies_special_chars.xml';
+ $renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer');
+
+ $this->assertSame(
+ '<img class="smilies" src="phpBB/images/smilies/%22%27%3C&amp;%3E.png" alt="&quot;\'&lt;&amp;&gt;" title="&quot;\'&lt;&amp;&gt;">',
+ $renderer->render('<r><E>"\'&lt;&amp;&gt;</E></r>')
+ );
+ }
+
+ public function test_duplicate_smilies()
+ {
+ $fixture = __DIR__ . '/fixtures/smilies_duplicate.xml';
+ $parser = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.parser');
+
+ $this->assertSame(
+ '<r><E>:)</E></r>',
+ $parser->parse(':)')
+ );
+ }
+
+ /**
+ * @testdox {INTTEXT} is supported in custom BBCodes
+ */
+ public function test_inttext_token()
+ {
+ $fixture = __DIR__ . '/fixtures/inttext_token.xml';
+ $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture);
+ $parser = $container->get('text_formatter.parser');
+ $renderer = $container->get('text_formatter.renderer');
+
+ $original = '[spoiler=ɎɆS]text[/spoiler]';
+ $expected = '<div class="spoiler"><div class="title">ɎɆS</div><div class="content">text</div></div>';
+ $this->assertSame($expected, $renderer->render($parser->parse($original)));
+
+ $original = '[spoiler=N:O:P:E]text[/spoiler]';
+ $expected = $original;
+ $this->assertSame($expected, $renderer->render($parser->parse($original)));
+ }
+
+ /**
+ * @testdox Preserves comments in custom BBCodes
+ */
+ public function test_preserve_comments()
+ {
+ $fixture = __DIR__ . '/fixtures/preserve_comments.xml';
+ $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture);
+ $parser = $container->get('text_formatter.parser');
+ $renderer = $container->get('text_formatter.renderer');
+
+ $original = '[X]';
+ $expected = '<!-- comment -->';
+ $this->assertSame($expected, $renderer->render($parser->parse($original)));
+ }
+
+ /**
+ * @testdox Accepts unsafe custom BBCodes
+ */
+ public function test_unsafe_bbcode()
+ {
+ $fixture = __DIR__ . '/fixtures/unsafe_bbcode.xml';
+ $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture);
+ $parser = $container->get('text_formatter.parser');
+ $renderer = $container->get('text_formatter.renderer');
+
+ $original = '[xss=javascript:alert(1)]text[/xss]';
+ $expected = '<a href="javascript:alert(1)">text</a>';
+ $this->assertSame($expected, $renderer->render($parser->parse($original)));
+ }
+
+ /**
+ * @testdox get_configurator() triggers events before and after configuration
+ */
+ public function test_configure_events()
+ {
+ $this->dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface');
+ $this->dispatcher
+ ->expects($this->at(0))
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_configure_before',
+ $this->callback(array($this, 'configure_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+ $this->dispatcher
+ ->expects($this->at(1))
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_configure_after',
+ $this->callback(array($this, 'configure_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+
+ $this->get_factory()->get_configurator();
+ }
+
+ public function configure_event_callback($vars)
+ {
+ return isset($vars['configurator']) && $vars['configurator'] instanceof \s9e\TextFormatter\Configurator;
+ }
+}
diff --git a/tests/text_formatter/s9e/fixtures/default_formatting.xml b/tests/text_formatter/s9e/fixtures/default_formatting.xml
new file mode 100644
index 0000000000..2b7236fb30
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/default_formatting.xml
@@ -0,0 +1,466 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>1</value>
+ <value>:D</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>1</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>:-D</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>2</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>:grin:</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>3</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>:)</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>4</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>:-)</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>5</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>:smile:</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>6</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>7</value>
+ <value>;)</value>
+ <value>Wink</value>
+ <value>icon_e_wink.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>7</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>8</value>
+ <value>;-)</value>
+ <value>Wink</value>
+ <value>icon_e_wink.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>8</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>9</value>
+ <value>:wink:</value>
+ <value>Wink</value>
+ <value>icon_e_wink.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>9</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>10</value>
+ <value>:(</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>10</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>11</value>
+ <value>:-(</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>11</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>12</value>
+ <value>:sad:</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>12</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>13</value>
+ <value>:o</value>
+ <value>Surprised</value>
+ <value>icon_e_surprised.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>13</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>14</value>
+ <value>:-o</value>
+ <value>Surprised</value>
+ <value>icon_e_surprised.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>14</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>15</value>
+ <value>:eek:</value>
+ <value>Surprised</value>
+ <value>icon_e_surprised.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>15</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>16</value>
+ <value>:shock:</value>
+ <value>Shocked</value>
+ <value>icon_eek.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>16</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>17</value>
+ <value>:?</value>
+ <value>Confused</value>
+ <value>icon_e_confused.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>17</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>18</value>
+ <value>:-?</value>
+ <value>Confused</value>
+ <value>icon_e_confused.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>18</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>19</value>
+ <value>:???:</value>
+ <value>Confused</value>
+ <value>icon_e_confused.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>19</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>20</value>
+ <value>8-)</value>
+ <value>Cool</value>
+ <value>icon_cool.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>20</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>21</value>
+ <value>:cool:</value>
+ <value>Cool</value>
+ <value>icon_cool.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>21</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>22</value>
+ <value>:lol:</value>
+ <value>Laughing</value>
+ <value>icon_lol.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>22</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>23</value>
+ <value>:x</value>
+ <value>Mad</value>
+ <value>icon_mad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>23</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>24</value>
+ <value>:-x</value>
+ <value>Mad</value>
+ <value>icon_mad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>24</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>25</value>
+ <value>:mad:</value>
+ <value>Mad</value>
+ <value>icon_mad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>25</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>26</value>
+ <value>:P</value>
+ <value>Razz</value>
+ <value>icon_razz.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>26</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>27</value>
+ <value>:-P</value>
+ <value>Razz</value>
+ <value>icon_razz.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>27</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>28</value>
+ <value>:razz:</value>
+ <value>Razz</value>
+ <value>icon_razz.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>28</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>29</value>
+ <value>:oops:</value>
+ <value>Embarrassed</value>
+ <value>icon_redface.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>29</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>30</value>
+ <value>:cry:</value>
+ <value>Crying or Very Sad</value>
+ <value>icon_cry.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>30</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>31</value>
+ <value>:evil:</value>
+ <value>Evil or Very Mad</value>
+ <value>icon_evil.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>31</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>32</value>
+ <value>:twisted:</value>
+ <value>Twisted Evil</value>
+ <value>icon_twisted.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>32</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>33</value>
+ <value>:roll:</value>
+ <value>Rolling Eyes</value>
+ <value>icon_rolleyes.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>33</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>34</value>
+ <value>:!:</value>
+ <value>Exclamation</value>
+ <value>icon_exclaim.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>34</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>35</value>
+ <value>:?:</value>
+ <value>Question</value>
+ <value>icon_question.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>35</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>36</value>
+ <value>:idea:</value>
+ <value>Idea</value>
+ <value>icon_idea.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>36</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>37</value>
+ <value>:arrow:</value>
+ <value>Arrow</value>
+ <value>icon_arrow.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>37</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>38</value>
+ <value>:|</value>
+ <value>Neutral</value>
+ <value>icon_neutral.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>38</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>39</value>
+ <value>:-|</value>
+ <value>Neutral</value>
+ <value>icon_neutral.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>39</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>40</value>
+ <value>:mrgreen:</value>
+ <value>Mr. Green</value>
+ <value>icon_mrgreen.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>40</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>41</value>
+ <value>:geek:</value>
+ <value>Geek</value>
+ <value>icon_e_geek.gif</value>
+ <value>17</value>
+ <value>17</value>
+ <value>41</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>42</value>
+ <value>:ugeek:</value>
+ <value>Uber Geek</value>
+ <value>icon_e_ugeek.gif</value>
+ <value>17</value>
+ <value>18</value>
+ <value>42</value>
+ <value>1</value>
+ </row>
+ </table>
+
+ <table name="phpbb_styles">
+ <column>style_id</column>
+ <column>style_name</column>
+ <column>style_copyright</column>
+ <column>style_active</column>
+ <column>style_path</column>
+ <column>bbcode_bitfield</column>
+ <column>style_parent_id</column>
+ <column>style_parent_tree</column>
+ <row>
+ <value>1</value>
+ <value>prosilver</value>
+ <value>&amp;copy; phpBB Group</value>
+ <value>1</value>
+ <value>prosilver</value>
+ <value>kNg=</value>
+ <value>0</value>
+ <value></value>
+ </row>
+ </table>
+
+ <table name="phpbb_words">
+ <column>word_id</column>
+ <column>word</column>
+ <column>replacement</column>
+
+ <row>
+ <value>1</value>
+ <value>apple</value>
+ <value>banana</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/default_lang.xml b/tests/text_formatter/s9e/fixtures/default_lang.xml
new file mode 100644
index 0000000000..2cfde4aab2
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/default_lang.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+
+ <row>
+ <value>13</value>
+ <value>foo</value>
+ <value></value>
+ <value>1</value>
+ <value>[foo]{TEXT}[/foo]</value>
+ <value>{L_FOO_BAR}</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/factory.xml b/tests/text_formatter/s9e/fixtures/factory.xml
new file mode 100644
index 0000000000..9ae52e9747
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/factory.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>custom</value>
+ <value></value>
+ <value>1</value>
+ <value>[custom]{TEXT}[/custom]</value>
+ <value>&lt;span style=&quot;color:red&quot;&gt;{TEXT}&lt;/span&gt;</value>
+ <value>!\[custom\](.*?)\[/custom\]!ies</value>
+ <value>'[custom:$uid]'.str_replace(array(&quot;\r\n&quot;, '\&quot;', '\'', '(', ')'), array(&quot;\n&quot;, '&quot;', '&amp;#39;', '&amp;#40;', '&amp;#41;'), trim('${1}')).'[/custom:$uid]'</value>
+ <value>!\[custom:$uid\](.*?)\[/custom:$uid\]!s</value>
+ <value>&lt;span style=&quot;color:red&quot;&gt;${1}&lt;/span&gt;</value>
+ </row>
+ <row>
+ <value>14</value>
+ <value>unsafe</value>
+ <value></value>
+ <value>1</value>
+ <value>[unsafe]{TEXT}[/unsafe]</value>
+ <value>&lt;script&gt;{TEXT}&lt;/script&gt;</value>
+ <value>!\[unsafe\](.*?)\[/unsafe\]!ies</value>
+ <value>'[unsafe:$uid]'.str_replace(array(&quot;\r\n&quot;, '\&quot;', '\'', '(', ')'), array(&quot;\n&quot;, '&quot;', '&amp;#39;', '&amp;#40;', '&amp;#41;'), trim('${1}')).'[/unsafe:$uid]'</value>
+ <value>!\[unsafe:$uid\](.*?)\[/unsafe:$uid\]!s</value>
+ <value>&lt;script&gt;${1}&lt;/script&gt;</value>
+ </row>
+ </table>
+
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>1</value>
+ <value>:D</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>2</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>:)</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>4</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>10</value>
+ <value>:(</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>10</value>
+ <value>1</value>
+ </row>
+ </table>
+
+ <table name="phpbb_styles">
+ <column>style_id</column>
+ <column>style_name</column>
+ <column>style_copyright</column>
+ <column>style_active</column>
+ <column>style_path</column>
+ <column>bbcode_bitfield</column>
+ <column>style_parent_id</column>
+ <column>style_parent_tree</column>
+
+ <row>
+ <value>1</value>
+ <value>prosilver</value>
+ <value>&amp;copy; phpBB Group</value>
+ <value>1</value>
+ <value>prosilver</value>
+ <value>kNg=</value>
+ <value>0</value>
+ <value></value>
+ </row>
+ </table>
+
+ <table name="phpbb_words">
+ <column>word_id</column>
+ <column>word</column>
+ <column>replacement</column>
+
+ <row>
+ <value>1</value>
+ <value>apple</value>
+ <value>banana</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/inttext_token.xml b/tests/text_formatter/s9e/fixtures/inttext_token.xml
new file mode 100644
index 0000000000..30b971f315
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/inttext_token.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>spoiler=</value>
+ <value></value>
+ <value>1</value>
+ <value>[spoiler={INTTEXT}]{TEXT}[/spoiler]</value>
+ <value><![CDATA[<div class="spoiler"><div class="title">{INTTEXT}</div><div class="content">{TEXT}</div></div>]]></value>
+ <value><![CDATA[!\[spoiler\=([\p{L}\p{N}\-+,_. ]+)\](.*?)\[/spoiler\]!iues]]></value>
+ <value><![CDATA['[spoiler=${1}:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${2}')).'[/spoiler:$uid]']]></value>
+ <value><![CDATA[!\[spoiler\=([\p{L}\p{N}\-+,_. ]+):$uid\](.*?)\[/spoiler:$uid\]!su]]></value><value><![CDATA[<div class="spoiler"><div class="title">${1}</div><div class="content">${2}</div></div>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/local_url.xml b/tests/text_formatter/s9e/fixtures/local_url.xml
new file mode 100644
index 0000000000..9db2bf4710
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/local_url.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>local</value>
+ <value></value>
+ <value>1</value>
+ <value>[local]{LOCAL_URL}[/local]</value>
+ <value><![CDATA[<a href="{LOCAL_URL}">{LOCAL_URL}</a>]]></value>
+ <value><![CDATA[!\[local\]((?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?)\[/local\]!ie]]></value>
+ <value><![CDATA['[local:$uid]'.$this->bbcode_specialchars('${1}').'[/local:$uid]']]></value>
+ <value><![CDATA[!\[local:$uid\](?i)((?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?)(?-i)\[/local:$uid\]!s]]></value>
+ <value><![CDATA[<a href="http://path/to/phpBB/${1}">http://path/to/phpBB/${1}</a>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/preserve_comments.xml b/tests/text_formatter/s9e/fixtures/preserve_comments.xml
new file mode 100644
index 0000000000..f81d366aad
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/preserve_comments.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>X</value>
+ <value></value>
+ <value>1</value>
+ <value>[X][/X]</value>
+ <value><![CDATA[<!-- comment -->]]></value>
+ <value><![CDATA[!\[x\]\[/x\]!i]]></value>
+ <value><![CDATA[[x:$uid][/x:$uid]]]></value>
+ <value><![CDATA[[x:$uid][/x:$uid]]]></value>
+ <value></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/smilies_duplicate.xml b/tests/text_formatter/s9e/fixtures/smilies_duplicate.xml
new file mode 100644
index 0000000000..9645f3e516
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/smilies_duplicate.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>1</value>
+ <value>:)</value>
+ <value>:)</value>
+ <value>foo.png</value>
+ <value>15</value>
+ <value>17</value>
+ <value>2</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>:)</value>
+ <value>:)</value>
+ <value>bar.png</value>
+ <value>15</value>
+ <value>17</value>
+ <value>2</value>
+ <value>2</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml
new file mode 100644
index 0000000000..d3a7cfa4f7
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>1</value>
+ <value>"'&lt;&amp;&gt;</value>
+ <value>"'&lt;&amp;&gt;</value>
+ <value>"'&lt;&amp;&gt;.png</value>
+ <value>15</value>
+ <value>17</value>
+ <value>2</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/style_inheritance.xml b/tests/text_formatter/s9e/fixtures/style_inheritance.xml
new file mode 100644
index 0000000000..a692d0ef2d
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/style_inheritance.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_styles">
+ <column>style_id</column>
+ <column>style_name</column>
+ <column>style_copyright</column>
+ <column>style_active</column>
+ <column>style_path</column>
+ <column>bbcode_bitfield</column>
+ <column>style_parent_id</column>
+ <column>style_parent_tree</column>
+
+ <row>
+ <value>1</value>
+ <value>foo</value>
+ <value></value>
+ <value>1</value>
+ <value>foo</value>
+ <!-- Bitfield for "b" only -->
+ <value>QA==</value>
+ <value>0</value>
+ <value></value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>fooplus</value>
+ <value></value>
+ <value>1</value>
+ <value>fooplus</value>
+ <value>QA==</value>
+ <value>1</value>
+ <value></value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>fooplusplus</value>
+ <value></value>
+ <value>1</value>
+ <value>fooplusplus</value>
+ <value>QA==</value>
+ <value>2</value>
+ <value></value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>bar</value>
+ <value></value>
+ <value>1</value>
+ <value>bar</value>
+ <!-- Bitfield for "b" only -->
+ <value>QA==</value>
+ <value>0</value>
+ <value></value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>barplus</value>
+ <value></value>
+ <value>1</value>
+ <value>barplus</value>
+ <value>QA==</value>
+ <value>4</value>
+ <value></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/styles.xml b/tests/text_formatter/s9e/fixtures/styles.xml
new file mode 100644
index 0000000000..8004412aea
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/styles.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_styles">
+ <column>style_id</column>
+ <column>style_name</column>
+ <column>style_copyright</column>
+ <column>style_active</column>
+ <column>style_path</column>
+ <column>bbcode_bitfield</column>
+ <column>style_parent_id</column>
+ <column>style_parent_tree</column>
+
+ <row>
+ <value>1</value>
+ <value>foo</value>
+ <value></value>
+ <value>1</value>
+ <value>foo</value>
+ <!-- Bitfield for "b" only -->
+ <value>QA==</value>
+ <value>0</value>
+ <value></value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>bar</value>
+ <value></value>
+ <value>1</value>
+ <value>bar</value>
+ <!-- Bitfield for "b" only -->
+ <value>QA==</value>
+ <value>0</value>
+ <value></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html
new file mode 100644
index 0000000000..76a35542be
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html
@@ -0,0 +1,40 @@
+<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open -->
+<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default -->
+<!-- BEGIN ulist_close --></ul><!-- END ulist_close -->
+
+<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open -->
+<!-- BEGIN olist_close --></ol><!-- END olist_close -->
+
+<!-- BEGIN listitem --><li><!-- END listitem -->
+<!-- BEGIN listitem_close --></li><!-- END listitem_close -->
+
+<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open -->
+<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open -->
+<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close -->
+
+<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open -->
+<!-- BEGIN code_close --></code></div><!-- END code_close -->
+
+<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open -->
+<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close -->
+
+<!-- BEGIN b_open --><b><!-- END b_open -->
+<!-- BEGIN b_close --></b><!-- END b_close -->
+
+<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open -->
+<!-- BEGIN u_close --></span><!-- END u_close -->
+
+<!-- BEGIN i_open --><em><!-- END i_open -->
+<!-- BEGIN i_close --></em><!-- END i_close -->
+
+<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color -->
+
+<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: 116%;">{TEXT}</span><!-- END size -->
+
+<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img -->
+
+<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url -->
+
+<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email -->
+
+<!-- BEGIN flash --><object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}"><param name="movie" value="{URL}" /><param name="play" value="false" /><param name="loop" value="false" /><param name="quality" value="high" /><param name="allowScriptAccess" value="never" /><param name="allowNetworking" value="internal" /><embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed></object><!-- END flash -->
diff --git a/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html
new file mode 100644
index 0000000000..fad8d828fd
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html
@@ -0,0 +1,40 @@
+<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open -->
+<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default -->
+<!-- BEGIN ulist_close --></ul><!-- END ulist_close -->
+
+<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open -->
+<!-- BEGIN olist_close --></ol><!-- END olist_close -->
+
+<!-- BEGIN listitem --><li><!-- END listitem -->
+<!-- BEGIN listitem_close --></li><!-- END listitem_close -->
+
+<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open -->
+<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open -->
+<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close -->
+
+<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open -->
+<!-- BEGIN code_close --></code></div><!-- END code_close -->
+
+<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open -->
+<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close -->
+
+<!-- BEGIN b_open --><b class="barplus"><!-- END b_open -->
+<!-- BEGIN b_close --></b><!-- END b_close -->
+
+<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open -->
+<!-- BEGIN u_close --></span><!-- END u_close -->
+
+<!-- BEGIN i_open --><em><!-- END i_open -->
+<!-- BEGIN i_close --></em><!-- END i_close -->
+
+<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color -->
+
+<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: 116%;">{TEXT}</span><!-- END size -->
+
+<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img -->
+
+<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url -->
+
+<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email -->
+
+<!-- BEGIN flash --><object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}"><param name="movie" value="{URL}" /><param name="play" value="false" /><param name="loop" value="false" /><param name="quality" value="high" /><param name="allowScriptAccess" value="never" /><param name="allowNetworking" value="internal" /><embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed></object><!-- END flash -->
diff --git a/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html
new file mode 100644
index 0000000000..3e38d13a32
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html
@@ -0,0 +1,40 @@
+<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open -->
+<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default -->
+<!-- BEGIN ulist_close --></ul><!-- END ulist_close -->
+
+<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open -->
+<!-- BEGIN olist_close --></ol><!-- END olist_close -->
+
+<!-- BEGIN listitem --><li><!-- END listitem -->
+<!-- BEGIN listitem_close --></li><!-- END listitem_close -->
+
+<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open -->
+<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open -->
+<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close -->
+
+<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open -->
+<!-- BEGIN code_close --></code></div><!-- END code_close -->
+
+<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open -->
+<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close -->
+
+<!-- BEGIN b_open --><strong><!-- END b_open -->
+<!-- BEGIN b_close --></strong><!-- END b_close -->
+
+<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open -->
+<!-- BEGIN u_close --></span><!-- END u_close -->
+
+<!-- BEGIN i_open --><em><!-- END i_open -->
+<!-- BEGIN i_close --></em><!-- END i_close -->
+
+<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color -->
+
+<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: 116%;">{TEXT}</span><!-- END size -->
+
+<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img -->
+
+<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url -->
+
+<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email -->
+
+<!-- BEGIN flash --><object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}"><param name="movie" value="{URL}" /><param name="play" value="false" /><param name="loop" value="false" /><param name="quality" value="high" /><param name="allowScriptAccess" value="never" /><param name="allowNetworking" value="internal" /><embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed></object><!-- END flash -->
diff --git a/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml b/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml
new file mode 100644
index 0000000000..55a2e689b6
--- /dev/null
+++ b/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>xss=</value>
+ <value></value>
+ <value>1</value>
+ <value>[xss={TEXT1}]{TEXT2}[/xss]</value>
+ <value><![CDATA[<a href="{TEXT1}">{TEXT2}</a>]]></value>
+ <value><![CDATA[!\[xss\=(.*?)\](.*?)\[/xss\]!ies]]></value>
+ <value><![CDATA['[xss='.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${2}')).'[/xss:$uid]']]></value>
+ <value><![CDATA[!\[xss\=(.*?):$uid\](.*?)\[/xss:$uid\]!s]]></value>
+ <value><![CDATA[<a href="${1}">${2}</a>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php
new file mode 100644
index 0000000000..4b9bbf9bb2
--- /dev/null
+++ b/tests/text_formatter/s9e/parser_test.php
@@ -0,0 +1,258 @@
+<?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.
+*
+*/
+
+class phpbb_textformatter_s9e_parser_test extends phpbb_test_case
+{
+ public function test_load_from_cache()
+ {
+ $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache = $this->getMock('phpbb_mock_cache');
+ $cache->expects($this->once())
+ ->method('get')
+ ->with('_foo_parser')
+ ->will($this->returnValue($mock));
+
+ $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory->expects($this->never())->method('regenerate');
+
+ $parser = new \phpbb\textformatter\s9e\parser(
+ $cache,
+ '_foo_parser',
+ $factory,
+ new phpbb_mock_event_dispatcher
+ );
+ }
+
+ public function test_use_from_cache()
+ {
+ $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects($this->once())
+ ->method('parse')
+ ->with('test')
+ ->will($this->returnValue('<t>test</t>'));
+
+ $cache = new phpbb_mock_cache;
+ $cache->put('_foo_parser', $mock);
+
+ $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory->expects($this->never())->method('regenerate');
+
+ $parser = new \phpbb\textformatter\s9e\parser(
+ $cache,
+ '_foo_parser',
+ $factory,
+ new phpbb_mock_event_dispatcher
+ );
+
+ $this->assertSame('<t>test</t>', $parser->parse('test'));
+ }
+
+ public function test_regenerate_on_cache_miss()
+ {
+ $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects($this->once())
+ ->method('parse')
+ ->with('test')
+ ->will($this->returnValue('<t>test</t>'));
+
+ $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory->expects($this->once())
+ ->method('regenerate')
+ ->will($this->returnValue(array('parser' => $mock)));
+
+ $parser = new \phpbb\textformatter\s9e\parser(
+ new phpbb_mock_cache,
+ '_foo_parser',
+ $factory,
+ new phpbb_mock_event_dispatcher
+ );
+
+ $this->assertSame('<t>test</t>', $parser->parse('test'));
+ }
+
+ /**
+ * @dataProvider get_options_tests()
+ */
+ public function test_options($adapter_method, $adapter_arg, $concrete_method, $concrete_arg)
+ {
+ $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser')
+ ->setMethods(array($concrete_method))
+ ->disableOriginalConstructor()
+ ->getMock();
+ foreach ((array) $concrete_arg as $i => $concrete_arg)
+ {
+ $mock->expects($this->at($i))
+ ->method($concrete_method)
+ ->with($concrete_arg);
+ }
+
+ $cache = new phpbb_mock_cache;
+ $cache->put('_foo_parser', $mock);
+
+ $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser = new \phpbb\textformatter\s9e\parser(
+ $cache,
+ '_foo_parser',
+ $factory,
+ new phpbb_mock_event_dispatcher
+ );
+
+ call_user_func_array(array($parser, $adapter_method), (array) $adapter_arg);
+ }
+
+ public function get_options_tests()
+ {
+ return array(
+ array(
+ 'disable_bbcode', 'url',
+ 'disableTag', 'URL'
+ ),
+ array(
+ 'disable_bbcodes', null,
+ 'disablePlugin', 'BBCodes'
+ ),
+ array(
+ 'disable_magic_url', null,
+ 'disablePlugin', array('Autoemail', 'Autolink')
+ ),
+ array(
+ 'disable_smilies', null,
+ 'disablePlugin', 'Emoticons'
+ ),
+ array(
+ 'enable_bbcode', 'url',
+ 'enableTag', 'URL'
+ ),
+ array(
+ 'enable_bbcodes', null,
+ 'enablePlugin', 'BBCodes'
+ ),
+ array(
+ 'enable_magic_url', null,
+ 'enablePlugin', array('Autoemail', 'Autolink')
+ ),
+ array(
+ 'enable_smilies', null,
+ 'enablePlugin', 'Emoticons'
+ )
+ );
+ }
+
+ /**
+ * @testdox The constructor triggers a core.text_formatter_s9e_parser_setup event
+ */
+ public function test_setup_event()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface');
+ $dispatcher
+ ->expects($this->once())
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_parser_setup',
+ $this->callback(array($this, 'setup_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+
+ new \phpbb\textformatter\s9e\parser(
+ $container->get('cache.driver'),
+ '_foo_parser',
+ $container->get('text_formatter.s9e.factory'),
+ $dispatcher
+ );
+ }
+
+ public function setup_event_callback($vars)
+ {
+ return isset($vars['parser'])
+ && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser;
+ }
+
+ /**
+ * @testdox parse() triggers a core.text_formatter_s9e_parse_before and core.text_formatter_s9e_parse_after events
+ */
+ public function test_parse_event()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface');
+ $dispatcher
+ ->expects($this->any())
+ ->method('trigger_event')
+ ->will($this->returnArgument(1));
+ $dispatcher
+ ->expects($this->at(1))
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_parse_before',
+ $this->callback(array($this, 'parse_before_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+ $dispatcher
+ ->expects($this->at(2))
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_parse_after',
+ $this->callback(array($this, 'parse_after_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+
+ $parser = new \phpbb\textformatter\s9e\parser(
+ $container->get('cache.driver'),
+ '_foo_parser',
+ $container->get('text_formatter.s9e.factory'),
+ $dispatcher
+ );
+ $parser->parse('...');
+ }
+
+ public function parse_before_event_callback($vars)
+ {
+ return isset($vars['parser'])
+ && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser
+ && isset($vars['text'])
+ && $vars['text'] === '...';
+ }
+
+ public function parse_after_event_callback($vars)
+ {
+ return isset($vars['parser'])
+ && $vars['parser'] instanceof \phpbb\textformatter\s9e\parser
+ && isset($vars['xml'])
+ && $vars['xml'] === '<t>...</t>';
+ }
+
+ public function test_get_parser()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $parser = $container->get('text_formatter.parser');
+ $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser->get_parser());
+ }
+}
diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php
new file mode 100644
index 0000000000..2b034259c9
--- /dev/null
+++ b/tests/text_formatter/s9e/renderer_test.php
@@ -0,0 +1,481 @@
+<?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.
+*
+*/
+
+class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case
+{
+ public function get_cache_dir()
+ {
+ return __DIR__ . '/../../tmp/';
+ }
+
+ public function test_load_from_cache()
+ {
+ // Save a fake renderer class in the cache dir
+ file_put_contents(
+ $this->get_cache_dir() . 'renderer_foo.php',
+ '<?php class renderer_foo { public function setParameter() {} }'
+ );
+
+ $cache = $this->getMock('phpbb_mock_cache');
+ $cache->expects($this->once())
+ ->method('get')
+ ->with('_foo_renderer')
+ ->will($this->returnValue(array('class' => 'renderer_foo')));
+
+ $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory->expects($this->never())->method('regenerate');
+
+ $renderer = new \phpbb\textformatter\s9e\renderer(
+ $cache,
+ $this->get_cache_dir(),
+ '_foo_renderer',
+ $factory,
+ new phpbb_mock_event_dispatcher
+ );
+ }
+
+ public function test_regenerate_on_cache_miss()
+ {
+ $mock = $this->getMockForAbstractClass('s9e\\TextFormatter\\Renderer');
+
+ $cache = $this->getMock('phpbb_mock_cache');
+ $cache->expects($this->once())
+ ->method('get')
+ ->with('_foo_renderer')
+ ->will($this->returnValue(false));
+
+ $factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $factory->expects($this->once())
+ ->method('regenerate')
+ ->will($this->returnValue(array('parser' => $mock)));
+
+ $renderer = new \phpbb\textformatter\s9e\renderer(
+ $cache,
+ $this->get_cache_dir(),
+ '_foo_renderer',
+ $factory,
+ new phpbb_mock_event_dispatcher
+ );
+ }
+
+ /**
+ * @dataProvider get_options_cases
+ */
+ public function test_options($original, $expected, $calls)
+ {
+ $container = new phpbb_mock_container_builder;
+ $this->get_test_case_helpers()->set_s9e_services($container);
+
+ $renderer = $container->get('text_formatter.renderer');
+
+ foreach ($calls as $method => $arg)
+ {
+ $renderer->$method($arg);
+ }
+
+ $this->assertSame($expected, $renderer->render($original));
+ }
+
+ public function get_options_cases()
+ {
+ return array(
+ array(
+ '<t>apple</t>',
+ 'banana',
+ array('set_viewcensors' => true)
+ ),
+ array(
+ '<t>apple</t>',
+ 'apple',
+ array('set_viewcensors' => false)
+ ),
+ array(
+ '<r><FLASH height="456" url="http://example.org/foo.swf" width="123"><s>[flash=123,456]</s><URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL><e>[/flash]</e></FLASH></r>',
+ '<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="123" height="456"><param name="movie" value="http://example.org/foo.swf"><param name="play" value="false"><param name="loop" value="false"><param name="quality" value="high"><param name="allowScriptAccess" value="never"><param name="allowNetworking" value="internal"><embed src="http://example.org/foo.swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="123" height="456" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></object>',
+ array('set_viewflash' => true)
+ ),
+ array(
+ '<r><IMG src="http://example.org/foo.png"><s>[img]</s>http://example.org/foo.png<e>[/img]</e></IMG></r>',
+ '<img src="http://example.org/foo.png" class="postimage" alt="Image">',
+ array('set_viewimg' => true)
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ '<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile">',
+ array('set_viewsmilies' => true)
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ ':)',
+ array('set_viewsmilies' => false)
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider get_default_options_cases
+ */
+ public function test_default_options($original, $expected, $setup = null)
+ {
+ $container = new phpbb_mock_container_builder;
+
+ if (isset($setup))
+ {
+ $setup($container, $this);
+ }
+
+ $this->get_test_case_helpers()->set_s9e_services($container);
+
+ $this->assertSame($expected, $container->get('text_formatter.renderer')->render($original));
+ }
+
+ public function get_default_options_cases()
+ {
+ return array(
+ array(
+ '<t>apple</t>',
+ 'banana'
+ ),
+ array(
+ '<t>apple</t>',
+ 'banana',
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewcensors', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ array(
+ '<t>apple</t>',
+ 'banana',
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewcensors', false);
+
+ $config = new \phpbb\config\config(array('allow_nocensors' => true));
+
+ $phpbb_container->set('user', $user);
+ $phpbb_container->set('config', $config);
+ }
+ ),
+ array(
+ '<t>apple</t>',
+ 'apple',
+ function ($phpbb_container, $test)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewcensors', false);
+
+ $config = new \phpbb\config\config(array('allow_nocensors' => true));
+
+ $auth = $test->getMock('phpbb\\auth\\auth');
+ $auth->expects($test->any())
+ ->method('acl_get')
+ ->with('u_chgcensors')
+ ->will($test->returnValue(true));
+
+ $phpbb_container->set('user', $user);
+ $phpbb_container->set('config', $config);
+ $phpbb_container->set('auth', $auth);
+ }
+ ),
+ array(
+ '<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>',
+ '<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="123" height="456"><param name="movie" value="http://localhost/foo.swf"><param name="play" value="false"><param name="loop" value="false"><param name="quality" value="high"><param name="allowScriptAccess" value="never"><param name="allowNetworking" value="internal"><embed src="http://localhost/foo.swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="123" height="456" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></object>'
+ ),
+ array(
+ '<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>',
+ 'http://localhost/foo.swf',
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewflash', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ array(
+ '<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>',
+ '<img src="http://localhost/mrgreen.gif" class="postimage" alt="Image">'
+ ),
+ array(
+ '<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>',
+ '<a href="http://localhost/mrgreen.gif" class="postlink">http://localhost/mrgreen.gif</a>',
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewimg', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ '<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile">'
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ ':)',
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('smilies', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ );
+ }
+
+ public function test_default_lang()
+ {
+ global $phpbb_container;
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/default_lang.xml');
+
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+
+ $this->assertSame('FOO_BAR', $renderer->render('<r><FOO/></r>'));
+ }
+
+ /**
+ * @dataProvider get_option_names
+ */
+ public function test_get_option($option_name)
+ {
+ global $phpbb_container;
+ $this->get_test_case_helpers()->set_s9e_services();
+
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+
+ $renderer->{'set_' . $option_name}(false);
+ $this->assertFalse($renderer->{'get_' . $option_name}());
+ $renderer->{'set_' . $option_name}(true);
+ $this->assertTrue($renderer->{'get_' . $option_name}());
+ }
+
+ public function get_option_names()
+ {
+ return array(
+ array('viewcensors'),
+ array('viewflash'),
+ array('viewimg'),
+ array('viewsmilies')
+ );
+ }
+
+ public function test_styles()
+ {
+ global $phpbb_container;
+
+ $tests = array(
+ 1 => '<strong>bold</strong>',
+ 2 => '<b>bold</b>'
+ );
+
+ global $phpbb_root_path, $phpEx;
+
+ foreach ($tests as $style_id => $expected)
+ {
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->style = array('style_id' => $style_id);
+
+ $phpbb_container = new phpbb_mock_container_builder;
+ $phpbb_container->set('user', $user);
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/styles.xml', __DIR__ . '/fixtures/styles/');
+
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+ $this->assertSame(
+ $expected,
+ $renderer->render('<r><B><s>[b]</s>bold<e>[/b]</e></B></r>')
+ );
+ }
+ }
+
+ public function test_style_inheritance1()
+ {
+ global $phpbb_container, $phpbb_root_path, $phpEx;
+
+ // Style 3 inherits from 2 which inherits from 1. Only style 1 has a bbcode.html
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->style = array('style_id' => 3);
+
+ $phpbb_container = new phpbb_mock_container_builder;
+ $phpbb_container->set('user', $user);
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/');
+
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+ $this->assertSame(
+ '<strong>bold</strong>',
+ $renderer->render('<r><B><s>[b]</s>bold<e>[/b]</e></B></r>')
+ );
+ }
+
+ public function test_style_inheritance2()
+ {
+ global $phpbb_container, $phpbb_root_path, $phpEx;
+
+ // Style 5 inherits from 4, but both have a bbcode.html
+ $tests = array(
+ 4 => '<b>bold</b>',
+ 5 => '<b class="barplus">bold</b>'
+ );
+
+ foreach ($tests as $style_id => $expected)
+ {
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->style = array('style_id' => $style_id);
+
+ $phpbb_container = new phpbb_mock_container_builder;
+ $phpbb_container->set('user', $user);
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/');
+
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+ $this->assertSame(
+ $expected,
+ $renderer->render('<r><B><s>[b]</s>bold<e>[/b]</e></B></r>')
+ );
+ }
+ }
+
+ /**
+ * @testdox The constructor triggers a core.text_formatter_s9e_renderer_setup event
+ */
+ public function test_setup_event()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface');
+ $dispatcher
+ ->expects($this->once())
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_renderer_setup',
+ $this->callback(array($this, 'setup_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+
+ new \phpbb\textformatter\s9e\renderer(
+ $container->get('cache.driver'),
+ $container->getParameter('cache.dir'),
+ '_foo_renderer',
+ $container->get('text_formatter.s9e.factory'),
+ $dispatcher
+ );
+ }
+
+ public function setup_event_callback($vars)
+ {
+ return isset($vars['renderer'])
+ && $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer;
+ }
+
+ /**
+ * @testdox render() triggers a core.text_formatter_s9e_render_before and core.text_formatter_s9e_render_after events
+ */
+ public function test_render_event()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface');
+ $dispatcher
+ ->expects($this->any())
+ ->method('trigger_event')
+ ->will($this->returnArgument(1));
+ $dispatcher
+ ->expects($this->at(1))
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_render_before',
+ $this->callback(array($this, 'render_before_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+ $dispatcher
+ ->expects($this->at(2))
+ ->method('trigger_event')
+ ->with(
+ 'core.text_formatter_s9e_render_after',
+ $this->callback(array($this, 'render_after_event_callback'))
+ )
+ ->will($this->returnArgument(1));
+
+ $renderer = new \phpbb\textformatter\s9e\renderer(
+ $container->get('cache.driver'),
+ $container->getParameter('cache.dir'),
+ '_foo_renderer',
+ $container->get('text_formatter.s9e.factory'),
+ $dispatcher
+ );
+ $renderer->render('<t>...</t>');
+ }
+
+ public function render_before_event_callback($vars)
+ {
+ return isset($vars['renderer'])
+ && $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer
+ && isset($vars['xml'])
+ && $vars['xml'] === '<t>...</t>';
+ }
+
+ public function render_after_event_callback($vars)
+ {
+ return isset($vars['html'])
+ && $vars['html'] === '...'
+ && isset($vars['renderer'])
+ && $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer;
+ }
+
+ public function test_get_renderer()
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $renderer = $container->get('text_formatter.renderer');
+ $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer->get_renderer());
+ }
+}
diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php
new file mode 100644
index 0000000000..719d3cda88
--- /dev/null
+++ b/tests/text_formatter/s9e/utils_test.php
@@ -0,0 +1,276 @@
+<?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.
+*
+*/
+
+class phpbb_textformatter_s9e_utils_test extends phpbb_test_case
+{
+ /**
+ * @dataProvider get_unparse_tests
+ */
+ public function test_unparse($original, $expected)
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $utils = $container->get('text_formatter.utils');
+
+ $this->assertSame($expected, $utils->unparse($original));
+ }
+
+ public function get_unparse_tests()
+ {
+ return array(
+ array(
+ '<t>Plain text</t>',
+ 'Plain text'
+ ),
+ array(
+ "<t>Multi<br/>\nline</t>",
+ "Multi\nline"
+ ),
+ array(
+ '<r><B><s>[b]</s>bold<e>[/b]</e></B></r>',
+ '[b]bold[/b]'
+ )
+ );
+ }
+
+ /**
+ * @dataProvider get_clean_formatting_tests
+ */
+ public function test_clean_formatting($original, $expected)
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $utils = $container->get('text_formatter.utils');
+
+ $this->assertSame($expected, $utils->clean_formatting($original));
+ }
+
+ public function get_clean_formatting_tests()
+ {
+ return array(
+ array(
+ '<t>Plain text</t>',
+ 'Plain text'
+ ),
+ array(
+ "<t>Multi<br/>\nline</t>",
+ "Multi\nline"
+ ),
+ array(
+ '<r><B><s>[b]</s>bold<e>[/b]</e></B></r>',
+ ' bold '
+ )
+ );
+ }
+
+ /**
+ * @dataProvider get_outermost_quote_authors_tests
+ */
+ public function test_get_outermost_quote_authors($original, $expected)
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $utils = $container->get('text_formatter.utils');
+ $parser = $container->get('text_formatter.parser');
+
+ $this->assertSame($expected, $utils->get_outermost_quote_authors($parser->parse($original)));
+ }
+
+ public function get_outermost_quote_authors_tests()
+ {
+ return array(
+ array(
+ 'No quotes here',
+ array()
+ ),
+ array(
+ '[quote="foo"]..[/quote] [quote]..[/quote]',
+ array('foo')
+ ),
+ array(
+ '[quote=foo]..[/quote] [quote]..[/quote]',
+ array('foo')
+ ),
+ array(
+ '[quote=foo]..[/quote] [quote=bar]..[/quote]',
+ array('foo', 'bar')
+ ),
+ array(
+ '[quote=foo].[quote=baz]..[/quote].[/quote] [quote=bar]..[/quote]',
+ array('foo', 'bar')
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider get_generate_quote_tests
+ */
+ public function test_generate_quote($text, $params, $expected)
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $utils = $container->get('text_formatter.utils');
+
+ $this->assertSame($expected, $utils->generate_quote($text, $params));
+ }
+
+ public function get_generate_quote_tests()
+ {
+ return array(
+ array(
+ '...',
+ array(),
+ '[quote]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => 'Brian Kibler'),
+ '[quote="Brian Kibler"]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => 'Brian "Brian Kibler" Kibler of Brian Kibler Gaming'),
+ '[quote=\'Brian "Brian Kibler" Kibler of Brian Kibler Gaming\']...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => "Brian Kibler Gaming's Brian Kibler"),
+ '[quote="Brian Kibler Gaming\'s Brian Kibler"]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => "\\\"'"),
+ '[quote="\\\\\\"\'"]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => 'Lots of doubles """ one single \' one backslash \\'),
+ '[quote=\'Lots of doubles """ one single \\\' one backslash \\\\\']...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => "Lots of singles ''' one double \" one backslash \\"),
+ '[quote="Lots of singles \'\'\' one double \\" one backslash \\\\"]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => 'Defaults to doublequotes """\'\'\''),
+ '[quote="Defaults to doublequotes \\"\\"\\"\'\'\'"]...[/quote]',
+ ),
+ array(
+ '...',
+ array(
+ 'author' => 'user',
+ 'post_id' => 123,
+ 'url' => 'http://example.org'
+ ),
+ '[quote=user post_id=123 url=http://example.org]...[/quote]',
+ ),
+ array(
+ '...',
+ array(
+ 'author' => 'user',
+ 'post_id' => 123,
+ 'user_id' => ANONYMOUS
+ ),
+ '[quote=user post_id=123]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => ' '),
+ '[quote=" "]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => 'foo bar'),
+ '[quote="foo bar"]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => '\\'),
+ '[quote="\\\\"]...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => '[quote="foo"]'),
+ '[quote=\'[quote="foo"]\']...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => '""'),
+ '[quote=\'""\']...[/quote]',
+ ),
+ array(
+ '...',
+ array('author' => "''"),
+ '[quote="\'\'"]...[/quote]',
+ ),
+ array(
+ 'This is a long quote that is definitely going to exceed 80 characters',
+ array(),
+ "[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]",
+ ),
+ array(
+ ' This is a short quote on its own line ',
+ array(),
+ '[quote]This is a short quote on its own line[/quote]',
+ ),
+ array(
+ "This is a short quote\non two lines",
+ array(),
+ "[quote]\nThis is a short quote\non two lines\n[/quote]",
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider get_remove_bbcode_tests
+ */
+ public function test_remove_bbcode($original, $name, $depth, $expected)
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services();
+ $parser = $container->get('text_formatter.parser');
+ $utils = $container->get('text_formatter.utils');
+
+ $parsed = $parser->parse($original);
+ $actual = $utils->unparse($utils->remove_bbcode($parsed, $name, $depth));
+
+ $this->assertSame($expected, $actual);
+ }
+
+ public function get_remove_bbcode_tests()
+ {
+ return array(
+ array(
+ 'Plain text',
+ 'b',
+ 1,
+ 'Plain text'
+ ),
+ array(
+ '[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]',
+ 'quote',
+ 0,
+ '[b]bold[/b]',
+ ),
+ array(
+ '[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]',
+ 'quote',
+ 1,
+ '[quote="u0"]q0[/quote][b]bold[/b]',
+ ),
+ array(
+ '[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]',
+ 'quote',
+ 2,
+ '[quote="u0"][quote="u1"]q1[/quote]q0[/quote][b]bold[/b]',
+ ),
+ );
+ }
+}
diff --git a/tests/text_processing/censor_text_test.php b/tests/text_processing/censor_text_test.php
index 983a5ba2d3..eda2bbb1b3 100644
--- a/tests/text_processing/censor_text_test.php
+++ b/tests/text_processing/censor_text_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_text_processing_censor_text_test extends phpbb_test_case
{
public function censor_text_data()
diff --git a/tests/text_processing/decode_message_test.php b/tests/text_processing/decode_message_test.php
new file mode 100644
index 0000000000..e2402e721a
--- /dev/null
+++ b/tests/text_processing/decode_message_test.php
@@ -0,0 +1,113 @@
+<?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.
+*
+*/
+
+class phpbb_text_processing_decode_message_test extends phpbb_test_case
+{
+ public function setUp()
+ {
+ parent::setUp();
+
+ global $phpbb_dispatcher;
+
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ }
+
+ /**
+ * @dataProvider get_legacy_tests
+ */
+ public function test_legacy($original, $expected, $bbcode_uid = '')
+ {
+ $actual = $original;
+ decode_message($actual, $bbcode_uid);
+
+ $this->assertSame($expected, $actual);
+ }
+
+ public function get_legacy_tests()
+ {
+ return array(
+ array(
+ "&amp;&lt;&gt;&quot;'",
+ "&amp;&lt;&gt;&quot;'"
+ ),
+ array(
+ '<!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) -->',
+ ':)'
+ ),
+ array(
+ '<!-- w --><a class="postlink" href="http://www.phpbb.com">www.phpbb.com</a><!-- w -->',
+ 'www.phpbb.com'
+ ),
+ array(
+ '<!-- m --><a class="postlink" href="http://www.phpbb.com">http://www.phpbb.com</a><!-- m -->',
+ 'http://www.phpbb.com'
+ ),
+ array(
+ '<!-- m --><a class="postlink" href="http://www.phpbb.com">this is just text</a><!-- m -->',
+ 'http://www.phpbb.com'
+ ),
+ array(
+ '<!-- m --><a class="postlink" href="http://www.phpbb.com/some/more/link/that/is/shortened">http://www.phpbb.com/some/ ... /shortened</a><!-- m -->',
+ 'http://www.phpbb.com/some/more/link/that/is/shortened'
+ ),
+ /**
+ * Fails as per PHPBB3-8420
+ * @link http://tracker.phpbb.com/browse/PHPBB3-8420
+ *
+ array(
+ '[url=http://example.com:2cpxwbdy]<!-- s:arrow: --><img src="{SMILIES_PATH}/icon_arrow.gif" alt=":arrow:" title="Arrow" /><!-- s:arrow: --> here[/url:2cpxwbdy]',
+ '[url=http://example.com] :arrow: here[/url]',
+ '2cpxwbdy'
+ ),
+ */
+ );
+ }
+
+ /**
+ * @dataProvider get_text_formatter_tests
+ */
+ public function test_text_formatter($original, $expected)
+ {
+ $this->get_test_case_helpers()->set_s9e_services();
+
+ $actual = $original;
+ decode_message($actual);
+
+ $this->assertSame($expected, $actual);
+ }
+
+ public function get_text_formatter_tests()
+ {
+ return array(
+ array(
+ "<t>&amp;&lt;&gt;\"'",
+ "&amp;&lt;&gt;&quot;'"
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ ':)'
+ ),
+ array(
+ "<t>a<br/>\nb</t>",
+ "a\nb"
+ ),
+ /**
+ * @link http://tracker.phpbb.com/browse/PHPBB3-8420
+ */
+ array(
+ '<r><URL url="http://example.com"><s>[url=http://example.com]</s> <E>:arrow:</E> here<e>[/url]</e></URL></r>',
+ '[url=http://example.com] :arrow: here[/url]'
+ ),
+ );
+ }
+}
diff --git a/tests/text_processing/fixtures/empty.xml b/tests/text_processing/fixtures/empty.xml
new file mode 100644
index 0000000000..d8206ad124
--- /dev/null
+++ b/tests/text_processing/fixtures/empty.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+</dataset>
diff --git a/tests/text_processing/fixtures/smilies.xml b/tests/text_processing/fixtures/smilies.xml
new file mode 100644
index 0000000000..25b2e60836
--- /dev/null
+++ b/tests/text_processing/fixtures/smilies.xml
@@ -0,0 +1,443 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>1</value>
+ <value>:D</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>1</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>:-D</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>2</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>:grin:</value>
+ <value>Very Happy</value>
+ <value>icon_e_biggrin.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>3</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>:)</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>4</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>:-)</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>5</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>:smile:</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>6</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>7</value>
+ <value>;)</value>
+ <value>Wink</value>
+ <value>icon_e_wink.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>7</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>8</value>
+ <value>;-)</value>
+ <value>Wink</value>
+ <value>icon_e_wink.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>8</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>9</value>
+ <value>:wink:</value>
+ <value>Wink</value>
+ <value>icon_e_wink.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>9</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>10</value>
+ <value>:(</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>10</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>11</value>
+ <value>:-(</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>11</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>12</value>
+ <value>:sad:</value>
+ <value>Sad</value>
+ <value>icon_e_sad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>12</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>13</value>
+ <value>:o</value>
+ <value>Surprised</value>
+ <value>icon_e_surprised.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>13</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>14</value>
+ <value>:-o</value>
+ <value>Surprised</value>
+ <value>icon_e_surprised.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>14</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>15</value>
+ <value>:eek:</value>
+ <value>Surprised</value>
+ <value>icon_e_surprised.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>15</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>16</value>
+ <value>:shock:</value>
+ <value>Shocked</value>
+ <value>icon_eek.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>16</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>17</value>
+ <value>:?</value>
+ <value>Confused</value>
+ <value>icon_e_confused.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>17</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>18</value>
+ <value>:-?</value>
+ <value>Confused</value>
+ <value>icon_e_confused.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>18</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>19</value>
+ <value>:???:</value>
+ <value>Confused</value>
+ <value>icon_e_confused.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>19</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>20</value>
+ <value>8-)</value>
+ <value>Cool</value>
+ <value>icon_cool.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>20</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>21</value>
+ <value>:cool:</value>
+ <value>Cool</value>
+ <value>icon_cool.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>21</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>22</value>
+ <value>:lol:</value>
+ <value>Laughing</value>
+ <value>icon_lol.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>22</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>23</value>
+ <value>:x</value>
+ <value>Mad</value>
+ <value>icon_mad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>23</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>24</value>
+ <value>:-x</value>
+ <value>Mad</value>
+ <value>icon_mad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>24</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>25</value>
+ <value>:mad:</value>
+ <value>Mad</value>
+ <value>icon_mad.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>25</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>26</value>
+ <value>:P</value>
+ <value>Razz</value>
+ <value>icon_razz.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>26</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>27</value>
+ <value>:-P</value>
+ <value>Razz</value>
+ <value>icon_razz.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>27</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>28</value>
+ <value>:razz:</value>
+ <value>Razz</value>
+ <value>icon_razz.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>28</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>29</value>
+ <value>:oops:</value>
+ <value>Embarrassed</value>
+ <value>icon_redface.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>29</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>30</value>
+ <value>:cry:</value>
+ <value>Crying or Very Sad</value>
+ <value>icon_cry.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>30</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>31</value>
+ <value>:evil:</value>
+ <value>Evil or Very Mad</value>
+ <value>icon_evil.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>31</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>32</value>
+ <value>:twisted:</value>
+ <value>Twisted Evil</value>
+ <value>icon_twisted.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>32</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>33</value>
+ <value>:roll:</value>
+ <value>Rolling Eyes</value>
+ <value>icon_rolleyes.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>33</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>34</value>
+ <value>:!:</value>
+ <value>Exclamation</value>
+ <value>icon_exclaim.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>34</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>35</value>
+ <value>:?:</value>
+ <value>Question</value>
+ <value>icon_question.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>35</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>36</value>
+ <value>:idea:</value>
+ <value>Idea</value>
+ <value>icon_idea.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>36</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>37</value>
+ <value>:arrow:</value>
+ <value>Arrow</value>
+ <value>icon_arrow.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>37</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>38</value>
+ <value>:|</value>
+ <value>Neutral</value>
+ <value>icon_neutral.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>38</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>39</value>
+ <value>:-|</value>
+ <value>Neutral</value>
+ <value>icon_neutral.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>39</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>40</value>
+ <value>:mrgreen:</value>
+ <value>Mr. Green</value>
+ <value>icon_mrgreen.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>40</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>41</value>
+ <value>:geek:</value>
+ <value>Geek</value>
+ <value>icon_e_geek.gif</value>
+ <value>17</value>
+ <value>17</value>
+ <value>41</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>42</value>
+ <value>:ugeek:</value>
+ <value>Uber Geek</value>
+ <value>icon_e_ugeek.gif</value>
+ <value>17</value>
+ <value>18</value>
+ <value>42</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>43</value>
+ <value>8)</value>
+ <value>8)</value>
+ <value>custom.gif</value>
+ <value>17</value>
+ <value>18</value>
+ <value>42</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php
index 057416da33..dfbd0977a0 100644
--- a/tests/text_processing/generate_text_for_display_test.php
+++ b/tests/text_processing/generate_text_for_display_test.php
@@ -11,11 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-require_once dirname(__FILE__) . '/../mock/user.php';
-require_once dirname(__FILE__) . '/../mock/cache.php';
-
class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_case
{
public function setUp()
@@ -24,21 +19,195 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca
parent::setUp();
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher;
+ $config = new \phpbb\config\config(array());
+ set_config(null, null, null, $config);
+ }
+
+ /**
+ * @dataProvider get_legacy_tests
+ */
+ public function test_legacy($original, $expected, $uid = '', $bitfield = '', $flags = 0, $censor_text = true)
+ {
+ global $cache, $user;
+
+ global $phpbb_root_path, $phpEx;
+
$cache = new phpbb_mock_cache;
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewcensors', true);
+ $user->optionset('viewflash', true);
+ $user->optionset('viewimg', true);
+ $user->optionset('viewsmilies', true);
+
+ $actual = generate_text_for_display($original, $uid, $bitfield, $flags, $censor_text);
+
+ $this->assertSame($expected, $actual);
+ }
+
+ public function get_legacy_tests()
+ {
+ return array(
+ array(
+ '',
+ ''
+ ),
+ array(
+ '0',
+ '0'
+ ),
+ );
+ }
+
+ public function test_censor_is_restored()
+ {
+ global $phpbb_container;
+
+ $phpbb_container = new phpbb_mock_container_builder;
+
+ global $phpbb_root_path, $phpEx;
- $user = new phpbb_mock_user;
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
$user->optionset('viewcensors', false);
- $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $config = new \phpbb\config\config(array('allow_nocensors' => true));
+
+ $auth = $this->getMock('phpbb\\auth\\auth');
+ $auth->expects($this->any())
+ ->method('acl_get')
+ ->with('u_chgcensors')
+ ->will($this->returnValue(true));
+
+ $phpbb_container->set('user', $user);
+ $phpbb_container->set('config', $config);
+ $phpbb_container->set('auth', $auth);
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container);
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+
+ $original = '<r><CENSOR with="banana">apple</CENSOR></r>';
+
+ $renderer->set_viewcensors(false);
+ $this->assertSame('apple', $renderer->render($original));
+ $renderer->set_viewcensors(true);
+ $this->assertSame('banana', $renderer->render($original));
+ $this->assertSame('apple', generate_text_for_display($original, '', '', 0, false));
+ $this->assertSame('banana', $renderer->render($original), 'The original setting was not restored');
+
+ $renderer->set_viewcensors(false);
+ $this->assertSame('apple', $renderer->render($original));
+ $this->assertSame('banana', generate_text_for_display($original, '', '', 0, truee));
+ $this->assertSame('apple', $renderer->render($original), 'The original setting was not restored');
}
- public function test_empty_string()
+ /**
+ * @dataProvider get_text_formatter_tests
+ */
+ public function test_text_formatter($original, $expected, $censor_text = true, $setup = null)
{
- $this->assertSame('', generate_text_for_display('', '', '', 0));
+ global $phpbb_container;
+
+ $phpbb_container = new phpbb_mock_container_builder;
+
+ if (isset($setup))
+ {
+ $setup($phpbb_container, $this);
+ }
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container);
+
+ $this->assertSame($expected, generate_text_for_display($original, '', '', 0, $censor_text));
}
- public function test_zero_string()
+ public function get_text_formatter_tests()
{
- $this->assertSame('0', generate_text_for_display('0', '', '', 0));
+ return array(
+ array(
+ '<t>Plain text</t>',
+ 'Plain text'
+ ),
+ array(
+ '<r>Hello <URL url="http://example.org"><s>[url=http://example.org]</s>world<e>[/url]</e></URL></r>',
+ 'Hello <a href="http://example.org" class="postlink">world</a>'
+ ),
+ array(
+ '<t>&amp;&lt;&gt;"\'</t>',
+ '&amp;&lt;&gt;"\''
+ ),
+ array(
+ '<r><CENSOR with="banana">apple</CENSOR></r>',
+ 'banana',
+ true
+ ),
+ array(
+ '<r><CENSOR with="banana">apple</CENSOR></r>',
+ 'apple',
+ false
+ ),
+ array(
+ '<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>',
+ '<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="123" height="456"><param name="movie" value="http://localhost/foo.swf"><param name="play" value="false"><param name="loop" value="false"><param name="quality" value="high"><param name="allowScriptAccess" value="never"><param name="allowNetworking" value="internal"><embed src="http://localhost/foo.swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="123" height="456" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></object>'
+ ),
+ array(
+ '<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>',
+ 'http://localhost/foo.swf',
+ true,
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewflash', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ array(
+ '<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>',
+ '<img src="http://localhost/mrgreen.gif" class="postimage" alt="Image">'
+ ),
+ array(
+ '<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>',
+ '<a href="http://localhost/mrgreen.gif" class="postlink">http://localhost/mrgreen.gif</a>',
+ true,
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('viewimg', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ '<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile">'
+ ),
+ array(
+ '<r><E>:)</E></r>',
+ ':)',
+ true,
+ function ($phpbb_container)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+ $user = new \phpbb\user($lang, '\phpbb\datetime');
+ $user->optionset('smilies', false);
+
+ $phpbb_container->set('user', $user);
+ }
+ ),
+ );
}
}
diff --git a/tests/text_processing/generate_text_for_edit_test.php b/tests/text_processing/generate_text_for_edit_test.php
new file mode 100644
index 0000000000..8258a196f5
--- /dev/null
+++ b/tests/text_processing/generate_text_for_edit_test.php
@@ -0,0 +1,89 @@
+<?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.
+*
+*/
+
+class phpbb_text_processing_generate_text_for_edit_test extends phpbb_test_case
+{
+ /**
+ * @dataProvider get_legacy_tests
+ */
+ public function test_legacy($original, $expected, $uid = '', $flags = 0)
+ {
+ global $cache, $user, $phpbb_dispatcher;
+
+ $cache = new phpbb_mock_cache;
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher;
+
+ $user = new phpbb_mock_user;
+ $user->optionset('viewcensors', false);
+
+ $return = generate_text_for_edit($original, $uid, $flags);
+
+ $this->assertSame($expected, $return['text']);
+ }
+
+ public function get_legacy_tests()
+ {
+ return array(
+ array(
+ '',
+ ''
+ ),
+ array(
+ '0',
+ '0'
+ ),
+ array(
+ 'Hello [url=http&#58;//example&#46;org:1f4coh9x]world[/url:1f4coh9x] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) -->',
+ 'Hello [url=http&#58;//example&#46;org]world[/url] :)',
+ '1f4coh9x',
+ 0
+ ),
+ array(
+ "&amp;&lt;&gt;&quot;'",
+ "&amp;&lt;&gt;&quot;'"
+ )
+ );
+ }
+
+ /**
+ * @dataProvider get_text_formatter_tests
+ */
+ public function test_text_formatter($original, $expected)
+ {
+ global $phpbb_dispatcher;
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher;
+ $this->get_test_case_helpers()->set_s9e_services();
+
+ $return = generate_text_for_edit($original, '', 0);
+
+ $this->assertSame($expected, $return['text']);
+ }
+
+ public function get_text_formatter_tests()
+ {
+ return array(
+ array(
+ '<t>Plain text</t>',
+ 'Plain text'
+ ),
+ array(
+ '<r>Hello <URL url="http://example.org"><s>[url=http://example.org]</s>world<e>[/url]</e></URL> <E>:)</E></r>',
+ 'Hello [url=http://example.org]world[/url] :)'
+ ),
+ array(
+ '<t>&amp;&lt;&gt;"\'</t>',
+ "&amp;&lt;&gt;&quot;'"
+ )
+ );
+ }
+}
diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php
new file mode 100644
index 0000000000..f0588fec4f
--- /dev/null
+++ b/tests/text_processing/generate_text_for_storage_test.php
@@ -0,0 +1,178 @@
+<?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.
+*
+*/
+
+class phpbb_text_processing_generate_text_for_storage_test extends phpbb_test_case
+{
+ public function setUp()
+ {
+ global $config, $phpbb_container, $phpbb_dispatcher;
+
+ parent::setUp();
+
+ $config = new \phpbb\config\config(array());
+ set_config(null, null, null, $config);
+
+ $phpbb_container = new phpbb_mock_container_builder;
+ $phpbb_container->set('config', $config);
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container);
+
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher;
+ }
+
+ /**
+ * @dataProvider get_text_formatter_tests
+ */
+ public function test_text_formatter($original, $expected, $allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode, $setup = null)
+ {
+ $actual = $original;
+ $uid = '';
+ $bitfield = '';
+ $flags = 0;
+
+ if (isset($setup))
+ {
+ $setup();
+ }
+
+ generate_text_for_storage($actual, $uid, $bitfield, $flags, $allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode);
+
+ $this->assertSame($expected, $actual);
+ }
+
+ public function get_text_formatter_tests()
+ {
+ return array(
+ array(
+ 'Hello world',
+ '<t>Hello world</t>',
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ ),
+ array(
+ 'Hello [url=http://example.org]world[/url] :)',
+ '<r>Hello <URL url="http://example.org"><s>[url=http://example.org]</s>world<e>[/url]</e></URL> <E>:)</E></r>',
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ ),
+ array(
+ '&<>"\'',
+ '<t>&amp;&lt;&gt;"\'</t>',
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<t>[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</t>',
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</r>',
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r>[b]..[/b] <URL url="http://example.org">http://example.org</URL> :) [img]<URL url="http://example.org/img.png">http://example.org/img.png</URL>[/img] [flash=123,123]<URL url="http://example.org/flash.swf">http://example.org/flash.swf</URL>[/flash] [quote]...[/quote] [url]<URL url="http://example.org">http://example.org</URL>[/url]</r>',
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r>[b]..[/b] http://example.org <E>:)</E> [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</r>',
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) <IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG> [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</r>',
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] <FLASH height="123" url="http://example.org/flash.swf" width="123"><s>[flash=123,123]</s>http://example.org/flash.swf<e>[/flash]</e></FLASH> [quote]...[/quote] [url]http://example.org[/url]</r>',
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] <QUOTE><s>[quote]</s>...<e>[/quote]</e></QUOTE> [url]http://example.org[/url]</r>',
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ ),
+ array(
+ '[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]',
+ '<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] <URL url="http://example.org"><s>[url]</s>http://example.org<e>[/url]</e></URL></r>',
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ ),
+ );
+ }
+}
diff --git a/tests/text_processing/make_clickable_test.php b/tests/text_processing/make_clickable_test.php
index 95e304dd97..3c8539c612 100644
--- a/tests/text_processing/make_clickable_test.php
+++ b/tests/text_processing/make_clickable_test.php
@@ -11,9 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
-
class phpbb_text_processing_make_clickable_test extends phpbb_test_case
{
public function make_clickable_data()
diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php
new file mode 100644
index 0000000000..a3dbf644f6
--- /dev/null
+++ b/tests/text_processing/message_parser_test.php
@@ -0,0 +1,540 @@
+<?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.
+*
+*/
+
+require_once __DIR__ . '/../../phpBB/includes/bbcode.php';
+require_once __DIR__ . '/../../phpBB/includes/message_parser.php';
+
+class phpbb_text_processing_message_parser_test extends phpbb_test_case
+{
+ public static function setUpBeforeClass()
+ {
+ parent::setUpBeforeClass();
+
+ // Set up an intercepting proxy for getimagesize() calls
+ stream_wrapper_unregister('http');
+ stream_wrapper_register('http', __CLASS__ . '_proxy');
+ }
+
+ public static function tearDownAfterClass()
+ {
+ parent::tearDownAfterClass();
+ stream_wrapper_restore('http');
+ }
+
+ protected function prepare_s9e_services($setup = null)
+ {
+ global $config, $phpbb_container, $user;
+
+ $config = new \phpbb\config\config(array('max_poll_options' => 999));
+
+ $map = array(
+ array('MAX_FLASH_HEIGHT_EXCEEDED', 123, 'Your flash files may only be up to 123 pixels high.'),
+ array('MAX_FLASH_WIDTH_EXCEEDED', 456, 'Your flash files may only be up to 456 pixels wide.'),
+ array('MAX_FONT_SIZE_EXCEEDED', 120, 'You may only use fonts up to size 120.'),
+ array('MAX_FONT_SIZE_EXCEEDED', 200, 'You may only use fonts up to size 200.'),
+ array('MAX_IMG_HEIGHT_EXCEEDED', 12, 'Your images may only be up to 12 pixels high.'),
+ array('MAX_IMG_WIDTH_EXCEEDED', 34, 'Your images may only be up to 34 pixels wide.'),
+ array('TOO_MANY_SMILIES', 3, 'Your message contains too many smilies. The maximum number of smilies allowed is 3.'),
+ array('TOO_MANY_URLS', 2, 'Your message contains too many URLs. The maximum number of URLs allowed is 2.'),
+ array('UNAUTHORISED_BBCODE', '[flash]', 'You cannot use certain BBCodes: [flash].'),
+ array('UNAUTHORISED_BBCODE', '[img]', 'You cannot use certain BBCodes: [img].'),
+ array('UNAUTHORISED_BBCODE', '[quote]', 'You cannot use certain BBCodes: [quote].'),
+ array('UNAUTHORISED_BBCODE', '[url]', 'You cannot use certain BBCodes: [url].'),
+ array('UNABLE_GET_IMAGE_SIZE', 'It was not possible to determine the dimensions of the image.'),
+ );
+
+ $user = $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock();
+ $user->expects($this->any())
+ ->method('lang')
+ ->will($this->returnValueMap($map));
+
+ $user->data = array(
+ 'is_bot' => false,
+ 'is_registered' => true,
+ 'user_id' => 2,
+ );
+ $user->style = array('style_id' => 1);
+
+ $user->lang = array(
+ 'NO_POLL_TITLE' => 'You have to enter a poll title.',
+ 'POLL_TITLE_TOO_LONG' => 'The poll title must contain fewer than 100 characters.',
+ 'POLL_TITLE_COMP_TOO_LONG' => 'The parsed size of your poll title is too large, consider removing BBCodes or smilies.',
+ 'TOO_FEW_POLL_OPTIONS' => 'You must enter at least two poll options.',
+ 'TOO_MANY_POLL_OPTIONS' => 'You have tried to enter too many poll options.',
+ 'TOO_MANY_USER_OPTIONS' => 'You cannot specify more options per user than existing poll options.',
+ );
+
+ $phpbb_container = new phpbb_mock_container_builder;
+ $phpbb_container->set('user', $user);
+ $phpbb_container->set('config', $config);
+
+ if (isset($setup))
+ {
+ $setup($phpbb_container, $this);
+ }
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container);
+ }
+
+ /**
+ * @dataProvider get_test_polls
+ */
+ public function test_parse_poll($poll, $expected, $warn_msg = array())
+ {
+ $this->prepare_s9e_services();
+
+ $message_parser = new parse_message('Me[i]s[/i]sage');
+
+ // Add some default values
+ $poll += array(
+ 'poll_length' => 123,
+ 'poll_start' => 123,
+ 'poll_last_vote' => 123,
+ 'poll_vote_change' => true,
+ 'enable_bbcode' => true,
+ 'enable_urls' => true,
+ 'enable_smilies' => true,
+ 'img_status' => true
+ );
+
+ $message_parser->parse_poll($poll);
+ $this->assertSame($expected, array_intersect_key($poll, $expected));
+
+ $this->assertSame(
+ '<r>Me<I><s>[i]</s>s<e>[/i]</e></I>sage</r>',
+ $message_parser->parse(true, true, true, true, true, true, true, false)
+ );
+
+ $this->assertSame($warn_msg, $message_parser->warn_msg);
+ }
+
+ public function get_test_polls()
+ {
+ return array(
+ array(
+ array(
+ 'poll_title' => 'foo [b]bar[/b] baz',
+ 'poll_option_text' => "[i]foo[/i]\nbar\n[i]baz[/i]",
+ 'poll_max_options' => 3,
+ 'poll_options_size' => 3
+ ),
+ array(
+ 'poll_title' => '<r>foo <B><s>[b]</s>bar<e>[/b]</e></B> baz</r>',
+ 'poll_option_text' => "<r><I><s>[i]</s>foo<e>[/i]</e></I></r>\n<t>bar</t>\n<r><I><s>[i]</s>baz<e>[/i]</e></I></r>",
+ 'poll_options' => array(
+ '<r><I><s>[i]</s>foo<e>[/i]</e></I></r>',
+ '<t>bar</t>',
+ '<r><I><s>[i]</s>baz<e>[/i]</e></I></r>'
+ )
+ )
+ ),
+ array(
+ array(
+ 'poll_title' => 'xxx',
+ 'poll_option_text' => "[quote]quote[/quote]\n:)",
+ 'poll_max_options' => 2,
+ 'poll_options_size' => 2
+ ),
+ array(
+ 'poll_title' => '<t>xxx</t>',
+ 'poll_option_text' => "<t>[quote]quote[/quote]</t>\n<r><E>:)</E></r>",
+ 'poll_options' => array(
+ '<t>[quote]quote[/quote]</t>',
+ '<r><E>:)</E></r>'
+ )
+ ),
+ array('You cannot use certain BBCodes: [quote].')
+ ),
+ array(
+ array(
+ 'poll_title' => 'xxx',
+ 'poll_option_text' => "[flash=12,34]http://example.org/x.swf[/flash]\n:)",
+ 'poll_max_options' => 2,
+ 'poll_options_size' => 2
+ ),
+ array(
+ 'poll_title' => '<t>xxx</t>',
+ 'poll_option_text' => "<t>[flash=12,34]http://example.org/x.swf[/flash]</t>\n<r><E>:)</E></r>",
+ 'poll_options' => array(
+ '<t>[flash=12,34]http://example.org/x.swf[/flash]</t>',
+ '<r><E>:)</E></r>'
+ )
+ ),
+ array('You cannot use certain BBCodes: [flash].')
+ ),
+ array(
+ array(
+ 'poll_title' => 'xxx',
+ 'poll_option_text' => "[b]x\ny[/b]",
+ 'poll_max_options' => 2,
+ 'poll_options_size' => 2
+ ),
+ array(
+ 'poll_title' => '<t>xxx</t>',
+ 'poll_option_text' => "<r><B><s>[b]</s>x</B></r>\n<t>y[/b]</t>",
+ 'poll_options' => array(
+ '<r><B><s>[b]</s>x</B></r>',
+ '<t>y[/b]</t>',
+ )
+ )
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider get_test_cases
+ */
+ public function test_options($original, $expected, array $args, $setup = null, $warn_msg = array())
+ {
+ $this->prepare_s9e_services($setup);
+
+ $message_parser = new parse_message($original);
+ call_user_func_array(array($message_parser, 'parse'), $args);
+
+ $this->assertSame($expected, $message_parser->message);
+ $this->assertSame($warn_msg, $message_parser->warn_msg);
+ }
+
+ public function get_test_cases()
+ {
+ return array(
+ array(
+ '[b]bold[/b]',
+ '<r><B><s>[b]</s>bold<e>[/b]</e></B></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ '[b]bold[/b]',
+ '<t>[b]bold[/b]</t>',
+ array(false, true, true, true, true, true, true)
+ ),
+ array(
+ 'http://example.org',
+ '<r><URL url="http://example.org">http://example.org</URL></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ 'http://example.org',
+ '<t>http://example.org</t>',
+ array(true, false, true, true, true, true, true)
+ ),
+ array(
+ ':)',
+ '<r><E>:)</E></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ ':)',
+ '<t>:)</t>',
+ array(true, true, false, true, true, true, true)
+ ),
+ array(
+ '[url=http://example.org][img]http://example.org/img.png[/img][/url]',
+ '<r><URL url="http://example.org"><s>[url=http://example.org]</s><IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG><e>[/url]</e></URL></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ '[url=http://example.org][img]http://example.org/img.png[/img][/url]',
+ '<r><URL url="http://example.org"><s>[url=http://example.org]</s>[img]http://example.org/img.png[/img]<e>[/url]</e></URL></r>',
+ array(true, true, true, false, true, true, true),
+ null,
+ array('You cannot use certain BBCodes: [img].')
+ ),
+ array(
+ '[flash=12,34]http://example.org/foo.swf[/flash]',
+ '<r><FLASH height="34" url="http://example.org/foo.swf" width="12"><s>[flash=12,34]</s><URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL><e>[/flash]</e></FLASH></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ '[flash=12,34]http://example.org/foo.swf[/flash]',
+ '<r>[flash=12,34]<URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL>[/flash]</r>',
+ array(true, true, true, true, false, true, true),
+ null,
+ array('You cannot use certain BBCodes: [flash].')
+ ),
+ array(
+ '[quote="foo"]bar :)[/quote]',
+ '<r><QUOTE author="foo"><s>[quote="foo"]</s>bar <E>:)</E><e>[/quote]</e></QUOTE></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ '[quote="foo"]bar :)[/quote]',
+ '<r>[quote="foo"]bar <E>:)</E>[/quote]</r>',
+ array(true, true, true, true, true, false, true),
+ null,
+ array('You cannot use certain BBCodes: [quote].')
+ ),
+ array(
+ '[url=http://example.org][img]http://example.org/img.png[/img][/url]',
+ '<r><URL url="http://example.org"><s>[url=http://example.org]</s><IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG><e>[/url]</e></URL></r>',
+ array(true, true, true, true, true, true, true)
+ ),
+ array(
+ '[url=http://example.org][img]http://example.org/img.png[/img][/url]',
+ '<r>[url=http://example.org]<IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG>[/url]</r>',
+ array(true, true, true, true, true, true, false),
+ null,
+ array('You cannot use certain BBCodes: [url].')
+ ),
+ array(
+ '[size=200]200[/size]',
+ '<r><SIZE size="200"><s>[size=200]</s>200<e>[/size]</e></SIZE></r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_font_size', 200);
+ }
+ ),
+ array(
+ '[size=200]200[/size]',
+ '<r><SIZE size="200"><s>[size=200]</s>200<e>[/size]</e></SIZE></r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_font_size', 0);
+ }
+ ),
+ array(
+ '[size=2000]2000[/size]',
+ '<t>[size=2000]2000[/size]</t>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_font_size', 200);
+ },
+ array('You may only use fonts up to size 200.')
+ ),
+ array(
+ '[size=0]0[/size]',
+ '<t>[size=0]0[/size]</t>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_font_size', 200);
+ }
+ ),
+ array(
+ '[size=200]200[/size]',
+ '<r><SIZE size="200"><s>[size=200]</s>200<e>[/size]</e></SIZE></r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_sig_font_size', 200);
+ }
+ ),
+ array(
+ '[size=200]200[/size]',
+ '<t>[size=200]200[/size]</t>',
+ array(true, true, true, true, true, true, true, true, 'sig'),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_sig_font_size', 120);
+ },
+ array('You may only use fonts up to size 120.')
+ ),
+ array(
+ '[img]http://example.org/100x100.png[/img]',
+ '<r>[img]<URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL>[/img]</r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_height', 12);
+ },
+ array('Your images may only be up to 12 pixels high.')
+ ),
+ array(
+ '[img]http://example.org/100x100.png[/img]',
+ '<r>[img]<URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL>[/img]</r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_width', 34);
+ },
+ array('Your images may only be up to 34 pixels wide.')
+ ),
+ array(
+ '[img]http://example.org/100x100.png[/img]',
+ '<r><IMG src="http://example.org/100x100.png"><s>[img]</s><URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL><e>[/img]</e></IMG></r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_height', 0);
+ $phpbb_container->get('config')->set('max_post_img_width', 0);
+ }
+ ),
+ array(
+ '[img]http://example.org/100x100.png[/img]',
+ '<r><IMG src="http://example.org/100x100.png"><s>[img]</s><URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL><e>[/img]</e></IMG></r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_height', 100);
+ $phpbb_container->get('config')->set('max_post_img_width', 100);
+ }
+ ),
+ array(
+ '[img]http://example.org/100x100.png[/img]',
+ '<r><IMG src="http://example.org/100x100.png"><s>[img]</s><URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL><e>[/img]</e></IMG></r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_sig_img_height', 12);
+ $phpbb_container->get('config')->set('max_sig_img_width', 34);
+ }
+ ),
+ array(
+ '[img]http://example.org/404.png[/img]',
+ '<r>[img]<URL url="http://example.org/404.png">http://example.org/404.png</URL>[/img]</r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_height', 12);
+ },
+ array('It was not possible to determine the dimensions of the image.')
+ ),
+ array(
+ '[flash=999,999]http://example.org/foo.swf[/flash]',
+ '<r>[flash=999,999]<URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL>[/flash]</r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_height', 123);
+ },
+ array('Your flash files may only be up to 123 pixels high.')
+ ),
+ array(
+ '[flash=999,999]http://example.org/foo.swf[/flash]',
+ '<r>[flash=999,999]<URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL>[/flash]</r>',
+ array(true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_img_width', 456);
+ },
+ array('Your flash files may only be up to 456 pixels wide.')
+ ),
+ array(
+ ':) :) :)',
+ '<r><E>:)</E> <E>:)</E> <E>:)</E></r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_smilies', 3);
+ }
+ ),
+ array(
+ ':) :) :) :)',
+ '<r><E>:)</E> <E>:)</E> <E>:)</E> :)</r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_smilies', 3);
+ },
+ array('Your message contains too many smilies. The maximum number of smilies allowed is 3.')
+ ),
+ array(
+ ':) :) :) :)',
+ '<r><E>:)</E> <E>:)</E> <E>:)</E> <E>:)</E></r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_smilies', 0);
+ }
+ ),
+ array(
+ ':) :) :) :)',
+ '<r><E>:)</E> <E>:)</E> <E>:)</E> <E>:)</E></r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_sig_smilies', 3);
+ }
+ ),
+ array(
+ ':) :) :) :)',
+ '<r><E>:)</E> <E>:)</E> <E>:)</E> :)</r>',
+ array(true, true, true, true, true, true, true, true, 'sig'),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_sig_smilies', 3);
+ },
+ array('Your message contains too many smilies. The maximum number of smilies allowed is 3.')
+ ),
+ array(
+ 'http://example.org http://example.org http://example.org',
+ '<r><URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL> http://example.org</r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_urls', 2);
+ },
+ array('Your message contains too many URLs. The maximum number of URLs allowed is 2.')
+ ),
+ array(
+ 'http://example.org http://example.org http://example.org',
+ '<r><URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL></r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_post_urls', 0);
+ }
+ ),
+ array(
+ 'http://example.org http://example.org http://example.org',
+ '<r><URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL></r>',
+ array(true, true, true, true, true, true, true, true),
+ function ($phpbb_container)
+ {
+ $phpbb_container->get('config')->set('max_sig_urls', 2);
+ }
+ ),
+ );
+ }
+}
+
+class phpbb_text_processing_message_parser_test_proxy
+{
+ protected $response;
+
+ public function stream_open($url)
+ {
+ if (strpos($url, '100x100'))
+ {
+ // Return a 100 x 100 PNG image
+ $this->response = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQAAAABYmaj5AAAAE0lEQVR4AWOgKxgFo2AUjIJRAAAFeAABHs0ozQAAAABJRU5ErkJggg==');
+ }
+ else
+ {
+ $this->response = '404 not found';
+ }
+
+ return true;
+ }
+
+ public function stream_stat()
+ {
+ return false;
+ }
+
+ public function stream_read($len)
+ {
+ $chunk = substr($this->response, 0, $len);
+ $this->response = substr($this->response, $len);
+
+ return $chunk;
+ }
+
+ public function stream_eof()
+ {
+ return ($this->response === false);
+ }
+}
diff --git a/tests/text_processing/smilies_test.php b/tests/text_processing/smilies_test.php
new file mode 100644
index 0000000000..ebdbe7dadc
--- /dev/null
+++ b/tests/text_processing/smilies_test.php
@@ -0,0 +1,49 @@
+<?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.
+*
+*/
+
+class phpbb_text_processing_smilies_test extends phpbb_test_case
+{
+ /**
+ * @dataProvider get_text_formatter_tests
+ */
+ public function test_text_formatter($original, $expected)
+ {
+ $container = $this->get_test_case_helpers()->set_s9e_services(null, __DIR__ . '/fixtures/smilies.xml');
+ $parser = $container->get('text_formatter.parser');
+ $renderer = $container->get('text_formatter.renderer');
+
+ $this->assertSame($expected, $renderer->render($parser->parse($original)));
+ }
+
+ public function get_text_formatter_tests()
+ {
+ return array(
+ array(
+ ':) beginning',
+ '<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile"> beginning'
+ ),
+ array(
+ 'end :)',
+ 'end <img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile">'
+ ),
+ array(
+ ':)',
+ '<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile">'
+ ),
+ array(
+ 'xx (18) 8) xx',
+ 'xx (18) <img class="smilies" src="phpBB/images/smilies/custom.gif" alt="8)" title="8)"> xx'
+ ),
+ );
+ }
+}
diff --git a/tests/text_processing/strip_bbcode_test.php b/tests/text_processing/strip_bbcode_test.php
new file mode 100644
index 0000000000..9acedc2872
--- /dev/null
+++ b/tests/text_processing/strip_bbcode_test.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.
+*
+*/
+
+class phpbb_text_processing_strip_bbcode_test extends phpbb_test_case
+{
+ public function test_legacy()
+ {
+ $original = '[b:20m4ill1]bold[/b:20m4ill1]';
+ $expected = ' bold ';
+
+ $actual = $original;
+ strip_bbcode($actual);
+
+ $this->assertSame($expected, $actual, '20m4ill1');
+ }
+
+ public function test_s9e()
+ {
+ $phpbb_container = $this->get_test_case_helpers()->set_s9e_services();
+
+ $original = '<r><B><s>[b]</s>bold<e>[/b]</e></B></r>';
+ $expected = ' bold ';
+
+ $actual = $original;
+ strip_bbcode($actual);
+
+ $this->assertSame($expected, $actual);
+ }
+}
diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.html b/tests/text_processing/tickets_data/PHPBB3-10002.html
new file mode 100644
index 0000000000..82990b2253
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10002.html
@@ -0,0 +1,2 @@
+<blockquote class="uncited"><div><ul><li>one
+<blockquote class="uncited"><div><ul><li>two</li></ul></div></blockquote></li></ul></div></blockquote> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.txt b/tests/text_processing/tickets_data/PHPBB3-10002.txt
new file mode 100644
index 0000000000..fe2f29073f
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10002.txt
@@ -0,0 +1,2 @@
+[quote][list][*]one
+[quote][list][*]two[/list][/quote] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10122.html b/tests/text_processing/tickets_data/PHPBB3-10122.html
new file mode 100644
index 0000000000..f0fb6115b2
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10122.html
@@ -0,0 +1 @@
+<ul style="list-style-type: none"><li>This is my indented text</li></ul> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10122.txt b/tests/text_processing/tickets_data/PHPBB3-10122.txt
new file mode 100644
index 0000000000..a5e059df66
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10122.txt
@@ -0,0 +1 @@
+[list=none][*]This is my indented text[/list] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10268.html b/tests/text_processing/tickets_data/PHPBB3-10268.html
new file mode 100644
index 0000000000..c89e63f9a3
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10268.html
@@ -0,0 +1,4 @@
+<blockquote><div><cite><a href="http://phpbb.com" class="postlink">http://phpbb.com</a> wrote:</cite>...</div></blockquote>
+<blockquote><div><cite><a href="http://phpbb.com" class="postlink"> http://phpbb.com</a> wrote:</cite>...</div></blockquote>
+<span style="font-weight: bold"><a href="http://phpbb.com" class="postlink">http://phpbb.com</a></span><br>
+<span style="font-weight: bold"> <a href="http://phpbb.com" class="postlink">http://phpbb.com</a></span><br>
diff --git a/tests/text_processing/tickets_data/PHPBB3-10268.txt b/tests/text_processing/tickets_data/PHPBB3-10268.txt
new file mode 100644
index 0000000000..b4e49c9454
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10268.txt
@@ -0,0 +1,4 @@
+[quote="http://phpbb.com"]...[/quote]
+[quote=" http://phpbb.com"]...[/quote]
+[b]http://phpbb.com[/b]
+[b] http://phpbb.com[/b]
diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.html b/tests/text_processing/tickets_data/PHPBB3-10425.html
new file mode 100644
index 0000000000..522b2f8858
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10425.html
@@ -0,0 +1,3 @@
+<a href="http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" class="postlink">http://ar.wikipedia.org/wiki/الصÙحة_الرئيسية</a><br>
+<a href="http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" class="postlink">http://ar.wikipedia.org/wiki/الصÙحة_الرئيسية</a><br>
+<a href="http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" class="postlink">link</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.txt b/tests/text_processing/tickets_data/PHPBB3-10425.txt
new file mode 100644
index 0000000000..d93c0446b6
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10425.txt
@@ -0,0 +1,3 @@
+http://ar.wikipedia.org/wiki/الصÙحة_الرئيسية
+[url]http://ar.wikipedia.org/wiki/الصÙحة_الرئيسية[/url]
+[url=http://ar.wikipedia.org/wiki/الصÙحة_الرئيسية]link[/url] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.html b/tests/text_processing/tickets_data/PHPBB3-10587.html
new file mode 100644
index 0000000000..4c2e536989
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10587.html
@@ -0,0 +1,2 @@
+<a href="http://example.org/?tourney%5Bid%5D=34&amp;action=brackets" class="postlink">http://example.org/?tourney[id]=34&amp;action=brackets</a><br>
+<a href="http://example.org/?tourney%5Bid%5D=34&amp;action=brackets" class="postlink">link</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.txt b/tests/text_processing/tickets_data/PHPBB3-10587.txt
new file mode 100644
index 0000000000..84788b720d
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10587.txt
@@ -0,0 +1,2 @@
+[url]http://example.org/?tourney[id]=34&action=brackets[/url]
+[url="http://example.org/?tourney[id]=34&action=brackets"]link[/url] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html
new file mode 100644
index 0000000000..3ff117f171
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10922.html
@@ -0,0 +1,9 @@
+<a href="mailto:user@example.org">user@example.org</a><br>
+<a href="mailto:user@example.org">...</a><br>
+<a href="mailto:user@example.org">...</a><br>
+<a href="mailto:user@example.org?subject=Hello">...</a><br>
+<a href="mailto:user@example.org?subject=Hi%20there">user@example.org</a><br>
+<a href="mailto:user@example.org?body=Hi%20there">user@example.org</a><br>
+<a href="mailto:user@example.org?subject=Hello&amp;body=Sent%20from%20phpBB">user@example.org</a><br>
+<a href="mailto:user@example.org?subject=Hello&amp;body=Sent%20from%20phpBB">user@example.org</a><br>
+<a href="mailto:user@example.org?subject=Hello&amp;body=Sent%20from%20phpBB">...</a><br>
diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt
new file mode 100644
index 0000000000..e533ce6ed5
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt
@@ -0,0 +1,9 @@
+[email]user@example.org[/email]
+[email=user@example.org]...[/email]
+[email=user@example.org ]...[/email]
+[email=user@example.org subject="Hello"]...[/email]
+[email subject="Hi there"]user@example.org[/email]
+[email body="Hi there"]user@example.org[/email]
+[email subject="Hello" body="Sent from phpBB"]user@example.org[/email]
+[email body="Sent from phpBB" subject="Hello"]user@example.org[/email]
+[email body="Sent from phpBB" subject="Hello" email="user@example.org"]...[/email]
diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.html b/tests/text_processing/tickets_data/PHPBB3-10989.html
new file mode 100644
index 0000000000..cd24df60e5
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10989.html
@@ -0,0 +1,8 @@
+<blockquote><div><cite>Lorem wrote:</cite>[quote="Lorem"<blockquote class="uncited"><div> Suspendisse iaculis porta tempor. Nulla.</div></blockquote>
+ Nullam a tortor sit amet.</div></blockquote>
+ Proin ac mi eget magna.<br>
+
+<blockquote><div><cite>Lorem wrote:</cite>Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.</div></blockquote>
+
+<br>
+Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper. \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.txt b/tests/text_processing/tickets_data/PHPBB3-10989.txt
new file mode 100644
index 0000000000..dc2430f210
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-10989.txt
@@ -0,0 +1,8 @@
+[quote="Lorem"][quote="Lorem"[quote] Suspendisse iaculis porta tempor. Nulla.[/quote]
+ Nullam a tortor sit amet.[/quote]
+ Proin ac mi eget magna.
+
+[quote="Lorem"]Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.[/quote]
+
+
+Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper. \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.html b/tests/text_processing/tickets_data/PHPBB3-11153.html
new file mode 100644
index 0000000000..0f67ac4bc0
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-11153.html
@@ -0,0 +1 @@
+<a href="mailto:user@example.org">...</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.txt b/tests/text_processing/tickets_data/PHPBB3-11153.txt
new file mode 100644
index 0000000000..d2794978d9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-11153.txt
@@ -0,0 +1 @@
+[myemail=user@example.org]...[/myemail] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.xml b/tests/text_processing/tickets_data/PHPBB3-11153.xml
new file mode 100644
index 0000000000..a7fc69520b
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-11153.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>myemail</value>
+ <value></value>
+ <value>1</value>
+ <value>[myemail={EMAIL}]{TEXT}[/myemail]</value>
+ <value><![CDATA[<a href="mailto:{EMAIL}">{TEXT}</a>]]></value>
+ <value><![CDATA[!\[myemail\=(([\w\!\#$\%\&'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?))\](.*?)\[/myemail\]!ies]]></value>
+ <value><![CDATA['[myemail='.$this->bbcode_specialchars('${1}').':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${2}')).'[/myemail:$uid]']]></value>
+ <value><![CDATA[!\[myemail\=(([\w\!\#$\%\&'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)):$uid\](.*?)\[/myemail:$uid\]!s]]></value>
+ <value><![CDATA[<a href="mailto:${1}">${2}</a>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-11742.html b/tests/text_processing/tickets_data/PHPBB3-11742.html
new file mode 100644
index 0000000000..e7890eef19
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-11742.html
@@ -0,0 +1 @@
+<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code> tab</code></pre></div> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-11742.txt b/tests/text_processing/tickets_data/PHPBB3-11742.txt
new file mode 100644
index 0000000000..db72e5dda0
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-11742.txt
@@ -0,0 +1 @@
+[code] tab[/code] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.html b/tests/text_processing/tickets_data/PHPBB3-12195.html
new file mode 100644
index 0000000000..c286c0fee9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-12195.html
@@ -0,0 +1 @@
+<a href="//example.org/" class="postlink"><img src="//example.org/img.png" class="postimage" alt="Image"></a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.txt b/tests/text_processing/tickets_data/PHPBB3-12195.txt
new file mode 100644
index 0000000000..b66dbd5d96
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-12195.txt
@@ -0,0 +1 @@
+[url=//example.org/][img]//example.org/img.png[/img][/url] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-12221.html b/tests/text_processing/tickets_data/PHPBB3-12221.html
new file mode 100644
index 0000000000..567f552e84
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-12221.html
@@ -0,0 +1 @@
+<a href="https://example.com/test/#?javascript:lolhax" class="postlink">https://example.com/test/#?javascript:lolhax</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-12221.txt b/tests/text_processing/tickets_data/PHPBB3-12221.txt
new file mode 100644
index 0000000000..01a0bf8667
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-12221.txt
@@ -0,0 +1 @@
+https://example.com/test/#?javascript:lolhax \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.html b/tests/text_processing/tickets_data/PHPBB3-13425.html
new file mode 100644
index 0000000000..9a042dc558
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13425.html
@@ -0,0 +1 @@
+<blockquote class="uncited"><div><img class="smilies" src="phpBB/images/smilies/icon_lol.gif" alt=":lol:" title="Laughing"> starts with a smiley</div></blockquote> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.txt b/tests/text_processing/tickets_data/PHPBB3-13425.txt
new file mode 100644
index 0000000000..8456410df5
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13425.txt
@@ -0,0 +1 @@
+[quote]:lol: starts with a smiley[/quote] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.xml b/tests/text_processing/tickets_data/PHPBB3-13425.xml
new file mode 100644
index 0000000000..cbdcaa7fb7
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13425.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>22</value>
+ <value>:lol:</value>
+ <value>Laughing</value>
+ <value>icon_lol.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>22</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-13451.html b/tests/text_processing/tickets_data/PHPBB3-13451.html
new file mode 100644
index 0000000000..e0892c18a9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13451.html
@@ -0,0 +1 @@
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@example.org \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13451.txt b/tests/text_processing/tickets_data/PHPBB3-13451.txt
new file mode 100644
index 0000000000..e0892c18a9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13451.txt
@@ -0,0 +1 @@
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@example.org \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.html b/tests/text_processing/tickets_data/PHPBB3-13641.html
new file mode 100644
index 0000000000..1bd1c06dbb
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13641.html
@@ -0,0 +1 @@
+<code>[color=#FF0000]</code> - <span style="color: #FF0000">red</span> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.txt b/tests/text_processing/tickets_data/PHPBB3-13641.txt
new file mode 100644
index 0000000000..58f324715e
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13641.txt
@@ -0,0 +1 @@
+[c][color=#FF0000][/c] - [color=#FF0000]red[/color] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.xml b/tests/text_processing/tickets_data/PHPBB3-13641.xml
new file mode 100644
index 0000000000..451c5c69cd
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13641.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>c</value>
+ <value></value>
+ <value>1</value>
+ <value>[c]{TEXT}[/c]</value>
+ <value><![CDATA[<code>{TEXT}</code>]]></value>
+ <value><![CDATA[!\[c\](.*?)\[/c\]!ies]]></value>
+ <value><![CDATA['[c:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/c:$uid]']]></value>
+ <value><![CDATA[!\[c:$uid\](.*?)\[/c:$uid\]!s]]></value>
+ <value><![CDATA[<code>${1}</code>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.html b/tests/text_processing/tickets_data/PHPBB3-13921.html
new file mode 100644
index 0000000000..6a9dc7f504
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13921.html
@@ -0,0 +1 @@
+<span style="font-size: 200%; line-height: normal"></span><div style="text-align:center"><span style="font-size: 200%; line-height: normal">xxx</span></div> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.txt b/tests/text_processing/tickets_data/PHPBB3-13921.txt
new file mode 100644
index 0000000000..392da0c3c8
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13921.txt
@@ -0,0 +1 @@
+[size=200][center]xxx[/center][/size] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.xml b/tests/text_processing/tickets_data/PHPBB3-13921.xml
new file mode 100644
index 0000000000..8d39246bb4
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13921.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>center</value>
+ <value></value>
+ <value>1</value>
+ <value>[center]{TEXT}[/center]</value>
+ <value><![CDATA[<div style="text-align:center">{TEXT}</div>]]></value>
+ <value>!\[center\](.*?)\[/center\]!ies</value>
+ <value>'[center:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/center:$uid]'</value>
+ <value>!\[center:$uid\](.*?)\[/center:$uid\]!s</value>
+ <value><![CDATA[<div style="text-align:center">${1}</div>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-14260.html b/tests/text_processing/tickets_data/PHPBB3-14260.html
new file mode 100644
index 0000000000..c7e7cad237
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14260.html
@@ -0,0 +1 @@
+<a href="http://example.org/article/S0883-9441%2811%290483-7/pdf" class="postlink">http://example.org/article/S0883-9441(11)0483-7/pdf</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14260.txt b/tests/text_processing/tickets_data/PHPBB3-14260.txt
new file mode 100644
index 0000000000..f95523c00e
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14260.txt
@@ -0,0 +1 @@
+http://example.org/article/S0883-9441(11)0483-7/pdf \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14405.html b/tests/text_processing/tickets_data/PHPBB3-14405.html
new file mode 100644
index 0000000000..5e76e032ec
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14405.html
@@ -0,0 +1 @@
+[url=<a href="http://example.org" class="postlink">http://example.org</a>]... \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14405.txt b/tests/text_processing/tickets_data/PHPBB3-14405.txt
new file mode 100644
index 0000000000..7005b36b23
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14405.txt
@@ -0,0 +1 @@
+[url=http://example.org]... \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14663.html b/tests/text_processing/tickets_data/PHPBB3-14663.html
new file mode 100644
index 0000000000..b18bcfd52b
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14663.html
@@ -0,0 +1 @@
+<input type="button" value="Кнопка!"> ТеÑÑ‚ \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14663.txt b/tests/text_processing/tickets_data/PHPBB3-14663.txt
new file mode 100644
index 0000000000..5443ae3046
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14663.txt
@@ -0,0 +1 @@
+[test]ТеÑÑ‚[/test] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14663.xml b/tests/text_processing/tickets_data/PHPBB3-14663.xml
new file mode 100644
index 0000000000..423d01e242
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14663.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>test</value>
+ <value></value>
+ <value>1</value>
+ <value>[test]{TEXT}[/test]</value>
+ <value><![CDATA[<input type=button value="Кнопка!" /> {TEXT}]]></value>
+ <value><![CDATA[!\[test\](.*?)\[/test\]!ies]]></value>
+ <value><![CDATA['[test:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/test:$uid]']]></value>
+ <value><![CDATA[!\[test:$uid\](.*?)\[/test:$uid\]!s]]></value>
+ <value><![CDATA[<input type=button value="Кнопка!" /> ${1}]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-14706.html b/tests/text_processing/tickets_data/PHPBB3-14706.html
new file mode 100644
index 0000000000..b8f74c9e93
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14706.html
@@ -0,0 +1 @@
+<ul><li><ol style="list-style-type: lower-alpha"><li>a</li><li>b</li><li>c</li><li>d</li><li>e</li></ol></li><li>outer</li></ul> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14706.txt b/tests/text_processing/tickets_data/PHPBB3-14706.txt
new file mode 100644
index 0000000000..8ec2e9cd35
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14706.txt
@@ -0,0 +1 @@
+[list][list=a][*]a[*]b[*]c[*]d[*]e[/list][*]outer[/list] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14740.html b/tests/text_processing/tickets_data/PHPBB3-14740.html
new file mode 100644
index 0000000000..a1986a0901
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14740.html
@@ -0,0 +1,2 @@
+<div id="modremark"><div id="modremarkexclamation">!</div><div><div id="moderemarktitle">Moderatoropmerking from: neufke</div><div id="moderemarktext">Mod Remark</div></div></div>
+<div id="modremark"><div id="modremarkexclamation">!</div><div><div id="moderemarktitle">Moderatoropmerking from: neufke</div><div id="moderemarktext">Mod Remark</div></div></div> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14740.txt b/tests/text_processing/tickets_data/PHPBB3-14740.txt
new file mode 100644
index 0000000000..c5b2e74513
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14740.txt
@@ -0,0 +1,2 @@
+[mod=neufke]Mod Remark[/mod]
+[mod="neufke"]Mod Remark[/mod] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14740.xml b/tests/text_processing/tickets_data/PHPBB3-14740.xml
new file mode 100644
index 0000000000..9e7dc9760c
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14740.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>mod=</value>
+ <value></value>
+ <value>1</value>
+ <value>[mod=&quot;{TEXT1}&quot;]{TEXT2}[/mod]</value>
+ <value><![CDATA[<div id="modremark">
+ <div id="modremarkexclamation">!</div>
+ <div>
+ <div id="moderemarktitle">Moderatoropmerking {L_FROM}{L_COLON} {TEXT1}</div>
+ <div id="moderemarktext">{TEXT2}</div>
+ </div>
+</div>]]></value>
+ <value>!\[mod\=&quot;(.*?)&quot;\](.*?)\[/mod\]!ies</value>
+ <value>'[mod=&quot;'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'&quot;:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${2}')).'[/mod:$uid]'</value>
+ <value>!\[mod\=&quot;(.*?)&quot;:$uid\](.*?)\[/mod:$uid\]!s</value>
+ <value><![CDATA[<div id="modremark">
+ <div id="modremarkexclamation">!</div>
+ <div>
+ <div id="moderemarktitle">Moderatoropmerking {L_FROM}{L_COLON} ${1}</div>
+ <div id="moderemarktext">${2}</div>
+ </div>
+</div>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-14846.html b/tests/text_processing/tickets_data/PHPBB3-14846.html
new file mode 100644
index 0000000000..461ca25bc6
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14846.html
@@ -0,0 +1 @@
+<div style="padding: .2em .5em; font-size: .8em; width: 200px; background: #FFD;">moderator text<div style="font-weight: bold; text-align: right">- Mickroz</div></div> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14846.txt b/tests/text_processing/tickets_data/PHPBB3-14846.txt
new file mode 100644
index 0000000000..ded7b3f1fe
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14846.txt
@@ -0,0 +1 @@
+[mod=Mickroz]moderator text[/mod] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-14846.xml b/tests/text_processing/tickets_data/PHPBB3-14846.xml
new file mode 100644
index 0000000000..94b094f0e3
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-14846.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>mod=</value>
+ <value></value>
+ <value>1</value>
+ <value>[mod={TEXT1}]{TEXT2}[/mod]</value>
+ <value><![CDATA[<div style="padding: .2em .5em; font-size: .8em; width: 200px; background: #FFD;">{TEXT2}<div style="font-weight: bold; text-align: right">- {TEXT1}</div></div>]]></value>
+ <value><![CDATA[!\[mod\=(.*?)\](.*?)\[/mod\]!ies]]></value>
+ <value><![CDATA['[mod='.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${2}')).'[/mod:$uid]']]></value>
+ <value><![CDATA[!\[mod\=(.*?):$uid\](.*?)\[/mod:$uid\]!s]]></value>
+ <value><![CDATA[<div style="padding: .2em .5em; font-size: .8em; width: 200px; background: #FFD;">${2}<div style="font-weight: bold; text-align: right">- ${1}</div></div>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.before.php b/tests/text_processing/tickets_data/PHPBB3-3981.before.php
new file mode 100644
index 0000000000..1c326b52af
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-3981.before.php
@@ -0,0 +1,21 @@
+<?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.
+*
+*/
+
+function before_assert_phpbb3_3981($vars)
+{
+ if (!function_exists('idn_to_ascii'))
+ {
+ extract($vars);
+ $test->markTestSkipped('International URLs need idn_to_ascii()');
+ }
+}
diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.html b/tests/text_processing/tickets_data/PHPBB3-3981.html
new file mode 100644
index 0000000000..e5f1b4561d
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-3981.html
@@ -0,0 +1 @@
+<a href="http://www.xn--ndaaa.com" class="postlink">http://www.ööö.com</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.txt b/tests/text_processing/tickets_data/PHPBB3-3981.txt
new file mode 100644
index 0000000000..976823f1d1
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-3981.txt
@@ -0,0 +1 @@
+[url]http://www.ööö.com[/url] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.html b/tests/text_processing/tickets_data/PHPBB3-7187.html
new file mode 100644
index 0000000000..9138779d29
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7187.html
@@ -0,0 +1 @@
+<blockquote class="uncited"><div><img class="smilies" src="phpBB/images/smilies/icon_e_geek.gif" alt=":geek:" title="Geek"> <img class="smilies" src="phpBB/images/smilies/icon_e_ugeek.gif" alt=":ugeek:" title="Uber Geek"></div></blockquote> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.txt b/tests/text_processing/tickets_data/PHPBB3-7187.txt
new file mode 100644
index 0000000000..584151a083
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7187.txt
@@ -0,0 +1 @@
+[quote]:geek: :ugeek:[/quote] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.xml b/tests/text_processing/tickets_data/PHPBB3-7187.xml
new file mode 100644
index 0000000000..d270b12619
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7187.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>41</value>
+ <value>:geek:</value>
+ <value>Geek</value>
+ <value>icon_e_geek.gif</value>
+ <value>17</value>
+ <value>17</value>
+ <value>41</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>42</value>
+ <value>:ugeek:</value>
+ <value>Uber Geek</value>
+ <value>icon_e_ugeek.gif</value>
+ <value>17</value>
+ <value>18</value>
+ <value>42</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.after.php b/tests/text_processing/tickets_data/PHPBB3-7275.after.php
new file mode 100644
index 0000000000..99f41d7839
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7275.after.php
@@ -0,0 +1,19 @@
+<?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.
+*
+*/
+
+function after_assert_phpbb3_7275($vars)
+{
+ extract($vars);
+ decode_message($parsed_text);
+ $test->assertSame($original, $parsed_text);
+}
diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.html b/tests/text_processing/tickets_data/PHPBB3-7275.html
new file mode 100644
index 0000000000..12502833fd
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7275.html
@@ -0,0 +1 @@
+<div align="center"><img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" alt=":)" title="Smile"></div> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.txt b/tests/text_processing/tickets_data/PHPBB3-7275.txt
new file mode 100644
index 0000000000..8de97d67e0
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7275.txt
@@ -0,0 +1 @@
+[center]:)[/center] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.xml b/tests/text_processing/tickets_data/PHPBB3-7275.xml
new file mode 100644
index 0000000000..9e979afffb
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-7275.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>center</value>
+ <value></value>
+ <value>1</value>
+ <value>[center]{TEXT}[/center]</value>
+ <value><![CDATA[<div align="center">{TEXT}</div>]]></value>
+ <value>!\[center\](.*?)\[/center\]!ies</value>
+ <value><![CDATA['[center:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/center:$uid]']]></value>
+ <value>!\[center:$uid\](.*?)\[/center:$uid\]!s</value>
+ <value><![CDATA[<div align="center">${1}</div>]]></value>
+ </row>
+ </table>
+
+ <table name="phpbb_smilies">
+ <column>smiley_id</column>
+ <column>code</column>
+ <column>emotion</column>
+ <column>smiley_url</column>
+ <column>smiley_width</column>
+ <column>smiley_height</column>
+ <column>smiley_order</column>
+ <column>display_on_posting</column>
+ <row>
+ <value>4</value>
+ <value>:)</value>
+ <value>Smile</value>
+ <value>icon_e_smile.gif</value>
+ <value>15</value>
+ <value>17</value>
+ <value>4</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.html b/tests/text_processing/tickets_data/PHPBB3-8419.html
new file mode 100644
index 0000000000..38df626a94
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-8419.html
@@ -0,0 +1 @@
+<span style="font-style: italic"><span style="font-weight: bold"><span style="color: #FF0000">tę </span></span></span>przykład \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.txt b/tests/text_processing/tickets_data/PHPBB3-8419.txt
new file mode 100644
index 0000000000..dac47823b6
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-8419.txt
@@ -0,0 +1 @@
+[ort]tę [/ort]przykład \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.xml b/tests/text_processing/tickets_data/PHPBB3-8419.xml
new file mode 100644
index 0000000000..2f1df345f9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-8419.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>myemail</value>
+ <value></value>
+ <value>1</value>
+ <value>[ort]{TEXT}[/ort]</value>
+ <value><![CDATA[<span style="font-style: italic"><span style="font-weight: bold"><span style="color: #FF0000">{TEXT}</span></span></span>]]></value>
+ <value><![CDATA[!\[ort\](.*?)\[/ort\]!ies]]></value>
+ <value><![CDATA['[ort:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/ort:$uid]']]></value>
+ <value><![CDATA[!\[ort:$uid\](.*?)\[/ort:$uid\]!s]]></value>
+ <value><![CDATA[<span style="font-style: italic"><span style="font-weight: bold"><span style="color: #FF0000">${1}</span></span></span>]]></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.html b/tests/text_processing/tickets_data/PHPBB3-9073.html
new file mode 100644
index 0000000000..ff1f9fd0ce
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9073.html
@@ -0,0 +1,2 @@
+<a href="http://www.xxxx-xx-xxxx.com/" class="postlink">http://www.xxxx-xx-xxxx.com/</a><br>
+<a href="http://www.xxxx-xx-xxxx.com/" class="postlink">http://www.xxxx-xx-xxxx.com/</a><br>
diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.txt b/tests/text_processing/tickets_data/PHPBB3-9073.txt
new file mode 100644
index 0000000000..2c271173ce
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9073.txt
@@ -0,0 +1,2 @@
+http://www.some-ad-site.com/
+[url]http://www.some-ad-site.com/[/url]
diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.xml b/tests/text_processing/tickets_data/PHPBB3-9073.xml
new file mode 100644
index 0000000000..d635d51ed1
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9073.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_words">
+ <column>word_id</column>
+ <column>word</column>
+ <column>replacement</column>
+
+ <row>
+ <value>1</value>
+ <value>http://www.some-ad-site.com*</value>
+ <value>http://www.xxxx-xx-xxxx.com</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.html b/tests/text_processing/tickets_data/PHPBB3-9377.html
new file mode 100644
index 0000000000..dcfb79c173
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9377.html
@@ -0,0 +1 @@
+<span style="color:red">red <span style="color:blue">blue</span> red</span> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.txt b/tests/text_processing/tickets_data/PHPBB3-9377.txt
new file mode 100644
index 0000000000..dfd71492c5
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9377.txt
@@ -0,0 +1 @@
+[red]red [blue]blue[/blue] red[/red] \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.xml b/tests/text_processing/tickets_data/PHPBB3-9377.xml
new file mode 100644
index 0000000000..1d8ee3d53f
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9377.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_bbcodes">
+ <column>bbcode_id</column>
+ <column>bbcode_tag</column>
+ <column>bbcode_helpline</column>
+ <column>display_on_posting</column>
+ <column>bbcode_match</column>
+ <column>bbcode_tpl</column>
+ <column>first_pass_match</column>
+ <column>first_pass_replace</column>
+ <column>second_pass_match</column>
+ <column>second_pass_replace</column>
+
+ <row>
+ <value>13</value>
+ <value>red</value>
+ <value></value>
+ <value>1</value>
+ <value>[red]{TEXT}[/red]</value>
+ <value>&lt;span style=&quot;color:red&quot;&gt;{TEXT}&lt;/span&gt;</value>
+ <value>!\[red\](.*?)\[/red\]!ies</value>
+ <value>'[red:$uid]'.str_replace(array(&quot;\r\n&quot;, '\&quot;', '\'', '(', ')'), array(&quot;\n&quot;, '&quot;', '&amp;#39;', '&amp;#40;', '&amp;#41;'), trim('${1}')).'[/red:$uid]'</value>
+ <value>!\[red:$uid\](.*?)\[/red:$uid\]!s</value>
+ <value>&lt;span style=&quot;color:red&quot;&gt;${1}&lt;/span&gt;</value>
+ </row>
+
+ <row>
+ <value>14</value>
+ <value>blue</value>
+ <value></value>
+ <value>1</value>
+ <value>[blue]{TEXT}[/blue]</value>
+ <value>&lt;span style=&quot;color:blue&quot;&gt;{TEXT}&lt;/span&gt;</value>
+ <value>!\[blue\](.*?)\[/blue\]!ies</value>
+ <value>'[blue:$uid]'.str_replace(array(&quot;\r\n&quot;, '\&quot;', '\'', '(', ')'), array(&quot;\n&quot;, '&quot;', '&amp;#39;', '&amp;#40;', '&amp;#41;'), trim('${1}')).'[/blue:$uid]'</value>
+ <value>!\[blue:$uid\](.*?)\[/blue:$uid\]!s</value>
+ <value>&lt;span style=&quot;color:blue&quot;&gt;${1}&lt;/span&gt;</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_processing/tickets_data/PHPBB3-9791.html b/tests/text_processing/tickets_data/PHPBB3-9791.html
new file mode 100644
index 0000000000..3d0108c8a6
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9791.html
@@ -0,0 +1 @@
+<a href="http://www.phpbb.com/community/search.php?keywords=bogus&amp;terms=all&amp;author=&amp;fid%5B%5D=46&amp;sc=1&amp;sf=all&amp;sr=posts&amp;sk=t&amp;sd=d&amp;st=0&amp;ch=300&amp;t=0&amp;submit=Search" class="postlink">http://www.phpbb.com/community/search.p ... mit=Search</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-9791.txt b/tests/text_processing/tickets_data/PHPBB3-9791.txt
new file mode 100644
index 0000000000..e29b20086d
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9791.txt
@@ -0,0 +1 @@
+http://www.phpbb.com/community/search.php?keywords=bogus&terms=all&author=&fid[]=46&sc=1&sf=all&sr=posts&sk=t&sd=d&st=0&ch=300&t=0&submit=Search \ No newline at end of file
diff --git a/tests/text_processing/tickets_test.php b/tests/text_processing/tickets_test.php
new file mode 100644
index 0000000000..6230191a69
--- /dev/null
+++ b/tests/text_processing/tickets_test.php
@@ -0,0 +1,90 @@
+<?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.
+*
+*/
+
+class phpbb_text_processing_tickets_test extends phpbb_test_case
+{
+ /**
+ * @dataProvider get_tickets_data
+ */
+ public function test_tickets($ticket_id, $original, $expected, $fixture, $before_assert, $after_assert)
+ {
+ global $phpbb_container;
+
+ $phpbb_container = new phpbb_mock_container_builder;
+
+ $this->get_test_case_helpers()->set_s9e_services($phpbb_container, $fixture);
+
+ $parser = $phpbb_container->get('text_formatter.parser');
+ $renderer = $phpbb_container->get('text_formatter.renderer');
+
+ if (isset($before_assert))
+ {
+ $test = $this;
+ $before_assert(get_defined_vars());
+ }
+
+ $parsed_text = $parser->parse($original);
+
+ $this->assertSame($expected, $renderer->render($parsed_text));
+
+ if (isset($after_assert))
+ {
+ $test = $this;
+ $after_assert(get_defined_vars());
+ }
+ }
+
+ public function get_tickets_data()
+ {
+ $tests = array();
+
+ foreach (glob(__DIR__ . '/tickets_data/*.txt') as $txt_filename)
+ {
+ $ticket_id = basename($txt_filename, '.txt');
+ $html_filename = substr($txt_filename, 0, -3) . 'html';
+ $xml_filename = substr($txt_filename, 0, -3) . 'xml';
+ $before_filename = substr($txt_filename, 0, -3) . 'before.php';
+ $after_filename = substr($txt_filename, 0, -3) . 'after.php';
+
+ if (!file_exists($xml_filename))
+ {
+ $xml_filename = __DIR__ . '/../fixtures/empty.xml';
+ }
+
+ $before_assert = null;
+ if (file_exists($before_filename))
+ {
+ include($before_filename);
+ $before_assert = 'before_assert_' . strtolower(str_replace('-', '_', $ticket_id));
+ }
+
+ $after_assert = null;
+ if (file_exists($after_filename))
+ {
+ include($after_filename);
+ $after_assert = 'after_assert_' . strtolower(str_replace('-', '_', $ticket_id));
+ }
+
+ $tests[] = array(
+ $ticket_id,
+ file_get_contents($txt_filename),
+ file_get_contents($html_filename),
+ $xml_filename,
+ $before_assert,
+ $after_assert
+ );
+ }
+
+ return $tests;
+ }
+}
diff --git a/tests/text_reparser/base_test.php b/tests/text_reparser/base_test.php
new file mode 100644
index 0000000000..af2d56ea51
--- /dev/null
+++ b/tests/text_reparser/base_test.php
@@ -0,0 +1,69 @@
+<?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.
+*
+*/
+
+require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php';
+
+class phpbb_textreparser_base_test extends phpbb_database_test_case
+{
+ protected $db;
+
+ public function setUp()
+ {
+ global $config;
+ if (!isset($config))
+ {
+ $config = new \phpbb\config\config(array());
+ }
+ $this->get_test_case_helpers()->set_s9e_services();
+ $this->db = $this->new_dbal();
+ parent::setUp();
+ }
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/base.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\post_text($this->db, POSTS_TABLE);
+ }
+
+ protected function get_rows(array $ids)
+ {
+ $sql = 'SELECT post_id AS id, post_text AS text
+ FROM ' . POSTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('post_id', $ids) . '
+ ORDER BY id';
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ public function test_reparse_empty()
+ {
+ $this->get_reparser()->reparse_range(1, 1);
+
+ $this->assertEquals(
+ array(
+ array(
+ 'id' => 1,
+ 'text' => '<t></t>'
+ )
+ ),
+ $this->get_rows(array(1))
+ );
+ }
+}
diff --git a/tests/text_reparser/fixtures/base.xml b/tests/text_reparser/fixtures/base.xml
new file mode 100644
index 0000000000..a4921a8823
--- /dev/null
+++ b/tests/text_reparser/fixtures/base.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_posts">
+ <column>post_id</column>
+ <column>enable_bbcode</column>
+ <column>enable_smilies</column>
+ <column>enable_magic_url</column>
+ <column>post_text</column>
+ <column>bbcode_uid</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/fixtures/config_text.xml b/tests/text_reparser/fixtures/config_text.xml
new file mode 100644
index 0000000000..ba8e1fcfcc
--- /dev/null
+++ b/tests/text_reparser/fixtures/config_text.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_config_text">
+ <column>config_name</column>
+ <column>config_value</column>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/manager_test.php b/tests/text_reparser/manager_test.php
new file mode 100644
index 0000000000..df6adacb66
--- /dev/null
+++ b/tests/text_reparser/manager_test.php
@@ -0,0 +1,117 @@
+<?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.
+ *
+ */
+
+require_once __DIR__ . '/../mock/container_builder.php';
+require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php';
+
+class phpbb_text_reparser_manager_test extends phpbb_database_test_case
+{
+ /** @var \phpbb\config\config */
+ protected $config;
+
+ /** @var \phpbb\config\db_text */
+ protected $config_text;
+
+ /** @var \phpbb\textreparser\manager */
+ protected $reparser_manager;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config_text.xml');
+ }
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->config = new \phpbb\config\config(array(
+ 'test_reparser_cron_interval' => 0,
+ 'my_reparser_cron_interval' => 100,
+ ));
+
+ $db = $this->new_dbal();
+ $this->config_text = new \phpbb\config\db_text($db, 'phpbb_config_text');
+
+ $service_collection = new \phpbb\di\service_collection(new phpbb_mock_container_builder());
+ $service_collection->add('test_reparser');
+ $service_collection->add('another_reparser');
+ $service_collection->add('my_reparser');
+
+ $this->reparser_manager = new \phpbb\textreparser\manager($this->config, $this->config_text, $service_collection);
+ }
+
+ public function test_get_resume_data()
+ {
+ $resume_data = array(
+ 'test_reparser' => array(
+ 'range-min' => 0,
+ 'range-max' => 100,
+ 'range-size' => 50,
+ ),
+ );
+ $this->config_text->set('reparser_resume', serialize($resume_data));
+
+ $this->assert_array_content_equals($resume_data['test_reparser'], $this->reparser_manager->get_resume_data('test_reparser'));
+ $this->assertEmpty($this->reparser_manager->get_resume_data('another_reparser'));
+ }
+
+ public function test_update_resume_data()
+ {
+ $resume_data = array(
+ 'test_reparser' => array(
+ 'range-min' => 0,
+ 'range-max' => 100,
+ 'range-size' => 50,
+ ),
+ );
+ $this->config_text->set('reparser_resume', serialize($resume_data));
+
+ $this->reparser_manager->update_resume_data('another_reparser', 5, 20, 10, false);
+ $this->assert_array_content_equals($resume_data, unserialize($this->config_text->get('reparser_resume')));
+
+ $this->reparser_manager->update_resume_data('test_reparser', 0, 50, 50);
+ $resume_data = array(
+ 'test_reparser' => array(
+ 'range-min' => 0,
+ 'range-max' => 50,
+ 'range-size' => 50,
+ ),
+ 'another_reparser' => array(
+ 'range-min' => 5,
+ 'range-max' => 20,
+ 'range-size' => 10,
+ ),
+ );
+ $this->assert_array_content_equals($resume_data, unserialize($this->config_text->get('reparser_resume')));
+ }
+
+ public function test_schedule()
+ {
+ $this->reparser_manager->schedule('no_reparser', 21);
+ $this->assertArrayNotHasKey('no_reparser_cron_interval', $this->config);
+
+ $this->reparser_manager->schedule('another_reparser', 42);
+ $this->assertArrayNotHasKey('another_reparser_cron_interval', $this->config);
+
+ $this->reparser_manager->schedule('test_reparser', 20);
+ $this->assertEquals(20, $this->config['test_reparser_cron_interval']);
+ }
+
+ public function test_schedule_all()
+ {
+ $this->reparser_manager->schedule_all(180);
+ $this->assertEquals(180, $this->config['test_reparser_cron_interval']);
+ $this->assertEquals(180, $this->config['my_reparser_cron_interval']);
+ $this->assertArrayNotHasKey('another_reparser_cron_interval', $this->config);
+ }
+}
diff --git a/tests/text_reparser/plugins/contact_admin_info_test.php b/tests/text_reparser/plugins/contact_admin_info_test.php
new file mode 100644
index 0000000000..757b02be39
--- /dev/null
+++ b/tests/text_reparser/plugins/contact_admin_info_test.php
@@ -0,0 +1,95 @@
+<?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.
+*
+*/
+
+require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php';
+
+class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_case
+{
+ protected $db;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/contact_admin_info.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\contact_admin_info(new \phpbb\config\db_text($this->db, CONFIG_TEXT_TABLE));
+ }
+
+ protected function get_rows()
+ {
+ $sql = 'SELECT config_name, config_value
+ FROM ' . CONFIG_TEXT_TABLE . '
+ ORDER BY config_name';
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ public function setUp()
+ {
+ global $config;
+ if (!isset($config))
+ {
+ $config = new \phpbb\config\config(array());
+ }
+ $this->get_test_case_helpers()->set_s9e_services();
+ $this->db = $this->new_dbal();
+ parent::setUp();
+ }
+
+ public function test_get_max_id()
+ {
+ $reparser = $this->get_reparser();
+ $this->assertEquals(1, $reparser->get_max_id());
+ }
+
+ public function test_dry_run()
+ {
+ $old_rows = $this->get_rows();
+ $reparser = $this->get_reparser();
+ $reparser->disable_save();
+ $reparser->reparse_range(1, 1);
+ $new_rows = $this->get_rows();
+ $this->assertEquals($old_rows, $new_rows);
+ }
+
+ public function test_reparse()
+ {
+ $reparser = $this->get_reparser();
+ $reparser->enable_save();
+ $reparser->reparse_range(1, 1);
+ $expected = array(
+ array(
+ 'config_name' => 'contact_admin_info',
+ 'config_value' => '<r><EMAIL email="admin@example.org"><s>[email]</s>admin@example.org<e>[/email]</e></EMAIL></r>',
+ ),
+ array(
+ 'config_name' => 'contact_admin_info_bitfield',
+ 'config_value' => 'ACA=',
+ ),
+ array(
+ 'config_name' => 'contact_admin_info_flags',
+ 'config_value' => '7',
+ ),
+ array(
+ 'config_name' => 'contact_admin_info_uid',
+ 'config_value' => '1a2hbwf5',
+ ),
+ );
+ $this->assertEquals($expected, $this->get_rows());
+ }
+}
diff --git a/tests/text_reparser/plugins/fixtures/contact_admin_info.xml b/tests/text_reparser/plugins/fixtures/contact_admin_info.xml
new file mode 100644
index 0000000000..13cd82b1a4
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/contact_admin_info.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_config_text">
+ <column>config_name</column>
+ <column>config_value</column>
+ <row>
+ <value>contact_admin_info</value>
+ <value>[email:1a2hbwf5]admin@example&#46;org[/email:1a2hbwf5]</value>
+ </row>
+ <row>
+ <value>contact_admin_info_uid</value>
+ <value>1a2hbwf5</value>
+ </row>
+ <row>
+ <value>contact_admin_info_bitfield</value>
+ <value>ACA=</value>
+ </row>
+ <row>
+ <value>contact_admin_info_flags</value>
+ <value>7</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/forums.xml b/tests/text_reparser/plugins/fixtures/forums.xml
new file mode 100644
index 0000000000..c12c8d6d48
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/forums.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_forums">
+ <column>forum_id</column>
+ <column>forum_parents</column>
+ <column>forum_desc</column>
+ <column>forum_desc_uid</column>
+ <column>forum_desc_options</column>
+ <column>forum_rules</column>
+ <column>forum_rules_uid</column>
+ <column>forum_rules_options</column>
+ <row>
+ <value>1</value>
+ <value></value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ <value>0</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value></value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ <value>abcd1234</value>
+ <value>0</value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ <value>abcd1234</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value></value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ <value>abcd1234</value>
+ <value>1</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ <value>abcd1234</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value></value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ <value>abcd1234</value>
+ <value>2</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ <value>abcd1234</value>
+ <value>2</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value></value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ <value>abcd1234</value>
+ <value>4</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ <value>abcd1234</value>
+ <value>4</value>
+ </row>
+ <row>
+ <value>6</value>
+ <value></value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ <value>abcd1234</value>
+ <value>1</value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ <value>abcd1234</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>7</value>
+ <value></value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ <value>abcd1234</value>
+ <value>0</value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ <value>abcd1234</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>8</value>
+ <value></value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ <value>abcd1234</value>
+ <value>1</value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ <value>abcd1234</value>
+ <value>1</value>
+ </row>
+ <row>
+ <value>9</value>
+ <value></value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ <value>abcd1234</value>
+ <value>0</value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ <value>abcd1234</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>1000</value>
+ <value></value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ <value>0</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ <value>0</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/groups.xml b/tests/text_reparser/plugins/fixtures/groups.xml
new file mode 100644
index 0000000000..15151426bc
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/groups.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_groups">
+ <column>group_id</column>
+ <column>group_desc</column>
+ <column>group_desc_options</column>
+ <column>group_desc_uid</column>
+ <row>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>7</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ <value>0</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ <value>1</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ <value>2</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ <value>4</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>6</value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ <value>1</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>7</value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ <value>1</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>8</value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ <value>1</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>9</value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ <value>1</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>1000</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>7</value>
+ <value>abcd1234</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/poll_options.xml b/tests/text_reparser/plugins/fixtures/poll_options.xml
new file mode 100644
index 0000000000..48ba024315
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/poll_options.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_poll_options">
+ <column>poll_option_id</column>
+ <column>topic_id</column>
+ <column>poll_option_text</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ <value>This row should be [b:abcd1234]ignored[/b:abcd1234]</value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>2</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234]</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>2</value>
+ <value><![CDATA[<!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) -->]]></value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>2</value>
+ <value><![CDATA[<!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>11</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>12</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>13</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ </row>
+ <row>
+ <value>1</value>
+ <value>123</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>123</value>
+ <value>This row should be [b:abcd1234]ignored[/b:abcd1234]</value>
+ </row>
+ </table>
+ <table name="phpbb_posts">
+ <column>post_id</column>
+ <column>enable_bbcode</column>
+ <column>enable_smilies</column>
+ <column>enable_magic_url</column>
+ <column>post_text</column>
+ <column>bbcode_uid</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>11</value>
+ <value>1</value>
+ <value>0</value>
+ <value>0</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>12</value>
+ <value>0</value>
+ <value>1</value>
+ <value>0</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>13</value>
+ <value>0</value>
+ <value>0</value>
+ <value>1</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ </table>
+ <table name="phpbb_topics">
+ <column>topic_id</column>
+ <column>topic_first_post_id</column>
+ <column>poll_title</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ <row>
+ <value>11</value>
+ <value>11</value>
+ <value>BBCode</value>
+ </row>
+ <row>
+ <value>12</value>
+ <value>12</value>
+ <value>Smilies</value>
+ </row>
+ <row>
+ <value>13</value>
+ <value>13</value>
+ <value>Magic URLs</value>
+ </row>
+ <row>
+ <value>123</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/polls.xml b/tests/text_reparser/plugins/fixtures/polls.xml
new file mode 100644
index 0000000000..2960d640a9
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/polls.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_posts">
+ <column>post_id</column>
+ <column>enable_bbcode</column>
+ <column>enable_smilies</column>
+ <column>enable_magic_url</column>
+ <column>post_text</column>
+ <column>bbcode_uid</column>
+ <row>
+ <value>1</value>
+ <value>0</value>
+ <value>0</value>
+ <value>0</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ <value>0</value>
+ <value>0</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>0</value>
+ <value>1</value>
+ <value>0</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>0</value>
+ <value>0</value>
+ <value>1</value>
+ <value></value>
+ <value>abcd1234</value>
+ </row>
+ </table>
+ <table name="phpbb_topics">
+ <column>topic_id</column>
+ <column>topic_first_post_id</column>
+ <column>poll_title</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>1</value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>2</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>3</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>4</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>2</value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ </row>
+ <row>
+ <value>7</value>
+ <value>1</value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ </row>
+ <row>
+ <value>8</value>
+ <value>2</value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ </row>
+ <row>
+ <value>9</value>
+ <value>1</value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ </row>
+ <row>
+ <value>1000</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/posts.xml b/tests/text_reparser/plugins/fixtures/posts.xml
new file mode 100644
index 0000000000..ec31747ed9
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/posts.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_posts">
+ <column>post_id</column>
+ <column>enable_bbcode</column>
+ <column>enable_smilies</column>
+ <column>enable_magic_url</column>
+ <column>post_text</column>
+ <column>bbcode_uid</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>0</value>
+ <value>0</value>
+ <value>0</value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>1</value>
+ <value>0</value>
+ <value>0</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>0</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>0</value>
+ <value>0</value>
+ <value>1</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>7</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>8</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>9</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>1000</value>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/privmsgs.xml b/tests/text_reparser/plugins/fixtures/privmsgs.xml
new file mode 100644
index 0000000000..4049b9890a
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/privmsgs.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_privmsgs">
+ <column>msg_id</column>
+ <column>enable_bbcode</column>
+ <column>enable_smilies</column>
+ <column>enable_magic_url</column>
+ <column>message_text</column>
+ <column>bbcode_uid</column>
+ <column>to_address</column>
+ <column>bcc_address</column>
+ <row>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>0</value>
+ <value>0</value>
+ <value>0</value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>1</value>
+ <value>0</value>
+ <value>0</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>4</value>
+ <value>0</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>5</value>
+ <value>0</value>
+ <value>0</value>
+ <value>1</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>6</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>7</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>8</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>9</value>
+ <value>1</value>
+ <value>1</value>
+ <value>0</value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ <row>
+ <value>1000</value>
+ <value>1</value>
+ <value>1</value>
+ <value>1</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ <value></value>
+ <value></value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/fixtures/users.xml b/tests/text_reparser/plugins/fixtures/users.xml
new file mode 100644
index 0000000000..60c623b6b1
--- /dev/null
+++ b/tests/text_reparser/plugins/fixtures/users.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_users">
+ <column>user_id</column>
+ <column>user_permissions</column>
+ <column>username_clean</column>
+ <column>user_options</column>
+ <column>user_sig</column>
+ <column>user_sig_bbcode_uid</column>
+ <row>
+ <value>1</value>
+ <value></value>
+ <value>user1</value>
+ <value>230271</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value></value>
+ <value>user2</value>
+ <value>895</value>
+ <value>[b]Not bold[/b] :) http://example.org</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value></value>
+ <value>user3</value>
+ <value>33663</value>
+ <value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>4</value>
+ <value></value>
+ <value>user4</value>
+ <value>66431</value>
+ <value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>5</value>
+ <value></value>
+ <value>user5</value>
+ <value>131967</value>
+ <value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>6</value>
+ <value></value>
+ <value>user6</value>
+ <value>99199</value>
+ <value><![CDATA[[flash=123,345:abcd1234]http&#58;//example&#46;org/flash&#46;swf[/flash:abcd1234]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>7</value>
+ <value></value>
+ <value>user7</value>
+ <value>99199</value>
+ <value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>8</value>
+ <value></value>
+ <value>user8</value>
+ <value>99199</value>
+ <value><![CDATA[[img:abcd1234]http&#58;//example&#46;org/img&#46;png[/img:abcd1234]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>9</value>
+ <value></value>
+ <value>user9</value>
+ <value>99199</value>
+ <value><![CDATA[[img]http://example.org/img.png[/img]]]></value>
+ <value>abcd1234</value>
+ </row>
+ <row>
+ <value>1000</value>
+ <value></value>
+ <value>user1000</value>
+ <value>230271</value>
+ <value>This row should be [b]ignored[/b]</value>
+ <value>abcd1234</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/text_reparser/plugins/forum_description_test.php b/tests/text_reparser/plugins/forum_description_test.php
new file mode 100644
index 0000000000..57166e6a3c
--- /dev/null
+++ b/tests/text_reparser/plugins/forum_description_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_forum_description_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\forum_description($this->db, FORUMS_TABLE);
+ }
+}
diff --git a/tests/text_reparser/plugins/forum_rules_test.php b/tests/text_reparser/plugins/forum_rules_test.php
new file mode 100644
index 0000000000..72e4e98876
--- /dev/null
+++ b/tests/text_reparser/plugins/forum_rules_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_forum_rules_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\forum_rules($this->db, FORUMS_TABLE);
+ }
+}
diff --git a/tests/text_reparser/plugins/group_description_test.php b/tests/text_reparser/plugins/group_description_test.php
new file mode 100644
index 0000000000..babfc7e02f
--- /dev/null
+++ b/tests/text_reparser/plugins/group_description_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_group_description_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/groups.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\group_description($this->db, GROUPS_TABLE);
+ }
+}
diff --git a/tests/text_reparser/plugins/pm_text_test.php b/tests/text_reparser/plugins/pm_text_test.php
new file mode 100644
index 0000000000..6dc1a9cb4c
--- /dev/null
+++ b/tests/text_reparser/plugins/pm_text_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_pm_text_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/privmsgs.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\pm_text($this->db, PRIVMSGS_TABLE);
+ }
+}
diff --git a/tests/text_reparser/plugins/poll_option_test.php b/tests/text_reparser/plugins/poll_option_test.php
new file mode 100644
index 0000000000..177faac51d
--- /dev/null
+++ b/tests/text_reparser/plugins/poll_option_test.php
@@ -0,0 +1,129 @@
+<?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.
+*
+*/
+
+require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php';
+
+class phpbb_textreparser_poll_option_test extends phpbb_database_test_case
+{
+ protected $db;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/poll_options.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\poll_option($this->db);
+ }
+
+ protected function get_rows()
+ {
+ $sql = 'SELECT topic_id, poll_option_id, poll_option_text
+ FROM ' . POLL_OPTIONS_TABLE . '
+ ORDER BY topic_id, poll_option_id';
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ public function setUp()
+ {
+ global $config;
+ if (!isset($config))
+ {
+ $config = new \phpbb\config\config(array());
+ }
+ $this->get_test_case_helpers()->set_s9e_services();
+ $this->db = $this->new_dbal();
+ parent::setUp();
+ }
+
+ public function test_get_max_id()
+ {
+ $reparser = $this->get_reparser();
+ $this->assertEquals(123, $reparser->get_max_id());
+ }
+
+ public function test_dry_run()
+ {
+ $old_rows = $this->get_rows();
+ $reparser = $this->get_reparser();
+ $reparser->disable_save();
+ $reparser->reparse_range(1, 1);
+ $new_rows = $this->get_rows();
+ $this->assertEquals($old_rows, $new_rows);
+ }
+
+ public function testReparse()
+ {
+ $reparser = $this->get_reparser();
+ $reparser->enable_save();
+ $reparser->reparse_range(2, 13);
+ $expected = array(
+ array(
+ 'topic_id' => 1,
+ 'poll_option_id' => 1,
+ 'poll_option_text' => 'This row should be [b]ignored[/b]',
+ ),
+ array(
+ 'topic_id' => 1,
+ 'poll_option_id' => 2,
+ 'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]',
+ ),
+ array(
+ 'topic_id' => 2,
+ 'poll_option_id' => 1,
+ 'poll_option_text' => '<r><B><s>[b]</s>Bold<e>[/b]</e></B></r>',
+ ),
+ array(
+ 'topic_id' => 2,
+ 'poll_option_id' => 2,
+ 'poll_option_text' => '<r><E>:)</E></r>',
+ ),
+ array(
+ 'topic_id' => 2,
+ 'poll_option_id' => 3,
+ 'poll_option_text' => '<r><URL url="http://example.org">http://example.org</URL></r>',
+ ),
+ array(
+ 'topic_id' => 11,
+ 'poll_option_id' => 1,
+ 'poll_option_text' => '<r><B><s>[b]</s>Bold<e>[/b]</e></B> :) http://example.org</r>',
+ ),
+ array(
+ 'topic_id' => 12,
+ 'poll_option_id' => 1,
+ 'poll_option_text' => '<r>[b]Not bold[/b] <E>:)</E> http://example.org</r>',
+ ),
+ array(
+ 'topic_id' => 13,
+ 'poll_option_id' => 1,
+ 'poll_option_text' => '<r>[b]Not bold[/b] :) <URL url="http://example.org">http://example.org</URL></r>',
+ ),
+ array(
+ 'topic_id' => 123,
+ 'poll_option_id' => 1,
+ 'poll_option_text' => 'This row should be [b]ignored[/b]',
+ ),
+ array(
+ 'topic_id' => 123,
+ 'poll_option_id' => 2,
+ 'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]',
+ ),
+ );
+ $this->assertEquals($expected, $this->get_rows());
+ }
+}
diff --git a/tests/text_reparser/plugins/poll_title_test.php b/tests/text_reparser/plugins/poll_title_test.php
new file mode 100644
index 0000000000..046b6019c8
--- /dev/null
+++ b/tests/text_reparser/plugins/poll_title_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_poll_title_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/polls.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\poll_title($this->db, TOPICS_TABLE);
+ }
+}
diff --git a/tests/text_reparser/plugins/post_text_test.php b/tests/text_reparser/plugins/post_text_test.php
new file mode 100644
index 0000000000..8ea71e65f5
--- /dev/null
+++ b/tests/text_reparser/plugins/post_text_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_post_text_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/posts.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\post_text($this->db, POSTS_TABLE);
+ }
+}
diff --git a/tests/text_reparser/plugins/test_row_based_plugin.php b/tests/text_reparser/plugins/test_row_based_plugin.php
new file mode 100644
index 0000000000..3e9ff09448
--- /dev/null
+++ b/tests/text_reparser/plugins/test_row_based_plugin.php
@@ -0,0 +1,150 @@
+<?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.
+*
+*/
+
+require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php';
+
+abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_test_case
+{
+ protected $db;
+
+ abstract protected function get_reparser();
+
+ protected function get_rows(array $ids)
+ {
+ $reparser = $this->get_reparser();
+ $columns = $reparser->get_columns();
+
+ $reflection_reparser = new ReflectionClass(get_class($reparser));
+ $table_property = $reflection_reparser->getProperty('table');
+ $table_property->setAccessible(true);
+
+ $sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text
+ FROM ' . $table_property->getValue($reparser) . '
+ WHERE ' . $this->db->sql_in_set($columns['id'], $ids) . '
+ ORDER BY id';
+ $result = $this->db->sql_query($sql);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ return $rows;
+ }
+
+ public function setUp()
+ {
+ global $config;
+ if (!isset($config))
+ {
+ $config = new \phpbb\config\config(array());
+ }
+ $this->get_test_case_helpers()->set_s9e_services();
+ $this->db = $this->new_dbal();
+ parent::setUp();
+ }
+
+ public function test_get_max_id()
+ {
+ $reparser = $this->get_reparser();
+ $this->assertEquals(1000, $reparser->get_max_id());
+ }
+
+ public function test_dry_run()
+ {
+ $old_rows = $this->get_rows(array(1));
+ $reparser = $this->get_reparser();
+ $reparser->disable_save();
+ $reparser->reparse_range(1, 1);
+ $new_rows = $this->get_rows(array(1));
+ $this->assertEquals($old_rows, $new_rows);
+ }
+
+ /**
+ * @dataProvider get_reparse_tests
+ */
+ public function test_reparse($min_id, $max_id, $expected)
+ {
+ $reparser = $this->get_reparser();
+ $reparser->reparse_range($min_id, $max_id);
+
+ $ids = array();
+ foreach ($expected as $row)
+ {
+ $ids[] = $row['id'];
+ }
+
+ $this->assertEquals($expected, $this->get_rows($ids));
+ }
+
+ public function get_reparse_tests()
+ {
+ return array(
+ array(
+ 2,
+ 5,
+ array(
+ array(
+ 'id' => '1',
+ 'text' => 'This row should be [b]ignored[/b]',
+ ),
+ array(
+ 'id' => '2',
+ 'text' => '<t>[b]Not bold[/b] :) http://example.org</t>',
+ ),
+ array(
+ 'id' => '3',
+ 'text' => '<r><B><s>[b]</s>Bold<e>[/b]</e></B> :) http://example.org</r>',
+ ),
+ array(
+ 'id' => '4',
+ 'text' => '<r>[b]Not bold[/b] <E>:)</E> http://example.org</r>',
+ ),
+ array(
+ 'id' => '5',
+ 'text' => '<r>[b]Not bold[/b] :) <URL url="http://example.org">http://example.org</URL></r>',
+ ),
+ array(
+ 'id' => '1000',
+ 'text' => 'This row should be [b]ignored[/b]',
+ ),
+ )
+ ),
+ array(
+ 6,
+ 7,
+ array(
+ array(
+ 'id' => '6',
+ 'text' => '<r><FLASH height="345" url="http://example.org/flash.swf" width="123"><s>[flash=123,345]</s>http://example.org/flash.swf<e>[/flash]</e></FLASH></r>',
+ ),
+ array(
+ 'id' => '7',
+ 'text' => '<t>[flash=123,345]http://example.org/flash.swf[/flash]</t>',
+ ),
+ )
+ ),
+ array(
+ 8,
+ 9,
+ array(
+ array(
+ 'id' => '8',
+ 'text' => '<r><IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG></r>',
+ ),
+ array(
+ 'id' => '9',
+ 'text' => '<t>[img]http://example.org/img.png[/img]</t>',
+ ),
+ )
+ ),
+ );
+ }
+}
diff --git a/tests/text_reparser/plugins/user_signature_test.php b/tests/text_reparser/plugins/user_signature_test.php
new file mode 100644
index 0000000000..5b66f2788a
--- /dev/null
+++ b/tests/text_reparser/plugins/user_signature_test.php
@@ -0,0 +1,26 @@
+<?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.
+*
+*/
+include_once __DIR__ . '/test_row_based_plugin.php';
+
+class phpbb_textreparser_user_signature_test extends phpbb_textreparser_test_row_based_plugin
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(__DIR__ . '/fixtures/users.xml');
+ }
+
+ protected function get_reparser()
+ {
+ return new \phpbb\textreparser\plugins\user_signature($this->db, USERS_TABLE);
+ }
+}
diff --git a/tests/tree/nestedset_forum_base.php b/tests/tree/nestedset_forum_base.php
index c56be1f81e..3daa75b2e4 100644
--- a/tests/tree/nestedset_forum_base.php
+++ b/tests/tree/nestedset_forum_base.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_tests_tree_nestedset_forum_base extends phpbb_database_test_case
{
public function getDataSet()
@@ -59,7 +57,6 @@ class phpbb_tests_tree_nestedset_forum_base extends phpbb_database_test_case
global $config;
$config = $this->config = new \phpbb\config\config(array('nestedset_forum_lock' => 0));
- set_config(null, null, null, $this->config);
$this->lock = new \phpbb\lock\db('nestedset_forum_lock', $this->config, $this->db);
$this->set = new \phpbb\tree\nestedset_forum($this->db, $this->lock, 'phpbb_forums');
diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php
new file mode 100644
index 0000000000..3501124fc1
--- /dev/null
+++ b/tests/ui/permission_roles_test.php
@@ -0,0 +1,90 @@
+<?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.
+*
+*/
+
+/**
+* @group ui
+*/
+class ui_permission_roles_test extends phpbb_ui_test_case
+{
+
+ public function test_permission_roles()
+ {
+ $this->login();
+ $this->admin_login();
+ $this->add_lang('acp/permissions');
+ $this->visit('adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid);
+
+ // Select forums
+ $elements = self::find_element('cssSelector', 'select#forum')
+ ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option'));
+
+ foreach ($elements as $element)
+ {
+ $element->click();
+ }
+ self::find_element('cssSelector', 'form#select_victim')
+ ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=submit]'))
+ ->click();
+
+ // Select administrators and guests
+ $groups_form = self::find_element('cssSelector', 'form#groups');
+ $elements = $groups_form
+ ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('select'))
+ ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option'));
+
+ foreach ($elements as $element)
+ {
+ if ($element->getText() === 'Administrators' || $element->getText() === 'Guests')
+ {
+ $element->click();
+ }
+ }
+ $groups_form->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[name=submit_edit_options]'))->click();
+
+ $first_fieldset = self::find_element('cssSelector', '#perm11');
+ $this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display'));
+ $first_fieldset
+ ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))
+ ->click();
+ $this->assertEquals('block', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display'));
+ $lis = $first_fieldset
+ ->findElements(\Facebook\WebDriver\WebDriverBy::cssSelector('ul > li'));
+
+ foreach ($lis as $li)
+ {
+ if ($li->getAttribute('data-id') == 18)
+ {
+ $li->click();
+
+ break;
+ }
+ }
+ $this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display'));
+ $this->assertEquals(18, $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value'));
+ $this->assertEquals($this->lang('ROLE_FORUM_LIMITED'), $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText());
+
+ // Check that admin settings didn't get changed
+ $second_fieldset = self::find_element('cssSelector', '#perm10');
+ $this->assertEquals('none', $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display'));
+ // Full access = 14
+ $this->assertEquals(14, $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value'));
+ $this->assertEquals($this->lang('ROLE_FORUM_FULL'), $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText());
+
+ // Check that category settings were not modified
+ $category_fieldset = self::find_element('cssSelector', '#perm00');
+ $this->assertEquals('none', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display'));
+ // No settings
+ $this->assertEquals('', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value'));
+ $this->assertEquals($this->lang('NO_ROLE_ASSIGNED'), $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText());
+ }
+}
diff --git a/tests/ui/quick_links_test.php b/tests/ui/quick_links_test.php
index 5bddb44a8b..582aeafcae 100644
--- a/tests/ui/quick_links_test.php
+++ b/tests/ui/quick_links_test.php
@@ -16,7 +16,6 @@
*/
class quick_links_test extends phpbb_ui_test_case
{
-
public function test_quick_links()
{
$this->visit('index.php');
diff --git a/tests/upload/filespec_test.php b/tests/upload/filespec_test.php
index ed28bcb38f..18b6deed1f 100644
--- a/tests/upload/filespec_test.php
+++ b/tests/upload/filespec_test.php
@@ -11,10 +11,6 @@
*
*/
-require_once __DIR__ . '/../../phpBB/includes/functions.php';
-require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php';
-require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';
-
class phpbb_filespec_test extends phpbb_test_case
{
const TEST_COUNT = 100;
@@ -23,14 +19,19 @@ class phpbb_filespec_test extends phpbb_test_case
const UPLOAD_MAX_FILESIZE = 1000;
private $config;
+ private $filesystem;
public $path;
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
protected function setUp()
{
// Global $config required by unique_id
- // Global $user required by filespec::additional_checks and
- // filespec::move_file
- global $config, $user;
+ global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
@@ -44,9 +45,6 @@ class phpbb_filespec_test extends phpbb_test_case
// See: phpBB/install/schemas/schema_data.sql
$config['mime_triggers'] = 'body|head|html|img|plaintext|a href|pre|script|table|title';
- $user = new phpbb_mock_user();
- $user->lang = new phpbb_mock_lang();
-
$this->config = &$config;
$this->path = __DIR__ . '/fixture/';
@@ -75,6 +73,17 @@ class phpbb_filespec_test extends phpbb_test_case
$guessers[2]->set_priority(-2);
$guessers[3]->set_priority(-2);
$this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers);
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ private function set_reflection_property(&$class, $property_name, $value)
+ {
+ $property = new ReflectionProperty($class, $property_name);
+ $property->setAccessible(true);
+ $property->setValue($class, $value);
}
private function get_filespec($override = array())
@@ -88,14 +97,13 @@ class phpbb_filespec_test extends phpbb_test_case
'error' => '',
);
- return new filespec(array_merge($upload_ary, $override), null, $this->mimetype_guesser);
+ $filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser);
+ return $filespec->set_upload_ary(array_merge($upload_ary, $override));
}
protected function tearDown()
{
- global $user;
$this->config = array();
- $user = null;
$iterator = new DirectoryIterator($this->path . 'copies');
foreach ($iterator as $fileinfo)
@@ -108,6 +116,13 @@ class phpbb_filespec_test extends phpbb_test_case
}
}
+ public function test_empty_upload_ary()
+ {
+ $filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser);
+ $this->assertInstanceOf('\phpbb\files\filespec', $filespec->set_upload_ary(array()));
+ $this->assertTrue($filespec->init_error());
+ }
+
public function additional_checks_variables()
{
// False here just indicates the file is too large and fails the
@@ -129,13 +144,26 @@ class phpbb_filespec_test extends phpbb_test_case
{
$upload = new phpbb_mock_fileupload();
$filespec = $this->get_filespec();
- $filespec->upload = $upload;
- $filespec->file_moved = true;
- $filespec->filesize = $filespec->get_filesize($this->path . $filename);
+ $filespec->set_upload_namespace($upload);
+ $this->set_reflection_property($filespec, 'file_moved', true);
+ $this->set_reflection_property($filespec, 'filesize', $filespec->get_filesize($this->path . $filename));
$this->assertEquals($expected, $filespec->additional_checks());
}
+ public function test_additional_checks_dimensions()
+ {
+ $upload = new phpbb_mock_fileupload();
+ $filespec = $this->get_filespec();
+ $filespec->set_upload_namespace($upload);
+ $upload->valid_dimensions = false;
+ $this->set_reflection_property($filespec, 'file_moved', true);
+ $upload->max_filesize = 0;
+
+ $this->assertEquals(false, $filespec->additional_checks());
+ $this->assertSame(array('WRONG_SIZE'), $filespec->error);
+ }
+
public function check_content_variables()
{
// False here indicates that a file is non-binary and contains
@@ -170,6 +198,7 @@ class phpbb_filespec_test extends phpbb_test_case
array($chunks[2] . $chunks[9]),
array($chunks[3] . $chunks[4]),
array($chunks[5] . $chunks[6]),
+ array('foobar.png'),
);
}
@@ -181,7 +210,7 @@ class phpbb_filespec_test extends phpbb_test_case
$bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
$filespec = $this->get_filespec(array('name' => $filename));
$filespec->clean_filename('real', self::PREFIX);
- $name = $filespec->realname;
+ $name = $filespec->get('realname');
$this->assertEquals(0, preg_match('/%(\w{2})/', $name));
foreach ($bad_chars as $char)
@@ -197,8 +226,8 @@ class phpbb_filespec_test extends phpbb_test_case
{
$filespec = $this->get_filespec();
$filespec->clean_filename('unique', self::PREFIX);
- $name = $filespec->realname;
-
+ $name = $filespec->get('realname');
+
$this->assertEquals(strlen($name), 32 + strlen(self::PREFIX));
$this->assertRegExp('#^[A-Za-z0-9]+$#', substr($name, strlen(self::PREFIX)));
$this->assertFalse(isset($filenames[$name]));
@@ -206,6 +235,55 @@ class phpbb_filespec_test extends phpbb_test_case
}
}
+ public function test_clean_filename_unique_ext()
+ {
+ $filenames = array();
+ for ($tests = 0; $tests < self::TEST_COUNT; $tests++)
+ {
+ $filespec = $this->get_filespec(array('name' => 'foobar.jpg'));
+ $filespec->clean_filename('unique_ext', self::PREFIX);
+ $name = $filespec->get('realname');
+
+ $this->assertEquals(strlen($name), 32 + strlen(self::PREFIX) + strlen('.jpg'));
+ $this->assertRegExp('#^[A-Za-z0-9]+\.jpg$#', substr($name, strlen(self::PREFIX)));
+ $this->assertFalse(isset($filenames[$name]));
+ $filenames[$name] = true;
+ }
+ }
+
+ public function data_clean_filename_avatar()
+ {
+ return array(
+ array(false, false, ''),
+ array('foobar.png', 'u5.png', 'avatar', 'u', 5),
+ array('foobar.png', 'g9.png', 'avatar', 'g', 9),
+
+ );
+ }
+
+ /**
+ * @dataProvider data_clean_filename_avatar
+ */
+ public function test_clean_filename_avatar($filename, $expected, $mode, $prefix = '', $user_id = '')
+ {
+ $filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser);
+
+ if ($filename)
+ {
+ $upload_ary = array(
+ 'name' => $filename,
+ 'type' => '',
+ 'size' => '',
+ 'tmp_name' => '',
+ 'error' => '',
+ );
+ $filespec->set_upload_ary($upload_ary);
+ }
+ $filespec->clean_filename($mode, $prefix, $user_id);
+
+ $this->assertSame($expected, $filespec->get('realname'));
+ }
+
public function get_extension_variables()
{
return array(
@@ -223,7 +301,7 @@ class phpbb_filespec_test extends phpbb_test_case
*/
public function test_get_extension($filename, $expected)
{
- $this->assertEquals($expected, filespec::get_extension($filename));
+ $this->assertEquals($expected, \phpbb\files\filespec::get_extension($filename));
}
public function is_image_variables()
@@ -286,7 +364,7 @@ class phpbb_filespec_test extends phpbb_test_case
array('txt_copy', 'txt_as_img', 'image/jpg', 'txt', false, true),
array('txt_copy_2', 'txt_moved', 'text/plain', 'txt', false, true),
array('jpg_copy', 'jpg_moved', 'image/png', 'jpg', false, true),
- array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH', true),
+ array('png_copy', 'png_moved', 'image/png', 'jpg', 'Image file type mismatch: expected extension png but extension jpg given.', true),
);
}
@@ -297,8 +375,7 @@ class phpbb_filespec_test extends phpbb_test_case
{
// Global $phpbb_root_path and $phpEx are required by phpbb_chmod
global $phpbb_root_path, $phpEx;
- $phpbb_root_path = '';
- $phpEx = 'php';
+ $this->phpbb_root_path = '';
$upload = new phpbb_mock_fileupload();
$upload->max_filesize = self::UPLOAD_MAX_FILESIZE;
@@ -308,18 +385,137 @@ class phpbb_filespec_test extends phpbb_test_case
'name' => $realname,
'type' => $mime_type,
));
- $filespec->extension = $extension;
- $filespec->upload = $upload;
- $filespec->local = true;
+ $this->set_reflection_property($filespec, 'extension', $extension);
+ $filespec->set_upload_namespace($upload);
+ $this->set_reflection_property($filespec, 'local', true);
$this->assertEquals($expected, $filespec->move_file($this->path . 'copies'));
- $this->assertEquals($filespec->file_moved, file_exists($this->path . 'copies/' . $realname));
+ $this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/' . $realname));
if ($error)
{
$this->assertEquals($error, $filespec->error[0]);
}
- $phpEx = '';
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ public function test_move_file_error()
+ {
+ $filespec = $this->get_filespec();
+ $this->assertFalse($filespec->move_file('foobar'));
+ $filespec->error[] = 'foo';
+ $this->assertFalse($filespec->move_file('foo'));
+ }
+
+ public function data_move_file_copy()
+ {
+ return array(
+ array('gif_copy', true, false, array()),
+ array('gif_copy', true, true, array()),
+ array('foo_bar', false, false, array('GENERAL_UPLOAD_ERROR')),
+ array('foo_bar', false, true, array('GENERAL_UPLOAD_ERROR')),
+ );
+ }
+
+ /**
+ * @dataProvider data_move_file_copy
+ */
+ public function test_move_file_copy($tmp_name, $move_success, $safe_mode_on, $expected_error)
+ {
+ // Initialise a blank filespec object for use with trivial methods
+ $upload_ary = array(
+ 'name' => 'gif_moved',
+ 'type' => 'image/gif',
+ 'size' => '',
+ 'tmp_name' => $this->path . 'copies/' . $tmp_name,
+ 'error' => '',
+ );
+
+ $php_ini = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper')
+ ->getMock();
+ $php_ini->expects($this->any())
+ ->method('getBool')
+ ->with($this->anything())
+ ->willReturn($safe_mode_on);
+ $upload = new phpbb_mock_fileupload();
+ $upload->max_filesize = self::UPLOAD_MAX_FILESIZE;
+ $filespec = new \phpbb\files\filespec($this->filesystem, $this->language, $php_ini, new \FastImageSize\FastImagesize, '', $this->mimetype_guesser);
+ $filespec->set_upload_ary($upload_ary);
+ $this->set_reflection_property($filespec, 'local', false);
+ $this->set_reflection_property($filespec, 'extension', 'gif');
+ $filespec->set_upload_namespace($upload);
+
+ $this->assertEquals($move_success, $filespec->move_file($this->path . 'copies'));
+ $this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/gif_moved'));
+ $this->assertSame($expected_error, $filespec->error);
+ }
+
+ public function data_move_file_imagesize()
+ {
+ return array(
+ array(
+ array(
+ 'width' => 2,
+ 'height' => 2,
+ 'type' => IMAGETYPE_GIF,
+ ),
+ array()
+ ),
+ array(
+ array(
+ 'width' => 2,
+ 'height' => 2,
+ 'type' => -1,
+ ),
+ array('Image file type -1 for mimetype image/gif not supported.')
+ ),
+ array(
+ array(
+ 'width' => 0,
+ 'height' => 0,
+ 'type' => IMAGETYPE_GIF,
+ ),
+ array('The image file you tried to attach is invalid.')
+ ),
+ array(
+ false,
+ array('It was not possible to determine the dimensions of the image. Please verify that the URL you entered is correct.')
+ )
+ );
+ }
+
+ /**
+ * @dataProvider data_move_file_imagesize
+ */
+ public function test_move_file_imagesize($imagesize_return, $expected_error)
+ {
+ // Initialise a blank filespec object for use with trivial methods
+ $upload_ary = array(
+ 'name' => 'gif_moved',
+ 'type' => 'image/gif',
+ 'size' => '',
+ 'tmp_name' => $this->path . 'copies/gif_copy',
+ 'error' => '',
+ );
+
+ $imagesize = $this->getMockBuilder('\FastImageSize\FastImageSize')
+ ->getMock();
+ $imagesize->expects($this->any())
+ ->method('getImageSize')
+ ->with($this->anything())
+ ->willReturn($imagesize_return);
+
+ $upload = new phpbb_mock_fileupload();
+ $upload->max_filesize = self::UPLOAD_MAX_FILESIZE;
+ $filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, $imagesize, '', $this->mimetype_guesser);
+ $filespec->set_upload_ary($upload_ary);
+ $this->set_reflection_property($filespec, 'local', false);
+ $this->set_reflection_property($filespec, 'extension', 'gif');
+ $filespec->set_upload_namespace($upload);
+
+ $this->assertEquals(true, $filespec->move_file($this->path . 'copies'));
+ $this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/gif_moved'));
+ $this->assertSame($expected_error, $filespec->error);
}
/**
@@ -333,6 +529,29 @@ class phpbb_filespec_test extends phpbb_test_case
$type_cast_helper->set_var($upload_name, $filename, 'string', true, true);
$filespec = $this->get_filespec(array('name'=> $upload_name));
- $this->assertSame(trim(utf8_basename(htmlspecialchars($filename))), $filespec->uploadname);
+ $this->assertSame(trim(utf8_basename(htmlspecialchars($filename))), $filespec->get('uploadname'));
+ }
+
+ public function test_is_uploaded()
+ {
+ $filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, null);
+ $reflection_filespec = new ReflectionClass($filespec);
+ $plupload_property = $reflection_filespec->getProperty('plupload');
+ $plupload_property->setAccessible(true);
+ $plupload_mock = $this->getMockBuilder('\phpbb\plupload\plupload')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $plupload_mock->expects($this->any())
+ ->method('is_active')
+ ->will($this->returnValue(true));
+ $plupload_property->setValue($filespec, $plupload_mock);
+ $is_uploaded = $reflection_filespec->getMethod('is_uploaded');
+
+ // Plupload is active and file does not exist
+ $this->assertFalse($is_uploaded->invoke($filespec));
+
+ // Plupload is not active and file was not uploaded
+ $plupload_property->setValue($filespec, null);
+ $this->assertFalse($is_uploaded->invoke($filespec));
}
}
diff --git a/tests/upload/fileupload_test.php b/tests/upload/fileupload_test.php
index fcfb84125d..fb72823f08 100644
--- a/tests/upload/fileupload_test.php
+++ b/tests/upload/fileupload_test.php
@@ -11,36 +11,88 @@
*
*/
-require_once __DIR__ . '/../../phpBB/includes/functions.php';
-require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php';
-require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';
require_once __DIR__ . '/../mock/filespec.php';
class phpbb_fileupload_test extends phpbb_test_case
{
private $path;
+ private $filesystem;
+
+ /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
+ protected $container;
+
+ /** @var \phpbb\files\factory */
+ protected $factory;
+
+ /** @var \bantu\IniGetWrapper\IniGetWrapper */
+ protected $php_ini;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var \phpbb\request\request_interface */
+ protected $request;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
protected function setUp()
{
// Global $config required by unique_id
- // Global $user required by several functions dealing with translations
- // Global $request required by form_upload, local_upload and is_valid
- global $config, $user, $request;
+ global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
- $config = array();
+ $config = new \phpbb\config\config(array());
}
$config['rand_seed'] = '';
$config['rand_seed_last_update'] = time() + 600;
- $user = new phpbb_mock_user();
- $user->lang = new phpbb_mock_lang();
-
- $request = new phpbb_mock_request();
+ $this->request = $this->getMock('\phpbb\request\request');
+ $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
+
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+ $guessers = array(
+ new \Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser(),
+ new \Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser(),
+ new \phpbb\mimetype\content_guesser(),
+ new \phpbb\mimetype\extension_guesser(),
+ );
+ $guessers[2]->set_priority(-2);
+ $guessers[3]->set_priority(-2);
+ $this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers);
+
+ $this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
+ $this->container->set('files.filespec', new \phpbb\files\filespec(
+ $this->filesystem,
+ $this->language,
+ $this->php_ini,
+ new \FastImageSize\FastImageSize(),
+ $phpbb_root_path,
+ new \phpbb\mimetype\guesser(array(
+ 'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
+ ))));
+ $this->factory = new \phpbb\files\factory($this->container);
+ $plupload = new \phpbb\plupload\plupload($phpbb_root_path, $config, $this->request, new \phpbb\user($this->language, '\phpbb\datetime'), $this->php_ini, $this->mimetype_guesser);
+ $this->container->set('files.types.form', new \phpbb\files\types\form(
+ $this->factory,
+ $this->language,
+ $this->php_ini,
+ $plupload,
+ $this->request
+ ), phpbb_mock_container_builder::SCOPE_PROTOTYPE);
+ $this->container->set('files.types.local', new \phpbb\files\types\local(
+ $this->factory,
+ $this->language,
+ $this->php_ini,
+ $this->request
+ ), phpbb_mock_container_builder::SCOPE_PROTOTYPE);
$this->path = __DIR__ . '/fixture/';
+ $this->phpbb_root_path = $phpbb_root_path;
}
private function gen_valid_filespec()
@@ -65,15 +117,38 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_common_checks_invalid_extension()
{
- $upload = new fileupload('', array('png'), 100);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('png'))
+ ->set_max_filesize(100);
$file = $this->gen_valid_filespec();
$upload->common_checks($file);
$this->assertEquals('DISALLOWED_EXTENSION', $file->error[0]);
}
+ public function test_common_checks_disallowed_content()
+ {
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(1000);
+ $file = new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path);
+ $file->set_upload_ary(array(
+ 'size' => 50,
+ 'tmp_name' => dirname(__FILE__) . '/fixture/disallowed',
+ 'name' => 'disallowed.jpg',
+ 'type' => 'image/jpg'
+ ))
+ ->set_upload_namespace($upload);
+ file_put_contents(dirname(__FILE__) . '/fixture/disallowed', '<body>' . file_get_contents(dirname(__FILE__) . '/fixture/jpg'));
+ $upload->common_checks($file);
+ $this->assertEquals('DISALLOWED_CONTENT', $file->error[0]);
+ unlink(dirname(__FILE__) . '/fixture/disallowed');
+ }
+
public function test_common_checks_invalid_filename()
{
- $upload = new fileupload('', array('jpg'), 100);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(100);
$file = $this->gen_valid_filespec();
$file->realname = 'invalid?';
$upload->common_checks($file);
@@ -82,7 +157,9 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_common_checks_too_large()
{
- $upload = new fileupload('', array('jpg'), 100);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(100);
$file = $this->gen_valid_filespec();
$file->filesize = 1000;
$upload->common_checks($file);
@@ -91,7 +168,9 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_common_checks_valid_file()
{
- $upload = new fileupload('', array('jpg'), 1000);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(1000);
$file = $this->gen_valid_filespec();
$upload->common_checks($file);
$this->assertEquals(0, sizeof($file->error));
@@ -99,33 +178,41 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_local_upload()
{
- $upload = new fileupload('', array('jpg'), 1000);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(1000);
copy($this->path . 'jpg', $this->path . 'jpg.jpg');
- $file = $upload->local_upload($this->path . 'jpg.jpg');
+ $file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');
$this->assertEquals(0, sizeof($file->error));
- unlink($this->path . 'jpg.jpg');
+ $this->assertFalse($file->additional_checks());
+ $this->assertTrue($file->move_file('../tests/upload/fixture/copies', true));
+ $file->remove();
}
public function test_move_existent_file()
{
- $upload = new fileupload('', array('jpg'), 1000);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(1000);
copy($this->path . 'jpg', $this->path . 'jpg.jpg');
- $file = $upload->local_upload($this->path . 'jpg.jpg');
+ $file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');
$this->assertEquals(0, sizeof($file->error));
$this->assertFalse($file->move_file('../tests/upload/fixture'));
- $this->assertFalse($file->file_moved);
+ $this->assertFalse($file->get('file_moved'));
$this->assertEquals(1, sizeof($file->error));
}
public function test_move_existent_file_overwrite()
{
- $upload = new fileupload('', array('jpg'), 1000);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(array('jpg'))
+ ->set_max_filesize(1000);
copy($this->path . 'jpg', $this->path . 'jpg.jpg');
copy($this->path . 'jpg', $this->path . 'copies/jpg.jpg');
- $file = $upload->local_upload($this->path . 'jpg.jpg');
+ $file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');
$this->assertEquals(0, sizeof($file->error));
$file->move_file('../tests/upload/fixture/copies', true);
$this->assertEquals(0, sizeof($file->error));
@@ -134,7 +221,10 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_valid_dimensions()
{
- $upload = new fileupload('', false, false, 1, 1, 100, 100);
+ $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
+ $upload->set_allowed_extensions(false)
+ ->set_max_filesize(false)
+ ->set_allowed_dimensions(1, 1, 100, 100);
$file1 = $this->gen_valid_filespec();
$file2 = $this->gen_valid_filespec();
diff --git a/tests/upload/fixture/bmp b/tests/upload/fixture/bmp
new file mode 100644
index 0000000000..04bff561ab
--- /dev/null
+++ b/tests/upload/fixture/bmp
Binary files differ
diff --git a/tests/upload/fixture/iff b/tests/upload/fixture/iff
new file mode 100644
index 0000000000..24eda8f593
--- /dev/null
+++ b/tests/upload/fixture/iff
Binary files differ
diff --git a/tests/upload/fixture/iff_maya b/tests/upload/fixture/iff_maya
new file mode 100644
index 0000000000..b6fb85101b
--- /dev/null
+++ b/tests/upload/fixture/iff_maya
Binary files differ
diff --git a/tests/upload/fixture/jp2 b/tests/upload/fixture/jp2
new file mode 100644
index 0000000000..adca6ecf0e
--- /dev/null
+++ b/tests/upload/fixture/jp2
Binary files differ
diff --git a/tests/upload/fixture/jpx b/tests/upload/fixture/jpx
new file mode 100644
index 0000000000..adca6ecf0e
--- /dev/null
+++ b/tests/upload/fixture/jpx
Binary files differ
diff --git a/tests/upload/fixture/psd b/tests/upload/fixture/psd
new file mode 100644
index 0000000000..d1bc9a6a70
--- /dev/null
+++ b/tests/upload/fixture/psd
Binary files differ
diff --git a/tests/upload/fixture/tif_compressed b/tests/upload/fixture/tif_compressed
new file mode 100644
index 0000000000..133b50c4f0
--- /dev/null
+++ b/tests/upload/fixture/tif_compressed
Binary files differ
diff --git a/tests/upload/fixture/tif_msb b/tests/upload/fixture/tif_msb
new file mode 100644
index 0000000000..32eb8abfbb
--- /dev/null
+++ b/tests/upload/fixture/tif_msb
Binary files differ
diff --git a/tests/upload/fixture/wbmp b/tests/upload/fixture/wbmp
new file mode 100644
index 0000000000..708c86ccee
--- /dev/null
+++ b/tests/upload/fixture/wbmp
Binary files differ
diff --git a/tests/upload/imagesize_test.php b/tests/upload/imagesize_test.php
new file mode 100644
index 0000000000..5429bb5c5e
--- /dev/null
+++ b/tests/upload/imagesize_test.php
@@ -0,0 +1,97 @@
+<?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.
+ *
+ */
+
+class phpbb_upload_imagesize_test extends \phpbb_test_case
+{
+ /** @var \FastImageSize\FastImageSize */
+ protected $imagesize;
+
+ /** @var string Path to fixtures */
+ protected $path;
+
+ public function setUp()
+ {
+ parent::setUp();
+ $this->imagesize = new \FastImageSize\FastImageSize();
+ $this->path = __DIR__ . '/fixture/';
+ }
+
+ public function data_get_imagesize()
+ {
+ return array(
+ array('foobar', 'image/bmp', false),
+ array('png', 'image/png', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)),
+ array('gif', 'image/png', false),
+ array('png', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)),
+ array('gif', 'image/gif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)),
+ array('jpg', 'image/gif', false),
+ array('gif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)),
+ array('jpg', 'image/jpg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)),
+ array('jpg', 'image/jpeg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)),
+ array('png', 'image/jpg', false),
+ array('jpg', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)),
+ array('psd', 'image/psd', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)),
+ array('psd', 'image/photoshop', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)),
+ array('jpg', 'image/psd', false),
+ array('psd', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)),
+ array('bmp', 'image/bmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)),
+ array('png', 'image/bmp', false),
+ array('bmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)),
+ array('tif', 'image/tif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
+ array('png', 'image/tif', false),
+ array('tif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
+ array('tif_compressed', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
+ array('png', 'image/tiff', false),
+ array('tif_compressed', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
+ array('tif_msb', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)),
+ array('tif_msb', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)),
+ array('wbmp', 'image/wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)),
+ array('wbmp', 'image/vnd.wap.wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)),
+ array('png', 'image/vnd.wap.wbmp', false),
+ array('wbmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)),
+ array('iff', 'image/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
+ array('iff', 'image/x-iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
+ array('iff_maya', 'iamge/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
+ array('png', 'image/iff', false),
+ array('png', 'image/x-iff', false),
+ array('iff', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
+ array('iff_maya', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
+ array('jp2', 'image/jp2', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
+ array('jp2', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
+ array('jp2', 'image/jpm', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
+ array('jpg', 'image/jp2', false),
+ array('jpx', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
+ array('jp2', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
+ array('jpx', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
+ );
+ }
+
+ /**
+ * @dataProvider data_get_imagesize
+ */
+ public function test_get_imagesize($file, $mime_type, $expected)
+ {
+ $this->assertEquals($expected, $this->imagesize->getImageSize($this->path . $file, $mime_type));
+ }
+
+ public function test_get_imagesize_remote()
+ {
+ $this->assertSame(array(
+ 'width' => 80,
+ 'height' => 80,
+ 'type' => IMAGETYPE_JPEG,
+ ),
+ $this->imagesize->getImageSize('https://secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg'));
+ }
+}
diff --git a/tests/user/lang_test.php b/tests/user/lang_test.php
deleted file mode 100644
index bb11bb63cb..0000000000
--- a/tests/user/lang_test.php
+++ /dev/null
@@ -1,119 +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.
-*
-*/
-
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
-class phpbb_user_lang_test extends phpbb_test_case
-{
- public function test_user_lang_sprintf()
- {
- $user = new \phpbb\user('\phpbb\datetime');
- $user->lang = array(
- 'FOO' => 'BAR',
- 'BARZ' => 'PENG',
- 'EMPTY' => '',
- 'ZERO' => '0',
- 'STR' => '%d %s, %d topics',
- 'STR2' => '%d foos',
- 'ARRY' => array(
- 0 => 'No posts', // 0
- 1 => '1 post', // 1
- 2 => '%d posts', // 2+
- ),
- 'ARRY_NO_ZERO' => array(
- 1 => '1 post', // 1
- 2 => '%d posts', // 0, 2+
- ),
- 'ARRY_MISSING' => array(
- 1 => '%d post', // 1
- //Missing second plural
- ),
- 'ARRY_FLOAT' => array(
- 1 => '1 post', // 1.x
- 2 => '%1$.1f posts', // 0.x, 2+.x
- ),
- 'ARRY_EMPTY' => array(
- ),
- 'dateformat' => array(
- 'AGO' => array(
- 1 => '%d second',
- 2 => '%d seconds',
- ),
- ),
- );
-
- // No param
- $this->assertEquals($user->lang('FOO'), 'BAR');
- $this->assertEquals($user->lang('EMPTY'), '');
- $this->assertEquals($user->lang('ZERO'), '0');
-
- // Invalid index
- $this->assertEquals($user->lang('VOID'), 'VOID');
-
- // Unnecessary param
- $this->assertEquals($user->lang('FOO', 2), 'BAR');
- $this->assertEquals($user->lang('FOO', 2, 3), 'BAR');
- $this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR');
-
- // String
- $this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics');
- $this->assertEquals($user->lang('STR2', 64), '64 foos');
-
- // Array
- $this->assertEquals($user->lang('ARRY', 0), 'No posts');
- $this->assertEquals($user->lang('ARRY', 1), '1 post');
- $this->assertEquals($user->lang('ARRY', 2), '2 posts');
- $this->assertEquals($user->lang('ARRY', 123), '123 posts');
-
- // Empty array returns the language key
- $this->assertEquals($user->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY');
-
- // No 0 key defined
- $this->assertEquals($user->lang('ARRY_NO_ZERO', 0), '0 posts');
- $this->assertEquals($user->lang('ARRY_NO_ZERO', 1), '1 post');
- $this->assertEquals($user->lang('ARRY_NO_ZERO', 2), '2 posts');
-
- // Array with missing keys
- $this->assertEquals($user->lang('ARRY_MISSING', 2), '2 post');
-
- // Floats as array key
- $this->assertEquals($user->lang('ARRY_FLOAT', 1.3), '1 post');
- $this->assertEquals($user->lang('ARRY_FLOAT', 2.0), '2.0 posts');
- $this->assertEquals($user->lang('ARRY_FLOAT', 2.51), '2.5 posts');
-
- // Use sub key, if first paramenter is an array
- $this->assertEquals($user->lang(array('dateformat', 'AGO'), 2), '2 seconds');
-
- // ticket PHPBB3-9949 - use first int to determinate the plural-form to use
- $this->assertEquals($user->lang('ARRY', 1, 2), '1 post');
- $this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post');
-
- // ticket PHPBB3-10345 - different plural rules, not just 0/1/2+
- $user = new \phpbb\user('\phpbb\datetime');
- $user->lang = array(
- 'PLURAL_RULE' => 13,
- 'ARRY' => array(
- 0 => '%d is 0', // 0
- 1 => '%d is 1', // 1
- 2 => '%d ends with 01-10', // ending with 01-10
- 3 => '%d ends with 11-19', // ending with 11-19
- 4 => '%d is part of the last rule', // everything else
- ),
- );
- $this->assertEquals($user->lang('ARRY', 0), '0 is 0');
- $this->assertEquals($user->lang('ARRY', 1), '1 is 1');
- $this->assertEquals($user->lang('ARRY', 103), '103 ends with 01-10');
- $this->assertEquals($user->lang('ARRY', 15), '15 ends with 11-19');
- $this->assertEquals($user->lang('ARRY', 300), '300 is part of the last rule');
- }
-}
diff --git a/tests/user/user_loader_test.php b/tests/user/user_loader_test.php
index 8d1f43707b..f871f324ca 100644
--- a/tests/user/user_loader_test.php
+++ b/tests/user/user_loader_test.php
@@ -11,8 +11,6 @@
*
*/
-include_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php');
-
class phpbb_user_loader_test extends phpbb_database_test_case
{
protected $db;
diff --git a/tests/utf/normalizer_test.php b/tests/utf/normalizer_test.php
deleted file mode 100644
index 50eafda859..0000000000
--- a/tests/utf/normalizer_test.php
+++ /dev/null
@@ -1,327 +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.
-*
-*/
-
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_normalizer.php';
-
-/**
-* @group slow
-*/
-class phpbb_utf_normalizer_test extends phpbb_test_case
-{
- static private $data_dir;
-
- static public function setUpBeforeClass()
- {
- self::$data_dir = dirname(__file__) . '/../tmp';
- self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', self::$data_dir);
- self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', self::$data_dir);
- }
-
- public function test_normalizer()
- {
- $test_suite = array(
- /**
- * NFC
- * c2 == NFC(c1) == NFC(c2) == NFC(c3)
- * c4 == NFC(c4) == NFC(c5)
- */
- 'NFC' => array(
- 'c2' => array('c1', 'c2', 'c3'),
- 'c4' => array('c4', 'c5')
- ),
-
- /**
- * NFD
- * c3 == NFD(c1) == NFD(c2) == NFD(c3)
- * c5 == NFD(c4) == NFD(c5)
- */
- 'NFD' => array(
- 'c3' => array('c1', 'c2', 'c3'),
- 'c5' => array('c4', 'c5')
- ),
-
- /**
- * NFKC
- * c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
- */
- 'NFKC' => array(
- 'c4' => array('c1', 'c2', 'c3', 'c4', 'c5')
- ),
-
- /**
- * NFKD
- * c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
- */
- 'NFKD' => array(
- 'c5' => array('c1', 'c2', 'c3', 'c4', 'c5')
- )
- );
-
- $tested_chars = array();
-
- $fp = fopen(self::$data_dir . '/NormalizationTest.txt', 'rb');
- while (!feof($fp))
- {
- $line = fgets($fp);
-
- if ($line[0] == '@')
- {
- continue;
- }
-
- if (!strpos(' 0123456789ABCDEF', $line[0]))
- {
- continue;
- }
-
- list($c1, $c2, $c3, $c4, $c5) = explode(';', $line);
-
- if (!strpos($c1, ' '))
- {
- /**
- * We are currently testing a single character, we add it to the list of
- * characters we have processed so that we can exclude it when testing
- * for invariants
- */
- $tested_chars[$c1] = 1;
- }
-
- foreach ($test_suite as $form => $serie)
- {
- foreach ($serie as $expected => $tests)
- {
- $hex_expected = ${$expected};
- $utf_expected = $this->hexseq_to_utf($hex_expected);
-
- foreach ($tests as $test)
- {
- $utf_result = $utf_expected;
- call_user_func_array(array('utf_normalizer', $form), array(&$utf_result));
-
- $hex_result = $this->utf_to_hexseq($utf_result);
- $this->assertEquals($utf_expected, $utf_result, "$expected == $form($test) ($hex_expected != $hex_result)");
- }
- }
- }
- }
- fclose($fp);
-
- return $tested_chars;
- }
-
- /**
- * @depends test_normalizer
- */
- public function test_invariants(array $tested_chars)
- {
- $fp = fopen(self::$data_dir . '/UnicodeData.txt', 'rb');
-
- while (!feof($fp))
- {
- $line = fgets($fp, 1024);
-
- if (!$pos = strpos($line, ';'))
- {
- continue;
- }
-
- $hex_tested = $hex_expected = substr($line, 0, $pos);
-
- if (isset($tested_chars[$hex_tested]))
- {
- continue;
- }
-
- $utf_expected = $this->hex_to_utf($hex_expected);
-
- if ($utf_expected >= UTF8_SURROGATE_FIRST
- && $utf_expected <= UTF8_SURROGATE_LAST)
- {
- /**
- * Surrogates are illegal on their own, we expect the normalizer
- * to return a replacement char
- */
- $utf_expected = UTF8_REPLACEMENT;
- $hex_expected = $this->utf_to_hexseq($utf_expected);
- }
-
- foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form)
- {
- $utf_result = $utf_expected;
- call_user_func_array(array('utf_normalizer', $form), array(&$utf_result));
- $hex_result = $this->utf_to_hexseq($utf_result);
-
- $this->assertEquals($utf_expected, $utf_result, "$hex_expected == $form($hex_tested) ($hex_expected != $hex_result)");
- }
- }
- fclose($fp);
- }
-
- /**
- * Convert a UTF string to a sequence of codepoints in hexadecimal
- *
- * @param string $utf UTF string
- * @return integer Unicode codepoints in hex
- */
- protected function utf_to_hexseq($str)
- {
- $pos = 0;
- $len = strlen($str);
- $ret = array();
-
- while ($pos < $len)
- {
- $c = $str[$pos];
- switch ($c & "\xF0")
- {
- case "\xC0":
- case "\xD0":
- $utf_char = substr($str, $pos, 2);
- $pos += 2;
- break;
-
- case "\xE0":
- $utf_char = substr($str, $pos, 3);
- $pos += 3;
- break;
-
- case "\xF0":
- $utf_char = substr($str, $pos, 4);
- $pos += 4;
- break;
-
- default:
- $utf_char = $c;
- ++$pos;
- }
-
- $hex = dechex($this->utf_to_cp($utf_char));
-
- if (!isset($hex[3]))
- {
- $hex = substr('000' . $hex, -4);
- }
-
- $ret[] = $hex;
- }
-
- return strtr(implode(' ', $ret), 'abcdef', 'ABCDEF');
- }
-
- /**
- * Convert a UTF-8 char to its codepoint
- *
- * @param string $utf_char UTF-8 char
- * @return integer Unicode codepoint
- */
- protected function utf_to_cp($utf_char)
- {
- switch (strlen($utf_char))
- {
- case 1:
- return ord($utf_char);
-
- case 2:
- return ((ord($utf_char[0]) & 0x1F) << 6) | (ord($utf_char[1]) & 0x3F);
-
- case 3:
- return ((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F);
-
- case 4:
- return ((ord($utf_char[0]) & 0x07) << 18) | ((ord($utf_char[1]) & 0x3F) << 12) | ((ord($utf_char[2]) & 0x3F) << 6) | (ord($utf_char[3]) & 0x3F);
-
- default:
- throw new RuntimeException('UTF-8 chars can only be 1-4 bytes long');
- }
- }
-
- /**
- * Return a UTF string formed from a sequence of codepoints in hexadecimal
- *
- * @param string $seq Sequence of codepoints, separated with a space
- * @return string UTF-8 string
- */
- protected function hexseq_to_utf($seq)
- {
- return implode('', array_map(array($this, 'hex_to_utf'), explode(' ', $seq)));
- }
-
- /**
- * Convert a codepoint in hexadecimal to a UTF-8 char
- *
- * @param string $hex Codepoint, in hexadecimal
- * @return string UTF-8 char
- */
- protected function hex_to_utf($hex)
- {
- return $this->cp_to_utf(hexdec($hex));
- }
-
- /**
- * Convert a codepoint to a UTF-8 char
- *
- * @param integer $cp Unicode codepoint
- * @return string UTF-8 string
- */
- protected function cp_to_utf($cp)
- {
- if ($cp > 0xFFFF)
- {
- return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
- }
- else if ($cp > 0x7FF)
- {
- return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
- }
- else if ($cp > 0x7F)
- {
- return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
- }
- else
- {
- return chr($cp);
- }
- }
-
- // chunked download helper
- static protected function download($url, $to)
- {
- $target = $to . '/' . basename($url);
-
- if (file_exists($target))
- {
- return;
- }
-
- if (!$fpr = fopen($url, 'rb'))
- {
- echo "Failed to download $url\n";
- return;
- }
-
- if (!$fpw = fopen($target, 'wb'))
- {
- echo "Failed to open $target for writing\n";
- return;
- }
-
- $chunk = 32768;
-
- while (!feof($fpr))
- {
- fwrite($fpw, fread($fpr, $chunk));
- }
- fclose($fpr);
- fclose($fpw);
- }
-}
diff --git a/tests/utf/utf8_clean_string_test.php b/tests/utf/utf8_clean_string_test.php
index 2bb65387e0..4b3c8a5a25 100644
--- a/tests/utf/utf8_clean_string_test.php
+++ b/tests/utf/utf8_clean_string_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_utf_utf8_clean_string_test extends phpbb_test_case
{
public function cleanable_strings()
diff --git a/tests/utf/utf8_wordwrap_test.php b/tests/utf/utf8_wordwrap_test.php
index ab053e2911..8906595d33 100644
--- a/tests/utf/utf8_wordwrap_test.php
+++ b/tests/utf/utf8_wordwrap_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
-
class phpbb_utf_utf8_wordwrap_test extends phpbb_test_case
{
public function test_utf8_wordwrap_ascii()
diff --git a/tests/version/version_fetch_test.php b/tests/version/version_fetch_test.php
index cfc87183cf..6ecc9b7223 100644
--- a/tests/version/version_fetch_test.php
+++ b/tests/version/version_fetch_test.php
@@ -28,13 +28,15 @@ class phpbb_version_helper_fetch_test extends phpbb_test_case
->disableOriginalConstructor()
->getMock();
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+
$this->version_helper = new \phpbb\version_helper(
$this->cache,
new \phpbb\config\config(array(
'version' => '3.1.0',
)),
new \phpbb\file_downloader(),
- new \phpbb\user('\phpbb\datetime')
+ new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime')
);
}
diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php
index 65ae7646b9..724c4c970c 100644
--- a/tests/version/version_helper_remote_test.php
+++ b/tests/version/version_helper_remote_test.php
@@ -30,20 +30,22 @@ class version_helper_remote_test extends \phpbb_test_case
));
$container = new \phpbb_mock_container_builder();
$db = new \phpbb\db\driver\factory($container);
- $this->cache = $this->getMock('\phpbb\cache\service', array('get'), array(new \phpbb\cache\driver\null(), $config, $db, '../../', 'php'));
+ $this->cache = $this->getMock('\phpbb\cache\service', array('get'), array(new \phpbb\cache\driver\dummy(), $config, $db, '../../', 'php'));
$this->cache->expects($this->any())
->method('get')
->with($this->anything())
->will($this->returnValue(false));
$this->file_downloader = new phpbb_mock_file_downloader();
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+
$this->version_helper = new \phpbb\version_helper(
$this->cache,
$config,
$this->file_downloader,
- new \phpbb\user('\phpbb\datetime')
+ new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime')
);
- $this->user = new \phpbb\user('\phpbb\datetime');
+ $this->user = new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime');
$this->user->add_lang('acp/common');
}
diff --git a/tests/version/version_test.php b/tests/version/version_test.php
index 528f1602d6..05577f6a18 100644
--- a/tests/version/version_test.php
+++ b/tests/version/version_test.php
@@ -25,13 +25,15 @@ class phpbb_version_helper_test extends phpbb_test_case
->disableOriginalConstructor()
->getMock();
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+
$this->version_helper = new \phpbb\version_helper(
$this->cache,
new \phpbb\config\config(array(
'version' => '3.1.0',
)),
new \phpbb\file_downloader(),
- new \phpbb\user('\phpbb\datetime')
+ new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime')
);
}
@@ -199,6 +201,11 @@ class phpbb_version_helper_test extends phpbb_test_case
*/
public function test_get_suggested_updates($current_version, $versions, $expected)
{
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+
$version_helper = $this
->getMockBuilder('\phpbb\version_helper')
->setMethods(array(
@@ -210,7 +217,7 @@ class phpbb_version_helper_test extends phpbb_test_case
'version' => $current_version,
)),
new \phpbb\file_downloader(),
- new \phpbb\user('\phpbb\datetime'),
+ new \phpbb\user($lang, '\phpbb\datetime'),
))
->getMock()
;
@@ -310,6 +317,11 @@ class phpbb_version_helper_test extends phpbb_test_case
*/
public function test_get_latest_on_current_branch($current_version, $versions, $expected)
{
+ global $phpbb_root_path, $phpEx;
+
+ $lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+ $lang = new \phpbb\language\language($lang_loader);
+
$version_helper = $this
->getMockBuilder('\phpbb\version_helper')
->setMethods(array(
@@ -321,7 +333,7 @@ class phpbb_version_helper_test extends phpbb_test_case
'version' => $current_version,
)),
new \phpbb\file_downloader(),
- new \phpbb\user('\phpbb\datetime'),
+ new \phpbb\user($lang, '\phpbb\datetime'),
))
->getMock()
;
diff --git a/tests/viewonline/helper_test.php b/tests/viewonline/helper_test.php
index bbbed59de7..6540d33287 100644
--- a/tests/viewonline/helper_test.php
+++ b/tests/viewonline/helper_test.php
@@ -17,7 +17,7 @@ class phpbb_viewonline_helper_test extends phpbb_test_case
{
parent::setUp();
- $this->viewonline_helper = new \phpbb\viewonline_helper(new \phpbb\filesystem());
+ $this->viewonline_helper = new \phpbb\viewonline_helper(new \phpbb\filesystem\filesystem());
}
public function session_pages_data()
diff --git a/tests/wrapper/gmgetdate_test.php b/tests/wrapper/gmgetdate_test.php
index 2e55a78d21..08ee491c0f 100644
--- a/tests/wrapper/gmgetdate_test.php
+++ b/tests/wrapper/gmgetdate_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_wrapper_gmgetdate_test extends phpbb_test_case
{
public static function phpbb_gmgetdate_data()
diff --git a/tests/wrapper/mt_rand_test.php b/tests/wrapper/mt_rand_test.php
index d190182286..8d370dee2a 100644
--- a/tests/wrapper/mt_rand_test.php
+++ b/tests/wrapper/mt_rand_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_wrapper_mt_rand_test extends phpbb_test_case
{
public function test_max_equals_min()
diff --git a/tests/wrapper/phpbb_php_ini_fake.php b/tests/wrapper/phpbb_php_ini_fake.php
index f218ff6d03..300ce30cfe 100644
--- a/tests/wrapper/phpbb_php_ini_fake.php
+++ b/tests/wrapper/phpbb_php_ini_fake.php
@@ -11,7 +11,7 @@
*
*/
-class phpbb_php_ini_fake extends \phpbb\php\ini
+class phpbb_php_ini_fake extends \bantu\IniGetWrapper\IniGetWrapper
{
function get($varname)
{
diff --git a/tests/wrapper/phpbb_php_ini_test.php b/tests/wrapper/phpbb_php_ini_test.php
index 27c2487f0a..5827744702 100644
--- a/tests/wrapper/phpbb_php_ini_test.php
+++ b/tests/wrapper/phpbb_php_ini_test.php
@@ -12,10 +12,10 @@
*/
require_once dirname(__FILE__) . '/phpbb_php_ini_fake.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case
{
+ /** @var \phpbb_php_ini_fake php_ini */
protected $php_ini;
public function setUp()
@@ -25,44 +25,44 @@ class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case
public function test_get_string()
{
- $this->assertSame(false, $this->php_ini->get_string(false));
- $this->assertSame('phpbb', $this->php_ini->get_string(' phpbb '));
+ $this->assertSame('', $this->php_ini->getString(false));
+ $this->assertSame('phpbb', $this->php_ini->getString(' phpbb '));
}
public function test_get_bool()
{
- $this->assertSame(true, $this->php_ini->get_bool('ON'));
- $this->assertSame(true, $this->php_ini->get_bool('on'));
- $this->assertSame(true, $this->php_ini->get_bool('1'));
+ $this->assertSame(true, $this->php_ini->getBool('ON'));
+ $this->assertSame(true, $this->php_ini->getBool('on'));
+ $this->assertSame(true, $this->php_ini->getBool('1'));
- $this->assertSame(false, $this->php_ini->get_bool('OFF'));
- $this->assertSame(false, $this->php_ini->get_bool('off'));
- $this->assertSame(false, $this->php_ini->get_bool('0'));
- $this->assertSame(false, $this->php_ini->get_bool(''));
+ $this->assertSame(false, $this->php_ini->getBool('OFF'));
+ $this->assertSame(false, $this->php_ini->getBool('off'));
+ $this->assertSame(false, $this->php_ini->getBool('0'));
+ $this->assertSame(false, $this->php_ini->getBool(''));
}
public function test_get_int()
{
- $this->assertSame(1234, $this->php_ini->get_int('1234'));
- $this->assertSame(-12345, $this->php_ini->get_int('-12345'));
- $this->assertSame(false, $this->php_ini->get_int('phpBB'));
+ $this->assertSame(1234, $this->php_ini->getNumeric('1234'));
+ $this->assertSame(-12345, $this->php_ini->getNumeric('-12345'));
+ $this->assertSame(null, $this->php_ini->getNumeric('phpBB'));
}
public function test_get_float()
{
- $this->assertSame(1234.0, $this->php_ini->get_float('1234'));
- $this->assertSame(-12345.0, $this->php_ini->get_float('-12345'));
- $this->assertSame(false, $this->php_ini->get_float('phpBB'));
+ $this->assertSame(1234.0, $this->php_ini->getNumeric('1234.0'));
+ $this->assertSame(-12345.0, $this->php_ini->getNumeric('-12345.0'));
+ $this->assertSame(null, $this->php_ini->getNumeric('phpBB'));
}
public function test_get_bytes_invalid()
{
- $this->assertSame(false, $this->php_ini->get_bytes(false));
- $this->assertSame(false, $this->php_ini->get_bytes('phpBB'));
- $this->assertSame(false, $this->php_ini->get_bytes('k'));
- $this->assertSame(false, $this->php_ini->get_bytes('-k'));
- $this->assertSame(false, $this->php_ini->get_bytes('M'));
- $this->assertSame(false, $this->php_ini->get_bytes('-M'));
+ $this->assertSame(null, $this->php_ini->getBytes(false));
+ $this->assertSame(null, $this->php_ini->getBytes('phpBB'));
+ $this->assertSame(null, $this->php_ini->getBytes('k'));
+ $this->assertSame(null, $this->php_ini->getBytes('-k'));
+ $this->assertSame(null, $this->php_ini->getBytes('M'));
+ $this->assertSame(null, $this->php_ini->getBytes('-M'));
}
/**
@@ -70,7 +70,7 @@ class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case
*/
public function test_get_bytes($expected, $value)
{
- $actual = $this->php_ini->get_bytes($value);
+ $actual = $this->php_ini->getBytes($value);
$this->assertTrue(is_float($actual) || is_int($actual));
$this->assertEquals($expected, $actual);
diff --git a/tests/wrapper/version_compare_test.php b/tests/wrapper/version_compare_test.php
index 93d9e0117d..8260d99504 100644
--- a/tests/wrapper/version_compare_test.php
+++ b/tests/wrapper/version_compare_test.php
@@ -11,8 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
class phpbb_wrapper_version_compare_test extends phpbb_test_case
{
public function test_two_parameters()
diff --git a/travis/check-executable-files.sh b/travis/check-executable-files.sh
index 4d420add1c..1aa8dca073 100755
--- a/travis/check-executable-files.sh
+++ b/travis/check-executable-files.sh
@@ -12,10 +12,11 @@ set -e
DB=$1
TRAVIS_PHP_VERSION=$2
-root="$3"
+NOTESTS=$3
+root="$4"
path="${root}phpBB/"
-if [ "$TRAVIS_PHP_VERSION" == "5.3.3" -a "$DB" == "mysqli" ]
+if [ "$NOTESTS" == '1' ]
then
# Check the permissions of the files
@@ -27,7 +28,7 @@ then
files_skipped="-false"
# Files which have to be executable
- executable_files="-path ${path}bin/*"
+ executable_files="-path ${path}bin/* -o -path ${path}install/phpbbcli.php"
incorrect_files=$( \
find ${path} \
diff --git a/travis/check-image-icc-profiles.sh b/travis/check-image-icc-profiles.sh
index 5926962d40..05c7de2d27 100755
--- a/travis/check-image-icc-profiles.sh
+++ b/travis/check-image-icc-profiles.sh
@@ -12,8 +12,9 @@ set -e
DB=$1
TRAVIS_PHP_VERSION=$2
+NOTESTS=$3
-if [ "$TRAVIS_PHP_VERSION" == "5.3.3" -a "$DB" == "mysqli" ]
+if [ "$NOTESTS" == '1' ]
then
find . -type f -a -iregex '.*\.\(gif\|jpg\|jpeg\|png\)$' -a -not -wholename '*vendor/*' | \
parallel --gnu --keep-order 'phpBB/develop/strip_icc_profiles.sh {}'
diff --git a/travis/check-sami-parse-errors.sh b/travis/check-sami-parse-errors.sh
index c3338e34db..4cc2cee525 100755
--- a/travis/check-sami-parse-errors.sh
+++ b/travis/check-sami-parse-errors.sh
@@ -12,8 +12,9 @@ set -e
DB=$1
TRAVIS_PHP_VERSION=$2
+NOTESTS=$3
-if [ "$TRAVIS_PHP_VERSION" == "5.3.3" -a "$DB" == "mysqli" ]
+if [ "$NOTESTS" == '1' ]
then
# Workarounds for
# https://github.com/fabpot/Sami/issues/116
diff --git a/travis/ext-sniff.sh b/travis/ext-sniff.sh
index 4e557a41c1..ca4d2115ba 100755
--- a/travis/ext-sniff.sh
+++ b/travis/ext-sniff.sh
@@ -10,12 +10,13 @@
#
set -e
set -x
-
+
DB=$1
TRAVIS_PHP_VERSION=$2
EXTNAME=$3
+NOTESTS=$4
-if [ "$TRAVIS_PHP_VERSION" == "5.5" -a "$DB" == "mysqli" ]
+if [ "$NOTESTS" == "1" ]
then
phpBB/vendor/bin/phpcs \
-s \
diff --git a/travis/install-phpbb-test-dependencies.sh b/travis/install-phpbb-test-dependencies.sh
deleted file mode 100755
index 25743ff2b1..0000000000
--- a/travis/install-phpbb-test-dependencies.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-#
-# 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.
-#
-set -e
-set -x
-
-cd tests
-php ../composer.phar install --dev --no-interaction --prefer-source
-cd ..
diff --git a/travis/phing-sniff.sh b/travis/phing-sniff.sh
index 660d1764c2..3f43b64130 100755
--- a/travis/phing-sniff.sh
+++ b/travis/phing-sniff.sh
@@ -13,8 +13,9 @@ set -x
DB=$1
TRAVIS_PHP_VERSION=$2
+NOTESTS=$3
-if [ "$TRAVIS_PHP_VERSION" == "5.5" -a "$DB" == "mysqli" ]
+if [ "$NOTESTS" == '1' ]
then
cd build
../phpBB/vendor/bin/phing sniff
diff --git a/travis/setup-database.sh b/travis/setup-database.sh
index 4ba9157d9d..3771f19073 100755
--- a/travis/setup-database.sh
+++ b/travis/setup-database.sh
@@ -13,6 +13,12 @@ set -x
DB=$1
TRAVIS_PHP_VERSION=$2
+NOTESTS=$3
+
+if [ "$NOTESTS" == '1' ]
+then
+ exit 0
+fi
if [ "$DB" == "postgres" ]
then
@@ -20,7 +26,7 @@ then
psql -c 'create database phpbb_tests;' -U postgres
fi
-if [ "$TRAVIS_PHP_VERSION" == "5.3" -a "$DB" == "mysqli" ]
+if [ "$TRAVIS_PHP_VERSION" == "5.4" -a "$DB" == "mysqli" ]
then
mysql -e 'SET GLOBAL storage_engine=MyISAM;'
fi
diff --git a/travis/setup-phpbb.sh b/travis/setup-phpbb.sh
index 4daa754481..f9fd9522ca 100755
--- a/travis/setup-phpbb.sh
+++ b/travis/setup-phpbb.sh
@@ -13,8 +13,9 @@ set -x
DB=$1
TRAVIS_PHP_VERSION=$2
+NOTESTS=$3
-if [ "$TRAVIS_PHP_VERSION" == "5.3.3" -a "$DB" == "mysqli" ]
+if [ "$NOTESTS" == '1' ]
then
travis/setup-exiftool.sh
travis/setup-unbuffer.sh
@@ -25,22 +26,16 @@ then
travis/setup-mariadb.sh
fi
-if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]
+if [ "$NOTESTS" != '1' -a "$TRAVIS_PHP_VERSION" != "hhvm" ]
then
travis/setup-php-extensions.sh
fi
-if [ `php -r "echo (int) version_compare(PHP_VERSION, '5.3.19', '>=');"` == "1" ]
+if [ "$NOTESTS" != '1' ]
then
travis/setup-webserver.sh
- travis/install-phpbb-test-dependencies.sh
fi
cd phpBB
-if [ `php -r "echo (int) version_compare(PHP_VERSION, '5.3.4', '<');"` == "1" ]
-then
- php ../composer.phar config disable-tls true
-fi
php ../composer.phar install --dev --no-interaction
-
cd ..
diff --git a/travis/setup-webserver.sh b/travis/setup-webserver.sh
index 911ba12f3c..3369d740fe 100755
--- a/travis/setup-webserver.sh
+++ b/travis/setup-webserver.sh
@@ -57,20 +57,12 @@ else
fi
# nginx
-echo "
- server {
- listen 80;
- root $PHPBB_ROOT_PATH/;
- index index.php index.html;
-
- location ~ \.php {
- include fastcgi_params;
- fastcgi_split_path_info ^(.+\.php)(/.*)$;
- fastcgi_param PATH_INFO \$fastcgi_path_info;
- fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
- fastcgi_pass unix:$APP_SOCK;
- }
- }
-" | sudo tee $NGINX_CONF > /dev/null
+cat $DIR/../phpBB/docs/nginx.sample.conf \
+| sed "s/root \/path\/to\/phpbb/root $(echo $PHPBB_ROOT_PATH | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g')/g" \
+| sed -e '1,/The actual board domain/d' \
+| sed -e '/If running php as fastcgi/,$d' \
+| sed -e "s/fastcgi_pass php;/fastcgi_pass unix:$(echo $APP_SOCK | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g');/g" \
+| sed -e 's/#listen 80/listen 80/' \
+| sudo tee $NGINX_CONF
sudo service nginx start
diff --git a/vagrant/after.sh b/vagrant/after.sh
new file mode 100755
index 0000000000..aadb7e7492
--- /dev/null
+++ b/vagrant/after.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+PHPBB_PATH="/home/vagrant/phpbb"
+PHPBB_CONFIG="${PHPBB_PATH}/phpBB/config.php"
+PHPBB_INSTALL="${PHPBB_PATH}/vagrant/phpbb-install-config.yml"
+
+# Ensure composer deps are installed
+cd ${PHPBB_PATH}/phpBB
+php ../composer.phar install
+
+# Backup current config.php file
+if [ -e ${PHPBB_CONFIG} ]
+then
+ cp --backup=numbered ${PHPBB_CONFIG} ${PHPBB_CONFIG}.bak
+fi
+
+# Delete any sqlite db and config file
+rm -rf /tmp/phpbb.sqlite3
+rm -rf ${PHPBB_CONFIG}
+
+# Install phpBB
+php ${PHPBB_PATH}/phpBB/install/phpbbcli.php install ${PHPBB_INSTALL}
+
+# Update sqlite db file permissions
+sudo chown -R vagrant /tmp/phpbb.sqlite3
+
+# Add DEBUG mode to phpBB to remove annoying installer warnings
+sed -i "$ a @define('DEBUG', true);" ${PHPBB_CONFIG}
+
+# Update the PHP memory limits (enough to allow phpunit tests to run)
+sed -i "s/memory_limit = .*/memory_limit = 1024M/" /etc/php5/fpm/php.ini
+
+echo "Your board is ready at http://192.168.10.10/"
diff --git a/vagrant/bootstrap.yaml b/vagrant/bootstrap.yaml
new file mode 100644
index 0000000000..1c2b265712
--- /dev/null
+++ b/vagrant/bootstrap.yaml
@@ -0,0 +1,40 @@
+---
+ip: "192.168.10.10"
+memory: 2048
+cpus: 1
+hostname: phpbb
+name: phpbb
+provider: virtualbox
+
+authorize: ~/.ssh/id_rsa.pub
+
+keys:
+ - ~/.ssh/id_rsa
+
+folders:
+ - map: "."
+ to: "/home/vagrant/phpbb"
+
+sites:
+ - map: phpbb.app
+ to: "/home/vagrant/phpbb/phpBB"
+
+databases:
+ - phpbb
+
+variables:
+ - key: APP_ENV
+ value: local
+
+# blackfire:
+# - id: foo
+# token: bar
+# client-id: foo
+# client-token: bar
+
+# ports:
+# - send: 50000
+# to: 5000
+# - send: 7777
+# to: 777
+# protocol: udp
diff --git a/vagrant/phpbb-install-config.yml b/vagrant/phpbb-install-config.yml
new file mode 100644
index 0000000000..023d7b1a9d
--- /dev/null
+++ b/vagrant/phpbb-install-config.yml
@@ -0,0 +1,51 @@
+installer:
+ admin:
+ name: admin
+ password: adminadmin
+ email: admin@example.org
+
+ board:
+ lang: en
+ name: phpBB Dev Board
+ description: My phpBB development board
+
+ database:
+ dbms: mysqli
+ dbhost: 127.0.0.1
+ dbport: ~
+ dbuser: homestead
+ dbpasswd: secret
+ dbname: phpbb
+ table_prefix: phpbb_
+# database:
+# dbms: postgres
+# dbhost: 127.0.0.1
+# dbport: 5432
+# dbuser: homestead
+# dbpasswd: secret
+# dbname: phpbb
+# table_prefix: phpbb_
+# database:
+# dbms: sqlite3
+# dbhost: /tmp/phpbb.sqlite3
+# dbport: ~
+# dbuser: ~
+# dbpasswd: ~
+# dbname: phpbb
+# table_prefix: phpbb_
+
+ email:
+ enabled: false
+ smtp_delivery : ~
+ smtp_host: ~
+ smtp_auth: ~
+ smtp_user: ~
+ smtp_pass: ~
+
+ server:
+ cookie_secure: false
+ server_protocol: http://
+ force_server_vars: false
+ server_name: 192.168.10.10
+ server_port: 80
+ script_path: /