diff --git a/phpBB/adm/style/acp_ban.html b/phpBB/adm/style/acp_ban.html index acb6e46df1..bc326345b0 100644 --- a/phpBB/adm/style/acp_ban.html +++ b/phpBB/adm/style/acp_ban.html @@ -97,11 +97,11 @@
-
+
-
+

diff --git a/phpBB/adm/style/acp_groups.html b/phpBB/adm/style/acp_groups.html index c90a075f9e..5df8a16a39 100644 --- a/phpBB/adm/style/acp_groups.html +++ b/phpBB/adm/style/acp_groups.html @@ -74,6 +74,10 @@


{L_GROUP_MESSAGE_LIMIT_EXPLAIN}
+
+

{L_GROUP_MAX_RECIPIENTS_EXPLAIN}
+
+

{L_GROUP_COLOR_EXPLAIN}
  [ {L_COLOUR_SWATCH} ]
diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index bad15bef30..3bfa7602c7 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -21,6 +21,13 @@ + +
+

{L_WARNING}

+

{L_WRITABLE_CONFIG}

+
+ + diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index a1363fce8d..bebbdb4235 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -261,11 +261,11 @@ « {L_BACK} - +

{L_TEMPLATE_CACHE}

- +

{L_TEMPLATE_CACHE_EXPLAIN}

- +
{L_TEMPLATE_CACHE} @@ -283,7 +283,7 @@
- + @@ -361,7 +361,7 @@

- + @@ -461,6 +461,12 @@
{COPYRIGHT}
+ +
+
+
{S_SUPERTEMPLATE}
+
+
@@ -475,11 +481,11 @@
{IMAGESET_NAME}
- +
-

{L_LOCATION_EXPLAIN}
-
-
+

{L_LOCATION_DISABLED_EXPLAIN}{L_LOCATION_EXPLAIN}
+
+
@@ -507,7 +513,7 @@ {S_FORM_TOKEN} - + diff --git a/phpBB/adm/style/acp_users.html b/phpBB/adm/style/acp_users.html index 2e4b3ef8f2..34e4147356 100644 --- a/phpBB/adm/style/acp_users.html +++ b/phpBB/adm/style/acp_users.html @@ -197,7 +197,7 @@ {S_ON_PAGE}{PAGINATION} - +

{L_MARK_ALL}{L_UNMARK_ALL}

@@ -215,7 +215,7 @@
- {L_SELECT_FORUM}: + {L_SELECT_FORUM}: {S_FORM_TOKEN}
diff --git a/phpBB/adm/style/acp_users_overview.html b/phpBB/adm/style/acp_users_overview.html index 0611ccba46..e3eff369cc 100644 --- a/phpBB/adm/style/acp_users_overview.html +++ b/phpBB/adm/style/acp_users_overview.html @@ -30,7 +30,7 @@
-
{USER_POSTS}
+
{USER_POSTS} ({L_POSTS_IN_QUEUE}) ({L_POSTS_IN_QUEUE})
@@ -138,7 +138,7 @@

- + diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 8e6f0b7295..219ff20eba 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -1333,18 +1333,21 @@ fieldset.permissions .permissions-switch { fieldset.permissions .padding { } +.permissions-switch { + margin-top: -6px; + font-size: .9em; +} + .permissions-switch a { text-decoration: underline; - font-size: 0.90em; } .permissions-reset { - margin-top: -6px; padding-bottom: 10px; } .permissions-reset a { - font-size: .8em; + font-size: .85em; } /* Tabbed menu */ diff --git a/phpBB/adm/style/install_update.html b/phpBB/adm/style/install_update.html index 318795f4cf..2448f1d39b 100644 --- a/phpBB/adm/style/install_update.html +++ b/phpBB/adm/style/install_update.html @@ -186,7 +186,7 @@

{L_NO_UPDATE_FILES_EXPLAIN}


{NO_UPDATE_FILES} - + @@ -226,7 +226,7 @@
- +
@@ -295,7 +295,7 @@

{L_UPDATE_METHOD_EXPLAIN}

-     +    
@@ -360,9 +360,18 @@

{L_CONNECTION_SUCCESS}

+
+

{L_TRY_DOWNLOAD_METHOD}

+ +
+ +
+
+

{L_CONNECTION_FAILED}
{ERROR_MSG}

+
@@ -378,7 +387,7 @@
- +
{S_HIDDEN_FIELDS} diff --git a/phpBB/adm/style/overall_header.html b/phpBB/adm/style/overall_header.html index 6fd34ac678..0720519ce2 100644 --- a/phpBB/adm/style/overall_header.html +++ b/phpBB/adm/style/overall_header.html @@ -185,7 +185,7 @@ function switch_menu() diff --git a/phpBB/common.php b/phpBB/common.php index 4fca1be2b4..c4a3160102 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -103,7 +103,7 @@ if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) } else { - set_magic_quotes_runtime(0); + @set_magic_quotes_runtime(0); // Be paranoid with passed vars if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on' || !function_exists('ini_get')) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 5f583648bf..3c8e5275a0 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1140,6 +1140,7 @@ function get_schema_struct() 'group_sig_chars' => array('UINT', 0), 'group_receive_pm' => array('BOOL', 0), 'group_message_limit' => array('UINT', 0), + 'group_max_recipients' => array('UINT', 0), 'group_legend' => array('BOOL', 1), ), 'PRIMARY_KEY' => 'group_id', @@ -1608,6 +1609,8 @@ function get_schema_struct() 'template_path' => array('VCHAR:100', ''), 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), 'template_storedb' => array('BOOL', 0), + 'template_inherits_id' => array('UINT:4', 0), + 'template_inherit_path' => array('VCHAR', ''), ), 'PRIMARY_KEY' => 'template_id', 'KEYS' => array( diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index ea64a1a94f..82fbfb09eb 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -477,7 +477,7 @@ function get_schema_struct() 'topic_id' => array('UINT', 0), 'forum_id' => array('UINT', 0), 'save_time' => array('TIMESTAMP', 0), - 'draft_subject' => array('XSTEXT_UNI', ''), + 'draft_subject' => array('STEXT_UNI', ''), 'draft_message' => array('MTEXT_UNI', ''), ), 'PRIMARY_KEY' => 'draft_id', @@ -539,11 +539,12 @@ function get_schema_struct() 'forum_topics_real' => array('UINT', 0), 'forum_last_post_id' => array('UINT', 0), 'forum_last_poster_id' => array('UINT', 0), - 'forum_last_post_subject' => array('XSTEXT_UNI', ''), + 'forum_last_post_subject' => array('STEXT_UNI', ''), 'forum_last_post_time' => array('TIMESTAMP', 0), 'forum_last_poster_name'=> array('VCHAR_UNI', ''), 'forum_last_poster_colour'=> array('VCHAR:6', ''), 'forum_flags' => array('TINT:4', 32), + 'display_subforum_list' => array('BOOL', 1), 'display_on_index' => array('BOOL', 1), 'enable_indexing' => array('BOOL', 1), 'enable_icons' => array('BOOL', 1), @@ -611,11 +612,12 @@ function get_schema_struct() 'group_sig_chars' => array('UINT', 0), 'group_receive_pm' => array('BOOL', 0), 'group_message_limit' => array('UINT', 0), + 'group_max_recipients' => array('UINT', 0), 'group_legend' => array('BOOL', 1), ), 'PRIMARY_KEY' => 'group_id', 'KEYS' => array( - 'group_legend' => array('INDEX', 'group_legend'), + 'group_legend_name' => array('INDEX', array('group_legend', 'group_name')), ), ); @@ -752,8 +754,8 @@ function get_schema_struct() 'enable_magic_url' => array('BOOL', 1), 'enable_sig' => array('BOOL', 1), 'post_username' => array('VCHAR_UNI:255', ''), - 'post_subject' => array('XSTEXT_UNI', '', 'true_sort'), - 'post_text' => array('MTEXT_UNI', '', ($GLOBALS['mysql_indexer']) ? 'true_sort' : 'no_sort'), + 'post_subject' => array('STEXT_UNI', '', 'true_sort'), + 'post_text' => array('MTEXT_UNI', ''), 'post_checksum' => array('VCHAR:32', ''), 'post_attachment' => array('BOOL', 0), 'bbcode_bitfield' => array('VCHAR:255', ''), @@ -788,7 +790,7 @@ function get_schema_struct() 'enable_smilies' => array('BOOL', 1), 'enable_magic_url' => array('BOOL', 1), 'enable_sig' => array('BOOL', 1), - 'message_subject' => array('XSTEXT_UNI', ''), + 'message_subject' => array('STEXT_UNI', ''), 'message_text' => array('MTEXT_UNI', ''), 'message_edit_reason' => array('STEXT_UNI', ''), 'message_edit_user' => array('UINT', 0), @@ -991,6 +993,7 @@ function get_schema_struct() 'COLUMNS' => array( 'session_id' => array('CHAR:32', ''), 'session_user_id' => array('UINT', 0), + 'session_forum_id' => array('UINT', 0), 'session_last_visit' => array('TIMESTAMP', 0), 'session_start' => array('TIMESTAMP', 0), 'session_time' => array('TIMESTAMP', 0), @@ -1006,6 +1009,7 @@ function get_schema_struct() 'KEYS' => array( 'session_time' => array('INDEX', 'session_time'), 'session_user_id' => array('INDEX', 'session_user_id'), + 'session_fid' => array('INDEX', 'session_forum_id'), ), ); @@ -1151,7 +1155,7 @@ function get_schema_struct() 'topic_attachment' => array('BOOL', 0), 'topic_approved' => array('BOOL', 1), 'topic_reported' => array('BOOL', 0), - 'topic_title' => array('XSTEXT_UNI', '', 'true_sort'), + 'topic_title' => array('STEXT_UNI', '', 'true_sort'), 'topic_poster' => array('UINT', 0), 'topic_time' => array('TIMESTAMP', 0), 'topic_time_limit' => array('TIMESTAMP', 0), @@ -1167,7 +1171,7 @@ function get_schema_struct() 'topic_last_poster_id' => array('UINT', 0), 'topic_last_poster_name' => array('VCHAR_UNI', ''), 'topic_last_poster_colour' => array('VCHAR:6', ''), - 'topic_last_post_subject' => array('XSTEXT_UNI', ''), + 'topic_last_post_subject' => array('STEXT_UNI', ''), 'topic_last_post_time' => array('TIMESTAMP', 0), 'topic_last_view_time' => array('TIMESTAMP', 0), 'topic_moved_id' => array('UINT', 0), diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index fa08d3b26a..efb9dcd815 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -53,6 +53,7 @@
  1. Changelog
      +
    1. Changes since 3.0.2
    2. Changes since 3.0.1
    3. Changes since 3.0.0
    4. Changes since RC-8
    5. @@ -82,7 +83,105 @@
      -

      1.i. Changes since 3.0.1

      +

      1.i. Changes since 3.0.2

      + +
        +
      • [Fix] Correctly set topic starter if first post in topic removed (Bug #30575 - Patch by blueray2048)
      • +
      • [Fix] Delete avatar files (Bug #29985).
      • +
      • [Fix] Preserve selection in the MCP. (Bug #31265).
      • +
      • [Fix] Added VST - Venezuela Standard Time (Bug #30545).
      • +
      • [Fix] Close DB connections in file.php.
      • +
      • [Fix] Correctly return results for nested cached queries (Bug #31445 - Patch by faw).
      • +
      • [Fix] Allow export of PM pages greater one. (#33155)
      • +
      • [Fix] Display coloured username of last poster in list of subscribed forums (prosilver).
      • +
      • [Fix] Added missing UCP language string NO_AUTH_READ_HOLD_MESSAGE.
      • +
      • [Fix] Do not jump back to page 1 when hiding member search in memberlist. (Bug #32515)
      • +
      • [Fix] Correctly limit input of the users location to 100 characters in the UCP and ACP. (Bug #32655)
      • +
      • [Fix] Sync reports when using the move all users posts tool in the ACP. (Bug #31165)
      • +
      • [Fix] Extra slash is included in the redirect url when redirecting to the forum root directory. (Bug #33605)
      • +
      • [Fix] Remove reported flag from shadow topics when closing reports. (Bug #19765)
      • +
      • [Fix] Do not show non indexed forums on the search page if they contain no subforums. (Bug #33125)
      • +
      • [Fix] Stop search bots incrementing topic views. (Bug #32675 - Patch by eviL<3)
      • +
      • [Fix] Use correct link for post author search. (Bug #32595)
      • +
      • [Fix] Do not decrease topics counter when deleting shadow topics. (Bug #26495)
      • +
      • [Fix] Send localised disapproval reasons in the recipients local language. (Bug #31645)
      • +
      • [Fix] Language typos/fixes. (Bugs #27625, #30755, #34185, #32795)
      • +
      • [Fix] Added missing terms parameter to search pagination. (Bug #34085)
      • +
      • [Fix] Wrong table order in query obtaining posts if post id given.
      • +
      • [Fix] Do not display reported topic icon for shadow topics. (Bug #13970)
      • +
      • [Fix] Display popular topic based on posts within topic instead of replies within topic. (Bug #16099)
      • +
      • [Fix] Expand shown ban reason in unban screen to fully show long entries. (Bug #16234)
      • +
      • [Fix] Preserve alpha transparency for created thumbnails. (Bug #16575)
      • +
      • [Fix] Use correct port delimiter for MSSQL connections in windows. (Bug #16615)
      • +
      • [Fix] Do not allow setting forums parent to the forum itself. (Bug #18855)
      • +
      • [Fix] Display assigned rank/avatar for guests. (Bug #19155)
      • +
      • [Fix] Set secure cookie for style switcher if required. (Bug #19625)
      • +
      • [Fix] Fix native full text search on postgresql while using excluding keyword matches. (Bug #19195)
      • +
      • [Fix] Pass S_SEARCH_ACTION through append_sid() in search.php. (Bug #21585)
      • +
      • [Fix] Correctly delete message attachments. (Bug #23755)
      • +
      • [Fix] Correctly handle unread status of subforums (that are not shown on the index) of forums that are shown on the index. (Bug #14589)
      • +
      • [Fix] Stop users from deleting posts after the edit time has passed or they have been locked. (Bug #19115)
      • +
      • [Fix] Split posts target forum requires 'f_post' now instead of 'm_split'. (Bug #31015)
      • +
      • [Fix] Duplicate log messages for deleting a topic ('LOG_TOPIC_DELETED' has been deprecated in favour of 'LOG_DELETE_TOPIC').
      • +
      • [Fix] Use a distinct log message for shadow topic deletions to differentiate between normal topic deletions. (Bug #34635)
      • +
      • [Fix] Fix problems with styles using an underscore within the filename. (Bug #34315)
      • +
      • [Fix] Better return links when deleting topics through the MCP. (Bug #34655)
      • +
      • [Fix] Add quoting support to PM history when composing a reply. (Bug #34285)
      • +
      • [Fix] Use phpBB 3.1.x method for storing cached data to prevent PHP bug with our usage of var_export(). (Thanks to Techie-Micheal and HoL for pointing out possible problems)
      • +
      • [Fix] Check users pm preferences for pm's sent to groups. (Bug #33245)
      • +
      • [Fix] Do not allow password reminders if u_passchg permission is not given. (Bug #14806)
      • +
      • [Fix] Implemented strict check for cached user permissions and existing ACL options. This fix makes sure cached permissions are valid, even if they got already cached.
      • +
      • [Fix] Do not show link to user/group profiles if user has no permission to view the linked page and gets a denied message anyway. (Bug #15088)
      • +
      • [Fix] Do not display last post link and sort display options for search engines. (Bug #15088)
      • +
      • [Fix] Make sure users still get notifications if they set to only be notified by Jabber, but Jabber service disabled. (Bug #29715 - Patch by Paul)
      • +
      • [Fix] Don't show forum subscription link on categories. (Bug #34895)
      • +
      • [Fix] Display a message if no topics or forums are selected when unsubscribing. (Bug #34855)
      • +
      • [Fix] Mark/unmark all links in UCP now select/unselect both subscribed topics and forums.
      • +
      • [Fix] Increase board topic counter when splitting topics. (Bug #32125)
      • +
      • [Fix] Display profile icons when viewing a topic, or PM when only the jabber icon is to be visible. (Bug #34755)
      • +
      • [Fix] Do not send PMs with warnings if the user cannot read PMs or they are disabled. (Bug #30815)
      • +
      • [Fix] Correctly convert Niels' Birthday MOD to the date format used in phpBB3. (Bug #32895)
      • +
      • [Fix] Parse BBCode lists of type square, circle and disc. (Bug #35295)
      • +
      • [Fix] Round the displayed percentages in polls. (Bug #32375)
      • +
      • [Fix] Disable mass e-mail when e-mail is disabled. (Bug #27385)
      • +
      • [Fix] Display coloured poster username of queued posts displayed on the front of the MCP.
      • +
      • [Fix] Moderators can only see reports/queue/logs from forums they can actually read. (Bug #31085)
      • +
      • [Fix] Correctly display topic when start parameter is equal to the number of posts.
      • +
      • [Fix] Correctly display topic in MCP when start parameter is equal to or greater than the number of posts. (Bug #30525)
      • + +
      • [Change] No longer allow the direct use of MULTI_INSERT in sql_build_array. sql_multi_insert() must be used.
      • +
      • [Change] Display warning in ACP if config.php file is left writable.
      • +
      • [Change] More restrictive chmod to new files being created. (phpbb_chmod() function mostly by faw)
      • +
      • [Change] Set headers to allow browsers to better cache attachments (Mylek pointed this out)
      • +
      • [Change] Hide parameters if they equal the default in viewforum/viewtopic (Bug #31185)
      • +
      • [Change] Various improvements to group listings (Bugs #32155, #32145, #32085, #26675, #26265)
      • +
      • [Change] Set headers for IE 8 in file.php
      • +
      • [Change] Do not count queued posts to user_posts.
      • +
      • [Change] Allow setting birth year to current year.
      • +
      • [Change] Do not use the topics posted table when performing an egosearch.
      • +
      • [Change] Log the forum name that topics are moved into.
      • +
      • [Change] Automatically add users/groups to the PM recipient list, if entered or selected.
      • +
      • [Change] Reply to PM now includes all previous recipients and not only the original sender.
      • +
      • [Change] Make topic selection for merge less confusing by removing unneeded controls. (Bug #21925)
      • +
      • [Change] MCP topic view checkboxes now default to unchecked.
      • +
      • [Change] Adjust language key SPLIT_AFTER to make the action clearer.
      • +
      • [Change] Add links to the post and forum when viewing a report from the MCP. (Bugs #33795, #33805)
      • +
      • [Change] Remove NUL-Bytes directly in request_var() for strings and within the custom DBAL sql_escape() functions (MSSQL, Firebird, Oracle) (reported by AdhostMikeSw)
      • + +
      • [Feature] Allow limited inheritance for template sets.
      • +
      • [Feature] Allow hard disabling of the template editor.
      • +
      • [Feature] Allow setting custom language path through $user->set_custom_lang_path(). $user->lang_path now also do not include the user language, but only the path.
      • +
      • [Feature] Ability to define nullar/singular/plural language entries
      • +
      • [Feature] Ability to mimic sprintf() calls with $user->lang() with the ability to correctly assign nullar/singular/plural language entries.
      • +
      • [Feature] Added the possibility to force user posts put in queue if post count is lower than an admin defined value. Guest posting is not affected by this setting.
      • +
      • [Feature] Added 'max_recipients' setting for private messages. This setting allows admins to define the maximum number of recipients per private message with a board-wide setting and a group-specific setting.
      • +
      • [Feature] Added new permission setting for sending private messages to groups. Now there are two permissions to define sending private messages to multiple recipients and private messages to groups.
      • +
      • [Feature] Allow specific connection to different server for jabber functionality by providing a valid JID as username. This also allows the use of talk.google.com as jabber server with gmail.com JIDs. (Bug #14989)
      • + +
      • [Sec Precaution] Stricter validation of the HTTP_HOST header (Thanks to Techie-Micheal et al for pointing out possible issues in derived code)
      • +
      + +

      1.ii. Changes since 3.0.1

      • [Fix] Ability to set permissions on non-mysql dbms (Bug #24955)
      • @@ -130,7 +229,7 @@
      • [Sec] Only allow urls gone through redirect() being used within login_box(). (thanks nookieman)
      -

      1.ii. Changes since 3.0.0

      +

      1.iii. Changes since 3.0.0

      • [Change] Validate birthdays (Bug #15004)
      • @@ -201,7 +300,7 @@
      • [Fix] Find and display colliding usernames correctly when converting from one database to another (Bug #23925)
      -

      1.iii. Changes since 3.0.RC8

      +

      1.iv. Changes since 3.0.RC8

      • [Fix] Cleaned usernames contain only single spaces, so "a_name" and "a__name" are treated as the same name (Bug #15634)
      • @@ -210,7 +309,7 @@
      • [Fix] Call garbage_collection() within database updater to correctly close connections (affects Oracle for example)
      -

      1.iv. Changes since 3.0.RC7

      +

      1.v. Changes since 3.0.RC7

      • [Fix] Fixed MSSQL related bug in the update system
      • @@ -245,7 +344,7 @@
      • [Fix] No duplication of active topics (Bug #15474)
      -

      1.v. Changes since 3.0.RC6

      +

      1.vi. Changes since 3.0.RC6

      • [Fix] Submitting language changes using acp_language (Bug #14736)
      • @@ -255,7 +354,7 @@
      • [Fix] Able to request new password (Bug #14743)
      -

      1.vi. Changes since 3.0.RC5

      +

      1.vii. Changes since 3.0.RC5

      • [Feature] Removing constant PHPBB_EMBEDDED in favor of using an exit_handler(); the constant was meant to achive this more or less.
      • @@ -318,7 +417,7 @@
      • [Sec] New password hashing mechanism for storing passwords (#i42)
      -

      1.vii. Changes since 3.0.RC4

      +

      1.viii. Changes since 3.0.RC4

      • [Fix] MySQL, PostgreSQL and SQLite related database fixes (Bug #13862)
      • @@ -369,7 +468,7 @@
      • [Fix] odbc_autocommit causing existing result sets to be dropped (Bug #14182)
      -

      1.viii. Changes since 3.0.RC3

      +

      1.ix. Changes since 3.0.RC3

      • [Fix] Fixing some subsilver2 and prosilver style issues
      • @@ -478,7 +577,7 @@
      -

      1.ix. Changes since 3.0.RC2

      +

      1.x. Changes since 3.0.RC2

      • [Fix] Re-allow searching within the memberlist
      • @@ -524,7 +623,7 @@
      -

      1.x. Changes since 3.0.RC1

      +

      1.xi. Changes since 3.0.RC1

      • [Fix] (X)HTML issues within the templates (Bug #11255, #11255)
      • diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 6e7fbf8e21..81e6f36e1b 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -273,7 +273,7 @@

        This package is meant for those wanting to only replace changed files from a previous version to the latest version. This package normally contains the changed files from up to five previous versions.

        -

        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 3.0.1 you should select the phpBB-3.0.1_to_3.0.2.zip/tar.gz file.

        +

        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 3.0.2 you should select the phpBB-3.0.2_to_3.0.3.zip/tar.gz file.

        The directory structure has been preserved enabling you (if you wish) to simply upload the 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 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.

        @@ -285,7 +285,7 @@

        The patch file is one solution for those with many Modifications (MODs) or other changes who do not want to re-add them back to all the changed files if they use the method explained above. To use this you will need command line access to a standard UNIX type patch application. If you do not have access to such an application but still want to use this update approach, we strongly recommend the Automatic update package explained below. It is also the preferred update method.

        -

        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 3.0.1 you need the phpBB-3.0.1_to_3.0.2.patch file. Place the correct patch in the parent directory containing the phpBB3 core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: patch -cl -d [PHPBB DIRECTORY] -p1 < [PATCH NAME] (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB3, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.

        +

        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 3.0.2 you need the phpBB-3.0.2_to_3.0.3.patch file. Place the correct patch in the parent directory containing the phpBB3 core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: patch -cl -d [PHPBB DIRECTORY] -p1 < [PATCH NAME] (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB3, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.

        If you do get failures you should look at using the Changed files only package to replace the files which failed to patch, please note that you will need to manually re-add any Modifications (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.

        @@ -295,7 +295,7 @@

        This update method is the preferred method for updating. This package allows detecting changed files automatically and merges changes if needed.

        -

        The automatic update package is holding - contrary to the others - only the update informations for updating the last released version to the latest available version. These package is meant for use with the automatic update tool.

        +

        The automatic update package contains - contrary to the others - only the information required to update the previous release version to the latest available version. These packages are meant for use with the automatic update tool.

        To perform the update, either follow the instructions from the Administration Control Panel->System 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.

        @@ -371,9 +371,9 @@

        Path to your former board The converter expects the relative path to your old board's files. So, - for instance - if the old board is located at http://www.yourdomain.com/forum and the phpBB3 installation is located at http://www.yourdomain.com/phpBB3, then the correct value would be ../forum. Note that the webserver user must be able to access the source installation's files.

        -

        Missing images If your default board language's language pack does not include all images, then some images might be missing in your installation. Always use a complete language pack as default language.

        +

        Missing images If your default board language's language pack does not include all images, then some images might be missing in your installation. Always use a complete language pack as default language.

        -

        Smilies During the conversion you might see warnings about image files where the copying failed. That can happen if the old board's smilies have the same file names as those on the new board. Copy those files manually after the conversion, if you want to continue using the old smilies.

        +

        Smilies During the conversion you might see warnings about image files where the copying failed. That can happen if the old board's smilies have the same file names as those on the new board. Copy those files manually after the conversion, if you want to continue using the old smilies.

      diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index 7d777056d9..bfd134faac 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -69,7 +69,15 @@
  2. Styling
  3. -
  4. Templating
  5. +
      +
    1. Style Config Files
    2. +
    3. General Styling Rules
    4. +
    +
  6. Templating +
      +
    1. General Templating
    2. +
    3. Template Inheritance
    4. +
  7. Character Sets and Encodings
  8. Translation (i18n/L10n) Guidelines
      @@ -188,8 +196,7 @@ class ...
    1. /includes/db/firebird.php
      Firebird/Interbase Database Abstraction Layer
    2. /includes/db/msssql.php
      MSSQL Database Abstraction Layer
    3. /includes/db/mssql_odbc.php
      MSSQL ODBC Database Abstraction Layer for MSSQL
    4. -
    5. /includes/db/mysql.php
      MySQL Database Abstraction Layer for MySQL 3.x/4.0.x
    6. -
    7. /includes/db/mysql4.php
      MySQL4 Database Abstraction Layer for MySQL 4.1.x/5.x
    8. +
    9. /includes/db/mysql.php
      MySQL Database Abstraction Layer for MySQL 3.x/4.0.x/4.1.x/5.x
    10. /includes/db/mysqli.php
      MySQLi Database Abstraction Layer
    11. /includes/db/oracle.php
      Oracle Database Abstraction Layer
    12. /includes/db/postgres.php
      PostgreSQL Database Abstraction Layer
    13. @@ -518,7 +525,7 @@ switch ($mode) break; default: - // Always assume that the case got not catched + // Always assume that a case was not caught break; } @@ -541,7 +548,7 @@ switch ($mode) default: - // Always assume that the case got not catched + // Always assume that a case was not caught break; } @@ -569,7 +576,7 @@ switch ($mode) default: - // Always assume that the case got not catched + // Always assume that a case was not caught break; } @@ -690,7 +697,29 @@ $sql = 'UPDATE ' . SOME_TABLE . ' $db->sql_query($sql); -

      The $db->sql_build_array() function supports the following modes: INSERT (example above), INSERT_SELECT (building query for INSERT INTO table (...) SELECT value, column ... statements), MULTI_INSERT (for returning extended inserts), UPDATE (example above) and SELECT (for building WHERE statement [AND logic]).

      +

      The $db->sql_build_array() function supports the following modes: INSERT (example above), INSERT_SELECT (building query for INSERT INTO table (...) SELECT value, column ... statements), UPDATE (example above) and SELECT (for building WHERE statement [AND logic]).

      + +

      sql_multi_insert():

      + +

      If you want to insert multiple statements at once, please use the separate sql_multi_insert() method. An example:

      + +
      +$sql_ary = array();
      +
      +$sql_ary[] = array(
      +	'somedata'		=> $my_string_1,
      +	'otherdata'		=> $an_int_1,
      +	'moredata'		=> $another_int_1,
      +);
      +
      +$sql_ary[] = array(
      +	'somedata'		=> $my_string_2,
      +	'otherdata'		=> $an_int_2,
      +	'moredata'		=> $another_int_2,
      +);
      +
      +$db->sql_multi_insert(SOME_TABLE, $sql_ary);
      +	

      sql_in_set():

      @@ -973,8 +1002,18 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;
      - -

      General things

      +

      3.i. Style Config Files

      +

      Style cfg files are simple name-value lists with the information necessary for installing a style. Similar cfg files exist for templates, themes and imagesets. These follow the same principle and will not be introduced individually. Styles can use installed components by using the required_theme/required_template/required_imageset entries. The important part of the style configuration file is assigning an unique name.

      +
      +        # General Information about this style
      +        name = prosilver_duplicate
      +        copyright = © phpBB Group, 2007
      +        version = 3.0.3
      +        required_template = prosilver
      +        required_theme = prosilver
      +        required_imageset = prosilver
      +	
      +

      3.2. General Styling Rules

      Templates should be produced in a consistent manner. Where appropriate they should be based off an existing copy, e.g. index, viewforum or viewtopic (the combination of which implement a range of conditional and variable forms). Please also note that the intendation and coding guidelines also apply to templates where possible.

      The outer table class forumline has gone and is replaced with tablebg.

      @@ -1041,6 +1080,7 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;
      +

      4.i. General Templating

      File naming

      Firstly templates now take the suffix ".html" rather than ".tpl". This was done simply to make the lifes of some people easier wrt syntax highlighting, etc.

      @@ -1429,6 +1469,29 @@ div </fieldset> </form>

      + +

      4.ii. Template Inheritance

      +

      When basing a new template on an existing one, it is not necessary to provide all template files. By declaring the template to be "inheriting" in the template configuration file.

      + +

      The limitation on this is that the base style has to be installed and complete, meaning that it is not itself inheriting.

      + +

      The effect of doing so is that the template engine will use the files in the new template where they exist, but fall back to files in the base template otherwise. Declaring a style to be inheriting also causes it to use some of the configuration settings of the base style, notably database storage.

      + +

      We strongly encourage the use of inheritance for styles based on the bundled styles, as it will ease the update procedure.

      + +
      +        # General Information about this template
      +        name = inherits
      +        copyright = © phpBB Group, 2007
      +        version = 3.0.3
      +
      +        # Defining a different template bitfield
      +        template_bitfield = lNg=
      +
      +        # Are we inheriting?
      +        inherit_from = prosilver
      +		
      +
      @@ -2195,6 +2258,21 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
      + +

      Revision 8732

      + + + +

      Revision 8596+

      + +
        +
      • Removed sql_build_array('MULTI_INSERT'... statements.
      • +
      • Added sql_multi_insert() explanation.
      • +
      +

      Revision 1.31

        diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 1d325a500e..a89f05b8cf 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -15,6 +15,20 @@ define('IN_PHPBB', true); $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); + +// Thank you sun. +if (isset($_SERVER['CONTENT_TYPE'])) +{ + if ($_SERVER['CONTENT_TYPE'] === 'application/x-java-archive') + { + exit; + } +} +else if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Java') !== false) +{ + exit; +} + if (isset($_GET['avatar'])) { require($phpbb_root_path . 'config.' . $phpEx); @@ -45,6 +59,8 @@ if (isset($_GET['avatar'])) $config = $cache->obtain_config(); $filename = $_GET['avatar']; $avatar_group = false; + $exit = false; + if ($filename[0] === 'g') { $avatar_group = true; @@ -55,75 +71,37 @@ if (isset($_GET['avatar'])) if (strpos($filename, '.') == false) { header('HTTP/1.0 403 Forbidden'); - if (!empty($cache)) - { - $cache->unload(); - } - $db->sql_close(); - exit; + $exit = true; } - $ext = substr(strrchr($filename, '.'), 1); - $stamp = (int) substr(stristr($filename, '_'), 1); - $filename = (int) $filename; - - // let's see if we have to send the file at all - $last_load = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime(trim($_SERVER['HTTP_IF_MODIFIED_SINCE'])) : false; - if (strpos(strtolower($browser), 'msie 6.0') === false) + if (!$exit) { - if ($last_load !== false && $last_load <= $stamp) + $ext = substr(strrchr($filename, '.'), 1); + $stamp = (int) substr(stristr($filename, '_'), 1); + $filename = (int) $filename; + $exit = set_modified_headers($stamp, $browser); + } + if (!$exit && !in_array($ext, array('png', 'gif', 'jpg', 'jpeg'))) + { + // no way such an avatar could exist. They are not following the rules, stop the show. + header("HTTP/1.0 403 Forbidden"); + $exit = true; + } + + + if (!$exit) + { + if (!$filename) { - if (@php_sapi_name() === 'CGI') - { - header('Status: 304 Not Modified', true, 304); - } - else - { - header('HTTP/1.0 304 Not Modified', true, 304); - } - // seems that we need those too ... browsers - header('Pragma: public'); - header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); - exit(); + // no way such an avatar could exist. They are not following the rules, stop the show. + header("HTTP/1.0 403 Forbidden"); } else { - header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT'); + send_avatar_to_browser(($avatar_group ? 'g' : '') . $filename . '.' . $ext, $browser); } } - - if (!in_array($ext, array('png', 'gif', 'jpg', 'jpeg'))) - { - // no way such an avatar could exist. They are not following the rules, stop the show. - header("HTTP/1.0 403 Forbidden"); - if (!empty($cache)) - { - $cache->unload(); - } - $db->sql_close(); - exit; - } - - if (!$filename) - { - // no way such an avatar could exist. They are not following the rules, stop the show. - header("HTTP/1.0 403 Forbidden"); - if (!empty($cache)) - { - $cache->unload(); - } - $db->sql_close(); - exit; - } - - send_avatar_to_browser(($avatar_group ? 'g' : '') . $filename . '.' . $ext, $browser); - - if (!empty($cache)) - { - $cache->unload(); - } - $db->sql_close(); - exit; + file_gc(); } // implicit else: we are not in avatar mode @@ -148,7 +126,7 @@ if (!$config['allow_attachments'] && !$config['allow_pm_attach']) trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED'); } -$sql = 'SELECT attach_id, in_message, post_msg_id, extension, is_orphan, poster_id +$sql = 'SELECT attach_id, in_message, post_msg_id, extension, is_orphan, poster_id, filetime FROM ' . ATTACHMENTS_TABLE . " WHERE attach_id = $download_id"; $result = $db->sql_query_limit($sql, 1); @@ -259,7 +237,7 @@ if (!download_allowed()) $download_mode = (int) $extensions[$attachment['extension']]['download_mode']; // Fetching filename here to prevent sniffing of filename -$sql = 'SELECT attach_id, is_orphan, in_message, post_msg_id, extension, physical_filename, real_filename, mimetype +$sql = 'SELECT attach_id, is_orphan, in_message, post_msg_id, extension, physical_filename, real_filename, mimetype, filetime FROM ' . ATTACHMENTS_TABLE . " WHERE attach_id = $download_id"; $result = $db->sql_query_limit($sql, 1); @@ -297,7 +275,7 @@ else if (($display_cat == ATTACHMENT_CATEGORY_NONE || $display_cat == ATTACHMENT $db->sql_query($sql); } -if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && strpos(strtolower($user->browser), 'msie') !== false) +if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && ((strpos(strtolower($user->browser), 'msie') !== false) && (strpos(strtolower($user->browser), 'msie 8.0') === false))) { wrap_img_in_html(append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'id=' . $attachment['attach_id']), $attachment['real_filename']); } @@ -313,12 +291,12 @@ else } redirect($phpbb_root_path . $config['upload_path'] . '/' . $attachment['physical_filename']); - exit; + file_gc(); } else { send_file_to_browser($attachment, $config['upload_path'], $display_cat); - exit; + file_gc(); } } @@ -354,7 +332,7 @@ function send_avatar_to_browser($file, $browser) $image_data = @getimagesize($file_path); header('Content-Type: ' . image_type_to_mime_type($image_data[2])); - if (strpos(strtolower($browser), 'msie') !== false) + if (strpos(strtolower($browser), 'msie') !== false && strpos(strtolower($browser), 'msie 8.0') === false) { header('Content-Disposition: attachment; ' . header_filename($file)); @@ -379,7 +357,7 @@ function send_avatar_to_browser($file, $browser) header("Content-Length: $size"); } - if (@readfile($file_path) === false) + if (@readfile($file_path) == false) { $fp = @fopen($file_path, 'rb'); @@ -484,9 +462,10 @@ function send_file_to_browser($attachment, $upload_dir, $category) */ // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer. - header('Content-Type: ' . $attachment['mimetype']); + $is_ie8 = (strpos(strtolower($user->browser), 'msie 8.0') !== false); + header('Content-Type: ' . $attachment['mimetype'] . (($is_ie8) ? '; authoritative=true;' : '')); - if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie') !== false)) + if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false))) { header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false)) @@ -497,6 +476,10 @@ function send_file_to_browser($attachment, $upload_dir, $category) else { header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); + if ($is_ie8 && (strpos($attachment['mimetype'], 'image') !== 0)) + { + header('X-Download-Options: noopen'); + } } if ($size) @@ -504,26 +487,32 @@ function send_file_to_browser($attachment, $upload_dir, $category) header("Content-Length: $size"); } - // Try to deliver in chunks - @set_time_limit(0); + // Close the db connection before sending the file + $db->sql_close(); - $fp = @fopen($filename, 'rb'); - - if ($fp !== false) + if (!set_modified_headers($attachment['filetime'], $user->browser)) { - while (!feof($fp)) + // Try to deliver in chunks + @set_time_limit(0); + + $fp = @fopen($filename, 'rb'); + + if ($fp !== false) { - echo fread($fp, 8192); + while (!feof($fp)) + { + echo fread($fp, 8192); + } + fclose($fp); + } + else + { + @readfile($filename); } - fclose($fp); - } - else - { - @readfile($filename); - } - flush(); - exit; + flush(); + } + file_gc(); } /** @@ -655,4 +644,48 @@ function download_allowed() return $allowed; } +/** +* Check if the browser has the file already and set the appropriate headers- +* @returns false if a resend is in order. +*/ +function set_modified_headers($stamp, $browser) +{ + // let's see if we have to send the file at all + $last_load = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime(trim($_SERVER['HTTP_IF_MODIFIED_SINCE'])) : false; + if ((strpos(strtolower($browser), 'msie 6.0') === false) && (strpos(strtolower($browser), 'msie 8.0') === false)) + { + if ($last_load !== false && $last_load <= $stamp) + { + if (@php_sapi_name() === 'CGI') + { + header('Status: 304 Not Modified', true, 304); + } + else + { + header('HTTP/1.0 304 Not Modified', true, 304); + } + // seems that we need those too ... browsers + header('Pragma: public'); + header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + return true; + } + else + { + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT'); + } + } + return false; +} + +function file_gc() +{ + global $cache, $db; + if (!empty($cache)) + { + $cache->unload(); + } + $db->sql_close(); + exit; +} + ?> \ No newline at end of file diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php index 5851016f3d..577f893e77 100644 --- a/phpBB/includes/acm/acm_file.php +++ b/phpBB/includes/acm/acm_file.php @@ -93,7 +93,7 @@ class acm @flock($fp, LOCK_UN); fclose($fp); - @chmod($this->cache_dir . 'data_global.' . $phpEx, 0666); + phpbb_chmod($this->cache_dir . 'data_global.' . $phpEx, CHMOD_WRITE); } else { @@ -154,7 +154,7 @@ class acm } } } - + set_config('cache_last_gc', time(), true); } @@ -193,11 +193,11 @@ class acm if ($fp = @fopen($this->cache_dir . "data{$var_name}.$phpEx", 'wb')) { @flock($fp, LOCK_EX); - fwrite($fp, " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$data = " . var_export($var, true) . ";\n?>"); + fwrite($fp, " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$data = unserialize(" . var_export(serialize($var), true) . ");\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); - @chmod($this->cache_dir . "data{$var_name}.$phpEx", 0666); + phpbb_chmod($this->cache_dir . "data{$var_name}.$phpEx", CHMOD_WRITE); } } else @@ -412,11 +412,11 @@ class acm $file = " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n"; - fwrite($fp, $file . "\n\$this->sql_rowset[\$query_id] = " . var_export($this->sql_rowset[$query_id], true) . ";\n?>"); + fwrite($fp, $file . "\n\$this->sql_rowset[\$query_id] = unserialize(" . var_export(serialize($this->sql_rowset[$query_id]), true) . ");\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); - @chmod($filename, 0666); + phpbb_chmod($filename, CHMOD_WRITE); $query_result = $query_id; } @@ -491,7 +491,7 @@ class acm */ function remove_file($filename, $check = false) { - if ($check && !@is_writeable($this->cache_dir)) + if ($check && !@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/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 4e8a8ef719..15e9e6ab62 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -279,7 +279,7 @@ class acp_attachments { $l_explain = (isset($user->lang[$vars['lang'] . '_EXPLAIN'])) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : ''; } - + $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars); if (empty($content)) { @@ -765,6 +765,8 @@ class acp_attachments $s_forum_id_options = ''; + /** @todo use in-built function **/ + $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id FROM ' . FORUMS_TABLE . ' ORDER BY left_id ASC'; @@ -795,7 +797,7 @@ class acp_attachments } else if ($row['left_id'] > $right + 1) { - $padding = $padding_store[$row['parent_id']]; + $padding = empty($padding_store[$row['parent_id']]) ? '' : $padding_store[$row['parent_id']]; } $right = $row['right_id']; @@ -1168,7 +1170,7 @@ class acp_attachments $location .= '/'; } - if (@is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) + if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) { $imagick = str_replace('\\', '/', $location); continue; @@ -1196,7 +1198,7 @@ class acp_attachments if (!file_exists($phpbb_root_path . $upload_dir)) { @mkdir($phpbb_root_path . $upload_dir, 0777); - @chmod($phpbb_root_path . $upload_dir, 0777); + phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); } } diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 33e8fe7ec1..b827d1107e 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -168,6 +168,12 @@ class acp_bbcodes { trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); } + + + if (strlen($bbcode_helpline) > 255) + { + trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } $sql_ary = array( 'bbcode_tag' => $data['bbcode_tag'], diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index a7abae286a..bce35ee68f 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -131,6 +131,7 @@ class acp_board 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), 'full_folder_action' => array('lang' => 'FULL_FOLDER_ACTION', 'validate' => 'int', 'type' => 'select', 'method' => 'full_folder_select', 'explain' => true), 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + 'pm_max_recipients' => array('lang' => 'PM_MAX_RECIPIENTS', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), 'legend2' => 'GENERAL_OPTIONS', 'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), @@ -163,6 +164,8 @@ class acp_board 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend2' => 'POSTING', + 'enable_queue_trigger' => array('lang' => 'ENABLE_QUEUE_TRIGGER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'queue_trigger_posts' => array('lang' => 'QUEUE_TRIGGER_POSTS', 'validate' => 'int:0:250', 'type' => 'text:4:4', 'explain' => true), 'bump_type' => false, 'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), 'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), @@ -557,14 +560,14 @@ class acp_board { $l_explain = (isset($user->lang[$vars['lang'] . '_EXPLAIN'])) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : ''; } - + $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars); - + if (empty($content)) { continue; } - + $template->assign_block_vars('options', array( 'KEY' => $config_key, 'TITLE' => (isset($user->lang[$vars['lang']])) ? $user->lang[$vars['lang']] : $vars['lang'], @@ -677,7 +680,7 @@ class acp_board return h_radio('config[ip_check]', $radio_ary, $value, $key); } - + /** * Select referer validation */ @@ -687,7 +690,7 @@ class acp_board return h_radio('config[referer_validation]', $radio_ary, $value, $key); } - + /** * Select account activation method */ diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 18523506a4..90aa4e8683 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -80,7 +80,11 @@ class acp_captcha $captcha_vars = array_keys($captcha_vars); foreach ($captcha_vars as $captcha_var) { - set_config($captcha_var, request_var($captcha_var, 0)); + $value = request_var($captcha_var, 0); + if ($value >= 0) + { + set_config($captcha_var, $value); + } } trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 5b479a08eb..e2ca66b2f3 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -620,7 +620,7 @@ class mysql_extractor extends base_extractor if ($new_extract === null) { - if ($db->sql_layer === 'mysqli' || version_compare($db->mysql_version, '3.23.20', '>=')) + if ($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>=')) { $new_extract = true; } diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 8c05cce5b1..6095fdd48b 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -154,8 +154,11 @@ class acp_forums if ($forum_data['forum_type'] == FORUM_LINK) { $forum_data['display_on_index'] = request_var('link_display_on_index', false); + } - // Linked forums are not able to be locked... + // Linked forums and categories are not able to be locked... + if ($forum_data['forum_type'] == FORUM_LINK || $forum_data['forum_type'] == FORUM_CAT) + { $forum_data['forum_status'] = ITEM_UNLOCKED; } @@ -922,10 +925,9 @@ class acp_forums $range_test_ary = array( array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'), ); + validate_range($range_test_ary, $errors); - - // Set forum flags // 1 = link tracking // 2 = prune old polls @@ -1206,7 +1208,14 @@ class acp_forums if ($row['parent_id'] != $forum_data_sql['parent_id']) { - $errors = $this->move_forum($forum_data_sql['forum_id'], $forum_data_sql['parent_id']); + if ($row['forum_id'] != $forum_data_sql['parent_id']) + { + $errors = $this->move_forum($forum_data_sql['forum_id'], $forum_data_sql['parent_id']); + } + else + { + $forum_data_sql['parent_id'] = $row['parent_id']; + } } if (sizeof($errors)) @@ -1647,7 +1656,8 @@ class acp_forums $sql = 'SELECT poster_id FROM ' . POSTS_TABLE . ' WHERE forum_id = ' . $forum_id . ' - AND post_postcount = 1'; + AND post_postcount = 1 + AND post_approved = 1'; $result = $db->sql_query($sql); $post_counts = array(); @@ -1768,6 +1778,7 @@ class acp_forums WHERE user_id = ' . $poster_id . ' AND user_posts < ' . $substract; $db->sql_query($sql); + $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = user_posts - ' . $substract . ' WHERE user_id = ' . $poster_id . ' @@ -1811,7 +1822,7 @@ class acp_forums $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - set_config('upload_dir_size', (int) $row['stat'], true); + set_config('upload_dir_size', (float) $row['stat'], true); return array(); } diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 6d789fb5ff..96ac3de3ce 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -303,6 +303,7 @@ class acp_groups 'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0, 'legend' => isset($_REQUEST['group_legend']) ? 1 : 0, 'message_limit' => request_var('group_message_limit', 0), + 'max_recipients' => request_var('group_max_recipients', 0), 'founder_manage' => 0, ); @@ -395,7 +396,7 @@ class acp_groups // were made. $group_attributes = array(); - $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'founder_manage'); + $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients', 'founder_manage'); foreach ($test_variables as $test) { if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test])) @@ -555,6 +556,7 @@ class acp_groups 'GROUP_FOUNDER_MANAGE' => (isset($group_row['group_founder_manage']) && $group_row['group_founder_manage']) ? ' checked="checked"' : '', 'GROUP_LEGEND' => (isset($group_row['group_legend']) && $group_row['group_legend']) ? ' checked="checked"' : '', 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, + 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 00d99d2f9a..a88090cb25 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -73,6 +73,13 @@ class acp_icons foreach ($imglist as $path => $img_ary) { + if (empty($img_ary)) + { + continue; + } + + asort($img_ary, SORT_STRING); + foreach ($img_ary as $img) { $img_size = getimagesize($phpbb_root_path . $img_path . '/' . $path . $img); @@ -99,6 +106,11 @@ class acp_icons } } closedir($dir); + + if (!empty($_paks)) + { + asort($_paks, SORT_STRING); + } } } diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 3862ee1ee8..499543cc6c 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -85,6 +85,19 @@ class acp_jabber $jabber->disconnect(); } + else + { + // This feature is disabled. + // We update the user table to be sure all users that have IM as notify type are set to both as notify type + $sql_ary = array( + 'user_notify_type' => NOTIFY_BOTH, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_notify_type = ' . NOTIFY_IM; + $db->sql_query($sql); + } set_config('jab_enable', $jab_enable); set_config('jab_host', $jab_host); diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index fc2ae11b1e..71970b4b50 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -181,7 +181,7 @@ class acp_language case 'submit_file': case 'download_file': case 'upload_data': - + if (!$submit || !check_form_key($form_name)) { trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); @@ -261,16 +261,16 @@ class acp_language if (!$safe_mode) { $mkdir_ary = array('language', 'language/' . $row['lang_iso']); - + if ($this->language_directory) { $mkdir_ary[] = 'language/' . $row['lang_iso'] . '/' . $this->language_directory; } - + foreach ($mkdir_ary as $dir) { $dir = $phpbb_root_path . 'store/' . $dir; - + if (!is_dir($dir)) { if (!@mkdir($dir, 0777)) @@ -316,7 +316,7 @@ class acp_language } $entry = "\tarray(\n"; - + foreach ($value as $_key => $_value) { $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n"; @@ -433,7 +433,7 @@ class acp_language { trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); } - + $this->page_title = 'LANGUAGE_PACK_DETAILS'; $sql = 'SELECT * @@ -442,7 +442,7 @@ class acp_language $result = $db->sql_query($sql); $lang_entries = $db->sql_fetchrow($result); $db->sql_freeresult($result); - + $lang_iso = $lang_entries['lang_iso']; $missing_vars = $missing_files = array(); @@ -488,7 +488,7 @@ class acp_language trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); } } - + if (isset($_POST['remove_store'])) { $store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true); @@ -532,7 +532,7 @@ class acp_language if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file))) { $missing_vars[$file] = $this->compare_language_files($config['default_lang'], $lang_iso, '', $file); - + if (sizeof($missing_vars[$file])) { $is_missing_var = true; @@ -550,7 +550,7 @@ class acp_language if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'acp', $file))) { $missing_vars['acp/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'acp', $file); - + if (sizeof($missing_vars['acp/' . $file])) { $is_missing_var = true; @@ -569,7 +569,7 @@ class acp_language if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'mods', $file))) { $missing_vars['mods/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'mods', $file); - + if (sizeof($missing_vars['mods/' . $file])) { $is_missing_var = true; @@ -581,7 +581,7 @@ class acp_language } } } - + // More missing files... for example email templates? foreach ($email_files as $file) { @@ -1046,7 +1046,7 @@ class acp_language $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.html'); $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.html'); $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.html'); - + if (sizeof($mod_files)) { $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.html'); @@ -1208,7 +1208,7 @@ $lang = array_merge($lang, array( function get_filename($lang_iso, $directory, $filename, $check_store = false, $only_return_filename = false) { global $phpbb_root_path, $safe_mode; - + $check_filename = "language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; if ($check_store) diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 7498ab2aef..2b932ebeeb 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -166,9 +166,9 @@ class acp_main FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 0'; $result = $db->sql_query($sql); - set_config('upload_dir_size', (int) $db->sql_fetchfield('stat'), true); + set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true); $db->sql_freeresult($result); - + if (!function_exists('update_last_username')) { include($phpbb_root_path . "includes/functions_user.$phpEx"); @@ -184,22 +184,44 @@ class acp_main trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - $sql = 'SELECT COUNT(p.post_id) AS num_posts, u.user_id - FROM ' . USERS_TABLE . ' u - LEFT JOIN ' . POSTS_TABLE . ' p ON (u.user_id = p.poster_id AND p.post_postcount = 1) - GROUP BY u.user_id'; - $result = $db->sql_query($sql); + // Resync post counts + $start = 0; + $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000; - while ($row = $db->sql_fetchrow($result)) + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_posts = 0'); + + do { - $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['user_id']}"); + $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id + FROM ' . POSTS_TABLE . ' + WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' + AND post_postcount = 1 AND post_approved = 1 + GROUP BY poster_id'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $sql = 'UPDATE ' . USERS_TABLE . " SET user_posts = user_posts + {$row['num_posts']} WHERE user_id = {$row['poster_id']}"; + $db->sql_query($sql); + } + while ($row = $db->sql_fetchrow($result)); + + $start += $step; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); } - $db->sql_freeresult($result); + while ($start); add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); break; - + case 'date': if (!$auth->acl_get('a_board')) { @@ -209,7 +231,7 @@ class acp_main set_config('board_startdate', time() - 1); add_log('admin', 'LOG_RESET_DATE'); break; - + case 'db_track': switch ($db->sql_layer) { @@ -231,7 +253,7 @@ class acp_main FROM ' . FORUMS_TABLE . ' WHERE forum_type <> ' . FORUM_CAT; $result = $db->sql_query($sql); - + $forum_ids = array(); while ($row = $db->sql_fetchrow($result)) { @@ -281,7 +303,7 @@ class acp_main $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); } } - + add_log('admin', 'LOG_RESYNC_POST_MARKING'); break; @@ -320,7 +342,7 @@ class acp_main $files_per_day = sprintf('%.2f', $total_files / $boarddays); $upload_dir_size = get_formatted_filesize($config['upload_dir_size']); - + $avatar_dir_size = 0; if ($avatar_dir = @opendir($phpbb_root_path . $config['avatar_path'])) @@ -463,6 +485,11 @@ class acp_main $template->assign_var('S_REMOVE_INSTALL', true); } + if (file_exists($phpbb_root_path . 'config.' . $phpEx) && is_writable($phpbb_root_path . 'config.' . $phpEx)) + { + $template->assign_var('S_WRITABLE_CONFIG', true); + } + $this->tpl_name = 'acp_main'; $this->page_title = 'ACP_MAIN'; } diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index 9240db271c..727aa0d25d 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -369,8 +369,8 @@ class acp_permissions $template->assign_vars(array( 'S_SELECT_GROUP' => true, - 'S_GROUP_OPTIONS' => group_select_options(false, false, (($user->data['user_type'] == USER_FOUNDER) ? false : 0))) - ); + 'S_GROUP_OPTIONS' => group_select_options(false, false, false), // Show all groups + )); break; @@ -415,7 +415,7 @@ class acp_permissions 'S_SELECT_USERGROUP_VIEW' => ($victim == 'usergroup_view') ? true : false, 'S_DEFINED_USER_OPTIONS' => $items['user_ids_options'], 'S_DEFINED_GROUP_OPTIONS' => $items['group_ids_options'], - 'S_ADD_GROUP_OPTIONS' => group_select_options(false, $items['group_ids'], (($user->data['user_type'] == USER_FOUNDER) ? false : 0)), + 'S_ADD_GROUP_OPTIONS' => group_select_options(false, $items['group_ids'], false), // Show all groups 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=add_user&field=username&select_single=true'), )); diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index dd5255f755..70c306014d 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -93,6 +93,15 @@ version = {VERSION} parse_css_file = {PARSE_CSS_FILE} '; + $this->template_cfg .= ' +# Some configuration options + +# +# You can use this function to inherit templates from another template. +# The template of the given name has to be installed. +# Templates cannot inherit from inheriting templates. +#'; + $this->imageset_keys = array( 'logos' => array( 'site_logo', @@ -670,6 +679,11 @@ parse_css_file = {PARSE_CSS_FILE} { global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; + if (defined('DISABLE_ACP_EDITOR')) + { + trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action)); + } + $this->page_title = 'EDIT_TEMPLATE'; $filelist = $filelist_cats = array(); @@ -682,7 +696,7 @@ parse_css_file = {PARSE_CSS_FILE} // make sure template_file path doesn't go upwards $template_file = str_replace('..', '.', $template_file); - + // Retrieve some information about the template $sql = 'SELECT template_storedb, template_path, template_name FROM ' . STYLES_TEMPLATE_TABLE . " @@ -695,7 +709,7 @@ parse_css_file = {PARSE_CSS_FILE} { trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); } - + if ($save_changes && !check_form_key('acp_styles')) { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); @@ -729,13 +743,14 @@ parse_css_file = {PARSE_CSS_FILE} // If it's not stored in the db yet, then update the template setting and store all template files in the db if (!$template_info['template_storedb']) { - $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' - SET template_storedb = 1 - WHERE template_id = ' . $template_id; - $db->sql_query($sql); - - $filelist = filelist("{$phpbb_root_path}styles/{$template_info['template_path']}/template", '', 'html'); - $this->store_templates('insert', $template_id, $template_info['template_path'], $filelist); + if ($this->get_super('template', $template_id)) + { + $this->store_in_db('template', $super['template_id']); + } + else + { + $this->store_in_db('template', $template_id); + } add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']); $additional .= '
        ' . $user->lang['EDIT_TEMPLATE_STORED_DB']; @@ -923,7 +938,7 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&action=cache&id=$template_id")); } - $cache_prefix = 'tpl_' . $template_row['template_path']; + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); // Someone wants to see the cached source ... so we'll highlight it, // add line numbers and indent it appropriately. This could be nasty @@ -975,17 +990,30 @@ parse_css_file = {PARSE_CSS_FILE} $filemtime = array(); if ($template_row['template_storedb']) { - $sql = 'SELECT template_filename, template_mtime - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $template_id"; - $result = $db->sql_query($sql); - - $filemtime = array(); - while ($row = $db->sql_fetchrow($result)) + $ids = array(); + if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) { - $filemtime[$row['template_filename']] = $row['template_mtime']; + $ids[] = $template_row['template_inherits_id']; + } + $ids[] = $template_row['template_id']; + + $filemtime = array(); + $file_template_db = array(); + + foreach ($ids as $id) + { + $sql = 'SELECT template_filename, template_mtime + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $filemtime[$row['template_filename']] = $row['template_mtime']; + $file_template_db[$row['template_filename']] = $id; + } + $db->sql_freeresult($result); } - $db->sql_freeresult($result); } // Get a list of cached template files and then retrieve additional information about them @@ -994,12 +1022,12 @@ parse_css_file = {PARSE_CSS_FILE} foreach ($file_ary as $file) { $file = str_replace('/', '.', $file); - + // perform some dirty guessing to get the path right. // We assume that three dots in a row were '../' $tpl_file = str_replace('.', '/', $file); $tpl_file = str_replace('///', '../', $tpl_file); - + $filename = "{$cache_prefix}_$file.html.$phpEx"; if (!file_exists("{$phpbb_root_path}cache/$filename")) @@ -1007,13 +1035,38 @@ parse_css_file = {PARSE_CSS_FILE} continue; } + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html"; + $inherited = false; + + if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) + { + if (!$template_row['template_storedb']) + { + if (!file_exists($file_tpl)) + { + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; + $inherited = true; + } + } + else + { + if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id']) + { + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; + $inherited = true; + } + } + } + + $template->assign_block_vars('file', array( 'U_VIEWSOURCE' => $this->u_action . "&action=cache&id=$template_id&source=$file", 'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")), 'FILENAME' => $file, + 'FILENAME_PATH' => $file_tpl, 'FILESIZE' => sprintf('%.1f ' . $user->lang['KIB'], filesize("{$phpbb_root_path}cache/$filename") / 1024), - 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html") : $filemtime[$file . '.html'])) + 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html'])) ); } unset($filemtime); @@ -1048,7 +1101,7 @@ parse_css_file = {PARSE_CSS_FILE} // make sure theme_file path doesn't go upwards $theme_file = str_replace('..', '.', $theme_file); - + // Retrieve some information about the theme $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data FROM ' . STYLES_THEME_TABLE . " @@ -1229,7 +1282,7 @@ parse_css_file = {PARSE_CSS_FILE} $imgsize = request_var('imgsize', false); $imgwidth = request_var('imgwidth', 0); $imgheight = request_var('imgheight', 0); - + $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname); $imgpath = str_replace('..', '.', $imgpath); @@ -1517,6 +1570,18 @@ parse_css_file = {PARSE_CSS_FILE} break; } + if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id))) + { + $l_type = strtoupper($mode); + $msg = $user->lang[$l_type . '_DELETE_DEPENDENT']; + foreach ($conflicts as $id => $values) + { + $msg .= '
        ' . $values['template_name']; + } + + trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING); + } + $l_prefix = strtoupper($mode); $sql = "SELECT $sql_select @@ -1717,7 +1782,7 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); } - $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright'); + $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright'); foreach ($var_ary as $var) { @@ -1749,7 +1814,23 @@ parse_css_file = {PARSE_CSS_FILE} if ($mode == 'template' || $inc_template) { $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version']), $this->template_cfg); - $template_cfg .= "\nbbcode_bitfield = {$style_row['bbcode_bitfield']}"; + + $use_template_name = ''; + + // Add the inherit from variable, depending on it's use... + if ($style_row['template_inherits_id']) + { + // Get the template name + $sql = 'SELECT template_name + FROM ' . STYLES_TEMPLATE_TABLE . ' + WHERE template_id = ' . (int) $style_row['template_inherits_id']; + $result = $db->sql_query($sql); + $use_template_name = (string) $db->sql_fetchfield('template_name'); + $db->sql_freeresult($result); + } + + $template_cfg .= ($use_template_name) ? "\ninherit_from = $use_template_name" : "\n#inherit_from = "; + $template_cfg .= "\n\nbbcode_bitfield = {$style_row['bbcode_bitfield']}"; $data[] = array( 'src' => $template_cfg, @@ -2095,6 +2176,14 @@ parse_css_file = {PARSE_CSS_FILE} $style_default = request_var('style_default', 0); $store_db = request_var('store_db', 0); + $sql = "SELECT {$mode}_id + FROM $sql_from + WHERE {$mode}_id <> $style_id + AND {$mode}_name = '" . $db->sql_escape(strtolower($name)) . "'"; + $result = $db->sql_query($sql); + $conflict = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id)) { $error[] = $user->lang['STYLE_ERR_NO_IDS']; @@ -2105,7 +2194,7 @@ parse_css_file = {PARSE_CSS_FILE} $error[] = $user->lang['DEACTIVATE_DEFAULT']; } - if (!$name) + if (!$name || $conflict) { $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; } @@ -2132,7 +2221,7 @@ parse_css_file = {PARSE_CSS_FILE} } } } - + if (!sizeof($error)) { // Check length settings @@ -2218,51 +2307,38 @@ parse_css_file = {PARSE_CSS_FILE} if ($style_row['template_storedb'] != $store_db) { - if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template")) + if ($super = $this->get_super($mode, $style_row['template_id'])) { - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $style_id"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) + $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); + $sql_ary = array(); + } + else + { + if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template")) { - if (!($fp = @fopen("{$phpbb_root_path}styles/{$style_row['template_path']}/template/" . $row['template_filename'], 'wb'))) + $err = $this->store_in_fs('template', $style_row['template_id']); + if ($err) { - $store_db = 1; - $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB']; - break; + $error += $err; } - - fwrite($fp, $row['template_data']); - fclose($fp); } - $db->sql_freeresult($result); - - if (!$store_db) + else if ($store_db) { + $this->store_in_db('template', $style_row['template_id']); + } + else + { + // We no longer store within the db, but are also not able to update the file structure + // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " WHERE template_id = $style_id"; $db->sql_query($sql); } - } - else if ($store_db) - { - $filelist = filelist("{$phpbb_root_path}styles/{$style_row['template_path']}/template", '', 'html'); - $this->store_templates('insert', $style_id, $style_row['template_path'], $filelist); - } - else - { - // We no longer store within the db, but are also not able to update the file structure - // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache - $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $style_id"; - $db->sql_query($sql); - } - $sql_ary += array( - 'template_storedb' => $store_db, - ); + $sql_ary += array( + 'template_storedb' => $store_db, + ); + } } break; } @@ -2313,6 +2389,16 @@ parse_css_file = {PARSE_CSS_FILE} } } + + if ($mode == 'template') + { + $super = array(); + if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id']) + { + $super = $this->get_super($mode, $style_row['template_id']); + } + } + $this->page_title = 'EDIT_DETAILS_' . $l_type; $template->assign_vars(array( @@ -2323,8 +2409,10 @@ parse_css_file = {PARSE_CSS_FILE} 'S_THEME' => ($mode == 'theme') ? true : false, 'S_IMAGESET' => ($mode == 'imageset') ? true : false, 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, + 'S_STORE_DB_DISABLED' => (isset($style_row[$mode . '_inherits_id'])) ? $style_row[$mode . '_inherits_id'] : 0, 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0, 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', @@ -2363,6 +2451,10 @@ parse_css_file = {PARSE_CSS_FILE} { $content = ''; } + if (defined('DEBUG')) + { + $content = "/* BEGIN @include $filename */ \n $content \n /* END @include $filename */ \n"; + } return $content; } @@ -2487,7 +2579,7 @@ parse_css_file = {PARSE_CSS_FILE} { global $phpbb_root_path, $phpEx, $user; - $cache_prefix = 'tpl_' . $template_path; + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_path); if (!($dp = @opendir("{$phpbb_root_path}cache"))) { @@ -2523,7 +2615,7 @@ parse_css_file = {PARSE_CSS_FILE} { global $phpbb_root_path, $phpEx, $user; - $cache_prefix = 'tpl_' . $template_row['template_path']; + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); if (!$file_ary || !is_array($file_ary)) { @@ -2624,6 +2716,23 @@ parse_css_file = {PARSE_CSS_FILE} { $style_row[$element . '_name'] = $reqd_template; } + + // Merge other information to installcfg... if present + $cfg_file = $phpbb_root_path . 'styles/' . $install_path . '/' . $element . '/' . $element . '.cfg'; + + if (file_exists($cfg_file)) + { + $cfg_contents = parse_cfg_file($cfg_file); + + // Merge only specific things. We may need them later. + foreach (array('inherit_from', 'parse_css_file') as $key) + { + if (!empty($cfg_contents[$key]) && !isset($installcfg[$key])) + { + $installcfg[$key] = $cfg_contents[$key]; + } + } + } } break; @@ -2682,8 +2791,10 @@ parse_css_file = {PARSE_CSS_FILE} 'S_DETAILS' => true, 'S_INSTALL' => true, 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_LOCATION' => (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true, 'S_STYLE' => ($mode == 'style') ? true : false, 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_SUPERTEMPLATE' => (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '', 'S_THEME' => ($mode == 'theme') ? true : false, 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, @@ -3034,6 +3145,9 @@ parse_css_file = {PARSE_CSS_FILE} { global $phpbb_root_path, $db, $user; + // we parse the cfg here (again) + $cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg"); + switch ($mode) { case 'template': @@ -3075,6 +3189,7 @@ parse_css_file = {PARSE_CSS_FILE} $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); + if ($row) { // If it exist, we just use the style on installation @@ -3087,6 +3202,34 @@ parse_css_file = {PARSE_CSS_FILE} $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST']; } + if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) + { + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb + FROM $sql_from + WHERE {$mode}_name = '" . $db->sql_escape(strtolower($cfg_data['inherit_from'])) . "' + AND {$mode}_inherits_id = 0"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + if (!$row) + { + $error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $cfg_data['inherit_from']); + } + else + { + $inherit_id = $row["{$mode}_id"]; + $inherit_path = $row["{$mode}_path"]; + $cfg_data['store_db'] = $row["{$mode}_storedb"]; + $store_db = $row["{$mode}_storedb"]; + } + } + else + { + $inherit_id = 0; + $inherit_path = ''; + } + + if (sizeof($error)) { return false; @@ -3102,8 +3245,6 @@ parse_css_file = {PARSE_CSS_FILE} { case 'template': // We check if the template author defined a different bitfield - $cfg_data = parse_cfg_file("$root_path$mode/template.cfg"); - if (!empty($cfg_data['template_bitfield'])) { $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield']; @@ -3115,15 +3256,21 @@ parse_css_file = {PARSE_CSS_FILE} // We set a pre-defined bitfield here which we may use further in 3.2 $sql_ary += array( - 'template_storedb' => $store_db + 'template_storedb' => $store_db, ); + if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) + { + $sql_ary += array( + 'template_inherits_id' => $inherit_id, + 'template_inherit_path' => $inherit_path, + ); + } break; case 'theme': // We are only interested in the theme configuration for now - $theme_cfg = parse_cfg_file("{$phpbb_root_path}styles/$path/theme/theme.cfg"); - if (isset($theme_cfg['parse_css_file']) && $theme_cfg['parse_css_file']) + if (isset($cfg_data['parse_css_file']) && $cfg_data['parse_css_file']) { $store_db = 1; } @@ -3263,6 +3410,297 @@ parse_css_file = {PARSE_CSS_FILE} return $store_db; } + /** + * Checks downwards dependencies + * + * @access public + * @param string $mode The element type to check - only template is supported + * @param int $id The template id + * @returns false if no component inherits, array with name, path and id for each subtemplate otherwise + */ + function check_inheritance($mode, $id) + { + global $db; + + $l_type = strtoupper($mode); + + switch ($mode) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM $sql_from + WHERE {$mode}_inherits_id = " . (int) $id; + $result = $db->sql_query($sql); + + $names = array(); + while ($row = $db->sql_fetchrow($result)) + { + + $names[$row["{$mode}_id"]] = array( + "{$mode}_id" => $row["{$mode}_id"], + "{$mode}_name" => $row["{$mode}_name"], + "{$mode}_path" => $row["{$mode}_path"], + ); + } + $db->sql_freeresult($result); + + if (sizeof($names)) + { + return $names; + } + else + { + return false; + } + } + + /** + * Checks upwards dependencies + * + * @access public + * @param string $mode The element type to check - only template is supported + * @param int $id The template id + * @returns false if the component does not inherit, array with name, path and id otherwise + */ + function get_super($mode, $id) + { + global $db; + + $l_type = strtoupper($mode); + + switch ($mode) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + + $sql = "SELECT {$mode}_inherits_id + FROM $sql_from + WHERE {$mode}_id = " . (int) $id; + $result = $db->sql_query_limit($sql, 1); + + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + } + else + { + return false; + } + + $super_id = $row["{$mode}_inherits_id"]; + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM $sql_from + WHERE {$mode}_id = " . (int) $super_id; + + $result = $db->sql_query_limit($sql, 1); + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + return $row; + } + + return false; + } + + /** + * Moves a template set and its subtemplates to the database + * + * @access public + * @param string $mode The component to move - only template is supported + * @param int $id The template id + */ + function store_in_db($mode, $id) + { + global $db, $user; + + $error = array(); + $l_type = strtoupper($mode); + if ($super = $this->get_super($mode, $id)) + { + $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); + return $error; + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM " . STYLES_TEMPLATE_TABLE . ' + WHERE template_id = ' . (int) $id; + + $result = $db->sql_query_limit($sql, 1); + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + $subs = $this->check_inheritance($mode, $id); + + $this->_store_in_db($mode, $id, $row["{$mode}_path"]); + if ($subs && sizeof($subs)) + { + foreach ($subs as $sub_id => $sub) + { + if ($err = $this->_store_in_db($mode, $sub["{$mode}_id"], $sub["{$mode}_path"])) + { + $error[] = $err; + } + } + } + } + if (sizeof($error)) + { + return $error; + } + + return false; + } + + /** + * Moves a template set to the database + * + * @access private + * @param string $mode The component to move - only template is supported + * @param int $id The template id + * @param string $path TThe path to the template files + */ + function _store_in_db($mode, $id, $path) + { + global $phpbb_root_path, $db; + + $filelist = filelist("{$phpbb_root_path}styles/{$path}/template", '', 'html'); + $this->store_templates('insert', $id, $path, $filelist); + + // Okay, we do the query here -shouldn't be triggered often. + $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' + SET template_storedb = 1 + WHERE template_id = ' . $id; + $db->sql_query($sql); + } + + /** + * Moves a template set and its subtemplates to the filesystem + * + * @access public + * @param string $mode The component to move - only template is supported + * @param int $id The template id + */ + function store_in_fs($mode, $id) + { + global $db, $user; + + $error = array(); + $l_type = strtoupper($mode); + if ($super = $this->get_super($mode, $id)) + { + $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); + return($error); + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM " . STYLES_TEMPLATE_TABLE . ' + WHERE template_id = ' . (int) $id; + + $result = $db->sql_query_limit($sql, 1); + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + if (!sizeof($error)) + { + $subs = $this->check_inheritance($mode, $id); + + $this->_store_in_fs($mode, $id, $row["{$mode}_path"]); + + if ($subs && sizeof($subs)) + { + foreach ($subs as $sub_id => $sub) + { + $this->_store_in_fs($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]); + } + } + } + if (sizeof($error)) + { + $this->store_in_db($id, $mode); + return $error; + } + } + return false; + } + + /** + * Moves a template set to the filesystem + * + * @access private + * @param string $mode The component to move - only template is supported + * @param int $id The template id + * @param string $path The path to the template + */ + function _store_in_fs($mode, $id, $path) + { + global $phpbb_root_path, $db, $user, $safe_mode; + + $store_db = 0; + $error = array(); + if (!$safe_mode && @is_writable("{$phpbb_root_path}styles/{$path}/template")) + { + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!($fp = @fopen("{$phpbb_root_path}styles/{$path}/template/" . $row['template_filename'], 'wb'))) + { + $store_db = 1; + $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB']; + break; + } + + fwrite($fp, $row['template_data']); + fclose($fp); + } + $db->sql_freeresult($result); + + if (!$store_db) + { + $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $id"; + $db->sql_query($sql); + } + } + if (sizeof($error)) + { + return $error; + } + $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' + SET template_storedb = 0 + WHERE template_id = ' . $id; + $db->sql_query($sql); + + return false; + } + } ?> \ No newline at end of file diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 32bbe4e46d..05a087f4c3 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -634,7 +634,7 @@ class acp_users if (sizeof($topic_id_ary)) { - sync('reported', 'topic_id', $topic_id_ary); + sync('topic_reported', 'topic_id', $topic_id_ary); sync('topic', 'topic_id', $topic_id_ary); } @@ -891,9 +891,19 @@ class acp_users } } + // Posts in Queue + $sql = 'SELECT COUNT(post_id) as posts_in_queue + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . $user_id . ' + AND post_approved = 0'; + $result = $db->sql_query($sql); + $user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue'); + $db->sql_freeresult($result); + $template->assign_vars(array( 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $user_row['posts_in_queue']), 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, 'S_OVERVIEW' => true, @@ -905,9 +915,11 @@ class acp_users 'U_SHOW_IP' => $this->u_action . "&u=$user_id&ip=" . (($ip == 'ip') ? 'hostname' : 'ip'), 'U_WHOIS' => $this->u_action . "&action=whois&user_ip={$user_row['user_ip']}", + 'U_MCP_QUEUE' => ($auth->acl_getf_global('m_approve')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue', true, $user->session_id) : '', 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_row['user_id']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&u={$user_row['user_id']}") : '', + 'POSTS_IN_QUEUE' => $user_row['posts_in_queue'], 'USER' => $user_row['username'], 'USER_REGISTERED' => $user->format_date($user_row['user_regdate']), 'REGISTERED_IP' => ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'], @@ -1081,7 +1093,7 @@ class acp_users 'website' => array( array('string', true, 12, 255), array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), - 'location' => array('string', true, 2, 255), + 'location' => array('string', true, 2, 100), 'occupation' => array('string', true, 2, 500), 'interests' => array('string', true, 2, 500), 'bday_day' => array('num', true, 1, 31), diff --git a/phpBB/includes/acp/info/acp_email.php b/phpBB/includes/acp/info/acp_email.php index f2270892e0..4ad7bca58b 100644 --- a/phpBB/includes/acp/info/acp_email.php +++ b/phpBB/includes/acp/info/acp_email.php @@ -20,7 +20,7 @@ class acp_email_info 'title' => 'ACP_MASS_EMAIL', 'version' => '1.0.0', 'modes' => array( - 'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email', 'cat' => array('ACP_GENERAL_TASKS')), + 'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')), ), ); } diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php index d0b38b67a3..1196a9a0f0 100644 --- a/phpBB/includes/auth.php +++ b/phpBB/includes/auth.php @@ -71,7 +71,46 @@ class auth $this->acl_cache($userdata); } - $user_permissions = explode("\n", $userdata['user_permissions']); + // Fill ACL array + $this->_fill_acl($userdata['user_permissions']); + + // Verify bitstring length with options provided... + $renew = false; + $global_length = sizeof($this->acl_options['global']); + $local_length = sizeof($this->acl_options['local']); + + // Specify comparing length (bitstring is padded to 31 bits) + $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length; + $local_length = ($local_length % 31) ? ($local_length - ($local_length % 31) + 31) : $local_length; + + // You thought we are finished now? Noooo... now compare them. + foreach ($this->acl as $forum_id => $bitstring) + { + if (($forum_id && strlen($bitstring) != $local_length) || (!$forum_id && strlen($bitstring) != $global_length)) + { + $renew = true; + break; + } + } + + // If a bitstring within the list does not match the options, we have a user with incorrect permissions set and need to renew them + if ($renew) + { + $this->acl_cache($userdata); + $this->_fill_acl($userdata['user_permissions']); + } + + return; + } + + /** + * Fill ACL array with relevant bitstrings from user_permissions column + * @access private + */ + function _fill_acl($user_permissions) + { + $this->acl = array(); + $user_permissions = explode("\n", $user_permissions); foreach ($user_permissions as $f => $seq) { @@ -92,8 +131,6 @@ class auth } } } - - return; } /** @@ -169,7 +206,7 @@ class auth $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE; - + if (sizeof($this->acl)) { $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true); @@ -184,7 +221,7 @@ class auth $db->sql_freeresult($result); } } - + if (isset($this->acl_options['local'][$opt])) { foreach ($this->acl as $f => $bitstring) @@ -418,7 +455,7 @@ class auth // The line number indicates the id, therefore we have to add empty lines for those ids not present $hold_str .= str_repeat("\n", $f - $last_f); - + // Convert bitstring for storage - we do not use binary/bytes because PHP's string functions are not fully binary safe for ($i = 0, $bit_length = strlen($bitstring); $i < $bit_length; $i += 31) { @@ -549,7 +586,7 @@ class auth // Now the role settings - user-specific $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . ' FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . ' - WHERE a.auth_role_id = r.role_id ' . + WHERE a.auth_role_id = r.role_id ' . (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . (($sql_user) ? 'AND a.' . $sql_user : '') . " $sql_forum @@ -607,7 +644,7 @@ class auth if ($row['auth_setting'] == ACL_NEVER) { $flag = substr($option, 0, strpos($option, '_') + 1); - + if (isset($hold_ary[$row['user_id']][$row['forum_id']][$flag]) && $hold_ary[$row['user_id']][$row['forum_id']][$flag] == ACL_YES) { unset($hold_ary[$row['user_id']][$row['forum_id']][$flag]); @@ -827,7 +864,7 @@ class auth { $flag = substr($this->acl_options['option'][$option_id], 0, strpos($this->acl_options['option'][$option_id], '_') + 1); $flag = (int) $this->acl_options['id'][$flag]; - + if (isset($hold_ary[$flag]) && $hold_ary[$flag] == ACL_YES) { unset($hold_ary[$flag]); diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index ef73762582..fd8fadf3a7 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -134,10 +134,21 @@ class bbcode { $this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']); $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html'; - + if (!@file_exists($this->template_filename)) { - trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) + { + $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template/bbcode.html'; + if (!@file_exists($this->template_filename)) + { + trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); + } + } + else + { + trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); + } } } diff --git a/phpBB/includes/cache.php b/phpBB/includes/cache.php index 31b8b73e10..fc9a01ae4e 100644 --- a/phpBB/includes/cache.php +++ b/phpBB/includes/cache.php @@ -63,7 +63,7 @@ class cache extends acm $this->put('config', $cached_config); } - + return $config; } @@ -103,7 +103,7 @@ class cache extends acm if (($icons = $this->get('_icons')) === false) { global $db; - + // Topic icons $sql = 'SELECT * FROM ' . ICONS_TABLE . ' @@ -134,7 +134,7 @@ class cache extends acm if (($ranks = $this->get('_ranks')) === false) { global $db; - + $sql = 'SELECT * FROM ' . RANKS_TABLE . ' ORDER BY rank_min DESC'; @@ -284,7 +284,7 @@ class cache extends acm if (($bots = $this->get('_bots')) === false) { global $db; - + switch ($db->sql_layer) { case 'mssql': @@ -321,7 +321,7 @@ class cache extends acm $this->put('_bots', $bots); } - + return $bots; } diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 7c681a4040..e2a43da8c4 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -24,6 +24,9 @@ if (!defined('IN_PHPBB')) * PHPBB_ADMIN_PATH */ +// phpBB Version +define('PHPBB_VERSION', '3.0.3-RC1'); + // QA-related // define('PHPBB_QA', 1); @@ -176,6 +179,11 @@ define('REFERER_VALIDATE_NONE', 0); define('REFERER_VALIDATE_HOST', 1); define('REFERER_VALIDATE_PATH', 2); +// phpbb_chmod() permissions +@define('CHMOD_ALL', 7); +@define('CHMOD_READ', 4); +@define('CHMOD_WRITE', 2); +@define('CHMOD_EXECUTE', 1); // Additional constants define('VOTE_CONVERTED', 127); diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 0a65fc12ca..703af25086 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -265,7 +265,7 @@ class phpbb_db_tools break; case 'mysql4': - if (version_compare($this->db->mysql_version, '4.1.3', '>=')) + if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) { $this->sql_layer = 'mysql_41'; } @@ -593,7 +593,7 @@ class phpbb_db_tools /** * Private method for performing sql statements (either execute them or return them) - * @private + * @access private */ function _sql_run_sql($statements) { @@ -624,7 +624,7 @@ class phpbb_db_tools /** * Function to prepare some column information for better usage - * @private + * @access private */ function sql_prepare_column_data($table_name, $column_name, $column_data) { diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index 21d095155e..179eff65d2 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -34,7 +34,7 @@ class dbal var $query_hold = ''; var $html_hold = ''; var $sql_report = ''; - + var $persistency = false; var $user = ''; var $server = ''; @@ -47,7 +47,7 @@ class dbal var $sql_error_sql = ''; // Holding the error information - only populated if sql_error_triggered is set var $sql_error_returned = array(); - + // Holding transaction count var $transactions = 0; @@ -65,6 +65,11 @@ class dbal var $any_char; var $one_char; + /** + * Exact version of the DBAL, directly queried + */ + var $sql_server_version = false; + /** * Constructor */ @@ -137,8 +142,14 @@ class dbal { $this->sql_freeresult($query_id); } - - return $this->_sql_close(); + + // Connection closed correctly. Set db_connect_id to false to prevent errors + if ($result = $this->_sql_close()) + { + $this->db_connect_id = false; + } + + return $result; } /** @@ -179,7 +190,7 @@ class dbal return $result; } - + return false; } @@ -300,7 +311,7 @@ class dbal * Build sql statement from array for insert/update/select statements * * Idea for this from Ikonboard - * Possible query values: INSERT, INSERT_SELECT, MULTI_INSERT, UPDATE, SELECT + * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT * */ function sql_build_array($query, $assoc_ary = false) @@ -333,24 +344,7 @@ class dbal } else if ($query == 'MULTI_INSERT') { - $ary = array(); - foreach ($assoc_ary as $id => $sql_ary) - { - // If by accident the sql array is only one-dimensional we build a normal insert statement - if (!is_array($sql_ary)) - { - return $this->sql_build_array('INSERT', $assoc_ary); - } - - $values = array(); - foreach ($sql_ary as $key => $var) - { - $values[] = $this->_sql_validate_value($var); - } - $ary[] = '(' . implode(', ', $values) . ')'; - } - - $query = ' (' . implode(', ', array_keys($assoc_ary[0])) . ') VALUES ' . implode(', ', $ary); + trigger_error('The MULTI_INSERT query value is no longer supported. Please use sql_multi_insert() instead.', E_USER_ERROR); } else if ($query == 'UPDATE' || $query == 'SELECT') { @@ -435,7 +429,25 @@ class dbal if ($this->multi_insert) { - $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('MULTI_INSERT', $sql_ary)); + $ary = array(); + foreach ($sql_ary as $id => $_sql_ary) + { + // If by accident the sql array is only one-dimensional we build a normal insert statement + if (!is_array($_sql_ary)) + { + $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary)); + return true; + } + + $values = array(); + foreach ($_sql_ary as $key => $var) + { + $values[] = $this->_sql_validate_value($var); + } + $ary[] = '(' . implode(', ', $values) . ')'; + } + + $this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary)); } else { @@ -700,7 +712,7 @@ class dbal
{L_FORUM_STATS}
{file.FILENAME}{file.FILENAME_PATH} {file.FILESIZE} {file.CACHED} {file.MODIFIED}
- + ' . $this->html_hold . '

@@ -728,24 +740,24 @@ class dbal case 'start': $this->query_hold = $query; $this->html_hold = ''; - + $this->_sql_report($mode, $query); $this->curtime = explode(' ', microtime()); $this->curtime = $this->curtime[0] + $this->curtime[1]; break; - + case 'add_select_row': $html_table = func_get_arg(2); $row = func_get_arg(3); - + if (!$html_table && sizeof($row)) { $html_table = true; $this->html_hold .= ''; - + foreach (array_keys($row) as $val) { $this->html_hold .= ''; @@ -761,7 +773,7 @@ class dbal $this->html_hold .= ''; } $this->html_hold .= ''; - + return $html_table; break; @@ -792,7 +804,7 @@ class dbal break; default: - + $this->_sql_report($mode, $query); break; diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php index d23d1866c1..3b31942a8b 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/firebird.php @@ -37,26 +37,42 @@ class dbal_firebird extends dbal $this->persistency = $persistency; $this->user = $sqluser; $this->server = $sqlserver . (($port) ? ':' . $port : ''); - $this->dbname = $database; + $this->dbname = str_replace('\\', '/', $database); - $this->db_connect_id = ($this->persistency) ? @ibase_pconnect($this->server . ':' . $this->dbname, $this->user, $sqlpassword, false, false, 3) : @ibase_connect($this->server . ':' . $this->dbname, $this->user, $sqlpassword, false, false, 3); + // There are three possibilities to connect to an interbase db + if (!$this->server) + { + $use_database = $this->dbname; + } + else if (strpos($this->server, '//') === 0) + { + $use_database = $this->server . $this->dbname; + } + else + { + $use_database = $this->server . ':' . $this->dbname; + } - $this->service_handle = (function_exists('ibase_service_attach')) ? @ibase_service_attach($this->server, $this->user, $sqlpassword) : false; + $this->db_connect_id = ($this->persistency) ? @ibase_pconnect($use_database, $this->user, $sqlpassword, false, false, 3) : @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3); + + $this->service_handle = (function_exists('ibase_service_attach') && $this->server) ? @ibase_service_attach($this->server, $this->user, $sqlpassword) : false; return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); } /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { if ($this->service_handle !== false && function_exists('ibase_server_info')) { return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION); } - return 'Firebird/Interbase'; + return ($raw) ? '2.0' : 'Firebird/Interbase'; } /** @@ -238,7 +254,7 @@ class dbal_firebird extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** @@ -409,7 +425,7 @@ class dbal_firebird extends dbal */ function sql_escape($msg) { - return str_replace("'", "''", $msg); + return str_replace(array("'", "\0"), array("''", ''), $msg); } /** diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php index b222588cf2..7134574691 100644 --- a/phpBB/includes/db/mssql.php +++ b/phpBB/includes/db/mssql.php @@ -32,9 +32,11 @@ class dbal_mssql extends dbal { $this->persistency = $persistency; $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); $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); @@ -62,24 +64,38 @@ class dbal_mssql extends dbal /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - $result_id = @mssql_query("SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')", $this->db_connect_id); + global $cache; - $row = false; - if ($result_id) + if (empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false) { - $row = @mssql_fetch_assoc($result_id); - @mssql_free_result($result_id); + $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)) + { + $cache->put('mssql_version', $this->sql_server_version); + } } - if ($row) + if ($raw) { - return 'MSSQL
' . implode(' ', $row); + return $this->sql_server_version; } - return 'MSSQL'; + return ($this->sql_server_version) ? 'MSSQL
' . $this->sql_server_version : 'MSSQL'; } /** @@ -162,7 +178,7 @@ class dbal_mssql extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** @@ -312,7 +328,7 @@ class dbal_mssql extends dbal */ function sql_escape($msg) { - return str_replace("'", "''", $msg); + return str_replace(array("'", "\0"), array("''", ''), $msg); } /** diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php index 7722f79952..14c4831010 100644 --- a/phpBB/includes/db/mssql_odbc.php +++ b/phpBB/includes/db/mssql_odbc.php @@ -40,9 +40,11 @@ class dbal_mssql_odbc extends dbal { $this->persistency = $persistency; $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); $this->dbname = $database; + $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; + $this->server = $sqlserver . (($port) ? $port_delimiter . $port : ''); + $max_size = @ini_get('odbc.defaultlrl'); if (!empty($max_size)) { @@ -73,24 +75,38 @@ class dbal_mssql_odbc extends dbal /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - $result_id = @odbc_exec($this->db_connect_id, "SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')"); + global $cache; - $row = false; - if ($result_id) + if (empty($cache) || ($this->sql_server_version = $cache->get('mssqlodbc_version')) === false) { - $row = @odbc_fetch_array($result_id); - @odbc_free_result($result_id); + $result_id = @odbc_exec($this->db_connect_id, "SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')"); + + $row = false; + if ($result_id) + { + $row = @odbc_fetch_array($result_id); + @odbc_free_result($result_id); + } + + $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; + + if (!empty($cache)) + { + $cache->put('mssqlodbc_version', $this->sql_server_version); + } } - if ($row) + if ($raw) { - return 'MSSQL (ODBC)
' . implode(' ', $row); + return $this->sql_server_version; } - return 'MSSQL (ODBC)'; + return ($this->sql_server_version) ? 'MSSQL (ODBC)
' . $this->sql_server_version : 'MSSQL (ODBC)'; } /** @@ -174,7 +190,7 @@ class dbal_mssql_odbc extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** @@ -333,7 +349,7 @@ class dbal_mssql_odbc extends dbal */ function sql_escape($msg) { - return str_replace("'", "''", $msg); + return str_replace(array("'", "\0"), array("''", ''), $msg); } /** diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php index 2d689f86f9..080f3d541a 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -29,7 +29,6 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); */ class dbal_mysql extends dbal { - var $mysql_version; var $multi_insert = true; /** @@ -52,13 +51,12 @@ class dbal_mysql extends dbal if (@mysql_select_db($this->dbname, $this->db_connect_id)) { // Determine what version we are using and if it natively supports UNICODE - $this->mysql_version = mysql_get_server_info($this->db_connect_id); - - if (version_compare($this->mysql_version, '4.1.3', '>=')) + if (version_compare($this->sql_server_info(true), '4.1.3', '>=')) { @mysql_query("SET NAMES 'utf8'", $this->db_connect_id); + // enforce strict mode on databases that support it - if (version_compare($this->mysql_version, '5.0.2', '>=')) + 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); @@ -83,7 +81,7 @@ class dbal_mysql extends dbal @mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id); } } - else if (version_compare($this->mysql_version, '4.0.0', '<')) + else if (version_compare($this->sql_server_info(true), '4.0.0', '<')) { $this->sql_layer = 'mysql'; } @@ -97,10 +95,28 @@ class dbal_mysql extends dbal /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - return 'MySQL ' . $this->mysql_version; + global $cache; + + if (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); + + $this->sql_server_version = $row['version']; + + if (!empty($cache)) + { + $cache->put('mysql_version', $this->sql_server_version); + } + } + + return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version; } /** @@ -183,7 +199,7 @@ class dbal_mysql extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** @@ -367,13 +383,9 @@ class dbal_mysql extends dbal if ($test_prof === null) { $test_prof = false; - if (strpos($this->mysql_version, 'community') !== false) + if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) { - $ver = substr($this->mysql_version, 0, strpos($this->mysql_version, '-')); - if (version_compare($ver, '5.0.37', '>=') && version_compare($ver, '5.1', '<')) - { - $test_prof = true; - } + $test_prof = true; } } diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index 32765d15f7..f0e58fd148 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -45,12 +45,14 @@ class dbal_mysqli extends dbal if ($this->db_connect_id && $this->dbname != '') { @mysqli_query($this->db_connect_id, "SET NAMES 'utf8'"); + // enforce strict mode on databases that support it - if (mysqli_get_server_version($this->db_connect_id) >= 50002) + 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'); $row = @mysqli_fetch_assoc($result); @mysqli_free_result($result); + $modes = array_map('trim', explode(',', $row['sql_mode'])); // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES @@ -78,10 +80,28 @@ class dbal_mysqli extends dbal /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - return 'MySQL(i) ' . @mysqli_get_server_info($this->db_connect_id); + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->get('mysqli_version')) === false) + { + $result = @mysqli_query($this->db_connect_id, 'SELECT VERSION() AS version'); + $row = @mysqli_fetch_assoc($result); + @mysqli_free_result($result); + + $this->sql_server_version = $row['version']; + + if (!empty($cache)) + { + $cache->put('mysqli_version', $this->sql_server_version); + } + } + + return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; } /** @@ -163,7 +183,7 @@ class dbal_mysqli extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index a63c06e5c0..8fdb29ce5b 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -55,10 +55,31 @@ class dbal_oracle extends dbal /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - return @ociserverversion($this->db_connect_id); +/* + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->get('oracle_version')) === false) + { + $result = @ociparse($this->db_connect_id, 'SELECT * FROM v$version WHERE banner LIKE \'Oracle%\''); + @ociexecute($result, OCI_DEFAULT); + @ocicommit($this->db_connect_id); + + $row = array(); + @ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS); + @ocifreestatement($result); + $this->sql_server_version = trim($row['BANNER']); + + $cache->put('oracle_version', $this->sql_server_version); + } +*/ + $this->sql_server_version = @ociserverversion($this->db_connect_id); + + return $this->sql_server_version; } /** @@ -355,7 +376,7 @@ class dbal_oracle extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** @@ -530,7 +551,7 @@ class dbal_oracle extends dbal */ function sql_escape($msg) { - return str_replace("'", "''", $msg); + return str_replace(array("'", "\0"), array("''", ''), $msg); } /** diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php index bb689a7394..83678e2904 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/postgres.php @@ -26,7 +26,6 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); class dbal_postgres extends dbal { var $last_query_text = ''; - var $pgsql_version; /** * Connect to server @@ -81,24 +80,7 @@ class dbal_postgres extends dbal if ($this->db_connect_id) { - // determine what version of PostgreSQL is running, we can be more efficient if they are running 8.2+ - if (version_compare(PHP_VERSION, '5.0.0', '>=')) - { - $this->pgsql_version = @pg_parameter_status($this->db_connect_id, 'server_version'); - } - else - { - $query_id = @pg_query($this->db_connect_id, 'SELECT VERSION()'); - $row = @pg_fetch_assoc($query_id, null); - @pg_free_result($query_id); - - if (!empty($row['version'])) - { - $this->pgsql_version = substr($row['version'], 10); - } - } - - if (!empty($this->pgsql_version) && $this->pgsql_version[0] >= '8' && $this->pgsql_version[2] >= '2') + if (version_compare($this->sql_server_info(true), '8.2', '>=')) { $this->multi_insert = true; } @@ -115,10 +97,28 @@ class dbal_postgres extends dbal /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - return 'PostgreSQL ' . $this->pgsql_version; + global $cache; + + if (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); + + $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0; + + if (!empty($cache)) + { + $cache->put('pgsql_version', $this->sql_server_version); + } + } + + return ($raw) ? $this->sql_server_version : 'PostgreSQL ' . $this->sql_server_version; } /** @@ -202,7 +202,7 @@ class dbal_postgres extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php index 5ae36df4f5..288f6e0992 100644 --- a/phpBB/includes/db/sqlite.php +++ b/phpBB/includes/db/sqlite.php @@ -41,18 +41,31 @@ class dbal_sqlite extends dbal 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); } /** * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version */ - function sql_server_info() + function sql_server_info($raw = false) { - return 'SQLite ' . @sqlite_libversion(); + global $cache; + + if (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; + $cache->put('sqlite_version', $this->sql_server_version); + } + + return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version; } /** @@ -135,7 +148,7 @@ class dbal_sqlite extends dbal return false; } - return ($this->query_result) ? $this->query_result : false; + return $this->query_result; } /** diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php index 0b3d14dbda..ef018b2d9a 100644 --- a/phpBB/includes/diff/diff.php +++ b/phpBB/includes/diff/diff.php @@ -17,7 +17,7 @@ if (!defined('IN_PHPBB')) } /** -* Code from pear.php.net, Text_Diff-0.2.1 (beta) package +* Code from pear.php.net, Text_Diff-1.0.0 package * http://pear.php.net/package/Text_Diff/ * * Modified by phpBB Group to meet our coding standards @@ -26,6 +26,9 @@ if (!defined('IN_PHPBB')) * General API for generating and formatting diffs - the differences between * two sequences of strings. * +* Copyright 2004 Geoffrey T. Dairiki +* Copyright 2004-2008 The Horde Project (http://www.horde.org/) +* * @package diff * @author Geoffrey T. Dairiki */ @@ -45,7 +48,7 @@ class diff */ function diff(&$from_content, &$to_content, $preserve_cr = true) { - $diff_engine = &new diff_engine(); + $diff_engine = new diff_engine(); $this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr); } @@ -62,7 +65,7 @@ class diff * * Example: * - * $diff = &new diff($lines1, $lines2); + * $diff = new diff($lines1, $lines2); * $rev = $diff->reverse(); * * @@ -285,7 +288,7 @@ class diff_op var $orig; var $final; - function reverse() + function &reverse() { trigger_error('[diff] Abstract method', E_USER_ERROR); } @@ -321,7 +324,7 @@ class diff_op_copy extends diff_op function &reverse() { - $reverse = &new diff_op_copy($this->final, $this->orig); + $reverse = new diff_op_copy($this->final, $this->orig); return $reverse; } } @@ -342,7 +345,7 @@ class diff_op_delete extends diff_op function &reverse() { - $reverse = &new diff_op_add($this->orig); + $reverse = new diff_op_add($this->orig); return $reverse; } } @@ -363,7 +366,7 @@ class diff_op_add extends diff_op function &reverse() { - $reverse = &new diff_op_delete($this->final); + $reverse = new diff_op_delete($this->final); return $reverse; } } @@ -384,7 +387,7 @@ class diff_op_change extends diff_op function &reverse() { - $reverse = &new diff_op_change($this->final, $this->orig); + $reverse = new diff_op_change($this->final, $this->orig); return $reverse; } } @@ -413,7 +416,7 @@ class diff3 extends diff */ function diff3(&$orig, &$final1, &$final2) { - $diff_engine = &new diff_engine(); + $diff_engine = new diff_engine(); $diff_1 = $diff_engine->diff($orig, $final1); $diff_2 = $diff_engine->diff($orig, $final2); @@ -548,7 +551,7 @@ class diff3 extends diff function _diff3(&$edits1, &$edits2) { $edits = array(); - $bb = &new diff3_block_builder(); + $bb = new diff3_block_builder(); $e1 = current($edits1); $e2 = current($edits2); @@ -565,7 +568,7 @@ class diff3 extends diff } $ncopy = min($e1->norig(), $e2->norig()); - $edits[] = &new diff3_op_copy(array_slice($e1->orig, 0, $ncopy)); + $edits[] = new diff3_op_copy(array_slice($e1->orig, 0, $ncopy)); if ($e1->norig() > $ncopy) { @@ -759,7 +762,7 @@ class diff3_block_builder } else { - $edit = &new diff3_op($this->orig, $this->final1, $this->final2); + $edit = new diff3_op($this->orig, $this->final1, $this->final2); $this->_init(); return $edit; } diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php index 576839ea60..d82afb048a 100644 --- a/phpBB/includes/diff/engine.php +++ b/phpBB/includes/diff/engine.php @@ -17,21 +17,20 @@ if (!defined('IN_PHPBB')) } /** -* Code from pear.php.net, Text_Diff-0.2.1 (beta) package -* http://pear.php.net/package/Text_Diff/ +* Code from pear.php.net, Text_Diff-1.0.0 package +* http://pear.php.net/package/Text_Diff/ (native engine) * * Modified by phpBB Group to meet our coding standards * and being able to integrate into phpBB * -* Class used internally by Diff to actually compute the diffs. This class is -* implemented using native PHP code. +* Class used internally by Text_Diff to actually compute the diffs. This +* class is implemented using native PHP code. * * The algorithm used here is mostly lifted from the perl module * Algorithm::Diff (version 1.06) by Ned Konz, which is available at: * http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip * -* More ideas are taken from: -* http://www.ics.uci.edu/~eppstein/161/960229.html +* More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html * * Some ideas (and a bit of code) are taken from analyze.c, of GNU * diffutils-2.7, which can be found at: @@ -41,6 +40,8 @@ if (!defined('IN_PHPBB')) * Geoffrey T. Dairiki . The original PHP version of this * code was written by him, and is used/adapted with his permission. * +* Copyright 2004-2008 The Horde Project (http://www.horde.org/) +* * @author Geoffrey T. Dairiki * @package diff * @@ -159,7 +160,7 @@ class diff_engine if ($copy) { - $edits[] = &new diff_op_copy($copy); + $edits[] = new diff_op_copy($copy); } // Find deletes & adds. @@ -177,15 +178,15 @@ class diff_engine if ($delete && $add) { - $edits[] = &new diff_op_change($delete, $add); + $edits[] = new diff_op_change($delete, $add); } else if ($delete) { - $edits[] = &new diff_op_delete($delete); + $edits[] = new diff_op_delete($delete); } else if ($add) { - $edits[] = &new diff_op_add($add); + $edits[] = new diff_op_add($add); } } @@ -251,7 +252,7 @@ class diff_engine } } - $x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks); + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); for (; $x < $x1; $x++) { @@ -262,7 +263,8 @@ class diff_engine } $matches = $ymatches[$line]; - foreach ($matches as $y) + reset($matches); + while (list(, $y) = each($matches)) { if (empty($this->in_seq[$y])) { @@ -273,7 +275,7 @@ class diff_engine } // no reset() here - while (list($junk, $y) = each($matches)) + while (list(, $y) = each($matches)) { if ($y > $this->seq[$k - 1]) { diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php index f4a0bce3f9..2e0ec86e75 100644 --- a/phpBB/includes/diff/renderer.php +++ b/phpBB/includes/diff/renderer.php @@ -17,7 +17,7 @@ if (!defined('IN_PHPBB')) } /** -* Code from pear.php.net, Text_Diff-0.2.1 (beta) package +* Code from pear.php.net, Text_Diff-1.0.0 package * http://pear.php.net/package/Text_Diff/ * * Modified by phpBB Group to meet our coding standards @@ -28,6 +28,8 @@ if (!defined('IN_PHPBB')) * This class renders the diff in classic diff format. It is intended that * this class be customized via inheritance, to obtain fancier outputs. * +* Copyright 2004-2008 The Horde Project (http://www.horde.org/) +* * @package diff */ class diff_renderer @@ -105,7 +107,7 @@ class diff_renderer unset($diff3); - $diff = &new diff($diff_1, $diff_2); + $diff = new diff($diff_1, $diff_2); } $nlead = $this->_leading_context_lines; @@ -116,33 +118,41 @@ class diff_renderer foreach ($diffs as $i => $edit) { + // If these are unchanged (copied) lines, and we want to keep leading or trailing context lines, extract them from the copy block. if (is_a($edit, 'diff_op_copy')) { + // Do we have any diff blocks yet? if (is_array($block)) { + // How many lines to keep as context from the copy block. $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail; if (sizeof($edit->orig) <= $keep) { + // We have less lines in the block than we want for context => keep the whole block. $block[] = $edit; } else { if ($ntrail) { + // Create a new block with as many lines as we need for the trailing context. $context = array_slice($edit->orig, 0, $ntrail); - $block[] = &new diff_op_copy($context); + $block[] = new diff_op_copy($context); } $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block); $block = false; } } + // Keep the copy block as the context for the next block. $context = $edit->orig; } else { + // Don't we have any diff blocks yet? if (!is_array($block)) { + // Extract context lines from the preceding copy block. $context = array_slice($context, sizeof($context) - $nlead); $x0 = $xi - sizeof($context); $y0 = $yi - sizeof($context); @@ -150,7 +160,7 @@ class diff_renderer if ($context) { - $block[] = &new diff_op_copy($context); + $block[] = new diff_op_copy($context); } } $block[] = $edit; @@ -219,6 +229,16 @@ class diff_renderer $ybeg .= ',' . ($ybeg + $ylen - 1); } + // this matches the GNU Diff behaviour + if ($xlen && !$ylen) + { + $ybeg--; + } + else if (!$xlen) + { + $xbeg--; + } + return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; } @@ -449,11 +469,11 @@ class diff_renderer_inline extends diff_renderer $splitted_text_1 = $this->_split_on_words($text1, $nl); $splitted_text_2 = $this->_split_on_words($text2, $nl); - $diff = &new diff($splitted_text_1, $splitted_text_2); + $diff = new diff($splitted_text_1, $splitted_text_2); unset($splitted_text_1, $splitted_text_2); // Get the diff in inline format. - $renderer = &new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words'))); + $renderer = new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words'))); // Run the diff and get the output. return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 8c194f4fc2..fabb1e1aa3 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -32,7 +32,7 @@ function set_var(&$result, $var, $type, $multibyte = false) if ($type == 'string') { - $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r"), array("\n", "\n"), $result), ENT_COMPAT, 'UTF-8')); + $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8')); if (!empty($result)) { @@ -320,6 +320,11 @@ function phpbb_hash($password) /** * Check for correct password +* +* @param string $password The password in plain text +* @param string $hash The stored password hash +* +* @return bool Returns true if the password is correct, false if not. */ function phpbb_check_hash($password, $hash) { @@ -454,6 +459,142 @@ function _hash_crypt_private($password, $setting, &$itoa64) return $output; } +/** +* 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 $filename The file/directory to be chmodded +* @param $perms Permissions to set +* @return true on success, otherwise false +* +* @author faw, phpBB Group +*/ +function phpbb_chmod($filename, $perms = CHMOD_READ) +{ + // Return if the file no longer exists. + if (!file_exists($filename)) + { + return false; + } + + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + $file_uid = $file_gid = false; + $common_php_owner = $common_php_group = 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); + + $file_uid = fileowner($filename); + $file_gid = filegroup($filename); + + // Try to set the owner to the same common.php has + if ($common_php_owner !== $file_uid && $common_php_owner !== false && $file_uid !== false) + { + // Will most likely not work + if (@chown($filename, $common_php_owner)); + { + $file_uid = fileowner($filename); + } + } + + // Try to set the group to the same common.php has + if ($common_php_group !== $file_gid && $common_php_group !== false && $file_gid !== false) + { + if (@chgrp($filename, $common_php_group)); + { + $file_gid = filegroup($filename); + } + } + } + + // 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; + + // Who is PHP? + if ($file_uid === false || $file_gid === false || $php_uid === false || $php_gids === false) + { + $php = null; + } + else if ($file_uid == $php_uid /* && $common_php_owner !== false && $common_php_owner === $file_uid*/) + { + $php = 'owner'; + } + else if (in_array($file_gid, $php_gids)) + { + $php = 'group'; + } + else + { + $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 null: + case 'owner': + $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); + + if (!is_null($php) || (is_readable($filename) && is_writable($filename))) + { + break; + } + + case 'group': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); + + if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + { + break; + } + + case 'other': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); + + if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + { + break; + } + + default: + return false; + break; + } + + return $result; +} + // Compatibility functions if (!function_exists('array_combine')) @@ -1766,6 +1907,7 @@ function generate_board_url($without_script_path = false) $script_path = $config['script_path']; $url = $server_protocol . $server_name; + $cookie_secure = $config['cookie_secure']; } else { @@ -1776,7 +1918,7 @@ function generate_board_url($without_script_path = false) $script_path = $user->page['root_script_path']; } - if ($server_port && (($config['cookie_secure'] && $server_port <> 443) || (!$config['cookie_secure'] && $server_port <> 80))) + if ($server_port && (($cookie_secure && $server_port <> 443) || (!$cookie_secure && $server_port <> 80))) { // HTTP HOST can carry a port number (we fetch $user->host, but for old versions this may be true) if (strpos($server_name, ':') === false) @@ -1902,7 +2044,7 @@ function redirect($url, $return = false, $disable_cd_check = false) $url = substr($url, 1); } - $url = $dir . '/' . $url; + $url = (!empty($dir) ? $dir . '/' : '') . $url; $url = generate_board_url() . '/' . $url; } } @@ -2066,6 +2208,37 @@ function meta_refresh($time, $url) //Form validation + +/** +* Add a secret hash for use in links/GET requests +* @param string $link_name The name of the link; has to match the name used in check_link_hash, otherwise no restrictions apply +* @return string the hash + +*/ +function generate_link_hash($link_name) +{ + global $user; + + if (!isset($user->data["hash_$link_name"])) + { + $user->data["hash_$link_name"] = substr(sha1($user->data['user_form_salt'] . $link_name), 0, 8); + } + + return $user->data["hash_$link_name"]; +} + + +/** +* checks a link hash - for GET requests +* @param string $token the submitted token +* @param string $link_name The name of the link +* @return boolean true if all is fine +*/ +function check_link_hash($token, $link_name) +{ + return $token === generate_link_hash($link_name); +} + /** * Add a secret token to the form (requires the S_FORM_TOKEN template variable) * @param string $form_name The name of the form; has to match the name used in check_form_key, otherwise no restrictions apply @@ -2073,16 +2246,18 @@ function meta_refresh($time, $url) function add_form_key($form_name) { global $config, $template, $user; + $now = time(); $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : ''; $token = sha1($now . $user->data['user_form_salt'] . $form_name . $token_sid); $s_fields = build_hidden_fields(array( - 'creation_time' => $now, - 'form_token' => $token, + 'creation_time' => $now, + 'form_token' => $token, )); + $template->assign_vars(array( - 'S_FORM_TOKEN' => $s_fields, + 'S_FORM_TOKEN' => $s_fields, )); } @@ -2108,23 +2283,26 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg $creation_time = abs(request_var('creation_time', 0)); $token = request_var('form_token', ''); - $diff = (time() - $creation_time); + $diff = time() - $creation_time; - if (($diff <= $timespan) || $timespan === -1) + // If creation_time and the time() now is zero we can assume it was not a human doing this (the check for if ($diff)... + if ($diff && ($diff <= $timespan || $timespan === -1)) { $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : ''; - $key = sha1($creation_time . $user->data['user_form_salt'] . $form_name . $token_sid); + if ($key === $token) { return true; } } } + if ($trigger) { trigger_error($user->lang['FORM_INVALID'] . $return_page); } + return false; } @@ -2960,7 +3138,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) } // Another quick fix for those having gzip compression enabled, but do not flush if the coder wants to catch "something". ;) - if ($config['gzip_compress']) + if (!empty($config['gzip_compress'])) { if (@extension_loaded('zlib') && !headers_sent() && !ob_get_level()) { @@ -3050,6 +3228,9 @@ function msg_handler($errno, $msg_text, $errfile, $errline) echo ''; exit_handler(); + + // On a fatal error (and E_USER_ERROR *is* fatal) we never want other scripts to continue and force an exit here. + exit; break; case E_USER_WARNING: @@ -3409,7 +3590,7 @@ function page_header($page_title = '', $display_online_list = true) $s_privmsg_new = false; // Obtain number of new private messages if user is logged in - if (isset($user->data['is_registered']) && $user->data['is_registered']) + if (!empty($user->data['is_registered'])) { if ($user->data['user_new_privmsg']) { @@ -3500,14 +3681,14 @@ function page_header($page_title = '', $display_online_list = true) 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), 'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'), 'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'), - 'U_TEAM' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'), + 'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'), 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false, 'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false, 'S_BOARD_DISABLED' => ($config['board_disable']) ? true : false, - 'S_REGISTERED_USER' => $user->data['is_registered'], - 'S_IS_BOT' => $user->data['is_bot'], + 'S_REGISTERED_USER' => (!empty($user->data['is_registered'])) ? true : false, + 'S_IS_BOT' => (!empty($user->data['is_bot'])) ? true : false, 'S_USER_PM_POPUP' => $user->optionget('popuppm'), 'S_USER_LANG' => $user_lang, 'S_USER_BROWSER' => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'], @@ -3519,13 +3700,14 @@ function page_header($page_title = '', $display_online_list = true) 'S_TIMEZONE' => ($user->data['user_dst'] || ($user->data['user_id'] == ANONYMOUS && $config['board_dst'])) ? sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], $user->lang['tz']['dst']) : sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], ''), 'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0, 'S_DISPLAY_SEARCH' => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1), - 'S_DISPLAY_PM' => ($config['allow_privmsg'] && $user->data['is_registered'] && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false, + 'S_DISPLAY_PM' => ($config['allow_privmsg'] && !empty($user->data['is_registered']) && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false, 'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0, 'S_NEW_PM' => ($s_privmsg_new) ? 1 : 0, 'S_REGISTER_ENABLED' => ($config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false, 'T_THEME_PATH' => "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme', 'T_TEMPLATE_PATH' => "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template', + 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path'])) ? "{$phpbb_root_path}styles/" . $user->theme['template_inherit_path'] . '/template' : '', 'T_IMAGESET_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset', 'T_IMAGESET_LANG_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'], 'T_IMAGES_PATH' => "{$phpbb_root_path}images/", @@ -3538,8 +3720,10 @@ function page_header($page_title = '', $display_online_list = true) 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&id=" . $user->theme['style_id'] . '&lang=' . $user->data['user_lang'], 'T_STYLESHEET_NAME' => $user->theme['theme_name'], - 'SITE_LOGO_IMG' => $user->img('site_logo')) - ); + 'SITE_LOGO_IMG' => $user->img('site_logo'), + + 'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')), + )); // application/xhtml+xml not used because of IE header('Content-type: text/html; charset=UTF-8'); @@ -3593,7 +3777,7 @@ function page_footer($run_cron = true) 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '', 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', - 'U_ACP' => ($auth->acl_get('a_') && $user->data['is_registered']) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '') + 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '') ); // Call cron-type script @@ -3682,7 +3866,7 @@ function exit_handler() } // As a pre-caution... some setups display a blank page if the flush() is not there. - (!$config['gzip_compress']) ? @flush() : @ob_flush(); + (empty($config['gzip_compress'])) ? @flush() : @ob_flush(); exit; } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 028456c246..0349cbc6a8 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -97,7 +97,7 @@ function recalc_btree($sql_id, $sql_table, $module_class = '') $item_data['left_id'] = $row['right_id'] + 1; $item_data['right_id'] = $row['right_id'] + 2; } - + $sql = "UPDATE $sql_table SET left_id = {$item_data['left_id']}, right_id = {$item_data['right_id']} WHERE $sql_id = " . $item_data[$sql_id]; @@ -551,7 +551,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s 'posts' => ($call_delete_posts) ? delete_posts($where_type, $where_ids, false, true, $post_count_sync, false) : 0, ); - $sql = 'SELECT topic_id, forum_id, topic_approved + $sql = 'SELECT topic_id, forum_id, topic_approved, topic_moved_id FROM ' . TOPICS_TABLE . ' WHERE ' . $where_clause; $result = $db->sql_query($sql); @@ -561,7 +561,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s $forum_ids[] = $row['forum_id']; $topic_ids[] = $row['topic_id']; - if ($row['topic_approved']) + if ($row['topic_approved'] && !$row['topic_moved_id']) { $approved_topics++; } @@ -670,7 +670,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $topic_ids[] = $row['topic_id']; $forum_ids[] = $row['forum_id']; - if ($row['post_postcount'] && $post_count_sync) + if ($row['post_postcount'] && $post_count_sync && $row['post_approved']) { $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; } @@ -709,6 +709,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = WHERE user_id = ' . $poster_id . ' AND user_posts < ' . $substract; $db->sql_query($sql); + $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = user_posts - ' . $substract . ' WHERE user_id = ' . $poster_id . ' @@ -790,8 +791,8 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = /** * Delete Attachments * -* @param string $mode can be: post|topic|attach|user -* @param mixed $ids can be: post_ids, topic_ids, attach_ids, user_ids +* @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) @@ -813,42 +814,55 @@ function delete_attachments($mode, $ids, $resync = true) return false; } - $sql_id = ($mode == 'user') ? 'poster_id' : (($mode == 'post') ? 'post_msg_id' : (($mode == 'topic') ? 'topic_id' : 'attach_id')); - - $post_ids = $topic_ids = $physical = array(); - - // Collect post and topics ids for later use - if ($mode == 'attach' || $mode == 'user' || ($mode == 'topic' && $resync)) + switch ($mode) { - $sql = 'SELECT post_msg_id as post_id, topic_id, physical_filename, thumbnail, filesize + case 'post': + case 'message': + $sql_id = 'post_msg_id'; + 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(); + + // 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); - $result = $db->sql_query($sql); + $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $post_ids[] = $row['post_id']; - $topic_ids[] = $row['topic_id']; - $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']); - } - $db->sql_freeresult($result); - } - - if ($mode == 'post') + while ($row = $db->sql_fetchrow($result)) { - $sql = 'SELECT topic_id, physical_filename, thumbnail, filesize - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('post_msg_id', $ids) . ' - AND in_message = 0'; - $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']) { - $topic_ids[] = $row['topic_id']; - $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']); + if (!$row['in_message']) + { + $post_ids[] = $row['post_msg_id']; + $topic_ids[] = $row['topic_id']; + } + else + { + $message_ids[] = $row['post_msg_id']; + } } - $db->sql_freeresult($result); + + $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']); } + $db->sql_freeresult($result); // Delete attachments $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' @@ -865,8 +879,9 @@ function delete_attachments($mode, $ids, $resync = true) $space_removed = $files_removed = 0; foreach ($physical as $file_ary) { - if (phpbb_unlink($file_ary['filename'], 'file', true)) + 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++; } @@ -876,122 +891,72 @@ function delete_attachments($mode, $ids, $resync = true) phpbb_unlink($file_ary['filename'], 'thumbnail', true); } } - set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true); - set_config('num_files', $config['num_files'] - $files_removed, true); - if ($mode == 'topic' && !$resync) + if ($space_removed || $files_removed) + { + set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true); + set_config('num_files', $config['num_files'] - $files_removed, true); + } + + // If we do not resync, we do not need to adjust any message, post, topic or user entries + if (!$resync) { return $num_deleted; } - if ($mode == 'post') - { - $post_ids = $ids; - } + // 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 + // Update post indicators for posts now no longer having attachments if (sizeof($post_ids)) { - if ($mode == 'post' || $mode == 'topic') - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_attachment = 0 - WHERE ' . $db->sql_in_set('post_id', $post_ids); - $db->sql_query($sql); - } - - if ($mode == 'user' || $mode == 'attach') - { - $remaining = array(); - - $sql = 'SELECT post_msg_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' - AND in_message = 0'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $remaining[] = $row['post_msg_id']; - } - $db->sql_freeresult($result); - - $unset_ids = array_diff($post_ids, $remaining); - - if (sizeof($unset_ids)) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_attachment = 0 - WHERE ' . $db->sql_in_set('post_id', $unset_ids); - $db->sql_query($sql); - } - - $remaining = array(); - - $sql = 'SELECT post_msg_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' - AND in_message = 1'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $remaining[] = $row['post_msg_id']; - } - $db->sql_freeresult($result); - - $unset_ids = array_diff($post_ids, $remaining); - - if (sizeof($unset_ids)) - { - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET message_attachment = 0 - WHERE ' . $db->sql_in_set('msg_id', $unset_ids); - $db->sql_query($sql); - } - } + $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)) + { + $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)) { - // Update topic indicator - if ($mode == 'topic') + // 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); + + // Now only unset those ids remaining + $topic_ids = array_diff($topic_ids, $remaining_ids); + + 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); } - - if ($mode == 'post' || $mode == 'user' || $mode == 'attach') - { - $remaining = array(); - - $sql = 'SELECT topic_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $db->sql_in_set('topic_id', $topic_ids); - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $remaining[] = $row['topic_id']; - } - $db->sql_freeresult($result); - - $unset_ids = array_diff($topic_ids, $remaining); - - if (sizeof($unset_ids)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_attachment = 0 - WHERE ' . $db->sql_in_set('topic_id', $unset_ids); - $db->sql_query($sql); - } - } } return $num_deleted; @@ -1015,7 +980,7 @@ function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true) . $where; $db->sql_query($sql); break; - + default: $sql = 'SELECT t.topic_id FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2 @@ -1213,7 +1178,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, AND t1.forum_id = t2.forum_id"; $db->sql_query($sql); break; - + default: $sql = 'SELECT t1.topic_id FROM ' .TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2 @@ -2369,7 +2334,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id $log_type = LOG_USERS; $sql_forum = 'AND l.reportee_id = ' . (int) $user_id; break; - + case 'users': $log_type = LOG_USERS; $sql_forum = ''; @@ -2379,7 +2344,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id $log_type = LOG_CRITICAL; $sql_forum = ''; break; - + default: return; } @@ -2433,8 +2398,14 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id if (isset($user->lang[$row['log_operation']])) { - // We supress the warning about inappropriate number of passed parameters here due to possible changes within LOG strings from one version to another. - $log[$i]['action'] = @vsprintf($log[$i]['action'], $log_data_ary); + // Check if there are more occurrences of % than arguments, if there are we fill out the arguments array + // It doesn't matter if we add more arguments than placeholders + if (substr_count($log[$i]['action'], '%') - sizeof($log_data_ary)) + { + $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($log[$i]['action'], '%') - sizeof($log_data_ary), '')); + } + + $log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); // If within the admin panel we do not censor text out if (defined('IN_ADMIN')) @@ -2615,7 +2586,7 @@ function update_foes($group_id = false, $user_id = false) { case 'mysqli': case 'mysql4': - $sql = 'DELETE ' . (($db->sql_layer === 'mysqli' || version_compare($db->mysql_version, '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . ' + $sql = 'DELETE ' . (($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . ' FROM ' . ZEBRA_TABLE . ' z, ' . USER_GROUP_TABLE . ' ug WHERE z.zebra_id = ug.user_id AND z.foe = 1 @@ -2637,7 +2608,7 @@ function update_foes($group_id = false, $user_id = false) $db->sql_freeresult($result); if (sizeof($users)) - { + { $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' WHERE ' . $db->sql_in_set('zebra_id', $users) . ' AND foe = 1'; @@ -2717,7 +2688,7 @@ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $li $row['inactive_reason'] = $user->lang['INACTIVE_REASON_REMIND']; break; } - + $users[] = $row; } @@ -2897,7 +2868,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port @fputs($fsock, "GET $directory/$filename HTTP/1.1\r\n"); @fputs($fsock, "HOST: $host\r\n"); @fputs($fsock, "Connection: close\r\n\r\n"); - + $file_info = ''; $get_info = false; @@ -2936,7 +2907,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port return false; } } - + return $file_info; } @@ -2972,7 +2943,7 @@ function tidy_warnings() $sql = 'DELETE FROM ' . WARNINGS_TABLE . ' WHERE ' . $db->sql_in_set('warning_id', $warning_list); $db->sql_query($sql); - + foreach ($user_list as $user_id => $value) { $sql = 'UPDATE ' . USERS_TABLE . " SET user_warnings = user_warnings - $value @@ -3034,7 +3005,7 @@ function add_permission_language() // Now search in acp and mods folder for permissions_ files. foreach (array('acp/', 'mods/') as $path) { - $dh = @opendir($user->lang_path . $path); + $dh = @opendir($user->lang_path . $user->lang_name . '/' . $path); if ($dh) { diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index 021079deef..881e1ba5cc 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -228,7 +228,7 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - @chmod($str, 0777); + phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); } } } @@ -257,7 +257,7 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - @chmod($str, 0777); + phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); } } } @@ -544,7 +544,7 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - @chmod($str, 0777); + phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); } } } @@ -571,7 +571,7 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - @chmod($str, 0777); + phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); } } @@ -580,7 +580,7 @@ class compress_tar extends compress { trigger_error("Couldn't create file $filename"); } - @chmod($target_filename, 0777); + phpbb_chmod($target_filename, CHMOD_READ); // 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 ced5106c14..627e6a71cd 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -41,57 +41,66 @@ if (!defined('IN_PHPBB')) /** * Generate sort selection fields */ -function 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) +function 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, $def_st = false, $def_sk = false, $def_sd = false) { global $user; $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); - // Check if the key is selectable. If not, we reset to the first key found. - // This ensures the values are always valid. - if (!isset($limit_days[$sort_days])) - { - @reset($limit_days); - $sort_days = key($limit_days); - } + $sorts = array( + 'st' => array( + 'key' => 'sort_days', + 'default' => $def_st, + 'options' => $limit_days, + 'output' => &$s_limit_days, + ), - if (!isset($sort_by_text[$sort_key])) - { - @reset($sort_by_text); - $sort_key = key($sort_by_text); - } + 'sk' => array( + 'key' => 'sort_key', + 'default' => $def_sk, + 'options' => $sort_by_text, + 'output' => &$s_sort_key, + ), - if (!isset($sort_dir_text[$sort_dir])) - { - @reset($sort_dir_text); - $sort_dir = key($sort_dir_text); - } + 'sd' => array( + 'key' => 'sort_dir', + 'default' => $def_sd, + 'options' => $sort_dir_text, + 'output' => &$s_sort_dir, + ), + ); + $u_sort_param = ''; - $s_limit_days = ''; + $key = $sort_ary['key']; + $selected = $$sort_ary['key']; - $s_sort_key = ''; + // Check if the key is selectable. If not, we reset to the default or first key found. + // This ensures the values are always valid. We also set $sort_dir/sort_key/etc. to the + // correct value, else the protection is void. ;) + if (!isset($sort_ary['options'][$selected])) + { + if ($sort_ary['default'] !== false) + { + $selected = $$key = $sort_ary['default']; + } + else + { + @reset($sort_ary['options']); + $selected = $$key = key($sort_ary['options']); + } + } - $s_sort_dir = ''; + $sort_ary['output'] = ''; - $u_sort_param = "st=$sort_days&sk=$sort_key&sd=$sort_dir"; + $u_sort_param .= ($selected !== $sort_ary['default']) ? ((strlen($u_sort_param)) ? '&' : '') . "{$name}={$selected}" : ''; + } return; } @@ -239,7 +248,7 @@ function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_po function get_context($text, $words, $length = 400) { // first replace all whitespaces with single spaces - $text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", ' '), $text); + $text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", ' ')); $word_indizes = array(); if (sizeof($words)) diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index b6af76e8f6..2213df7d0f 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -1744,6 +1744,7 @@ function sync_post_count($offset, $limit) $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id FROM ' . POSTS_TABLE . ' WHERE post_postcount = 1 + AND post_approved = 1 GROUP BY poster_id ORDER BY poster_id'; $result = $db->sql_query_limit($sql, $limit, $offset); @@ -1951,7 +1952,7 @@ function update_dynamic_config() FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 0'; $result = $db->sql_query($sql); - set_config('upload_dir_size', (int) $db->sql_fetchfield('stat'), true); + set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true); $db->sql_freeresult($result); /** diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index b0cdd26eef..44bd0214fa 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -205,6 +205,12 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $subforums[$parent_id][$forum_id]['display'] = ($row['display_on_index']) ? true : false; $subforums[$parent_id][$forum_id]['name'] = $row['forum_name']; $subforums[$parent_id][$forum_id]['orig_forum_last_post_time'] = $row['forum_last_post_time']; + $subforums[$parent_id][$forum_id]['children'] = array(); + + if (isset($subforums[$parent_id][$row['parent_id']]) && !$row['display_on_index']) + { + $subforums[$parent_id][$row['parent_id']]['children'][] = $forum_id; + } $forum_rows[$parent_id]['forum_topics'] += $row['forum_topics']; @@ -231,23 +237,30 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod // Handle marking posts if ($mark_read == 'forums' || $mark_read == 'all') { - $redirect = build_url('mark'); - - if ($mark_read == 'all') + $redirect = build_url('mark', 'hash'); + $token = request_var('hash', ''); + if (check_link_hash($token, 'global')) { - markread('all'); - - $message = sprintf($user->lang['RETURN_INDEX'], '', ''); + if ($mark_read == 'all') + { + markread('all'); + $message = sprintf($user->lang['RETURN_INDEX'], '', ''); + } + else + { + markread('topics', $forum_ids); + $message = sprintf($user->lang['RETURN_FORUM'], '', ''); + } + meta_refresh(3, $redirect); + trigger_error($user->lang['FORUMS_MARKED'] . '

' . $message); } else { - markread('topics', $forum_ids); - - $message = sprintf($user->lang['RETURN_FORUM'], '', ''); + $message = sprintf($user->lang['RETURN_PAGE'], '', ''); + meta_refresh(3, $redirect); + trigger_error($message); } - meta_refresh(3, $redirect); - trigger_error($user->lang['FORUMS_MARKED'] . '

' . $message); } // Grab moderators ... if necessary @@ -297,6 +310,19 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod { $subforum_unread = (isset($forum_tracking_info[$subforum_id]) && $subforum_row['orig_forum_last_post_time'] > $forum_tracking_info[$subforum_id]) ? true : false; + if (!$subforum_unread && !empty($subforum_row['children'])) + { + foreach ($subforum_row['children'] as $child_id) + { + if (isset($forum_tracking_info[$child_id]) && $subforums[$forum_id][$child_id]['orig_forum_last_post_time'] > $forum_tracking_info[$child_id]) + { + // Once we found an unread child forum, we can drop out of this loop + $subforum_unread = true; + break; + } + } + } + if ($subforum_row['display'] && $subforum_row['name']) { $subforums_list[] = array( @@ -444,7 +470,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod } $template->assign_vars(array( - 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $root_data['forum_id'] . '&mark=forums') : '', + 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums') : '', 'S_HAS_SUBFORUM' => ($visible_forums) ? true : false, 'L_SUBFORUM' => ($visible_forums == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS'], 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST')) @@ -630,7 +656,7 @@ function topic_generate_pagination($replies, $url) */ function get_moderators(&$forum_moderators, $forum_id = false) { - global $config, $template, $db, $phpbb_root_path, $phpEx; + global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth; // Have we disabled the display of moderators? If so, then return // from whence we came ... @@ -689,7 +715,16 @@ function get_moderators(&$forum_moderators, $forum_id = false) } else { - $forum_moderators[$row['forum_id']][] = '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $group_name = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + + if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) + { + $forum_moderators[$row['forum_id']][] = '' . $group_name . ''; + } + else + { + $forum_moderators[$row['forum_id']][] = '' . $group_name . ''; + } } } $db->sql_freeresult($result); @@ -772,7 +807,8 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold $folder = 'topic_read'; $folder_new = 'topic_unread'; - if ($config['hot_threshold'] && $replies >= $config['hot_threshold'] && $topic_row['topic_status'] != ITEM_LOCKED) + // Hot topic threshold is for posts in a topic, which is replies + the first post. ;) + if ($config['hot_threshold'] && ($replies + 1) >= $config['hot_threshold'] && $topic_row['topic_status'] != ITEM_LOCKED) { $folder .= '_hot'; $folder_new .= '_hot'; @@ -988,8 +1024,8 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $table_sql = ($mode == 'forum') ? FORUMS_WATCH_TABLE : TOPICS_WATCH_TABLE; $where_sql = ($mode == 'forum') ? 'forum_id' : 'topic_id'; $match_id = ($mode == 'forum') ? $forum_id : $topic_id; - - $u_url = ($mode == 'forum') ? 'f' : 'f=' . $forum_id . '&t'; + $u_url = "uid={$user->data['user_id']}"; + $u_url .= ($mode == 'forum') ? '&f' : '&f=' . $forum_id . '&t'; // Is user watching this thread? if ($user_id != ANONYMOUS) @@ -1010,8 +1046,16 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, if (!is_null($notify_status) && $notify_status !== '') { + if (isset($_GET['unwatch'])) { + $uid = request_var('uid', 0); + if ($uid != $user_id) + { + $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); + $message = $user->lang['ERR_UNWATCHING'] . '

' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); + trigger_error($message); + } if ($_GET['unwatch'] == $mode) { $is_watching = 0; @@ -1047,19 +1091,25 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, { if (isset($_GET['watch'])) { - if ($_GET['watch'] == $mode) + $token = request_var('hash', ''); + $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); + + if ($_GET['watch'] == $mode && check_link_hash($token, "{$mode}_$match_id")) { $is_watching = true; $sql = 'INSERT INTO ' . $table_sql . " (user_id, $where_sql, notify_status) VALUES ($user_id, $match_id, 0)"; $db->sql_query($sql); + $message = $user->lang['ARE_WATCHING_' . strtoupper($mode)] . '

' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); + } + else + { + $message = $user->lang['ERR_WATCHING'] . '

' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); } - $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); meta_refresh(3, $redirect_url); - $message = $user->lang['ARE_WATCHING_' . strtoupper($mode)] . '

' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); trigger_error($message); } else @@ -1083,7 +1133,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, if ($can_watch) { - $s_watching['link'] = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&" . (($is_watching) ? 'unwatch' : 'watch') . "=$mode&start=$start"); + $s_watching['link'] = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&" . (($is_watching) ? 'unwatch' : 'watch') . "=$mode&start=$start&hash=" . generate_link_hash("{$mode}_$match_id")); $s_watching['title'] = $user->lang[(($is_watching) ? 'STOP' : 'START') . '_WATCHING_' . strtoupper($mode)]; $s_watching['is_watching'] = $is_watching; } @@ -1169,7 +1219,7 @@ function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $ } $avatar_img .= $avatar; - return '' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . ''; + return '' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . ''; } ?> \ No newline at end of file diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php index 6cae90d1c2..6d5021b9aa 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/includes/functions_jabber.php @@ -20,7 +20,7 @@ if (!defined('IN_PHPBB')) * * Jabber class from Flyspray project * -* @version class.jabber2.php 1488 2007-11-25 +* @version class.jabber2.php 1595 2008-09-19 (0.9.9) * @copyright 2006 Flyspray.org * @author Florian Schmitz (floele) * @@ -35,6 +35,7 @@ class jabber var $timeout = 10; var $server; + var $connect_server; var $port; var $username; var $password; @@ -50,9 +51,23 @@ class jabber */ function jabber($server, $port, $username, $password, $use_ssl = false) { - $this->server = ($server) ? $server : 'localhost'; + $this->connect_server = ($server) ? $server : 'localhost'; $this->port = ($port) ? $port : 5222; - $this->username = $username; + + // Get the server and the username + if (strpos($username, '@') === false) + { + $this->server = $this->connect_server; + $this->username = $username; + } + else + { + $jid = explode('@', $username, 2); + + $this->username = $jid[0]; + $this->server = $jid[1]; + } + $this->password = $password; $this->use_ssl = ($use_ssl && $this->can_use_ssl()) ? true : false; @@ -123,7 +138,7 @@ class jabber $this->session['ssl'] = $this->use_ssl; - if ($this->open_socket($this->server, $this->port, $this->use_ssl)) + if ($this->open_socket($this->connect_server, $this->port, $this->use_ssl)) { $this->send("\n"); $this->send("\n"); @@ -399,13 +414,11 @@ class jabber $second_time = isset($this->session['id']); $this->session['id'] = $xml['stream:stream'][0]['@']['id']; - /** Currently commented out due to problems with some jabber server - reason unknown if ($second_time) { // If we are here for the second time after TLS, we need to continue logging in - $this->login(); - return; - }*/ + return $this->login(); + } // go on with authentication? if (isset($this->features['stream:features'][0]['#']['bind']) || !empty($this->session['tls'])) @@ -501,14 +514,7 @@ class jabber } // better generate a cnonce, maybe it's needed - $str = ''; - mt_srand((double)microtime()*10000000); - - for ($i = 0; $i < 32; $i++) - { - $str .= chr(mt_rand(0, 255)); - } - $decoded['cnonce'] = base64_encode($str); + $decoded['cnonce'] = base64_encode(md5(uniqid(mt_rand(), true))); // second challenge? if (isset($decoded['rspauth'])) diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 90dbc33363..b125a1586a 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -562,7 +562,7 @@ class queue $fp = @fopen($this->cache_file . '.lock', 'wb'); fclose($fp); - @chmod($this->cache_file . '.lock', 0666); + @chmod($this->cache_file . '.lock', 0777); include($this->cache_file); @@ -683,21 +683,21 @@ class queue break; } } - + if (!sizeof($this->queue_data)) { @unlink($this->cache_file); } else { - if ($fp = @fopen($this->cache_file, 'w')) + if ($fp = @fopen($this->cache_file, 'wb')) { @flock($fp, LOCK_EX); - fwrite($fp, "queue_data = " . var_export($this->queue_data, true) . ";\n?>"); + fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); - @chmod($this->cache_file, 0666); + phpbb_chmod($this->cache_file, CHMOD_WRITE); } } @@ -713,11 +713,11 @@ class queue { return; } - + if (file_exists($this->cache_file)) { include($this->cache_file); - + foreach ($this->queue_data as $object => $data_ary) { if (isset($this->data[$object]) && sizeof($this->data[$object])) @@ -734,11 +734,11 @@ class queue if ($fp = @fopen($this->cache_file, 'w')) { @flock($fp, LOCK_EX); - fwrite($fp, "queue_data = " . var_export($this->data, true) . ";\n?>"); + fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); - @chmod($this->cache_file, 0666); + phpbb_chmod($this->cache_file, CHMOD_WRITE); } } } @@ -1047,7 +1047,7 @@ class smtp_class $err_msg .= $message; } } - + /** * Log into server and get possible auth codes if neccessary */ @@ -1108,7 +1108,7 @@ class smtp_class return false; } - // If EHLO fails, we try HELO + // If EHLO fails, we try HELO $this->server_send("HELO {$local_host}"); if ($err_msg = $this->server_parse('250', __LINE__)) { @@ -1129,7 +1129,7 @@ class smtp_class { return false; } - + if (!isset($this->commands['AUTH'])) { return (isset($user->lang['SMTP_NO_AUTH_SUPPORT'])) ? $user->lang['SMTP_NO_AUTH_SUPPORT'] : 'SMTP server does not support authentication'; @@ -1290,7 +1290,7 @@ class smtp_class } $md5_challenge = base64_decode($this->responses[0]); - + // Parse the md5 challenge - from AUTH_SASL (PEAR) $tokens = array(); while (preg_match('/^([a-z-]+)=("[^"]+(?lang_path . 'mods')) + if (file_exists($user->lang_path . $user->lang_name . '/mods')) { $add_files = array(); - $dir = @opendir($user->lang_path . 'mods'); + $dir = @opendir($user->lang_path . $user->lang_name . '/mods'); if ($dir) { diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 72c4fd0728..eaa3ab0cd3 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -688,6 +688,10 @@ function create_thumbnail($source, $destination, $mimetype) return false; } + // Preserve alpha transparency (png for example) + @imagealphablending($new_image, false); + @imagesavealpha($new_image, true); + imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } @@ -729,7 +733,7 @@ function create_thumbnail($source, $destination, $mimetype) return false; } - @chmod($destination, 0666); + phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); return true; } @@ -761,20 +765,20 @@ function posting_gen_inline_attachments(&$attachment_data) /** * Generate inline attachment entry */ -function posting_gen_attachment_entry($attachment_data, &$filename_data) +function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true) { - global $template, $config, $phpbb_root_path, $phpEx, $user; + global $template, $config, $phpbb_root_path, $phpEx, $user, $auth; + // Some default template variables $template->assign_vars(array( - 'S_SHOW_ATTACH_BOX' => true) - ); + 'S_SHOW_ATTACH_BOX' => $show_attach_box, + 'S_HAS_ATTACHMENTS' => sizeof($attachment_data), + 'FILESIZE' => $config['max_filesize'], + 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '', + )); if (sizeof($attachment_data)) { - $template->assign_vars(array( - 'S_HAS_ATTACHMENTS' => true) - ); - // We display the posted attachments within the desired order. ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); @@ -804,11 +808,6 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data) } } - $template->assign_vars(array( - 'FILE_COMMENT' => $filename_data['filecomment'], - 'FILESIZE' => $config['max_filesize']) - ); - return sizeof($attachment_data); } @@ -1251,6 +1250,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id $msg_list_ary[$row['template']][$pos]['jabber'] = $row['user_jabber']; $msg_list_ary[$row['template']][$pos]['name'] = $row['username']; $msg_list_ary[$row['template']][$pos]['lang'] = $row['user_lang']; + $msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id']; } unset($msg_users); @@ -1271,8 +1271,8 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id 'U_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id", 'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id", 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id", - 'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&unwatch=topic", - 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id&unwatch=forum", + 'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic", + 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum", )); $messenger->send($addr['method']); @@ -1437,7 +1437,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data) $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; } - $sql_data[TOPICS_TABLE] = 'topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; + $sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; // Decrementing topic_replies here is fine because this case only happens if there is more than one post within the topic - basically removing one "reply" $sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); @@ -1604,10 +1604,18 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $data['post_approved'] = $topic_row['post_approved']; } + // This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval + $post_approval = 1; + + // Check the permissions for post approval, as well as the queue trigger where users are put on approval with a post count lower than specified. Moderators are not affected. + if (($config['enable_queue_trigger'] && $user->data['user_posts'] < $config['queue_trigger_posts'] && !$auth->acl_get('m_approve', $data['forum_id'])) || !$auth->acl_get('f_noapprove', $data['forum_id'])) + { + $post_approval = 0; + } + // Start the transaction here $db->sql_transaction('begin'); - // Collect Information switch ($post_mode) { @@ -1619,7 +1627,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, - 'post_approved' => (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) ? 0 : 1, + 'post_approved' => $post_approval, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], @@ -1685,7 +1693,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], - 'post_approved' => (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) ? 0 : $data['post_approved'], + 'post_approved' => (!$post_approval) ? 0 : $data['post_approved'], 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], @@ -1719,7 +1727,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'topic_time' => $current_time, 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], - 'topic_approved' => (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) ? 0 : 1, + 'topic_approved' => $post_approval, 'topic_title' => $subject, 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], @@ -1739,24 +1747,23 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u ); } - $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id'])) ? ', user_posts = user_posts + 1' : ''); + $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); if ($topic_type != POST_GLOBAL) { - if ($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id'])) + if ($post_approval) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; } - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id'])) ? ', forum_topics = forum_topics + 1' : ''); + $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($post_approval) ? ', forum_topics = forum_topics + 1' : ''); } break; case 'reply': - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies_real = topic_replies_real + 1, topic_bumped = 0, topic_bumper = 0' . (($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id'])) ? ', topic_replies = topic_replies + 1' : '') . ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); + $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies_real = topic_replies_real + 1, topic_bumped = 0, topic_bumper = 0' . (($post_approval) ? ', topic_replies = topic_replies + 1' : '') . ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); + $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); - $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id'])) ? ', user_posts = user_posts + 1' : ''); - - if (($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id'])) && $topic_type != POST_GLOBAL) + if ($post_approval && $topic_type != POST_GLOBAL) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; } @@ -1768,7 +1775,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $sql_data[TOPICS_TABLE]['sql'] = array( 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], - 'topic_approved' => (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) ? 0 : $data['topic_approved'], + 'topic_approved' => (!$post_approval) ? 0 : $data['topic_approved'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, @@ -1783,7 +1790,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u ); // Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved - if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id']) && $data['topic_approved']) + if (!$post_approval && $data['topic_approved']) { // Do we need to grab some topic informations? if (!sizeof($topic_row)) @@ -1805,6 +1812,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u set_config('num_topics', $config['num_topics'] - 1, true); set_config('num_posts', $config['num_posts'] - ($topic_row['topic_replies'] + 1), true); + + // Only decrement this post, since this is the one non-approved now + if ($auth->acl_get('f_postcount', $data['forum_id'])) + { + $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; + } } break; @@ -1813,12 +1826,17 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u case 'edit_last_post': // Correctly set back the topic replies and forum posts... but only if the post was approved before. - if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id']) && $data['post_approved']) + if (!$post_approval && $data['post_approved']) { $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1'; set_config('num_posts', $config['num_posts'] - 1, true); + + if ($auth->acl_get('f_postcount', $data['forum_id'])) + { + $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; + } } break; @@ -2294,7 +2312,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } // Update total post count, do not consider moderated posts/topics - if ($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id'])) + if ($post_approval) { if ($post_mode == 'post') { @@ -2309,7 +2327,7 @@ 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'], USERS_TABLE => 'user_id = ' . $user->data['user_id']); + $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id); foreach ($sql_data as $table => $update_ary) { @@ -2426,14 +2444,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } // Send Notifications - if ($mode != 'edit' && $mode != 'delete' && ($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id']))) + if ($mode != 'edit' && $mode != 'delete' && $post_approval) { user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']); } $params = $add_anchor = ''; - if ($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id'])) + if ($post_approval) { $params .= '&t=' . $data['topic_id']; diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index d01d89a7e3..4926cabf2c 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -930,7 +930,7 @@ function handle_mark_actions($user_id, $mark_action) */ function delete_pm($user_id, $msg_ids, $folder_id) { - global $db, $user; + global $db, $user, $phpbb_root_path, $phpEx; $user_id = (int) $user_id; $folder_id = (int) $folder_id; @@ -979,6 +979,8 @@ function delete_pm($user_id, $msg_ids, $folder_id) return false; } + $db->sql_transaction('begin'); + // if no one has read the message yet (meaning it is in users outbox) // then mark the message as deleted... if ($folder_id == PRIVMSGS_OUTBOX) @@ -1056,11 +1058,21 @@ 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); + $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' WHERE ' . $db->sql_in_set('msg_id', $delete_ids); $db->sql_query($sql); } + $db->sql_transaction('commit'); + return true; } @@ -1329,12 +1341,17 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) if (isset($data['address_list']['g']) && sizeof($data['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 + $sql_allow_pm = (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) ? ' AND u.user_allow_pm = 1' : ''; + $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'])) . ' AND ug.user_pending = 0 AND u.user_id = ug.user_id - AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; + AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' . + $sql_allow_pm; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -1756,6 +1773,16 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $message = censor_text($message); + $decoded_message = false; + + if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != $user->data['user_id']) + { + $decoded_message = $message; + decode_message($decoded_message, $row['bbcode_uid']); + + $decoded_message = bbcode_nl2br($decoded_message); + } + if ($row['bbcode_bitfield']) { $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']); @@ -1774,15 +1801,17 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode } $template->assign_block_vars('history_row', array( + 'MESSAGE_AUTHOR_QUOTE' => (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''), 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']), 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']), 'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']), 'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']), - 'SUBJECT' => $subject, - 'SENT_DATE' => $user->format_date($row['message_time']), - 'MESSAGE' => $message, - 'FOLDER' => implode(', ', $row['folder']), + 'SUBJECT' => $subject, + 'SENT_DATE' => $user->format_date($row['message_time']), + 'MESSAGE' => $message, + 'FOLDER' => implode(', ', $row['folder']), + 'DECODED_MESSAGE' => $decoded_message, 'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id), 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php index 17d3328427..15efc7ec00 100644 --- a/phpBB/includes/functions_template.php +++ b/phpBB/includes/functions_template.php @@ -50,7 +50,7 @@ class template_compile { $this->template = &$template; } - + /** * Load template source from file * @access private @@ -74,7 +74,7 @@ class template_compile global $db, $user; $sql_ary = array( - 'template_id' => $user->theme['template_id'], + 'template_id' => $this->template->files_template[$handle], 'template_filename' => $this->template->filename[$handle], 'template_included' => '', 'template_mtime' => time(), @@ -264,8 +264,8 @@ class template_compile } // Handle remaining varrefs - $text_blocks = preg_replace('#\{([a-z0-9\-_]*)\}#is', "_rootref['\\1'])) ? \$this->_rootref['\\1'] : ''; ?>", $text_blocks); - $text_blocks = preg_replace('#\{\$([a-z0-9\-_]*)\}#is', "_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks); + $text_blocks = preg_replace('#\{([a-z0-9\-_]+)\}#is', "_rootref['\\1'])) ? \$this->_rootref['\\1'] : ''; ?>", $text_blocks); + $text_blocks = preg_replace('#\{\$([a-z0-9\-_]+)\}#is', "_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks); return; } @@ -515,11 +515,20 @@ class template_compile } $token = "sizeof($varref)"; } + else if (!empty($token)) + { + $token = '(' . $token . ')'; + } break; } } + // If there are no valid tokens left or only control/compare characters left, we do skip this statement + if (!sizeof($tokens) || str_replace(array(' ', '=', '!', '<', '>', '&', '|', '%', '(', ')'), '', implode('', $tokens)) == '') + { + $tokens = array('false'); + } return (($elseif) ? '} else if (' : 'if (') . (implode(' ', $tokens) . ') { '); } @@ -746,7 +755,7 @@ class template_compile @flock($fp, LOCK_UN); @fclose($fp); - @chmod($filename, 0666); + phpbb_chmod($filename, CHMOD_WRITE); } return; diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index a1374b8d54..e3a9363d62 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -121,9 +121,9 @@ class filespec 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; @@ -228,8 +228,8 @@ class filespec { return @filesize($filename); } - - + + /** * Check the first 256 bytes for forbidden content */ @@ -239,7 +239,7 @@ class filespec { return true; } - + $fp = @fopen($this->filename, 'rb'); if ($fp !== false) @@ -263,10 +263,11 @@ class filespec * * @param string $destination_path Destination path, for example $config['avatar_path'] * @param bool $overwrite If set to true, an already existing file will be overwritten - * @param octal $chmod Permission mask for chmodding the file after a successful move + * @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 = 0666) + function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false) { global $user, $phpbb_root_path; @@ -275,6 +276,8 @@ class filespec 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; @@ -345,7 +348,7 @@ class filespec break; } - @chmod($this->destination_file, $chmod); + phpbb_chmod($this->destination_file, $chmod); } // Try to get real filesize from destination folder @@ -416,7 +419,7 @@ class filespec { $size_lang = ($this->upload->max_filesize >= 1048576) ? $user->lang['MIB'] : (($this->upload->max_filesize >= 1024) ? $user->lang['KIB'] : $user->lang['BYTES'] ); $max_filesize = get_formatted_filesize($this->upload->max_filesize, false); - + $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang); return false; @@ -528,7 +531,7 @@ class fileupload $this->max_filesize = (int) $max_filesize; } } - + /** * Set disallowed strings */ @@ -872,7 +875,7 @@ class fileupload { $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension')); } - + // MIME Sniffing if (!$this->valid_content($file)) { diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 185c177b18..ea62a75306 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -147,7 +147,7 @@ function user_update_name($old_name, $new_name) * * @param mixed $user_row An array containing the following keys (and the appropriate values): username, group_id (the group to place the user in), user_email and the user_type(usually 0). Additional entries not overridden by defaults will be forwarded. * @param string $cp_data custom profile fields, see custom_profile::build_insert_sql_array -* @return: the new user's ID. +* @return the new user's ID. */ function user_add($user_row, $cp_data = false) { @@ -315,8 +315,6 @@ function user_delete($mode, $user_id, $post_username = false) return false; } - $db->sql_transaction('begin'); - // Before we begin, we will remove the reports the user issued. $sql = 'SELECT r.post_id, p.topic_id FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p @@ -385,6 +383,8 @@ function user_delete($mode, $user_id, $post_username = false) { case 'retain': + $db->sql_transaction('begin'); + if ($post_username === false) { $post_username = $user->lang['GUEST']; @@ -432,6 +432,9 @@ function user_delete($mode, $user_id, $post_username = false) $db->sql_query($sql); } } + + $db->sql_transaction('commit'); + break; case 'remove': @@ -485,6 +488,8 @@ function user_delete($mode, $user_id, $post_username = false) break; } + $db->sql_transaction('begin'); + $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE, DRAFTS_TABLE, BOOKMARKS_TABLE); foreach ($table_ary as $table) @@ -553,6 +558,8 @@ function user_delete($mode, $user_id, $post_username = false) $db->sql_query($sql); } + $db->sql_transaction('commit'); + // Reset newest user info if appropriate if ($config['newest_user_id'] == $user_id) { @@ -565,8 +572,6 @@ function user_delete($mode, $user_id, $post_username = false) set_config('num_users', $config['num_users'] - 1, true); } - $db->sql_transaction('commit'); - return false; } @@ -934,7 +939,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $sql = "SELECT $type FROM " . BANLIST_TABLE . " WHERE $sql_where - AND ban_exclude = $ban_exclude"; + AND ban_exclude = " . (int) $ban_exclude; $result = $db->sql_query($sql); // Reset $sql_where, because we use it later... @@ -2297,22 +2302,29 @@ function avatar_process_user(&$error, $custom_userdata = false) // Do we actually have any data to update? if (sizeof($sql_ary)) { + $ext_new = $ext_old = ''; + if (isset($sql_ary['user_avatar'])) + { + $userdata = ($custom_userdata === false) ? $user->data : $custom_userdata; + $ext_new = (empty($sql_ary['user_avatar'])) ? '' : substr(strrchr($sql_ary['user_avatar'], '.'), 1); + $ext_old = (empty($userdata['user_avatar'])) ? '' : substr(strrchr($userdata['user_avatar'], '.'), 1); + + if ($userdata['user_avatar_type'] == AVATAR_UPLOAD) + { + // Delete old avatar if present + if ((!empty($userdata['user_avatar']) && empty($sql_ary['user_avatar'])) + || ( !empty($userdata['user_avatar']) && !empty($sql_ary['user_avatar']) && $ext_new !== $ext_old)) + { + avatar_delete('user', $userdata); + } + } + } + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . (($custom_userdata === false) ? $user->data['user_id'] : $custom_userdata['user_id']); $db->sql_query($sql); - if (isset($sql_ary['user_avatar'])) - { - $userdata = ($custom_userdata === false) ? $user->data : $custom_userdata; - - // Delete old avatar if present - if ((!empty($userdata['user_avatar']) && empty($sql_ary['user_avatar']) && $userdata['user_avatar_type'] == AVATAR_UPLOAD) - || ( !empty($userdata['user_avatar']) && !empty($sql_ary['user_avatar']) && $userdata['user_avatar_type'] == AVATAR_UPLOAD && $sql_ary['user_avatar_type'] != AVATAR_UPLOAD)) - { - avatar_delete('user', $userdata); - } - } } } @@ -2343,12 +2355,13 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow 'group_receive_pm' => 'int', 'group_legend' => 'int', 'group_message_limit' => 'int', + 'group_max_recipients' => 'int', 'group_founder_manage' => 'int', ); // Those are group-only attributes - $group_only_ary = array('group_receive_pm', 'group_legend', 'group_message_limit', 'group_founder_manage'); + $group_only_ary = array('group_receive_pm', 'group_legend', 'group_message_limit', 'group_max_recipients', 'group_founder_manage'); // Check data. Limit group name length. if (!utf8_strlen($name) || utf8_strlen($name) > 60) @@ -3080,7 +3093,7 @@ function group_validate_groupname($group_id, $group_name) /** * Set users default group * -* @private +* @access private */ function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false) { diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index a1b8de2c98..b70601b479 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -246,7 +246,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), - 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false, + 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false, 'S_TOPIC_UNAPPROVED' => $topic_unapproved, 'S_POSTS_UNAPPROVED' => $posts_unapproved, 'S_UNREAD_TOPIC' => $unread_topic, diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index 707fe22685..05c1b796ac 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -27,7 +27,7 @@ function mcp_front_view($id, $mode, $action) // Latest 5 unapproved if ($module->loaded('queue')) { - $forum_list = get_forum_list('m_approve'); + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))); $post_list = array(); $forum_names = array(); @@ -81,7 +81,7 @@ function mcp_front_view($id, $mode, $action) if ($total) { - $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.username, u.username_clean, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id + $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.username, u.username_clean, u.user_colour, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u WHERE ' . $db->sql_in_set('p.post_id', $post_list) . ' AND t.topic_id = p.topic_id @@ -103,12 +103,15 @@ function mcp_front_view($id, $mode, $action) 'U_MCP_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=topic_view&f=' . $row['forum_id'] . '&t=' . $row['topic_id']), 'U_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', 'U_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), - 'U_AUTHOR' => ($row['poster_id'] == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['poster_id']), + + 'AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour']), + 'AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour']), + 'AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour']), + 'U_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour']), 'FORUM_NAME' => (!$global_topic) ? $forum_names[$row['forum_id']] : $user->lang['GLOBAL_ANNOUNCEMENT'], 'POST_ID' => $row['post_id'], 'TOPIC_TITLE' => $row['topic_title'], - 'AUTHOR' => ($row['poster_id'] == ANONYMOUS) ? (($row['post_username']) ? $row['post_username'] : $user->lang['GUEST']) : $row['username'], 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], 'POST_TIME' => $user->format_date($row['post_time'])) ); @@ -140,7 +143,7 @@ function mcp_front_view($id, $mode, $action) // Latest 5 reported if ($module->loaded('reports')) { - $forum_list = get_forum_list('m_report'); + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_report'))); $template->assign_var('S_SHOW_REPORTS', (!empty($forum_list)) ? true : false); @@ -243,7 +246,7 @@ function mcp_front_view($id, $mode, $action) // Latest 5 logs if ($module->loaded('logs')) { - $forum_list = get_forum_list('m_'); + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); if (!empty($forum_list)) { diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index 6c20cf85b4..a6b1935c88 100644 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -63,7 +63,7 @@ class mcp_logs $this->tpl_name = 'mcp_logs'; $this->page_title = 'MCP_LOGS'; - $forum_list = get_forum_list('m_'); + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); $forum_list[] = 0; $forum_id = $topic_id = 0; diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 85f9a1e839..8fafb232cc 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -641,7 +641,7 @@ function mcp_move_topic($topic_ids) { // Get the list of forums to resync, add a log entry $forum_ids[] = $row['forum_id']; - add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name']); + add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name'], $forum_data['forum_name']); // If we have moved a global announcement, we need to correct the topic type if ($row['topic_type'] == POST_GLOBAL) @@ -659,8 +659,8 @@ function mcp_move_topic($topic_ids) 'forum_id' => (int) $row['forum_id'], 'icon_id' => (int) $row['icon_id'], 'topic_attachment' => (int) $row['topic_attachment'], - 'topic_approved' => 1, - 'topic_reported' => (int) $row['topic_reported'], + 'topic_approved' => 1, // a shadow topic is always approved + 'topic_reported' => 0, // a shadow topic is never reported 'topic_title' => (string) $row['topic_title'], 'topic_poster' => (int) $row['topic_poster'], 'topic_time' => (int) $row['topic_time'], @@ -781,7 +781,7 @@ function mcp_delete_topic($topic_ids) foreach ($data as $topic_id => $row) { - add_log('mod', $row['forum_id'], 0, 'LOG_TOPIC_DELETED', $row['topic_title']); + add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_' . ($row['topic_moved_id'] ? 'SHADOW_' : '') . 'TOPIC', $row['topic_title']); } $return = delete_topics('topic_id', $topic_ids); @@ -791,8 +791,17 @@ function mcp_delete_topic($topic_ids) confirm_box(false, (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS', $s_hidden_fields); } - $redirect = request_var('redirect', "index.$phpEx"); - $redirect = reapply_sid($redirect); + if (!isset($_REQUEST['quickmod'])) + { + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + $redirect_message = 'PAGE'; + } + else + { + $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); + $redirect_message = 'FORUM'; + } if (!$success_msg) { @@ -800,9 +809,8 @@ function mcp_delete_topic($topic_ids) } else { - $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); - meta_refresh(3, $redirect_url); - trigger_error($user->lang[$success_msg] . '

' . sprintf($user->lang['RETURN_FORUM'], '', '')); + meta_refresh(3, $redirect); + trigger_error($user->lang[$success_msg] . '

' . sprintf($user->lang['RETURN_' . $redirect_message], '', '')); } } diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 8f4630bf4c..fa44e006dd 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -415,8 +415,8 @@ function change_poster(&$post_info, $userdata) sync('forum', 'forum_id', $post_info['forum_id'], false, false); } - // Adjust post counts - if ($post_info['post_postcount']) + // Adjust post counts... only if the post is approved (else, it was not added the users post count anyway) + if ($post_info['post_postcount'] && $post_info['post_approved']) { $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = user_posts - 1 @@ -470,11 +470,11 @@ function change_poster(&$post_info, $userdata) if (file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) { require("{$phpbb_root_path}includes/search/$search_type.$phpEx"); - + // We do some additional checks in the module to ensure it can actually be utilised $error = false; $search = new $search_type($error); - + if (!$error && method_exists($search, 'destroy_cache')) { $search->destroy_cache(array(), array($post_info['user_id'], $userdata['user_id'])); diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index ab09761378..1e368c4fc6 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -242,6 +242,17 @@ class mcp_queue } $forum_list_approve = get_forum_list('m_approve', false, true); + $forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs + + // Remove forums we cannot read + foreach ($forum_list_approve as $k => $forum_data) + { + if (!isset($forum_list_read[$forum_data['forum_id']])) + { + unset($forum_list_approve[$k]); + } + } + unset($forum_list_read); if (!$forum_id) { @@ -481,6 +492,7 @@ function approve_post($post_id_list, $id, $mode) $total_topics = $total_posts = 0; $forum_topics_posts = $topic_approve_sql = $topic_replies_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array(); + $user_posts_sql = array(); $update_forum_information = false; @@ -493,6 +505,9 @@ function approve_post($post_id_list, $id, $mode) $forum_id_list[$post_data['forum_id']] = 1; } + // User post update (we do not care about topic or post, since user posts are strictly connected to posts + $user_posts_sql[$post_data['poster_id']] = (empty($user_posts_sql[$post_data['poster_id']])) ? 1 : $user_posts_sql[$post_data['poster_id']] + 1; + // Topic or Post. ;) if ($post_data['topic_first_post_id'] == $post_id) { @@ -612,6 +627,25 @@ function approve_post($post_id_list, $id, $mode) } } + if (sizeof($user_posts_sql)) + { + // Try to minimize the query count by merging users with the same post count additions + $user_posts_update = array(); + + foreach ($user_posts_sql as $user_id => $user_posts) + { + $user_posts_update[$user_posts][] = $user_id; + } + + foreach ($user_posts_update as $user_posts => $user_id_ary) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts + ' . $user_posts . ' + WHERE ' . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + } + } + if ($total_topics) { set_config('num_topics', $config['num_topics'] + $total_topics, true); @@ -793,6 +827,13 @@ function disapprove_post($post_id_list, $id, $mode) // If the reason is defined within the language file, we will use the localized version, else just use the database entry... $disapprove_reason = (strtolower($row['reason_title']) != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : ''; $disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; + + if (isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $disapprove_reason_lang = strtoupper($row['reason_title']); + } + + $email_disapprove_reason = $disapprove_reason; } } @@ -912,6 +953,8 @@ function disapprove_post($post_id_list, $id, $mode) // Notify Poster? if ($notify_poster) { + $lang_reasons = array(); + foreach ($post_info as $post_id => $post_data) { if ($post_data['poster_id'] == ANONYMOUS) @@ -919,6 +962,35 @@ function disapprove_post($post_id_list, $id, $mode) continue; } + if (isset($disapprove_reason_lang)) + { + // Okay we need to get the reason from the posters language + if (!isset($lang_reasons[$post_data['user_lang']])) + { + // Assign the current users translation as the default, this is not ideal but getting the board default adds another layer of complexity. + $lang_reasons[$post_data['user_lang']] = $user->lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; + + // Only load up the language pack if the language is different to the current one + if ($post_data['user_lang'] != $user->lang_name && file_exists($phpbb_root_path . '/language/' . $post_data['user_lang'] . '/mcp.' . $phpEx)) + { + // Load up the language pack + $lang = array(); + @include($phpbb_root_path . '/language/' . $post_data['user_lang'] . '/mcp.' . $phpEx); + + // If we find the reason in this language pack use it + if (isset($lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang])) + { + $lang_reasons[$post_data['user_lang']] = $lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; + } + + unset($lang); // Free memory + } + } + + $email_disapprove_reason = $lang_reasons[$post_data['user_lang']]; + $email_disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; + } + $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_disapproved' : 'post_disapproved'; $messenger->template($email_template, $post_data['user_lang']); @@ -928,15 +1000,17 @@ function disapprove_post($post_id_list, $id, $mode) $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($post_data['username']), - 'REASON' => htmlspecialchars_decode($disapprove_reason), + 'REASON' => htmlspecialchars_decode($email_disapprove_reason), 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title']))) ); $messenger->send($post_data['user_notify_type']); } + + unset($lang_reasons); } - unset($post_info, $disapprove_reason); + unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang); $messenger->save_queue(); diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index ce55fec7df..27d841c81b 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -65,7 +65,7 @@ class mcp_reports { case 'report_details': - $user->add_lang('posting'); + $user->add_lang(array('posting', 'viewforum', 'viewtopic')); $post_id = request_var('p', 0); @@ -200,6 +200,7 @@ class mcp_reports 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $report['user_id']) : '', 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $post_info['forum_id']), 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), @@ -245,6 +246,17 @@ class mcp_reports $forum_info = array(); $forum_list_reports = get_forum_list('m_report', false, true); + $forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs + + // Remove forums we cannot read + foreach ($forum_list_reports as $k => $forum_data) + { + if (!isset($forum_list_read[$forum_data['forum_id']])) + { + unset($forum_list_reports[$k]); + } + } + unset($forum_list_read); if ($topic_id && $forum_id) { @@ -555,7 +567,8 @@ function close_report($report_id_list, $mode, $action) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_reported = 0 - WHERE ' . $db->sql_in_set('topic_id', $close_report_topics); + WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . ' + OR ' . $db->sql_in_set('topic_moved_id', $close_report_topics); $db->sql_query($sql); } } @@ -634,7 +647,7 @@ function close_report($report_id_list, $mode, $action) $return_topic = ''; if (sizeof($topic_ids == 1)) { - $return_topic = sprintf($user->lang['RETURN_TOPIC'], '', '') . '

'; + $return_topic = sprintf($user->lang['RETURN_TOPIC'], '', '') . '

'; } trigger_error($user->lang[$success_msg] . '

' . $return_forum . $return_topic . sprintf($user->lang['RETURN_PAGE'], "", '')); diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index a468712a25..931300897e 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -46,8 +46,9 @@ function mcp_topic_view($id, $mode, $action) $forum_id = request_var('f', 0); $to_topic_id = request_var('to_topic_id', 0); $to_forum_id = request_var('to_forum_id', 0); - $post_id_list = request_var('post_id_list', array(0)); $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)); // Split Topic? if ($action == 'split_all' || $action == 'split_beyond') @@ -113,11 +114,18 @@ function mcp_topic_view($id, $mode, $action) { $posts_per_page = $total; } - if (!empty($sort_days_old) && $sort_days_old != $sort_days) + + if ((!empty($sort_days_old) && $sort_days_old != $sort_days) || $total <= $posts_per_page) { $start = 0; } + // Make sure $start is set to the last page if it exceeds the amount + if ($start < 0 || $start >= $total) + { + $start = ($start < 0) ? 0 : floor(($total - 1) / $posts_per_page) * $posts_per_page; + } + $sql = 'SELECT u.username, u.username_clean, u.user_colour, p.* FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE ' . (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' @@ -226,7 +234,7 @@ function mcp_topic_view($id, $mode, $action) 'S_POST_REPORTED' => ($row['post_reported']) ? true : false, 'S_POST_UNAPPROVED' => ($row['post_approved']) ? false : true, - 'S_CHECKED' => ($post_id_list && in_array(intval($row['post_id']), $post_id_list)) ? true : false, + 'S_CHECKED' => (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false, 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, 'U_POST_DETAILS' => "$url&i=$id&p={$row['post_id']}&mode=post_details" . (($forum_id) ? "&f=$forum_id" : ''), @@ -279,6 +287,7 @@ function mcp_topic_view($id, $mode, $action) $s_hidden_fields = build_hidden_fields(array( 'st_old' => $sort_days, + 'post_ids' => $post_id_list, )); $template->assign_vars(array( @@ -328,7 +337,7 @@ 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; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config; $post_id_list = request_var('post_id_list', array(0)); $forum_id = request_var('forum_id', 0); @@ -370,11 +379,11 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) return; } - $forum_info = get_forum_data(array($to_forum_id), 'm_split'); + $forum_info = get_forum_data(array($to_forum_id), 'f_post'); if (!sizeof($forum_info)) { - $template->assign_var('MESSAGE', $user->lang['NOT_MODERATOR']); + $template->assign_var('MESSAGE', $user->lang['USER_CANNOT_POST']); return; } @@ -491,6 +500,9 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $success_msg = 'TOPIC_SPLIT_SUCCESS'; + // Update forum statistics + set_config('num_topics', $config['num_topics'] + 1, true); + // Link back to both topics $return_link = sprintf($user->lang['RETURN_TOPIC'], '', '') . '

' . sprintf($user->lang['RETURN_NEW_TOPIC'], '', ''); } diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index 7c17de9f43..bf0e66dc67 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -249,6 +249,25 @@ class mcp_warn $this->u_action .= "&f=$forum_id&p=$post_id"; } + // Check if can send a notification + if ($config['allow_privmsg']) + { + $auth2 = new auth(); + $auth2->acl($user_row); + $s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false; + unset($auth2); + } + else + { + $s_can_notify = false; + } + + // Prevent against clever people + if ($notify && !$s_can_notify) + { + $notify = false; + } + if ($warning && $action == 'add_warning') { if (check_form_key('mcp_warn')) @@ -307,6 +326,8 @@ class mcp_warn 'RANK_IMG' => $rank_img, 'L_WARNING_POST_DEFAULT' => sprintf($user->lang['WARNING_POST_DEFAULT'], generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&p=$post_id#p$post_id"), + + 'S_CAN_NOTIFY' => $s_can_notify, )); } @@ -351,6 +372,25 @@ class mcp_warn $this->u_action .= "&u=$user_id"; } + // Check if can send a notification + if ($config['allow_privmsg']) + { + $auth2 = new auth(); + $auth2->acl($user_row); + $s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false; + unset($auth2); + } + else + { + $s_can_notify = false; + } + + // Prevent against clever people + if ($notify && !$s_can_notify) + { + $notify = false; + } + if ($warning && $action == 'add_warning') { if (check_form_key('mcp_warn')) @@ -389,6 +429,8 @@ class mcp_warn 'AVATAR_IMG' => $avatar_img, 'RANK_IMG' => $rank_img, + + 'S_CAN_NOTIFY' => $s_can_notify, )); return $user_id; diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 8e0103af05..4e350bce99 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -391,7 +391,7 @@ class bbcode_firstpass extends bbcode /** * Parse code text from code tag - * @private + * @access private */ function bbcode_parse_code($stx, &$code) { @@ -604,10 +604,10 @@ class bbcode_firstpass extends bbcode $out .= array_pop($list_end_tags) . ']'; $tok = '['; } - else if (preg_match('#^list(=[0-9a-z])?$#i', $buffer, $m)) + else if (preg_match('#^list(=[0-9a-z]+)?$#i', $buffer, $m)) { // sub-list, add a closing tag - if (empty($m[1]) || preg_match('/^(?:disc|square|circle)$/i', $m[1])) + if (empty($m[1]) || preg_match('/^=(?:disc|square|circle)$/i', $m[1])) { array_push($list_end_tags, '/list:u:' . $this->bbcode_uid); } diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index 80724fb5c5..2a67b58246 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -704,7 +704,7 @@ class fulltext_mysql extends search_backend if (!isset($this->stats['post_subject'])) { - if ($db->sql_layer == 'mysqli' || version_compare($db->mysql_version, '4.1.3', '>=')) + if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>=')) { //$alter[] = 'MODIFY post_subject varchar(100) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; } @@ -717,7 +717,7 @@ class fulltext_mysql extends search_backend if (!isset($this->stats['post_text'])) { - if ($db->sql_layer == 'mysqli' || version_compare($db->mysql_version, '4.1.3', '>=')) + if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>=')) { $alter[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL'; } diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index b0e95a1559..9bd3c81311 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -447,11 +447,12 @@ class fulltext_native extends search_backend 'FROM' => array( SEARCH_WORDMATCH_TABLE => array(), SEARCH_WORDLIST_TABLE => array(), - POSTS_TABLE => 'p' ), - 'LEFT_JOIN' => array() + 'LEFT_JOIN' => array(array( + 'FROM' => array(POSTS_TABLE => 'p'), + 'ON' => 'm0.post_id = p.post_id', + )), ); - $sql_where[] = 'm0.post_id = p.post_id'; $title_match = ''; $group_by = true; diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/search.php index 32d7ed595f..2f20d11495 100644 --- a/phpBB/includes/search/search.php +++ b/phpBB/includes/search/search.php @@ -52,10 +52,10 @@ class search_backend $words = array(); - if (file_exists("{$user->lang_path}/search_ignore_words.$phpEx")) + if (file_exists("{$user->lang_path}{$user->lang_name}/search_ignore_words.$phpEx")) { // include the file containing ignore words - include("{$user->lang_path}/search_ignore_words.$phpEx"); + include("{$user->lang_path}{$user->lang_name}/search_ignore_words.$phpEx"); } $this->ignore_words = $words; @@ -74,10 +74,10 @@ class search_backend $synonyms = array(); - if (file_exists("{$user->lang_path}/search_synonyms.$phpEx")) + if (file_exists("{$user->lang_path}{$user->lang_name}/search_synonyms.$phpEx")) { // include the file containing synonyms - include("{$user->lang_path}/search_synonyms.$phpEx"); + include("{$user->lang_path}{$user->lang_name}/search_synonyms.$phpEx"); } $this->match_synonym = array_keys($synonyms); diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 958833ece7..2e697f6359 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -73,7 +73,7 @@ class session continue; } - $use_args[str_replace($find, $replace, $key)] = str_replace($find, $replace, $argument); + $use_args[] = str_replace($find, $replace, $argument); } unset($args); @@ -136,6 +136,60 @@ class session return $page_array; } + /** + * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present. + */ + function extract_current_hostname() + { + global $config; + + // Get hostname + $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); + + // Should be a string and lowered + $host = (string) strtolower($host); + + // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid + if ((isset($config['cookie_domain']) && $host === $config['cookie_domain']) || (isset($config['server_name']) && $host === $config['server_name'])) + { + return $host; + } + + // Is the host actually a IP? If so, we use the IP... (IPv4) + if (long2ip(ip2long($host)) === $host) + { + return $host; + } + + // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned + $host = @parse_url('http://' . $host); + $host = (!empty($host['host'])) ? $host['host'] : ''; + + // Remove any portions not removed by parse_url (#) + $host = str_replace('#', '', $host); + + // If, by any means, the host is now empty, we will use a "best approach" way to guess one + if (empty($host)) + { + if (!empty($config['server_name'])) + { + $host = $config['server_name']; + } + else if (!empty($config['cookie_domain'])) + { + $host = (strpos($config['cookie_domain'], '.') === 0) ? substr($config['cookie_domain'], 1) : $config['cookie_domain']; + } + else + { + // Set to OS hostname or localhost + $host = (function_exists('php_uname')) ? php_uname('n') : 'localhost'; + } + } + + // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set) + return $host; + } + /** * Start session management * @@ -160,14 +214,8 @@ class session $this->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; $this->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; $this->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; - $this->host = (!empty($_SERVER['HTTP_HOST'])) ? (string) strtolower($_SERVER['HTTP_HOST']) : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); - - // Since HTTP_HOST may carry a port definition, we need to remove it here... - if (strpos($this->host, ':') !== false) - { - $this->host = substr($this->host, 0, strpos($this->host, ':')); - } + $this->host = $this->extract_current_hostname(); $this->page = $this->extract_current_page($phpbb_root_path); // if the forwarded for header shall be checked we have to validate its contents @@ -1156,7 +1204,6 @@ class session } $dnsbl_check = array( - 'list.dsbl.org' => 'http://dsbl.org/listing?', 'sbl-xbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=', ); @@ -1322,7 +1369,7 @@ class session function validate_referer($check_script_path = false) { // no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason) - if (empty($this->referer) || empty($this->host) ) + if (empty($this->referer) || empty($this->host)) { return true; } @@ -1330,7 +1377,7 @@ class session $host = htmlspecialchars($this->host); $ref = substr($this->referer, strpos($this->referer, '://') + 3); - if (!(stripos($ref , $host) === 0)) + if (!(stripos($ref, $host) === 0)) { return false; } @@ -1382,7 +1429,7 @@ class user extends session var $timezone; var $dst; - var $lang_name; + var $lang_name = false; var $lang_id = false; var $lang_path; var $img_lang; @@ -1392,6 +1439,32 @@ class user extends session var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10); var $keyvalues = array(); + /** + * Constructor to set the lang path + */ + function user() + { + global $phpbb_root_path; + + $this->lang_path = $phpbb_root_path . 'language/'; + } + + /** + * 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) + { + $this->lang_path = $lang_path; + + if (substr($this->lang_path, -1) != '/') + { + $this->lang_path .= '/'; + } + } + /** * Setup basic user-specific items (style, language, ...) */ @@ -1401,8 +1474,7 @@ class user extends session if ($this->data['user_id'] != ANONYMOUS) { - $this->lang_name = (file_exists($phpbb_root_path . 'language/' . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); - $this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/'; + $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); $this->date_format = $this->data['user_dateformat']; $this->timezone = $this->data['user_timezone'] * 3600; @@ -1411,7 +1483,6 @@ class user extends session else { $this->lang_name = basename($config['default_lang']); - $this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/'; $this->date_format = $config['default_dateformat']; $this->timezone = $config['board_timezone'] * 3600; $this->dst = $config['board_dst'] * 3600; @@ -1431,10 +1502,9 @@ class user extends session $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2)); $accept_lang = basename($accept_lang); - if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx")) + if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx")) { $this->lang_name = $config['default_lang'] = $accept_lang; - $this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/'; break; } else @@ -1443,10 +1513,9 @@ class user extends session $accept_lang = substr($accept_lang, 0, 2); $accept_lang = basename($accept_lang); - if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx")) + if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx")) { $this->lang_name = $config['default_lang'] = $accept_lang; - $this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/'; break; } } @@ -1458,9 +1527,9 @@ class user extends session // We include common language file here to not load it every time a custom language file is included $lang = &$this->lang; - if ((@include $this->lang_path . "common.$phpEx") === false) + if ((@include $this->lang_path . $this->lang_name . "/common.$phpEx") === false) { - die('Language file ' . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); + die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); } $this->add_lang($lang_set); @@ -1480,7 +1549,7 @@ class user extends session $style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']); } - $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name + $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i WHERE s.style_id = $style AND t.template_id = s.template_id @@ -1769,6 +1838,72 @@ class user extends session return; } + /** + * More 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: $user->lang('NUM_POSTS_IN_QUEUE', 1); + */ + function lang() + { + $args = func_get_args(); + $key = $args[0]; + + // Return if language string does not exist + if (!isset($this->lang[$key]) || (!is_string($this->lang[$key]) && !is_array($this->lang[$key]))) + { + return $key; + } + + // If the language entry is a string, we simply mimic sprintf() behaviour + if (is_string($this->lang[$key])) + { + if (sizeof($args) == 1) + { + return $this->lang[$key]; + } + + // Replace key with language entry and simply pass along... + $args[0] = $this->lang[$key]; + return call_user_func_array('sprintf', $args); + } + + // 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])) + { + $numbers = array_keys($this->lang[$key]); + + foreach ($numbers as $num) + { + if ($num > $args[$i]) + { + break; + } + + $key_found = $num; + } + } + } + + // 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($this->lang[$key]); + $key_found = end($numbers); + } + + // Use the language string we determined and pass it to sprintf() + $args[0] = $this->lang[$key][$key_found]; + return call_user_func_array('sprintf', $args); + } + /** * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion) * @@ -1830,12 +1965,11 @@ class user extends session { global $phpEx; - // Make sure the language path is set (if the user setup did not happen it is not set) - if (!$this->lang_path) + // Make sure the language name is set (if the user setup did not happen it is not set) + if (!$this->lang_name) { - global $phpbb_root_path, $config; - - $this->lang_path = $phpbb_root_path . 'language/' . basename($config['default_lang']) . '/'; + global $config; + $this->lang_name = basename($config['default_lang']); } // $lang == $this->lang @@ -1845,16 +1979,16 @@ class user extends session { if ($use_help && strpos($lang_file, '/') !== false) { - $language_filename = $this->lang_path . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . $phpEx; + $language_filename = $this->lang_path . $this->lang_name . '/' . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . $phpEx; } else { - $language_filename = $this->lang_path . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx; + $language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx; } if ((@include $language_filename) === false) { - trigger_error('Language file ' . basename($language_filename) . ' couldn\'t be opened.', E_USER_ERROR); + trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); } } else if ($use_db) @@ -1962,6 +2096,7 @@ class user extends session /** * Specify/Get image + * $suffix is no longer used - we know it. ;) It is there for backward compatibility. */ function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag') { diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php index 2e60beb658..0098c484bd 100644 --- a/phpBB/includes/template.php +++ b/phpBB/includes/template.php @@ -36,6 +36,9 @@ class template var $cachepath = ''; var $files = array(); var $filename = array(); + var $files_inherit = array(); + var $files_template = array(); + var $inherit_root = ''; // this will hash handle names to the compiled/uncompiled code for that handle. var $compiled_code = array(); @@ -51,7 +54,12 @@ class template if (file_exists($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template')) { $this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template'; - $this->cachepath = $phpbb_root_path . 'cache/tpl_' . $user->theme['template_path'] . '_'; + $this->cachepath = $phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $user->theme['template_path']) . '_'; + + if ($user->theme['template_inherits_id']) + { + $this->inherit_root = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template'; + } } else { @@ -72,7 +80,7 @@ class template global $phpbb_root_path; $this->root = $template_path; - $this->cachepath = $phpbb_root_path . 'cache/ctpl_' . $template_name . '_'; + $this->cachepath = $phpbb_root_path . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_'; return true; } @@ -88,7 +96,6 @@ class template { return false; } - foreach ($filename_array as $handle => $filename) { if (empty($filename)) @@ -98,8 +105,13 @@ class template $this->filename[$handle] = $filename; $this->files[$handle] = $this->root . '/' . $filename; + + if ($this->inherit_root) + { + $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; + } } - + return true; } @@ -197,7 +209,7 @@ class template return true; } - + /** * Load a compiled template if possible, if not, recompile it * @access private @@ -207,9 +219,24 @@ class template global $user, $phpEx, $config; $filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx; - - $recompile = (($config['load_tplcompile'] && @filemtime($filename) < filemtime($this->files[$handle])) || !file_exists($filename) || @filesize($filename) === 0) ? true : false; - + $this->files_template[$handle] = $user->theme['template_id']; + + $recompile = false; + if (!file_exists($filename) || @filesize($filename) === 0) + { + $recompile = true; + } + else if ($config['load_tplcompile']) + { + // No way around it: we need to check inheritance here + if ($user->theme['template_inherits_id'] && !file_exists($this->files[$handle])) + { + $this->files[$handle] = $this->files_inherit[$handle]; + $this->files_template[$handle] = $user->theme['template_inherits_id']; + } + $recompile = (@filemtime($filename) < filemtime($this->files[$handle])) ? true : false; + } + // Recompile page if the original template is newer, otherwise load the compiled version if (!$recompile) { @@ -222,7 +249,14 @@ class template { include($phpbb_root_path . 'includes/functions_template.' . $phpEx); } - + + // Inheritance - we point to another template file for this one. Equality is also used for store_db + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($this->files[$handle])) + { + $this->files[$handle] = $this->files_inherit[$handle]; + $this->files_template[$handle] = $user->theme['template_inherits_id']; + } + $compile = new template_compile($this); // If we don't have a file assigned to this handle, die. @@ -240,28 +274,70 @@ class template if (isset($user->theme['template_storedb']) && $user->theme['template_storedb']) { - $sql = 'SELECT * + $rows = array(); + $ids = array(); + // Inheritance + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) + { + $ids[] = $user->theme['template_inherits_id']; + } + $ids[] = $user->theme['template_id']; + + foreach ($ids as $id) + { + $sql = 'SELECT * FROM ' . STYLES_TEMPLATE_DATA_TABLE . ' - WHERE template_id = ' . $user->theme['template_id'] . " + WHERE template_id = ' . $id . " AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "' OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')'; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - - if ($row) - { - do + + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) { - if ($row['template_mtime'] < filemtime($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/' . $row['template_filename'])) + $rows[$row['template_filename']] = $row; + } + $db->sql_freeresult($result); + } + + if (sizeof($rows)) + { + foreach ($rows as $row) + { + $file = $this->root . '/' . $row['template_filename']; + $force_reload = false; + if ($row['template_id'] != $user->theme['template_id']) + { + // make sure that we are not overlooking a file not in the db yet + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file)) + { + $file = $this->inherit_root . '/' . $row['template_filename']; + $this->files[$row['template_filename']] = $file; + $this->files_inherit[$row['template_filename']] = $file; + $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; + } + else if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) + { + // Ok, we have a situation. There is a file in the subtemplate, but nothing in the DB. We have to fix that. + $force_reload = true; + $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; + } + } + else + { + $this->files_template[$row['template_filename']] = $user->theme['template_id']; + } + + if ($force_reload || $row['template_mtime'] < filemtime($file)) { if ($row['template_filename'] == $this->filename[$handle]) { - $compile->_tpl_load_file($handle); + $compile->_tpl_load_file($handle, true); } else { - $this->files[$row['template_filename']] = $this->root . '/' . $row['template_filename']; - $compile->_tpl_load_file($row['template_filename']); + $this->files[$row['template_filename']] = $file; + $this->filename[$row['template_filename']] = $row['template_filename']; + $compile->_tpl_load_file($row['template_filename'], true); unset($this->compiled_code[$row['template_filename']]); unset($this->files[$row['template_filename']]); unset($this->filename[$row['template_filename']]); @@ -284,15 +360,22 @@ class template } } } - while ($row = $db->sql_fetchrow($result)); } else { + $file = $this->root . '/' . $row['template_filename']; + + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file)) + { + $file = $this->inherit_root . '/' . $row['template_filename']; + $this->files[$row['template_filename']] = $file; + $this->files_inherit[$row['template_filename']] = $file; + $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; + } // Try to load from filesystem and instruct to insert into the styles table... $compile->_tpl_load_file($handle, true); return false; } - $db->sql_freeresult($result); return false; } @@ -512,8 +595,12 @@ class template $handle = $filename; $this->filename[$handle] = $filename; $this->files[$handle] = $this->root . '/' . $filename; + if ($this->inherit_root) + { + $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; + } - $filename = $this->_tpl_load($handle); + $filename = $this->_tpl_load($handle); if ($include) { diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 355c9898c2..7de2511423 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -65,6 +65,7 @@ class ucp_activate 'user_password' => $user_row['user_newpasswd'], 'user_newpasswd' => '', 'user_pass_convert' => 0, + 'user_login_attempts' => 0, ); $sql = 'UPDATE ' . USERS_TABLE . ' diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index d884e0d571..32d24337c9 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -221,8 +221,9 @@ class ucp_groups $messenger->im($row['user_jabber'], $row['username']); $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($row['username']), - 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), + 'USERNAME' => htmlspecialchars_decode($row['username']), + 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), + 'REQUEST_USERNAME' => $user->data['username'], 'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id", 'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id") @@ -434,6 +435,23 @@ class ucp_groups { trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . $return_page, E_USER_WARNING); } + + $group_name = $group_row['group_name']; + $group_type = $group_row['group_type']; + $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : ''; + + $template->assign_vars(array( + 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_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']), + 'GROUP_TYPE' => $group_row['group_type'], + + 'AVATAR' => $avatar_img, + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '', + 'AVATAR_HEIGHT' => (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', + )); } switch ($action) @@ -487,7 +505,8 @@ class ucp_groups 'colour' => request_var('group_colour', ''), 'rank' => request_var('group_rank', 0), 'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0, - 'message_limit' => request_var('group_message_limit', 0) + 'message_limit' => request_var('group_message_limit', 0), + 'max_recipients'=> request_var('group_max_recipients', 0), ); $data['uploadurl'] = request_var('uploadurl', ''); @@ -585,7 +604,7 @@ class ucp_groups // were made. $group_attributes = array(); - $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height'); + $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients'); foreach ($test_variables as $test) { if ($action == 'add' || (isset($submit_ary[$test]) && $group_row['group_' . $test] != $submit_ary[$test])) @@ -629,9 +648,7 @@ class ucp_groups } else { - $group_name = $group_row['group_name']; $group_desc_data = generate_text_for_edit($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_options']); - $group_type = $group_row['group_type']; $group_rank = $group_row['group_rank']; } @@ -654,8 +671,6 @@ class ucp_groups $type_closed = ($group_type == GROUP_CLOSED) ? ' checked="checked"' : ''; $type_hidden = ($group_type == GROUP_HIDDEN) ? ' checked="checked"' : ''; - $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : ''; - $display_gallery = (isset($_POST['display_gallery'])) ? true : false; if ($config['allow_avatar_local'] && $display_gallery) @@ -665,7 +680,6 @@ class ucp_groups $avatars_enabled = ($can_upload || ($config['allow_avatar_local'] || $config['allow_avatar_remote'])) ? true : false; - $template->assign_vars(array( 'S_EDIT' => true, 'S_INCLUDE_SWATCH' => true, @@ -678,23 +692,17 @@ class ucp_groups 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false, 'ERROR_MSG' => (sizeof($error)) ? implode('
', $error) : '', - 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_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"' : '', 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, - 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', - + 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, + + 'GROUP_DESC' => $group_desc_data['text'], 'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'], 'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'], 'S_DESC_SMILIES_CHECKED'=> $group_desc_data['allow_smilies'], 'S_RANK_OPTIONS' => $rank_options, - 'AVATAR' => $avatar_img, - 'AVATAR_IMAGE' => $avatar_img, 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], - 'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '', - 'AVATAR_HEIGHT' => (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', 'GROUP_TYPE_FREE' => GROUP_FREE, 'GROUP_TYPE_OPEN' => GROUP_OPEN, @@ -741,7 +749,7 @@ class ucp_groups WHERE ug.group_id = $group_id AND u.user_id = ug.user_id AND ug.group_leader = 1 - ORDER BY ug.group_leader DESC, ug.user_pending ASC, u.username_clean"; + ORDER BY ug.user_pending DESC, u.username_clean"; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -774,10 +782,11 @@ class ucp_groups WHERE ug.group_id = $group_id AND u.user_id = ug.user_id AND ug.group_leader = 0 - ORDER BY ug.group_leader DESC, ug.user_pending ASC, u.username_clean"; + ORDER BY ug.user_pending DESC, u.username_clean"; $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); $pending = false; + $approved = false; while ($row = $db->sql_fetchrow($result)) { @@ -786,9 +795,19 @@ class ucp_groups $template->assign_block_vars('member', array( 'S_PENDING' => true) ); + $template->assign_var('S_PENDING_SET', true); $pending = true; } + else if (!$row['user_pending'] && !$approved) + { + $template->assign_block_vars('member', array( + 'S_APPROVED' => true) + ); + $template->assign_var('S_APPROVED_SET', true); + + $approved = true; + } $template->assign_block_vars('member', array( 'USERNAME' => $row['username'], diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index c2fa50c79e..73e4af8b04 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -237,7 +237,10 @@ class ucp_main $l_unwatch .= '_TOPICS'; } $msg = $user->lang['UNWATCHED' . $l_unwatch]; - + } + else + { + $msg = $user->lang['NO_WATCHED_SELECTED']; } } else diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 6271639cd1..060baaefa0 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -25,6 +25,10 @@ function compose_pm($id, $mode, $action) global $template, $db, $auth, $user; global $phpbb_root_path, $phpEx, $config; + // Damn php and globals - i know, this is horrible + // Needed for handle_message_list_actions() + global $refresh, $submit, $preview; + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include($phpbb_root_path . 'includes/functions_display.' . $phpEx); include($phpbb_root_path . 'includes/message_parser.' . $phpEx); @@ -45,6 +49,11 @@ function compose_pm($id, $mode, $action) // Do NOT use request_var or specialchars here $address_list = isset($_REQUEST['address_list']) ? $_REQUEST['address_list'] : array(); + if (!is_array($address_list)) + { + $address_list = array(); + } + $submit = (isset($_POST['post'])) ? true : false; $preview = (isset($_POST['preview'])) ? true : false; $save = (isset($_POST['save'])) ? true : false; @@ -79,7 +88,8 @@ function compose_pm($id, $mode, $action) // Output PM_TO box if message composing if ($action != 'edit') { - if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) + // Add groups to PM box + if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) { $sql = 'SELECT g.group_id, g.group_name, g.group_type FROM ' . GROUPS_TABLE . ' g'; @@ -112,7 +122,7 @@ function compose_pm($id, $mode, $action) $template->assign_vars(array( 'S_SHOW_PM_BOX' => true, 'S_ALLOW_MASS_PM' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? true : false, - 'S_GROUP_OPTIONS' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? $group_options : '', + 'S_GROUP_OPTIONS' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) ? $group_options : '', 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=searchuser&form=postform&field=username_list&select_single=$select_single"), )); } @@ -281,7 +291,24 @@ function compose_pm($id, $mode, $action) if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !sizeof($address_list) && !$refresh && !$submit && !$preview) { - $address_list = array('u' => array($post['author_id'] => 'to')); + if ($action == 'quotepost') + { + $address_list = array('u' => array($post['author_id'] => 'to')); + } + else + { + // We try to include every previously listed member from the TO Header + $address_list = rebuild_header(array('to' => $post['to_address'])); + + // Add the author (if he is already listed then this is no shame (it will be overwritten)) + $address_list['u'][$post['author_id']] = 'to'; + + // Now, make sure the user itself is not listed. ;) + if (isset($address_list['u'][$user->data['user_id']])) + { + unset($address_list['u'][$user->data['user_id']]); + } + } } else if ($action == 'edit' && !sizeof($address_list) && !$refresh && !$submit && !$preview) { @@ -315,7 +342,7 @@ function compose_pm($id, $mode, $action) $check_value = 0; } - if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm'))) + if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group'))) { trigger_error('NO_AUTH_GROUP_MESSAGE'); } @@ -380,14 +407,58 @@ function compose_pm($id, $mode, $action) redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=view&action=view_message&p=' . $msg_id)); } + // 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 = (!$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 + if (($action == 'reply' || $action == 'quote') && $max_recipients) + { + // We try to include every previously listed member from the TO Header + $list = rebuild_header(array('to' => $post['to_address'])); + $list = $list['u']; + $list[$post['author_id']] = 'to'; + + if (isset($list[$user->data['user_id']])) + { + unset($list[$user->data['user_id']]); + } + + $max_recipients = ($max_recipients < sizeof($list)) ? sizeof($list) : $max_recipients; + + unset($list); + } + // Handle User/Group adding/removing handle_message_list_actions($address_list, $error, $remove_u, $remove_g, $add_to, $add_bcc); - // Check for too many recipients + // Check mass pm to group permission + if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group')) && !empty($address_list['g'])) + { + $address_list = array(); + $error[] = $user->lang['NO_AUTH_GROUP_MESSAGE']; + } + + // Check mass pm to users permission if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm')) && num_recipients($address_list) > 1) { - $address_list = get_recipient_pos($address_list, 1); - $error[] = $user->lang['TOO_MANY_RECIPIENTS']; + $address_list = get_recipients($address_list, 1); + $error[] = $user->lang('TOO_MANY_RECIPIENTS', 1); + } + + // Check for too many recipients + if (!empty($address_list['u']) && $max_recipients && sizeof($address_list['u']) > $max_recipients) + { + $address_list = get_recipients($address_list, $max_recipients); + $error[] = $user->lang('TOO_MANY_RECIPIENTS', $max_recipients); } // Always check if the submitted attachment data is valid and belongs to the user. @@ -762,7 +833,7 @@ function compose_pm($id, $mode, $action) $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); $forward_text[] = sprintf($user->lang['FWD_TO'], implode(', ', $fwd_to_field['to'])); - $message_parser->message = implode("\n", $forward_text) . "\n\n[quote=\"{$quote_username}\"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; + $message_parser->message = implode("\n", $forward_text) . "\n\n[quote="{$quote_username}"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject); } @@ -932,7 +1003,7 @@ function compose_pm($id, $mode, $action) $s_hidden_fields .= (isset($check_value)) ? '' : ''; $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '' : ''; - $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || @ini_get('file_uploads') == '0' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; + $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"'; // Start assigning vars for main posting page ... $template->assign_vars(array( @@ -949,6 +1020,7 @@ function compose_pm($id, $mode, $action) 'URL_STATUS' => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), 'ERROR' => (sizeof($error)) ? implode('
', $error) : '', + 'MAX_RECIPIENTS' => ($config['allow_mass_pm'] && ($auth->acl_get('u_masspm') || $auth->acl_get('u_masspm_group'))) ? $max_recipients : 0, 'S_COMPOSE_PM' => true, 'S_EDIT_POST' => ($action == 'edit'), @@ -982,11 +1054,11 @@ function compose_pm($id, $mode, $action) // Build custom bbcodes array display_custom_bbcodes(); + // Show attachment box for adding attachments if true + $allowed = ($auth->acl_get('u_pm_attach') && $config['allow_pm_attach'] && $form_enctype); + // Attachment entry - if ($auth->acl_get('u_pm_attach') && $config['allow_pm_attach'] && $form_enctype) - { - posting_gen_attachment_entry($attachment_data, $filename_data); - } + posting_gen_attachment_entry($attachment_data, $filename_data, $allowed); // Message History if ($action == 'reply' || $action == 'quote' || $action == 'forward') @@ -1027,14 +1099,33 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove } } + // Add Selected Groups + $group_list = request_var('group_list', array(0)); + + // Build usernames to add + $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '', true)) : array(); + $username_list = request_var('username_list', '', true); + if ($username_list) + { + $usernames = array_merge($usernames, explode("\n", $username_list)); + } + + // If add to or add bcc not pressed, users could still have usernames listed they want to add... + if (!$add_to && !$add_bcc && (sizeof($group_list) || sizeof($usernames))) + { + $add_to = true; + + global $refresh, $submit, $preview; + + $refresh = $preview = true; + $submit = false; + } + // Add User/Group [TO] if ($add_to || $add_bcc) { $type = ($add_to) ? 'to' : 'bcc'; - // Add Selected Groups - $group_list = request_var('group_list', array(0)); - if (sizeof($group_list)) { foreach ($group_list as $group_id) @@ -1046,14 +1137,6 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove // User ID's to add... $user_id_ary = array(); - // Build usernames to add - $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '', true)) : array(); - $username_list = request_var('username_list', '', true); - if ($username_list) - { - $usernames = array_merge($usernames, explode("\n", $username_list)); - } - // Reveal the correct user_ids if (sizeof($usernames)) { @@ -1068,7 +1151,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove } // Add Friends if specified - $friend_list = (is_array($_REQUEST['add_' . $type])) ? array_map('intval', array_keys($_REQUEST['add_' . $type])) : array(); + $friend_list = (isset($_REQUEST['add_' . $type]) && is_array($_REQUEST['add_' . $type])) ? array_map('intval', array_keys($_REQUEST['add_' . $type])) : array(); $user_id_ary = array_merge($user_id_ary, $friend_list); foreach ($user_id_ary as $user_id) @@ -1144,22 +1227,22 @@ function num_recipients($address_list) } /** -* Get recipient at position 'pos' +* Get number of 'num_recipients' recipients from first position */ -function get_recipient_pos($address_list, $position = 1) +function get_recipients($address_list, $num_recipients = 1) { $recipient = array(); - $count = 1; + $count = 0; foreach ($address_list as $field => $adr_ary) { foreach ($adr_ary as $id => $type) { - if ($count == $position) + if ($count >= $num_recipients) { - $recipient[$field][$id] = $type; break 2; } + $recipient[$field][$id] = $type; $count++; } } diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index 8c765b1e90..360912ae49 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -511,9 +511,9 @@ function get_pm_from($folder_id, $folder, $user_id) 'S_SELECT_SORT_DAYS' => $s_limit_days, 'S_TOPIC_ICONS' => ($config['enable_pm_icons']) ? true : false, - 'U_POST_NEW_TOPIC' => ($auth->acl_get('u_sendpm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose') : '', - 'S_PM_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&action=view_folder&f=$folder_id")) - ); + 'U_POST_NEW_TOPIC' => ($auth->acl_get('u_sendpm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose') : '', + 'S_PM_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&action=view_folder&f=$folder_id" . (($start !== 0) ? "&start=$start" : '')), + )); // Grab all pm data $rowset = $pm_list = array(); diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index 3762cf25f6..9b705fba6c 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -53,6 +53,12 @@ class ucp_prefs 'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']), ); + if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml'))) + { + // Jabber isnt enabled, or no jabber field filled in. Update the users table to be sure its correct. + $data['notifymethod'] = NOTIFY_BOTH; + } + if ($submit) { $data['style'] = ($config['override_user_style']) ? $config['default_style'] : $data['style']; @@ -294,7 +300,7 @@ class ucp_prefs 'bbcode' => request_var('bbcode', $user->optionget('bbcode')), 'smilies' => request_var('smilies', $user->optionget('smilies')), 'sig' => request_var('sig', $user->optionget('attachsig')), - 'notify' => request_var('notify', $user->data['user_notify']), + 'notify' => request_var('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 8aacf8a244..328d374e9a 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -315,7 +315,7 @@ class ucp_profile 'website' => array( array('string', true, 12, 255), array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), - 'location' => array('string', true, 2, 255), + 'location' => array('string', true, 2, 100), 'occupation' => array('string', true, 2, 500), 'interests' => array('string', true, 2, 500), ); @@ -347,6 +347,15 @@ class ucp_profile if (!sizeof($error)) { + $data['notify'] = $user->data['user_notify_type']; + + if (!$config['jab_enable'] || !$data['jabber'] || !@extension_loaded('xml')) + { + // User has not filled in a jabber address (Or one of the modules is disabled or jabber is disabled) + // Disable notify by Jabber now for this user. + $data['notify'] = NOTIFY_BOTH; + } + $sql_ary = array( 'user_icq' => $data['icq'], 'user_aim' => $data['aim'], @@ -357,6 +366,7 @@ class ucp_profile 'user_from' => $data['location'], 'user_occ' => $data['occupation'], 'user_interests'=> $data['interests'], + 'user_notify_type' => $data['notify'], ); if ($config['allow_birthdays']) @@ -418,7 +428,7 @@ class ucp_profile $now = getdate(); $s_birthday_year_options = ''; - for ($i = $now['year'] - 100; $i < $now['year']; $i++) + for ($i = $now['year'] - 100; $i <= $now['year']; $i++) { $selected = ($i == $data['bday_year']) ? ' selected="selected"' : ''; $s_birthday_year_options .= ""; @@ -460,7 +470,7 @@ class ucp_profile { trigger_error('NO_AUTH_SIGNATURE'); } - + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include($phpbb_root_path . 'includes/functions_display.' . $phpEx); @@ -589,9 +599,9 @@ class ucp_profile 'ERROR' => (sizeof($error)) ? implode('
', $error) : '', 'AVATAR' => get_user_avatar($user->data['user_avatar'], $user->data['user_avatar_type'], $user->data['user_avatar_width'], $user->data['user_avatar_height']), 'AVATAR_SIZE' => $config['avatar_filesize'], - + 'U_GALLERY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&mode=avatar&display_gallery=1'), - + 'S_FORM_ENCTYPE' => ($can_upload) ? ' enctype="multipart/form-data"' : '', 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), @@ -604,7 +614,7 @@ class ucp_profile else { $avatars_enabled = ($can_upload || ($auth->acl_get('u_chgavatar') && ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false; - + $template->assign_vars(array( 'AVATAR_WIDTH' => request_var('width', $user->data['user_avatar_width']), 'AVATAR_HEIGHT' => request_var('height', $user->data['user_avatar_height']), diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 8a7bc14839..315d24d47f 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -43,7 +43,7 @@ class ucp_register $submit = (isset($_POST['submit'])) ? true : false; $change_lang = request_var('change_lang', ''); $user_lang = request_var('lang', $user->lang_name); - + if ($agreed) { add_form_key('ucp_register'); @@ -58,7 +58,7 @@ class ucp_register { $use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang); - if (file_exists($phpbb_root_path . 'language/' . $use_lang . '/')) + if (file_exists($user->lang_path . $use_lang . '/')) { if ($change_lang) { @@ -69,7 +69,6 @@ class ucp_register } $user->lang_name = $lang = $use_lang; - $user->lang_path = $phpbb_root_path . 'language/' . $lang . '/'; $user->lang = array(); $user->add_lang(array('common', 'ucp')); } @@ -471,7 +470,7 @@ class ucp_register if (!$change_lang || !$confirm_id) { $user->confirm_gc(CONFIRM_REG); - + $sql = 'SELECT COUNT(session_id) AS attempts FROM ' . CONFIRM_TABLE . " WHERE session_id = '" . $db->sql_escape($user->session_id) . "' diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index 12de817099..6325bf89b6 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -36,7 +36,7 @@ class ucp_remind if ($submit) { - $sql = 'SELECT user_id, username, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason + $sql = 'SELECT user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason FROM ' . USERS_TABLE . " WHERE user_email = '" . $db->sql_escape($email) . "' AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; @@ -66,6 +66,15 @@ class ucp_remind } } + // Check users permissions + $auth2 = new auth(); + $auth2->acl($user_row); + + if (!$auth2->acl_get('u_chgpasswd')) + { + trigger_error('NO_AUTH_PASSWORD_REMINDER'); + } + $server_url = generate_board_url(); $key_len = 54 - strlen($server_url); diff --git a/phpBB/index.php b/phpBB/index.php index e1727c2f0a..2d1329c511 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -60,22 +60,25 @@ else } $result = $db->sql_query($sql); -$legend = ''; +$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']; - if ($row['group_name'] == 'BOTS') + if ($row['group_name'] == 'BOTS' || ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile'))) { - $legend .= (($legend != '') ? ', ' : '') . '' . $user->lang['G_BOTS'] . ''; + $legend[] = '' . $group_name . ''; } else { - $legend .= (($legend != '') ? ', ' : '') . '' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . ''; + $legend[] = '' . $group_name . ''; } } $db->sql_freeresult($result); +$legend = implode(', ', $legend); + // Generate birthday list if required ... $birthday_list = ''; if ($config['load_birthdays'] && $config['allow_birthdays']) @@ -117,7 +120,7 @@ $template->assign_vars(array( 'S_LOGIN_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'), 'S_DISPLAY_BIRTHDAY_LIST' => ($config['load_birthdays']) ? true : false, - 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'mark=forums') : '', + 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'hash=' . generate_link_hash('global') . '&mark=forums') : '', 'U_MCP' => ($auth->acl_get('m_') || $auth->acl_getf_global('m_')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=front', true, $user->session_id) : '') ); diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 63644d7212..f413e2555a 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -32,7 +32,7 @@ unset($dbpasswd); $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', 'version' => '1.0.2', - 'phpbb_version' => '3.0.2', + 'phpbb_version' => '3.0.3', 'author' => 'phpBB Group', 'dbms' => $dbms, 'dbhost' => $dbhost, diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php index c69574c565..0acf666312 100644 --- a/phpBB/install/convertors/functions_phpbb20.php +++ b/phpBB/install/convertors/functions_phpbb20.php @@ -461,7 +461,7 @@ function phpbb_get_birthday($birthday = '') } // The birthday mod from niels is using this code to transform to day/month/year - return gmdate('d-m-Y', $birthday * 86400 + 1); + return sprintf('%2d-%2d-%4d', gmdate('n', $birthday * 86400 + 1), gmdate('j', $birthday * 86400 + 1), gmdate('Y', $birthday * 86400 + 1)); } } @@ -1710,7 +1710,7 @@ function phpbb_check_username_collisions() break; case 'mysql4': - if (version_compare($db->mysql_version, '4.1.3', '>=')) + if (version_compare($db->sql_server_info(true), '4.1.3', '>=')) { $map_dbms = 'mysql_41'; } diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index fb287299e5..e84d63a950 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -8,7 +8,7 @@ * */ -$updates_to_version = '3.0.2'; +$updates_to_version = '3.0.3-RC1'; // Return if we "just include it" to find out for which version the database update is responsible for if (defined('IN_PHPBB') && defined('IN_INSTALL')) @@ -531,6 +531,20 @@ $database_update_info = array( ), // No changes from 3.0.2-RC2 to 3.0.2 '3.0.2-RC2' => array(), + + // Changes from 3.0.2 to 3.0.3-RC1 + '3.0.2' => array( + // Add the following columns + 'add_columns' => array( + STYLES_TEMPLATE_TABLE => array( + 'template_inherits_id' => array('UINT:4', 0), + 'template_inherit_path' => array('VCHAR', ''), + ), + GROUPS_TABLE => array( + 'group_max_recipients' => array('UINT', 0), + ), + ), + ), ); // Determine mapping database type @@ -541,7 +555,7 @@ switch ($db->sql_layer) break; case 'mysql4': - if (version_compare($db->mysql_version, '4.1.3', '>=')) + if (version_compare($db->sql_server_info(true), '4.1.3', '>=')) { $map_dbms = 'mysql_41'; } @@ -1402,7 +1416,7 @@ if (function_exists('exit_handler')) */ function change_database_data(&$no_updates, $version) { - global $db, $map_dbms, $errored, $error_ary, $config, $phpbb_root_path; + global $db, $map_dbms, $errored, $error_ary, $config, $phpbb_root_path, $phpEx; switch ($version) { @@ -1820,6 +1834,107 @@ function change_database_data(&$no_updates, $version) // No changes from 3.0.2-RC2 to 3.0.2 case '3.0.2-RC2': break; + + // Changes from 3.0.2 to 3.0.3-RC1 + case '3.0.2': + set_config('enable_queue_trigger', '0'); + set_config('queue_trigger_posts', '3'); + + set_config('pm_max_recipients', '0'); + + // Set maximum number of recipients for the registered users, bots, guests group + $sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_max_recipients = 5 + WHERE ' . $db->sql_in_set('group_name', array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS')); + _sql($sql, $errored, $error_ary); + + // Not prefilling yet + set_config('dbms_version', ''); + + // Add new permission u_masspm_group and duplicate settings from u_masspm + include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + $auth_admin = new auth_admin(); + + // Only add the new permission if it does not already exist + if (empty($auth_admin->acl_options['id']['u_masspm_group'])) + { + $auth_admin->acl_add_option(array('global' => array('u_masspm_group'))); + + // Now the tricky part, filling the permission + $old_id = $auth_admin->acl_options['id']['u_masspm']; + $new_id = $auth_admin->acl_options['id']['u_masspm_group']; + + $tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE); + + foreach ($tables as $table) + { + $sql = 'SELECT * + FROM ' . $table . ' + WHERE auth_option_id = ' . $old_id; + $result = _sql($sql, $errored, $error_ary); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $row['auth_option_id'] = $new_id; + $sql_ary[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert($table, $sql_ary); + } + } + + // Remove any old permission entries + $auth_admin->acl_clear_prefetch(); + } + + /** + * Do not resync post counts here. An admin may do this later from the ACP + $start = 0; + $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000; + + $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = 0'; + _sql($sql, $errored, $error_ary); + + do + { + $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id + FROM ' . POSTS_TABLE . ' + WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' + AND post_postcount = 1 AND post_approved = 1 + GROUP BY poster_id'; + $result = _sql($sql, $errored, $error_ary); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $sql = 'UPDATE ' . USERS_TABLE . " SET user_posts = user_posts + {$row['num_posts']} WHERE user_id = {$row['poster_id']}"; + _sql($sql, $errored, $error_ary); + } + while ($row = $db->sql_fetchrow($result)); + + $start += $step; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + */ + + $sql = 'UPDATE ' . MODULES_TABLE . ' + SET module_auth = \'acl_a_email && cfg_email_enable\' + WHERE module_class = \'acp\' + AND module_basename = \'email\''; + _sql($sql, $errored, $error_ary); + + $no_updates = false; + break; } } diff --git a/phpBB/install/index.php b/phpBB/install/index.php index bbf7fe34d3..b1eba60af5 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -108,7 +108,7 @@ if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) } else { - set_magic_quotes_runtime(0); + @set_magic_quotes_runtime(0); // Be paranoid with passed vars if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on') @@ -230,6 +230,14 @@ include($phpbb_root_path . 'language/' . $language . '/acp/board.' . $phpEx); include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx); include($phpbb_root_path . 'language/' . $language . '/posting.' . $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_var('mode', 'overview'); $sub = request_var('sub', ''); @@ -336,11 +344,6 @@ class module foreach ($module as $row) { - // Check any module pre-reqs - if ($row['module_reqs'] != '') - { - } - // Module order not specified or module already assigned at this position? if (!isset($row['module_order']) || isset($this->module_ary[$row['module_order']])) { diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 25d8551df4..7a4155e09d 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -685,7 +685,7 @@ class install_convert extends module // Thanks MySQL, for silently converting... case 'mysql': case 'mysql4': - if (version_compare($src_db->mysql_version, '4.1.3', '>=')) + if (version_compare($src_db->sql_server_info(true), '4.1.3', '>=')) { $convert->mysql_convert = true; } diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 282afd5e23..8591446fea 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -398,7 +398,7 @@ class install_install extends module $location .= '/'; } - if (@is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) + if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) { $img_imagick = str_replace('\\', '/', $location); continue; @@ -438,16 +438,13 @@ class install_install extends module if (!file_exists($phpbb_root_path . $dir)) { @mkdir($phpbb_root_path . $dir, 0777); - @chmod($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)) { - if (!@is_writable($phpbb_root_path . $dir)) - { - @chmod($phpbb_root_path . $dir, 0777); - } + phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE); $exists = true; } @@ -877,7 +874,7 @@ class install_install extends module } @fclose($fp); - @chmod($phpbb_root_path . 'cache/install_lock', 0666); + @chmod($phpbb_root_path . 'cache/install_lock', 0777); $load_extensions = implode(',', $load_extensions); @@ -930,7 +927,8 @@ class install_install extends module if ($written) { - @chmod($phpbb_root_path . 'config.' . $phpEx, 0644); + // 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); } } @@ -1120,6 +1118,7 @@ class install_install extends module // HTTP_HOST is having the correct browser url in most cases... $server_name = (!empty($_SERVER['HTTP_HOST'])) ? strtolower($_SERVER['HTTP_HOST']) : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); + $referer = (!empty($_SERVER['HTTP_REFERER'])) ? strtolower($_SERVER['HTTP_REFERER']) : getenv('HTTP_REFERER'); // HTTP HOST can carry a port number... if (strpos($server_name, ':') !== false) @@ -1159,7 +1158,7 @@ class install_install extends module // 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->mysql_version, '4.1.3', '>=')) + if (version_compare($db->sql_server_info(true), '4.1.3', '>=')) { $available_dbms[$data['dbms']]['SCHEMA'] .= '_41'; } @@ -1365,6 +1364,10 @@ class install_install extends module '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') || can_load_dll('gd')) @@ -1374,6 +1377,15 @@ class install_install extends module 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()); @@ -1478,7 +1490,7 @@ class install_install extends module include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx); - $_module = &new acp_modules(); + $_module = new acp_modules(); $module_classes = array('acp', 'mcp', 'ucp'); // Add categories diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index d494007f3d..8ff7427b09 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -896,8 +896,9 @@ class install_update extends module 'S_FTP_UPLOAD' => true, 'UPLOAD_METHOD' => $method, 'U_ACTION' => append_sid($this->p_master->module_url, "mode=$mode&sub=update_files"), - 'S_HIDDEN_FIELDS' => $s_hidden_fields) - ); + 'U_DOWNLOAD_METHOD' => append_sid($this->p_master->module_url, "mode=$mode&sub=update_files&download=1"), + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + )); return; } @@ -1106,7 +1107,7 @@ class install_update extends module 'file2' => ($option == MERGE_NEW_FILE) ? implode("\n", $diff->merged_new_output()) : implode("\n", $diff->merged_orig_output()), ); - $diff = &new diff($tmp['file1'], $tmp['file2']); + $diff = new diff($tmp['file1'], $tmp['file2']); unset($tmp); @@ -1183,7 +1184,7 @@ class install_update extends module trigger_error('Chosen diff mode is not supported', E_USER_ERROR); } - $renderer = &new $render_class(); + $renderer = new $render_class(); $template->assign_vars(array( 'DIFF_CONTENT' => $renderer->get_diff_content($diff), @@ -1346,7 +1347,7 @@ class install_update extends module ); // 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); + $diff = new diff($tmp['file1'], $tmp['file2'], false); $empty = $diff->is_empty(); unset($tmp, $diff); @@ -1381,7 +1382,7 @@ class install_update extends module ); // 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); + $diff = new diff($tmp['file1'], $tmp['file2'], false); $empty_1 = $diff->is_empty(); unset($tmp, $diff); @@ -1392,7 +1393,7 @@ class install_update extends module ); // 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); + $diff = new diff($tmp['file1'], $tmp['file2'], false); $empty_2 = $diff->is_empty(); unset($tmp, $diff); @@ -1428,7 +1429,7 @@ class install_update extends module 'file3' => file_get_contents($this->new_location . $original_file), ); - $diff = &new diff3($tmp['file1'], $tmp['file2'], $tmp['file3'], false); + $diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3'], false); unset($tmp); @@ -1442,7 +1443,7 @@ class install_update extends module 'file2' => implode("\n", $diff->merged_orig_output()), ); - $diff = &new diff($tmp['file1'], $tmp['file2'], false); + $diff = new diff($tmp['file1'], $tmp['file2'], false); $empty = $diff->is_empty(); if ($empty) @@ -1465,7 +1466,7 @@ class install_update extends module ); // now compare the merged output with the original file to see if the modified file is up to date - $diff = &new diff($tmp['file1'], $tmp['file2'], false); + $diff = new diff($tmp['file1'], $tmp['file2'], false); $empty = $diff->is_empty(); if ($empty) @@ -1634,11 +1635,11 @@ class install_update extends module $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']); + $diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3']); } else { - $diff = &new diff($tmp['file1'], $tmp['file2']); + $diff = new diff($tmp['file1'], $tmp['file2']); } unset($tmp); diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 1d2ec37eaa..e3e2e43723 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -440,6 +440,7 @@ CREATE TABLE phpbb_groups ( group_sig_chars INTEGER DEFAULT 0 NOT NULL, group_receive_pm INTEGER DEFAULT 0 NOT NULL, group_message_limit INTEGER DEFAULT 0 NOT NULL, + group_max_recipients INTEGER DEFAULT 0 NOT NULL, group_legend INTEGER DEFAULT 1 NOT NULL );; @@ -1076,7 +1077,9 @@ CREATE TABLE phpbb_styles_template ( template_copyright VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, template_path VARCHAR(100) CHARACTER SET NONE DEFAULT '' NOT NULL, bbcode_bitfield VARCHAR(255) CHARACTER SET NONE DEFAULT 'kNg=' NOT NULL, - template_storedb INTEGER DEFAULT 0 NOT NULL + template_storedb INTEGER DEFAULT 0 NOT NULL, + template_inherits_id INTEGER DEFAULT 0 NOT NULL, + template_inherit_path VARCHAR(255) CHARACTER SET NONE DEFAULT '' NOT NULL );; ALTER TABLE phpbb_styles_template ADD PRIMARY KEY (template_id);; diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index 6890148243..3a3d3fcbd4 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -545,6 +545,7 @@ CREATE TABLE [phpbb_groups] ( [group_sig_chars] [int] DEFAULT (0) NOT NULL , [group_receive_pm] [int] DEFAULT (0) NOT NULL , [group_message_limit] [int] DEFAULT (0) NOT NULL , + [group_max_recipients] [int] DEFAULT (0) NOT NULL , [group_legend] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] GO @@ -1295,7 +1296,9 @@ CREATE TABLE [phpbb_styles_template] ( [template_copyright] [varchar] (255) DEFAULT ('') NOT NULL , [template_path] [varchar] (100) DEFAULT ('') NOT NULL , [bbcode_bitfield] [varchar] (255) DEFAULT ('kNg=') NOT NULL , - [template_storedb] [int] DEFAULT (0) NOT NULL + [template_storedb] [int] DEFAULT (0) NOT NULL , + [template_inherits_id] [int] DEFAULT (0) NOT NULL , + [template_inherit_path] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 7e4ddeb3cd..01d8efa921 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -312,6 +312,7 @@ CREATE TABLE phpbb_groups ( group_sig_chars mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, group_receive_pm tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, group_message_limit mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + group_max_recipients mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, group_legend tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, PRIMARY KEY (group_id), KEY group_legend_name (group_legend, group_name(255)) @@ -739,6 +740,8 @@ CREATE TABLE phpbb_styles_template ( template_path varbinary(100) DEFAULT '' NOT NULL, bbcode_bitfield varbinary(255) DEFAULT 'kNg=' NOT NULL, template_storedb tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, + template_inherits_id int(4) UNSIGNED DEFAULT '0' NOT NULL, + template_inherit_path varbinary(255) DEFAULT '' NOT NULL, PRIMARY KEY (template_id), UNIQUE tmplte_nm (template_name(255)) ); diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index ba51ea2102..0119e4ce9d 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -312,6 +312,7 @@ CREATE TABLE phpbb_groups ( group_sig_chars mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, group_receive_pm tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, group_message_limit mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, + group_max_recipients mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, group_legend tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, PRIMARY KEY (group_id), KEY group_legend_name (group_legend, group_name) @@ -739,6 +740,8 @@ CREATE TABLE phpbb_styles_template ( template_path varchar(100) DEFAULT '' NOT NULL, bbcode_bitfield varchar(255) DEFAULT 'kNg=' NOT NULL, template_storedb tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, + template_inherits_id int(4) UNSIGNED DEFAULT '0' NOT NULL, + template_inherit_path varchar(255) DEFAULT '' NOT NULL, PRIMARY KEY (template_id), UNIQUE tmplte_nm (template_name) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index 19f09bcebd..c9b138b8d8 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -602,6 +602,7 @@ CREATE TABLE phpbb_groups ( group_sig_chars number(8) DEFAULT '0' NOT NULL, group_receive_pm number(1) DEFAULT '0' NOT NULL, group_message_limit number(8) DEFAULT '0' NOT NULL, + group_max_recipients number(8) DEFAULT '0' NOT NULL, group_legend number(1) DEFAULT '1' NOT NULL, CONSTRAINT pk_phpbb_groups PRIMARY KEY (group_id) ) @@ -1431,6 +1432,8 @@ CREATE TABLE phpbb_styles_template ( template_path varchar2(100) DEFAULT '' , bbcode_bitfield varchar2(255) DEFAULT 'kNg=' NOT NULL, template_storedb number(1) DEFAULT '0' NOT NULL, + template_inherits_id number(4) DEFAULT '0' NOT NULL, + template_inherit_path varchar2(255) DEFAULT '' , CONSTRAINT pk_phpbb_styles_template PRIMARY KEY (template_id), CONSTRAINT u_phpbb_tmplte_nm UNIQUE (template_name) ) diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index f11f1b4d35..32f3f0cd4a 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -455,6 +455,7 @@ CREATE TABLE phpbb_groups ( group_sig_chars INT4 DEFAULT '0' NOT NULL CHECK (group_sig_chars >= 0), group_receive_pm INT2 DEFAULT '0' NOT NULL CHECK (group_receive_pm >= 0), group_message_limit INT4 DEFAULT '0' NOT NULL CHECK (group_message_limit >= 0), + group_max_recipients INT4 DEFAULT '0' NOT NULL CHECK (group_max_recipients >= 0), group_legend INT2 DEFAULT '1' NOT NULL CHECK (group_legend >= 0), PRIMARY KEY (group_id) ); @@ -972,6 +973,8 @@ CREATE TABLE phpbb_styles_template ( template_path varchar(100) DEFAULT '' NOT NULL, bbcode_bitfield varchar(255) DEFAULT 'kNg=' NOT NULL, template_storedb INT2 DEFAULT '0' NOT NULL CHECK (template_storedb >= 0), + template_inherits_id INT4 DEFAULT '0' NOT NULL CHECK (template_inherits_id >= 0), + template_inherit_path varchar(255) DEFAULT '' NOT NULL, PRIMARY KEY (template_id) ); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 900695c791..f774090a66 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -75,6 +75,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_enable', '0' INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_fax', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_mail', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('database_gc', '604800'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('dbms_version', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_dateformat', 'D M d, Y g:i a'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_style', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_edited', '1'); @@ -87,6 +88,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '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 ('enable_queue_trigger', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval', '15'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('force_server_vars', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_lifetime', '7200'); @@ -179,9 +181,11 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('pass_complex', 'PA INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_edit_time', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_boxes', '4'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_msgs', '50'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_recipients', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('posts_per_page', '10'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('print_pm', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_interval', '600'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_trigger_posts', '3'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('ranks_path', 'images/ranks'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation', '1'); @@ -214,7 +218,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('topics_per_page', 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 ('version', '3.0.2'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.0.3-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'); @@ -343,6 +347,7 @@ INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_download', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_hideonline', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_ignoreflood', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm_group', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_attach', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_bbcode', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_delete', 1); @@ -484,12 +489,12 @@ INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_reg INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_from, user_icq, user_aim, user_yim, user_msnm, user_jabber, user_website, user_occ, user_interests, user_actkey, user_newpasswd) VALUES (3, 5, 'Admin', 'admin', 0, '21232f297a57a5a743894a0e4a801fc3', 'admin@yourdomain.com', 'en', 1, 1, 'AA0000', 1, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); # -- Groups -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid) VALUES ('GUESTS', 3, 0, '', 0, '', '', ''); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid) VALUES ('REGISTERED', 3, 0, '', 0, '', '', ''); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid) VALUES ('REGISTERED_COPPA', 3, 0, '', 0, '', '', ''); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid) VALUES ('GLOBAL_MODERATORS', 3, 0, '00AA00', 1, '', '', ''); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid) VALUES ('ADMINISTRATORS', 3, 1, 'AA0000', 1, '', '', ''); -INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid) VALUES ('BOTS', 3, 0, '9E8DA7', 0, '', '', ''); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GUESTS', 3, 0, '', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED', 3, 0, '', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED_COPPA', 3, 0, '', 0, '', '', '', 5); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GLOBAL_MODERATORS', 3, 0, '00AA00', 1, '', '', '', 0); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('ADMINISTRATORS', 3, 1, 'AA0000', 1, '', '', '', 0); +INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('BOTS', 3, 0, '9E8DA7', 0, '', '', '', 5); # -- User -> Group INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (1, 1, 0, 0); @@ -521,15 +526,15 @@ 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 6, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_flash', 'u_pm_forward'); # Limited Features (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 7, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 7, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group'); # No Private Messages (u_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_', 'u_chgavatar', 'u_chgcensors', 'u_chgemail', 'u_chgpasswd', 'u_download', 'u_hideonline', 'u_sig', 'u_viewprofile'); -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_readpm', 'u_sendpm', 'u_masspm'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_readpm', 'u_sendpm', 'u_masspm', 'u_masspm_group'); # No Avatar (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_chgavatar', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim'); -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_chgavatar'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_chgavatar', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_chgavatar', 'u_masspm', 'u_masspm_group'); # Full Moderator (m_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 10, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%'; diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index d7ac93f672..8033b2d583 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -304,6 +304,7 @@ CREATE TABLE phpbb_groups ( group_sig_chars INTEGER UNSIGNED NOT NULL DEFAULT '0', group_receive_pm INTEGER UNSIGNED NOT NULL DEFAULT '0', group_message_limit INTEGER UNSIGNED NOT NULL DEFAULT '0', + group_max_recipients INTEGER UNSIGNED NOT NULL DEFAULT '0', group_legend INTEGER UNSIGNED NOT NULL DEFAULT '1' ); @@ -713,7 +714,9 @@ CREATE TABLE phpbb_styles_template ( template_copyright varchar(255) NOT NULL DEFAULT '', template_path varchar(100) NOT NULL DEFAULT '', bbcode_bitfield varchar(255) NOT NULL DEFAULT 'kNg=', - template_storedb INTEGER UNSIGNED NOT NULL DEFAULT '0' + template_storedb INTEGER UNSIGNED NOT NULL DEFAULT '0', + template_inherits_id INTEGER UNSIGNED NOT NULL DEFAULT '0', + template_inherit_path varchar(255) NOT NULL DEFAULT '' ); CREATE UNIQUE INDEX phpbb_styles_template_tmplte_nm ON phpbb_styles_template (template_name); diff --git a/phpBB/language/en/acp/attachments.php b/phpBB/language/en/acp/attachments.php index 594eb9de33..f6369b6739 100644 --- a/phpBB/language/en/acp/attachments.php +++ b/phpBB/language/en/acp/attachments.php @@ -59,7 +59,7 @@ $lang = array_merge($lang, array( 'ATTACH_MAX_FILESIZE' => 'Maximum file size', 'ATTACH_MAX_FILESIZE_EXPLAIN' => 'Maximum size of each file, with 0 being unlimited.', 'ATTACH_MAX_PM_FILESIZE' => 'Maximum file size messaging', - 'ATTACH_MAX_PM_FILESIZE_EXPLAIN' => 'Maximum drive space available per user for private message attachments, with 0 being unlimited.', + 'ATTACH_MAX_PM_FILESIZE_EXPLAIN' => 'Maximum size of each file, with 0 being unlimited, attached to a private message.', 'ATTACH_ORPHAN_URL' => 'Orphan attachments', 'ATTACH_POST_ID' => 'Post ID', 'ATTACH_QUOTA' => 'Total attachment quota', @@ -105,8 +105,8 @@ $lang = array_merge($lang, array( 'IMAGICK_PATH' => 'Imagemagick path', 'IMAGICK_PATH_EXPLAIN' => 'Full path to the imagemagick convert application, e.g. /usr/bin/.', - 'MAX_ATTACHMENTS' => 'Max attachments per post', - 'MAX_ATTACHMENTS_PM' => 'Max attachments per message', + 'MAX_ATTACHMENTS' => 'Maximum number of attachments per post', + 'MAX_ATTACHMENTS_PM' => 'Maximum number of attachments per private message', 'MAX_EXTGROUP_FILESIZE' => 'Maximum file size', 'MAX_IMAGE_SIZE' => 'Maximum image dimensions', 'MAX_IMAGE_SIZE_EXPLAIN' => 'Maximum size of image attachments. Set both values to 0px by 0px to disable dimension checking.', diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index ae122c54ee..fc61cd2eaa 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -113,6 +113,7 @@ $lang = array_merge($lang, array( 'ALLOW_FORWARD_PM' => 'Allow forwarding of private messages', 'ALLOW_IMG_PM' => 'Allow use of [IMG] BBCode tag', 'ALLOW_MASS_PM' => 'Allow sending of private messages to multiple users and groups', + 'ALLOW_MASS_PM_EXPLAIN' => 'Sending to groups can be adjusted per group within the group settings page.', 'ALLOW_PRINT_PM' => 'Allow print view in private messaging', 'ALLOW_QUOTE_PM' => 'Allow quotes in private messages', 'ALLOW_SIG_PM' => 'Allow signature in private messages', @@ -127,6 +128,8 @@ $lang = array_merge($lang, array( 'HOLD_NEW_MESSAGES' => 'Hold new messages', 'PM_EDIT_TIME' => 'Limit editing time', 'PM_EDIT_TIME_EXPLAIN' => 'Limits the time available to edit a private message not already delivered. Setting the value to 0 disables this behaviour.', + 'PM_MAX_RECIPIENTS' => 'Maximum number of allowed recipients', + 'PM_MAX_RECIPIENTS_EXPLAIN' => 'The maximum number of allowed recipients in a private message. If 0 is entered, an unlimited number is allowed. This setting can be adjusted for every group within the group settings page.', )); // Post Settings @@ -137,6 +140,11 @@ $lang = array_merge($lang, array( 'ALLOW_POST_FLASH' => 'Allow use of [FLASH] BBCode tag in posts', 'ALLOW_POST_FLASH_EXPLAIN' => 'If disallowed the [FLASH] BBCode tag is disabled in posts. Otherwise the permission system controls which users can use the [FLASH] BBCode tag.', + 'ENABLE_QUEUE_TRIGGER' => 'Enable queued posts', + 'ENABLE_QUEUE_TRIGGER_EXPLAIN' => 'Ability to put registered users posts to post approval if their post count is lower than the specified value below. This setting has no effect on the permission setting for post/topic approval.', + 'QUEUE_TRIGGER_POSTS' => 'Maximum post count for queued posts', + 'QUEUE_TRIGGER_POSTS_EXPLAIN' => 'If queued posts is enabled, this is the post count the user need to reach in order to post without post approval. If the users post count is below this number, the post is stored in the queue automatically.', + 'BUMP_INTERVAL' => 'Bump interval', 'BUMP_INTERVAL_EXPLAIN' => 'Number of minutes, hours or days between the last post to a topic and the ability to bump this topic.', 'CHAR_LIMIT' => 'Maximum characters per post', @@ -278,7 +286,7 @@ $lang = array_merge($lang, array( 'YES_ANON_READ_MARKING' => 'Enable topic marking for guests', 'YES_ANON_READ_MARKING_EXPLAIN' => 'Stores read/unread status information for guests. If disabled posts are always read for guests.', 'YES_BIRTHDAYS' => 'Enable birthday listing', - 'YES_BIRTHDAYS_EXPLAIN' => 'If disabled the birthday listing is no longer displayed. To let this setting take effect the birthday feature need to be enabled too.', + 'YES_BIRTHDAYS_EXPLAIN' => 'If disabled the birthday listing is no longer displayed. To let this setting take effect the birthday feature needs to be enabled too.', 'YES_JUMPBOX' => 'Enable display of jumpbox', 'YES_MODERATORS' => 'Enable display of moderators', 'YES_ONLINE' => 'Enable online user listings', @@ -362,7 +370,7 @@ $lang = array_merge($lang, array( 'BROWSER_VALID' => 'Validate browser', 'BROWSER_VALID_EXPLAIN' => 'Enables browser validation for each session improving security.', 'CHECK_DNSBL' => 'Check IP against DNS Blackhole List', - 'CHECK_DNSBL_EXPLAIN' => 'If enabled the user’s IP address is checked against the following DNSBL services on registration and posting: spamcop.net, dsbl.org and www.spamhaus.org. This lookup may take a while, depending on the server’s configuration. If slowdowns are experienced or too many false positives reported it is recommended to disable this check.', + 'CHECK_DNSBL_EXPLAIN' => 'If enabled the user’s IP address is checked against the following DNSBL services on registration and posting: spamcop.net and www.spamhaus.org. This lookup may take a while, depending on the server’s configuration. If slowdowns are experienced or too many false positives reported it is recommended to disable this check.', 'CLASS_B' => 'A.B', 'CLASS_C' => 'A.B.C', 'EMAIL_CHECK_MX' => 'Check e-mail domain for valid MX record', @@ -410,7 +418,7 @@ $lang = array_merge($lang, array( 'EMAIL_FUNCTION_NAME' => 'E-mail function name', 'EMAIL_FUNCTION_NAME_EXPLAIN' => 'The e-mail function used to send mails through PHP.', 'EMAIL_PACKAGE_SIZE' => 'E-mail package size', - 'EMAIL_PACKAGE_SIZE_EXPLAIN' => 'This is the number of maximum e-mails sent out in one package. This setting is applied to the internal message queue; set this value to 0 if you have problems with non-delivered notification emails.', + 'EMAIL_PACKAGE_SIZE_EXPLAIN' => 'This is the number of maximum e-mails sent out in one package. This setting is applied to the internal message queue; set this value to 0 if you have problems with non-delivered notification e-mails.', 'EMAIL_SIG' => 'E-mail signature', 'EMAIL_SIG_EXPLAIN' => 'This text will be attached to all e-mails the board sends.', 'ENABLE_EMAIL' => 'Enable board-wide e-mails', @@ -451,8 +459,8 @@ $lang = array_merge($lang, array( 'JAB_SETTINGS_CHANGED' => 'Jabber settings changed successfully.', 'JAB_USE_SSL' => 'Use SSL to connect', 'JAB_USE_SSL_EXPLAIN' => 'If enabled a secure connection is tried to be established. The Jabber port will be modified to 5223 if port 5222 is specified.', - 'JAB_USERNAME' => 'Jabber username', - 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username. The username will not be checked for validity.', + 'JAB_USERNAME' => 'Jabber username or JID', + 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username or a valid JID. The username will not be checked for validity. If you only specify a username, then your JID will be the username and the server you specified above. Else, specify a valid JID, for example user@jabber.org.', )); ?> \ No newline at end of file diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 9ed92bfcfb..a9708308ac 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -268,7 +268,7 @@ $lang = array_merge($lang, array( 'SELECT_OPTION' => 'Select option', 'SETTING_TOO_LOW' => 'The entered value for the setting “%1$s” is too low. The minimal allowed value is %2$d.', - 'SETTING_TOO_BIG' => 'The entered value for the setting “%1$s” is too big. The maximal allowed value is %2$d.', + 'SETTING_TOO_BIG' => 'The entered value for the setting “%1$s” is too big. The maximal allowed value is %2$d.', 'SETTING_TOO_LONG' => 'The entered value for the setting “%1$s” is too long. The maximal allowed length is %2$d.', 'SETTING_TOO_SHORT' => 'The entered value for the setting “%1$s” is not long enough. The minimal allowed length is %2$d.', @@ -362,6 +362,7 @@ $lang = array_merge($lang, array( 'VIEW_INACTIVE_USERS' => 'View inactive users', 'WELCOME_PHPBB' => 'Welcome to phpBB', + 'WRITABLE_CONFIG' => 'Your config file (config.php) is currently world-writable. We strongly encourage you to change the permissions to 640 or at least to 644 (for example: chmod 640 config.php).', )); // Inactive Users @@ -473,12 +474,13 @@ $lang = array_merge($lang, array( 'LOG_APPROVE_TOPIC' => 'Approved topic
» %s', 'LOG_BUMP_TOPIC' => 'User bumped topic
» %s', 'LOG_DELETE_POST' => 'Deleted post
» %s', + 'LOG_DELETE_SHADOW_TOPIC' => 'Deleted shadow topic
» %s', 'LOG_DELETE_TOPIC' => 'Deleted topic
» %s', 'LOG_FORK' => 'Copied topic
» from %s', 'LOG_LOCK' => 'Locked topic
» %s', 'LOG_LOCK_POST' => 'Locked post
» %s', 'LOG_MERGE' => 'Merged posts into topic
» %s', - 'LOG_MOVE' => 'Moved topic
» from %s', + 'LOG_MOVE' => 'Moved topic
» from %1$s to %2$s', 'LOG_POST_APPROVED' => 'Approved post
» %s', 'LOG_POST_DISAPPROVED' => 'Disapproved post “%1$s” with the following reason
» %2$s', 'LOG_POST_EDITED' => 'Edited post “%1$s” written by
» %2$s', @@ -487,7 +489,6 @@ $lang = array_merge($lang, array( 'LOG_SPLIT_DESTINATION' => 'Moved split posts
» to %s', 'LOG_SPLIT_SOURCE' => 'Split posts
» from %s', - 'LOG_TOPIC_DELETED' => 'Deleted topic
» %s', 'LOG_TOPIC_APPROVED' => 'Approved topic
» %s', 'LOG_TOPIC_DISAPPROVED' => 'Disapproved topic “%1$s” with the following reason
%2$s', 'LOG_TOPIC_RESYNC' => 'Resynchronised topic counters
» %s', @@ -687,4 +688,9 @@ $lang = array_merge($lang, array( 'LOG_WORD_EDIT' => 'Edited word censor
» %s', )); +// Two language keys with the same text were used in different locations +// LOG_DELETE_TOPIC is the correct one, this line is here so that existing +// log entries are not broken. Ensure it is included in your language file. +$lang['LOG_TOPIC_DELETED'] = $lang['LOG_DELETE_TOPIC']; + ?> \ No newline at end of file diff --git a/phpBB/language/en/acp/groups.php b/phpBB/language/en/acp/groups.php index f74110a7d3..db6f334540 100644 --- a/phpBB/language/en/acp/groups.php +++ b/phpBB/language/en/acp/groups.php @@ -86,6 +86,8 @@ $lang = array_merge($lang, array( 'GROUP_NAME_TAKEN' => 'The group name you entered is already in use, please select an alternative.', '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_PROMOTE' => 'Promote to group leader', 'GROUP_RANK' => 'Group rank', 'GROUP_RECEIVE_PM' => 'Group able to receive private messages', diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php index 8f090667b4..c8ccc0e56a 100644 --- a/phpBB/language/en/acp/permissions_phpbb.php +++ b/phpBB/language/en/acp/permissions_phpbb.php @@ -111,7 +111,8 @@ $lang = array_merge($lang, array( 'acl_u_sig' => array('lang' => 'Can use signature', 'cat' => 'post'), 'acl_u_sendpm' => array('lang' => 'Can send private messages', 'cat' => 'pm'), - 'acl_u_masspm' => array('lang' => 'Can send pm to multiple users and groups', 'cat' => 'pm'), + 'acl_u_masspm' => array('lang' => 'Can send messages to multiple users', 'cat' => 'pm'), + 'acl_u_masspm_group'=> array('lang' => 'Can send messages to groups', 'cat' => 'pm'), 'acl_u_readpm' => array('lang' => 'Can read private messages', 'cat' => 'pm'), 'acl_u_pm_edit' => array('lang' => 'Can edit own private messages', 'cat' => 'pm'), 'acl_u_pm_delete' => array('lang' => 'Can remove private messages from own folder', 'cat' => 'pm'), diff --git a/phpBB/language/en/acp/posting.php b/phpBB/language/en/acp/posting.php index ebde75cfaa..66ce911ff6 100644 --- a/phpBB/language/en/acp/posting.php +++ b/phpBB/language/en/acp/posting.php @@ -47,6 +47,8 @@ $lang = array_merge($lang, array( 'BBCODE_HELPLINE' => 'Help line', 'BBCODE_HELPLINE_EXPLAIN' => 'This field contains the mouse over text of the BBCode.', 'BBCODE_HELPLINE_TEXT' => 'Help line text', + 'BBCODE_HELPLINE_TOO_LONG' => 'The help line you entered is too long.', + 'BBCODE_INVALID_TAG_NAME' => 'The BBCode tag name that you selected already exists.', 'BBCODE_INVALID' => 'Your BBCode is constructed in an invalid form.', 'BBCODE_OPEN_ENDED_TAG' => 'Your custom BBCode must contain both an opening and a closing tag.', diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php index a6333fcba0..eb742fd140 100644 --- a/phpBB/language/en/acp/styles.php +++ b/phpBB/language/en/acp/styles.php @@ -86,6 +86,7 @@ $lang = array_merge($lang, array( 'DETAILS' => 'Details', 'DIMENSIONS_EXPLAIN' => 'Selecting yes here will include width/height parameters.', + 'EDIT_DETAILS_IMAGESET' => 'Edit imageset details', 'EDIT_DETAILS_IMAGESET_EXPLAIN' => 'Here you can edit certain imageset details such as its name.', 'EDIT_DETAILS_STYLE' => 'Edit style', @@ -103,6 +104,7 @@ $lang = array_merge($lang, array( 'EDIT_THEME_EXPLAIN' => 'Here you can edit the selected theme, changing colours, images, etc.', 'EDIT_THEME_STORED_DB' => 'The stylesheet file was unwritable so the stylesheet is now stored in the database containing your modification.', 'EDIT_THEME_STORE_PARSED' => 'The theme requires that its stylesheet is parsed. This is only possible if it’s stored in the database.', + 'EDITOR_DISABLED' => 'The template editor is disabled.', 'EXPORT' => 'Export', 'FOREGROUND' => 'Foreground', @@ -168,7 +170,7 @@ $lang = array_merge($lang, array( 'IMG_FORUM_UNREAD_SUBFORUM' => 'Subforum new posts', 'IMG_SUBFORUM_READ' => 'Legend subforum', 'IMG_SUBFORUM_UNREAD' => 'Legend subforum new posts', - + 'IMG_TOPIC_MOVED' => 'Topic moved', 'IMG_TOPIC_READ' => 'Topic', @@ -269,6 +271,7 @@ $lang = array_merge($lang, array( 'INCLUDE_IMAGESET' => 'Include imageset', 'INCLUDE_TEMPLATE' => 'Include template', 'INCLUDE_THEME' => 'Include theme', + 'INHERITING_FROM' => 'Inherits from', 'INSTALL_IMAGESET' => 'Install imageset', 'INSTALL_IMAGESET_EXPLAIN' => 'Here you can install your selected imageset. You can edit certain details if you wish or use the installation defaults.', 'INSTALL_STYLE' => 'Install style', @@ -284,6 +287,8 @@ $lang = array_merge($lang, array( 'LINE_SPACING' => 'Line spacing', 'LOCALISED_IMAGES' => 'Localised', + 'LOCATION_DISABLED_EXPLAIN' => 'This setting is inherited and cannot be changed.', + 'NO_CLASS' => 'Cannot find class in stylesheet.', 'NO_IMAGESET' => 'Cannot find imageset on filesystem.', @@ -364,6 +369,7 @@ $lang = array_merge($lang, array( 'TEMPLATE_CACHE_CLEARED' => 'Template cache cleared successfully.', 'TEMPLATE_CACHE_EMPTY' => 'There are no cached templates.', 'TEMPLATE_DELETED' => 'Template set deleted successfully.', + 'TEMPLATE_DELETE_DEPENDENT' => 'The template set cannot be deleted as there are one or more other template sets inheriting from it:', 'TEMPLATE_DELETED_FS' => 'Template set removed from database but some files may remain on the filesystem.', 'TEMPLATE_DETAILS_UPDATED' => 'Template details successfully updated.', 'TEMPLATE_EDITOR' => 'Raw HTML template editor', @@ -375,12 +381,14 @@ $lang = array_merge($lang, array( 'TEMPLATE_ERR_NAME_EXIST' => 'A template set with that name already exists.', 'TEMPLATE_ERR_NAME_LONG' => 'The template name can be no longer than 30 characters.', 'TEMPLATE_ERR_NOT_TEMPLATE' => 'The archive you specified does not contain a valid template set.', + 'TEMPLATE_ERR_REQUIRED_OR_INCOMPLETE' => 'The new template set requires the template %s to be installed and not inheriting itself.', 'TEMPLATE_ERR_STYLE_NAME' => 'You must supply a name for this template.', 'TEMPLATE_EXPORT' => 'Export templates', 'TEMPLATE_EXPORT_EXPLAIN' => 'Here you can export a template set in the form of an archive. This archive will contain all the files necessary to install the templates on another board. You may select whether to download the file directly or to place it in your store folder for download later or via FTP.', 'TEMPLATE_EXPORTED' => 'Templates exported successfully and stored in %s.', 'TEMPLATE_FILE' => 'Template file', 'TEMPLATE_FILE_UPDATED' => 'Template file updated successfully.', + 'TEMPLATE_INHERITS' => 'This template sets inherits from %s and thus cannot have a different storage setting than its super template.', 'TEMPLATE_LOCATION' => 'Store templates in', 'TEMPLATE_LOCATION_EXPLAIN' => 'Images are always stored on the filesystem.', 'TEMPLATE_NAME' => 'Template name', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 7739c63521..93ad31e127 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -170,6 +170,8 @@ $lang = array_merge($lang, array( 'ERR_JAB_AUTH' => 'Could not authorise on Jabber server.', 'ERR_JAB_CONNECT' => 'Could not connect to Jabber server.', 'ERR_UNABLE_TO_LOGIN' => 'The specified username or password is incorrect.', + 'ERR_UNWATCHING' => 'An error occured while trying to unsubscribe.', + 'ERR_WATCHING' => 'An error occured while trying to subscribe.', 'ERR_WRONG_PATH_TO_PHPBB' => 'The phpBB path specified appears to be invalid.', 'EXPAND_VIEW' => 'Expand view', 'EXTENSION' => 'Extension', @@ -262,7 +264,7 @@ $lang = array_merge($lang, array( 'HOME' => 'Home', 'ICQ' => 'ICQ', - 'ICQ_STATUS' => 'ICQ status', + 'ICQ_STATUS' => 'ICQ status', 'IF' => 'If', 'IMAGE' => 'Image', 'IMAGE_FILETYPE_INVALID' => 'Image file type %d for mimetype %s not supported.', @@ -278,7 +280,7 @@ $lang = array_merge($lang, array( 'JABBER' => 'Jabber', 'JOINED' => 'Joined', - 'JUMP_PAGE' => 'Enter the page number you wish to go to.', + 'JUMP_PAGE' => 'Enter the page number you wish to go to', 'JUMP_TO' => 'Jump to', 'JUMP_TO_PAGE' => 'Click to jump to page…', @@ -333,7 +335,7 @@ $lang = array_merge($lang, array( 'MODERATORS' => 'Moderators', 'MONTH' => 'Month', 'MOVE' => 'Move', - 'MSNM' => 'MSNM/WLM', + 'MSNM' => 'MSNM/WLM', 'NA' => 'N/A', 'NEWEST_USER' => 'Our newest member %s', @@ -355,7 +357,7 @@ $lang = array_merge($lang, array( 'NOTIFY_ADMIN_EMAIL' => 'Please notify the board administrator or webmaster: %1$s', 'NO_ACCESS_ATTACHMENT' => 'You are not allowed to access this file.', 'NO_ACTION' => 'No action specified.', - 'NO_ADMINISTRATORS' => 'No administrators assigned at this board.', + 'NO_ADMINISTRATORS' => 'There are no administrators.', 'NO_AUTH_ADMIN' => 'Access to the Administration Control Panel is not allowed as you do not have administrative permissions.', 'NO_AUTH_ADMIN_USER_DIFFER' => 'You are not able to re-authenticate as a different user.', 'NO_AUTH_OPERATION' => 'You do not have the necessary permissions to complete this operation.', @@ -372,7 +374,7 @@ $lang = array_merge($lang, array( 'NO_MEMBERS' => 'No members found for this search criterion.', 'NO_MESSAGES' => 'No messages', 'NO_MODE' => 'No mode specified.', - 'NO_MODERATORS' => 'No moderators assigned at this board.', + 'NO_MODERATORS' => 'There are no moderators.', 'NO_NEW_MESSAGES' => 'No new messages', 'NO_NEW_PM' => '0 new messages', 'NO_NEW_POSTS' => 'No new posts', @@ -392,6 +394,13 @@ $lang = array_merge($lang, array( 'NO_USERS' => 'The requested users do not exist.', 'NO_USER_SPECIFIED' => 'No username was specified.', + // Nullar/Singular/Plural language entry. The key numbers define the number range in which a certain grammatical expression is valid. + 'NUM_POSTS_IN_QUEUE' => array( + 0 => 'No posts in queue', // 0 + 1 => '1 post in queue', // 1 + 2 => '%d posts in queue', // 2+ + ), + 'OCCUPATION' => 'Occupation', 'OFFLINE' => 'Offline', 'ONLINE' => 'Online', @@ -500,7 +509,7 @@ $lang = array_merge($lang, array( 'SEARCHING_FORUMS' => 'Searching forums', 'SEARCH_ACTIVE_TOPICS' => 'View active topics', 'SEARCH_FOR' => 'Search for', - 'SEARCH_FORUM' => 'Search this forum…', + 'SEARCH_FORUM' => 'Search this forum…', 'SEARCH_NEW' => 'View new posts', 'SEARCH_POSTS_BY' => 'Search posts by', 'SEARCH_SELF' => 'View your posts', @@ -543,6 +552,8 @@ $lang = array_merge($lang, array( 'THE_TEAM' => 'The team', 'TIME' => 'Time', + 'TOO_LONG' => 'The value you entered is too long.', + 'TOO_LONG_AIM' => 'The screenname you entered is too long.', 'TOO_LONG_CONFIRM_CODE' => 'The confirm code you entered is too long.', 'TOO_LONG_DATEFORMAT' => 'The date format you entered is too long.', @@ -563,6 +574,8 @@ $lang = array_merge($lang, array( 'TOO_MANY_VOTE_OPTIONS' => 'You have tried to vote for too many options.', + 'TOO_SHORT' => 'The value you entered is too short.', + 'TOO_SHORT_AIM' => 'The screenname you entered is too short.', 'TOO_SHORT_CONFIRM_CODE' => 'The confirm code you entered is too short.', 'TOO_SHORT_DATEFORMAT' => 'The date format you entered is too short.', @@ -674,7 +687,7 @@ $lang = array_merge($lang, array( 'YEAR' => 'Year', 'YEAR_MONTH_DAY' => '(YYYY-MM-DD)', 'YES' => 'Yes', - 'YIM' => 'YIM', + 'YIM' => 'YIM', 'YOU_LAST_VISIT' => 'Last visit was: %s', 'YOU_NEW_PM' => 'A new private message is waiting for you in your Inbox.', 'YOU_NEW_PMS' => 'New private messages are waiting for you in your Inbox.', @@ -738,6 +751,7 @@ $lang = array_merge($lang, array( '-7' => 'UTC - 7 hours', '-6' => 'UTC - 6 hours', '-5' => 'UTC - 5 hours', + '-4.5' => 'UTC - 4:30 hours', '-4' => 'UTC - 4 hours', '-3.5' => 'UTC - 3:30 hours', '-3' => 'UTC - 3 hours', @@ -781,6 +795,7 @@ $lang = array_merge($lang, array( '-7' => '[UTC - 7] Mountain Standard Time', '-6' => '[UTC - 6] Central Standard Time', '-5' => '[UTC - 5] Eastern Standard Time', + '-4.5' => '[UTC - 4:30] Venezuelan Standard Time', '-4' => '[UTC - 4] Atlantic Standard Time', '-3.5' => '[UTC - 3:30] Newfoundland Standard Time', '-3' => '[UTC - 3] Amazon Standard Time, Central Greenland Time', diff --git a/phpBB/language/en/email/group_request.txt b/phpBB/language/en/email/group_request.txt index 85664857dd..75840831fb 100644 --- a/phpBB/language/en/email/group_request.txt +++ b/phpBB/language/en/email/group_request.txt @@ -2,7 +2,7 @@ Subject: A request to join your group has been made Dear {USERNAME}, -A user has requested to join the group "{GROUP_NAME}" you moderate on "{SITENAME}". +The user "{REQUEST_USERNAME}" has requested to join the group "{GROUP_NAME}" you moderate on "{SITENAME}". To approve or deny this request for group membership please visit the following link: {U_PENDING} diff --git a/phpBB/language/en/help_faq.php b/phpBB/language/en/help_faq.php index 354d432d51..89ac845021 100644 --- a/phpBB/language/en/help_faq.php +++ b/phpBB/language/en/help_faq.php @@ -120,7 +120,7 @@ $help = array( ), 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 Add signature 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 your profile. 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.' + 1 => 'To add a signature to a post you must first create one via your User Control Panel. Once created, you can check the Attach a signature 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 your profile. 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?', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 31778f7cf4..e6555f5a41 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -212,7 +212,7 @@ $lang = array_merge($lang, array(
  • MS SQL Server 2000 or above (directly or via ODBC)
  • Oracle
  • - +

    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', @@ -278,7 +278,7 @@ $lang = array_merge($lang, array( '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!

    phpBB™ is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a seven year long package lineup. 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.

    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 the installation guide.

    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.', + 'OVERVIEW_BODY' => 'Welcome to phpBB3!

    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.

    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 the installation guide.

    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 not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.', @@ -397,6 +397,7 @@ $lang = array_merge($lang, array( 'DONE' => 'Done', 'DOWNLOAD' => 'Download', 'DOWNLOAD_AS' => 'Download as', + 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)', '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.', @@ -497,6 +498,8 @@ $lang = array_merge($lang, array( '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.
    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', diff --git a/phpBB/language/en/mcp.php b/phpBB/language/en/mcp.php index f53babdc69..93b694be77 100644 --- a/phpBB/language/en/mcp.php +++ b/phpBB/language/en/mcp.php @@ -292,7 +292,7 @@ $lang = array_merge($lang, array( 'SORT_DATE' => 'Date', 'SORT_IP' => 'IP address', 'SORT_WARNINGS' => 'Warnings', - 'SPLIT_AFTER' => 'Split from selected post', + 'SPLIT_AFTER' => 'Split topic from selected post onwards', 'SPLIT_FORUM' => 'Forum for new topic', 'SPLIT_POSTS' => 'Split selected posts', 'SPLIT_SUBJECT' => 'New topic title', @@ -346,6 +346,7 @@ $lang = array_merge($lang, array( 'USER_WARNING_ADDED' => 'User warned successfully.', 'VIEW_DETAILS' => 'View details', + 'VIEW_POST' => 'View post', 'WARNED_USERS' => 'Warned users', 'WARNED_USERS_EXPLAIN' => 'This is a list of users with unexpired warnings issued to them.', diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 4f9920c931..f18ebbaf8b 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -50,7 +50,7 @@ $lang = array_merge($lang, array(
    We may also create cookies external to the phpBB software whilst browsing “%1$s”, though these are outside the scope of this document which is intended to only cover the pages created by the phpBB software. The second way in which we collect your information is by what you submit to us. This can be, and is not limited to: posting as an anonymous user (hereinafter “anonymous posts”), registering on “%1$s” (hereinafter “your account”) and posts submitted by you after registration and whilst logged in (hereinafter “your posts”).

    - Your account will at a bare minimum contain a uniquely identifiable name (hereinafter “your user name”), a personal password used for logging into your account (hereinafter “your password”) and a personal, valid e-mail address (hereinafter “your e-mail”). Your information for your account at “%1$s” is protected by data-protection laws applicable in the country that hosts us. Any information beyond your user name, your password and your e-mail required by “%1$s” during the registration process are at our digression what is mandatory and what is optional. In all cases, you have the option of what information in your account is publicly displayed. Furthermore, within your account, you have the option to opt-in or opt-out of automatically generated e-mails from the phpBB software.
    + Your account will at a bare minimum contain a uniquely identifiable name (hereinafter “your user name”), a personal password used for logging into your account (hereinafter “your password”) and a personal, valid e-mail address (hereinafter “your e-mail”). Your information for your account at “%1$s” is protected by data-protection laws applicable in the country that hosts us. Any information beyond your user name, your password, and your e-mail address required by “%1$s” during the registration process is either mandatory or optional, at the discretion of “%1$s”. In all cases, you have the option of what information in your account is publicly displayed. Furthermore, within your account, you have the option to opt-in or opt-out of automatically generated e-mails from the phpBB software.

    Your password is ciphered (a one-way hash) so that it is secure. However, it is recommended that you do not reuse the same password across a number of different websites. Your password is the means of accessing your account at “%1$s”, so please guard it carefully and under no circumstance will anyone affiliated with “%1$s”, phpBB or another 3rd party, legitimately ask you for your password. Should you forget your password for your account, you can use the “I forgot my password” feature provided by the phpBB software. This process will ask you to submit your user name and your e-mail, then the phpBB software will generate a new password to reclaim your account.
    ', @@ -288,9 +288,11 @@ $lang = array_merge($lang, array( 'NO_AUTH_EDIT_MESSAGE' => 'You are not authorised to edit private messages.', 'NO_AUTH_FORWARD_MESSAGE' => 'You are not authorised to forward private messages.', 'NO_AUTH_GROUP_MESSAGE' => 'You are not authorised to send private messages to groups.', + 'NO_AUTH_PASSWORD_REMINDER' => 'You are not authorised to request a new password.', + 'NO_AUTH_READ_HOLD_MESSAGE' => 'You are not authorised to read private messages that are on hold.', 'NO_AUTH_READ_MESSAGE' => 'You are not authorised to read private messages.', 'NO_AUTH_READ_REMOVED_MESSAGE' => 'You are not able to read this message because it was removed by the author.', - 'NO_AUTH_SEND_MESSAGE' => 'You are not authorised sending private messages.', + 'NO_AUTH_SEND_MESSAGE' => 'You are not authorised to send private messages.', 'NO_AUTH_SIGNATURE' => 'You are not authorised to define a signature.', 'NO_BCC_RECIPIENT' => 'None', @@ -314,6 +316,7 @@ $lang = array_merge($lang, array( 'NO_SAVED_DRAFTS' => 'No drafts saved.', 'NO_TO_RECIPIENT' => 'None', 'NO_WATCHED_FORUMS' => 'You are not subscribed to any forums.', + 'NO_WATCHED_SELECTED' => 'You have not selected any subscribed topics or forums.', 'NO_WATCHED_TOPICS' => 'You are not subscribed to any topics.', 'PASS_TYPE_ALPHA_EXPLAIN' => 'Password must be between %1$d and %2$d characters long, must contain letters in mixed case and must contain numbers.', @@ -390,7 +393,7 @@ $lang = array_merge($lang, array( 'TIMEZONE' => 'Timezone', 'TO' => 'To', - 'TOO_MANY_RECIPIENTS' => 'Too many recipients.', + 'TOO_MANY_RECIPIENTS' => 'You tried to send a private message to too many recipients.', 'TOO_MANY_REGISTERS' => 'You have exceeded the maximum number of registration attempts for this session. Please try again later.', 'UCP' => 'User Control Panel', diff --git a/phpBB/language/en/viewtopic.php b/phpBB/language/en/viewtopic.php index 337a21c11f..4252fa7542 100644 --- a/phpBB/language/en/viewtopic.php +++ b/phpBB/language/en/viewtopic.php @@ -40,6 +40,7 @@ $lang = array_merge($lang, array( 'ATTACHMENT_FUNCTIONALITY_DISABLED' => 'The attachments feature has been disabled.', 'BOOKMARK_ADDED' => 'Bookmarked topic successfully.', + 'BOOKMARK_ERR' => 'Bookmarking the topic failed. Please try again.', 'BOOKMARK_REMOVED' => 'Removed bookmarked topic successfully.', 'BOOKMARK_TOPIC' => 'Bookmark topic', 'BOOKMARK_TOPIC_REMOVE' => 'Remove from bookmarks', diff --git a/phpBB/mcp.php b/phpBB/mcp.php index cb6c14ca0c..47578c3532 100644 --- a/phpBB/mcp.php +++ b/phpBB/mcp.php @@ -166,7 +166,7 @@ if ($quickmod) case 'delete_post': case 'delete_topic': $module->load('mcp', 'main', 'quickmod'); - exit; + return; break; case 'topic_logs': @@ -183,7 +183,8 @@ if ($quickmod) break; default: - trigger_error("$action not allowed as quickmod"); + trigger_error("$action not allowed as quickmod", E_USER_ERROR); + break; } } else @@ -611,7 +612,7 @@ function mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, $sql = 'SELECT COUNT(post_id) AS total FROM ' . POSTS_TABLE . " - $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : get_forum_list('m_approve')) . ' + $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))) . ' AND post_approved = 0'; if ($min_time) @@ -627,7 +628,7 @@ function mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, $sql = 'SELECT COUNT(topic_id) AS total FROM ' . TOPICS_TABLE . " - $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : get_forum_list('m_approve')) . ' + $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))) . ' AND topic_approved = 0'; if ($min_time) @@ -653,7 +654,7 @@ function mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, } else { - $where_sql .= ' ' . $db->sql_in_set('p.forum_id', get_forum_list('!m_report'), true, true); + $where_sql .= ' ' . $db->sql_in_set('p.forum_id', get_forum_list(array('!f_read', '!m_report')), true, true); } if ($mode == 'reports') @@ -679,7 +680,7 @@ function mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, $sql = 'SELECT COUNT(log_id) AS total FROM ' . LOG_TABLE . " - $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : get_forum_list('m_')) . ' + $where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_'))) . ' AND log_time >= ' . $min_time . ' AND log_type = ' . LOG_MOD; break; diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index f33eac5bac..ccd0568fd6 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -129,7 +129,7 @@ switch ($mode) $admin_memberships = group_memberships($admin_group_id, $admin_id_ary); $admin_user_ids = array(); - + if (!empty($admin_memberships)) { // ok, we only need the user ids... @@ -527,13 +527,32 @@ switch ($mode) unset($module); } + // If the user has m_approve permission or a_user permission, then list then display unapproved posts + if ($auth->acl_getf_global('m_approve') || $auth->acl_get('a_user')) + { + $sql = 'SELECT COUNT(post_id) as posts_in_queue + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . $user_id . ' + AND post_approved = 0'; + $result = $db->sql_query($sql); + $member['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue'); + $db->sql_freeresult($result); + } + else + { + $member['posts_in_queue'] = 0; + } + $template->assign_vars(array( + 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $member['posts_in_queue']), + 'POSTS_DAY' => sprintf($user->lang['POST_DAY'], $posts_per_day), 'POSTS_PCT' => sprintf($user->lang['POST_PCT'], $percentage), 'OCCUPATION' => (!empty($member['user_occ'])) ? censor_text($member['user_occ']) : '', 'INTERESTS' => (!empty($member['user_interests'])) ? censor_text($member['user_interests']) : '', 'SIGNATURE' => $member['user_sig'], + 'POSTS_IN_QUEUE'=> $member['posts_in_queue'], 'AVATAR_IMG' => $poster_avatar, 'PM_IMG' => $user->img('icon_contact_pm', $user->lang['SEND_PRIVATE_MESSAGE']), @@ -552,6 +571,7 @@ switch ($mode) 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '', 'U_USER_BAN' => ($auth->acl_get('m_ban')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=ban&mode=user&u=' . $user_id, true, $user->session_id) : '', + 'U_MCP_QUEUE' => ($auth->acl_getf_global('m_approve')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue', true, $user->session_id) : '', 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_id) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&u={$user_id}") : '', @@ -925,10 +945,13 @@ switch ($mode) $field = request_var('field', ''); $select_single = request_var('select_single', false); + // Search URL parameters, if any of these are in the URL we do a search + $search_params = array('username', 'email', 'icq', 'aim', 'yahoo', 'msn', 'jabber', 'search_group_id', 'joined_select', 'active_select', 'count_select', 'joined', 'active', 'count', 'ip'); + // We validate form and field here, only id/class allowed $form = (!preg_match('/^[a-z0-9_-]+$/i', $form)) ? '' : $form; $field = (!preg_match('/^[a-z0-9_-]+$/i', $field)) ? '' : $field; - if ($mode == 'searchuser' && ($config['load_search'] || $auth->acl_get('a_'))) + if (($mode == 'searchuser' || sizeof(array_intersect(array_keys($_GET), $search_params)) > 0) && ($config['load_search'] || $auth->acl_get('a_'))) { $username = request_var('username', '', true); $email = strtolower(request_var('email', '')); @@ -1139,7 +1162,7 @@ switch ($mode) 'RANK_IMG' => $rank_img, 'RANK_IMG_SRC' => $rank_img_src, - 'U_PM' => ($auth->acl_get('u_sendpm') && $auth->acl_get('u_masspm') && $group_row['group_receive_pm'] && $config['allow_privmsg'] && $config['allow_mass_pm']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&g=' . $group_id) : '',) + 'U_PM' => ($auth->acl_get('u_sendpm') && $auth->acl_get('u_masspm_group') && $group_row['group_receive_pm'] && $config['allow_privmsg'] && $config['allow_mass_pm']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&g=' . $group_id) : '',) ); $sql_select = ', ug.group_leader'; @@ -1149,7 +1172,7 @@ switch ($mode) $sql_where .= " AND ug.user_pending = 0 AND u.user_id = ug.user_id AND ug.group_id = $group_id"; $sql_where_data = " AND u.user_id = ug.user_id AND ug.group_id = $group_id"; } - + // Sorting and order if (!isset($sort_key_sql[$sort_key])) { @@ -1233,14 +1256,17 @@ switch ($mode) } } - $u_hide_find_member = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $params)); + $u_hide_find_member = append_sid("{$phpbb_root_path}memberlist.$phpEx", "start=$start" . (!empty($params) ? '&' . implode('&', $params) : '')); - $params[] = "mode=$mode"; - $sort_params[] = "mode=$mode"; + if ($mode) + { + $params[] = "mode=$mode"; + $sort_params[] = "mode=$mode"; + } $pagination_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $params)); $sort_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $sort_params)); - unset($params, $sort_params); + unset($search_params, $sort_params); // Some search user specific data if ($mode == 'searchuser' && ($config['load_search'] || $auth->acl_get('a_'))) @@ -1326,7 +1352,7 @@ switch ($mode) $user_list[] = (int) $row['user_id']; } $db->sql_freeresult($result); - + $leaders_set = false; // So, did we get any users? if (sizeof($user_list)) { @@ -1386,15 +1412,16 @@ switch ($mode) // If we sort by last active date we need to adjust the id cache due to user_lastvisit not being the last active date... if ($sort_key == 'l') { - $lesser_than = ($sort_dir == 'a') ? -1 : 1; // uasort($id_cache, create_function('$first, $second', "return (\$first['last_visit'] == \$second['last_visit']) ? 0 : ((\$first['last_visit'] < \$second['last_visit']) ? $lesser_than : ($lesser_than * -1));")); - usort($user_list, create_function('$first, $second', "global \$id_cache; return (\$id_cache[\$first]['last_visit'] == \$id_cache[\$second]['last_visit']) ? 0 : ((\$id_cache[\$first]['last_visit'] < \$id_cache[\$second]['last_visit']) ? $lesser_than : ($lesser_than * -1));")); + usort($user_list, '_sort_last_active'); } for ($i = 0, $end = sizeof($user_list); $i < $end; ++$i) { $user_id = $user_list[$i]; $row =& $id_cache[$user_id]; + $is_leader = (isset($row['group_leader']) && $row['group_leader']) ? true : false; + $leaders_set = ($leaders_set || $is_leader); $cp_row = array(); if ($config['load_cpf_memberlist']) @@ -1406,7 +1433,7 @@ switch ($mode) 'ROW_NUMBER' => $i + ($start + 1), 'S_CUSTOM_PROFILE' => (isset($cp_row['row']) && sizeof($cp_row['row'])) ? true : false, - 'S_GROUP_LEADER' => (isset($row['group_leader']) && $row['group_leader']) ? true : false, + 'S_GROUP_LEADER' => $is_leader, 'U_VIEW_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $user_id)) ); @@ -1447,7 +1474,7 @@ switch ($mode) 'JABBER_IMG' => $user->img('icon_contact_jabber', $user->lang['JABBER']), 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), - 'U_FIND_MEMBER' => ($config['load_search'] || $auth->acl_get('a_')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser') : '', + 'U_FIND_MEMBER' => ($config['load_search'] || $auth->acl_get('a_')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser' . (($start) ? "&start=$start" : '') . (!empty($params) ? '&' . implode('&', $params) : '')) : '', 'U_HIDE_FIND_MEMBER' => ($mode == 'searchuser') ? $u_hide_find_member : '', 'U_SORT_USERNAME' => $sort_url . '&sk=a&sd=' . (($sort_key == 'a' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_FROM' => $sort_url . '&sk=b&sd=' . (($sort_key == 'b' && $sort_dir == 'a') ? 'd' : 'a'), @@ -1466,6 +1493,7 @@ switch ($mode) 'S_SHOW_GROUP' => ($mode == 'group') ? true : false, 'S_VIEWONLINE' => $auth->acl_get('u_viewonline'), + 'S_LEADERS_SET' => $leaders_set, 'S_MODE_SELECT' => $s_sort_key, 'S_ORDER_SELECT' => $s_sort_dir, 'S_CHAR_OPTIONS' => $s_char_options, @@ -1596,4 +1624,24 @@ function show_profile($data) ); } +function _sort_last_active($first, $second) +{ + global $id_cache, $sort_dir; + + $lesser_than = ($sort_dir === 'd') ? -1 : 1; + + if (isset($id_cache[$first]['group_leader']) && $id_cache[$first]['group_leader'] && (!isset($id_cache[$second]['group_leader']) || !$id_cache[$second]['group_leader'])) + { + return -1; + } + else if (isset($id_cache[$second]['group_leader']) && (!isset($id_cache[$first]['group_leader']) || !$id_cache[$first]['group_leader']) && $id_cache[$second]['group_leader']) + { + return 1; + } + else + { + return $lesser_than * (int) ($id_cache[$first]['last_visit'] - $id_cache[$second]['last_visit']); + } +} + ?> \ No newline at end of file diff --git a/phpBB/posting.php b/phpBB/posting.php index 1dd2244656..a3dcc27d44 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -114,7 +114,7 @@ switch ($mode) else { upload_popup(); - exit; + return; } break; @@ -145,7 +145,7 @@ if (!$post_data) if ($mode == 'popup') { upload_popup($post_data['forum_style']); - exit; + return; } $user->setup(array('posting', 'mcp', 'viewtopic'), $post_data['forum_style']); @@ -276,13 +276,14 @@ if ($mode == 'edit' && !$auth->acl_get('m_edit', $forum_id)) if ($mode == 'delete') { handle_post_delete($forum_id, $topic_id, $post_id, $post_data); - exit; + return; } // Handle bump mode... 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'])) + 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']}")) { $db->sql_transaction('begin'); @@ -998,10 +999,9 @@ if ($submit || $preview || $refresh) } $redirect_url = submit_post($mode, $post_data['post_subject'], $post_data['username'], $post_data['topic_type'], $poll, $data, $update_message); - $post_need_approval = (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) ? true : false; - // If the post need approval we will wait a lot longer. - if ($post_need_approval) + // Check the permissions for post approval, as well as the queue trigger where users are put on approval with a post count lower than specified. Moderators are not affected. + if (($config['enable_queue_trigger'] && $user->data['user_posts'] < $config['queue_trigger_posts'] && !$auth->acl_get('m_approve', $data['forum_id'])) || !$auth->acl_get('f_noapprove', $data['forum_id'])) { meta_refresh(10, $redirect_url); $message = ($mode == 'edit') ? $user->lang['POST_EDITED_MOD'] : $user->lang['POST_STORED_MOD']; @@ -1264,7 +1264,7 @@ if ($solved_captcha !== false) ); } -$form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || @ini_get('file_uploads') == '0' || !$config['allow_attachments'] || !$auth->acl_get('u_attach') || !$auth->acl_get('f_attach', $forum_id)) ? '' : ' enctype="multipart/form-data"'; +$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'); @@ -1302,7 +1302,7 @@ $template->assign_vars(array( 'S_EDIT_REASON' => ($mode == 'edit' && $auth->acl_get('m_edit', $forum_id)) ? true : false, 'S_DISPLAY_USERNAME' => (!$user->data['is_registered'] || ($mode == 'edit' && $post_data['poster_id'] == ANONYMOUS)) ? true : false, 'S_SHOW_TOPIC_ICONS' => $s_topic_icons, - 'S_DELETE_ALLOWED' => ($mode == 'edit' && (($post_id == $post_data['topic_last_post_id'] && $post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) || $auth->acl_get('m_delete', $forum_id))) ? true : false, + 'S_DELETE_ALLOWED' => ($mode == 'edit' && (($post_id == $post_data['topic_last_post_id'] && $post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id) && !$post_data['post_edit_locked'] && ($post_data['post_time'] > time() - ($config['edit_time'] * 60) || !$config['edit_time'])) || $auth->acl_get('m_delete', $forum_id))) ? true : false, 'S_BBCODE_ALLOWED' => $bbcode_status, 'S_BBCODE_CHECKED' => ($bbcode_checked) ? ' checked="checked"' : '', 'S_SMILIES_ALLOWED' => $smilies_status, @@ -1354,12 +1354,11 @@ if (($mode == 'post' || ($mode == 'edit' && $post_id == $post_data['topic_first_ ); } +// Show attachment box for adding attachments if true +$allowed = ($auth->acl_get('f_attach', $forum_id) && $auth->acl_get('u_attach') && $config['allow_attachments'] && $form_enctype); + // Attachment entry -// Not using acl_gets here, because it is using OR logic -if ($auth->acl_get('f_attach', $forum_id) && $auth->acl_get('u_attach') && $config['allow_attachments'] && $form_enctype) -{ - posting_gen_attachment_entry($attachment_data, $filename_data); -} +posting_gen_attachment_entry($attachment_data, $filename_data, $allowed); // Output page ... page_header($page_title); @@ -1411,11 +1410,11 @@ function upload_popup($forum_style = 0) */ function handle_post_delete($forum_id, $topic_id, $post_id, &$post_data) { - global $user, $db, $auth; + global $user, $db, $auth, $config; global $phpbb_root_path, $phpEx; // If moderator removing post or user itself removing post, present a confirmation screen - if ($auth->acl_get('m_delete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_delete', $forum_id) && $post_id == $post_data['topic_last_post_id'])) + if ($auth->acl_get('m_delete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_delete', $forum_id) && $post_id == $post_data['topic_last_post_id'] && !$post_data['post_edit_locked'] && ($post_data['post_time'] > time() - ($config['edit_time'] * 60) || !$config['edit_time']))) { $s_hidden_fields = build_hidden_fields(array( 'p' => $post_id, diff --git a/phpBB/search.php b/phpBB/search.php index 5335680c46..965c1a3c4b 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -419,7 +419,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) } else if (sizeof($author_id_ary)) { - $firstpost_only = ($search_fields === 'firstpost') ? true : false; + $firstpost_only = ($search_fields === 'firstpost' || $search_fields == 'titleonly') ? true : false; $total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_id_ary, $id_ary, $start, $per_page); } @@ -476,6 +476,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $u_search = append_sid("{$phpbb_root_path}search.$phpEx", $u_sort_param . $u_show_results); $u_search .= ($search_id) ? '&search_id=' . $search_id : ''; $u_search .= ($u_hilit) ? '&keywords=' . urlencode(htmlspecialchars_decode($search->search_query)) : ''; + $u_search .= ($search_terms != 'all') ? '&terms=' . $search_terms : ''; $u_search .= ($topic_id) ? '&t=' . $topic_id : ''; $u_search .= ($author) ? '&author=' . urlencode(htmlspecialchars_decode($author)) : ''; $u_search .= ($author_id) ? '&author_id=' . $author_id : ''; @@ -542,7 +543,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) if ($user->data['is_registered']) { - if ($config['load_db_track']) + if ($config['load_db_track'] && $author_id !== $user->data['user_id']) { $sql_from .= ' LEFT JOIN ' . TOPICS_POSTED_TABLE . ' tp ON (tp.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tp.topic_id)'; @@ -772,6 +773,11 @@ if ($keywords || $author || $author_id || $search_id || $submit) if ($show_results == 'topics') { + if ($config['load_db_track'] && $author_id === $user->data['user_id']) + { + $row['topic_posted'] = 1; + } + $folder_img = $folder_alt = $topic_type = ''; topic_status($row, $replies, (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]) ? true : false, $folder_img, $folder_alt, $topic_type); @@ -800,6 +806,10 @@ if ($keywords || $author || $author_id || $search_id || $submit) 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), + 'TOPIC_FOLDER_IMG_ALT' => $user->lang[$folder_alt], + 'TOPIC_FOLDER_IMG_WIDTH'=> $user->img($folder_img, '', false, '', 'width'), + 'TOPIC_FOLDER_IMG_HEIGHT' => $user->img($folder_img, '', false, '', 'height'), + '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'] : '', @@ -923,7 +933,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) // Search forum $s_forums = ''; -$sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.left_id, f.right_id, f.forum_password, fa.user_id +$sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.left_id, f.right_id, f.forum_password, f.enable_indexing, fa.user_id FROM ' . FORUMS_TABLE . ' f LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id AND fa.session_id = '" . $db->sql_escape($user->session_id) . "') @@ -942,6 +952,12 @@ while ($row = $db->sql_fetchrow($result)) continue; } + if ($row['forum_type'] == FORUM_POST && ($row['left_id'] + 1 == $row['right_id']) && !$row['enable_indexing']) + { + // Postable forum with no subforums and indexing disabled, don't display + continue; + } + if ($row['forum_type'] == FORUM_LINK || ($row['forum_password'] && !$row['user_id'])) { // if this forum is a link or password protected (user has not entered the password yet) then skip to the next branch @@ -1037,7 +1053,7 @@ if (!empty($_EXTRA_URL)) } $template->assign_vars(array( - 'S_SEARCH_ACTION' => "{$phpbb_root_path}search.$phpEx", + 'S_SEARCH_ACTION' => append_sid("{$phpbb_root_path}search.$phpEx", false, true, 0), // We force no ?sid= appending by using 0 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), 'S_CHARACTER_OPTIONS' => $s_characters, 'S_FORUM_OPTIONS' => $s_forums, diff --git a/phpBB/style.php b/phpBB/style.php index cb2bcff115..843c18b88d 100644 --- a/phpBB/style.php +++ b/phpBB/style.php @@ -27,7 +27,7 @@ if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type)) if (version_compare(PHP_VERSION, '6.0.0-dev', '<')) { - set_magic_quotes_runtime(0); + @set_magic_quotes_runtime(0); } // Load Extensions @@ -62,6 +62,7 @@ if ($id) require($phpbb_root_path . 'includes/cache.' . $phpEx); require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); + require($phpbb_root_path . 'includes/functions.' . $phpEx); $db = new $sql_db(); $cache = new cache(); diff --git a/phpBB/styles/prosilver/imageset/imageset.cfg b/phpBB/styles/prosilver/imageset/imageset.cfg index 4635a8bcef..3e1ea21dce 100644 --- a/phpBB/styles/prosilver/imageset/imageset.cfg +++ b/phpBB/styles/prosilver/imageset/imageset.cfg @@ -19,7 +19,7 @@ # General Information about this style name = prosilver copyright = © phpBB Group, 2007 -version = 3.0.2 +version = 3.0.3 # Images img_site_logo = site_logo.gif*52*139 diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 988dee1650..faf4401c3d 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -19,4 +19,4 @@ # General Information about this style name = prosilver copyright = © phpBB Group, 2007 -version = 3.0.2 \ No newline at end of file +version = 3.0.3 \ No newline at end of file diff --git a/phpBB/styles/prosilver/template/faq_body.html b/phpBB/styles/prosilver/template/faq_body.html index aec578985e..78c2fc11b7 100644 --- a/phpBB/styles/prosilver/template/faq_body.html +++ b/phpBB/styles/prosilver/template/faq_body.html @@ -16,7 +16,7 @@

    {faq_block.BLOCK_TITLE}
    -
    {faq_block.faq_row.FAQ_QUESTION}
    +
    {faq_block.faq_row.FAQ_QUESTION}
    @@ -36,7 +36,7 @@

    {faq_block.BLOCK_TITLE}

    -
    {faq_block.faq_row.FAQ_QUESTION}
    +
    {faq_block.faq_row.FAQ_QUESTION}
    {faq_block.faq_row.FAQ_ANSWER}
    {L_BACK_TO_TOP}
    diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index 29b75240c1..8ed80883e9 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -42,7 +42,7 @@
    {forumrow.POSTS} {L_POSTS}
    {L_LAST_POST} {L_POST_BY_AUTHOR} {forumrow.LAST_POSTER_FULL} - {LAST_POST_IMG}
    {L_POSTED_ON_DATE} {forumrow.LAST_POST_TIME}{L_NO_POSTS}
    + {LAST_POST_IMG}
    {L_POSTED_ON_DATE} {forumrow.LAST_POST_TIME}{L_NO_POSTS}
    diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html index ceb10f4b76..abca202c73 100644 --- a/phpBB/styles/prosilver/template/mcp_forum.html +++ b/phpBB/styles/prosilver/template/mcp_forum.html @@ -26,7 +26,7 @@
    {L_TOPICS}
    {L_REPLIES}
    {L_LAST_POST}
    -
    {L_MARK}
    +
    {L_MARK}
    @@ -47,9 +47,11 @@
    {topicrow.REPLIES} {L_REPLIES}
    {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} {L_POSTED_ON_DATE}
    {topicrow.LAST_POST_TIME}
    +
    checked="checked" /> 
    + @@ -83,6 +85,7 @@
    + + {S_FORM_TOKEN}
    diff --git a/phpBB/styles/prosilver/template/mcp_front.html b/phpBB/styles/prosilver/template/mcp_front.html index a186d95970..484179e2ac 100644 --- a/phpBB/styles/prosilver/template/mcp_front.html +++ b/phpBB/styles/prosilver/template/mcp_front.html @@ -29,7 +29,7 @@
    {unapproved.SUBJECT} {unapproved.ATTACH_ICON_IMG}
    {report.PAGINATION} - {L_POSTED} {L_POST_BY_AUTHOR} {unapproved.AUTHOR}{unapproved.AUTHOR} {L_POSTED_ON_DATE} {unapproved.POST_TIME} + {L_POSTED} {L_POST_BY_AUTHOR} {unapproved.AUTHOR_FULL} {L_POSTED_ON_DATE} {unapproved.POST_TIME}
    {L_TOPIC}: {unapproved.TOPIC_TITLE} [{L_MODERATE}]
    diff --git a/phpBB/styles/prosilver/template/mcp_header.html b/phpBB/styles/prosilver/template/mcp_header.html index 9af0f4c4e6..13cc7e12cf 100644 --- a/phpBB/styles/prosilver/template/mcp_header.html +++ b/phpBB/styles/prosilver/template/mcp_header.html @@ -45,7 +45,7 @@

    {L_MESSAGE}

    -

    {MESSAGE}

    +

    {MESSAGE}

    {return_links.MESSAGE_LINK}

    diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html index b4706ec9ac..c8b2ffc56d 100644 --- a/phpBB/styles/prosilver/template/mcp_post.html +++ b/phpBB/styles/prosilver/template/mcp_post.html @@ -50,7 +50,7 @@ -

    {POST_SUBJECT}

    +

    {POST_SUBJECT}

    {MINI_POST_IMG} {L_POSTED} {L_POST_BY_AUTHOR} {POST_AUTHOR_FULL} {L_POSTED_ON_DATE} {POST_DATE}

    @@ -152,7 +152,7 @@
    -

    {RETURN_QUEUE} | {RETURN_TOPIC_SIMPLE} | {RETURN_POST}{RETURN_REPORTS} | {L_VIEW_TOPIC}{RETURN_TOPIC}

    +

    {RETURN_QUEUE} | {RETURN_TOPIC_SIMPLE} | {RETURN_POST}{RETURN_REPORTS} | {L_VIEW_POST} | {L_VIEW_TOPIC} | {L_VIEW_FORUM}{RETURN_TOPIC}

    diff --git a/phpBB/styles/prosilver/template/mcp_warn_post.html b/phpBB/styles/prosilver/template/mcp_warn_post.html index 5937598a52..d09209f5a4 100644 --- a/phpBB/styles/prosilver/template/mcp_warn_post.html +++ b/phpBB/styles/prosilver/template/mcp_warn_post.html @@ -52,11 +52,13 @@
    +

     
    +
    diff --git a/phpBB/styles/prosilver/template/mcp_warn_user.html b/phpBB/styles/prosilver/template/mcp_warn_user.html index c807a6b640..5b5156f3a1 100644 --- a/phpBB/styles/prosilver/template/mcp_warn_user.html +++ b/phpBB/styles/prosilver/template/mcp_warn_user.html @@ -36,11 +36,13 @@
    +

     
    +
    diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html index 6846432b2e..007f29a64b 100644 --- a/phpBB/styles/prosilver/template/memberlist_body.html +++ b/phpBB/styles/prosilver/template/memberlist_body.html @@ -72,14 +72,14 @@ - +
    ' . (($val) ? ucwords(str_replace('_', ' ', $val)) : ' ') . '' . (($val) ? $val : ' ') . '
    - + @@ -87,6 +87,9 @@ + + + @@ -95,23 +98,32 @@ +
    {L_RANK}{L_GROUP_LEADER}{L_USERNAME}{L_RANK}{L_GROUP_LEADER}{L_USERNAME} {L_POSTS} {L_WEBSITE}{L_COMMA_SEPARATOR}{L_LOCATION} {L_JOINED}
     
    - +

    + + + + + + + + @@ -171,4 +183,4 @@ - + \ No newline at end of file diff --git a/phpBB/styles/prosilver/template/memberlist_leaders.html b/phpBB/styles/prosilver/template/memberlist_leaders.html index 88b4510a71..3917498050 100644 --- a/phpBB/styles/prosilver/template/memberlist_leaders.html +++ b/phpBB/styles/prosilver/template/memberlist_leaders.html @@ -28,7 +28,7 @@ - + @@ -61,7 +61,7 @@ - + diff --git a/phpBB/styles/prosilver/template/memberlist_view.html b/phpBB/styles/prosilver/template/memberlist_view.html index 7df3eb6a91..23f87d6bbe 100644 --- a/phpBB/styles/prosilver/template/memberlist_view.html +++ b/phpBB/styles/prosilver/template/memberlist_view.html @@ -5,7 +5,7 @@
    - +
    {AVATAR_IMG}
    @@ -55,7 +55,7 @@

    {L_CONTACT_USER} {USERNAME}

    - +
    {L_EMAIL_ADDRESS}:
    {L_SEND_EMAIL_USER} {USERNAME}
    {L_WEBSITE}:
    {U_WWW}
    @@ -82,7 +82,11 @@
    {L_WARNINGS}:
    {WARNINGS} [ {L_VIEW_NOTES} | {L_WARN_USER} ]
    -
    {L_TOTAL_POSTS}:
    {POSTS} | {L_SEARCH_USER_POSTS}
    ({POSTS_PCT} / {POSTS_DAY})
    +
    {L_TOTAL_POSTS}:
    +
    {POSTS} | {L_SEARCH_USER_POSTS} +
    ({POSTS_PCT} / {POSTS_DAY}) +
    ({L_POSTS_IN_QUEUE})
    ({L_POSTS_IN_QUEUE}) +
    {L_ACTIVE_IN_FORUM}:
    {ACTIVE_FORUM}
    ({ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT}) -
    {L_ACTIVE_IN_TOPIC}:
    {ACTIVE_TOPIC}
    ({ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT}) -
    diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 4abe2bb2a4..fd8af31db6 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -13,7 +13,7 @@
  • {L_BOOKMARK_TOPIC}
  • {L_BUMP_TOPIC}
  • -
  • {L_THE_TEAM}{L_DELETE_COOKIES}{S_TIMEZONE}
  • +
  • {L_THE_TEAM}{L_DELETE_COOKIES}{S_TIMEZONE}
  • diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index c0cb7640eb..21d536d4b3 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -32,6 +32,7 @@ var per_page = '{PER_PAGE}'; var base_url = '{A_BASE_URL}'; var style_cookie = 'phpBBstyle'; + var style_cookie_settings = '{A_COOKIE_SETTINGS}'; var onload_functions = new Array(); var onunload_functions = new Array(); diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index 3924fa3944..9159b126f1 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -66,7 +66,7 @@
    {searchresults.TOPIC_VIEWS}
    {L_POST_BY_AUTHOR} {searchresults.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG}
    {L_POSTED_ON_DATE} {searchresults.LAST_POST_TIME}
    + {LAST_POST_IMG}
    {L_POSTED_ON_DATE} {searchresults.LAST_POST_TIME}
    diff --git a/phpBB/styles/prosilver/template/styleswitcher.js b/phpBB/styles/prosilver/template/styleswitcher.js index c68215d13f..203d8e4c21 100644 --- a/phpBB/styles/prosilver/template/styleswitcher.js +++ b/phpBB/styles/prosilver/template/styleswitcher.js @@ -112,7 +112,7 @@ function createCookie(name, value, days) expires = ''; } - document.cookie = name + '=' + value + expires + '; path=/'; + document.cookie = name + '=' + value + expires + style_cookie_settings; } function readCookie(name) diff --git a/phpBB/styles/prosilver/template/template.cfg b/phpBB/styles/prosilver/template/template.cfg index dbf3a29077..ebfc3f0d6b 100644 --- a/phpBB/styles/prosilver/template/template.cfg +++ b/phpBB/styles/prosilver/template/template.cfg @@ -19,7 +19,7 @@ # General Information about this template name = prosilver copyright = © phpBB Group, 2007 -version = 3.0.2 +version = 3.0.3 # Defining a different template bitfield template_bitfield = lNg= diff --git a/phpBB/styles/prosilver/template/ucp_groups_manage.html b/phpBB/styles/prosilver/template/ucp_groups_manage.html index b64a3f63ea..47a8acb13a 100644 --- a/phpBB/styles/prosilver/template/ucp_groups_manage.html +++ b/phpBB/styles/prosilver/template/ucp_groups_manage.html @@ -1,6 +1,6 @@ -

    {L_USERGROUPS}

    + style="color:#{GROUP_COLOR};">{L_USERGROUPS} :: {GROUP_NAME} @@ -79,6 +79,7 @@ +
    {L_RANK}{L_GROUP_MEMBERS}{L_USERNAME}{L_POSTS}{L_WEBSITE}{L_COMMA_SEPARATOR}{L_LOCATION}{L_JOINED}{L_LAST_ACTIVE} {L_GROUP_MEMBERS}        
    {L_NO_MEMBERS}{L_NO_ADMINISTRATORS}
    {L_NO_MEMBERS}{L_NO_MODERATORS}
    @@ -101,23 +102,10 @@
    + - - - - - - - - - - - - -
    {L_GROUP_APPROVED}{L_GROUP_DEFAULT}{L_POSTS}{L_JOINED}{L_MARK}
    - @@ -128,7 +116,23 @@ - + + + + +
    {L_MARK}
    + + + + + + + + + + + + diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html index b146619f75..582ee37459 100644 --- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html +++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html @@ -23,8 +23,7 @@
  • {forumrow.FORUM_NAME}
    - {L_LAST_POST} {L_POST_BY_AUTHOR} {forumrow.LAST_POST_AUTHOR} - {forumrow.LAST_POST_AUTHOR} {LAST_POST_IMG} {L_POSTED_ON_DATE} {forumrow.LAST_POST_TIME} + {L_LAST_POST} {forumrow.LAST_POST_AUTHOR_FULL} {LAST_POST_IMG} {L_POSTED_ON_DATE} {forumrow.LAST_POST_TIME} {L_NO_POSTS}
    @@ -81,7 +80,7 @@
    - + {S_FORM_TOKEN}
    diff --git a/phpBB/styles/prosilver/template/ucp_pm_history.html b/phpBB/styles/prosilver/template/ucp_pm_history.html index 5f2994f145..29e3a75c05 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_history.html +++ b/phpBB/styles/prosilver/template/ucp_pm_history.html @@ -10,18 +10,17 @@
    - +

    class="current">{history_row.SUBJECT}

    {history_row.MINI_POST_IMG} {L_SENT_AT}: {history_row.SENT_DATE}
    {L_MESSAGE_BY_AUTHOR} {history_row.MESSAGE_AUTHOR_FULL}

    -
    - {history_row.MESSAGE} -
    +
    {history_row.MESSAGE}
    +
    diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html index 4c244782d8..535641f33b 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html @@ -71,16 +71,16 @@
    {L_JOINED}: {AUTHOR_JOINED}
    {L_LOCATION}: {AUTHOR_FROM}
    - +
    diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 056afb0548..b3f81df865 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -147,7 +147,7 @@
    {topicrow.REPLIES} {L_REPLIES}
    {topicrow.VIEWS} {L_VIEWS}
    {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG}
    {L_POSTED_ON_DATE} {topicrow.LAST_POST_TIME}
    + {LAST_POST_IMG}
    {L_POSTED_ON_DATE} {topicrow.LAST_POST_TIME}
  • @@ -173,9 +173,11 @@
    {L_PREVIOUS} {L_NEXT} + +

    @@ -204,7 +206,7 @@ -

    {L_WHO_IS_ONLINE}

    +

    {L_WHO_IS_ONLINE}{L_WHO_IS_ONLINE}

    {LOGGED_IN_USER_LIST}

    diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index ee89b3b15f..d949ba55e3 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -196,7 +196,7 @@ - +
    • {L_PRIVATE_MESSAGE}
    • @@ -229,8 +229,10 @@
      {L_PREVIOUS} {L_NEXT} + +
      @@ -264,7 +266,7 @@ -

      {L_WHO_IS_ONLINE}

      +

      {L_WHO_IS_ONLINE}{L_WHO_IS_ONLINE}

      {LOGGED_IN_USER_LIST}

      diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 936b53f78a..00342604bb 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -385,6 +385,15 @@ dd .signature { border: none; } +.signature li { + list-style-type: inherit; +} + +.signature ul, .signature ol { + margin-bottom: 1em; + margin-left: 3em; +} + /* Post noticies */ .notice { font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif; diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index 4c4ccd31a9..9f3b7e3ae7 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -10,6 +10,7 @@ a:active { color: #d2d2d2; text-decoration: none; } .username-coloured { font-weight: bold; display: inline !important; + padding: 0 !important; } /* Links on gradient backgrounds */ diff --git a/phpBB/styles/prosilver/theme/theme.cfg b/phpBB/styles/prosilver/theme/theme.cfg index 070d356aa5..efed06babb 100644 --- a/phpBB/styles/prosilver/theme/theme.cfg +++ b/phpBB/styles/prosilver/theme/theme.cfg @@ -21,7 +21,7 @@ # General Information about this theme name = prosilver copyright = © phpBB Group, 2007 -version = 3.0.2 +version = 3.0.3 # Some configuration options diff --git a/phpBB/styles/subsilver2/imageset/imageset.cfg b/phpBB/styles/subsilver2/imageset/imageset.cfg index 11800f5fb7..16aced113d 100644 --- a/phpBB/styles/subsilver2/imageset/imageset.cfg +++ b/phpBB/styles/subsilver2/imageset/imageset.cfg @@ -19,7 +19,7 @@ # General Information about this style name = subsilver2 copyright = © phpBB Group, 2003 -version = 3.0.2 +version = 3.0.3 # Images img_site_logo = site_logo.gif*94*170 diff --git a/phpBB/styles/subsilver2/style.cfg b/phpBB/styles/subsilver2/style.cfg index 6451ea13db..c9a93c15de 100644 --- a/phpBB/styles/subsilver2/style.cfg +++ b/phpBB/styles/subsilver2/style.cfg @@ -19,4 +19,4 @@ # General Information about this style name = subsilver2 copyright = © 2005 phpBB Group -version = 3.0.2 +version = 3.0.3 diff --git a/phpBB/styles/subsilver2/template/faq_body.html b/phpBB/styles/subsilver2/template/faq_body.html index 9e324b4fd2..bbd9b82b19 100644 --- a/phpBB/styles/subsilver2/template/faq_body.html +++ b/phpBB/styles/subsilver2/template/faq_body.html @@ -13,7 +13,7 @@ {faq_block.BLOCK_TITLE}
      - {faq_block.faq_row.FAQ_QUESTION}
      + {faq_block.faq_row.FAQ_QUESTION}

      @@ -38,7 +38,7 @@
    diff --git a/phpBB/styles/subsilver2/template/forumlist_body.html b/phpBB/styles/subsilver2/template/forumlist_body.html index 70e4ca813f..368610ebe1 100644 --- a/phpBB/styles/subsilver2/template/forumlist_body.html +++ b/phpBB/styles/subsilver2/template/forumlist_body.html @@ -60,7 +60,7 @@

    {forumrow.LAST_POST_TIME}

    {forumrow.LAST_POSTER_FULL} - {LAST_POST_IMG} + {LAST_POST_IMG}

    {L_NO_POSTS}

    diff --git a/phpBB/styles/subsilver2/template/index_body.html b/phpBB/styles/subsilver2/template/index_body.html index 3958743229..bf523dc3f2 100644 --- a/phpBB/styles/subsilver2/template/index_body.html +++ b/phpBB/styles/subsilver2/template/index_body.html @@ -10,7 +10,9 @@ -{L_DELETE_COOKIES} | {L_THE_TEAM}
    + +{L_DELETE_COOKIES} | {L_THE_TEAM}
    +
    diff --git a/phpBB/styles/subsilver2/template/mcp_ban.html b/phpBB/styles/subsilver2/template/mcp_ban.html index 04f90530c9..0e352b57dd 100644 --- a/phpBB/styles/subsilver2/template/mcp_ban.html +++ b/phpBB/styles/subsilver2/template/mcp_ban.html @@ -88,11 +88,11 @@ - + - + diff --git a/phpBB/styles/subsilver2/template/mcp_forum.html b/phpBB/styles/subsilver2/template/mcp_forum.html index 956d253aa6..80a6047858 100644 --- a/phpBB/styles/subsilver2/template/mcp_forum.html +++ b/phpBB/styles/subsilver2/template/mcp_forum.html @@ -44,7 +44,7 @@ @@ -52,6 +52,7 @@ + +
    {L_GROUP_APPROVED}{L_GROUP_DEFAULT}{L_POSTS}{L_JOINED}{L_MARK}
    {member.USERNAME_FULL} -
    » {faq_block.faq_row.FAQ_QUESTION}
    +
    » {faq_block.faq_row.FAQ_QUESTION}
    {faq_block.faq_row.FAQ_ANSWER}

    {L_BACK_TO_TOP}

    {L_BAN_REASON}:
    {L_BAN_GIVE_REASON}:
       

    {topicrow.REPLIES}

    {topicrow.LAST_POST_TIME}

    - checked="checked" />  + checked="checked" /> 

    {L_NO_TOPICS}

    {S_FORM_TOKEN} +
    {L_MARK_ALL} :: {L_UNMARK_ALL}
    + \ No newline at end of file diff --git a/phpBB/styles/subsilver2/template/mcp_front.html b/phpBB/styles/subsilver2/template/mcp_front.html index 122f5283ae..029ba3cb3c 100644 --- a/phpBB/styles/subsilver2/template/mcp_front.html +++ b/phpBB/styles/subsilver2/template/mcp_front.html @@ -20,7 +20,7 @@ {unapproved.FORUM_NAME}{unapproved.FORUM_NAME}
    [ {L_MODERATE} ] {unapproved.TOPIC_TITLE}
    [ {L_MODERATE} ] {unapproved.SUBJECT}
    [ {L_VIEW_DETAILS} ] - {unapproved.AUTHOR}{unapproved.AUTHOR} + {unapproved.AUTHOR_FULL} {unapproved.POST_TIME} diff --git a/phpBB/styles/subsilver2/template/mcp_post.html b/phpBB/styles/subsilver2/template/mcp_post.html index 402f25a655..6260c79d7d 100644 --- a/phpBB/styles/subsilver2/template/mcp_post.html +++ b/phpBB/styles/subsilver2/template/mcp_post.html @@ -46,7 +46,7 @@ {L_POST_DETAILS} - {RETURN_QUEUE} | {RETURN_TOPIC_SIMPLE} | {RETURN_POST}{RETURN_REPORTS} | {L_VIEW_TOPIC}{RETURN_TOPIC} + {RETURN_QUEUE} | {RETURN_TOPIC_SIMPLE} | {RETURN_POST}{RETURN_REPORTS} | {L_VIEW_POST} | {L_VIEW_TOPIC} | {L_VIEW_FORUM}{RETURN_TOPIC} {L_POST_SUBJECT}: diff --git a/phpBB/styles/subsilver2/template/mcp_warn_post.html b/phpBB/styles/subsilver2/template/mcp_warn_post.html index 1ad5757f15..ef0595e48e 100644 --- a/phpBB/styles/subsilver2/template/mcp_warn_post.html +++ b/phpBB/styles/subsilver2/template/mcp_warn_post.html @@ -45,9 +45,11 @@ + {L_NOTIFY_USER_WARN} +    diff --git a/phpBB/styles/subsilver2/template/mcp_warn_user.html b/phpBB/styles/subsilver2/template/mcp_warn_user.html index 5e8c350935..bb77c91654 100644 --- a/phpBB/styles/subsilver2/template/mcp_warn_user.html +++ b/phpBB/styles/subsilver2/template/mcp_warn_user.html @@ -58,9 +58,11 @@ + {L_NOTIFY_USER_WARN} +    diff --git a/phpBB/styles/subsilver2/template/memberlist_view.html b/phpBB/styles/subsilver2/template/memberlist_view.html index cb7346dacf..c4536e4621 100644 --- a/phpBB/styles/subsilver2/template/memberlist_view.html +++ b/phpBB/styles/subsilver2/template/memberlist_view.html @@ -22,7 +22,7 @@ - {USERNAME} [ {L_USER_ADMIN} ] + {USERNAME} [ {L_USER_BAN} ] [ {L_USER_ADMIN} ] @@ -74,7 +74,9 @@ {L_TOTAL_POSTS}: - {POSTS}
    [{POSTS_PCT} / {POSTS_DAY}]
    {L_SEARCH_USER_POSTS}
    + {POSTS}
    [{POSTS_PCT} / {POSTS_DAY}] +
    [{L_POSTS_IN_QUEUE}]
    [{L_POSTS_IN_QUEUE}] +
    {L_SEARCH_USER_POSTS}
    diff --git a/phpBB/styles/subsilver2/template/template.cfg b/phpBB/styles/subsilver2/template/template.cfg index c1f549eac2..47099947fc 100644 --- a/phpBB/styles/subsilver2/template/template.cfg +++ b/phpBB/styles/subsilver2/template/template.cfg @@ -19,5 +19,5 @@ # General Information about this template name = subsilver2 copyright = © phpBB Group, 2003 -version = 3.0.2 +version = 3.0.3 diff --git a/phpBB/styles/subsilver2/template/ucp_groups_manage.html b/phpBB/styles/subsilver2/template/ucp_groups_manage.html index 4a3296d153..6ae9816ca8 100644 --- a/phpBB/styles/subsilver2/template/ucp_groups_manage.html +++ b/phpBB/styles/subsilver2/template/ucp_groups_manage.html @@ -151,14 +151,16 @@ - - {L_GROUP_APPROVED} - + {L_GROUP_PENDING} + + + {L_GROUP_APPROVED} + {member.USERNAME_FULL} diff --git a/phpBB/styles/subsilver2/template/ucp_main_subscribed.html b/phpBB/styles/subsilver2/template/ucp_main_subscribed.html index 844a90f3e6..9335d01f12 100644 --- a/phpBB/styles/subsilver2/template/ucp_main_subscribed.html +++ b/phpBB/styles/subsilver2/template/ucp_main_subscribed.html @@ -78,7 +78,7 @@ - + \ No newline at end of file diff --git a/phpBB/styles/subsilver2/template/ucp_pm_history.html b/phpBB/styles/subsilver2/template/ucp_pm_history.html index 9e05368340..cb87d1892a 100644 --- a/phpBB/styles/subsilver2/template/ucp_pm_history.html +++ b/phpBB/styles/subsilver2/template/ucp_pm_history.html @@ -32,7 +32,7 @@ - +
    {history_row.MESSAGE}
    {history_row.MESSAGE}
    @@ -54,7 +54,7 @@ {L_VIEW_PM} - + diff --git a/phpBB/styles/subsilver2/template/viewforum_body.html b/phpBB/styles/subsilver2/template/viewforum_body.html index c196bc60a0..c4375b6415 100644 --- a/phpBB/styles/subsilver2/template/viewforum_body.html +++ b/phpBB/styles/subsilver2/template/viewforum_body.html @@ -58,7 +58,7 @@

    {topicrow.LAST_POST_TIME}

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} + {LAST_POST_IMG}

    @@ -209,7 +209,7 @@

    {topicrow.LAST_POST_TIME}

    {topicrow.LAST_POST_AUTHOR_FULL} - {LAST_POST_IMG} + {LAST_POST_IMG}

    @@ -226,6 +226,7 @@ + @@ -235,6 +236,7 @@
    {L_DISPLAY_TOPICS}: {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    + diff --git a/phpBB/styles/subsilver2/template/viewtopic_body.html b/phpBB/styles/subsilver2/template/viewtopic_body.html index cf264ca4f8..b177a15250 100644 --- a/phpBB/styles/subsilver2/template/viewtopic_body.html +++ b/phpBB/styles/subsilver2/template/viewtopic_body.html @@ -290,11 +290,13 @@ +
    {L_DISPLAY_POSTS}: {S_SELECT_SORT_DAYS} {L_SORT_BY} {S_SELECT_SORT_KEY} {S_SELECT_SORT_DIR} 
    + diff --git a/phpBB/styles/subsilver2/theme/theme.cfg b/phpBB/styles/subsilver2/theme/theme.cfg index 96a68258cb..7d5bdd0615 100644 --- a/phpBB/styles/subsilver2/theme/theme.cfg +++ b/phpBB/styles/subsilver2/theme/theme.cfg @@ -21,7 +21,7 @@ # General Information about this theme name = subsilver2 copyright = © phpBB Group, 2003 -version = 3.0.2 +version = 3.0.3 # Some configuration options diff --git a/phpBB/ucp.php b/phpBB/ucp.php index 2b236c29c5..908d4fb89a 100644 --- a/phpBB/ucp.php +++ b/phpBB/ucp.php @@ -36,6 +36,7 @@ $user->setup('ucp'); $template->assign_var('S_IN_UCP', true); $module = new p_master(); +$default = false; // Basic "global" modes switch ($mode) @@ -69,7 +70,6 @@ switch ($mode) case 'confirm': $module->load('ucp', 'confirm'); - exit; break; case 'login': @@ -233,6 +233,16 @@ switch ($mode) trigger_error($message); break; + + default: + $default = true; + break; +} + +// We use this approach because it does not impose large code changes +if (!$default) +{ + return true; } // Only registered users can go beyond this point diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 12a6d940d1..14564ad38c 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -26,9 +26,13 @@ $forum_id = request_var('f', 0); $mark_read = request_var('mark', ''); $start = request_var('start', 0); -$sort_days = request_var('st', ((!empty($user->data['user_topic_show_days'])) ? $user->data['user_topic_show_days'] : 0)); -$sort_key = request_var('sk', ((!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't')); -$sort_dir = request_var('sd', ((!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd')); +$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); // Check if the user has actually sent a forum ID with his/her request // If not give them a nice error page. @@ -109,7 +113,7 @@ if ($forum_data['forum_type'] == FORUM_LINK && $forum_data['forum_link']) // We redirect to the url. The third parameter indicates that external redirects are allowed. redirect($forum_data['forum_link'], false, true); - exit; + return; } // Build navigation links @@ -169,8 +173,11 @@ if (!$auth->acl_get('f_read', $forum_id)) // Handle marking posts if ($mark_read == 'topics') { - markread('topics', $forum_id); - + $token = request_var('hash', ''); + if (check_link_hash($token, 'global')) + { + markread('topics', $forum_id); + } $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); meta_refresh(3, $redirect_url); @@ -196,7 +203,7 @@ $s_watching_forum = array( 'is_watching' => false, ); -if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'] && $auth->acl_get('f_subscribe', $forum_id)) +if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'] && $forum_data['forum_type'] == FORUM_POST && $auth->acl_get('f_subscribe', $forum_id)) { $notify_status = (isset($forum_data['notify_status'])) ? $forum_data['notify_status'] : NULL; watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0, $notify_status); @@ -212,7 +219,7 @@ $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIM $sort_by_sql = array('a' => 't.topic_first_poster_name', 't' => 't.topic_last_post_time', 'r' => 't.topic_replies', 's' => 't.topic_title', 'v' => 't.topic_views'); $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); +gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir); // Limit topics to certain time frame, obtain correct topic count // global announcements must not be counted, normal announcements have to @@ -302,8 +309,8 @@ $template->assign_vars(array( 'U_MCP' => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", true, $user->session_id) : '', 'U_POST_NEW_TOPIC' => ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=post&f=' . $forum_id) : '', - 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id&$u_sort_param&start=$start"), - 'U_MARK_TOPICS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id&mark=topics") : '', + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '') . "&start=$start"), + 'U_MARK_TOPICS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . "&f=$forum_id&mark=topics") : '', )); // Grab icons @@ -501,6 +508,9 @@ if (sizeof($shadow_topic_list)) 'topic_type' => $rowset[$orig_topic_id]['topic_type'], )); + // Shadow topics are never reported + $row['topic_reported'] = 0; + $rowset[$orig_topic_id] = $row; } $db->sql_freeresult($result); @@ -514,7 +524,7 @@ if ($s_display_active) } $template->assign_vars(array( - 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id&$u_sort_param"), $topics_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '')), $topics_count, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($topics_count, $config['topics_per_page'], $start), 'TOTAL_TOPICS' => ($s_display_active) ? false : (($topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $topics_count))) ); @@ -632,6 +642,9 @@ if (sizeof($topic_list)) 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), 'TOPIC_FOLDER_IMG_ALT' => $user->lang[$folder_alt], + 'TOPIC_FOLDER_IMG_WIDTH'=> $user->img($folder_img, '', false, '', 'width'), + 'TOPIC_FOLDER_IMG_HEIGHT' => $user->img($folder_img, '', false, '', 'height'), + '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'] : '', diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index fba2bca69a..6ac50322ab 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -305,7 +305,7 @@ while ($row = $db->sql_fetchrow($result)) $location_url = append_sid("{$phpbb_root_path}index.$phpEx"); break; - case 'download': + case 'download/file': $location = $user->lang['DOWNLOADING_FILE']; $location_url = append_sid("{$phpbb_root_path}index.$phpEx"); break; diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 0fafefad1e..3241c9c21a 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -31,9 +31,13 @@ $voted_id = request_var('vote_id', array('' => 0)); $start = request_var('start', 0); $view = request_var('view', ''); -$sort_days = request_var('st', ((!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0)); -$sort_key = request_var('sk', ((!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't')); -$sort_dir = request_var('sd', ((!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a')); +$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); $update = request_var('update', false); @@ -174,11 +178,18 @@ if ($view && !$post_id) $sql_array = array( 'SELECT' => 't.*, f.*', - 'FROM' => array( - FORUMS_TABLE => 'f', - ) + 'FROM' => array(FORUMS_TABLE => 'f'), ); +// The FROM-Order is quite important here, else t.* columns can not be correctly bound. +if ($post_id) +{ + $sql_array['FROM'][POSTS_TABLE] = 'p'; +} + +// Topics table need to be the last in the chain +$sql_array['FROM'][TOPICS_TABLE] = 't'; + if ($user->data['is_registered']) { $sql_array['SELECT'] .= ', tw.notify_status'; @@ -221,7 +232,6 @@ if (!$post_id) else { $sql_array['WHERE'] = "p.post_id = $post_id AND t.topic_id = p.topic_id" . ((!$auth->acl_get('m_approve', $forum_id)) ? ' AND p.post_approved = 1' : ''); - $sql_array['FROM'][POSTS_TABLE] = 'p'; } $sql_array['WHERE'] .= ' AND (f.forum_id = t.forum_id'; @@ -239,7 +249,6 @@ else } $sql_array['WHERE'] .= ')'; -$sql_array['FROM'][TOPICS_TABLE] = 't'; // Join to forum table on topic forum_id unless topic forum_id is zero // whereupon we join on the forum_id passed as a parameter ... this @@ -388,7 +397,8 @@ $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIM $sort_by_sql = array('a' => 'u.username_clean', 't' => 'p.post_time', 's' => 'p.post_subject'); $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); + +gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir); // Obtain correct post count and ordering SQL if user has // requested anything different @@ -436,13 +446,13 @@ if ($hilit_words) } // Make sure $start is set to the last page if it exceeds the amount -if ($start < 0 || $start > $total_posts) +if ($start < 0 || $start >= $total_posts) { $start = ($start < 0) ? 0 : floor(($total_posts - 1) / $config['posts_per_page']) * $config['posts_per_page']; } // General Viewtopic URL for return links -$viewtopic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&start=$start&$u_sort_param" . (($highlight_match) ? "&hilit=$highlight" : '')); +$viewtopic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&start=$start" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '') . (($highlight_match) ? "&hilit=$highlight" : '')); // Are we watching this topic? $s_watching_topic = array( @@ -466,25 +476,31 @@ if (($config['email_enable'] || $config['jab_enable']) && $config['allow_topic_n // Bookmarks if ($config['allow_bookmarks'] && $user->data['is_registered'] && request_var('bookmark', 0)) { - if (!$topic_data['bookmarked']) + if (check_link_hash(request_var('hash', ''), "topic_$topic_id")) { - $sql = 'INSERT INTO ' . BOOKMARKS_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'user_id' => $user->data['user_id'], - 'topic_id' => $topic_id, - )); - $db->sql_query($sql); + if (!$topic_data['bookmarked']) + { + $sql = 'INSERT INTO ' . BOOKMARKS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => $user->data['user_id'], + 'topic_id' => $topic_id, + )); + $db->sql_query($sql); + } + else + { + $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND topic_id = $topic_id"; + $db->sql_query($sql); + } + $message = (($topic_data['bookmarked']) ? $user->lang['BOOKMARK_REMOVED'] : $user->lang['BOOKMARK_ADDED']) . '

    ' . sprintf($user->lang['RETURN_TOPIC'], '', ''); } else { - $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . " - WHERE user_id = {$user->data['user_id']} - AND topic_id = $topic_id"; - $db->sql_query($sql); + $message = $user->lang['BOOKMARK_ERR'] . '

    ' . sprintf($user->lang['RETURN_TOPIC'], '', ''); } - meta_refresh(3, $viewtopic_url); - $message = (($topic_data['bookmarked']) ? $user->lang['BOOKMARK_REMOVED'] : $user->lang['BOOKMARK_ADDED']) . '

    ' . sprintf($user->lang['RETURN_TOPIC'], '', ''); trigger_error($message); } @@ -523,7 +539,7 @@ $topic_mod .= ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_mod .= ($auth->acl_get('m_', $forum_id)) ? '' : ''; // If we've got a hightlight set pass it on to pagination. -$pagination = generate_pagination(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&$u_sort_param" . (($highlight_match) ? "&hilit=$highlight" : '')), $total_posts, $config['posts_per_page'], $start); +$pagination = generate_pagination(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '') . (($highlight_match) ? "&hilit=$highlight" : '')), $total_posts, $config['posts_per_page'], $start); // Navigation links generate_forum_nav($topic_data); @@ -557,7 +573,7 @@ $template->assign_vars(array( 'PAGINATION' => $pagination, 'PAGE_NUMBER' => on_page($total_posts, $config['posts_per_page'], $start), 'TOTAL_POSTS' => ($total_posts == 1) ? $user->lang['VIEW_TOPIC_POST'] : sprintf($user->lang['VIEW_TOPIC_POSTS'], $total_posts), - 'U_MCP' => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&mode=topic_view&f=$forum_id&t=$topic_id&start=$start&$u_sort_param", true, $user->session_id) : '', + 'U_MCP' => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&mode=topic_view&f=$forum_id&t=$topic_id&start=$start" . ((strlen($u_sort_param)) ? "&$u_sort_param" : ''), true, $user->session_id) : '', 'MODERATORS' => (isset($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id])) ? implode(', ', $forum_moderators[$forum_id]) : '', 'POST_IMG' => ($topic_data['forum_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', 'FORUM_LOCKED') : $user->img('button_topic_new', 'POST_NEW_TOPIC'), @@ -610,12 +626,12 @@ $template->assign_vars(array( 'L_WATCH_TOPIC' => $s_watching_topic['title'], 'S_WATCHING_TOPIC' => $s_watching_topic['is_watching'], - 'U_BOOKMARK_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks']) ? $viewtopic_url . '&bookmark=1' : '', + 'U_BOOKMARK_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks']) ? $viewtopic_url . '&bookmark=1&hash=' . generate_link_hash("topic_$topic_id") : '', 'L_BOOKMARK_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'], 'U_POST_NEW_TOPIC' => ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=post&f=$forum_id") : '', 'U_POST_REPLY_TOPIC' => ($auth->acl_get('f_reply', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=reply&f=$forum_id&t=$topic_id") : '', - 'U_BUMP_TOPIC' => (bump_topic_allowed($forum_id, $topic_data['topic_bumped'], $topic_data['topic_last_post_time'], $topic_data['topic_poster'], $topic_data['topic_last_poster_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=bump&f=$forum_id&t=$topic_id") : '') + 'U_BUMP_TOPIC' => (bump_topic_allowed($forum_id, $topic_data['topic_bumped'], $topic_data['topic_last_post_time'], $topic_data['topic_poster'], $topic_data['topic_last_poster_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=bump&f=$forum_id&t=$topic_id&hash=" . generate_link_hash("topic_$topic_id")) : '') ); // Does this topic contain a poll? @@ -803,7 +819,7 @@ if (!empty($topic_data['poll_start'])) foreach ($poll_info as $poll_option) { $option_pct = ($poll_total > 0) ? $poll_option['poll_option_total'] / $poll_total : 0; - $option_pct_txt = sprintf("%.1d%%", ($option_pct * 100)); + $option_pct_txt = sprintf("%.1d%%", round($option_pct * 100)); $template->assign_block_vars('poll_option', array( 'POLL_OPTION_ID' => $poll_option['poll_option_id'], @@ -964,6 +980,7 @@ while ($row = $db->sql_fetchrow($result)) 'post_edit_time' => $row['post_edit_time'], 'post_edit_reason' => $row['post_edit_reason'], 'post_edit_user' => $row['post_edit_user'], + 'post_edit_locked' => $row['post_edit_locked'], // Make sure the icon actually exists 'icon_id' => (isset($icons[$row['icon_id']]['img'], $icons[$row['icon_id']]['height'], $icons[$row['icon_id']]['width'])) ? $row['icon_id'] : 0, @@ -1005,7 +1022,7 @@ while ($row = $db->sql_fetchrow($result)) 'sig_bbcode_bitfield' => '', 'online' => false, - 'avatar' => '', + 'avatar' => ($user->optionget('viewavatars')) ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], $row['user_avatar_width'], $row['user_avatar_height']) : '', 'rank_title' => '', 'rank_image' => '', 'rank_image_src' => '', @@ -1029,6 +1046,8 @@ while ($row = $db->sql_fetchrow($result)) 'warnings' => 0, 'allow_pm' => 0, ); + + get_user_rank($row['user_rank'], $row['user_posts'], $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']); } else { @@ -1072,7 +1091,7 @@ while ($row = $db->sql_fetchrow($result)) 'msn' => ($row['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&action=msnm&u=$poster_id") : '', 'yim' => ($row['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($row['user_yim']) . '&.src=pg' : '', 'jabber' => ($row['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&action=jabber&u=$poster_id") : '', - 'search' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", 'search_author=' . urlencode($row['username']) .'&sr=posts') : '', + 'search' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id=$poster_id&sr=posts") : '', ); get_user_rank($row['user_rank'], $row['user_posts'], $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']); @@ -1421,7 +1440,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) 'U_EDIT' => (!$user->data['is_registered']) ? '' : ((($user->data['user_id'] == $poster_id && $auth->acl_get('f_edit', $forum_id) && ($row['post_time'] > time() - ($config['edit_time'] * 60) || !$config['edit_time'])) || $auth->acl_get('m_edit', $forum_id)) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&f=$forum_id&p={$row['post_id']}") : ''), 'U_QUOTE' => ($auth->acl_get('f_reply', $forum_id)) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=quote&f=$forum_id&p={$row['post_id']}") : '', 'U_INFO' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&mode=post_details&f=$forum_id&p=" . $row['post_id'], true, $user->session_id) : '', - 'U_DELETE' => (!$user->data['is_registered']) ? '' : ((($user->data['user_id'] == $poster_id && $auth->acl_get('f_delete', $forum_id) && $topic_data['topic_last_post_id'] == $row['post_id'] && ($row['post_time'] > time() - ($config['edit_time'] * 60) || !$config['edit_time'])) || $auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=delete&f=$forum_id&p={$row['post_id']}") : ''), + 'U_DELETE' => (!$user->data['is_registered']) ? '' : ((($user->data['user_id'] == $poster_id && $auth->acl_get('f_delete', $forum_id) && $topic_data['topic_last_post_id'] == $row['post_id'] && !$row['post_edit_locked'] && ($row['post_time'] > time() - ($config['edit_time'] * 60) || !$config['edit_time'])) || $auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=delete&f=$forum_id&p={$row['post_id']}") : ''), 'U_PROFILE' => $user_cache[$poster_id]['profile'], 'U_SEARCH' => $user_cache[$poster_id]['search'], @@ -1494,8 +1513,8 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) } unset($rowset, $user_cache); -// Update topic view and if necessary attachment view counters ... but only if this is the first 'page view' -if (isset($user->data['session_page']) && strpos($user->data['session_page'], '&t=' . $topic_id) === false) +// Update topic view and if necessary attachment view counters ... but only for humans and if this is the first 'page view' +if (isset($user->data['session_page']) && !$user->data['is_bot'] && strpos($user->data['session_page'], '&t=' . $topic_id) === false) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_views = topic_views + 1, topic_last_view_time = ' . time() . " @@ -1569,7 +1588,7 @@ if (empty($_REQUEST['f'])) } // Output the page -page_header($user->lang['VIEW_TOPIC'] .' - ' . $topic_data['topic_title']); +page_header($user->lang['VIEW_TOPIC'] . ' - ' . $topic_data['topic_title']); $template->set_filenames(array( 'body' => ($view == 'print') ? 'viewtopic_print.html' : 'viewtopic_body.html')