diff --git a/phpBB/adm/index.php b/phpBB/adm/index.php index c0fa2fdddb..2c3f9deb6c 100644 --- a/phpBB/adm/index.php +++ b/phpBB/adm/index.php @@ -131,7 +131,7 @@ function adm_page_header($page_title) 'ICON_MOVE_UP' => '' . $user->lang['MOVE_UP'] . '', 'ICON_MOVE_UP_DISABLED' => '' . $user->lang['MOVE_UP'] . '', 'ICON_MOVE_DOWN' => '' . $user->lang['MOVE_DOWN'] . '', - 'ICON_MOVE_DOWN_DISABLED' => '' . $user->lang['MOVE_DOWN'] . '', + 'ICON_MOVE_DOWN_DISABLED' => '' . $user->lang['MOVE_DOWN'] . '', 'ICON_EDIT' => '' . $user->lang['EDIT'] . '', 'ICON_EDIT_DISABLED' => '' . $user->lang['EDIT'] . '', 'ICON_DELETE' => '' . $user->lang['DELETE'] . '', @@ -301,8 +301,9 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) break; case 'select': + case 'select_multiple': case 'custom': - + $return = ''; if (isset($vars['method'])) @@ -339,12 +340,21 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) } else { + if ($tpl_type[0] == 'select_multiple') + { + $new[$config_key] = @unserialize(trim($new[$config_key])); + } + $args = array($new[$config_key], $key); } - + $return = call_user_func_array($call, $args); - if ($tpl_type[0] == 'select') + if ($tpl_type[0] == 'select_multiple') + { + $tpl = ''; + } + else if ($tpl_type[0] == 'select') { $tpl = ''; } @@ -377,19 +387,19 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) $type = 0; $min = 1; $max = 2; - + foreach ($config_vars as $config_name => $config_definition) { if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) { continue; } - + if (!isset($config_definition['validate'])) { continue; } - + $validator = explode(':', $config_definition['validate']); // Validate a bit. ;) (0 = type, 1 = min, 2= max) @@ -548,14 +558,14 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) function validate_range($value_ary, &$error) { global $user; - + $column_types = array( 'BOOL' => array('php_type' => 'int', 'min' => 0, 'max' => 1), 'USINT' => array('php_type' => 'int', 'min' => 0, 'max' => 65535), 'UINT' => array('php_type' => 'int', 'min' => 0, 'max' => (int) 0x7fffffff), 'INT' => array('php_type' => 'int', 'min' => (int) 0x80000000, 'max' => (int) 0x7fffffff), 'TINT' => array('php_type' => 'int', 'min' => -128, 'max' => 127), - + 'VCHAR' => array('php_type' => 'string', 'min' => 0, 'max' => 255), ); foreach ($value_ary as $value) @@ -582,7 +592,7 @@ function validate_range($value_ary, &$error) } break; - case 'int': + case 'int': $min = (isset($column[1])) ? max($column[1],$type['min']) : $type['min']; $max = (isset($column[2])) ? min($column[2],$type['max']) : $type['max']; if ($value['value'] < $min) diff --git a/phpBB/adm/style/acp_captcha.html b/phpBB/adm/style/acp_captcha.html index d9d087d6ba..8a067cda66 100644 --- a/phpBB/adm/style/acp_captcha.html +++ b/phpBB/adm/style/acp_captcha.html @@ -22,6 +22,11 @@
+
+

{L_VISUAL_CONFIRM_REFRESH_EXPLAIN}
+
+
+

{L_CAPTCHA_GD_EXPLAIN}
@@ -41,6 +46,26 @@

{L_CAPTCHA_GD_Y_GRID_EXPLAIN}
+
+

{L_CAPTCHA_GD_WAVE_EXPLAIN}
+
+ +
+
+
+

{L_CAPTCHA_GD_3D_NOISE_EXPLAIN}
+
+ +
+
+
+

{L_CAPTCHA_GD_FONTS_EXPLAIN}
+
+ + + +
+
diff --git a/phpBB/adm/style/acp_database.html b/phpBB/adm/style/acp_database.html index ebc76c36a3..e839fb1bda 100644 --- a/phpBB/adm/style/acp_database.html +++ b/phpBB/adm/style/acp_database.html @@ -70,8 +70,8 @@
-
- +
+
diff --git a/phpBB/adm/style/acp_email.html b/phpBB/adm/style/acp_email.html index b1d9b4af11..885809ffe2 100644 --- a/phpBB/adm/style/acp_email.html +++ b/phpBB/adm/style/acp_email.html @@ -44,7 +44,7 @@

-   +  

{S_FORM_TOKEN} diff --git a/phpBB/adm/style/acp_forums.html b/phpBB/adm/style/acp_forums.html index 636d4ded7b..547ac66e3c 100644 --- a/phpBB/adm/style/acp_forums.html +++ b/phpBB/adm/style/acp_forums.html @@ -444,7 +444,7 @@
{forums.FORUM_IMAGE}
{forums.FORUM_NAME}{forums.FORUM_NAME}
{forums.FORUM_DESCRIPTION} -

{L_TOPICS}: {forums.FORUM_TOPICS} / {L_POSTS}: {forums.FORUM_POSTS} +

{L_TOPICS}: {forums.FORUM_TOPICS} / {L_POSTS}: {forums.FORUM_POSTS} diff --git a/phpBB/adm/style/acp_permissions.html b/phpBB/adm/style/acp_permissions.html index b4386d5f19..63583093b0 100644 --- a/phpBB/adm/style/acp_permissions.html +++ b/phpBB/adm/style/acp_permissions.html @@ -3,7 +3,7 @@ - +

{L_ACP_PERMISSIONS}

{L_ACP_PERMISSIONS_EXPLAIN} @@ -12,10 +12,12 @@ + « {L_BACK} +

{L_TITLE}

{L_EXPLAIN}

- +

{L_FORUMS}: {FORUM_NAMES}

@@ -62,7 +64,7 @@ - + @@ -123,7 +125,7 @@
- +
{S_HIDDEN_FIELDS} {S_FORM_TOKEN} @@ -154,7 +156,7 @@
- +

{L_USERGROUPS}

@@ -168,7 +170,7 @@
- +
{S_HIDDEN_FIELDS} {S_FORM_TOKEN} @@ -177,7 +179,7 @@
- +
{L_ADD_GROUPS}
@@ -199,7 +201,7 @@
- +

{L_USERS}

@@ -210,7 +212,7 @@
- +
{S_HIDDEN_FIELDS} {S_FORM_TOKEN} @@ -240,7 +242,7 @@
- +

{L_USERGROUPS}

@@ -251,7 +253,7 @@
- +
{S_HIDDEN_FIELDS} {S_FORM_TOKEN} @@ -311,11 +313,11 @@ - +
{S_HIDDEN_FIELDS} {S_FORM_TOKEN} - {L_SELECT_TYPE}: + {L_SELECT_TYPE}:
@@ -347,7 +349,7 @@


- +
diff --git a/phpBB/adm/style/acp_search.html b/phpBB/adm/style/acp_search.html index 0879780749..5fd7a23d97 100644 --- a/phpBB/adm/style/acp_search.html +++ b/phpBB/adm/style/acp_search.html @@ -32,6 +32,10 @@

{L_MIN_SEARCH_AUTHOR_CHARS_EXPLAIN}
+
+

{L_MAX_NUM_SEARCH_KEYWORDS_EXPLAIN}
+
+

{L_SEARCH_STORE_RESULTS_EXPLAIN}
{L_SECONDS}
@@ -130,9 +134,9 @@ - + - +

@@ -142,7 +146,7 @@

{S_FORM_TOKEN}
- + diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index bebbdb4235..c93d8b7d2d 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -54,7 +54,7 @@ // @@ -455,30 +455,30 @@ {L_TITLE}
-
{NAME}
+
{NAME}
-
{COPYRIGHT}
+
{COPYRIGHT}
-
{S_SUPERTEMPLATE}
+
{S_SUPERTEMPLATE}
-
{TEMPLATE_NAME}
+
{TEMPLATE_NAME}
-
{THEME_NAME}
+
{THEME_NAME}
-
{IMAGESET_NAME}
+
{IMAGESET_NAME}
diff --git a/phpBB/adm/style/install_update.html b/phpBB/adm/style/install_update.html index c0dc185361..a5a0f8b5b6 100644 --- a/phpBB/adm/style/install_update.html +++ b/phpBB/adm/style/install_update.html @@ -192,94 +192,170 @@
- - - - - + +

{L_FILES_UP_TO_DATE}

+

{L_FILES_UP_TO_DATE_EXPLAIN}

+ +
+ {L_STATUS_UP_TO_DATE} + +
+
{up_to_date.FILENAME}
+
+ +
+ + + + +

{L_FILES_NEW}

+

{L_FILES_NEW_EXPLAIN}

+ +
+ {L_STATUS_NEW} + +
+
{new.DIR_PART}
{new.FILE_PART}
+
{L_FILE_USED}: {new.CUSTOM_ORIGINAL} +
+
+ [ {new.L_SHOW_DIFF} + {L_BINARY_FILE} +
+ +
+ +
+ +
+ + + + +

{L_FILES_NOT_MODIFIED}

+
» {L_TOGGLE_DISPLAY}
+

{L_FILES_NOT_MODIFIED_EXPLAIN}

+ + -

{files.TITLE}

+ -
» {L_TOGGLE_DISPLAY}
-

{files.EXPLAIN}

+ +

{L_FILES_MODIFIED}

+

{L_FILES_MODIFIED_EXPLAIN}

-
+ +
+ {L_STATUS_MODIFIED} +
+
{modified.DIR_PART}
{modified.FILE_PART}
+
{L_FILE_USED}: {modified.CUSTOM_ORIGINAL} +
+
 
+ +
+ +
+
+
+
[ {modified.L_SHOW_DIFF} ]{L_BINARY_FILE}
+
+
+
+
[{L_SHOW_DIFF_FINAL}] 
+
+
+
+
[{L_SHOW_DIFF_FINAL}] 
+
+
+ -
- {files.L_STATUS} + + + +

{L_FILES_NEW_CONFLICT}

+

{L_FILES_NEW_CONFLICT_EXPLAIN}

+ +
+ {L_STATUS_NEW_CONFLICT} + +
+
{new_conflict.DIR_PART}
{new_conflict.FILE_PART}
+
{L_FILE_USED}: {new_conflict.CUSTOM_ORIGINAL} +
+
+ [ {new_conflict.L_SHOW_DIFF} + {L_BINARY_FILE} +
+ +
+ +
+ +
+ + + + +

{L_FILES_CONFLICT}

+

{L_FILES_CONFLICT_EXPLAIN}

+ + +
+ {L_STATUS_CONFLICT} +
+
{conflict.DIR_PART}
{conflict.FILE_PART}
+
{L_FILE_USED}: {conflict.CUSTOM_ORIGINAL} +
{L_NUM_CONFLICTS}: {conflict.NUM_CONFLICTS} +
+
+ [ {L_DOWNLOAD_CONFLICTS} ]
{L_DOWNLOAD_CONFLICTS_EXPLAIN} + {L_BINARY_FILE} +
+ +
+ +
+ +
+
+
 
+
- -
{files.FILENAME}
- -
- {files.DIR_PART}
{files.FILE_PART}
- -
{L_FILE_USED}: {files.CUSTOM_ORIGINAL} - - -
{L_NUM_CONFLICTS}: {files.NUM_CONFLICTS} - -
-
 [ {files.L_SHOW_DIFF} ]{L_BINARY_FILE}
- -
- - - -
-
-
-
[ {files.L_SHOW_DIFF} ]{L_BINARY_FILE}
-
-
-
-
[{L_SHOW_DIFF_FINAL}] 
-
-
-
-
[{L_SHOW_DIFF_FINAL}] 
-
- -
- -
- {files.L_STATUS} - - - - - - -
-
-
[{L_SHOW_DIFF_FINAL}] 
-
- -
-
-
[{L_SHOW_DIFF_FINAL}]
-
-
-
-
[{L_SHOW_DIFF_FINAL}]
-
- - -
- -
- {files.L_STATUS} - - - - - +
+
[{L_SHOW_DIFF_MODIFIED}]
+ +
+
+
[{L_SHOW_DIFF_MODIFIED}]
+
+
+
+
[{L_SHOW_DIFF_FINAL}]
+
+
+
+
[{L_SHOW_DIFF_FINAL}]
+
- +
+ -

@@ -371,7 +447,6 @@

{L_CONNECTION_FAILED}
{ERROR_MSG}

-
@@ -387,7 +462,7 @@
- +
{S_HIDDEN_FIELDS} diff --git a/phpBB/adm/style/overall_header.html b/phpBB/adm/style/overall_header.html index 0720519ce2..ccf38e49b8 100644 --- a/phpBB/adm/style/overall_header.html +++ b/phpBB/adm/style/overall_header.html @@ -28,9 +28,16 @@ function jumpto() { var page = prompt(jump_page, on_page); - if (page !== null && !isNaN(page) && page > 0) + if (page !== null && !isNaN(page) && page == Math.floor(page) && page > 0) { - document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + if (base_url.indexOf('?') == -1) + { + document.location.href = base_url + '?start=' + ((page - 1) * per_page); + } + else + { + document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + } } } diff --git a/phpBB/adm/style/simple_header.html b/phpBB/adm/style/simple_header.html index 3e36c47988..2339b70a93 100644 --- a/phpBB/adm/style/simple_header.html +++ b/phpBB/adm/style/simple_header.html @@ -39,9 +39,16 @@ function jumpto() { var page = prompt(jump_page, on_page); - if (page !== null && !isNaN(page) && page > 0) + if (page !== null && !isNaN(page) && page == Math.floor(page) && page > 0) { - document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + if (base_url.indexOf('?') == -1) + { + document.location.href = base_url + '?start=' + ((page - 1) * per_page); + } + else + { + document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + } } } diff --git a/phpBB/develop/collect_cache_stats.sh b/phpBB/develop/collect_cache_stats.sh new file mode 100755 index 0000000000..5bb31c5173 --- /dev/null +++ b/phpBB/develop/collect_cache_stats.sh @@ -0,0 +1,3 @@ +#!/bin/sh +DIR=$(dirname "$0")/../cache; +cat "$DIR/sql_*.php" | grep '/* SELECT' | sed 's,/\* ,,;s, \*/,,' | sort diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 4d39d0c6b0..52c72fc72c 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -855,7 +855,7 @@ function get_schema_struct() ), 'PRIMARY_KEY' => 'auth_option_id', 'KEYS' => array( - 'auth_option' => array('INDEX', 'auth_option'), + 'auth_option' => array('UNIQUE', 'auth_option'), ), ); diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index bc1994bcb3..77341500e1 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -327,7 +327,7 @@ function get_schema_struct() ), 'PRIMARY_KEY' => 'auth_option_id', 'KEYS' => array( - 'auth_option' => array('INDEX', 'auth_option'), + 'auth_option' => array('UNIQUE', 'auth_option'), ), ); @@ -1082,6 +1082,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/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index a468ef6976..396c64b3c0 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -53,6 +53,7 @@
  1. Changelog
      +
    1. Changes since 3.0.4
    2. Changes since 3.0.3
    3. Changes since 3.0.2
    4. Changes since 3.0.1
    5. @@ -83,7 +84,95 @@
      -

      1.i. Changes since 3.0.3

      +

      1.i. Changes since 3.0.4

      + +
        +
      • [Fix] Delete user entry from ban list table upon user deletion (Bug #40015 - Patch by TerraFrost)
      • +
      • [Fix] Posts incremented for multiple approval of the same topic (Bug #40495 - Patch by TerraFrost)
      • +
      • [Fix] Missing end " in quote bb tag deletes text (Bug #40565 - Patch by TerraFrost)
      • +
      • [Fix] Friend/foe system displays posts made by foes while composing (Bug #40325 - Patch by TerraFrost and Highway of Life)
      • +
      • [Fix] Check forum_image whether it exists (Bug #39005 - Patch by TerraFrost)
      • +
      • [Fix] The sql query in acp_users.php lacks a condition (Bug #40275 - Patch by grimskies)
      • +
      • [Fix] Added missing read permission information for some phpbb_chmod() calls
      • +
      • [Fix] Correctly display future dates (Bug #38755)
      • +
      • [Fix] Fix guest/bot session problems with apache authentication plugin (Bug #41085)
      • +
      • [Fix] Whois now works reliably for RIRs other than APNIC and RIPE
      • +
      • [Fix] Correctly convert Niels' Birthday MOD to the date format used in phpBB3. (Bug #32895)
      • +
      • [Fix] Changed the success message when requesting a new password to be more accurate. (Bug #41405)
      • +
      • [Fix] Add missing anti-abuse email headers to acp_inactive.php and ucp_resend.php.
      • +
      • [Fix] Only remind users in the correct inactive states depending on the board account activation level.
      • +
      • [Fix] Various XHTML mistakes in prosilver, subsilver2 and the ACP. (Bugs #41745, #42265 - Patch by nickvergessen, #38465, #43015)
      • +
      • [Fix] Log password changes via password reset function. (Bug #41365)
      • +
      • [Fix] Poll, negative durations generate error (Bug #41295 - Patch by TerraFrost)
      • +
      • [Fix] Visibility of custom field on registration is incorrectly controlled by setting "display" (Bug #41385 - Patch by Eelke and fade2gray)
      • +
      • [Fix] Smilies in username are misparsed on [quote=""] (Bug #41955 - Patch by TerraFrost)
      • +
      • [Fix] Deleting all posts in a topic - bad redirect (Bug #41705 - Patch by TerraFrost)
      • +
      • [Fix] Deleted users still appear logged in (Bug #41985 - Patch by TerraFrost)
      • +
      • [Fix] Removed redundant code and unnecessary queries in forum management. (Bug #42265 - Patch by nickvergessen)
      • +
      • [Fix] Correct mbstring regular expression for the allowable username characters, only affects USERNAME_LETTER_NUM_SPACERS. (Bug #42325)
      • +
      • [Fix] Fix infinite loop in message handler if cache directory is not writable. (Bug #38675)
      • +
      • [Fix] While post is awaiting approval it can still be edited even though it can not be seen (Bug #41435 - Patch by TerraFrost)
      • +
      • [Fix] Fix imageset editing for retaining and correctly setting dimensions for images, as well as displaying correct settings for first page load.
      • +
      • [Fix] Use OS-specific line endings for mail headers. (related to Bug #42755)
      • +
      • [Fix] Hide font size options which are bigger than the allowed size in the editor. (Bug #42615 - Patch by nickvergessen)
      • +
      • [Fix] Better thumbnail quality with imagemagick. (Bug #42565)
      • +
      • [Fix] Fix download count increments for image attachments without corresponding thumbnails. (Bug #42505)
      • +
      • [Fix] Fix wrong bot ip check if bot ip was wrongly entered by admin. (Bug #42485)
      • +
      • [Fix] Fix javascript errors in simple header (prosilver) by adding forum_fn.js and the corresponding variables. (Bug #42135)
      • +
      • [Fix] Set connection encoding for MySQL versions 4.1.0 to 4.1.2. This may fix some conversion issues with special characters. (Bug #41805)
      • +
      • [Fix] Deleting private message attachments could delete post attachments. (Bug #42815)
      • +
      • [Fix] Do not suppress PHP notices/errors in language packs if DEBUG_EXTRA mode enabled. (Bug #41485)
      • +
      • [Fix] Flash files do not display anymore after update to flash player 10 (Bug #41315)
      • +
      • [Fix] Use FQDN for SMTP EHLO/HELO command. (Bug #41025)
      • +
      • [Fix] Mass Email works again for users with empty jabber address but notification set to 'both'. (Bug #39755)
      • +
      • [Fix] Fix race condition for updating post/topic/etc. counter. (Reported by BartVB)
      • +
      • [Fix] Fix duplicate creation of acl options in acl_add_options() under certain conditions. (Bug #38385, #40225)
      • +
      • [Fix] Cancel when replying to global announcement redirects to first forum - not to the current forum (Bug #41225 - Patch by TerraFrost)
      • +
      • [Fix] Cursor Jumps on New Topic in IE (Bug #42455 - Patch by TerraFrost)
      • +
      • [Fix] Add indicator to be used in code if session was created (user visits the site for the first time).
      • +
      • [Fix] Correctly count topic views for guests visiting the website the first time by entering the topic directly (Bug #43445)
      • +
      • [Fix] Fix bug in postgresql db layer for LIMIT ALL clauses (Reported by JRSweets)
      • +
      • [Fix] Sort backups by date, newest first (Bug #14818)
      • +
      • [Fix] Prevent incomplete backups stored if option "store and download" is selected and admin cancel download by removing the option. (Bug #20325)
      • +
      • [Fix] Enforce correct case for template variables
      • +
      • [Fix] Set topic_last_view_time on post/reply/edit to circumvent race conditions in auto prune and false removal of topics for manual forum prune (Bug #18055, #43515)
      • +
      • [Fix] Correctly split long subject lines according to the used RFC. This fixes extra spaces within long subjects. (Bug #43715)
      • +
      • [Fix] Fix skipping messages if using next/prev PM in history links. (Bug #22205)
      • +
      • [Fix] Messenger now also able to use a custom language path. (Bug #36545)
      • +
      • [Fix] PM Export uses ISO 8601 date now. (Bug #32645)
      • +
      • [Fix] Apply append_sid() to newest/latest post links in viewforum/search and UCP main module. (Bug #26815)
      • +
      • [Fix] Do not create thumbnail if thumbnail would've the same size as the original image. (Bug #30725)
      • +
      • [Fix] Ability to vote in poll is now required for the ability to change existing vote. (Bug #38925)
      • +
      • [Fix] Search for 'topic title only' and 'first post' should work again for non-mysql dbms. (Bug #40605)
      • +
      • [Fix] Make sure additional information for accessibility is always exposed to screen readers (Bug #44335 - Patch by MarcoZ)
      • +
      • [Fix] Approving a topic when some of the posts within that topic have already been approved (Bug #42585 - Patch by TerraFrost)
      • +
      • [Fix] Online status shown when post hidden (Bug #35505 - Patch by Raimon)
      • +
      • [Fix] memberlist.php display formating can be distorted by posting long URL for website (Bug #36675 - Patch by TerraFrost)
      • +
      • [Fix] Display the online status of hidden users to users with the u_viewonline permission when viewing PMs.
      • +
      • [Fix] "Select all" selects much too much in Opera (Bug #42885 - Patch by TerraFrost and ToonArmy)
      • +
      • [Fix] Correct calculation of source/target forum statistics if mass moving topics with global announcements (Bug #44545)
      • +
      • [Fix] Fix column handling in db updater, custom profile fields an db tools for firebird DBMS (Bug #44555)
      • +
      • [Fix] IE8 textarea issues (Bug #43305)
      • +
      • [Change] Default difference view is now 'inline' instead of 'side by side'
      • +
      • [Change] Added new option for merging differences to conflicting files in automatic updater
      • +
      • [Change] Add link to user profile in the MCP for user notes and warn user.
      • +
      • [Change] Add IN_PHPBB check to generated cache files. (Reported by bantu)
      • +
      • [Change] Add topic icons to prosilver UCP main and subscribed templates (Bug #42735 - Patch by Raimon)
      • +
      • [Change] Add unique key to ACL options table to prevent duplicate permission options. (Bug #41835)
      • +
      • [Change] Redirect to relevant MCP page of multi-page topic if accessing quickmod tools (Split option for example)
      • +
      • [Change] Performance improvements for native fulltext search (Patch by Paul)
      • +
      • [Change] Changed jumpto() JS function to be more fail-safe. (But #27635 - Patch by peterkclee)
      • +
      • [Feature] Added new options for visual confirmation.
      • +
      • [Feature] Allow download of conflicting file for later reference in automatic updater
      • +
      • [Feature] Allow translation of custom BBCode help messages. (Patch by bantu)
      • +
      • [Feature] db_tools now support create table and drop table.
      • +
      • [Feature] Database updater checks for incompatible db schema (MySQL 3.x/4.x against MySQL 4.1.x/5.x/6.x)
      • +
      • [Feature] New search option: Maximum number of words allowed to search for.
      • +
      • [Sec] Prevent accounts from being activated by users when admin activation is turned on and the correct activation key is known.
      • +
      • [Sec] Only use forum id supplied for posting if global announcement detected. (Reported by nickvergessen)
      • +
      + +

      1.ii. Changes since 3.0.3

      • [Fix] Allow mixed-case template directories to be inherited (Bug #36725)
      • @@ -115,7 +204,7 @@
      • [Sec] Ask for forum password if post within passworded forum quoted in private message. (Reported by nickvergessen)
      -

      1.ii. Changes since 3.0.2

      +

      1.iii. Changes since 3.0.2

      • [Fix] Correctly set topic starter if first post in topic removed (Bug #30575 - Patch by blueray2048)
      • @@ -214,7 +303,7 @@
      • [Sec Precaution] Stricter validation of the HTTP_HOST header (Thanks to Techie-Micheal et al for pointing out possible issues in derived code)
      -

      1.iii. Changes since 3.0.1

      +

      1.iv. Changes since 3.0.1

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

      1.iv. Changes since 3.0.0

      +

      1.v. Changes since 3.0.0

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

      1.v. Changes since 3.0.RC8

      +

      1.vi. 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)
      • @@ -342,7 +431,7 @@
      • [Fix] Call garbage_collection() within database updater to correctly close connections (affects Oracle for example)
      -

      1.vi. Changes since 3.0.RC7

      +

      1.vii. Changes since 3.0.RC7

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

      1.vii. Changes since 3.0.RC6

      +

      1.viii. Changes since 3.0.RC6

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

      1.viii. Changes since 3.0.RC5

      +

      1.ix. 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.
      • @@ -450,7 +539,7 @@
      • [Sec] New password hashing mechanism for storing passwords (#i42)
      -

      1.ix. Changes since 3.0.RC4

      +

      1.x. Changes since 3.0.RC4

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

      1.x. Changes since 3.0.RC3

      +

      1.xi. Changes since 3.0.RC3

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

      1.xi. Changes since 3.0.RC2

      +

      1.xii. Changes since 3.0.RC2

      • [Fix] Re-allow searching within the memberlist
      • @@ -656,7 +745,7 @@
      -

      1.xii. Changes since 3.0.RC1

      +

      1.xiii. Changes since 3.0.RC1

      • [Fix] (X)HTML issues within the templates (Bug #11255, #11255)
      • diff --git a/phpBB/docs/FAQ.html b/phpBB/docs/FAQ.html index ee92427530..f91d4bc223 100644 --- a/phpBB/docs/FAQ.html +++ b/phpBB/docs/FAQ.html @@ -53,7 +53,7 @@
          -
        • I cannot install this it is too difficult! Will you do it?
        • +
        • I am finding phpBB too difficult to install. Will you do it for me?
        • I am having problems with the admin at a certain board, help!
        • A board has ripped off my graphics/software/etc., stop them!
        • A board is dealing in warez/porn/etc., you need to prevent them doing this!
        • @@ -62,7 +62,7 @@
        • I keep getting Mail sending errors when I (or my users) post/send PM's/etc.!
        • My users are complaining that emails are not in their selected language!
        • My AOL based users keep getting logged out!
        • -
        • No matter what I set the uploadable avatars to I cannot upload one from my computer!
        • +
        • I am unable to upload avatars from my computer, regardless of the settings.
        • I just cannot get gallery avatars to appear!
        • How do I use/set permissions?
        • I (or my users) cannot stay logged in to the forum!
        • @@ -78,7 +78,7 @@
          -

          I cannot install this it is too difficult! Will you do it?

          +

          I am finding phpBB too difficult to install. Will you do it for me?

          @@ -205,7 +205,7 @@ I want to sue you because i think you host an illegal board!
          -

          No matter what I set the uploadable avatars to I cannot upload one from my computer!

          +

          I am unable to upload avatars from my computer, regardless of the settings.

          diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 6fa296709c..4eee4520dc 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.3 you should select the phpBB-3.0.3_to_3.0.4.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.4 you should select the phpBB-3.0.4_to_3.0.5.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.3 you need the phpBB-3.0.3_to_3.0.4.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.4 you need the phpBB-3.0.4_to_3.0.5.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.

          diff --git a/phpBB/download/file.php b/phpBB/download/file.php index a89f05b8cf..32b5f87950 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -16,7 +16,7 @@ $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); -// Thank you sun. +// Thank you sun. if (isset($_SERVER['CONTENT_TYPE'])) { if ($_SERVER['CONTENT_TYPE'] === 'application/x-java-archive') @@ -60,7 +60,7 @@ if (isset($_GET['avatar'])) $filename = $_GET['avatar']; $avatar_group = false; $exit = false; - + if ($filename[0] === 'g') { $avatar_group = true; @@ -87,8 +87,8 @@ if (isset($_GET['avatar'])) header("HTTP/1.0 403 Forbidden"); $exit = true; } - - + + if (!$exit) { if (!$filename) @@ -266,7 +266,7 @@ if ($thumbnail) { $attachment['physical_filename'] = 'thumb_' . $attachment['physical_filename']; } -else if (($display_cat == ATTACHMENT_CATEGORY_NONE || $display_cat == ATTACHMENT_CATEGORY_IMAGE) && !$attachment['is_orphan']) +else if (($display_cat == ATTACHMENT_CATEGORY_NONE/* || $display_cat == ATTACHMENT_CATEGORY_IMAGE*/) && !$attachment['is_orphan']) { // Update download count $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' @@ -278,6 +278,7 @@ else if (($display_cat == ATTACHMENT_CATEGORY_NONE || $display_cat == ATTACHMENT 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']); + file_gc(); } else { @@ -375,7 +376,7 @@ function send_avatar_to_browser($file, $browser) } else { - header('HTTP/1.0 404 not found'); + header('HTTP/1.0 404 Not Found'); } } @@ -463,22 +464,35 @@ 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. $is_ie8 = (strpos(strtolower($user->browser), 'msie 8.0') !== false); - header('Content-Type: ' . $attachment['mimetype'] . (($is_ie8) ? '; authoritative=true;' : '')); + header('Content-Type: ' . $attachment['mimetype']); - if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false))) + if ($is_ie8) { - header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); - if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false)) - { - header('expires: -1'); - } + header('X-Content-Type-Options: nosniff'); + } + + if ($category == ATTACHMENT_CATEGORY_FLASH && request_var('view', 0) === 1) + { + // We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline + header('Content-Disposition: inline'); } else { - header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); - if ($is_ie8 && (strpos($attachment['mimetype'], 'image') !== 0)) + if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false))) { - header('X-Download-Options: noopen'); + header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); + if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false)) + { + header('expires: -1'); + } + } + 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'); + } } } @@ -656,8 +670,9 @@ function set_modified_headers($stamp, $browser) { if ($last_load !== false && $last_load <= $stamp) { - if (@php_sapi_name() === 'CGI') + if (substr(strtolower(@php_sapi_name()),0,3) === 'cgi') { + // in theory, we shouldn't need that due to php doing it. Reality offers a differing opinion, though header('Status: 304 Not Modified', true, 304); } else diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php index f58f925506..f9ff92e19d 100644 --- a/phpBB/includes/acm/acm_file.php +++ b/phpBB/includes/acm/acm_file.php @@ -89,7 +89,7 @@ class acm if ($fp = @fopen($this->cache_dir . 'data_global.' . $phpEx, 'wb')) { @flock($fp, LOCK_EX); - fwrite($fp, "vars = " . var_export($this->vars, true) . ";\n\n\$this->var_expires = " . var_export($this->var_expires, true) . "\n?>"); + fwrite($fp, "vars = " . var_export($this->vars, true) . ";\n\n\$this->var_expires = " . var_export($this->var_expires, true) . "\n?>"); @flock($fp, LOCK_UN); fclose($fp); @@ -99,17 +99,20 @@ class acm include($phpbb_root_path . 'includes/functions.' . $phpEx); } - phpbb_chmod($this->cache_dir . 'data_global.' . $phpEx, CHMOD_WRITE); + phpbb_chmod($this->cache_dir . 'data_global.' . $phpEx, CHMOD_READ | CHMOD_WRITE); } else { // Now, this occurred how often? ... phew, just tell the user then... if (!@is_writable($this->cache_dir)) { - trigger_error($this->cache_dir . ' is NOT writable.', E_USER_ERROR); + // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload()) + die($this->cache_dir . ' is NOT writable.'); + exit; } - trigger_error('Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx, E_USER_ERROR); + die('Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx); + exit; } $this->is_modified = false; @@ -199,7 +202,7 @@ 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 = " . (sizeof($var) ? "unserialize(" . var_export(serialize($var), true) . ");" : 'array();') . "\n\n?>"); + fwrite($fp, " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$data = " . (sizeof($var) ? "unserialize(" . var_export(serialize($var), true) . ");" : 'array();') . "\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); @@ -209,7 +212,7 @@ class acm include($phpbb_root_path . 'includes/functions.' . $phpEx); } - phpbb_chmod($this->cache_dir . "data{$var_name}.$phpEx", CHMOD_WRITE); + phpbb_chmod($this->cache_dir . "data{$var_name}.$phpEx", CHMOD_READ | CHMOD_WRITE); } } else @@ -421,7 +424,7 @@ class acm } $db->sql_freeresult($query_result); - $file = " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n"; fwrite($fp, $file . "\n\$this->sql_rowset[\$query_id] = " . (sizeof($this->sql_rowset[$query_id]) ? "unserialize(" . var_export(serialize($this->sql_rowset[$query_id]), true) . ");" : 'array();') . "\n\n?>"); @@ -434,7 +437,7 @@ class acm include($phpbb_root_path . 'includes/functions.' . $phpEx); } - phpbb_chmod($filename, CHMOD_WRITE); + phpbb_chmod($filename, CHMOD_READ | CHMOD_WRITE); $query_result = $query_id; } diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 15e9e6ab62..ef20b48cec 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1003,8 +1003,8 @@ class acp_attachments if ($files_added) { - set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true); - set_config('num_files', $config['num_files'] + $files_added, true); + set_config_count('upload_dir_size', $space_taken, true); + set_config_count('num_files', $files_added, true); } } } diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 90aa4e8683..93505e1590 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -28,22 +28,26 @@ class acp_captcha global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/board'); - - $captcha_vars = array( 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID', 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID', 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE', - 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED' + 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED', + 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE', + 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE', + 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS', + ); if (isset($_GET['demo'])) { $captcha_vars = array_keys($captcha_vars); + foreach ($captcha_vars as $captcha_var) { $config[$captcha_var] = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; } + if ($config['captcha_gd']) { include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); @@ -52,14 +56,16 @@ class acp_captcha { include($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx); } + $captcha = new captcha(); - $captcha->execute(gen_rand_string(mt_rand(5, 8)), time()); + $captcha->execute(gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)), time()); exit; } $config_vars = array( 'enable_confirm' => 'REG_ENABLE', 'enable_post_confirm' => 'POST_ENABLE', + 'confirm_refresh' => 'CONFIRM_REFRESH', 'captcha_gd' => 'CAPTCHA_GD', ); @@ -73,11 +79,14 @@ class acp_captcha if ($submit && check_form_key($form_key)) { $config_vars = array_keys($config_vars); + foreach ($config_vars as $config_var) { set_config($config_var, request_var($config_var, '')); } + $captcha_vars = array_keys($captcha_vars); + foreach ($captcha_vars as $captcha_var) { $value = request_var($captcha_var, 0); @@ -86,35 +95,39 @@ class acp_captcha set_config($captcha_var, $value); } } + + add_log('admin', 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } else if ($submit) { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action)); + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action)); } else { - $preview_image_src = append_sid(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&demo=demo")); + if (@extension_loaded('gd')) { $template->assign_var('GD', true); } + foreach ($config_vars as $config_var => $template_var) { $template->assign_var($template_var, (isset($_REQUEST[$config_var])) ? request_var($config_var, '') : $config[$config_var]) ; } + foreach ($captcha_vars as $captcha_var => $template_var) { $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; $template->assign_var($template_var, $var); $preview_image_src .= "&$captcha_var=" . $var; } + $template->assign_vars(array( 'CAPTCHA_PREVIEW' => $preview_image_src, 'PREVIEW' => isset($_POST['preview']), )); - } } } diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index e2ca66b2f3..856b867c9a 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -27,7 +27,7 @@ class acp_database { global $cache, $db, $user, $auth, $template, $table_prefix; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - + $user->add_lang('acp/database'); $this->tpl_name = 'acp_database'; @@ -82,6 +82,7 @@ class acp_database } @set_time_limit(1200); + @set_time_limit(0); $time = time(); @@ -187,7 +188,7 @@ class acp_database $template->assign_vars(array( 'U_ACTION' => $this->u_action . '&action=download' )); - + $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2'); foreach ($available_methods as $type => $module) @@ -424,27 +425,37 @@ class acp_database $dir = $phpbb_root_path . 'store/'; $dh = @opendir($dir); + $backup_files = array(); + if ($dh) { while (($file = readdir($dh)) !== false) { if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) { - $supported = in_array($matches[2], $methods); - - if ($supported == 'true') + if (in_array($matches[2], $methods)) { - $template->assign_block_vars('files', array( - 'FILE' => $file, - 'NAME' => gmdate("d-m-Y H:i:s", $matches[1]), - 'SUPPORTED' => $supported - )); + $backup_files[gmdate("d-m-Y H:i:s", $matches[1])] = $file; } } } closedir($dh); } + if (!empty($backup_files)) + { + krsort($backup_files); + + foreach ($backup_files as $name => $file) + { + $template->assign_block_vars('files', array( + 'FILE' => $file, + 'NAME' => $name, + 'SUPPORTED' => true, + )); + } + } + $template->assign_vars(array( 'U_ACTION' => $this->u_action . '&action=submit' )); @@ -508,7 +519,7 @@ class base_extractor header('Pragma: no-cache'); header("Content-Type: $mimetype; name=\"$name\""); header("Content-disposition: attachment; filename=$name"); - + switch ($format) { case 'bzip2': @@ -527,14 +538,14 @@ class base_extractor break; } } - + if ($store == true) { global $phpbb_root_path; $file = $phpbb_root_path . 'store/' . $filename . $ext; - + $this->fp = $open($file, 'w'); - + if (!$this->fp) { trigger_error('Unable to write temporary file to storage folder', E_USER_ERROR); @@ -545,6 +556,7 @@ class base_extractor function write_end() { static $close; + if ($this->store) { if ($close === null) @@ -662,11 +674,11 @@ class mysql_extractor extends base_extractor if ($result != false) { $fields_cnt = mysqli_num_fields($result); - + // Get field information $field = mysqli_fetch_fields($result); $field_set = array(); - + for ($j = 0; $j < $fields_cnt; $j++) { $field_set[] = $field[$j]->name; @@ -679,7 +691,7 @@ class mysql_extractor extends base_extractor $first_set = true; $query_len = 0; $max_len = get_usable_memory(); - + while ($row = mysqli_fetch_row($result)) { $values = array(); @@ -750,7 +762,7 @@ class mysql_extractor extends base_extractor $field[] = mysql_fetch_field($result, $i); } $field_set = array(); - + for ($j = 0; $j < $fields_cnt; $j++) { $field_set[] = $field[$j]->name; @@ -966,7 +978,7 @@ class sqlite_extractor extends base_extractor $ar[] = $row; } $db->sql_freeresult($result); - + foreach ($ar as $value) { if (strpos($value['name'], 'autoindex') !== false) @@ -1124,7 +1136,7 @@ class postgres_extractor extends base_extractor $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; } $db->sql_freeresult($result); - + $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull FROM pg_class c, pg_attribute a, pg_type t WHERE c.relname = '" . $db->sql_escape($table_name) . "' @@ -1188,7 +1200,7 @@ class postgres_extractor extends base_extractor { $line .= ' NOT NULL'; } - + $lines[] = $line; } $db->sql_freeresult($result); @@ -1388,33 +1400,33 @@ class mssql_extractor extends base_extractor $sql_data .= "GO\n"; $sql_data .= "\nCREATE TABLE [$table_name] (\n"; $rows = array(); - + $text_flag = false; - + $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '$table_name'"; $result = $db->sql_query($sql); - + while ($row = $db->sql_fetchrow($result)) { $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; - + if ($row['DATA_TYPE'] == 'text') { $text_flag = true; } - + if ($row['IS_IDENTITY']) { $line .= ' IDENTITY (1 , 1)'; } - + if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') { $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; } - + if ($row['IS_NULLABLE'] == 'YES') { $line .= ' NULL'; @@ -1423,27 +1435,27 @@ class mssql_extractor extends base_extractor { $line .= ' NOT NULL'; } - + if ($row['COLUMN_DEFAULT']) { $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; } - + $rows[] = $line; } $db->sql_freeresult($result); - + $sql_data .= implode(",\n", $rows); $sql_data .= "\n) ON [PRIMARY]"; - + if ($text_flag) { $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; } - + $sql_data .= "\nGO\n\n"; $rows = array(); - + $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = '$table_name'"; @@ -1463,7 +1475,7 @@ class mssql_extractor extends base_extractor $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; } $db->sql_freeresult($result); - + $index = array(); $sql = "EXEC sp_statistics '$table_name'"; $result = $db->sql_query($sql); @@ -1475,12 +1487,12 @@ class mssql_extractor extends base_extractor } } $db->sql_freeresult($result); - + foreach ($index as $index_name => $column_name) { $index[$index_name] = implode(', ', $column_name); } - + foreach ($index as $index_name => $columns) { $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; @@ -1508,7 +1520,7 @@ class mssql_extractor extends base_extractor $ary_type = $ary_name = array(); $ident_set = false; $sql_data = ''; - + // Grab all of the data from current table. $sql = "SELECT * FROM $table_name"; @@ -1602,7 +1614,7 @@ class mssql_extractor extends base_extractor $ary_type = $ary_name = array(); $ident_set = false; $sql_data = ''; - + // Grab all of the data from current table. $sql = "SELECT * FROM $table_name"; @@ -1819,7 +1831,7 @@ class oracle_extractor extends base_extractor { global $db; $ary_type = $ary_name = array(); - + // Grab all of the data from current table. $sql = "SELECT * FROM $table_name"; @@ -1915,7 +1927,7 @@ class firebird_extractor extends base_extractor { global $db; $ary_type = $ary_name = array(); - + // Grab all of the data from current table. $sql = "SELECT * FROM $table_name"; @@ -2244,7 +2256,7 @@ function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) { $record = ''; $delim_len = strlen($delim); - + while (!$eof($fp)) { $pos = strpos($record, $delim); diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 125908c296..350693a630 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -108,7 +108,7 @@ class acp_email $db->sql_freeresult($result); trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); } - + $i = $j = 0; // Send with BCC, no more than 50 recipients for one mail (to not exceed the limit) @@ -121,7 +121,7 @@ class acp_email { if (($row['user_notify_type'] == NOTIFY_EMAIL && $row['user_email']) || ($row['user_notify_type'] == NOTIFY_IM && $row['user_jabber']) || - ($row['user_notify_type'] == NOTIFY_BOTH && $row['user_email'] && $row['user_jabber'])) + ($row['user_notify_type'] == NOTIFY_BOTH && ($row['user_email'] || $row['user_jabber']))) { if ($i == $max_chunk_size || $row['user_lang'] != $old_lang || $row['user_notify_type'] != $old_notify_type) { @@ -173,7 +173,7 @@ class acp_email $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); - + $messenger->subject(htmlspecialchars_decode($subject)); $messenger->set_mail_priority($priority); @@ -181,7 +181,7 @@ class acp_email 'CONTACT_EMAIL' => $config['board_contact'], 'MESSAGE' => htmlspecialchars_decode($message)) ); - + if (!($messenger->send($used_method))) { $errored = true; @@ -239,7 +239,7 @@ class acp_email $select_list = ''; $select_list .= group_select_options($group_id, $exclude); - + $s_priority_options = ''; $s_priority_options .= ''; $s_priority_options .= ''; diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 6095fdd48b..bf5242ace6 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -183,7 +183,7 @@ class acp_forums $forum_perm_from = request_var('forum_perm_from', 0); // Copy permissions? - if ($forum_perm_from && !empty($forum_perm_from) && $forum_perm_from != $forum_data['forum_id'] && + if (!empty($forum_perm_from) && $forum_perm_from != $forum_data['forum_id'] && (($action != 'edit') || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) { // if we edit a forum delete current permissions first @@ -560,13 +560,12 @@ class acp_forums FROM ' . FORUMS_TABLE . ' WHERE forum_type = ' . FORUM_POST . " AND forum_id <> $forum_id"; - $result = $db->sql_query($sql); + $result = $db->sql_query_limit($sql, 1); + $postable_forum_exists = false; if ($db->sql_fetchrow($result)) { - $template->assign_vars(array( - 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_id, false, true, false)) - ); + $postable_forum_exists = true; } $db->sql_freeresult($result); @@ -583,25 +582,24 @@ class acp_forums $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); - $sql = 'SELECT forum_id - FROM ' . FORUMS_TABLE . ' - WHERE forum_type = ' . FORUM_POST . " - AND forum_id <> $forum_id"; - $result = $db->sql_query($sql); - - if ($db->sql_fetchrow($result)) + if ($postable_forum_exists) { $template->assign_vars(array( 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id)) // , false, true, false??? ); } - $db->sql_freeresult($result); $template->assign_vars(array( 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, 'S_FORUMS_LIST' => $forums_list) ); } + else if ($postable_forum_exists) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_id, false, true, false)) + ); + } $s_show_display_on_index = false; @@ -714,7 +712,7 @@ class acp_forums FROM ' . FORUMS_TABLE . ' WHERE forum_type = ' . FORUM_POST . " AND forum_id <> $forum_id"; - $result = $db->sql_query($sql); + $result = $db->sql_query_limit($sql, 1); if ($db->sql_fetchrow($result)) { @@ -807,10 +805,6 @@ class acp_forums $url = $this->u_action . "&parent_id=$this->parent_id&f={$row['forum_id']}"; - $forum_title = ($forum_type != FORUM_LINK) ? '' : ''; - $forum_title .= $row['forum_name']; - $forum_title .= ($forum_type != FORUM_LINK) ? '' : ''; - $template->assign_block_vars('forums', array( 'FOLDER_IMAGE' => $folder_image, 'FORUM_IMAGE' => ($row['forum_image']) ? '' : '', @@ -888,7 +882,7 @@ class acp_forums */ function update_forum_data(&$forum_data) { - global $db, $user, $cache; + global $db, $user, $cache, $phpbb_root_path; $errors = array(); @@ -926,6 +920,11 @@ class acp_forums array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'), ); + if (!file_exists($phpbb_root_path . $forum_data['forum_image'])) + { + $errors[] = $user->lang['FORUM_IMAGE_NO_EXIST']; + } + validate_range($range_test_ary, $errors); // Set forum flags diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 5683ae5dab..a38b47a704 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -111,6 +111,7 @@ class acp_inactive $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($row['username'])) @@ -161,7 +162,11 @@ class acp_inactive $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type, user_regdate, user_actkey FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', $mark); + WHERE ' . $db->sql_in_set('user_id', $mark) . ' + AND user_inactive_reason'; + + $sql .= ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? ' = ' . INACTIVE_REMIND : ' <> ' . INACTIVE_MANUAL; + $result = $db->sql_query($sql); if ($row = $db->sql_fetchrow($result)) @@ -179,9 +184,14 @@ class acp_inactive $messenger->to($row['user_email'], $row['username']); $messenger->im($row['user_jabber'], $row['username']); + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($row['username']), - 'REGISTER_DATE' => $user->format_date($row['user_regdate']), + 'REGISTER_DATE' => $user->format_date($row['user_regdate'], false, true), 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey']) ); diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 499543cc6c..3ab6eb64ed 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -88,7 +88,8 @@ class acp_jabber 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 + // We update the user table to be sure all users that have IM as notify type are set to both as notify type + // We set this to both because users still have their jabber address entered and may want to receive jabber notifications again once it is re-enabled. $sql_ary = array( 'user_notify_type' => NOTIFY_BOTH, ); diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index a558fe6712..8a92c06e04 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -510,6 +510,12 @@ class acp_main $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); } + // Fill dbms version if not yet filled + if (empty($config['dbms_version'])) + { + set_config('dbms_version', $db->sql_server_info(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 727aa0d25d..164970b5d5 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -23,7 +23,7 @@ class acp_permissions { var $u_action; var $permission_dropdown; - + function main($id, $mode) { global $db, $user, $auth, $template, $cache; @@ -94,7 +94,7 @@ class acp_permissions } $db->sql_freeresult($result); } - + // Map usernames to ids and vice versa if ($usernames) { @@ -112,7 +112,7 @@ class acp_permissions } } unset($username); - + // Build forum ids (of all forums are checked or subforum listing used) if ($all_forums) { @@ -528,7 +528,7 @@ class acp_permissions } continue; } - + if ($branch_there) { $s_options .= ' [' . $user->lang['PLUS_SUBFORUMS'] . ']'; @@ -539,14 +539,14 @@ class acp_permissions return $s_options; } - + /** * Build dropdown field for changing permission types */ function build_permission_dropdown($options, $default_option, $permission_scope) { global $user, $auth; - + $s_dropdown_options = ''; foreach ($options as $setting) { @@ -626,7 +626,7 @@ class acp_permissions { trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - + $ug_id = $forum_id = 0; // We loop through the auth settings defined in our submit @@ -762,7 +762,14 @@ class acp_permissions $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids); - trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_ids))); + } + else + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } } /** @@ -809,7 +816,7 @@ class acp_permissions function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id) { global $user, $db, $auth; - + // User or group to be set? $ug_type = (sizeof($user_id)) ? 'user' : 'group'; @@ -829,7 +836,14 @@ class acp_permissions $this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0))); - trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_id))); + } + else + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } } /** @@ -1150,7 +1164,11 @@ class acp_permissions { $sql_where = 'AND (' . $db->sql_in_set('a.auth_option_id', $option_ids) . ' OR ' . $db->sql_in_set('a.auth_role_id', $role_ids) . ')'; } - else + else if (sizeof($role_ids)) + { + $sql_where = 'AND ' . $db->sql_in_set('a.auth_role_id', $role_ids); + } + else if (sizeof($option_ids)) { $sql_where = 'AND ' . $db->sql_in_set('a.auth_option_id', $option_ids); } diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 7ab6ff7cd6..2b5ec88e5b 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -1539,7 +1539,7 @@ class acp_profile case 'firebird': // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. - $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD \"$field_ident\" "; + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' ADD "' . strtoupper($field_ident) . '" '; switch ($field_type) { diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index dc6f3d1c44..930c8d2a26 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -63,6 +63,7 @@ class acp_search 'load_search' => 'bool', 'limit_search_load' => 'float', 'min_search_author_chars' => 'integer', + 'max_num_search_keywords' => 'integer', 'search_store_results' => 'integer', ); @@ -216,6 +217,7 @@ class acp_search 'SEARCH_INTERVAL' => (float) $config['search_interval'], 'SEARCH_GUEST_INTERVAL' => (float) $config['search_anonymous_interval'], 'SEARCH_STORE_RESULTS' => (int) $config['search_store_results'], + 'MAX_NUM_SEARCH_KEYWORDS' => (int) $config['max_num_search_keywords'], 'S_SEARCH_TYPES' => $search_options, 'S_YES_SEARCH' => (bool) $config['load_search'], @@ -591,7 +593,7 @@ class acp_search ksort($this->state); - set_config('search_indexing_state', implode(',', $this->state)); + set_config('search_indexing_state', implode(',', $this->state), true); } /** diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 3a021bb4cf..184b71cec3 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -37,7 +37,10 @@ class acp_styles // Hardcoded template bitfield to add for new templates $bitfield = new bitfield(); $bitfield->set(0); + $bitfield->set(1); + $bitfield->set(2); $bitfield->set(3); + $bitfield->set(4); $bitfield->set(8); $bitfield->set(9); $bitfield->set(11); @@ -743,7 +746,7 @@ 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']) { - if ($this->get_super('template', $template_id)) + if ($super = $this->get_super('template', $template_id)) { $this->store_in_db('template', $super['template_id']); } @@ -1275,139 +1278,143 @@ parse_css_file = {PARSE_CSS_FILE} $this->page_title = 'EDIT_IMAGESET'; + if (!$imageset_id) + { + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $update = (isset($_POST['update'])) ? true : false; - $imgname = request_var('imgname', ''); - $imgpath = request_var('imgpath', ''); - $imgsize = request_var('imgsize', false); - $imgwidth = request_var('imgwidth', 0); - $imgheight = request_var('imgheight', 0); - + $imgname = request_var('imgname', 'site_logo'); $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname); - $imgpath = str_replace('..', '.', $imgpath); + $sql_extra = $imgnamelang = ''; - if ($imageset_id) + $sql = 'SELECT imageset_path, imageset_name + FROM ' . STYLES_IMAGESET_TABLE . " + WHERE imageset_id = $imageset_id"; + $result = $db->sql_query($sql); + $imageset_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$imageset_row) { - $sql = 'SELECT imageset_path, imageset_name - FROM ' . STYLES_IMAGESET_TABLE . " - WHERE imageset_id = $imageset_id"; - $result = $db->sql_query($sql); - $imageset_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } - $imageset_path = $imageset_row['imageset_path']; - $imageset_name = $imageset_row['imageset_name']; + $imageset_path = $imageset_row['imageset_path']; + $imageset_name = $imageset_row['imageset_name']; - $sql_extra = ''; - if (strpos($imgname, '-') !== false) + if (strpos($imgname, '-') !== false) + { + list($imgname, $imgnamelang) = explode('-', $imgname); + $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')"; + } + + $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $imageset_id + AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra"; + $result = $db->sql_query($sql); + $imageset_data_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $image_filename = $imageset_data_row['image_filename']; + $image_width = $imageset_data_row['image_width']; + $image_height = $imageset_data_row['image_height']; + $image_lang = $imageset_data_row['image_lang']; + $image_id = $imageset_data_row['image_id']; + $imgsize = ($imageset_data_row['image_width'] && $imageset_data_row['image_height']) ? 1 : 0; + + // Check to see whether the selected image exists in the table + $valid_name = ($update) ? false : true; + + foreach ($this->imageset_keys as $category => $img_ary) + { + if (in_array($imgname, $img_ary)) { - list($imgname, $imgnamelang) = explode('-', $imgname); - $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')"; + $valid_name = true; + break; + } + } + + if ($update && isset($_POST['imgpath']) && $valid_name) + { + // If imgwidth and imgheight are non-zero grab the actual size + // from the image itself ... we ignore width settings for the poll center image + $imgwidth = request_var('imgwidth', 0); + $imgheight = request_var('imgheight', 0); + $imgsize = request_var('imgsize', 0); + $imgpath = request_var('imgpath', ''); + $imgpath = str_replace('..', '.', $imgpath); + + // If no dimensions selected, we reset width and height to 0 ;) + if (!$imgsize) + { + $imgwidth = $imgheight = 0; } - $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id - FROM ' . STYLES_IMAGESET_DATA_TABLE . " - WHERE imageset_id = $imageset_id - AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra"; - $result = $db->sql_query($sql); - $imageset_data_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + $imglang = ''; - $image_filename = $imageset_data_row['image_filename']; - $image_width = $imageset_data_row['image_width']; - $image_height = $imageset_data_row['image_height']; - $image_lang = $imageset_data_row['image_lang']; - $image_id = $imageset_data_row['image_id']; - - if (!$imageset_row) + if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath")) { - trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); } - // Check to see whether the selected image exists in the table - $valid_name = ($update) ? false : true; - - foreach ($this->imageset_keys as $category => $img_ary) + // Determine width/height. If dimensions included and no width/height given, we detect them automatically... + if ($imgsize && $imgpath) { - if (in_array($imgname, $img_ary)) + if (!$imgwidth || !$imgheight) { - $valid_name = true; - break; + list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"); + $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file; + $imgheight = ($imgheight) ? $imgheight : $imgheight_file; } + $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0; + $imgheight = (int) $imgheight; } - if ($update && isset($_POST['imgpath'])) + if (strpos($imgpath, '/') !== false) { - if ($valid_name) - { - // If imgwidth and imgheight are non-zero grab the actual size - // from the image itself ... we ignore width settings for the poll center image - $imgwidth = request_var('imgwidth', 0); - $imgheight = request_var('imgheight', 0); - $imglang = ''; - - if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath")) - { - trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if ($imgsize && $imgpath) - { - if (!$imgwidth || !$imgheight) - { - list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"); - $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file; - $imgheight = ($imgheight) ? $imgheight : $imgheight_file; - } - $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0; - $imgheight = (int) $imgheight; - } - - - if (strpos($imgpath, '/') !== false) - { - list($imglang, $imgfilename) = explode('/', $imgpath); - } - else - { - $imgfilename = $imgpath; - } - - $sql_ary = array( - 'image_filename' => (string) $imgfilename, - 'image_width' => (int) $imgwidth, - 'image_height' => (int) $imgheight, - 'image_lang' => (string) $imglang, - ); - - // already exists - if ($imageset_data_row) - { - $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE image_id = $image_id"; - $db->sql_query($sql); - } - // does not exist - else if (!$imageset_data_row) - { - $sql_ary['image_name'] = $imgname; - $sql_ary['imageset_id'] = (int) $imageset_id; - $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - } - - $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - - add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name); - - $template->assign_var('SUCCESS', true); - - $image_filename = $imgfilename; - $image_width = $imgwidth; - $image_height = $imgheight; - $image_lang = $imglang; - } + list($imglang, $imgfilename) = explode('/', $imgpath); } + else + { + $imgfilename = $imgpath; + } + + $sql_ary = array( + 'image_filename' => (string) $imgfilename, + 'image_width' => (int) $imgwidth, + 'image_height' => (int) $imgheight, + 'image_lang' => (string) $imglang, + ); + + // already exists + if ($imageset_data_row) + { + $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE image_id = $image_id"; + $db->sql_query($sql); + } + // does not exist + else if (!$imageset_data_row) + { + $sql_ary['image_name'] = $imgname; + $sql_ary['imageset_id'] = (int) $imageset_id; + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name); + + $template->assign_var('SUCCESS', true); + + $image_filename = $imgfilename; + $image_width = $imgwidth; + $image_height = $imgheight; + $image_lang = $imglang; } $imglang = ''; @@ -1529,6 +1536,8 @@ parse_css_file = {PARSE_CSS_FILE} 'U_BACK' => $this->u_action, 'NAME' => $imageset_name, 'A_NAME' => addslashes($imageset_name), + 'PATH' => $imageset_path, + 'A_PATH' => addslashes($imageset_path), 'ERROR' => !$valid_name, 'IMG_SRC' => ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png', 'IMAGE_SELECT' => $image_found @@ -3210,7 +3219,16 @@ parse_css_file = {PARSE_CSS_FILE} if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) { - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb + if ($mode === 'template') + { + $select_bf = ', template_bitfield'; + } + else + { + $select_bf = ''; + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb $select_bf FROM $sql_from WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "' AND {$mode}_inherits_id = 0"; @@ -3225,6 +3243,7 @@ parse_css_file = {PARSE_CSS_FILE} { $inherit_id = $row["{$mode}_id"]; $inherit_path = $row["{$mode}_path"]; + $inherit_bf = ($mode === 'template') ? $row["{$mode}_bitfield"] : false; $cfg_data['store_db'] = $row["{$mode}_storedb"]; $store_db = $row["{$mode}_storedb"]; } @@ -3233,6 +3252,7 @@ parse_css_file = {PARSE_CSS_FILE} { $inherit_id = 0; $inherit_path = ''; + $inherit_bf = false; } @@ -3255,6 +3275,10 @@ parse_css_file = {PARSE_CSS_FILE} { $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield']; } + else if ($inherit_bf) + { + $sql_ary['bbcode_bitfield'] = $inherit_bf; + } else { $sql_ary['bbcode_bitfield'] = TEMPLATE_BITFIELD; diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 05a087f4c3..e5f83faec3 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -972,6 +972,7 @@ class acp_users { $sql = 'DELETE FROM ' . LOG_TABLE . ' WHERE log_type = ' . LOG_USERS . " + AND reportee_id = $user_id $where_sql"; $db->sql_query($sql); @@ -1161,7 +1162,8 @@ class acp_users foreach ($cp_data as $key => $value) { - $cp_data[$left_delim . $key . $right_delim] = $value; + // Firebird is case sensitive with delimiter + $cp_data[$left_delim . (($db->sql_layer == 'firebird') ? strtoupper($key) : $key) . $right_delim] = $value; unset($cp_data[$key]); } @@ -1846,6 +1848,16 @@ class acp_users } $error = array(); + + // The delete action was successful - therefore update the user row... + $sql = 'SELECT u.*, s.* + FROM ' . USERS_TABLE . ' u + LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id) + WHERE u.user_id = ' . $user_id . ' + ORDER BY s.session_time DESC'; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); } else { diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 6943f5ada1..10d7973da6 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -58,7 +58,7 @@ class auth_admin extends auth $cache->put('_acl_options', $this->acl_options); } } - + /** * Get permission mask * This function only supports getting permissions of one type (for example a_) @@ -140,7 +140,7 @@ class auth_admin extends auth $auth2 = &$auth; } - + $hold_ary[$userdata['user_id']] = array(); foreach ($forum_ids as $f_id) { @@ -345,7 +345,7 @@ class auth_admin extends auth // Build js roles array (role data assignments) $s_role_js_array = ''; - + if (sizeof($roles)) { $s_role_js_array = array(); @@ -696,6 +696,7 @@ class auth_admin extends auth $cur_options = array(); + // Determine current options $sql = 'SELECT auth_option, is_global, is_local FROM ' . ACL_OPTIONS_TABLE . ' ORDER BY auth_option_id'; @@ -703,15 +704,7 @@ class auth_admin extends auth while ($row = $db->sql_fetchrow($result)) { - if ($row['is_global']) - { - $cur_options['global'][] = $row['auth_option']; - } - - if ($row['is_local']) - { - $cur_options['local'][] = $row['auth_option']; - } + $cur_options[$row['auth_option']] = ($row['is_global'] && $row['is_local']) ? 'both' : (($row['is_global']) ? 'global' : 'local'); } $db->sql_freeresult($result); @@ -726,14 +719,11 @@ class auth_admin extends auth foreach ($option_ary as $option_value) { - if (!in_array($option_value, $cur_options[$type])) - { - $new_options[$type][] = $option_value; - } + $new_options[$type][] = $option_value; $flag = substr($option_value, 0, strpos($option_value, '_') + 1); - if (!in_array($flag, $cur_options[$type]) && !in_array($flag, $new_options[$type])) + if (!in_array($flag, $new_options[$type])) { $new_options[$type][] = $flag; } @@ -744,23 +734,53 @@ class auth_admin extends auth $options = array(); $options['local'] = array_diff($new_options['local'], $new_options['global']); $options['global'] = array_diff($new_options['global'], $new_options['local']); - $options['local_global'] = array_intersect($new_options['local'], $new_options['global']); + $options['both'] = array_intersect($new_options['local'], $new_options['global']); - $sql_ary = array(); + // Now check which options to add/update + $add_options = $update_options = array(); + // First local ones... foreach ($options as $type => $option_ary) { foreach ($option_ary as $option) { - $sql_ary[] = array( - 'auth_option' => (string) $option, - 'is_global' => ($type == 'global' || $type == 'local_global') ? 1 : 0, - 'is_local' => ($type == 'local' || $type == 'local_global') ? 1 : 0 - ); + if (!isset($cur_options[$option])) + { + $add_options[] = array( + 'auth_option' => (string) $option, + 'is_global' => ($type == 'global' || $type == 'both') ? 1 : 0, + 'is_local' => ($type == 'local' || $type == 'both') ? 1 : 0 + ); + + continue; + } + + // Else, update existing entry if it is changed... + if ($type === $cur_options[$option]) + { + continue; + } + + // New type is always both: + // If is now both, we set both. + // If it was global the new one is local and we need to set it to both + // If it was local the new one is global and we need to set it to both + $update_options[] = $option; } } - $db->sql_multi_insert(ACL_OPTIONS_TABLE, $sql_ary); + if (!empty($add_options)) + { + $db->sql_multi_insert(ACL_OPTIONS_TABLE, $add_options); + } + + if (!empty($update_options)) + { + $sql = 'UPDATE ' . ACL_OPTIONS_TABLE . ' + SET is_global = 1, is_local = 1 + WHERE ' . $db->sql_in_set('auth_option', $update_options); + $db->sql_query($sql); + } $cache->destroy('_acl_options'); $this->acl_clear_prefetch(); @@ -802,7 +822,7 @@ class auth_admin extends auth reset($auth); $flag = key($auth); $flag = substr($flag, 0, strpos($flag, '_') + 1); - + // This ID (the any-flag) is set if one or more permissions are true... $any_option_id = (int) $this->acl_options['id'][$flag]; @@ -916,7 +936,7 @@ class auth_admin extends auth reset($auth); $flag = key($auth); $flag = substr($flag, 0, strpos($flag, '_') + 1); - + // Remove any-flag from auth ary if (isset($auth[$flag])) { @@ -1067,7 +1087,7 @@ class auth_admin extends auth { $where_sql[] = $db->sql_in_set('auth_option_id', array_map('intval', $option_id_ary)); } - + $sql = "DELETE FROM $table WHERE " . implode(' AND ', $where_sql); $db->sql_query($sql); @@ -1090,7 +1110,7 @@ class auth_admin extends auth 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false, 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false, - + 'CAT_NAME' => $user->lang['permission_cat'][$cat]) ); @@ -1179,9 +1199,9 @@ class auth_admin extends auth 'lang' => '{ acl_' . $permission . ' }' ); } - + $cat = $user->lang['acl_' . $permission]['cat']; - + // Build our categories array if (!isset($categories[$cat])) { diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php index 80ac81ed46..930f5a0632 100644 --- a/phpBB/includes/auth/auth_apache.php +++ b/phpBB/includes/auth/auth_apache.php @@ -104,7 +104,7 @@ function login_apache(&$username, &$password) 'user_row' => $row, ); } - + // Successful login... return array( 'status' => LOGIN_SUCCESS, @@ -227,15 +227,22 @@ function user_row_apache($username, $password) */ function validate_session_apache(&$user) { - if (!isset($_SERVER['PHP_AUTH_USER'])) + // Check if PHP_AUTH_USER is set and handle this case + if (isset($_SERVER['PHP_AUTH_USER'])) { - return false; + $php_auth_user = ''; + set_var($php_auth_user, $_SERVER['PHP_AUTH_USER'], 'string', true); + + return ($php_auth_user === $user['username']) ? true : false; } - $php_auth_user = ''; - set_var($php_auth_user, $_SERVER['PHP_AUTH_USER'], 'string', true); + // PHP_AUTH_USER is not set. A valid session is now determined by the user type (anonymous/bot or not) + if ($user['user_type'] == USER_IGNORE) + { + return true; + } - return ($php_auth_user === $user['username']) ? true : false; + return false; } ?> \ No newline at end of file diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index 1a5fd9e418..24d4c56614 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -141,7 +141,9 @@ function login_db(&$username, &$password) } // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding - if (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password']) + // plain md5 support left in for conversions from other systems. + if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password']))) + || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password']))) { $hash = phpbb_hash($password_new_format); @@ -155,7 +157,7 @@ function login_db(&$username, &$password) $row['user_pass_convert'] = 0; $row['user_password'] = $hash; } - else + else { // Although we weren't able to convert this password we have to // increase login attempt count to make sure this cannot be exploited diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index fd8fadf3a7..562488db70 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -134,7 +134,7 @@ 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)) { if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) @@ -410,7 +410,7 @@ class bbcode if (empty($bbcode_hardtpl)) { global $user; - + $bbcode_hardtpl = array( 'b_open' => '', 'b_close' => '', @@ -528,12 +528,12 @@ class bbcode else if (is_numeric($type)) { $tpl = 'olist_open'; - $type = 'arabic-numbers'; + $type = 'decimal'; } else { $tpl = 'olist_open'; - $type = 'arabic-numbers'; + $type = 'decimal'; } return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl)); diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php index 9c9eb5eda7..9734a63c1b 100644 --- a/phpBB/includes/captcha/captcha_gd.php +++ b/phpBB/includes/captcha/captcha_gd.php @@ -27,6 +27,7 @@ class captcha var $width = 360; var $height = 96; + /** * Create the image containing $code with a seed of $seed */ @@ -34,7 +35,7 @@ class captcha { global $config; srand($seed); - mt_srand($seed); + //mt_srand($seed); // Create image $img = imagecreatetruecolor($this->width, $this->height); @@ -52,11 +53,11 @@ class captcha $bg_colours = array_splice($scheme, mt_rand(6, 12)); // Generate code characters - $characters = $sizes = $bounding_boxes = array(); + $characters = $sizes = $bounding_boxes = $noise = array(); $width_avail = $this->width - 15; $code_len = strlen($code); - $captcha_bitmaps = $this->captcha_bitmaps(); + for ($i = 0; $i < $code_len; ++$i) { $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]); @@ -69,6 +70,7 @@ class captcha $bounding_boxes[$i] = $box; } + // Redistribute leftover x-space $offset = array(); for ($i = 0; $i < $code_len; ++$i) @@ -98,7 +100,34 @@ class captcha imagedashedline($img, mt_rand($x -3, $x + 3), mt_rand(0, 4), mt_rand($x -3, $x + 3), mt_rand($this->height - 5, $this->height), $current_colour); } } + if ($config['captcha_gd_wave'] && ($config['captcha_gd_y_grid'] || $config['captcha_gd_y_grid'])) + { + $this->wave($img); + } + + + if ($config['captcha_gd_3d_noise']) + { + $xoffset = rand(0,9); + $noise_bitmaps = $this->captcha_noise_bg_bitmaps(); + for ($i = 0; $i < $code_len; ++$i) + { + $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, count($noise_bitmaps['data']))); + list($min, $max) = $noise[$i]->range(); + //$box = $noise[$i]->dimensions($sizes[$i]); + } + $xoffset = 0; + for ($i = 0; $i < $code_len; ++$i) + { + $dimm = $bounding_boxes[$i]; + $xoffset += ($offset[$i] - $dimm[0]); + $yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]); + + $noise[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); + $xoffset += $dimm[2]; + } + } $xoffset = 5; for ($i = 0; $i < $code_len; ++$i) { @@ -109,12 +138,14 @@ class captcha $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); $xoffset += $dimm[2]; } - + if ($config['captcha_gd_wave']) + { + $this->wave($img); + } if ($config['captcha_gd_foreground_noise']) { $this->noise_line($img, 0, 0, $this->width, $this->height, $colour->get_resource('background'), $scheme, $bg_colours); } - // Send image header('Content-Type: image/png'); header('Cache-control: no-cache, no-store'); @@ -122,6 +153,38 @@ class captcha imagedestroy($img); } + /** + * Sinus + */ + function wave($img) + { + global $config; + + $period_x = mt_rand(12,18); + $period_y = mt_rand(7,14); + $amp_x = mt_rand(5,10); + $amp_y = mt_rand(2,4); + $socket = mt_rand(0,100); + + $dampen_x = mt_rand($this->width/5, $this->width/2); + $dampen_y = mt_rand($this->height/5, $this->height/2); + $direction_x = (mt_rand (0, 1)); + $direction_y = (mt_rand (0, 1)); + + for ($i = 0; $i < $this->width; $i++) + { + $dir = ($direction_x) ? $i : ($this->width - $i); + imagecopy($img, $img, $i-1, sin($socket+ $i/($period_x + $dir/$dampen_x)) * $amp_x, $i, 0, 1, $this->height); + } + $socket = mt_rand(0,100); + for ($i = 0; $i < $this->height; $i++) + { + $dir = ($direction_y) ? $i : ($this->height - $i); + imagecopy($img, $img ,sin($socket + $i/($period_y + ($dir)/$dampen_y)) * $amp_y, $i-1, 0, $i, $this->width, 1); + } + return $img; + } + /** * Noise line */ @@ -171,458 +234,1468 @@ class captcha imagesetthickness($img, 1); } + + function captcha_noise_bg_bitmaps() + { + return array( + 'width' => 15, + 'height' => 5, + 'data' => array( + + 1 => array( + array(1,0,0,0,1,0,0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,1,0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,1,0,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0,0,0,1,0,0,0), + ), + 2 => array( + array(1,1,mt_rand(0,1),1,0,1,1,1,1,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,1,1,0,1,1,1), + ), + 3 => array( + array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0,0,0,0,0,1,0), + array(0,0,0,0,1,0,0,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1), + ), + 4 => array( + array(1,0,1,0,1,0,0,1,1,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(1,0,1,0,0,0,0,0,0,0,0,0,0,0,0), + ), + 5 => array( + array(1,1,1,1,0,0,0,1,1,1,0,0,1,0,1), + array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(1,0,1,0,0,0,0,0,0,0,0,0,0,0,0), + ), + 6 => array( + array(mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),0,mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),0,mt_rand(0,1),mt_rand(0,1),mt_rand(0,1)), + array(0,0,0,0,0,0,0,mt_rand(0,1),0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(mt_rand(0,1),0,mt_rand(0,1),0,0,0,0,0,0,0,0,0,0,0,0), + ), + 7 => array( + array(0,0,0,0,0,0,0,0,0,0,1,1,0,1,1), + array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + array(0,0,1,1,0,0,0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,1,0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + ), + )); + } + /** * Return bitmaps */ function captcha_bitmaps() { + global $config; + + $chars = array( + 'A' => array( + array( + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,1,1,1,1,1,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,1,1,0,1,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,1,1,1,1,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,0,0,0,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,1,1,1,1,1,0,0), + array(0,1,1,0,0,0,1,1,0), + array(1,1,0,0,0,0,0,1,1), + array(1,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,1,1), + array(0,0,0,0,0,1,1,1,1), + array(0,0,0,1,1,1,0,0,1), + array(0,1,1,1,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,1,0,0,0,0,1,1,1), + array(0,1,1,1,1,1,1,0,1), + ), + ), + 'B' => array( + array( + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + ), + array( + array(1,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + ), + array( + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,1,1,1,1,0,0), + ), + ), + 'C' => array( + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,1,1,1,1,1,0,1), + array(0,1,0,0,0,0,0,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,1), + array(0,0,1,1,1,1,1,0,1), + ), + ), + 'D' => array( + array( + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + ), + array( + array(1,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,1,1,1,1,1,0,1), + array(0,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,1,0,0,0,1,1,1), + array(0,0,1,1,1,1,1,0,1), + ), + ), + 'E' => array( + array( + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,1,1,1,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,1), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,1,1,1,1,1,0,0), + array(0,1,1,0,0,0,1,1,0), + array(1,1,0,0,0,0,0,1,1), + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,1), + array(1,1,0,0,0,0,0,1,1), + array(0,1,1,1,1,1,1,1,0), + ), + ), + 'F' => array( + array( + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + ), + array( + array(0,1,1,1,1,1,1,1,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,0,0,0), + ), + array( + array(0,0,0,1,1,0,0,0,0), + array(0,0,1,1,0,0,0,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(1,1,1,1,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + ), + ), + 'G' => array( + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,1,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,1,1,1,1,1,0,1), + array(0,1,0,0,0,0,0,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,1,1,1,1,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,1), + array(0,0,1,1,1,1,1,0,1), + ), + array( + array(0,0,1,1,1,1,1,0,1), + array(0,1,1,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,1,1,0,0,0,0,0,1), + array(0,0,1,1,1,1,1,1,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,1,1), + array(1,1,1,1,1,1,1,1,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + ), + ), + 'H' => array( + array( + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + ), + array( + array(1,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,1,1,1,1,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,0,0,0,1,1,1), + ), + array( + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,1,1,1,0,0,0), + array(1,1,1,1,0,1,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + ), + ), + 'I' => array( + array( + array(1,1,1,1,1,1,1,1,1), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(0,0,0,1,1,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,1,1,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,1,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,1,1,0,0,0), + ), + ), + 'J' => array( + array( + array(1,1,1,1,1,1,1,1,1), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(0,1,0,0,1,0,0,0,0), + array(0,0,1,1,0,0,0,0,0), + ), + array( + array(1,1,1,1,1,1,1,1,1), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,1,0,0,1,0,0,0,0), + array(1,0,1,1,0,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(0,1,0,0,1,0,0,0,0), + array(0,0,1,1,0,0,0,0,0), + ), + ), + 'K' => array( + array( // New 'K', supplied by NeoThermic + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,1,0,0,0,0), + array(1,0,0,1,0,0,0,0,0), + array(1,0,1,0,0,0,0,0,0), + array(1,1,0,0,0,0,0,0,0), + array(1,0,1,0,0,0,0,0,0), + array(1,0,0,1,0,0,0,0,0), + array(1,0,0,0,1,0,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + ), + array( + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,1,0,0), + array(0,1,0,0,0,1,0,0,0), + array(0,1,0,0,1,0,0,0,0), + array(0,1,0,1,0,0,0,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,1,0,1,0,0,0,0,0), + array(0,1,0,0,1,0,0,0,0), + array(0,1,0,0,0,1,0,0,0), + array(0,1,0,0,0,0,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,0,0,0,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,1,0,0,0), + array(0,1,0,0,1,0,0,0,0), + array(0,1,0,1,0,0,0,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,1,0,1,0,0,0,0,0), + array(0,1,0,0,1,0,0,0,0), + array(0,1,0,0,0,1,0,0,0), + array(0,1,0,0,0,0,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + ), + ), + 'L' => array( + array( + array(0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,1), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,0,1,1,1,0,0,0,0), + ), + ), + 'M' => array( + array( + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,0,1,0,0,0,1,0,1), + array(1,0,1,0,0,0,1,0,1), + array(1,0,1,0,0,0,1,0,1), + array(1,0,0,1,0,1,0,0,1), + array(1,0,0,1,0,1,0,0,1), + array(1,0,0,1,0,1,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,1,0,1,0,1,0,1,0), + array(0,1,0,1,0,1,0,1,0), + array(0,1,0,1,0,1,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,0,0,0,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,1,1,1,0,1,1,1,0), + array(1,1,0,1,1,1,0,1,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + ), + ), + 'N' => array( + array( + array(1,1,0,0,0,0,0,0,1), + array(1,1,0,0,0,0,0,0,1), + array(1,0,1,0,0,0,0,0,1), + array(1,0,1,0,0,0,0,0,1), + array(1,0,0,1,0,0,0,0,1), + array(1,0,0,1,0,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,0,1,0,0,1), + array(1,0,0,0,0,1,0,0,1), + array(1,0,0,0,0,0,1,0,1), + array(1,0,0,0,0,0,1,0,1), + array(1,0,0,0,0,0,0,1,1), + array(1,0,0,0,0,0,0,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,0,0,0,0,1,0), + array(0,1,1,0,0,0,0,1,0), + array(0,1,1,0,0,0,0,1,0), + array(0,1,0,1,0,0,0,1,0), + array(0,1,0,1,0,0,0,1,0), + array(0,1,0,1,0,0,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,0,1,1,0,1,0), + array(0,1,0,0,0,1,0,1,0), + array(0,1,0,0,0,1,1,1,0), + array(0,1,0,0,0,0,1,1,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,0,0,0,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(1,0,1,1,1,1,0,0,0), + array(1,1,1,0,0,1,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + ), + ), + 'O' => array( + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,1,1,1,1,1,0,0,0), + array(1,1,1,0,0,1,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,1,0,0,0,1,1,0,0), + array(0,1,1,1,1,1,0,0,0), + ), + ), + 'P' => array( + array( + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + ), + array( + array(1,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,1,1,0,0,0,0,0), + array(1,1,0,1,1,0,0,0,0), + array(1,0,0,0,1,0,0,0,0), + array(1,0,0,0,1,0,0,0,0), + array(1,0,0,1,1,0,0,0,0), + array(1,1,1,1,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + ), + ), + 'Q' => array( + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,1,0,0,1), + array(1,0,0,0,0,0,1,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,1), + ), + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,1,0,0,1,1,0,1,1), + array(0,1,1,1,1,1,1,1,0), + array(0,0,0,0,0,0,1,1,0), + array(0,0,0,0,0,0,0,1,1), + array(0,0,0,0,0,0,0,0,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,1,1,1,1), + array(0,0,0,0,1,1,0,0,1), + array(0,0,0,0,1,0,0,0,1), + array(0,0,0,0,1,0,0,0,1), + array(0,0,0,0,1,1,0,1,1), + array(0,0,0,0,0,1,1,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + ), + ), + 'R' => array( + array( + array(1,1,1,1,1,1,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + array(1,1,1,0,0,0,0,0,0), + array(1,0,0,1,0,0,0,0,0), + array(1,0,0,0,1,0,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,0,1,0,0), + array(1,0,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + ), + array( + array(1,1,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,1,1,1,1,0,0), + array(0,1,1,0,0,0,0,0,0), + array(0,1,1,1,0,0,0,0,0), + array(0,1,0,1,1,0,0,0,0), + array(0,1,0,0,1,1,0,0,0), + array(0,1,0,0,0,1,1,0,0), + array(0,1,0,0,0,0,1,1,0), + array(1,1,1,0,0,0,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,0,0,0,0), + array(1,1,0,0,1,1,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + ), + ), + 'S' => array( + array( + array(0,0,1,1,1,1,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,0,1,1,1,1,1,0,0), + array(0,0,0,0,0,0,0,1,0), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,1,1,1,1,1,0,1), + array(0,1,0,0,0,0,0,1,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(0,0,1,1,1,1,1,0,0), + array(0,0,0,0,0,0,0,1,0), + array(0,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,1,0,0,0,0,0,1,0), + array(1,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,1,1,1,1,0,0,0,0), + array(1,0,0,0,0,1,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,0,0,0,0,0,0,0), + array(0,1,1,1,1,0,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(1,0,0,0,1,1,0,0,0), + array(0,1,1,1,1,0,0,0,0), + ), + ), + 'T' => array( + array( + array(1,1,1,1,1,1,1,1,1), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + ), + array( + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,1,0,0,0,1), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,1,1,0,0,0), + ), + array( + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,1,1,1,1,1,1,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,1,0,0,0), + array(0,0,0,0,0,1,1,1,0), + ), + ), + 'U' => array( + array( + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,0,1,1,1,1,1,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,1,0,0,0,0,0,1), + array(0,0,1,0,0,0,0,0,1), + array(0,0,1,0,0,0,0,0,1), + array(0,0,1,0,0,0,0,0,1), + array(0,0,1,0,0,0,0,0,1), + array(0,0,1,0,0,0,0,1,1), + array(0,0,1,1,0,0,1,1,1), + array(0,0,0,1,1,1,1,0,1), + ), + ), + 'V' => array( + array( + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + ), + ), + 'W' => array( + array( + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,0,1,0,0,0,1), + array(1,0,0,1,0,1,0,0,1), + array(1,0,0,1,0,1,0,0,1), + array(1,0,0,1,0,1,0,0,1), + array(1,0,1,0,0,0,1,0,1), + array(1,0,1,0,0,0,1,0,1), + array(1,0,1,0,0,0,1,0,1), + array(1,1,0,0,0,0,0,1,1), + array(1,1,0,0,0,0,0,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,1,1,1,0,1,0), + array(0,1,0,1,0,1,0,1,0), + array(0,1,1,1,0,1,1,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,0,0,0,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,0,1,0,0,1,0), + array(0,1,0,1,1,1,0,1,0), + array(0,1,0,1,0,1,0,1,0), + array(0,1,1,1,0,1,1,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,0,0,0,0,0,0,0), + ), + ), + 'X' => array( + array( + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,1,0,0,0,0,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,1,0,0,0,0,1,0,0), + array(0,1,0,0,0,0,0,1,0), + array(1,1,1,0,0,0,1,1,1), + array(0,0,0,0,0,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,1,0), + array(0,1,1,0,0,0,1,1,0), + array(0,0,1,1,0,1,1,0,0), + array(0,0,0,1,1,1,0,0,0), + array(0,0,0,1,1,1,0,0,0), + array(0,0,1,1,0,1,1,0,0), + array(0,1,1,0,0,0,1,1,0), + array(0,0,0,0,0,0,0,0,0), + ), + ), + 'Y' => array( + array( + array(1,0,0,0,0,0,0,0,1), + array(1,0,0,0,0,0,0,0,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(1,1,1,0,0,0,1,1,1), + array(0,1,0,0,0,0,0,1,0), + array(0,1,0,0,0,0,0,1,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,1,0,0,0,1,0,0), + array(0,0,0,1,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,1,1,0,0,0), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,1,0,0,0,0,1), + array(0,0,0,1,1,0,0,0,1), + array(0,0,0,0,1,0,0,1,1), + array(0,0,0,0,1,1,0,1,0), + array(0,0,0,0,0,1,1,1,0), + array(0,0,0,0,0,0,1,0,0), + array(0,0,0,0,0,1,1,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,1,1,0,0,0), + array(0,0,1,1,1,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + ), + ), + 'Z' => array( + array( + array(1,1,1,1,1,1,1,1,1), + array(1,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,1,0), + array(0,0,0,0,0,0,1,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,1,0,0,0,0), + array(0,0,0,1,0,0,0,0,0), + array(0,0,0,1,0,0,0,0,0), + array(0,0,1,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,1), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(1,1,1,1,1,1,1,1,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,0,1), + array(0,0,0,0,0,0,0,1,0), + array(0,0,0,0,0,0,1,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,0,0,0,1,0,0,0), + array(0,0,1,1,1,1,1,0,0), + array(0,0,0,1,0,0,0,0,0), + array(0,0,0,1,0,0,0,0,0), + array(0,0,1,0,0,0,0,0,0), + array(0,1,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,0,0,0,0,0,0,0,0), + array(1,1,1,1,1,1,1,1,1), + ), + array( + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,0,0,0,0,0,0,0,0), + array(0,1,1,1,1,1,1,1,0), + array(0,0,0,0,0,1,1,0,0), + array(0,0,0,0,1,1,0,0,0), + array(0,0,0,1,1,0,0,0,0), + array(0,0,1,1,0,0,0,0,0), + array(0,0,1,0,0,0,0,0,0), + array(0,1,1,1,1,1,1,1,0), + ), + ), + ); return array( 'width' => 9, 'height' => 15, 'data' => array( - 'A' => array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'B' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - 'C' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'D' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - 'E' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - 'F' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - 'G' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'H' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'I' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - 'J' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - ), - 'K' => array( // New 'K', supplied by NeoThermic - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - 'L' => array( - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - 'M' => array( - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'N' => array( - array(1,1,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,1,1), - ), - 'O' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'P' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - 'Q' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,1), - ), - 'R' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,1,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - 'S' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'T' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - 'U' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'V' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - 'W' => array( // New 'W', supplied by MHobbit - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - ), - 'X' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'Y' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - 'Z' => array( // New 'Z' supplied by Anon - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), + 'A' => $chars['A'][mt_rand(0, min(count($chars['A']), $config['captcha_gd_fonts']) -1)], + 'B' => $chars['B'][mt_rand(0, min(count($chars['B']), $config['captcha_gd_fonts']) -1)], + 'C' => $chars['C'][mt_rand(0, min(count($chars['C']), $config['captcha_gd_fonts']) -1)], + 'D' => $chars['D'][mt_rand(0, min(count($chars['D']), $config['captcha_gd_fonts']) -1)], + 'E' => $chars['E'][mt_rand(0, min(count($chars['E']), $config['captcha_gd_fonts']) -1)], + 'F' => $chars['F'][mt_rand(0, min(count($chars['F']), $config['captcha_gd_fonts']) -1)], + 'G' => $chars['G'][mt_rand(0, min(count($chars['G']), $config['captcha_gd_fonts']) -1)], + 'H' => $chars['H'][mt_rand(0, min(count($chars['H']), $config['captcha_gd_fonts']) -1)], + 'I' => $chars['I'][mt_rand(0, min(count($chars['I']), $config['captcha_gd_fonts']) -1)], + 'J' => $chars['J'][mt_rand(0, min(count($chars['J']), $config['captcha_gd_fonts']) -1)], + 'K' => $chars['K'][mt_rand(0, min(count($chars['K']), $config['captcha_gd_fonts']) -1)], + 'L' => $chars['L'][mt_rand(0, min(count($chars['L']), $config['captcha_gd_fonts']) -1)], + 'M' => $chars['M'][mt_rand(0, min(count($chars['M']), $config['captcha_gd_fonts']) -1)], + 'N' => $chars['N'][mt_rand(0, min(count($chars['N']), $config['captcha_gd_fonts']) -1)], + 'O' => $chars['O'][mt_rand(0, min(count($chars['O']), $config['captcha_gd_fonts']) -1)], + 'P' => $chars['P'][mt_rand(0, min(count($chars['P']), $config['captcha_gd_fonts']) -1)], + 'Q' => $chars['Q'][mt_rand(0, min(count($chars['Q']), $config['captcha_gd_fonts']) -1)], + 'R' => $chars['R'][mt_rand(0, min(count($chars['R']), $config['captcha_gd_fonts']) -1)], + 'S' => $chars['S'][mt_rand(0, min(count($chars['S']), $config['captcha_gd_fonts']) -1)], + 'T' => $chars['T'][mt_rand(0, min(count($chars['T']), $config['captcha_gd_fonts']) -1)], + 'U' => $chars['U'][mt_rand(0, min(count($chars['U']), $config['captcha_gd_fonts']) -1)], + 'V' => $chars['V'][mt_rand(0, min(count($chars['V']), $config['captcha_gd_fonts']) -1)], + 'W' => $chars['W'][mt_rand(0, min(count($chars['W']), $config['captcha_gd_fonts']) -1)], + 'X' => $chars['X'][mt_rand(0, min(count($chars['X']), $config['captcha_gd_fonts']) -1)], + 'Y' => $chars['Y'][mt_rand(0, min(count($chars['Y']), $config['captcha_gd_fonts']) -1)], + 'Z' => $chars['Z'][mt_rand(0, min(count($chars['Z']), $config['captcha_gd_fonts']) -1)], + '1' => array( array(0,0,0,1,1,0,0,0,0), array(0,0,1,0,1,0,0,0,0), diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 2210b6f8a5..ff0e46974f 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -25,7 +25,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -define('PHPBB_VERSION', '3.0.4'); +define('PHPBB_VERSION', '3.0.5-RC1'); // QA-related // define('PHPBB_QA', 1); @@ -185,6 +185,10 @@ define('REFERER_VALIDATE_PATH', 2); @define('CHMOD_WRITE', 2); @define('CHMOD_EXECUTE', 1); +// Captcha code length +define('CAPTCHA_MIN_CHARS', 4); +define('CAPTCHA_MAX_CHARS', 7); + // Additional constants define('VOTE_CONVERTED', 127); diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 703af25086..bc6b027b1f 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -30,6 +30,15 @@ class phpbb_db_tools */ var $sql_layer = ''; + /** + * @var object DB object + */ + var $db = NULL; + + /** + * The Column types for every database we support + * @var array + */ var $dbms_type_map = array( 'mysql_41' => array( 'INT:' => 'int(%d)', @@ -242,20 +251,34 @@ class phpbb_db_tools ), ); - // A list of types being unsigned for better reference in some db's + /** + * A list of types being unsigned for better reference in some db's + * @var array + */ var $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); + + /** + * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. + * @var array + */ var $supported_dbms = array('firebird', 'mssql', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite'); /** - * Set this to true if you only want to return the 'to-be-executed' SQL statement(s) (as an array). + * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array). + * This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command. */ var $return_statements = false; /** + * Constructor. Set DB Object and set {@link $return_statements return_statements}. + * + * @param phpbb_dbal $db DBAL object + * @param bool $return_statements True if only statements should be returned and no SQL being executed */ - function phpbb_db_tools(&$db) + function phpbb_db_tools(&$db, $return_statements = false) { $this->db = $db; + $this->return_statements = $return_statements; // Determine mapping database type switch ($this->db->sql_layer) @@ -290,6 +313,245 @@ class phpbb_db_tools } } + /** + * Check if table exists + * + * + * @param string $table_name The table name to check for + * @return bool true if table exists, else false + */ + function sql_table_exists($table_name) + { + $this->db->sql_return_on_error(true); + $result = $this->db->sql_query_limit('SELECT * FROM ' . $table_name, 1); + $this->db->sql_return_on_error(false); + + if ($result) + { + $this->db->sql_freeresult($result); + return true; + } + + return false; + } + + /** + * Create SQL Table + * + * @param string $table_name The table name to create + * @param array $table_data Array containing table data. + * @return array Statements if $return_statements is true. + */ + function sql_create_table($table_name, $table_data) + { + // holds the DDL for a column + $columns = $statements = array(); + + // Begin transaction + $statements[] = 'begin'; + + // Determine if we have created a PRIMARY KEY in the earliest + $primary_key_gen = false; + + // Determine if the table must be created with TEXTIMAGE + $create_textimage = false; + + // Determine if the table requires a sequence + $create_sequence = false; + + // Begin table sql statement + switch ($this->sql_layer) + { + case 'mssql': + $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n"; + break; + + default: + $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n"; + break; + } + + // Iterate through the columns to create a table + foreach ($table_data['COLUMNS'] as $column_name => $column_data) + { + // here lies an array, filled with information compiled on the column's data + $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + + // here we add the definition of the new column to the list of columns + switch ($this->sql_layer) + { + case 'mssql': + $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default']; + break; + + default: + $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql']; + break; + } + + // see if we have found a primary key set due to a column definition if we have found it, we can stop looking + if (!$primary_key_gen) + { + $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set']; + } + + // create textimage DDL based off of the existance of certain column types + if (!$create_textimage) + { + $create_textimage = isset($prepared_column['textimage']) && $prepared_column['textimage']; + } + + // create sequence DDL based off of the existance of auto incrementing columns + if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment']) + { + $create_sequence = $column_name; + } + } + + // this makes up all the columns in the create table statement + $table_sql .= implode(",\n", $columns); + + // Close the table for two DBMS and add to the statements + switch ($this->sql_layer) + { + case 'firebird': + $table_sql .= "\n);"; + $statements[] = $table_sql; + break; + + case 'mssql': + $table_sql .= "\n) ON [PRIMARY]" . (($create_textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : ''); + $statements[] = $table_sql; + break; + } + + // we have yet to create a primary key for this table, + // this means that we can add the one we really wanted instead + if (!$primary_key_gen) + { + // Write primary key + if (isset($table_data['PRIMARY_KEY'])) + { + if (!is_array($table_data['PRIMARY_KEY'])) + { + $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']); + } + + switch ($this->sql_layer) + { + case 'mysql_40': + case 'mysql_41': + case 'postgres': + case 'sqlite': + $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; + break; + + case 'firebird': + case 'mssql': + $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']); + foreach ($primary_key_stmts as $pk_stmt) + { + $statements[] = $pk_stmt; + } + break; + + case 'oracle': + $table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; + break; + } + } + } + + // close the table + switch ($this->sql_layer) + { + case 'mysql_41': + // make sure the table is in UTF-8 mode + $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;"; + $statements[] = $table_sql; + break; + + case 'mysql_40': + case 'sqlite': + $table_sql .= "\n);"; + $statements[] = $table_sql; + break; + + case 'postgres': + // do we need to add a sequence for auto incrementing columns? + if ($create_sequence) + { + $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; + } + + $table_sql .= "\n);"; + $statements[] = $table_sql; + break; + + case 'oracle': + $table_sql .= "\n);"; + $statements[] = $table_sql; + + // do we need to add a sequence and a tigger for auto incrementing columns? + if ($create_sequence) + { + // create the actual sequence + $statements[] = "CREATE SEQUENCE {$table_name}_seq"; + + // the trigger is the mechanism by which we increment the counter + $trigger = "CREATE OR REPLACE TRIGGER t_{$table_name}\n"; + $trigger .= "BEFORE INSERT ON {$table_name}\n"; + $trigger .= "FOR EACH ROW WHEN (\n"; + $trigger .= "\tnew.{$create_sequence} IS NULL OR new.{$create_sequence} = 0\n"; + $trigger .= ")\n"; + $trigger .= "BEGIN\n"; + $trigger .= "\tSELECT {$table_name}_seq.nextval\n"; + $trigger .= "\tINTO :new.{$create_sequence}\n"; + $trigger .= "\tFROM dual\n"; + $trigger .= "END;"; + + $statements[] = $trigger; + } + break; + + case 'firebird': + if ($create_sequence) + { + $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; + } + break; + } + + // Write Keys + if (isset($table_data['KEYS'])) + { + foreach ($table_data['KEYS'] as $key_name => $key_data) + { + if (!is_array($key_data[1])) + { + $key_data[1] = array($key_data[1]); + } + + $old_return_statements = $this->return_statements; + $this->return_statements = true; + + $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]); + + foreach ($key_stmts as $key_stmt) + { + $statements[] = $key_stmt; + } + + $this->return_statements = $old_return_statements; + } + } + + // Commit Transaction + $statements[] = 'commit'; + + return $this->_sql_run_sql($statements); + } + /** * Handle passed database update array. * Expected structure... @@ -308,7 +570,7 @@ class phpbb_db_tools * {KEY/INDEX NAME} => array({COLUMN NAMES}), * ) * - * For more information have a look at /develop/create_schema_files.php (only available through CVS) + * For more information have a look at /develop/create_schema_files.php (only available through SVN) */ function perform_schema_changes($schema_changes) { @@ -326,7 +588,15 @@ class phpbb_db_tools { foreach ($columns as $column_name => $column_data) { - $result = $this->sql_column_change($table, $column_name, $column_data); + // If the column exists we change it, else we add it ;) + if ($this->sql_column_exists($table, $column_name)) + { + $result = $this->sql_column_change($table, $column_name, $column_data); + } + else + { + $result = $this->sql_column_add($table, $column_name, $column_data); + } if ($this->return_statements) { @@ -343,15 +613,19 @@ class phpbb_db_tools { foreach ($columns as $column_name => $column_data) { - // Only add the column if it does not exist yet - if (!$this->sql_column_exists($table, $column_name)) + // Only add the column if it does not exist yet, else change it (to be consistent) + if ($this->sql_column_exists($table, $column_name)) + { + $result = $this->sql_column_change($table, $column_name, $column_data); + } + else { $result = $this->sql_column_add($table, $column_name, $column_data); + } - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } + if ($this->return_statements) + { + $statements = array_merge($statements, $result); } } } @@ -381,11 +655,15 @@ class phpbb_db_tools { foreach ($columns as $column) { - $result = $this->sql_column_remove($table, $column); - - if ($this->return_statements) + // Only remove the column if it exists... + if ($this->sql_column_exists($table, $column)) { - $statements = array_merge($statements, $result); + $result = $this->sql_column_remove($table, $column); + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } } } } @@ -447,6 +725,10 @@ class phpbb_db_tools /** * Check if a specified column exist + * + * @param string $table Table to check the column at + * @param string $column_name The column to check + * * @return bool True if column exists, else false */ function sql_column_exists($table, $column_name) @@ -632,7 +914,6 @@ class phpbb_db_tools if (strpos($column_data[0], ':') !== false) { list($orig_column_type, $column_length) = explode(':', $column_data[0]); - if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'])) { $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length); @@ -705,6 +986,12 @@ class phpbb_db_tools $sql .= ' COLLATE UNICODE'; } + $return_array['auto_increment'] = false; + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $return_array['auto_increment'] = true; + } + break; case 'mssql': @@ -725,10 +1012,19 @@ class phpbb_db_tools } } + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { +// $sql .= 'IDENTITY (1, 1) '; + $sql_default .= 'IDENTITY (1, 1) '; + } + + $return_array['textimage'] = $column_type === '[text]'; + $sql .= 'NOT NULL'; $sql_default .= 'NOT NULL'; $return_array['column_type_sql_default'] = $sql_default; + break; case 'mysql_40': @@ -763,10 +1059,17 @@ class phpbb_db_tools // In Oracle empty strings ('') are treated as NULL. // Therefore in oracle we allow NULL's for all DEFAULT '' entries // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) - if (preg_match('/number/i', $column_type)) + if (!preg_match('/number/i', $column_type)) { $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; } + + $return_array['auto_increment'] = false; + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $return_array['auto_increment'] = true; + } + break; case 'postgres': @@ -774,9 +1077,11 @@ class phpbb_db_tools $sql .= " {$column_type} "; + $return_array['auto_increment'] = false; if (isset($column_data[2]) && $column_data[2] == 'auto_increment') { $default_val = "nextval('{$table_name}_seq')"; + $return_array['auto_increment'] = true; } else if (!is_null($column_data[1])) { @@ -795,12 +1100,15 @@ class phpbb_db_tools $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; $sql .= " CHECK ({$column_name} >= 0)"; } + break; case 'sqlite': + $return_array['primary_key_set'] = false; if (isset($column_data[2]) && $column_data[2] == 'auto_increment') { $sql .= ' INTEGER PRIMARY KEY'; + $return_array['primary_key_set'] = true; } else { @@ -809,6 +1117,7 @@ class phpbb_db_tools $sql .= ' NOT NULL '; $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; + break; } @@ -828,7 +1137,7 @@ class phpbb_db_tools switch ($this->sql_layer) { case 'firebird': - $statements[] = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql']; + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD "' . strtoupper($column_name) . '" ' . $column_data['column_type_sql']; break; case 'mssql': @@ -920,7 +1229,7 @@ class phpbb_db_tools switch ($this->sql_layer) { case 'firebird': - $statements[] = 'ALTER TABLE "' . $table_name . '" DROP "' . $column_name . '"'; + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP "' . strtoupper($column_name) . '"'; break; case 'mssql': @@ -1031,6 +1340,68 @@ class phpbb_db_tools return $this->_sql_run_sql($statements); } + /** + * Drop Table + */ + function sql_table_drop($table_name) + { + $statements = array(); + + // the most basic operation, get rid of the table + $statements[] = 'DROP TABLE ' . $table_name; + + switch ($this->sql_layer) + { + case 'firebird': + $sql = 'SELECT RDB$GENERATOR_NAME as gen + FROM RDB$GENERATORS + WHERE RDB$SYSTEM_FLAG = 0 + AND RDB$GENERATOR_NAME = \'' . strtoupper($table_name) . "_GEN'"; + $result = $this->db->sql_query($sql); + + // does a generator exist? + if ($row = $this->db->sql_fetchrow($result)) + { + $statements[] = "DROP GENERATOR {$row['gen']};"; + } + $this->db->sql_freeresult($result); + break; + + case 'oracle': + $sql = 'SELECT A.REFERENCED_NAME + FROM USER_DEPENDENCIES A, USER_TRIGGERS B + WHERE A.REFERENCED_TYPE = \'SEQUENCE\' + AND A.NAME = B.TRIGGER_NAME + AND B.TABLE_NAME = \'' . strtoupper($table_name) . "'"; + $result = $this->db->sql_query($sql); + + // any sequences ref'd to this table's triggers? + while ($row = $this->db->sql_fetchrow($result)) + { + $statements[] = "DROP SEQUENCE {$row['referenced_name']}"; + } + $this->db->sql_freeresult($result); + + case 'postgres': + // PGSQL does not "tightly" bind sequences and tables, we must guess... + $sql = "SELECT relname + FROM pg_class + WHERE relkind = 'S' + AND relname = '{$table_name}_seq'"; + $result = $this->db->sql_query($sql); + + // We don't even care about storing the results. We already know the answer if we get rows back. + if ($this->db->sql_fetchrow($result)) + { + $statements[] = "DROP SEQUENCE {$table_name}_seq;\n"; + } + $this->db->sql_freeresult($result); + break; + } + + return $this->_sql_run_sql($statements); + } + /** * Add primary key */ @@ -1042,6 +1413,8 @@ class phpbb_db_tools { case 'firebird': case 'postgres': + case 'mysql_40': + case 'mysql_41': $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; break; @@ -1054,11 +1427,6 @@ class phpbb_db_tools $statements[] = $sql; break; - case 'mysql_40': - case 'mysql_41': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; - break; - case 'oracle': $statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; break; @@ -1233,6 +1601,7 @@ class phpbb_db_tools FROM user_indexes WHERE table_name = '" . $table_name . "' AND generated = 'N'"; + $col = 'index_name'; break; case 'sqlite': @@ -1279,7 +1648,7 @@ class phpbb_db_tools { case 'firebird': // Change type... - $statements[] = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql']; + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql']; break; case 'mssql': diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php index 080f3d541a..c03b38708c 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -51,7 +51,7 @@ 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 - if (version_compare($this->sql_server_info(true), '4.1.3', '>=')) + if (version_compare($this->sql_server_info(true), '4.1.0', '>=')) { @mysql_query("SET NAMES 'utf8'", $this->db_connect_id); @@ -341,7 +341,7 @@ class dbal_mysql extends dbal return $data; } - + /** * return sql error array * @access private diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php index 83678e2904..d117e8c948 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/postgres.php @@ -26,7 +26,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); class dbal_postgres extends dbal { var $last_query_text = ''; - + /** * Connect to server */ @@ -55,7 +55,7 @@ class dbal_postgres extends dbal { $connect_string .= "host=$sqlserver "; } - + if ($port) { $connect_string .= "port=$port "; @@ -224,7 +224,7 @@ class dbal_postgres extends dbal // if $total is set to 0 we do not want to limit the number of rows if ($total == 0) { - $total = -1; + $total = 'ALL'; } $query .= "\n LIMIT $total OFFSET $offset"; diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php index ef018b2d9a..2adc3a3e6e 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-1.0.0 package +* Code from pear.php.net, Text_Diff-1.1.0 package * http://pear.php.net/package/Text_Diff/ * * Modified by phpBB Group to meet our coding standards @@ -60,6 +60,48 @@ class diff return $this->_edits; } + /** + * returns the number of new (added) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * + * @return integer The number of new lines + */ + function count_added_lines() + { + $count = 0; + + foreach ($this->_edits as $edit) + { + if (is_a($edit, 'diff_op_add') || is_a($edit, 'diff_op_change')) + { + $count += $edit->nfinal(); + } + } + return $count; + } + + /** + * Returns the number of deleted (removed) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * + * @return integer The number of deleted lines + */ + function count_deleted_lines() + { + $count = 0; + + foreach ($this->_edits as $edit) + { + if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_change')) + { + $count += $edit->norig(); + } + } + return $count; + } + /** * Computes a reversed diff. * @@ -427,33 +469,37 @@ class diff3 extends diff } /** - * Return merged output + * Return number of conflicts + */ + function get_num_conflicts() + { + $conflicts = 0; + + foreach ($this->_edits as $edit) + { + if ($edit->is_conflict()) + { + $conflicts++; + } + } + + return $conflicts; + } + + /** + * Get conflicts content for download. This is generally a merged file, but preserving conflicts and adding explanations to it. + * A user could then go through this file, search for the conflicts and changes the code accordingly. * * @param string $label1 the cvs file version/label from the original set of lines * @param string $label2 the cvs file version/label from the new set of lines * @param string $label_sep the explanation between label1 and label2 - more of a helper for the user - * @param bool $get_conflicts if set to true only the number of conflicts is returned - * @param bool $merge_new if set to true the merged output will have the new file contents on a conflicting merge * * @return mixed the merged output */ - function merged_output($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN', $get_conflicts = false, $merge_new = false) + function get_conflicts_content($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN') { global $user; - if ($get_conflicts) - { - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $this->_conflicting_blocks++; - } - } - - return $this->_conflicting_blocks; - } - $label1 = (!empty($user->lang[$label1])) ? $user->lang[$label1] : $label1; $label2 = (!empty($user->lang[$label2])) ? $user->lang[$label2] : $label2; $label_sep = (!empty($user->lang[$label_sep])) ? $user->lang[$label_sep] : $label_sep; @@ -464,14 +510,12 @@ class diff3 extends diff { if ($edit->is_conflict()) { - if (!$merge_new) - { - $lines = array_merge($lines, array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), $edit->final1, array('=======' . ($label_sep ? ' ' . $label_sep : '')), $edit->final2, array('>>>>>>>' . ($label2 ? ' ' . $label2 : ''))); - } - else - { - $lines = array_merge($lines, $edit->final1); - } + // Start conflict label + $label_start = array('<<<<<<< ' . $label1); + $label_mid = array('======= ' . $label_sep); + $label_end = array('>>>>>>> ' . $label2); + + $lines = array_merge($lines, $label_start, $edit->final1, $label_mid, $edit->final2, $label_end); $this->_conflicting_blocks++; } else @@ -483,6 +527,16 @@ class diff3 extends diff return $lines; } + /** + * Return merged output (used by the renderer) + * + * @return mixed the merged output + */ + function merged_output() + { + return $this->get_conflicts_content(); + } + /** * Merge the output and use the new file code for conflicts */ diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php index d82afb048a..eb0dcce395 100644 --- a/phpBB/includes/diff/engine.php +++ b/phpBB/includes/diff/engine.php @@ -17,7 +17,7 @@ if (!defined('IN_PHPBB')) } /** -* Code from pear.php.net, Text_Diff-1.0.0 package +* Code from pear.php.net, Text_Diff-1.1.0 package * http://pear.php.net/package/Text_Diff/ (native engine) * * Modified by phpBB Group to meet our coding standards diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php index 2e0ec86e75..02fb6ccc37 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-1.0.0 package +* Code from pear.php.net, Text_Diff-1.1.0 package * http://pear.php.net/package/Text_Diff/ * * Modified by phpBB Group to meet our coding standards diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 55c4cc5b51..be5e661d44 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -164,6 +164,37 @@ function set_config($config_name, $config_value, $is_dynamic = false) } } +/** +* Set dynamic config value with arithmetic operation. +*/ +function set_config_count($config_name, $increment, $is_dynamic = false) +{ + global $db, $cache; + + switch ($db->sql_layer) + { + case 'firebird': + $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as CHAR)'; + break; + + case 'postgres': + $sql_update = 'int4(config_value) + ' . (int) $increment; + break; + + // MySQL, SQlite, mssql, mssql_odbc, oracle + default: + $sql_update = 'config_value + ' . (int) $increment; + break; + } + + $db->sql_query('UPDATE ' . CONFIG_TABLE . ' SET config_value = ' . $sql_update . " WHERE config_name = '" . $db->sql_escape($config_name) . "'"); + + if (!$is_dynamic) + { + $cache->destroy('config'); + } +} + /** * Generates an alphanumeric random string of given length */ @@ -205,6 +236,11 @@ function get_formatted_filesize($bytes, $add_size_lang = true) { global $user; + if ($bytes >= pow(2, 30)) + { + return ($add_size_lang) ? round($bytes / 1024 / 1024 / 1024, 2) . ' ' . $user->lang['GIB'] : round($bytes / 1024 / 1024 / 1024, 2); + } + if ($bytes >= pow(2, 20)) { return ($add_size_lang) ? round($bytes / 1024 / 1024, 2) . ' ' . $user->lang['MIB'] : round($bytes / 1024 / 1024, 2); @@ -461,8 +497,9 @@ function _hash_crypt_private($password, $setting, &$itoa64) /** * 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. Permissions are mapped to the group, user always has rw(x) permission. +* 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. * @@ -475,76 +512,106 @@ function _hash_crypt_private($password, $setting, &$itoa64) * * 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 +* @param string $filename The file/directory to be chmodded +* @param int $perms Permissions to set * +* @return bool true on success, otherwise false * @author faw, phpBB Group */ function phpbb_chmod($filename, $perms = CHMOD_READ) { + static $_chmod_info; + // Return if the file no longer exists. if (!file_exists($filename)) { return false; } - if (!function_exists('fileowner') || !function_exists('filegroup')) + // Determine some common vars + if (empty($_chmod_info)) { - $file_uid = $file_gid = false; - $common_php_owner = $common_php_group = false; + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + // No need to further determine owner/group - it is unknown + $_chmod_info['process'] = false; + } + else + { + global $phpbb_root_path, $phpEx; + + // Determine owner/group of common.php file and the filename we want to change here + $common_php_owner = fileowner($phpbb_root_path . 'common.' . $phpEx); + $common_php_group = filegroup($phpbb_root_path . 'common.' . $phpEx); + + // And the owner and the groups PHP is running under. + $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; + $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; + + // If we are unable to get owner/group, then do not try to set them by guessing + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) + { + $_chmod_info['process'] = false; + } + else + { + $_chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); + } + } } - else + + if ($_chmod_info['process']) { - 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) + // Change owner + if (@chown($filename, $_chmod_info['common_owner'])) { - // Will most likely not work - if (@chown($filename, $common_php_owner)); - { - clearstatcache(); - $file_uid = fileowner($filename); - } + clearstatcache(); + $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) + // Change group + if (@chgrp($filename, $_chmod_info['common_group'])) { - if (@chgrp($filename, $common_php_group)); - { - clearstatcache(); - $file_gid = filegroup($filename); - } + clearstatcache(); + $file_gid = filegroup($filename); + } + + // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something + if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) + { + $_chmod_info['process'] = false; } } - // 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; + // Still able to process? + if ($_chmod_info['process']) + { + if ($file_uid == $_chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $_chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $_chmod_info['process'] = false; + } + } - // 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 + // We are not able to determine or change something + if (!$_chmod_info['process']) { $php = 'other'; } @@ -564,26 +631,22 @@ function phpbb_chmod($filename, $perms = CHMOD_READ) switch ($php) { - case null: case 'owner': - /* ATTENTION: if php is owner or NULL we set it to group here. This is the most failsafe combination for the vast majority of server setups. - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); clearstatcache(); - if (!is_null($php) || (is_readable($filename) && is_writable($filename))) + if (is_readable($filename) && is_writable($filename)) { break; } - */ case 'group': $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); clearstatcache(); - if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } @@ -593,7 +656,7 @@ function phpbb_chmod($filename, $perms = CHMOD_READ) clearstatcache(); - if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } @@ -703,7 +766,7 @@ if (!function_exists('stripos')) */ function is_absolute($path) { - return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:/#i', $path))) ? true : false; + return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:[/\\\]#i', $path))) ? true : false; } /** @@ -1065,7 +1128,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $sql_update = array(); while ($row = $db->sql_fetchrow($result)) { - $sql_update[] = $row['forum_id']; + $sql_update[] = (int) $row['forum_id']; } $db->sql_freeresult($result); @@ -2574,7 +2637,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $db->sql_query($sql); // Generate code - $code = gen_rand_string(mt_rand(5, 8)); + $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); $confirm_id = md5(unique_id($user->ip)); $seed = hexdec(substr(unique_id(), 4, 10)); @@ -3182,6 +3245,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) $msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text); echo '[phpBB Debug] PHP Notice: in file ' . $errfile . ' on line ' . $errline . ': ' . $msg_text . '
          ' . "\n"; + // echo '

          BACKTRACE
          ' . get_backtrace() . '
          ' . "\n"; } return; @@ -3369,7 +3433,7 @@ function obtain_guest_count($forum_id = 0) AND s.session_time >= ' . ($time - ((int) ($time % 60))) . $reading_sql; } - $result = $db->sql_query($sql, 60); + $result = $db->sql_query($sql); $guests_online = (int) $db->sql_fetchfield('num_guests'); $db->sql_freeresult($result); diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 5ec51e44cf..79282c0358 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -619,7 +619,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s if ($approved_topics) { - set_config('num_topics', $config['num_topics'] - $approved_topics, true); + set_config_count('num_topics', $approved_topics * (-1), true); } return $return; @@ -652,7 +652,23 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = return false; } - $where_clause = $db->sql_in_set($where_type, array_map('intval', $where_ids)); + $where_ids = array_map('intval', $where_ids); + +/* Possible code for splitting post deletion + if (sizeof($where_ids) >= 1001) + { + // Split into chunks of 1000 + $chunks = array_chunk($where_ids, 1000); + + foreach ($chunks as $_where_ids) + { + delete_posts($where_type, $_where_ids, $auto_sync, $posted_sync, $post_count_sync, $call_delete_topics); + } + + return; + }*/ + + $where_clause = $db->sql_in_set($where_type, $where_ids); } $approved_posts = 0; @@ -665,10 +681,10 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = while ($row = $db->sql_fetchrow($result)) { - $post_ids[] = $row['post_id']; - $poster_ids[] = $row['poster_id']; - $topic_ids[] = $row['topic_id']; - $forum_ids[] = $row['forum_id']; + $post_ids[] = (int) $row['post_id']; + $poster_ids[] = (int) $row['poster_id']; + $topic_ids[] = (int) $row['topic_id']; + $forum_ids[] = (int) $row['forum_id']; if ($row['post_postcount'] && $post_count_sync && $row['post_approved']) { @@ -776,7 +792,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = if ($approved_posts) { - set_config('num_posts', $config['num_posts'] - $approved_posts, true); + set_config_count('num_posts', $approved_posts * (-1), true); } // We actually remove topics now to not be inconsistent (the delete_topics function calls this function too) @@ -814,11 +830,14 @@ function delete_attachments($mode, $ids, $resync = true) return false; } + $sql_where = ''; + switch ($mode) { case 'post': case 'message': $sql_id = 'post_msg_id'; + $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0); break; case 'topic': @@ -842,6 +861,9 @@ function delete_attachments($mode, $ids, $resync = true) $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set($sql_id, $ids); + + $sql .= $sql_where; + $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -867,6 +889,9 @@ function delete_attachments($mode, $ids, $resync = true) // Delete attachments $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set($sql_id, $ids); + + $sql .= $sql_where; + $db->sql_query($sql); $num_deleted = $db->sql_affectedrows(); @@ -894,8 +919,8 @@ function delete_attachments($mode, $ids, $resync = true) 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); + set_config_count('upload_dir_size', $space_removed * (-1), true); + set_config_count('num_files', $files_removed * (-1), true); } // If we do not resync, we do not need to adjust any message, post, topic or user entries diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index f5c0786fed..23cbff7e8f 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -950,6 +950,8 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, 'S_THUMBNAIL' => true, 'THUMB_IMAGE' => $thumbnail_link, ); + + $update_count[] = $attachment['attach_id']; break; // Windows Media Streams @@ -996,6 +998,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, 'S_FLASH_FILE' => true, 'WIDTH' => $width, 'HEIGHT' => $height, + 'U_VIEW_LINK' => $download_link . '&view=1', ); // Viewed/Heared File ... update the download count @@ -1126,7 +1129,7 @@ function truncate_string($string, $max_length = 60, $max_store_length = 255, $al array_pop($chars); $string = implode('', $chars); } - while (utf8_strlen($string) > $max_store_length || !sizeof($chars)); + while (!empty($chars) && utf8_strlen($string) > $max_store_length); } if ($strip_reply) @@ -1159,72 +1162,87 @@ function truncate_string($string, $max_length = 60, $max_store_length = 255, $al function get_username_string($mode, $user_id, $username, $username_colour = '', $guest_username = false, $custom_profile_url = false) { static $_profile_cache; - static $_base_profile_url; - $cache_key = $user_id; - - // If the get_username_string() function had been executed once with an (to us) unkown mode, all modes are pre-filled and we can just grab it. - if ($user_id && $user_id != ANONYMOUS && isset($_profile_cache[$cache_key][$mode])) + // We cache some common variables we need within this function + if (empty($_profile_cache)) { - // If the mode is 'no_profile', we simply construct the TPL code due to calls to this mode being very very rare - if ($mode == 'no_profile') - { - $tpl = (!$_profile_cache[$cache_key]['colour']) ? '{USERNAME}' : '{USERNAME}'; - return str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($_profile_cache[$cache_key]['colour'], $_profile_cache[$cache_key]['username']), $tpl); - } + global $phpbb_root_path, $phpEx; - return $_profile_cache[$cache_key][$mode]; + $_profile_cache['base_url'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u={USER_ID}'); + $_profile_cache['tpl_noprofile'] = '{USERNAME}'; + $_profile_cache['tpl_noprofile_colour'] = '{USERNAME}'; + $_profile_cache['tpl_profile'] = '{USERNAME}'; + $_profile_cache['tpl_profile_colour'] = '{USERNAME}'; } - global $phpbb_root_path, $phpEx, $user, $auth; + global $user, $auth; - $username_colour = ($username_colour) ? '#' . $username_colour : ''; + // This switch makes sure we only run code required for the mode + switch ($mode) + { + case 'full': + case 'no_profile': + case 'colour': - if ($guest_username === false) - { - $username = ($username) ? $username : $user->lang['GUEST']; - } - else - { - $username = ($user_id && $user_id != ANONYMOUS) ? $username : ((!empty($guest_username)) ? $guest_username : $user->lang['GUEST']); + // Build correct username colour + $username_colour = ($username_colour) ? '#' . $username_colour : ''; + + // Return colour + if ($mode == 'colour') + { + return $username_colour; + } + + // no break; + + case 'username': + + // Build correct username + if ($guest_username === false) + { + $username = ($username) ? $username : $user->lang['GUEST']; + } + else + { + $username = ($user_id && $user_id != ANONYMOUS) ? $username : ((!empty($guest_username)) ? $guest_username : $user->lang['GUEST']); + } + + // Return username + if ($mode == 'username') + { + return $username; + } + + // no break; + + case 'profile': + + // Build correct profile url - only show if not anonymous and permission to view profile if registered user + // For anonymous the link leads to a login page. + if ($user_id && $user_id != ANONYMOUS && ($user->data['user_id'] == ANONYMOUS || $auth->acl_get('u_viewprofile'))) + { + $profile_url = ($custom_profile_url !== false) ? $custom_profile_url . '&u=' . (int) $user_id : str_replace(array('={USER_ID}', '=%7BUSER_ID%7D'), '=' . (int) $user_id, $_profile_cache['base_url']); + } + else + { + $profile_url = ''; + } + + // Return profile + if ($mode == 'profile') + { + return $profile_url; + } + + // no break; } - // Build cache for all modes - $_profile_cache[$cache_key]['colour'] = $username_colour; - $_profile_cache[$cache_key]['username'] = $username; - $_profile_cache[$cache_key]['no_profile'] = true; - - // Profile url - only show if not anonymous and permission to view profile if registered user - // For anonymous the link leads to a login page. - if ($user_id && $user_id != ANONYMOUS && ($user->data['user_id'] == ANONYMOUS || $auth->acl_get('u_viewprofile'))) + if (($mode == 'full' && !$profile_url) || $mode == 'no_profile') { - if (empty($_base_profile_url)) - { - $_base_profile_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u={USER_ID}'); - } - - $profile_url = ($custom_profile_url !== false) ? $custom_profile_url . '&u=' . (int) $user_id : str_replace('={USER_ID}', '=' . (int) $user_id, $_base_profile_url); - $tpl = (!$username_colour) ? '{USERNAME}' : '{USERNAME}'; - $_profile_cache[$cache_key]['full'] = str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), $tpl); - } - else - { - $tpl = (!$username_colour) ? '{USERNAME}' : '{USERNAME}'; - $_profile_cache[$cache_key]['full'] = str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($username_colour, $username), $tpl); - $profile_url = ''; + return str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_noprofile'] : $_profile_cache['tpl_noprofile_colour']); } - // Use the profile url from above - $_profile_cache[$cache_key]['profile'] = $profile_url; - - // If - by any chance - no_profile is called before any other mode, we need to do the calculation here - if ($mode == 'no_profile') - { - $tpl = (!$_profile_cache[$cache_key]['colour']) ? '{USERNAME}' : '{USERNAME}'; - return str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($_profile_cache[$cache_key]['colour'], $_profile_cache[$cache_key]['username']), $tpl); - } - - return $_profile_cache[$cache_key][$mode]; + return str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_profile'] : $_profile_cache['tpl_profile_colour']); } /** diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 14ab079202..fdcc118269 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -237,7 +237,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod // Handle marking posts if ($mark_read == 'forums' || $mark_read == 'all') { - $redirect = build_url('mark', 'hash'); + $redirect = build_url(array('mark', 'hash')); $token = request_var('hash', ''); if (check_link_hash($token, 'global')) { @@ -846,7 +846,7 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold */ function display_custom_bbcodes() { - global $db, $template; + global $db, $template, $user; // Start counting from 22 for the bbcode ids (every bbcode takes two ids - opening/closing) $num_predefined_bbcodes = 22; @@ -860,6 +860,12 @@ function display_custom_bbcodes() $i = 0; while ($row = $db->sql_fetchrow($result)) { + // If the helpline is defined within the language file, we will use the localised version, else just use the database entry... + if (isset($user->lang[strtoupper($row['bbcode_helpline'])])) + { + $row['bbcode_helpline'] = $user->lang[strtoupper($row['bbcode_helpline'])]; + } + $template->assign_block_vars('custom_tags', array( 'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'", 'BBCODE_ID' => $num_predefined_bbcodes + ($i * 2), diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index cbec2582a9..4fd5fd19e0 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -28,6 +28,7 @@ class messenger var $mail_priority = MAIL_NORMAL_PRIORITY; var $use_queue = true; var $tpl_msg = array(); + var $eol = "\n"; /** * Constructor @@ -38,6 +39,10 @@ class messenger $this->use_queue = (!$config['email_package_size']) ? false : $use_queue; $this->subject = ''; + + // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) + $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; + $this->eol = (!$this->eol) ? "\n" : $this->eol; } /** @@ -57,6 +62,11 @@ class messenger { global $config; + if (!trim($address)) + { + return; + } + $pos = isset($this->addresses['to']) ? sizeof($this->addresses['to']) : 0; $this->addresses['to'][$pos]['email'] = trim($address); @@ -77,6 +87,11 @@ class messenger */ function cc($address, $realname = '') { + if (!trim($address)) + { + return; + } + $pos = isset($this->addresses['cc']) ? sizeof($this->addresses['cc']) : 0; $this->addresses['cc'][$pos]['email'] = trim($address); $this->addresses['cc'][$pos]['name'] = trim($realname); @@ -87,6 +102,11 @@ class messenger */ function bcc($address, $realname = '') { + if (!trim($address)) + { + return; + } + $pos = isset($this->addresses['bcc']) ? sizeof($this->addresses['bcc']) : 0; $this->addresses['bcc'][$pos]['email'] = trim($address); $this->addresses['bcc'][$pos]['name'] = trim($realname); @@ -98,7 +118,7 @@ class messenger function im($address, $realname = '') { // IM-Addresses could be empty - if (!$address) + if (!trim($address)) { return; } @@ -153,7 +173,7 @@ class messenger */ function template($template_file, $template_lang = '') { - global $config, $phpbb_root_path; + global $config, $phpbb_root_path, $user; if (!trim($template_file)) { @@ -167,7 +187,8 @@ class messenger if (empty($this->tpl_msg[$template_lang . $template_file])) { - $tpl_file = "{$phpbb_root_path}language/$template_lang/email/$template_file.txt"; + $tpl_file = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/'; + $tpl_file .= $template_lang . "/email/$template_file.txt"; if (!file_exists($tpl_file)) { @@ -309,6 +330,7 @@ class messenger { global $config; + // We could use keys here, but we won't do this for 3.0.x to retain backwards compatibility $headers = array(); $headers[] = 'From: ' . $this->from; @@ -338,15 +360,12 @@ class messenger $headers[] = 'X-MimeOLE: phpBB3'; $headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()); - // We use \n here instead of \r\n because our smtp mailer is adjusting it to \r\n automatically, whereby the php mail function only works - // if using \n. - if (sizeof($this->extra_headers)) { - $headers[] = implode("\n", $this->extra_headers); + $headers = array_merge($headers, $this->extra_headers); } - return implode("\n", $headers); + return $headers; } /** @@ -361,6 +380,13 @@ class messenger return false; } + // Addresses to send to? + if (empty($this->addresses) || (empty($this->addresses['to']) && empty($this->addresses['cc']) && empty($this->addresses['bcc']))) + { + // Send was successful. ;) + return true; + } + $use_queue = false; if ($config['email_package_size'] && $this->use_queue) { @@ -412,6 +438,10 @@ class messenger } else { + // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... + // Reference: http://bugs.php.net/bug.php?id=15841 + $headers = implode($this->eol, $headers); + ob_start(); $result = $config['email_function_name']($mail_to, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $headers); $err_msg = ob_get_clean(); @@ -451,7 +481,8 @@ class messenger if (empty($this->addresses['im'])) { - return false; + // Send was successful. ;) + return true; } $use_queue = false; @@ -519,6 +550,7 @@ class queue var $queue_data = array(); var $package_size = 0; var $cache_file = ''; + var $eol = "\n"; /** * constructor @@ -529,6 +561,10 @@ class queue $this->data = array(); $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; + + // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) + $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; + $this->eol = (!$this->eol) ? "\n" : $this->eol; } /** @@ -652,7 +688,7 @@ class queue else { ob_start(); - $result = $config['email_function_name']($to, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers); + $result = $config['email_function_name']($to, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), implode($this->eol, $headers)); $err_msg = ob_get_clean(); } @@ -704,11 +740,11 @@ class queue if ($fp = @fopen($this->cache_file, 'wb')) { @flock($fp, LOCK_EX); - fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); + fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_WRITE); + phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); } } @@ -745,11 +781,11 @@ class queue if ($fp = @fopen($this->cache_file, 'w')) { @flock($fp, LOCK_EX); - fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); + fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); @flock($fp, LOCK_UN); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_WRITE); + phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); } } } @@ -757,40 +793,37 @@ class queue /** * Replacement or substitute for PHP's mail command */ -function smtpmail($addresses, $subject, $message, &$err_msg, $headers = '') +function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) { global $config, $user; // Fix any bare linefeeds in the message to make it RFC821 Compliant. $message = preg_replace("#(? 1) ? join("\n", $headers) : $headers[0]; + // Make sure there are no bare linefeeds in the headers + $headers = preg_replace('#(?server_send("$headers\r\n"); + if ($headers !== false) + { + $smtp->server_send("$headers\r\n"); + } // Ok now we are ready for the message... $smtp->server_send($message); @@ -1067,7 +1103,7 @@ class smtp_class global $user; $err_msg = ''; - $local_host = (function_exists('php_uname')) ? php_uname('n') : $user->host; + $local_host = (function_exists('php_uname')) ? gethostbyaddr(gethostbyname(php_uname('n'))) : $user->host; // If we are authenticating through pop-before-smtp, we // have to login ones before we get authenticated @@ -1411,9 +1447,10 @@ function mail_encode($str) // define start delimimter, end delimiter and spacer $start = "=?UTF-8?B?"; $end = "?="; - $spacer = $end . ' ' . $start; - $split_length = 64; + $delimiter = "\r\n "; + // Maximum length is 75. $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $delimiter . $end)!!! + $split_length = 60; $encoded_str = base64_encode($str); // If encoded string meets the limits, we just return with the correct data. @@ -1425,7 +1462,7 @@ function mail_encode($str) // If there is only ASCII data, we just return what we want, correctly splitting the lines. if (strlen($str) === utf8_strlen($str)) { - return $start . implode($spacer, str_split($encoded_str, $split_length)) . $end; + return $start . implode($end . $delimiter . $start, str_split($encoded_str, $split_length)) . $end; } // UTF-8 data, compose encoded lines @@ -1441,10 +1478,10 @@ function mail_encode($str) $text .= array_shift($array); } - $str .= $start . base64_encode($text) . $end . ' '; + $str .= $start . base64_encode($text) . $end . $delimiter; } - return substr($str, 0, -1); + return substr($str, 0, -strlen($delimiter)); } ?> \ No newline at end of file diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 4d96fb9537..07c8944992 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -614,7 +614,7 @@ function create_thumbnail($source, $destination, $mimetype) list($new_width, $new_height) = get_img_size_format($width, $height); // Do not create a thumbnail if the resulting width/height is bigger than the original one - if ($new_width > $width && $new_height > $height) + if ($new_width >= $width && $new_height >= $height) { return false; } @@ -629,7 +629,7 @@ function create_thumbnail($source, $destination, $mimetype) $config['img_imagick'] .= '/'; } - @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -antialias -sample ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" +profile "*" "' . str_replace('\\', '/', $destination) . '"'); + @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"'); if (file_exists($destination)) { @@ -963,13 +963,20 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id } $sql = $db->sql_build_query('SELECT', array( - 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*', + 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe', 'FROM' => array( USERS_TABLE => 'u', POSTS_TABLE => 'p', ), + 'LEFT_JOIN' => array( + array( + 'FROM' => array(ZEBRA_TABLE => 'z'), + 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id' + ) + ), + 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' AND u.user_id = p.poster_id' )); @@ -1060,6 +1067,9 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $post_subject = censor_text($post_subject); + $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; + $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); + $template->assign_block_vars($mode . '_row', array( 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), @@ -1067,6 +1077,9 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'U_POST_AUTHOR' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, + 'S_FRIEND' => ($row['friend']) ? true : false, + 'S_IGNORE_POST' => ($row['foe']) ? true : false, + 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "", '') : '', 'POST_SUBJECT' => $post_subject, 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), @@ -1113,7 +1126,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id if (!$topic_notification && !$forum_notification) { - trigger_error('WRONG_NOTIFICATION_MODE'); + trigger_error('NO_MODE'); } if (($topic_notification && !$config['allow_topic_notify']) || ($forum_notification && !$config['allow_forum_notify'])) @@ -1725,6 +1738,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $sql_data[TOPICS_TABLE]['sql'] = array( 'topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, + 'topic_last_view_time' => $current_time, 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => $post_approval, @@ -1738,11 +1752,23 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if (isset($poll['poll_options']) && !empty($poll['poll_options'])) { + $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; + $poll_length = $poll['poll_length'] * 86400; + if ($poll_length < 0) + { + $poll_start = $poll_start + $poll_length; + if ($poll_start < 0) + { + $poll_start = 0; + } + $poll_length = 1; + } + $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array( 'poll_title' => $poll['poll_title'], - 'poll_start' => ($poll['poll_start']) ? $poll['poll_start'] : $current_time, + 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], - 'poll_length' => ($poll['poll_length'] * 86400), + 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']) ); } @@ -1760,7 +1786,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u break; case 'reply': - $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[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ', + 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' : ''); if ($post_approval && $topic_type != POST_GLOBAL) @@ -1771,6 +1803,20 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u case 'edit_topic': case 'edit_first_post': + if (isset($poll['poll_options']) && !empty($poll['poll_options'])) + { + $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; + $poll_length = $poll['poll_length'] * 86400; + if ($poll_length < 0) + { + $poll_start = $poll_start + $poll_length; + if ($poll_start < 0) + { + $poll_start = 0; + } + $poll_length = 1; + } + } $sql_data[TOPICS_TABLE]['sql'] = array( 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], @@ -1781,10 +1827,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'topic_type' => $topic_type, 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '', - 'poll_start' => (isset($poll['poll_options'])) ? (($poll['poll_start']) ? $poll['poll_start'] : $current_time) : 0, + 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0, 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1, - 'poll_length' => (isset($poll['poll_options'])) ? ($poll['poll_length'] * 86400) : 0, + 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0, 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0, + 'topic_last_view_time' => $current_time, 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0), ); @@ -1810,8 +1857,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1); - set_config('num_topics', $config['num_topics'] - 1, true); - set_config('num_posts', $config['num_posts'] - ($topic_row['topic_replies'] + 1), true); + set_config_count('num_topics', -1, true); + set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * (-1), true); // Only decrement this post, since this is the one non-approved now if ($auth->acl_get('f_postcount', $data['forum_id'])) @@ -1828,10 +1875,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // Correctly set back the topic replies and forum posts... but only if the post was approved before. if (!$post_approval && $data['post_approved']) { - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1'; + $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1'; - set_config('num_posts', $config['num_posts'] - 1, true); + set_config_count('num_posts', -1, true); if ($auth->acl_get('f_postcount', $data['forum_id'])) { @@ -2098,8 +2145,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($space_taken && $files_added) { - set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true); - set_config('num_files', $config['num_files'] + $files_added, true); + set_config_count('upload_dir_size', $space_taken, true); + set_config_count('num_files', $files_added, true); } } @@ -2332,13 +2379,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { if ($post_mode == 'post') { - set_config('num_topics', $config['num_topics'] + 1, true); - set_config('num_posts', $config['num_posts'] + 1, true); + set_config_count('num_topics', 1, true); + set_config_count('num_posts', 1, true); } if ($post_mode == 'reply') { - set_config('num_posts', $config['num_posts'] + 1, true); + set_config_count('num_posts', 1, true); } } diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 4926cabf2c..05653f7e3b 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1350,7 +1350,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) 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); @@ -1571,8 +1571,8 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) if ($space_taken && $files_added) { - set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true); - set_config('num_files', $config['num_files'] + $files_added, true); + set_config_count('upload_dir_size', $space_taken, true); + set_config_count('num_files', $files_added, true); } } @@ -1763,8 +1763,14 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'); $next_history_pm = $previous_history_pm = $prev_id = 0; - foreach ($rowset as $id => $row) + // Re-order rowset to be able to get the next/prev message rows... + $rowset = array_values($rowset); + + for ($i = 0, $size = sizeof($rowset); $i < $size; $i++) { + $row = &$rowset[$i]; + $id = (int) $row['msg_id']; + $author_id = $row['author_id']; $folder_id = (int) $row['folder_id']; @@ -1795,8 +1801,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode if ($id == $msg_id) { - $next_history_pm = next($rowset); - $next_history_pm = (sizeof($next_history_pm)) ? (int) $next_history_pm['msg_id'] : 0; + $next_history_pm = (isset($rowset[$i + 1])) ? (int) $rowset[$i + 1]['msg_id'] : 0; $previous_history_pm = $prev_id; } diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index cc59648e54..26a1feb126 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -39,8 +39,8 @@ class custom_profile switch ($mode) { case 'register': - // If the field is required we show it on the registration page and do not show hidden fields - $sql_where .= ' AND f.field_show_on_reg = 1 AND f.field_no_view = 0'; + // If the field is required we show it on the registration page + $sql_where .= ' AND f.field_show_on_reg = 1'; break; case 'profile': @@ -270,8 +270,8 @@ class custom_profile switch ($mode) { case 'register': - // If the field is required we show it on the registration page and do not show hidden fields - $sql_where .= ' AND f.field_show_on_reg = 1 AND f.field_no_view = 0'; + // If the field is required we show it on the registration page + $sql_where .= ' AND f.field_show_on_reg = 1'; break; case 'profile': @@ -1086,4 +1086,4 @@ class custom_profile_admin extends custom_profile } } -?> +?> \ No newline at end of file diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php index 15efc7ec00..42a5eb3248 100644 --- a/phpBB/includes/functions_template.php +++ b/phpBB/includes/functions_template.php @@ -223,9 +223,12 @@ class template_compile // There will be a number of occasions where we switch into and out of // PHP mode instantaneously. Rather than "burden" the parser with this // we'll strip out such occurences, minimising such switching - $template_php = str_replace(' ?>_rootref['L_\\1'])) ? \$this->_rootref['L_\\1'] : ((isset(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '{ \\1 }')); ?>", $text_blocks); + $text_blocks = preg_replace('#\{L_([A-Z0-9\-_]+)\}#', "_rootref['L_\\1'])) ? \$this->_rootref['L_\\1'] : ((isset(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '{ \\1 }')); ?>", $text_blocks); } // Handle addslashed language variables prefixed with LA_ // If a template variable already exist, it will be used in favor of it... if (strpos($text_blocks, '{LA_') !== false) { - $text_blocks = preg_replace('#\{LA_([a-z0-9\-_]*)\}#is', "_rootref['LA_\\1'])) ? \$this->_rootref['LA_\\1'] : ((isset(\$this->_rootref['L_\\1'])) ? addslashes(\$this->_rootref['L_\\1']) : ((isset(\$user->lang['\\1'])) ? addslashes(\$user->lang['\\1']) : '{ \\1 }'))); ?>", $text_blocks); + $text_blocks = preg_replace('#\{LA_([A-Z0-9\-_]+)\}#', "_rootref['LA_\\1'])) ? \$this->_rootref['LA_\\1'] : ((isset(\$this->_rootref['L_\\1'])) ? addslashes(\$this->_rootref['L_\\1']) : ((isset(\$user->lang['\\1'])) ? addslashes(\$user->lang['\\1']) : '{ \\1 }'))); ?>", $text_blocks); } // 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\-_]+)\}#', "_rootref['\\1'])) ? \$this->_rootref['\\1'] : ''; ?>", $text_blocks); + $text_blocks = preg_replace('#\{\$([A-Z0-9\-_]+)\}#', "_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks); return; } @@ -748,6 +751,8 @@ class template_compile $filename = $this->template->cachepath . str_replace('/', '.', $this->template->filename[$handle]) . '.' . $phpEx; + $data = "' . $data); + if ($fp = @fopen($filename, 'wb')) { @flock($fp, LOCK_EX); @@ -755,7 +760,7 @@ class template_compile @flock($fp, LOCK_UN); @fclose($fp); - phpbb_chmod($filename, CHMOD_WRITE); + phpbb_chmod($filename, CHMOD_READ | CHMOD_WRITE); } return; diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index 2925a2df77..c345f81e1d 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -206,7 +206,7 @@ class transfer $directory = $this->root_path . str_replace($phpbb_root_path, '', $directory); $this->_chdir($directory); - $result = $this->_ls(''); + $result = $this->_ls(); if ($result !== false && is_array($result)) { @@ -460,7 +460,24 @@ class ftp extends transfer */ function _ls($dir = './') { - return @ftp_nlist($this->connection, $dir); + $list = @ftp_nlist($this->connection, $dir); + + // Remove path if prepended + foreach ($list as $key => $item) + { + // Use same separator for item and dir + $item = str_replace('\\', '/', $item); + $dir = str_replace('\\', '/', $dir); + + if (strpos($item, $dir) === 0) + { + $item = substr($item, strlen($dir)); + } + + $list[$key] = $item; + } + + return $list; } /** @@ -710,6 +727,24 @@ class ftp_fsock extends transfer } $this->_close_data_connection(); + // Clear buffer + $this->_check_command(); + + // Remove path if prepended + foreach ($list as $key => $item) + { + // Use same separator for item and dir + $item = str_replace('\\', '/', $item); + $dir = str_replace('\\', '/', $dir); + + if (strpos($item, $dir) === 0) + { + $item = substr($item, strlen($dir)); + } + + $list[$key] = $item; + } + return $list; } diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index e3a9363d62..1ad6223aa1 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -594,7 +594,18 @@ class fileupload // PHP Upload filesize exceeded if ($file->get('filename') == 'none') { - $file->error[] = (@ini_get('upload_max_filesize') == '') ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], @ini_get('upload_max_filesize')); + $max_filesize = @ini_get('upload_max_filesize'); + $unit = 'MB'; + + if (!empty($max_filesize)) + { + $unit = strtolower(substr($max_filesize, -1, 1)); + $max_filesize = (int) $max_filesize; + + $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); + } + + $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); return $file; } @@ -670,7 +681,18 @@ class fileupload // PHP Upload filesize exceeded if ($file->get('filename') == 'none') { - $file->error[] = (@ini_get('upload_max_filesize') == '') ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], @ini_get('upload_max_filesize')); + $max_filesize = @ini_get('upload_max_filesize'); + $unit = 'MB'; + + if (!empty($max_filesize)) + { + $unit = strtolower(substr($max_filesize, -1, 1)); + $max_filesize = (int) $max_filesize; + + $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); + } + + $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); return $file; } @@ -818,7 +840,18 @@ class fileupload switch ($errorcode) { case 1: - $error = (@ini_get('upload_max_filesize') == '') ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], @ini_get('upload_max_filesize')); + $max_filesize = @ini_get('upload_max_filesize'); + $unit = 'MB'; + + if (!empty($max_filesize)) + { + $unit = strtolower(substr($max_filesize, -1, 1)); + $max_filesize = (int) $max_filesize; + + $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); + } + + $error = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); break; case 2: diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index ea62a75306..027db39751 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -280,7 +280,7 @@ function user_add($user_row, $cp_data = false) { set_config('newest_user_id', $user_id, true); set_config('newest_username', $user_row['username'], true); - set_config('num_users', $config['num_users'] + 1, true); + set_config_count('num_users', 1, true); $sql = 'SELECT group_colour FROM ' . GROUPS_TABLE . ' @@ -490,7 +490,7 @@ function user_delete($mode, $user_id, $post_username = false) $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); + $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE, DRAFTS_TABLE, BOOKMARKS_TABLE, SESSIONS_KEYS_TABLE); foreach ($table_ary as $table) { @@ -501,6 +501,16 @@ function user_delete($mode, $user_id, $post_username = false) $cache->destroy('sql', MODERATOR_CACHE_TABLE); + // Delete the user_id from the banlist + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ban_userid = ' . $user_id; + $db->sql_query($sql); + + // Delete the user_id from the session table + $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' + WHERE session_user_id = ' . $user_id; + $db->sql_query($sql); + // Remove any undelivered mails... $sql = 'SELECT msg_id, user_id FROM ' . PRIVMSGS_TO_TABLE . ' @@ -569,7 +579,7 @@ function user_delete($mode, $user_id, $post_username = false) // Decrement number of users if this user is active if ($user_row['user_type'] != USER_INACTIVE && $user_row['user_type'] != USER_IGNORE) { - set_config('num_users', $config['num_users'] - 1, true); + set_config_count('num_users', -1, true); } return false; @@ -650,12 +660,12 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) if ($deactivated) { - set_config('num_users', $config['num_users'] - $deactivated, true); + set_config_count('num_users', $deactivated * (-1), true); } if ($activated) { - set_config('num_users', $config['num_users'] + $activated, true); + set_config_count('num_users', $activated, true); } // Update latest username @@ -1134,6 +1144,8 @@ function user_unban($mode, $ban) /** * Whois facility +* +* @link http://tools.ietf.org/html/rfc3912 RFC3912: WHOIS Protocol Specification */ function user_ipwhois($ip) { @@ -1146,16 +1158,10 @@ function user_ipwhois($ip) return ''; } - $match = array( - '#RIPE\.NET#is' => 'whois.ripe.net', - '#whois\.apnic\.net#is' => 'whois.apnic.net', - '#nic\.ad\.jp#is' => 'whois.nic.ad.jp', - '#whois\.registro\.br#is' => 'whois.registro.br' - ); - if (($fsk = @fsockopen('whois.arin.net', 43))) { - fputs($fsk, "$ip\n"); + // CRLF as per RFC3912 + fputs($fsk, "$ip\r\n"); while (!feof($fsk)) { $ipwhois .= fgets($fsk, 1024); @@ -1163,22 +1169,38 @@ function user_ipwhois($ip) @fclose($fsk); } - foreach (array_keys($match) as $server) + $match = array(); + + // Test for referrals from ARIN to other whois databases, roll on rwhois + if (preg_match('#ReferralServer: whois://(.+)#im', $ipwhois, $match)) { - if (preg_match($server, $ipwhois)) + if (strpos($match[1], ':') !== false) { - $ipwhois = ''; - if (($fsk = @fsockopen($match[$server], 43))) - { - fputs($fsk, "$ip\n"); - while (!feof($fsk)) - { - $ipwhois .= fgets($fsk, 1024); - } - @fclose($fsk); - } - break; + $pos = strrpos($match[1], ':'); + $server = substr($match[1], 0, $pos); + $port = (int) substr($match[1], $pos + 1); + unset($pos); } + else + { + $server = $match[1]; + $port = 43; + } + + $buffer = ''; + + if (($fsk = @fsockopen($server, $port))) + { + fputs($fsk, "$ip\r\n"); + while (!feof($fsk)) + { + $buffer .= fgets($fsk, 1024); + } + @fclose($fsk); + } + + // Use the result from ARIN if we don't get any result here + $ipwhois = (empty($buffer)) ? $ipwhois : $buffer; } $ipwhois = htmlspecialchars($ipwhois); @@ -1414,7 +1436,7 @@ function validate_username($username, $allowed_username = false) } else if ($mbstring) { - $regex = '[-\]_+ [[:upper:][:lower:][:digit:]]+'; + $regex = '[-\]_+ \[[:upper:][:lower:][:digit:]]+'; } else { @@ -1439,8 +1461,7 @@ function validate_username($username, $allowed_username = false) } else if ($mbstring) { - $matches = array(); - mb_ereg_search_init('^' . $username . '$', $regex, $matches); + mb_ereg_search_init($username, '^' . $regex . '$'); if (!mb_ereg_search()) { return 'INVALID_CHARS'; @@ -2713,9 +2734,16 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, */ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) { - global $db, $auth; + global $db, $auth, $config; - $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS'); + if ($config['coppa_enable']) + { + $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS'); + } + else + { + $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED', 'BOTS', 'GUESTS'); + } // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); @@ -2779,13 +2807,14 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $temp_ary = array(); while ($row = $db->sql_fetchrow($result)) { - if ($default_groups[$row['user_id']] == $group_id && (!isset($temp_ary[$row['user_id']]) || array_search($row['group_name'], $group_order) < $temp_ary[$row['user_id']])) + if ($default_groups[$row['user_id']] == $group_id && (!isset($temp_ary[$row['user_id']]) || $group_order_id[$row['group_name']] < $temp_ary[$row['user_id']])) { $temp_ary[$row['user_id']] = $row['group_id']; } } $db->sql_freeresult($result); + // sql_where_ary holds the new default groups and their users $sql_where_ary = array(); foreach ($temp_ary as $uid => $gid) { @@ -2797,7 +2826,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, { if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid])) { - remove_default_rank($group_id, $sql_where_ary[$gid]); + remove_default_rank($gid, $sql_where_ary[$gid]); remove_default_avatar($group_id, $sql_where_ary[$gid]); group_set_user_default($gid, $sql_where_ary[$gid], $default_data_ary); } diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 8fafb232cc..0dfe3b0086 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -594,44 +594,67 @@ function mcp_move_topic($topic_ids) $topic_data = get_topic_data($topic_ids); $leave_shadow = (isset($_POST['move_leave_shadow'])) ? true : false; - $topics_moved = sizeof($topic_ids); - $topics_authed_moved = 0; $forum_sync_data = array(); $forum_sync_data[$forum_id] = current($topic_data); $forum_sync_data[$to_forum_id] = $forum_data; + // Real topics added to target forum + $topics_moved = sizeof($topic_data); + + // Approved topics added to target forum + $topics_authed_moved = 0; + + // Posts (topic replies + topic post if approved) added to target forum + $topic_posts_added = 0; + + // Posts (topic replies + topic post if approved and not global announcement) removed from source forum + $topic_posts_removed = 0; + + // Real topics removed from source forum (all topics without global announcements) + $topics_removed = 0; + + // Approved topics removed from source forum (except global announcements) + $topics_authed_removed = 0; + foreach ($topic_data as $topic_id => $topic_info) { - if ($topic_info['topic_approved'] == '1') + if ($topic_info['topic_approved']) { $topics_authed_moved++; + $topic_posts_added++; + } + + $topic_posts_added += $topic_info['topic_replies']; + + if ($topic_info['topic_type'] != POST_GLOBAL) + { + $topics_removed++; + $topic_posts_removed += $topic_info['topic_replies']; + + if ($topic_info['topic_approved']) + { + $topics_authed_removed++; + $topic_posts_removed++; + } } } $db->sql_transaction('begin'); - $sql = 'SELECT SUM(t.topic_replies + t.topic_approved) as topic_posts - FROM ' . TOPICS_TABLE . ' t - WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids); - $result = $db->sql_query($sql); - $row_data = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - $sync_sql = array(); - if ($row_data['topic_posts']) + if ($topic_posts_added) { - $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . (int) $row_data['topic_posts']; - $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . (int) $row_data['topic_posts']; + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $topic_posts_added; } if ($topics_authed_moved) { - $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $topics_authed_moved; + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $topics_authed_moved; } - $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) $topics_moved; + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) $topics_moved; // Move topics, but do not resync yet move_topics($topic_ids, $to_forum_id, false); @@ -692,17 +715,26 @@ function mcp_move_topic($topic_ids) $db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow)); - $topics_authed_moved--; - $topics_moved--; + // Shadow topics only count on new "topics" and not posts... a shadow topic alone has 0 posts + $topics_removed--; + $topics_authed_removed--; } } unset($topic_data); - $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) $topics_moved; - - if ($topics_authed_moved) + if ($topic_posts_removed) { - $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $topics_authed_moved; + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . $topic_posts_removed; + } + + if ($topics_removed) + { + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) $topics_removed; + } + + if ($topics_authed_removed) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $topics_authed_removed; } $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; @@ -929,6 +961,11 @@ function mcp_delete_post($post_ids) } else { + if ($affected_topics != 1 || $deleted_topics || !$topic_id) + { + $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", false); + } + meta_refresh(3, $redirect); trigger_error($success_msg . '

          ' . sprintf($user->lang['RETURN_PAGE'], '', '') . '

          ' . implode('

          ', $return_link)); } @@ -1189,8 +1226,8 @@ function mcp_fork_topic($topic_ids) } sync('forum', 'forum_id', $to_forum_id); - set_config('num_topics', $config['num_topics'] + sizeof($new_topic_id_list), true); - set_config('num_posts', $config['num_posts'] + $total_posts, true); + set_config_count('num_topics', sizeof($new_topic_id_list), true); + set_config_count('num_posts', $total_posts, true); foreach ($new_topic_id_list as $topic_id => $new_topic_id) { diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index 42a64055ce..7480b24a46 100644 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -226,13 +226,16 @@ class mcp_notes 'PAGINATION' => generate_pagination($this->u_action . "&st=$st&sk=$sk&sd=$sd", $log_count, $config['posts_per_page'], $start), 'TOTAL_REPORTS' => ($log_count == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $log_count), - 'USERNAME' => $userrow['username'], - 'USER_COLOR' => (!empty($userrow['user_colour'])) ? $userrow['user_colour'] : '', 'RANK_TITLE' => $rank_title, 'JOINED' => $user->format_date($userrow['user_regdate']), 'POSTS' => ($userrow['user_posts']) ? $userrow['user_posts'] : 0, 'WARNINGS' => ($userrow['user_warnings']) ? $userrow['user_warnings'] : 0, + 'USERNAME_FULL' => get_username_string('full', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'USERNAME_COLOUR' => get_username_string('colour', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'USERNAME' => get_username_string('username', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'U_PROFILE' => get_username_string('profile', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'AVATAR_IMG' => $avatar_img, 'RANK_IMG' => $rank_img, ) diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index aa77dbdf16..6209a27bf7 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -492,12 +492,18 @@ 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(); + $user_posts_sql = $post_approved_list = array(); $update_forum_information = false; foreach ($post_info as $post_id => $post_data) { + if ($post_data['post_approved']) + { + $post_approved_list[] = $post_id; + continue; + } + $topic_id_list[$post_data['topic_id']] = 1; if ($post_data['forum_id']) @@ -539,12 +545,6 @@ function approve_post($post_id_list, $id, $mode) } else { - if (!isset($topic_replies_sql[$post_data['topic_id']])) - { - $topic_replies_sql[$post_data['topic_id']] = 0; - } - $topic_replies_sql[$post_data['topic_id']]++; - $approve_log[] = array( 'type' => 'post', 'post_subject' => $post_data['post_subject'], @@ -553,6 +553,15 @@ function approve_post($post_id_list, $id, $mode) ); } + if ($post_data['topic_replies_real'] > 0) + { + if (!isset($topic_replies_sql[$post_data['topic_id']])) + { + $topic_replies_sql[$post_data['topic_id']] = 0; + } + $topic_replies_sql[$post_data['topic_id']]++; + } + if ($post_data['forum_id']) { if (!isset($forum_topics_posts[$post_data['forum_id']])) @@ -583,6 +592,11 @@ function approve_post($post_id_list, $id, $mode) $update_forum_information = true; } } + $post_id_list = array_values(array_diff($post_id_list, $post_approved_list)); + for ($i = 0, $size = sizeof($post_approved_list); $i < $size; $i++) + { + unset($post_info[$post_approved_list[$i]]); + } if (sizeof($topic_approve_sql)) { @@ -652,12 +666,12 @@ function approve_post($post_id_list, $id, $mode) if ($total_topics) { - set_config('num_topics', $config['num_topics'] + $total_topics, true); + set_config_count('num_topics', $total_topics, true); } if ($total_posts) { - set_config('num_posts', $config['num_posts'] + $total_posts, true); + set_config_count('num_posts', $total_posts, true); } unset($topic_approve_sql, $topic_replies_sql, $post_approve_sql); @@ -733,7 +747,7 @@ function approve_post($post_id_list, $id, $mode) } else { - $success_msg = (sizeof($post_id_list) == 1) ? 'POST_APPROVED_SUCCESS' : 'POSTS_APPROVED_SUCCESS'; + $success_msg = (sizeof($post_id_list) + sizeof($post_approved_list) == 1) ? 'POST_APPROVED_SUCCESS' : 'POSTS_APPROVED_SUCCESS'; } } else diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 931300897e..576d20b466 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -501,7 +501,7 @@ 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); + set_config_count('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 bf0e66dc67..4ce67e5f9b 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -420,13 +420,16 @@ class mcp_warn $template->assign_vars(array( 'U_POST_ACTION' => $this->u_action, - 'USERNAME' => $user_row['username'], - 'USER_COLOR' => (!empty($user_row['user_colour'])) ? $user_row['user_colour'] : '', 'RANK_TITLE' => $rank_title, 'JOINED' => $user->format_date($user_row['user_regdate']), 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, + 'USERNAME_FULL' => get_username_string('full', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'USERNAME_COLOUR' => get_username_string('colour', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'USERNAME' => get_username_string('username', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'U_PROFILE' => get_username_string('profile', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'AVATAR_IMG' => $avatar_img, 'RANK_IMG' => $rank_img, diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 4e350bce99..ab6fc3f4f3 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -695,6 +695,7 @@ class bbcode_firstpass extends bbcode * [quote="[i]test[/i]"]test[/quote] (correct: parsed) * [quote="[quote]test[/quote]"]test[/quote] (correct: parsed - Username displayed as [quote]test[/quote]) * #20735 - [quote]test[/[/b]quote] test [/quote][/quote] test - (correct: quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted) + * #40565 - [quote="a"]a[/quote][quote="a]a[/quote] (correct: first quote tag parsed, second quote tag unparsed) */ $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in))); @@ -705,7 +706,7 @@ class bbcode_firstpass extends bbcode } // To let the parser not catch tokens within quote_username quotes we encode them before we start this... - $in = preg_replace('#quote="(.*?)"\]#ie', "'quote="' . str_replace(array('[', ']'), array('[', ']'), '\$1') . '"]'", $in); + $in = preg_replace('#quote="(.*?)"\]#ie', "'quote="' . str_replace(array('[', ']', '\\\"'), array('[', ']', '\"'), '\$1') . '"]'", $in); $tok = ']'; $out = '['; @@ -858,6 +859,8 @@ class bbcode_firstpass extends bbcode } while ($in); + $out .= $buffer; + if (sizeof($close_tags)) { $out .= '[' . implode('][', $close_tags) . ']'; @@ -1049,11 +1052,7 @@ class parse_message extends bbcode_firstpass { // Init BBCode UID $this->bbcode_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); - - if ($message) - { - $this->message = $message; - } + $this->message = $message; } /** @@ -1102,13 +1101,6 @@ class parse_message extends bbcode_firstpass } } - // Check for "empty" message - if ($mode !== 'sig' && utf8_clean_string($this->message) === '') - { - $this->warn_msg[] = $user->lang['TOO_FEW_CHARS']; - return (!$update_this_message) ? $return_message : $this->warn_msg; - } - // Prepare BBcode (just prepares some tags for better parsing) if ($allow_bbcode && strpos($this->message, '[') !== false) { @@ -1151,6 +1143,14 @@ class parse_message extends bbcode_firstpass } } + // Check for "empty" message. We do not check here for maximum length, because bbcode, smilies, etc. can add to the length. + // The maximum length check happened before any parsings. + if ($mode !== 'sig' && utf8_clean_string($this->message) === '') + { + $this->warn_msg[] = $user->lang['TOO_FEW_CHARS']; + return (!$update_this_message) ? $return_message : $this->warn_msg; + } + // Check number of links if ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls']) { diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index 2a67b58246..e1e7951367 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -118,7 +118,7 @@ class fulltext_mysql extends search_backend */ function split_keywords(&$keywords, $terms) { - global $config; + global $config, $user; if ($terms == 'all') { @@ -167,6 +167,12 @@ class fulltext_mysql extends search_backend $this->split_words = $matches[1]; } + // We limit the number of allowed keywords to minimize load on the database + if ($config['max_num_search_keywords'] && sizeof($this->split_words) > $config['max_num_search_keywords']) + { + trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $config['max_num_search_keywords'], sizeof($this->split_words))); + } + // to allow phrase search, we need to concatenate quoted words $tmp_split_words = array(); $phrase = ''; diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index 1c6a64d07c..8df5ddfbae 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -81,7 +81,7 @@ class fulltext_native extends search_backend */ function split_keywords($keywords, $terms) { - global $db, $user; + global $db, $user, $config; $keywords = trim($this->cleanup($keywords, '+-|()*')); @@ -167,6 +167,13 @@ class fulltext_native extends search_backend ); $keywords = preg_replace($match, $replace, $keywords); + $num_keywords = sizeof(explode(' ', $keywords)); + + // We limit the number of allowed keywords to minimize load on the database + if ($config['max_num_search_keywords'] && $num_keywords > $config['max_num_search_keywords']) + { + trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $config['max_num_search_keywords'], $num_keywords)); + } // $keywords input format: each word separated by a space, words in a bracket are not separated @@ -638,13 +645,21 @@ class fulltext_native extends search_backend $sql = ''; $sql_array_count = $sql_array; + if ($left_join_topics) + { + $sql_array_count['LEFT_JOIN'][] = array( + 'FROM' => array(TOPICS_TABLE => 't'), + 'ON' => 'p.topic_id = t.topic_id' + ); + } + switch ($db->sql_layer) { case 'mysql4': case 'mysqli': // 3.x does not support SQL_CALC_FOUND_ROWS - $sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT']; + // $sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT']; $is_mysql = true; break; @@ -693,10 +708,10 @@ class fulltext_native extends search_backend $sql_where[] = 'f.forum_id = p.forum_id'; break; } - + if ($left_join_topics) { - $sql_array['LEFT_JOIN'][$left_join_topics] = array( + $sql_array['LEFT_JOIN'][] = array( 'FROM' => array(TOPICS_TABLE => 't'), 'ON' => 'p.topic_id = t.topic_id' ); @@ -725,6 +740,16 @@ class fulltext_native extends search_backend // if we use mysql and the total result count is not cached yet, retrieve it from the db if (!$total_results && $is_mysql) { + // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it. + $sql_array_copy = $sql_array; + $sql_array_copy['SELECT'] = 'SQL_CALC_FOUND_ROWS p.post_id '; + + $sql = $db->sql_build_query('SELECT', $sql_array_copy); + unset($sql_array_copy); + + $db->sql_query($sql); + $db->sql_freeresult($result); + $sql = 'SELECT FOUND_ROWS() as total_results'; $result = $db->sql_query($sql); $total_results = (int) $db->sql_fetchfield('total_results'); @@ -848,7 +873,7 @@ class fulltext_native extends search_backend { case 'mysql4': case 'mysqli': - $select = 'SQL_CALC_FOUND_ROWS ' . $select; +// $select = 'SQL_CALC_FOUND_ROWS ' . $select; $is_mysql = true; break; @@ -941,6 +966,12 @@ class fulltext_native extends search_backend if (!$total_results && $is_mysql) { + // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it. + $sql = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql); + + $db->sql_query($sql); + $db->sql_freeresult($result); + $sql = 'SELECT FOUND_ROWS() as total_results'; $result = $db->sql_query($sql); $total_results = (int) $db->sql_fetchfield('total_results'); @@ -1110,7 +1141,7 @@ class fulltext_native extends search_backend // Get unique words from the above arrays $unique_add_words = array_unique(array_merge($words['add']['post'], $words['add']['title'])); - + // We now have unique arrays of all words to be added and removed and // individual arrays of added and removed words for text and title. What // we need to do now is add the new words (if they don't already exist) diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index c7d287181b..043a637584 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -182,7 +182,7 @@ class session else { // Set to OS hostname or localhost - $host = (function_exists('php_uname')) ? php_uname('n') : 'localhost'; + $host = (function_exists('php_uname')) ? gethostbyaddr(gethostbyname(php_uname('n'))) : 'localhost'; } } @@ -480,6 +480,13 @@ class session foreach (explode(',', $row['bot_ip']) as $bot_ip) { + $bot_ip = trim($bot_ip); + + if (!$bot_ip) + { + continue; + } + if (strpos($this->ip, $bot_ip) === 0) { $bot = (int) $row['user_id']; @@ -719,6 +726,15 @@ class session // Commented out because it will not allow forums to update correctly // $db->sql_return_on_error(false); + // Something quite important: session_page always holds the *last* page visited, except for the *first* visit. + // We are not able to simply have an empty session_page btw, therefore we need to tell phpBB how to detect this special case. + // If the session id is empty, we have a completely new one and will set an "identifier" here. This identifier is able to be checked later. + if (empty($this->data['session_id'])) + { + // This is a temporary variable, only set for the very first visit + $this->data['session_created'] = true; + } + $this->session_id = $this->data['session_id'] = md5(unique_id()); $sql_ary['session_id'] = (string) $this->session_id; @@ -1204,7 +1220,7 @@ class session } $dnsbl_check = array( - 'sbl-xbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=', + 'sbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=', ); if ($mode == 'register') @@ -1377,7 +1393,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) && (!$config['force_server'] || !(stripos($ref, $config['server_name']) === 0))) { return false; } @@ -1527,7 +1543,10 @@ 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 . $this->lang_name . "/common.$phpEx") === false) + // Do not suppress error if in DEBUG_EXTRA mode + $include_result = (defined('DEBUG_EXTRA')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx"); + + if ($include_result === false) { die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); } @@ -1657,7 +1676,8 @@ class user extends session $this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang']; - $sql = 'SELECT image_name, image_filename, image_lang, image_height, image_width + // Same query in style.php + $sql = 'SELECT * FROM ' . STYLES_IMAGESET_DATA_TABLE . ' WHERE imageset_id = ' . $this->theme['imageset_id'] . " AND image_filename <> '' @@ -1773,7 +1793,10 @@ class user extends session // Is board disabled and user not an admin or moderator? if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) { - header('HTTP/1.1 503 Service Unavailable'); + if ($this->data['is_bot']) + { + header('HTTP/1.1 503 Service Unavailable'); + } $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE'; trigger_error($message); @@ -1789,7 +1812,10 @@ class user extends session if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) { - header('HTTP/1.1 503 Service Unavailable'); + if ($this->data['is_bot']) + { + header('HTTP/1.1 503 Service Unavailable'); + } trigger_error('BOARD_UNAVAILABLE'); } } @@ -2000,7 +2026,10 @@ class user extends session $language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx; } - if ((@include $language_filename) === false) + // Do not suppress error if in DEBUG_EXTRA mode + $include_result = (defined('DEBUG_EXTRA')) ? (include $language_filename) : (@include $language_filename); + + if ($include_result === false) { trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); } @@ -2036,7 +2065,6 @@ class user extends session // Is the user requesting a friendly date format (i.e. 'Today 12:42')? $date_cache[$format] = array( 'is_short' => strpos($format, '|'), - 'zone_offset' => $this->timezone + $this->dst, 'format_short' => substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1), 'format_long' => str_replace('|', '', $format), 'lang' => $this->lang['datetime'], @@ -2049,8 +2077,11 @@ class user extends session } } + // Zone offset + $zone_offset = $this->timezone + $this->dst; + // Show date <= 1 hour ago as 'xx min ago' - // A small tolerence is given for times in the future and times in the future but in the same minute are displayed as '< than a minute ago' + // A small tolerence is given for times in the future but in the same minute are displayed as '< than a minute ago' if ($delta <= 3600 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO'])) { return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60))); @@ -2058,11 +2089,11 @@ class user extends session if (!$midnight) { - list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $date_cache[$format]['zone_offset'])); - $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $date_cache[$format]['zone_offset']; + list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset)); + $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset; } - if ($date_cache[$format]['is_short'] !== false && !$forcedate) + if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800)) { $day = false; @@ -2081,11 +2112,11 @@ class user extends session if ($day !== false) { - return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $date_cache[$format]['zone_offset']), $date_cache[$format]['lang'])); + return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $zone_offset), $date_cache[$format]['lang'])); } } - return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $date_cache[$format]['zone_offset']), $date_cache[$format]['lang']); + return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']); } /** @@ -2155,7 +2186,7 @@ class user extends session return $img_data; } - $img_data['src'] = $phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename']; + $img_data['src'] = $phpbb_root_path . 'styles/' . rawurlencode($this->theme['imageset_path']) . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename']; $img_data['width'] = $this->img_array[$img]['image_width']; $img_data['height'] = $this->img_array[$img]['image_height']; } diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index ad9dcc3659..36ab8a0e9b 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -56,6 +56,17 @@ class ucp_activate trigger_error('WRONG_ACTIVATION'); } + // Do not allow activating by non administrators when admin activation is on + // Only activation type the user should be able to do is INACTIVE_REMIND + if ($user_row['user_inactive_reason'] != INACTIVE_REMIND && $config['require_activation'] == USER_ACTIVATION_ADMIN && !$auth->acl_get('a_user')) + { + if (!$user->data['is_registered']) + { + login_box('', $user->lang['NO_AUTH_OPERATION']); + } + trigger_error('NO_AUTH_OPERATION'); + } + $update_password = ($user_row['user_newpasswd']) ? true : false; if ($update_password) @@ -72,6 +83,8 @@ class ucp_activate SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $user_row['user_id']; $db->sql_query($sql); + + add_log('user', $user_row['user_id'], 'LOG_USER_NEW_PASSWORD', $user_row['username']); } if (!$update_password) diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php index 5685702de2..b011b4f75d 100644 --- a/phpBB/includes/ucp/ucp_attachments.php +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -184,7 +184,7 @@ class ucp_attachments 'U_SORT_FILESIZE' => $this->u_action . "&sk=d&sd=" . (($sort_key == 'd' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_DOWNLOADS' => $this->u_action . "&sk=e&sd=" . (($sort_key == 'e' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_POST_TIME' => $this->u_action . "&sk=f&sd=" . (($sort_key == 'f' && $sort_dir == 'a') ? 'd' : 'a'), - 'U_SORT_TOPIC_TITLE' => $this->u_action . "&sk=g&sd=" . (($sort_key == 'f' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_TOPIC_TITLE' => $this->u_action . "&sk=g&sd=" . (($sort_key == 'g' && $sort_dir == 'a') ? 'd' : 'a'), 'S_DISPLAY_MARK_ALL' => ($num_attachments) ? true : false, 'S_DISPLAY_PAGINATION' => ($num_attachments) ? true : false, diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index db3dbc5cac..4e40f0a2a3 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -340,7 +340,7 @@ class ucp_groups 'S_ROW_COUNT' => ${$block . '_count'}++) ); - $group_id_ary[] = $row['group_id']; + $group_id_ary[] = (int) $row['group_id']; } $db->sql_freeresult($result); diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 6f4e525b2f..6ac2412ef0 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -633,11 +633,14 @@ class ucp_main */ function assign_topiclist($mode = 'subscribed', $forbidden_forum_ary = array()) { - global $user, $db, $template, $config, $auth, $phpbb_root_path, $phpEx; + global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx; $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE; $start = request_var('start', 0); + // Grab icons + $icons = $cache->obtain_icons(); + $sql_array = array( 'SELECT' => 'COUNT(t.topic_id) as topics_count', @@ -776,7 +779,8 @@ class ucp_main $folder_img = $folder_alt = $topic_type = ''; topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); - $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id"); + $view_topic_url_params = "f=$forum_id&t=$topic_id"; + $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params); // Send vars to template $template->assign_block_vars('topicrow', array( @@ -809,6 +813,7 @@ class ucp_main '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_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'] : '', @@ -818,8 +823,8 @@ class ucp_main 'S_USER_POSTED' => (!empty($row['topic_posted'])) ? true : false, 'S_UNREAD_TOPIC' => $unread_topic, - 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&view=unread") . '#unread', - 'U_LAST_POST' => $view_topic_url . '&p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'], + 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread', + 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], 'U_VIEW_TOPIC' => $view_topic_url, 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), )); diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index d451e25be4..008d8d6c88 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -850,7 +850,7 @@ function compose_pm($id, $mode, $action) $forward_text = array(); $forward_text[] = $user->lang['FWD_ORIGINAL_MESSAGE']; $forward_text[] = sprintf($user->lang['FWD_SUBJECT'], censor_text($message_subject)); - $forward_text[] = sprintf($user->lang['FWD_DATE'], $user->format_date($message_time)); + $forward_text[] = sprintf($user->lang['FWD_DATE'], $user->format_date($message_time, false, true)); $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); $forward_text[] = sprintf($user->lang['FWD_TO'], implode(', ', $fwd_to_field['to'])); @@ -1039,6 +1039,7 @@ function compose_pm($id, $mode, $action) 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'URL_STATUS' => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + 'MAX_FONT_SIZE' => (int) $config['max_post_font_size'], 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), 'ERROR' => (sizeof($error)) ? implode('
          ', $error) : '', 'MAX_RECIPIENTS' => ($config['allow_mass_pm'] && ($auth->acl_get('u_masspm') || $auth->acl_get('u_masspm_group'))) ? $max_recipients : 0, @@ -1124,7 +1125,9 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove $group_list = request_var('group_list', array(0)); // Build usernames to add - $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '', true)) : array(); + $usernames = request_var('username', '', true); + $usernames = (empty($usernames)) ? array() : array($usernames); + $username_list = request_var('username_list', '', true); if ($username_list) { diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index 360912ae49..cb96b77754 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -328,7 +328,8 @@ function view_folder($id, $mode, $folder_id, $folder) $data[] = array( 'subject' => censor_text($row['message_subject']), 'sender' => $row['username'], - 'date' => $user->format_date($row['message_time']), + // ISO 8601 date. For PHP4 we are able to hardcode the timezone because $user->format_date() does not set it. + 'date' => $user->format_date($row['message_time'], (PHP_VERSION >= 5) ? 'c' : "Y-m-d\TH:i:s+00:00", true), 'to' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? $address[$message_id] : '', 'message' => $message_row['message_text'] ); @@ -502,7 +503,7 @@ function get_pm_from($folder_id, $folder, $user_id) 'PAGE_NUMBER' => on_page($pm_count, $config['topics_per_page'], $start), 'TOTAL_MESSAGES' => (($pm_count == 1) ? $user->lang['VIEW_PM_MESSAGE'] : sprintf($user->lang['VIEW_PM_MESSAGES'], $pm_count)), - 'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'PM_LOCKED') : $user->img('button_pm_new', 'POST_PM'), + 'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'POST_PM_LOCKED') : $user->img('button_pm_new', 'POST_NEW_PM'), 'L_NO_MESSAGES' => (!$auth->acl_get('u_sendpm')) ? $user->lang['POST_PM_LOCKED'] : $user->lang['NO_MESSAGES'], @@ -511,7 +512,7 @@ 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') : '', + '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" : '')), )); diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index bdd0e44ea8..5fef30056f 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -286,7 +286,7 @@ function get_user_information($user_id, $user_row) $update_time = $config['load_online_time'] * 60; if ($row) { - $user_row['online'] = (time() - $update_time < $row['online_time'] && ($row['viewonline'])) ? true : false; + $user_row['online'] = (time() - $update_time < $row['online_time'] && ($row['viewonline'] || $auth->acl_get('u_viewonline'))) ? true : false; } } diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 328d374e9a..30752d8c8a 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -349,11 +349,11 @@ class ucp_profile { $data['notify'] = $user->data['user_notify_type']; - if (!$config['jab_enable'] || !$data['jabber'] || !@extension_loaded('xml')) + if ($data['notify'] == NOTIFY_IM && (!$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; + $data['notify'] = NOTIFY_EMAIL; } $sql_ary = array( @@ -549,6 +549,7 @@ class ucp_profile 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + 'MAX_FONT_SIZE' => (int) $config['max_sig_font_size'], 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 315d24d47f..549f96c42d 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -37,12 +37,13 @@ class ucp_register include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); - $confirm_id = request_var('confirm_id', ''); - $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; - $agreed = (!empty($_POST['agreed'])) ? 1 : 0; - $submit = (isset($_POST['submit'])) ? true : false; - $change_lang = request_var('change_lang', ''); - $user_lang = request_var('lang', $user->lang_name); + $confirm_id = request_var('confirm_id', ''); + $confirm_refresh = (isset($_POST['confirm_refresh']) && $config['confirm_refresh']) ? ((!empty($_POST['confirm_refresh'])) ? 1 : 0) : false; + $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; + $agreed = (!empty($_POST['agreed'])) ? 1 : 0; + $submit = (isset($_POST['submit'])) ? true : false; + $change_lang = request_var('change_lang', ''); + $user_lang = request_var('lang', $user->lang_name); if ($agreed) { @@ -187,7 +188,7 @@ class ucp_register array('string', false, 6, 60), array('email')), 'email_confirm' => array('string', false, 6, 60), - 'confirm_code' => array('string', !$config['enable_confirm'], 5, 8), + 'confirm_code' => array('string', !$config['enable_confirm'], CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS), 'tz' => array('num', false, -14, 14), 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), )); @@ -448,7 +449,7 @@ class ucp_register if ($config['enable_confirm']) { - if ($change_lang) + if ($change_lang || $confirm_refresh) { $str = '&change_lang=' . $change_lang; $sql = 'SELECT code @@ -467,7 +468,7 @@ class ucp_register { $str = ''; } - if (!$change_lang || !$confirm_id) + if (!$change_lang || !$confirm_id || !$confirm_refresh) { $user->confirm_gc(CONFIRM_REG); @@ -484,7 +485,7 @@ class ucp_register trigger_error('TOO_MANY_REGISTERS'); } - $code = gen_rand_string(mt_rand(5, 8)); + $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); $confirm_id = md5(unique_id($user->ip)); $seed = hexdec(substr(unique_id(), 4, 10)); @@ -500,6 +501,24 @@ class ucp_register ); $db->sql_query($sql); } + else if ($confirm_refresh) + { + $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); + $confirm_id = md5(unique_id($user->ip)); + $seed = hexdec(substr(unique_id(), 4, 10)); + // compute $seed % 0x7fffffff + $seed -= 0x7fffffff * floor($seed / 0x7fffffff); + $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'confirm_type' => (int) CONFIRM_REG, + 'code' => (string) $code, + 'seed' => (int) $seed) . " + WHERE + confirm_id = '" . $db->sql_escape($confirm_id) . "' AND + session_id = '" . $db->sql_escape($session_id) . "' AND + confirm_type = " . (int) CONFIRM_REG + ); + $db->sql_query($sql); + } $confirm_image = ''; $s_hidden_fields .= ''; } @@ -534,6 +553,7 @@ class ucp_register 'S_LANG_OPTIONS' => language_select($data['lang']), 'S_TZ_OPTIONS' => tz_select($data['tz']), 'S_CONFIRM_CODE' => ($config['enable_confirm']) ? true : false, + 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false, 'S_COPPA' => $coppa, 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 48176a3989..cad494541b 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -133,6 +133,11 @@ class ucp_resend $messenger->to($row['user_email'], $row['username']); $messenger->im($row['user_jabber'], $row['username']); + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($user_row['username']), 'U_USER_DETAILS' => generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$user_row['user_id']}", @@ -146,7 +151,7 @@ class ucp_resend meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); - $message = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? $user->lang['ACIVATION_EMAIL_SENT_ADMIN'] : $user->lang['ACTIVATION_EMAIL_SENT']; + $message = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? $user->lang['ACTIVATION_EMAIL_SENT_ADMIN'] : $user->lang['ACTIVATION_EMAIL_SENT']; $message .= '

          ' . sprintf($user->lang['RETURN_INDEX'], '', ''); trigger_error($message); } diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 98bb2ecebe..805c67b92d 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -494,7 +494,7 @@ if (!$get_info) array('topic_moved_id', 0, ''), array('topic_type', 'topics.topic_type', 'phpbb_convert_topic_type'), array('topic_first_post_id', 'topics.topic_first_post_id', ''), - array('topic_last_view_time', 'posts.post_time', ''), + array('topic_last_view_time', 'posts.post_time', 'intval'), array('poll_title', 'vote_desc.vote_text', array('function1' => 'null_to_str', 'function2' => 'phpbb_set_encoding', 'function3' => 'utf8_htmlspecialchars')), array('poll_start', 'vote_desc.vote_start', 'null_to_zero'), array('poll_length', 'vote_desc.vote_length', 'null_to_zero'), @@ -865,7 +865,7 @@ if (!$get_info) array('user_regdate', 'users.user_regdate', ''), array('username', 'users.username', 'phpbb_set_default_encoding'), // recode to utf8 with default lang array('username_clean', 'users.username', array('function1' => 'phpbb_set_default_encoding', 'function2' => 'utf8_clean_string')), - array('user_password', 'users.user_password', ''), + array('user_password', 'users.user_password', 'phpbb_hash'), array('user_pass_convert', 1, ''), array('user_posts', 'users.user_posts', 'intval'), array('user_email', 'users.user_email', 'strtolower'), diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php index 6452296782..124bbe83ce 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 sprintf('%2d-%2d-%4d', gmdate('n', $birthday * 86400 + 1), gmdate('j', $birthday * 86400 + 1), gmdate('Y', $birthday * 86400 + 1)); + return sprintf('%2d-%2d-%4d', gmdate('j', $birthday * 86400 + 1), gmdate('n', $birthday * 86400 + 1), gmdate('Y', $birthday * 86400 + 1)); } } diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index fb37b62203..ee28799694 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -8,7 +8,10 @@ * */ -$updates_to_version = '3.0.4'; +$updates_to_version = '3.0.5-RC1'; + +// Enter any version to update from to test updates. The version within the db will not be updated. +$debug_from_version = false; // 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')) @@ -140,489 +143,24 @@ include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx); // Define some variables for the database update $inline_update = (request_var('type', 0)) ? true : false; -// Database column types mapping -$dbms_type_map = array( - 'mysql_41' => array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'mediumint(8) UNSIGNED', - 'UINT:' => 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'smallint(4) UNSIGNED', - 'BOOL' => 'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT' => 'text', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT' => 'text', - 'TEXT_UNI' => 'text', - 'MTEXT' => 'mediumtext', - 'MTEXT_UNI' => 'mediumtext', - 'TIMESTAMP' => 'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VCHAR_CI' => 'varchar(255)', - 'VARBINARY' => 'varbinary(255)', - ), +// To let set_config() calls succeed, we need to make the config array available globally +$config = array(); - 'mysql_40' => array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'mediumint(8) UNSIGNED', - 'UINT:' => 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'smallint(4) UNSIGNED', - 'BOOL' => 'tinyint(1) UNSIGNED', - 'VCHAR' => 'varbinary(255)', - 'VCHAR:' => 'varbinary(%d)', - 'CHAR:' => 'binary(%d)', - 'XSTEXT' => 'blob', - 'XSTEXT_UNI'=> 'blob', - 'STEXT' => 'blob', - 'STEXT_UNI' => 'blob', - 'TEXT' => 'blob', - 'TEXT_UNI' => 'blob', - 'MTEXT' => 'mediumblob', - 'MTEXT_UNI' => 'mediumblob', - 'TIMESTAMP' => 'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'VCHAR_UNI' => 'blob', - 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')), - 'VCHAR_CI' => 'blob', - 'VARBINARY' => 'varbinary(255)', - ), +$sql = 'SELECT * + FROM ' . CONFIG_TABLE; +$result = $db->sql_query($sql); - 'firebird' => array( - 'INT:' => 'INTEGER', - 'BINT' => 'DOUBLE PRECISION', - 'UINT' => 'INTEGER', - 'UINT:' => 'INTEGER', - 'TINT:' => 'INTEGER', - 'USINT' => 'INTEGER', - 'BOOL' => 'INTEGER', - 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE', - 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE', - 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE', - 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8', - 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'TIMESTAMP' => 'INTEGER', - 'DECIMAL' => 'DOUBLE PRECISION', - 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8', - 'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE', - ), - - 'mssql' => array( - 'INT:' => '[int]', - 'BINT' => '[float]', - 'UINT' => '[int]', - 'UINT:' => '[int]', - 'TINT:' => '[int]', - 'USINT' => '[int]', - 'BOOL' => '[int]', - 'VCHAR' => '[varchar] (255)', - 'VCHAR:' => '[varchar] (%d)', - 'CHAR:' => '[char] (%d)', - 'XSTEXT' => '[varchar] (1000)', - 'STEXT' => '[varchar] (3000)', - 'TEXT' => '[varchar] (8000)', - 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', - 'TIMESTAMP' => '[int]', - 'DECIMAL' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VCHAR_CI' => '[varchar] (255)', - 'VARBINARY' => '[varchar] (255)', - ), - - 'oracle' => array( - 'INT:' => 'number(%d)', - 'BINT' => 'number(20)', - 'UINT' => 'number(8)', - 'UINT:' => 'number(%d)', - 'TINT:' => 'number(%d)', - 'USINT' => 'number(4)', - 'BOOL' => 'number(1)', - 'VCHAR' => 'varchar2(255)', - 'VCHAR:' => 'varchar2(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar2(1000)', - 'STEXT' => 'varchar2(3000)', - 'TEXT' => 'clob', - 'MTEXT' => 'clob', - 'XSTEXT_UNI'=> 'varchar2(300)', - 'STEXT_UNI' => 'varchar2(765)', - 'TEXT_UNI' => 'clob', - 'MTEXT_UNI' => 'clob', - 'TIMESTAMP' => 'number(11)', - 'DECIMAL' => 'number(5, 2)', - 'VCHAR_UNI' => 'varchar2(765)', - 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')), - 'VCHAR_CI' => 'varchar2(255)', - 'VARBINARY' => 'raw(255)', - ), - - 'sqlite' => array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED', - 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED', - 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text(65535)', - 'STEXT' => 'text(65535)', - 'TEXT' => 'text(65535)', - 'MTEXT' => 'mediumtext(16777215)', - 'XSTEXT_UNI'=> 'text(65535)', - 'STEXT_UNI' => 'text(65535)', - 'TEXT_UNI' => 'text(65535)', - 'MTEXT_UNI' => 'mediumtext(16777215)', - 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VCHAR_CI' => 'varchar(255)', - 'VARBINARY' => 'blob', - ), - - 'postgres' => array( - 'INT:' => 'INT4', - 'BINT' => 'INT8', - 'UINT' => 'INT4', // unsigned - 'UINT:' => 'INT4', // unsigned - 'USINT' => 'INT2', // unsigned - 'BOOL' => 'INT2', // unsigned - 'TINT:' => 'INT2', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar(1000)', - 'STEXT' => 'varchar(3000)', - 'TEXT' => 'varchar(8000)', - 'MTEXT' => 'TEXT', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT_UNI' => 'varchar(4000)', - 'MTEXT_UNI' => 'TEXT', - 'TIMESTAMP' => 'INT4', // unsigned - 'DECIMAL' => 'decimal(5,2)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VCHAR_CI' => 'varchar_ci', - 'VARBINARY' => 'bytea', - ), -); - -// A list of types being unsigned for better reference in some db's -$unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); - -// Only an example, but also commented out -$database_update_info = array( - // Changes from 3.0.RC2 to the next version - '3.0.RC2' => array( - // Change the following columns - 'change_columns' => array( - BANLIST_TABLE => array( - 'ban_reason' => array('VCHAR_UNI', ''), - 'ban_give_reason' => array('VCHAR_UNI', ''), - ), - ), - ), - // Changes from 3.0.RC3 to the next version - '3.0.RC3' => array( - // Change the following columns - 'change_columns' => array( - BANLIST_TABLE => array( - 'ban_reason' => array('VCHAR_UNI', ''), - 'ban_give_reason' => array('VCHAR_UNI', ''), - ), - STYLES_TABLE => array( - 'style_id' => array('USINT', 0), - 'template_id' => array('USINT', 0), - 'theme_id' => array('USINT', 0), - 'imageset_id' => array('USINT', 0), - ), - STYLES_TEMPLATE_TABLE => array( - 'template_id' => array('USINT', 0), - ), - STYLES_TEMPLATE_DATA_TABLE => array( - 'template_id' => array('USINT', 0), - ), - STYLES_THEME_TABLE => array( - 'theme_id' => array('USINT', 0), - ), - STYLES_IMAGESET_TABLE => array( - 'imageset_id' => array('USINT', 0), - ), - STYLES_IMAGESET_DATA_TABLE => array( - 'imageset_id' => array('USINT', 0), - ), - USERS_TABLE => array( - 'user_style' => array('USINT', 0), - ), - FORUMS_TABLE => array( - 'forum_style' => array('USINT', 0), - ), - GROUPS_TABLE => array( - 'group_avatar_type' => array('TINT:2', 0), - 'group_avatar_width' => array('USINT', 0), - 'group_avatar_height' => array('USINT', 0), - ), - ), - ), - // Changes from 3.0.RC4 to the next version - '3.0.RC4' => array( - // Change the following columns - 'change_columns' => array( - STYLES_TABLE => array( - 'style_id' => array('USINT', NULL, 'auto_increment'), - 'template_id' => array('USINT', 0), - 'theme_id' => array('USINT', 0), - 'imageset_id' => array('USINT', 0), - ), - STYLES_TEMPLATE_TABLE => array( - 'template_id' => array('USINT', NULL, 'auto_increment'), - ), - STYLES_TEMPLATE_DATA_TABLE => array( - 'template_id' => array('USINT', 0), - ), - STYLES_THEME_TABLE => array( - 'theme_id' => array('USINT', NULL, 'auto_increment'), - ), - STYLES_IMAGESET_TABLE => array( - 'imageset_id' => array('USINT', NULL, 'auto_increment'), - ), - STYLES_IMAGESET_DATA_TABLE => array( - 'imageset_id' => array('USINT', 0), - ), - USERS_TABLE => array( - 'user_style' => array('USINT', 0), - ), - FORUMS_TABLE => array( - 'forum_style' => array('USINT', 0), - ), - GROUPS_TABLE => array( - 'group_avatar_width' => array('USINT', 0), - 'group_avatar_height' => array('USINT', 0), - ), - ), - ), - // Changes from 3.0.RC5 to the next version - '3.0.RC5' => array( - // Add the following columns - 'add_columns' => array( - USERS_TABLE => array( - 'user_form_salt' => array('VCHAR_UNI:32', ''), - ), - ), - // Change the following columns - 'change_columns' => array( - POSTS_TABLE => array( - 'bbcode_uid' => array('VCHAR:8', ''), - ), - PRIVMSGS_TABLE => array( - 'bbcode_uid' => array('VCHAR:8', ''), - ), - USERS_TABLE => array( - 'user_sig_bbcode_uid' => array('VCHAR:8', ''), - ), - ), - ), - // Changes from 3.0.RC6 to the next version - '3.0.RC6' => array( - // Change the following columns - 'change_columns' => array( - FORUMS_TABLE => array( - 'forum_desc_uid' => array('VCHAR:8', ''), - 'forum_rules_uid' => array('VCHAR:8', ''), - ), - GROUPS_TABLE => array( - 'group_desc_uid' => array('VCHAR:8', ''), - ), - USERS_TABLE => array( - 'user_newpasswd' => array('VCHAR_UNI:40', ''), - ), - ), - ), - // Changes from 3.0.RC8 to the next version - '3.0.RC8' => array( - // Change the following columns - 'change_columns' => array( - USERS_TABLE => array( - 'user_new_privmsg' => array('INT:4', 0), - 'user_unread_privmsg' => array('INT:4', 0), - ), - ), - ), - // Changes from 3.0.0 to the next version - '3.0.0' => array( - // Add the following columns - 'add_columns' => array( - FORUMS_TABLE => array( - 'display_subforum_list' => array('BOOL', 1), - ), - SESSIONS_TABLE => array( - 'session_forum_id' => array('UINT', 0), - ), - ), - 'add_index' => array( - SESSIONS_TABLE => array( - 'session_forum_id' => array('session_forum_id'), - ), - GROUPS_TABLE => array( - 'group_legend_name' => array('group_legend', 'group_name'), - ), - ), - 'drop_keys' => array( - GROUPS_TABLE => array('group_legend'), - ), - ), - // No changes from 3.0.1-RC1 to 3.0.1 - '3.0.1-RC1' => array(), - // No changes from 3.0.1 to 3.0.2-RC1 - '3.0.1' => array(), - // Changes from 3.0.2-RC1 to 3.0.2-RC2 - '3.0.2-RC1' => array( - 'change_columns' => array( - DRAFTS_TABLE => array( - 'draft_subject' => array('STEXT_UNI', ''), - ), - FORUMS_TABLE => array( - 'forum_last_post_subject' => array('STEXT_UNI', ''), - ), - POSTS_TABLE => array( - 'post_subject' => array('STEXT_UNI', '', 'true_sort'), - ), - PRIVMSGS_TABLE => array( - 'message_subject' => array('STEXT_UNI', ''), - ), - TOPICS_TABLE => array( - 'topic_title' => array('STEXT_UNI', '', 'true_sort'), - 'topic_last_post_subject' => array('STEXT_UNI', ''), - ), - ), - 'drop_keys' => array( - SESSIONS_TABLE => array('session_forum_id'), - ), - 'add_index' => array( - SESSIONS_TABLE => array( - 'session_fid' => array('session_forum_id'), - ), - ), - ), - // 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), - ), - ), - ), - - // No changes from 3.0.3-RC1 to 3.0.3 - '3.0.3-RC1' => array(), - - // Changes from 3.0.3 to 3.0.4-RC1 - '3.0.3' => array( - 'add_columns' => array( - PROFILE_FIELDS_TABLE => array( - 'field_show_profile' => array('BOOL', 0), - ), - ), - 'change_columns' => array( - STYLES_TABLE => array( - 'style_id' => array('UINT', NULL, 'auto_increment'), - 'template_id' => array('UINT', 0), - 'theme_id' => array('UINT', 0), - 'imageset_id' => array('UINT', 0), - ), - STYLES_IMAGESET_TABLE => array( - 'imageset_id' => array('UINT', NULL, 'auto_increment'), - ), - STYLES_IMAGESET_DATA_TABLE => array( - 'image_id' => array('UINT', NULL, 'auto_increment'), - 'imageset_id' => array('UINT', 0), - ), - STYLES_THEME_TABLE => array( - 'theme_id' => array('UINT', NULL, 'auto_increment'), - ), - STYLES_TEMPLATE_TABLE => array( - 'template_id' => array('UINT', NULL, 'auto_increment'), - ), - STYLES_TEMPLATE_DATA_TABLE => array( - 'template_id' => array('UINT', 0), - ), - FORUMS_TABLE => array( - 'forum_style' => array('USINT', 0), - ), - USERS_TABLE => array( - 'user_style' => array('UINT', 0), - ), - ), - ), - - // Changes from 3.0.4-RC1 to 3.0.4 - '3.0.4-RC1' => array(), -); - -// Determine mapping database type -switch ($db->sql_layer) +while ($row = $db->sql_fetchrow($result)) { - case 'mysql': - $map_dbms = 'mysql_40'; - break; - - case 'mysql4': - if (version_compare($db->sql_server_info(true), '4.1.3', '>=')) - { - $map_dbms = 'mysql_41'; - } - else - { - $map_dbms = 'mysql_40'; - } - break; - - case 'mysqli': - $map_dbms = 'mysql_41'; - break; - - case 'mssql': - case 'mssql_odbc': - $map_dbms = 'mssql'; - break; - - default: - $map_dbms = $db->sql_layer; - break; + $config[$row['config_name']] = $row['config_value']; } +$db->sql_freeresult($result); + +// We do not include DB Tools here, because we can not be sure the file is up-to-date ;) +// Instead, this file defines a clean db_tools version (we are also not able to provide a different file, else the database update will not work standalone) +$db_tools = new updater_db_tools($db, true); + +$database_update_info = database_update_info(); $error_ary = array(); $errored = false; @@ -654,7 +192,7 @@ header('Content-type: text/html; charset=UTF-8');
          -
          +

          @@ -663,22 +201,10 @@ header('Content-type: text/html; charset=UTF-8');

          :: sql_layer; ?>
          sql_query($sql); - -while ($row = $db->sql_fetchrow($result)) -{ - $config[$row['config_name']] = $row['config_value']; -} -$db->sql_freeresult($result); - -/*if ($debug_from_version !== false) +if ($debug_from_version !== false) { $config['version'] = $debug_from_version; -}*/ +} echo $lang['PREVIOUS_VERSION'] . ' :: ' . $config['version'] . '
          '; echo $lang['UPDATED_VERSION'] . ' :: ' . $updates_to_version . '

          '; @@ -687,464 +213,40 @@ $current_version = str_replace('rc', 'RC', strtolower($config['version'])); $latest_version = str_replace('rc', 'RC', strtolower($updates_to_version)); $orig_version = $config['version']; -// If the latest version and the current version are 'unequal', we will update the version_update_from, else we do not update anything. -if ($inline_update) +// Fill DB version +if (empty($config['dbms_version'])) { - if ($current_version !== $latest_version) - { - set_config('version_update_from', $orig_version); - } -} -else -{ - // If not called from the update script, we will actually remove the traces - $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'"); + set_config('dbms_version', $db->sql_server_info(true)); } -// Checks/Operations that have to be completed prior to starting the update itself -$exit = false; -if (version_compare($current_version, '3.0.RC8', '<=')) /* && $debug_from_version === false) */ +// MySQL update from MySQL 3.x/4.x to > 4.1.x required? +if ($db->sql_layer == 'mysql' || $db->sql_layer == 'mysql4' || $db->sql_layer == 'mysqli') { - // Define missing language entries... - if (!isset($lang['CLEANING_USERNAMES'])) - { - $lang = array_merge($lang, array( - 'CLEANING_USERNAMES' => 'Cleaning usernames', - 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.', - 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.', - 'USER_ACTIVE' => 'Active user', - 'USER_INACTIVE' => 'Inactive user', - 'BOT' => 'Spider/Robot', - 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s', - - 'DELETE_USER_REMOVE' => 'Delete user and remove posts', - 'DELETE_USER_RETAIN' => 'Delete user but keep posts', - 'EDIT_USERNAME' => 'Edit username', - 'KEEP_OLD_NAME' => 'Keep username', - 'NEW_USERNAME' => 'New username', - )); - } -?> -

          - -

          - -
          - - '')); - $new_usernames = request_var('new_usernames', array(0 => ''), true); - - // We need this file if someone wants to edit usernames. - include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); - - if (!class_exists('utf_new_normalizer')) - { - if (!file_exists($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx)) - { - global $lang; - trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/new_normalizer.' . $phpEx), E_USER_ERROR); - } - include($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx); - } - - // the admin decided to change some usernames - if (sizeof($modify_users) && $submit) - { - $sql = 'SELECT user_id, username, user_type - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', array_keys($modify_users)); - $result = $db->sql_query($sql); - - $users = 0; - while ($row = $db->sql_fetchrow($result)) - { - $users++; - $user_id = (int) $row['user_id']; - - if (isset($modify_users[$user_id])) - { - $row['action'] = $modify_users[$user_id]; - $modify_users[$user_id] = $row; - } - } - $db->sql_freeresult($result); - - // only if all ids really existed - if (sizeof($modify_users) == $users) - { - $user->data['user_id'] = ANONYMOUS; - include($phpbb_root_path . 'includes/functions_user.' . $phpEx); - foreach ($modify_users as $user_id => $row) - { - switch ($row['action']) - { - case 'edit': - if (isset($new_usernames[$user_id])) - { - $data = array('username' => utf8_new_normalize_nfc($new_usernames[$user_id])); - // Need to update config, forum, topic, posting, messages, etc. - if ($data['username'] != $row['username']) - { - $check_ary = array('username' => array( - array('string', false, $config['min_name_chars'], $config['max_name_chars']), - array('username'), - )); - // need a little trick for this to work properly - $user->data['username_clean'] = utf8_clean_string($data['username']) . 'a'; - $errors = validate_data($data, $check_ary); - - if ($errors) - { - include($phpbb_root_path . 'language/' . $language . '/ucp.' . $phpEx); - echo '
          '; - foreach ($errors as $error) - { - echo '

          ' . $lang[$error] . '

          '; - } - echo '
          '; - } - - if (!$errors) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', array( - 'username' => $data['username'], - 'username_clean' => utf8_clean_string($data['username']) - )) . ' - WHERE user_id = ' . $user_id; - $db->sql_query($sql); - - add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $row['username'], $data['username']); - user_update_name($row['username'], $data['username']); - } - } - } - break; - - case 'delete_retain': - case 'delete_remove': - if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER) - { - user_delete(substr($row['action'], 7), $user_id, $row['username']); - add_log('admin', 'LOG_USER_DELETED', $row['username']); - } - break; - } - } - } - } -?> - -

          -

          :: - -sql_query($sql); - $colliding_users = $found_names = array(); - $echos = 0; - + $column_type = ''; while ($row = $db->sql_fetchrow($result)) { - // Calculate the new clean name. If it differs from the old one we need - // to make sure there is no collision - $clean_name = utf8_new_clean_string($row['username']); + $field = strtolower($row['Field']); - if ($clean_name != $row['username_clean']) + if ($field == 'config_value') { - // Check if there would be a collission, if not put it up for changing - $user_id = (int) $row['user_id']; - - // If this clean name was not the result of another user already ... - if (!isset($found_names[$clean_name])) - { - // then we need to figure out whether there are any other users - // who already had this clean name with the old version - $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . ' - WHERE username_clean = \'' . $db->sql_escape($clean_name) . '\''; - $result2 = $db->sql_query($sql); - - $user_ids = array($user_id); - while ($row = $db->sql_fetchrow($result2)) - { - // For not trimmed entries this could happen, yes. ;) - if ($row['user_id'] == $user_id) - { - continue; - } - - // Make sure this clean name will still be the same with the - // new function. If it is, then we have to add it to the list - // of user ids for this clean name - if (utf8_new_clean_string($row['username']) == $clean_name) - { - $user_ids[] = (int) $row['user_id']; - } - } - $db->sql_freeresult($result2); - - // if we already found a collision save it - if (sizeof($user_ids) > 1) - { - $colliding_users[$clean_name] = $user_ids; - $found_names[$clean_name] = true; - } - else - { - // otherwise just mark this name as found - $found_names[$clean_name] = $user_id; - } - } - // Else, if we already found the username - else - { - // If the value in the found_names lookup table is only true ... - if ($found_names[$clean_name] === true) - { - // then the actual data was already added to $colliding_users - // and we only need to append the user_id - $colliding_users[$clean_name][] = $user_id; - } - else - { - // otherwise it still keeps the first user_id for this name - // and we need to move the data to $colliding_users, and set - // the value in the found_names lookup table to true, so - // following users will directly be appended to $colliding_users - $colliding_users[$clean_name] = array($found_names[$clean_name], $user_id); - $found_names[$clean_name] = true; - } - } + $column_type = strtolower($row['Type']); + break; } - - if (($echos % 1000) == 0) - { - echo '.'; - flush(); - } - $echos++; } $db->sql_freeresult($result); - _write_result(false, $errored, $error_ary); - - // now retrieve all information about the users and let the admin decide what to do - if (sizeof($colliding_users)) + // If column type is blob, but mysql version says we are on > 4.1.3, then the schema needs an update + if (strpos($column_type, 'blob') !== false && version_compare($db->sql_server_info(true), '4.1.3', '>=')) { - $exit = true; - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - include($phpbb_root_path . 'language/' . $language . '/memberlist.' . $phpEx); - include($phpbb_root_path . 'language/' . $language . '/acp/users.' . $phpEx); + echo '

          '; + echo '

          ' . $lang['ERROR'] . '


          '; - // link a few things to the correct place so we don't get any problems - $user->lang = &$lang; - $user->data['user_id'] = ANONYMOUS; - $user->date_format = $config['default_dateformat']; - - // a little trick to get all user_ids - $user_ids = call_user_func_array('array_merge', array_values($colliding_users)); - - $sql = 'SELECT session_user_id, MAX(session_time) AS session_time - FROM ' . SESSIONS_TABLE . ' - WHERE session_time >= ' . (time() - $config['session_length']) . ' - AND ' . $db->sql_in_set('session_user_id', $user_ids) . ' - GROUP BY session_user_id'; - $result = $db->sql_query($sql); - - $session_times = array(); - while ($row = $db->sql_fetchrow($result)) - { - $session_times[$row['session_user_id']] = $row['session_time']; - } - $db->sql_freeresult($result); - - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', $user_ids); - $result = $db->sql_query($sql); - - $users = array(); - while ($row = $db->sql_fetchrow($result)) - { - if (isset($session_times[$row['user_id']])) - { - $row['session_time'] = $session_times[$row['user_id']]; - } - else - { - $row['session_time'] = 0; - } - $users[(int) $row['user_id']] = $row; - } - $db->sql_freeresult($result); - unset($session_times); - - // now display a table with all users, some information about them and options - // for the admin: keep name, change name (with text input) or delete user - $u_action = "database_update.$phpEx?language=$language&type=$inline_update"; + echo '

          ' . sprintf($lang['MYSQL_SCHEMA_UPDATE_REQUIRED'], $config['dbms_version'], $db->sql_server_info(true)) . '

          '; ?> -

          - -

          - - - - $user_ids) - { -?> -
          - - - - - - - - - - - - - - - $user_id) - { - $row = $users[$user_id]; - - $rank_title = $rank_img = ''; - get_user_rank($row['user_rank'], $row['user_posts'], $rank_title, $rank_img, $rank_img_src); - - $last_visit = (!empty($row['session_time'])) ? $row['session_time'] : $row['user_lastvisit']; - - $info = ''; - switch ($row['user_type']) - { - case USER_INACTIVE: - $info .= $lang['USER_INACTIVE']; - break; - - case USER_IGNORE: - $info .= $lang['BOT']; - break; - - case USER_FOUNDER: - $info .= $lang['FOUNDER']; - break; - - default: - $info .= $lang['USER_ACTIVE']; - } - - if ($user_id == ANONYMOUS) - { - $info = $lang['GUEST']; - } -?> - - - - - - - - - - - -
          -
          - -
          format_date($row['user_regdate']) ?>format_date($last_visit); ?>  -
          -
          - -
          - - -
          - -
          -
          - -

          - -

          - -sql_in_set('user_id', array_values($found_names)); - $result = $db->sql_query($sql); - - $found_names = array(); - while ($row = $db->sql_fetchrow($result)) - { - $clean_name = utf8_new_clean_string($row['username']); - - if ($clean_name != $row['username_clean']) - { - $user_id = (int) $row['user_id']; - $found_names[$user_id] = $clean_name; - - // impossible unique clean name - $sql = 'UPDATE ' . USERS_TABLE . " - SET username_clean = ' {$user_id}' - WHERE user_id = {$user_id}"; - $db->sql_query($sql); - } - } - $db->sql_freeresult($result); - - foreach ($found_names as $user_id => $clean_name) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET username_clean = \'' . $db->sql_escape($clean_name) . '\' - WHERE user_id = ' . $user_id; - $db->sql_query($sql); - } - } - unset($found_names); - unset($colliding_users); -} - -if ($exit) -{ -?> -
          @@ -1159,14 +261,27 @@ if ($exit) - sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'"); +} + // Schema updates ?>

          @@ -1197,13 +312,6 @@ for ($i = 0; $i < sizeof($versions); $i++) continue; } -/* if ($debug_from_version !== false) - { - // Applying update schema for version array with key '$version' - // for version '$version' to '$next_version' - continue; - }*/ - if (!sizeof($schema_changes)) { continue; @@ -1211,89 +319,11 @@ for ($i = 0; $i < sizeof($versions); $i++) $no_updates = false; - // Change columns? - if (!empty($schema_changes['change_columns'])) - { - foreach ($schema_changes['change_columns'] as $table => $columns) - { - foreach ($columns as $column_name => $column_data) - { - sql_column_change($map_dbms, $table, $column_name, $column_data); - } - } - } + $statements = $db_tools->perform_schema_changes($schema_changes); - // Add columns? - if (!empty($schema_changes['add_columns'])) + foreach ($statements as $sql) { - foreach ($schema_changes['add_columns'] as $table => $columns) - { - foreach ($columns as $column_name => $column_data) - { - // Only add the column if it does not exist yet - if (!column_exists($map_dbms, $table, $column_name)) - { - sql_column_add($map_dbms, $table, $column_name, $column_data); - } - } - } - } - - // Remove keys? - if (!empty($schema_changes['drop_keys'])) - { - foreach ($schema_changes['drop_keys'] as $table => $indexes) - { - foreach ($indexes as $index_name) - { - sql_index_drop($map_dbms, $index_name, $table); - } - } - } - - // Drop columns? - if (!empty($schema_changes['drop_columns'])) - { - foreach ($schema_changes['drop_columns'] as $table => $columns) - { - foreach ($columns as $column) - { - sql_column_remove($map_dbms, $table, $column); - } - } - } - - // Add primary keys? - if (!empty($schema_changes['add_primary_keys'])) - { - foreach ($schema_changes['add_primary_keys'] as $table => $columns) - { - sql_create_primary_key($map_dbms, $table, $columns); - } - } - - // Add unqiue indexes? - if (!empty($schema_changes['add_unique_index'])) - { - foreach ($schema_changes['add_unique_index'] as $table => $index_array) - { - foreach ($index_array as $index_name => $column) - { - sql_create_unique_index($map_dbms, $index_name, $table, $column); - } - } - } - - // Add indexes? - if (!empty($schema_changes['add_index'])) - { - foreach ($schema_changes['add_index'] as $table => $index_array) - { - foreach ($index_array as $index_name => $column) - { - sql_create_index($map_dbms, $index_name, $table, $column); - } - } + _sql($sql, $errored, $error_ary); } } @@ -1329,13 +359,6 @@ for ($i = 0; $i < sizeof($versions); $i++) continue; } -/* if ($debug_from_version !== false) - { - // Applying update schema for version array with key '$version' - // for version '$version' to '$next_version' - continue; - }*/ - change_database_data($no_updates, $version); } @@ -1355,14 +378,14 @@ $errored = $no_updates = false; flush(); -//if ($debug_from_version === false) -// { - -// update the version -$sql = "UPDATE " . CONFIG_TABLE . " - SET config_value = '$updates_to_version' - WHERE config_name = 'version'"; -_sql($sql, $errored, $error_ary); +if ($debug_from_version === false) +{ + // update the version + $sql = "UPDATE " . CONFIG_TABLE . " + SET config_value = '$updates_to_version' + WHERE config_name = 'version'"; + _sql($sql, $errored, $error_ary); +} // Reset permissions $sql = 'UPDATE ' . USERS_TABLE . " @@ -1370,7 +393,8 @@ $sql = 'UPDATE ' . USERS_TABLE . " user_perm_from = 0"; _sql($sql, $errored, $error_ary); -// } +// Update the dbms version if everything is ok... +set_config('dbms_version', $db->sql_server_info(true)); /* Optimize/vacuum analyze the tables where appropriate // this should be done for each version in future along with @@ -1403,8 +427,6 @@ _write_result($no_updates, $errored, $error_ary); if (!$inline_update) { - // Purge the cache... - $cache->purge(); ?>

          @@ -1457,380 +479,215 @@ if (function_exists('exit_handler')) } /** -* Function where all data changes are executed +* Function for triggering an sql statement */ +function _sql($sql, &$errored, &$error_ary, $echo_dot = true) +{ + global $db; + + if (defined('DEBUG_EXTRA')) + { + echo "
          \n{$sql}\n
          "; + } + + $db->sql_return_on_error(true); + + $result = $db->sql_query($sql); + if ($db->sql_error_triggered) + { + $errored = true; + $error_ary['sql'][] = $db->sql_error_sql; + $error_ary['error_code'][] = $db->_sql_error(); + } + + $db->sql_return_on_error(false); + + if ($echo_dot) + { + echo ". \n"; + flush(); + } + + return $result; +} + +function _write_result($no_updates, $errored, $error_ary) +{ + global $lang; + + if ($no_updates) + { + echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '

          '; + } + else + { + echo ' ' . $lang['DONE'] . '
          ' . $lang['RESULT'] . ' :: '; + + if ($errored) + { + echo ' ' . $lang['SOME_QUERIES_FAILED'] . '
            '; + + for ($i = 0; $i < sizeof($error_ary['sql']); $i++) + { + echo '
          • ' . $lang['ERROR'] . ' :: ' . htmlspecialchars($error_ary['error_code'][$i]['message']) . '
            '; + echo $lang['SQL'] . ' :: ' . htmlspecialchars($error_ary['sql'][$i]) . '

          • '; + } + + echo '


          ' . $lang['SQL_FAILURE_EXPLAIN'] . '

          '; + } + else + { + echo '' . $lang['NO_ERRORS'] . '

          '; + } + } +} + +/**************************************************************************** +* ADD YOUR DATABASE SCHEMA CHANGES HERE * +*****************************************************************************/ +function database_update_info() +{ + return array( + // Changes from 3.0.0 to the next version + '3.0.0' => array( + // Add the following columns + 'add_columns' => array( + FORUMS_TABLE => array( + 'display_subforum_list' => array('BOOL', 1), + ), + SESSIONS_TABLE => array( + 'session_forum_id' => array('UINT', 0), + ), + ), + 'add_index' => array( + SESSIONS_TABLE => array( + 'session_forum_id' => array('session_forum_id'), + ), + GROUPS_TABLE => array( + 'group_legend_name' => array('group_legend', 'group_name'), + ), + ), + 'drop_keys' => array( + GROUPS_TABLE => array('group_legend'), + ), + ), + // No changes from 3.0.1-RC1 to 3.0.1 + '3.0.1-RC1' => array(), + // No changes from 3.0.1 to 3.0.2-RC1 + '3.0.1' => array(), + // Changes from 3.0.2-RC1 to 3.0.2-RC2 + '3.0.2-RC1' => array( + 'change_columns' => array( + DRAFTS_TABLE => array( + 'draft_subject' => array('STEXT_UNI', ''), + ), + FORUMS_TABLE => array( + 'forum_last_post_subject' => array('STEXT_UNI', ''), + ), + POSTS_TABLE => array( + 'post_subject' => array('STEXT_UNI', '', 'true_sort'), + ), + PRIVMSGS_TABLE => array( + 'message_subject' => array('STEXT_UNI', ''), + ), + TOPICS_TABLE => array( + 'topic_title' => array('STEXT_UNI', '', 'true_sort'), + 'topic_last_post_subject' => array('STEXT_UNI', ''), + ), + ), + 'drop_keys' => array( + SESSIONS_TABLE => array('session_forum_id'), + ), + 'add_index' => array( + SESSIONS_TABLE => array( + 'session_fid' => array('session_forum_id'), + ), + ), + ), + // 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), + ), + ), + ), + + // No changes from 3.0.3-RC1 to 3.0.3 + '3.0.3-RC1' => array(), + + // Changes from 3.0.3 to 3.0.4-RC1 + '3.0.3' => array( + 'add_columns' => array( + PROFILE_FIELDS_TABLE => array( + 'field_show_profile' => array('BOOL', 0), + ), + ), + 'change_columns' => array( + STYLES_TABLE => array( + 'style_id' => array('UINT', NULL, 'auto_increment'), + 'template_id' => array('UINT', 0), + 'theme_id' => array('UINT', 0), + 'imageset_id' => array('UINT', 0), + ), + STYLES_IMAGESET_TABLE => array( + 'imageset_id' => array('UINT', NULL, 'auto_increment'), + ), + STYLES_IMAGESET_DATA_TABLE => array( + 'image_id' => array('UINT', NULL, 'auto_increment'), + 'imageset_id' => array('UINT', 0), + ), + STYLES_THEME_TABLE => array( + 'theme_id' => array('UINT', NULL, 'auto_increment'), + ), + STYLES_TEMPLATE_TABLE => array( + 'template_id' => array('UINT', NULL, 'auto_increment'), + ), + STYLES_TEMPLATE_DATA_TABLE => array( + 'template_id' => array('UINT', 0), + ), + FORUMS_TABLE => array( + 'forum_style' => array('UINT', 0), + ), + USERS_TABLE => array( + 'user_style' => array('UINT', 0), + ), + ), + ), + + // Changes from 3.0.4-RC1 to 3.0.4 + '3.0.4-RC1' => array(), + + // Changes from 3.0.4 to 3.0.5-RC1 + '3.0.4' => array( + 'change_columns' => array( + FORUMS_TABLE => array( + 'forum_style' => array('UINT', 0), + ), + ), + ), + ); +} + +/**************************************************************************** +* ADD YOUR DATABASE DATA CHANGES HERE * +* REMEMBER: You NEED to enter a schema array above and a data array here, * +* even if both or one of them are empty. * +*****************************************************************************/ function change_database_data(&$no_updates, $version) { - global $db, $map_dbms, $errored, $error_ary, $config, $phpbb_root_path, $phpEx; + global $db, $errored, $error_ary, $config, $phpbb_root_path, $phpEx; switch ($version) { - case '3.0.RC2': - - $smileys = array(); - - $sql = 'SELECT smiley_id, code - FROM ' . SMILIES_TABLE; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $smileys[$row['smiley_id']] = $row['code']; - } - $db->sql_freeresult($result); - - foreach ($smileys as $id => $code) - { - // 2.0 only entitized lt and gt; We need to do something about double quotes. - if (strchr($code, '"') === false) - { - continue; - } - - $new_code = str_replace('&', '&', $code); - $new_code = str_replace('<', '<', $new_code); - $new_code = str_replace('>', '>', $new_code); - $new_code = utf8_htmlspecialchars($new_code); - - $sql = 'UPDATE ' . SMILIES_TABLE . ' - SET code = \'' . $db->sql_escape($new_code) . '\' - WHERE smiley_id = ' . (int) $id; - $db->sql_query($sql); - } - - $index_list = sql_list_index($map_dbms, ACL_ROLES_DATA_TABLE); - - if (in_array('ath_opt_id', $index_list)) - { - sql_index_drop($map_dbms, 'ath_opt_id', ACL_ROLES_DATA_TABLE); - sql_create_index($map_dbms, 'ath_op_id', ACL_ROLES_DATA_TABLE, array('auth_option_id')); - } - - $no_updates = false; - break; - - case '3.0.RC3': - - if ($map_dbms === 'postgres') - { - $sql = "SELECT SETVAL('" . FORUMS_TABLE . "_seq',(select case when max(forum_id)>0 then max(forum_id)+1 else 1 end from " . FORUMS_TABLE . '));'; - _sql($sql, $errored, $error_ary); - } - - // we check for: - // ath_opt_id - // ath_op_id - // ACL_ROLES_DATA_TABLE_ath_opt_id - // we want ACL_ROLES_DATA_TABLE_ath_op_id - - $table_index_fix = array( - ACL_ROLES_DATA_TABLE => array( - 'ath_opt_id' => 'ath_op_id', - 'ath_op_id' => 'ath_op_id', - ACL_ROLES_DATA_TABLE . '_ath_opt_id' => 'ath_op_id' - ), - STYLES_IMAGESET_DATA_TABLE => array( - 'i_id' => 'i_d', - 'i_d' => 'i_d', - STYLES_IMAGESET_DATA_TABLE . '_i_id' => 'i_d' - ) - ); - - // we need to create some indicies... - $needed_creation = array(); - - foreach ($table_index_fix as $table_name => $index_info) - { - $index_list = sql_list_fake($map_dbms, $table_name); - foreach ($index_info as $bad_index => $good_index) - { - if (in_array($bad_index, $index_list)) - { - // mysql is actually OK, it won't get a hand in this crud - switch ($map_dbms) - { - // last version, mssql had issues with index removal - case 'mssql': - $sql = 'DROP INDEX ' . $table_name . '.' . $bad_index; - _sql($sql, $errored, $error_ary); - break; - - // last version, firebird, oracle, postgresql and sqlite all got bad index names - // we got kinda lucky, tho: they all support the same syntax - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - $sql = 'DROP INDEX ' . $bad_index; - _sql($sql, $errored, $error_ary); - break; - } - - // If the good index already exist we do not need to create it again... - if (($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41') && $bad_index == $good_index) - { - } - else - { - $needed_creation[$table_name][$good_index] = 1; - } - } - } - } - - $new_index_defs = array('ath_op_id' => array('auth_option_id'), 'i_d' => array('imageset_id')); - - foreach ($needed_creation as $bad_table => $index_repair_list) - { - foreach ($index_repair_list as $new_index => $garbage) - { - sql_create_index($map_dbms, $new_index, $bad_table, $new_index_defs[$new_index]); - } - } - - // Make sure empty smiley codes do not exist - $sql = 'DELETE FROM ' . SMILIES_TABLE . " - WHERE code = ''"; - _sql($sql, $errored, $error_ary); - - set_config('allow_birthdays', '1'); - set_config('cron_lock', '0', true); - - $no_updates = false; - break; - - case '3.0.RC4': - - $update_auto_increment = array( - STYLES_TABLE => 'style_id', - STYLES_TEMPLATE_TABLE => 'template_id', - STYLES_THEME_TABLE => 'theme_id', - STYLES_IMAGESET_TABLE => 'imageset_id' - ); - - $sql = 'SELECT * - FROM ' . STYLES_TABLE . ' - WHERE style_id = 0'; - $result = _sql($sql, $errored, $error_ary); - $bad_style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($bad_style_row) - { - $sql = 'SELECT MAX(style_id) as max_id - FROM ' . STYLES_TABLE; - $result = _sql($sql, $errored, $error_ary); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $proper_id = $row['max_id'] + 1; - - _sql('UPDATE ' . STYLES_TABLE . " SET style_id = $proper_id WHERE style_id = 0", $errored, $error_ary); - _sql('UPDATE ' . FORUMS_TABLE . " SET forum_style = $proper_id WHERE forum_style = 0", $errored, $error_ary); - _sql('UPDATE ' . USERS_TABLE . " SET user_style = $proper_id WHERE user_style = 0", $errored, $error_ary); - - $sql = 'SELECT config_value - FROM ' . CONFIG_TABLE . " - WHERE config_name = 'default_style'"; - $result = _sql($sql, $errored, $error_ary); - $style_config = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($style_config['config_value'] === '0') - { - set_config('default_style', (string) $proper_id); - } - } - - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_TABLE . ' - WHERE template_id = 0'; - $result = _sql($sql, $errored, $error_ary); - $bad_style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($bad_style_row) - { - $sql = 'SELECT MAX(template_id) as max_id - FROM ' . STYLES_TEMPLATE_TABLE; - $result = _sql($sql, $errored, $error_ary); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $proper_id = $row['max_id'] + 1; - - _sql('UPDATE ' . STYLES_TABLE . " SET template_id = $proper_id WHERE template_id = 0", $errored, $error_ary); - } - - $sql = 'SELECT * - FROM ' . STYLES_THEME_TABLE . ' - WHERE theme_id = 0'; - $result = _sql($sql, $errored, $error_ary); - $bad_style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($bad_style_row) - { - $sql = 'SELECT MAX(theme_id) as max_id - FROM ' . STYLES_THEME_TABLE; - $result = _sql($sql, $errored, $error_ary); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $proper_id = $row['max_id'] + 1; - - _sql('UPDATE ' . STYLES_TABLE . " SET theme_id = $proper_id WHERE theme_id = 0", $errored, $error_ary); - } - - $sql = 'SELECT * - FROM ' . STYLES_IMAGESET_TABLE . ' - WHERE imageset_id = 0'; - $result = _sql($sql, $errored, $error_ary); - $bad_style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($bad_style_row) - { - $sql = 'SELECT MAX(imageset_id) as max_id - FROM ' . STYLES_IMAGESET_TABLE; - $result = _sql($sql, $errored, $error_ary); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $proper_id = $row['max_id'] + 1; - - _sql('UPDATE ' . STYLES_TABLE . " SET imageset_id = $proper_id WHERE imageset_id = 0", $errored, $error_ary); - _sql('UPDATE ' . STYLES_IMAGESET_DATA_TABLE . " SET imageset_id = $proper_id WHERE imageset_id = 0", $errored, $error_ary); - } - - if ($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41') - { - foreach ($update_auto_increment as $auto_table_name => $auto_column_name) - { - $sql = "SELECT MAX({$auto_column_name}) as max_id - FROM {$auto_table_name}"; - $result = _sql($sql, $errored, $error_ary); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $max_id = ((int) $row['max_id']) + 1; - _sql("ALTER TABLE {$auto_table_name} AUTO_INCREMENT = {$max_id}", $errored, $error_ary); - } - } - else if ($map_dbms == 'postgres') - { - foreach ($update_auto_increment as $auto_table_name => $auto_column_name) - { - $sql = "SELECT SETVAL('" . $auto_table_name . "_seq',(select case when max({$auto_column_name})>0 then max({$auto_column_name})+1 else 1 end from " . $auto_table_name . '));'; - _sql($sql, $errored, $error_ary); - } - - $sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq'; - _sql($sql, $errored, $error_ary); - } - else if ($map_dbms == 'firebird') - { - $sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE; - _sql($sql, $errored, $error_ary); - - $sql = 'DROP GENERATOR ' . STYLES_TEMPLATE_DATA_TABLE . '_gen'; - _sql($sql, $errored, $error_ary); - } - else if ($map_dbms == 'oracle') - { - $sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE; - _sql($sql, $errored, $error_ary); - - $sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq'; - _sql($sql, $errored, $error_ary); - } - else if ($map_dbms == 'mssql') - { - // we use transactions because we need to have a working DB at the end of all of this - $db->sql_transaction('begin'); - - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_DATA_TABLE; - $result = _sql($sql, $errored, $error_ary); - $old_style_rows = array(); - while ($row = $db->sql_fetchrow($result)) - { - $old_style_rows[] = $row; - } - $db->sql_freeresult($result); - - // death to the table, it is evil! - $sql = 'DROP TABLE ' . STYLES_TEMPLATE_DATA_TABLE; - _sql($sql, $errored, $error_ary); - - // the table of awesomeness, praise be to it (or something) - $sql = 'CREATE TABLE [' . STYLES_TEMPLATE_DATA_TABLE . "] ( - [template_id] [int] DEFAULT (0) NOT NULL , - [template_filename] [varchar] (100) DEFAULT ('') NOT NULL , - [template_included] [varchar] (8000) DEFAULT ('') NOT NULL , - [template_mtime] [int] DEFAULT (0) NOT NULL , - [template_data] [text] DEFAULT ('') NOT NULL - ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]"; - _sql($sql, $errored, $error_ary); - - // index? index - $sql = 'CREATE INDEX [tid] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_id]) ON [PRIMARY]'; - _sql($sql, $errored, $error_ary); - - // yet another index - $sql = 'CREATE INDEX [tfn] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_filename]) ON [PRIMARY]'; - _sql($sql, $errored, $error_ary); - - foreach ($old_style_rows as $return_row) - { - _sql('INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $return_row), $errored, $error_ary); - } - - $db->sql_transaction('commit'); - } - - // Setting this here again because new installations may not have it... - set_config('cron_lock', '0', true); - set_config('ldap_port', ''); - set_config('ldap_user_filter', ''); - - $no_updates = false; - break; - - case '3.0.RC5': - - // In case the user is having the bot mediapartner google "as is", adjust it. - $sql = 'UPDATE ' . BOTS_TABLE . " - SET bot_agent = '" . $db->sql_escape('Mediapartners-Google') . "' - WHERE bot_agent = '" . $db->sql_escape('Mediapartners-Google/') . "'"; - _sql($sql, $errored, $error_ary); - - set_config('form_token_lifetime', '7200'); - set_config('form_token_mintime', '0'); - set_config('min_time_reg', '5'); - set_config('min_time_terms', '2'); - set_config('form_token_sid_guests', '1'); - - $db->sql_transaction('begin'); - - $sql = 'SELECT forum_id, forum_password - FROM ' . FORUMS_TABLE; - $result = _sql($sql, $errored, $error_ary); - - while ($row = $db->sql_fetchrow($result)) - { - if (!empty($row['forum_password'])) - { - _sql('UPDATE ' . FORUMS_TABLE . " SET forum_password = '" . md5($row['forum_password']) . "' WHERE forum_id = {$row['forum_id']}", $errored, $error_ary); - } - } - $db->sql_freeresult($result); - - $db->sql_transaction('commit'); - - $no_updates = false; - break; - case '3.0.0': $sql = 'UPDATE ' . TOPICS_TABLE . " @@ -2028,482 +885,1265 @@ function change_database_data(&$no_updates, $version) _sql('UPDATE ' . PROFILE_FIELDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE field_id = ' . $row['field_id'], $errored, $error_ary); } - $no_updates = false; + break; // Changes from 3.0.4-RC1 to 3.0.4 case '3.0.4-RC1': break; + + // Changes from 3.0.4 to 3.0.5-RC1 + case '3.0.4': + + // Captcha config variables + set_config('captcha_gd_wave', 0); + set_config('captcha_gd_3d_noise', 1); + set_config('captcha_gd_fonts', 1); + + set_config('confirm_refresh', 1); + + // Maximum number of keywords + set_config('max_num_search_keywords', 10); + + // Remove static config var and put it back as dynamic variable + $sql = 'UPDATE ' . CONFIG_TABLE . " + SET is_dynamic = 1 + WHERE config_name = 'search_indexing_state'"; + _sql($sql, $errored, $error_ary); + + // Hash old MD5 passwords + $sql = 'SELECT user_id, user_password + FROM ' . USERS_TABLE . ' + WHERE user_pass_convert = 1'; + $result = _sql($sql, $errored, $error_ary); + + while ($row = $db->sql_fetchrow($result)) + { + if (strlen($row['user_password']) == 32) + { + $sql_ary = array( + 'user_password' => phpbb_hash($row['user_password']), + ); + + _sql('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $row['user_id'], $errored, $error_ary); + } + } + $db->sql_freeresult($result); + + // Adjust bot entry + $sql = 'UPDATE ' . BOTS_TABLE . " + SET bot_agent = 'ichiro/' + WHERE bot_agent = 'ichiro/2'"; + _sql($sql, $errored, $error_ary); + + // Before we are able to add a unique key to auth_option, we need to remove duplicate entries + + // We get duplicate entries first + $sql = 'SELECT auth_option + FROM ' . ACL_OPTIONS_TABLE . ' + GROUP BY auth_option + HAVING COUNT(*) >= 1'; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[] = $row['auth_option']; + } + $db->sql_freeresult($result); + + // Remove specific auth options + if (!empty($auth_options)) + { + foreach ($auth_options as $option) + { + // Select auth_option_ids... the largest id will be preserved + $sql = 'SELECT auth_option_id + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option = '" . $db->sql_escape($option) . "' + ORDER BY auth_option_id DESC"; + // sql_query_limit not possible here, due to bug in postgresql layer + $result = $db->sql_query($sql); + + // Skip first row, this is our original auth option we want to preserve + $row = $db->sql_fetchrow($result); + + while ($row = $db->sql_fetchrow($result)) + { + // Ok, remove this auth option... + _sql('DELETE FROM ' . ACL_OPTIONS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); + _sql('DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); + _sql('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); + _sql('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); + } + $db->sql_freeresult($result); + } + } + + // Now make auth_option UNIQUE, by dropping the old index and adding a UNIQUE one. + $changes = array( + 'drop_keys' => array( + ACL_OPTIONS_TABLE => array('auth_option'), + ), + 'add_unique_index' => array( + ACL_OPTIONS_TABLE => array( + 'auth_option' => array('auth_option'), + ), + ), + ); + + global $db_tools; + + $statements = $db_tools->perform_schema_changes($changes); + + foreach ($statements as $sql) + { + _sql($sql, $errored, $error_ary); + } + + $no_updates = false; + + break; } } + /** -* Function for triggering an sql statement +* Database Tools for handling cross-db actions such as altering columns, etc. +* Currently not supported is returning SQL for creating tables. +* +* @package dbal */ -function _sql($sql, &$errored, &$error_ary, $echo_dot = true) +class updater_db_tools { - global $db; + /** + * Current sql layer + */ + var $sql_layer = ''; - if (defined('DEBUG_EXTRA')) + /** + * @var object DB object + */ + var $db = NULL; + + /** + * The Column types for every database we support + * @var array + */ + var $dbms_type_map = array( + 'mysql_41' => array( + 'INT:' => 'int(%d)', + 'BINT' => 'bigint(20)', + 'UINT' => 'mediumint(8) UNSIGNED', + 'UINT:' => 'int(%d) UNSIGNED', + 'TINT:' => 'tinyint(%d)', + 'USINT' => 'smallint(4) UNSIGNED', + 'BOOL' => 'tinyint(1) UNSIGNED', + 'VCHAR' => 'varchar(255)', + 'VCHAR:' => 'varchar(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'text', + 'XSTEXT_UNI'=> 'varchar(100)', + 'STEXT' => 'text', + 'STEXT_UNI' => 'varchar(255)', + 'TEXT' => 'text', + 'TEXT_UNI' => 'text', + 'MTEXT' => 'mediumtext', + 'MTEXT_UNI' => 'mediumtext', + 'TIMESTAMP' => 'int(11) UNSIGNED', + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'varchar(255)', + 'VCHAR_UNI:'=> 'varchar(%d)', + 'VCHAR_CI' => 'varchar(255)', + 'VARBINARY' => 'varbinary(255)', + ), + + 'mysql_40' => array( + 'INT:' => 'int(%d)', + 'BINT' => 'bigint(20)', + 'UINT' => 'mediumint(8) UNSIGNED', + 'UINT:' => 'int(%d) UNSIGNED', + 'TINT:' => 'tinyint(%d)', + 'USINT' => 'smallint(4) UNSIGNED', + 'BOOL' => 'tinyint(1) UNSIGNED', + 'VCHAR' => 'varbinary(255)', + 'VCHAR:' => 'varbinary(%d)', + 'CHAR:' => 'binary(%d)', + 'XSTEXT' => 'blob', + 'XSTEXT_UNI'=> 'blob', + 'STEXT' => 'blob', + 'STEXT_UNI' => 'blob', + 'TEXT' => 'blob', + 'TEXT_UNI' => 'blob', + 'MTEXT' => 'mediumblob', + 'MTEXT_UNI' => 'mediumblob', + 'TIMESTAMP' => 'int(11) UNSIGNED', + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'blob', + 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')), + 'VCHAR_CI' => 'blob', + 'VARBINARY' => 'varbinary(255)', + ), + + 'firebird' => array( + 'INT:' => 'INTEGER', + 'BINT' => 'DOUBLE PRECISION', + 'UINT' => 'INTEGER', + 'UINT:' => 'INTEGER', + 'TINT:' => 'INTEGER', + 'USINT' => 'INTEGER', + 'BOOL' => 'INTEGER', + 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE', + 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE', + 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE', + 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', + 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', + 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', + 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', + 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8', + 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', + 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', + 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', + 'TIMESTAMP' => 'INTEGER', + 'DECIMAL' => 'DOUBLE PRECISION', + 'DECIMAL:' => 'DOUBLE PRECISION', + 'PDECIMAL' => 'DOUBLE PRECISION', + 'PDECIMAL:' => 'DOUBLE PRECISION', + 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', + 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8', + 'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8', + 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE', + ), + + 'mssql' => array( + 'INT:' => '[int]', + 'BINT' => '[float]', + 'UINT' => '[int]', + 'UINT:' => '[int]', + 'TINT:' => '[int]', + 'USINT' => '[int]', + 'BOOL' => '[int]', + 'VCHAR' => '[varchar] (255)', + 'VCHAR:' => '[varchar] (%d)', + 'CHAR:' => '[char] (%d)', + 'XSTEXT' => '[varchar] (1000)', + 'STEXT' => '[varchar] (3000)', + 'TEXT' => '[varchar] (8000)', + 'MTEXT' => '[text]', + 'XSTEXT_UNI'=> '[varchar] (100)', + 'STEXT_UNI' => '[varchar] (255)', + 'TEXT_UNI' => '[varchar] (4000)', + 'MTEXT_UNI' => '[text]', + 'TIMESTAMP' => '[int]', + 'DECIMAL' => '[float]', + 'DECIMAL:' => '[float]', + 'PDECIMAL' => '[float]', + 'PDECIMAL:' => '[float]', + 'VCHAR_UNI' => '[varchar] (255)', + 'VCHAR_UNI:'=> '[varchar] (%d)', + 'VCHAR_CI' => '[varchar] (255)', + 'VARBINARY' => '[varchar] (255)', + ), + + 'oracle' => array( + 'INT:' => 'number(%d)', + 'BINT' => 'number(20)', + 'UINT' => 'number(8)', + 'UINT:' => 'number(%d)', + 'TINT:' => 'number(%d)', + 'USINT' => 'number(4)', + 'BOOL' => 'number(1)', + 'VCHAR' => 'varchar2(255)', + 'VCHAR:' => 'varchar2(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'varchar2(1000)', + 'STEXT' => 'varchar2(3000)', + 'TEXT' => 'clob', + 'MTEXT' => 'clob', + 'XSTEXT_UNI'=> 'varchar2(300)', + 'STEXT_UNI' => 'varchar2(765)', + 'TEXT_UNI' => 'clob', + 'MTEXT_UNI' => 'clob', + 'TIMESTAMP' => 'number(11)', + 'DECIMAL' => 'number(5, 2)', + 'DECIMAL:' => 'number(%d, 2)', + 'PDECIMAL' => 'number(6, 3)', + 'PDECIMAL:' => 'number(%d, 3)', + 'VCHAR_UNI' => 'varchar2(765)', + 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')), + 'VCHAR_CI' => 'varchar2(255)', + 'VARBINARY' => 'raw(255)', + ), + + 'sqlite' => array( + 'INT:' => 'int(%d)', + 'BINT' => 'bigint(20)', + 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED', + 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED', + 'TINT:' => 'tinyint(%d)', + 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED', + 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED', + 'VCHAR' => 'varchar(255)', + 'VCHAR:' => 'varchar(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'text(65535)', + 'STEXT' => 'text(65535)', + 'TEXT' => 'text(65535)', + 'MTEXT' => 'mediumtext(16777215)', + 'XSTEXT_UNI'=> 'text(65535)', + 'STEXT_UNI' => 'text(65535)', + 'TEXT_UNI' => 'text(65535)', + 'MTEXT_UNI' => 'mediumtext(16777215)', + 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED', + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'varchar(255)', + 'VCHAR_UNI:'=> 'varchar(%d)', + 'VCHAR_CI' => 'varchar(255)', + 'VARBINARY' => 'blob', + ), + + 'postgres' => array( + 'INT:' => 'INT4', + 'BINT' => 'INT8', + 'UINT' => 'INT4', // unsigned + 'UINT:' => 'INT4', // unsigned + 'USINT' => 'INT2', // unsigned + 'BOOL' => 'INT2', // unsigned + 'TINT:' => 'INT2', + 'VCHAR' => 'varchar(255)', + 'VCHAR:' => 'varchar(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'varchar(1000)', + 'STEXT' => 'varchar(3000)', + 'TEXT' => 'varchar(8000)', + 'MTEXT' => 'TEXT', + 'XSTEXT_UNI'=> 'varchar(100)', + 'STEXT_UNI' => 'varchar(255)', + 'TEXT_UNI' => 'varchar(4000)', + 'MTEXT_UNI' => 'TEXT', + 'TIMESTAMP' => 'INT4', // unsigned + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'varchar(255)', + 'VCHAR_UNI:'=> 'varchar(%d)', + 'VCHAR_CI' => 'varchar_ci', + 'VARBINARY' => 'bytea', + ), + ); + + /** + * A list of types being unsigned for better reference in some db's + * @var array + */ + var $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); + + /** + * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. + * @var array + */ + var $supported_dbms = array('firebird', 'mssql', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite'); + + /** + * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array). + * This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command. + */ + var $return_statements = false; + + /** + * Constructor. Set DB Object and set {@link $return_statements return_statements}. + * + * @param phpbb_dbal $db DBAL object + * @param bool $return_statements True if only statements should be returned and no SQL being executed + */ + function updater_db_tools(&$db, $return_statements = false) { - echo "
          \n{$sql}\n
          "; - } + $this->db = $db; + $this->return_statements = $return_statements; - $db->sql_return_on_error(true); - - $result = $db->sql_query($sql); - if ($db->sql_error_triggered) - { - $errored = true; - $error_ary['sql'][] = $db->sql_error_sql; - $error_ary['error_code'][] = $db->_sql_error(); - } - - $db->sql_return_on_error(false); - - if ($echo_dot) - { - echo ". \n"; - flush(); - } - - return $result; -} - -function _write_result($no_updates, $errored, $error_ary) -{ - global $lang; - - if ($no_updates) - { - echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '

          '; - } - else - { - echo ' ' . $lang['DONE'] . '
          ' . $lang['RESULT'] . ' :: '; - - if ($errored) + // Determine mapping database type + switch ($this->db->sql_layer) { - echo ' ' . $lang['SOME_QUERIES_FAILED'] . '
            '; + case 'mysql': + $this->sql_layer = 'mysql_40'; + break; - for ($i = 0; $i < sizeof($error_ary['sql']); $i++) - { - echo '
          • ' . $lang['ERROR'] . ' :: ' . htmlspecialchars($error_ary['error_code'][$i]['message']) . '
            '; - echo $lang['SQL'] . ' :: ' . htmlspecialchars($error_ary['sql'][$i]) . '

          • '; - } - - echo '


          ' . $lang['SQL_FAILURE_EXPLAIN'] . '

          '; - } - else - { - echo '' . $lang['NO_ERRORS'] . '

          '; - } - } -} - -/** -* Check if a specified column exist -*/ -function column_exists($dbms, $table, $column_name) -{ - global $db; - - switch ($dbms) - { - case 'mysql_40': - case 'mysql_41': - $sql = "SHOW COLUMNS - FROM $table"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['Field']) == $column_name) + case 'mysql4': + if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) { - $db->sql_freeresult($result); - return true; - } - } - $db->sql_freeresult($result); - return false; - break; - - // PostgreSQL has a way of doing this in a much simpler way but would - // not allow us to support all versions of PostgreSQL - case 'postgres': - $sql = "SELECT a.attname - FROM pg_class c, pg_attribute a - WHERE c.relname = '{$table}' - AND a.attnum > 0 - AND a.attrelid = c.oid"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['attname']) == $column_name) - { - $db->sql_freeresult($result); - return true; - } - } - $db->sql_freeresult($result); - return false; - break; - - // same deal with PostgreSQL, we must perform more complex operations than - // we technically could - case 'mssql': - $sql = "SELECT c.name - FROM syscolumns c - LEFT JOIN sysobjects o ON c.id = o.id - WHERE o.name = '{$table}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['name']) == $column_name) - { - $db->sql_freeresult($result); - return true; - } - } - $db->sql_freeresult($result); - return false; - break; - - case 'oracle': - $sql = "SELECT column_name - FROM user_tab_columns - WHERE table_name = '{$table}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['column_name']) == $column_name) - { - $db->sql_freeresult($result); - return true; - } - } - $db->sql_freeresult($result); - return false; - break; - - case 'firebird': - $sql = "SELECT RDB\$FIELD_NAME as FNAME - FROM RDB\$RELATION_FIELDS - WHERE RDB\$RELATION_NAME = '{$table}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['fname']) == $column_name) - { - $db->sql_freeresult($result); - return true; - } - } - $db->sql_freeresult($result); - return false; - break; - - // ugh, SQLite - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table}'"; - $result = $db->sql_query($sql); - - if (!$result) - { - return false; - } - - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $cols = trim($matches[1]); - $col_array = preg_split('/,(?![\s\w]+\))/m', $cols); - - foreach ($col_array as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - - if (strtolower($entities[0]) == $column_name) - { - return true; - } - } - return false; - break; - } -} - -/** -* Function to prepare some column information for better usage -*/ -function prepare_column_data($dbms, $column_data, $table_name, $column_name) -{ - global $dbms_type_map, $unsigned_types; - - // Get type - if (strpos($column_data[0], ':') !== false) - { - list($orig_column_type, $column_length) = explode(':', $column_data[0]); - - if (!is_array($dbms_type_map[$dbms][$orig_column_type . ':'])) - { - $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'], $column_length); - } - else - { - if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['rule'])) - { - switch ($dbms_type_map[$dbms][$orig_column_type . ':']['rule'][0]) - { - case 'div': - $column_length /= $dbms_type_map[$dbms][$orig_column_type . ':']['rule'][1]; - $column_length = ceil($column_length); - $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length); - break; - } - } - - if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['limit'])) - { - switch ($dbms_type_map[$dbms][$orig_column_type . ':']['limit'][0]) - { - case 'mult': - $column_length *= $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][1]; - if ($column_length > $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][2]) - { - $column_type = $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][3]; - } - else - { - $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length); - } - break; - } - } - } - $orig_column_type .= ':'; - } - else - { - $orig_column_type = $column_data[0]; - $column_type = $dbms_type_map[$dbms][$column_data[0]]; - } - - // Adjust default value if db-dependant specified - if (is_array($column_data[1])) - { - $column_data[1] = (isset($column_data[1][$dbms])) ? $column_data[1][$dbms] : $column_data[1]['default']; - } - - $sql = ''; - $return_array = array(); - - switch ($dbms) - { - case 'firebird': - $sql .= " {$column_type} "; - - if (!is_null($column_data[1])) - { - $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; - } - - $sql .= 'NOT NULL'; - - // This is a UNICODE column and thus should be given it's fair share - if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0])) - { - $sql .= ' COLLATE UNICODE'; - } - - break; - - case 'mssql': - $sql .= " {$column_type} "; - $sql_default = " {$column_type} "; - - // For adding columns we need the default definition - if (!is_null($column_data[1])) - { - // For hexadecimal values do not use single quotes - if (strpos($column_data[1], '0x') === 0) - { - $sql_default .= 'DEFAULT (' . $column_data[1] . ') '; + $this->sql_layer = 'mysql_41'; } else { - $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + $this->sql_layer = 'mysql_40'; } - } + break; - $sql .= 'NOT NULL'; - $sql_default .= 'NOT NULL'; + case 'mysqli': + $this->sql_layer = 'mysql_41'; + break; - $return_array['column_type_sql_default'] = $sql_default; - break; + case 'mssql': + case 'mssql_odbc': + $this->sql_layer = 'mssql'; + break; - case 'mysql_40': - case 'mysql_41': - $sql .= " {$column_type} "; + default: + $this->sql_layer = $this->db->sql_layer; + break; + } + } - // For hexadecimal values do not use single quotes - if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob') + /** + * Handle passed database update array. + * Expected structure... + * Key being one of the following + * change_columns: Column changes (only type, not name) + * add_columns: Add columns to a table + * drop_keys: Dropping keys + * drop_columns: Removing/Dropping columns + * add_primary_keys: adding primary keys + * add_unique_index: adding an unique index + * add_index: adding an index + * + * The values are in this format: + * {TABLE NAME} => array( + * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}), + * {KEY/INDEX NAME} => array({COLUMN NAMES}), + * ) + * + * For more information have a look at /develop/create_schema_files.php (only available through SVN) + */ + function perform_schema_changes($schema_changes) + { + if (empty($schema_changes)) + { + return; + } + + $statements = array(); + + // Change columns? + if (!empty($schema_changes['change_columns'])) + { + foreach ($schema_changes['change_columns'] as $table => $columns) { - $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' "; - } - $sql .= 'NOT NULL'; - - if (isset($column_data[2])) - { - if ($column_data[2] == 'auto_increment') + foreach ($columns as $column_name => $column_data) { - $sql .= ' auto_increment'; + // If the column exists we change it, else we add it ;) + if ($this->sql_column_exists($table, $column_name)) + { + $result = $this->sql_column_change($table, $column_name, $column_data); + } + else + { + $result = $this->sql_column_add($table, $column_name, $column_data); + } + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } } - else if ($dbms === 'mysql_41' && $column_data[2] == 'true_sort') + } + } + + // Add columns? + if (!empty($schema_changes['add_columns'])) + { + foreach ($schema_changes['add_columns'] as $table => $columns) + { + foreach ($columns as $column_name => $column_data) { - $sql .= ' COLLATE utf8_unicode_ci'; + // Only add the column if it does not exist yet, else change it (to be consistent) + if ($this->sql_column_exists($table, $column_name)) + { + $result = $this->sql_column_change($table, $column_name, $column_data); + } + else + { + $result = $this->sql_column_add($table, $column_name, $column_data); + } + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } } } + } - break; - - case 'oracle': - $sql .= " {$column_type} "; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : ''; - - // In Oracle empty strings ('') are treated as NULL. - // Therefore in oracle we allow NULL's for all DEFAULT '' entries - // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) - if (preg_match('/number/i', $column_type)) + // Remove keys? + if (!empty($schema_changes['drop_keys'])) + { + foreach ($schema_changes['drop_keys'] as $table => $indexes) { - $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; + foreach ($indexes as $index_name) + { + $result = $this->sql_index_drop($table, $index_name); + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } + } } - break; + } - case 'postgres': - $return_array['column_type'] = $column_type; - - $sql .= " {$column_type} "; - - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + // Drop columns? + if (!empty($schema_changes['drop_columns'])) + { + foreach ($schema_changes['drop_columns'] as $table => $columns) { - $default_val = "nextval('{$table_name}_seq')"; + foreach ($columns as $column) + { + // Only remove the column if it exists... + if ($this->sql_column_exists($table, $column)) + { + $result = $this->sql_column_remove($table, $column); + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } + } + } } - else if (!is_null($column_data[1])) + } + + // Add primary keys? + if (!empty($schema_changes['add_primary_keys'])) + { + foreach ($schema_changes['add_primary_keys'] as $table => $columns) { - $default_val = "'" . $column_data[1] . "'"; - $return_array['null'] = 'NOT NULL'; - $sql .= 'NOT NULL '; + $result = $this->sql_create_primary_key($table, $columns); + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } } + } - $return_array['default'] = $default_val; - - $sql .= "DEFAULT {$default_val}"; - - // Unsigned? Then add a CHECK contraint - if (in_array($orig_column_type, $unsigned_types)) + // Add unqiue indexes? + if (!empty($schema_changes['add_unique_index'])) + { + foreach ($schema_changes['add_unique_index'] as $table => $index_array) { - $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; - $sql .= " CHECK ({$column_name} >= 0)"; + foreach ($index_array as $index_name => $column) + { + $result = $this->sql_create_unique_index($table, $index_name, $column); + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } + } } - break; + } - case 'sqlite': - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + // Add indexes? + if (!empty($schema_changes['add_index'])) + { + foreach ($schema_changes['add_index'] as $table => $index_array) { - $sql .= ' INTEGER PRIMARY KEY'; + foreach ($index_array as $index_name => $column) + { + $result = $this->sql_create_index($table, $index_name, $column); + + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } + } + } + } + + if ($this->return_statements) + { + return $statements; + } + } + + /** + * Check if a specified column exist + * + * @param string $table Table to check the column at + * @param string $column_name The column to check + * + * @return bool True if column exists, else false + */ + function sql_column_exists($table, $column_name) + { + switch ($this->sql_layer) + { + case 'mysql_40': + case 'mysql_41': + + $sql = "SHOW COLUMNS FROM $table"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + // lower case just in case + if (strtolower($row['Field']) == $column_name) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + return false; + break; + + // PostgreSQL has a way of doing this in a much simpler way but would + // not allow us to support all versions of PostgreSQL + case 'postgres': + $sql = "SELECT a.attname + FROM pg_class c, pg_attribute a + WHERE c.relname = '{$table}' + AND a.attnum > 0 + AND a.attrelid = c.oid"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // lower case just in case + if (strtolower($row['attname']) == $column_name) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + + return false; + break; + + // same deal with PostgreSQL, we must perform more complex operations than + // we technically could + case 'mssql': + $sql = "SELECT c.name + FROM syscolumns c + LEFT JOIN sysobjects o ON c.id = o.id + WHERE o.name = '{$table}'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // lower case just in case + if (strtolower($row['name']) == $column_name) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + return false; + break; + + case 'oracle': + $sql = "SELECT column_name + FROM user_tab_columns + WHERE table_name = '{$table}'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // lower case just in case + if (strtolower($row['column_name']) == $column_name) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + return false; + break; + + case 'firebird': + $sql = "SELECT RDB\$FIELD_NAME as FNAME + FROM RDB\$RELATION_FIELDS + WHERE RDB\$RELATION_NAME = '{$table}'"; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // lower case just in case + if (strtolower($row['fname']) == $column_name) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + return false; + break; + + // ugh, SQLite + case 'sqlite': + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '{$table}'"; + $result = $this->db->sql_query($sql); + + if (!$result) + { + return false; + } + + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $cols = trim($matches[1]); + $col_array = preg_split('/,(?![\s\w]+\))/m', $cols); + + foreach ($col_array as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] == 'PRIMARY') + { + continue; + } + + if (strtolower($entities[0]) == $column_name) + { + return true; + } + } + return false; + break; + } + } + + /** + * Private method for performing sql statements (either execute them or return them) + * @access private + */ + function _sql_run_sql($statements) + { + if ($this->return_statements) + { + return $statements; + } + + // We could add error handling here... + foreach ($statements as $sql) + { + if ($sql === 'begin') + { + $this->db->sql_transaction('begin'); + } + else if ($sql === 'commit') + { + $this->db->sql_transaction('commit'); } else { - $sql .= ' ' . $column_type; + $this->db->sql_query($sql); } + } - $sql .= ' NOT NULL '; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; - break; + return true; } - $return_array['column_type_sql'] = $sql; - - return $return_array; -} - -/** -* Add new column -*/ -function sql_column_add($dbms, $table_name, $column_name, $column_data) -{ - global $errored, $error_ary; - - $column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name); - - switch ($dbms) + /** + * Function to prepare some column information for better usage + * @access private + */ + function sql_prepare_column_data($table_name, $column_name, $column_data) { - case 'firebird': - $sql = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'mssql': - $sql = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default']; - _sql($sql, $errored, $error_ary); - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'oracle': - $sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'sqlite': - if (version_compare(sqlite_libversion(), '3.0') == -1) + // Get type + if (strpos($column_data[0], ':') !== false) + { + list($orig_column_type, $column_length) = explode(':', $column_data[0]); + if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'])) { - global $db; + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length); + } + else + { + if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'])) + { + switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0]) + { + case 'div': + $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1]; + $column_length = ceil($column_length); + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); + break; + } + } + + if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'])) + { + switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0]) + { + case 'mult': + $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1]; + if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2]) + { + $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3]; + } + else + { + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); + } + break; + } + } + } + $orig_column_type .= ':'; + } + else + { + $orig_column_type = $column_data[0]; + $column_type = $this->dbms_type_map[$this->sql_layer][$column_data[0]]; + } + + // Adjust default value if db-dependant specified + if (is_array($column_data[1])) + { + $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default']; + } + + $sql = ''; + + $return_array = array(); + + switch ($this->sql_layer) + { + case 'firebird': + $sql .= " {$column_type} "; + + if (!is_null($column_data[1])) + { + $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; + } + + $sql .= 'NOT NULL'; + + // This is a UNICODE column and thus should be given it's fair share + if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0])) + { + $sql .= ' COLLATE UNICODE'; + } + + $return_array['auto_increment'] = false; + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $return_array['auto_increment'] = true; + } + + break; + + case 'mssql': + $sql .= " {$column_type} "; + $sql_default = " {$column_type} "; + + // For adding columns we need the default definition + if (!is_null($column_data[1])) + { + // For hexadecimal values do not use single quotes + if (strpos($column_data[1], '0x') === 0) + { + $sql_default .= 'DEFAULT (' . $column_data[1] . ') '; + } + else + { + $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + } + } + + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { +// $sql .= 'IDENTITY (1, 1) '; + $sql_default .= 'IDENTITY (1, 1) '; + } + + $return_array['textimage'] = $column_type === '[text]'; + + $sql .= 'NOT NULL'; + $sql_default .= 'NOT NULL'; + + $return_array['column_type_sql_default'] = $sql_default; + + break; + + case 'mysql_40': + case 'mysql_41': + $sql .= " {$column_type} "; + + // For hexadecimal values do not use single quotes + if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob') + { + $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' "; + } + $sql .= 'NOT NULL'; + + if (isset($column_data[2])) + { + if ($column_data[2] == 'auto_increment') + { + $sql .= ' auto_increment'; + } + else if ($this->sql_layer === 'mysql_41' && $column_data[2] == 'true_sort') + { + $sql .= ' COLLATE utf8_unicode_ci'; + } + } + + break; + + case 'oracle': + $sql .= " {$column_type} "; + $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : ''; + + // In Oracle empty strings ('') are treated as NULL. + // Therefore in oracle we allow NULL's for all DEFAULT '' entries + // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) + if (!preg_match('/number/i', $column_type)) + { + $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; + } + + $return_array['auto_increment'] = false; + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $return_array['auto_increment'] = true; + } + + break; + + case 'postgres': + $return_array['column_type'] = $column_type; + + $sql .= " {$column_type} "; + + $return_array['auto_increment'] = false; + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $default_val = "nextval('{$table_name}_seq')"; + $return_array['auto_increment'] = true; + } + else if (!is_null($column_data[1])) + { + $default_val = "'" . $column_data[1] . "'"; + $return_array['null'] = 'NOT NULL'; + $sql .= 'NOT NULL '; + } + + $return_array['default'] = $default_val; + + $sql .= "DEFAULT {$default_val}"; + + // Unsigned? Then add a CHECK contraint + if (in_array($orig_column_type, $this->unsigned_types)) + { + $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; + $sql .= " CHECK ({$column_name} >= 0)"; + } + + break; + + case 'sqlite': + $return_array['primary_key_set'] = false; + if (isset($column_data[2]) && $column_data[2] == 'auto_increment') + { + $sql .= ' INTEGER PRIMARY KEY'; + $return_array['primary_key_set'] = true; + } + else + { + $sql .= ' ' . $column_type; + } + + $sql .= ' NOT NULL '; + $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; + + break; + } + + $return_array['column_type_sql'] = $sql; + + return $return_array; + } + + /** + * Add new column + */ + function sql_column_add($table_name, $column_name, $column_data) + { + $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD "' . strtoupper($column_name) . '" ' . $column_data['column_type_sql']; + break; + + case 'mssql': + $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default']; + break; + + case 'mysql_40': + case 'mysql_41': + $statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql']; + break; + + case 'oracle': + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql']; + break; + + case 'postgres': + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql']; + break; + + case 'sqlite': + if (version_compare(sqlite_libversion(), '3.0') == -1) + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '{$table_name}' + ORDER BY type DESC, name;"; + $result = $this->db->sql_query($sql); + + if (!$result) + { + break; + } + + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $statements[] = 'begin'; + + // Create a backup table and populate it, destroy the existing one + $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); + $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; + $statements[] = 'DROP TABLE ' . $table_name; + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $new_table_cols = trim($matches[1]); + $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); + $column_list = array(); + + foreach ($old_table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] == 'PRIMARY') + { + continue; + } + $column_list[] = $entities[0]; + } + + $columns = implode(',', $column_list); + + $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols; + + // create a new table and fill it up. destroy the temp one + $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'; + $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; + $statements[] = 'DROP TABLE ' . $table_name . '_temp'; + + $statements[] = 'commit'; + } + else + { + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']'; + } + break; + } + + return $this->_sql_run_sql($statements); + } + + /** + * Drop column + */ + function sql_column_remove($table_name, $column_name) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP "' . strtoupper($column_name) . '"'; + break; + + case 'mssql': + $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; + break; + + case 'mysql_40': + case 'mysql_41': + $statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`'; + break; + + case 'oracle': + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name; + break; + + case 'postgres': + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"'; + break; + + case 'sqlite': + if (version_compare(sqlite_libversion(), '3.0') == -1) + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '{$table_name}' + ORDER BY type DESC, name;"; + $result = $this->db->sql_query($sql); + + if (!$result) + { + break; + } + + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $statements[] = 'begin'; + + // Create a backup table and populate it, destroy the existing one + $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); + $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; + $statements[] = 'DROP TABLE ' . $table_name; + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $new_table_cols = trim($matches[1]); + $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); + $column_list = array(); + + foreach ($old_table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name) + { + continue; + } + $column_list[] = $entities[0]; + } + + $columns = implode(',', $column_list); + + $new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols); + + // create a new table and fill it up. destroy the temp one + $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'; + $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; + $statements[] = 'DROP TABLE ' . $table_name . '_temp'; + + $statements[] = 'commit'; + } + else + { + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; + } + break; + } + + return $this->_sql_run_sql($statements); + } + + /** + * Drop Index + */ + function sql_index_drop($table_name, $index_name) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'mssql': + $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name; + break; + + case 'mysql_40': + case 'mysql_41': + $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; + break; + + case 'firebird': + case 'oracle': + case 'postgres': + case 'sqlite': + $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; + break; + } + + return $this->_sql_run_sql($statements); + } + + /** + * Add primary key + */ + function sql_create_primary_key($table_name, $column) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + case 'postgres': + case 'mysql_40': + case 'mysql_41': + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; + break; + + case 'mssql': + $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD "; + $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED ("; + $sql .= '[' . implode("],\n\t\t[", $column) . ']'; + $sql .= ') ON [PRIMARY]'; + + $statements[] = $sql; + break; + + case 'oracle': + $statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; + break; + + case 'sqlite': $sql = "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '{$table_name}' ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); if (!$result) { break; } - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); - $db->sql_transaction('begin'); + $statements[] = 'begin'; // Create a backup table and populate it, destroy the existing one - $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql'])); - $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name); - $db->sql_query('DROP TABLE ' . $table_name); + $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); + $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; + $statements[] = 'DROP TABLE ' . $table_name; preg_match('#\((.*)\)#s', $row['sql'], $matches); @@ -2523,84 +2163,190 @@ function sql_column_add($dbms, $table_name, $column_name, $column_data) $columns = implode(',', $column_list); - $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols; - // create a new table and fill it up. destroy the temp one - $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'); - $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'); - $db->sql_query('DROP TABLE ' . $table_name . '_temp'); + $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));'; + $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; + $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - $db->sql_transaction('commit'); - } - else - { - $sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']'; - _sql($sql, $errored, $error_ary); - } - break; + $statements[] = 'commit'; + break; + } + + return $this->_sql_run_sql($statements); } -} -/** -* Drop column -*/ -function sql_column_remove($dbms, $table_name, $column_name) -{ - global $errored, $error_ary; - - switch ($dbms) + /** + * Add unique index + */ + function sql_create_unique_index($table_name, $index_name, $column) { - case 'firebird': - $sql = 'ALTER TABLE "' . $table_name . '" DROP "' . $column_name . '"'; - _sql($sql, $errored, $error_ary); - break; + $statements = array(); - case 'mssql': - $sql = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; - _sql($sql, $errored, $error_ary); - break; + switch ($this->sql_layer) + { + case 'firebird': + case 'postgres': + case 'oracle': + case 'sqlite': + $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + break; - case 'mysql_40': - case 'mysql_41': - $sql = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`'; - _sql($sql, $errored, $error_ary); - break; + case 'mysql_40': + case 'mysql_41': + $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + break; - case 'oracle': - $sql = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name; - _sql($sql, $errored, $error_ary); - break; + case 'mssql': + $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; + break; + } - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"'; - _sql($sql, $errored, $error_ary); - break; + return $this->_sql_run_sql($statements); + } + + /** + * Add index + */ + function sql_create_index($table_name, $index_name, $column) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + case 'postgres': + case 'oracle': + case 'sqlite': + $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + break; + + case 'mysql_40': + case 'mysql_41': + $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + break; + + case 'mssql': + $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; + break; + } + + return $this->_sql_run_sql($statements); + } + + /** + * Change column type (not name!) + */ + function sql_column_change($table_name, $column_name, $column_data) + { + $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + // Change type... + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql']; + break; + + case 'mssql': + $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; + break; + + case 'mysql_40': + case 'mysql_41': + $statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql']; + break; + + case 'oracle': + $statements[] = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql']; + break; + + case 'postgres': + $sql = 'ALTER TABLE ' . $table_name . ' '; + + $sql_array = array(); + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type']; + + if (isset($column_data['null'])) + { + if ($column_data['null'] == 'NOT NULL') + { + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL'; + } + else if ($column_data['null'] == 'NULL') + { + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL'; + } + } + + if (isset($column_data['default'])) + { + $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; + } + + // we don't want to double up on constraints if we change different number data types + if (isset($column_data['constraint'])) + { + $constraint_sql = "SELECT consrc as constraint_data + FROM pg_constraint, pg_class bc + WHERE conrelid = bc.oid + AND bc.relname = '{$table_name}' + AND NOT EXISTS ( + SELECT * + FROM pg_constraint as c, pg_inherits as i + WHERE i.inhrelid = pg_constraint.conrelid + AND c.conname = pg_constraint.conname + AND c.consrc = pg_constraint.consrc + AND c.conrelid = i.inhparent + )"; + + $constraint_exists = false; + + $result = $this->db->sql_query($constraint_sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (trim($row['constraint_data']) == trim($column_data['constraint'])) + { + $constraint_exists = true; + break; + } + } + $this->db->sql_freeresult($result); + + if (!$constraint_exists) + { + $sql_array[] = 'ADD ' . $column_data['constraint']; + } + } + + $sql .= implode(', ', $sql_array); + + $statements[] = $sql; + break; + + case 'sqlite': - case 'sqlite': - if (version_compare(sqlite_libversion(), '3.0') == -1) - { - global $db; $sql = "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '{$table_name}' ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); if (!$result) { break; } - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); - $db->sql_transaction('begin'); + $statements[] = 'begin'; - // Create a backup table and populate it, destroy the existing one - $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql'])); - $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name); - $db->sql_query('DROP TABLE ' . $table_name); + // Create a temp table and populate it, destroy the existing one + $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); + $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; + $statements[] = 'DROP TABLE ' . $table_name; preg_match('#\((.*)\)#s', $row['sql'], $matches); @@ -2608,565 +2354,30 @@ function sql_column_remove($dbms, $table_name, $column_name) $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); $column_list = array(); - foreach ($old_table_cols as $declaration) + foreach ($old_table_cols as $key => $declaration) { $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name) - { - continue; - } $column_list[] = $entities[0]; + if ($entities[0] == $column_name) + { + $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql']; + } } $columns = implode(',', $column_list); - $new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols); - // create a new table and fill it up. destroy the temp one - $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'); - $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'); - $db->sql_query('DROP TABLE ' . $table_name . '_temp'); + $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');'; + $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; + $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - $db->sql_transaction('commit'); - } - else - { - $sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; - _sql($sql, $errored, $error_ary); - } - break; - } -} + $statements[] = 'commit'; -function sql_index_drop($dbms, $index_name, $table_name) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - switch ($dbms) - { - case 'mssql': - $sql = 'DROP INDEX ' . $table_name . '.' . $index_name; - _sql($sql, $errored, $error_ary); - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; - _sql($sql, $errored, $error_ary); - break; - - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - $sql = 'DROP INDEX ' . $table_name . '_' . $index_name; - _sql($sql, $errored, $error_ary); - break; - } -} - -function sql_create_primary_key($dbms, $table_name, $column) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - switch ($dbms) - { - case 'firebird': - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'mssql': - $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD "; - $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED ("; - $sql .= '[' . implode("],\n\t\t[", $column) . ']'; - $sql .= ') ON [PRIMARY]'; - _sql($sql, $errored, $error_ary); - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'oracle': - $sql = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = _sql($sql, $errored, $error_ary); - - if (!$result) - { - break; - } - - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $db->sql_transaction('begin'); - - // Create a backup table and populate it, destroy the existing one - $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql'])); - $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name); - $db->sql_query('DROP TABLE ' . $table_name); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));'); - $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'); - $db->sql_query('DROP TABLE ' . $table_name . '_temp'); - - $db->sql_transaction('commit'); - break; - } -} - -function sql_create_unique_index($dbms, $index_name, $table_name, $column) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - switch ($dbms) - { - case 'firebird': - case 'postgres': - case 'oracle': - case 'sqlite': - $sql = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'mssql': - $sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; - _sql($sql, $errored, $error_ary); - break; - } -} - -function sql_create_index($dbms, $index_name, $table_name, $column) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - switch ($dbms) - { - case 'firebird': - case 'postgres': - case 'oracle': - case 'sqlite': - $sql = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - _sql($sql, $errored, $error_ary); - break; - - case 'mssql': - $sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; - _sql($sql, $errored, $error_ary); - break; - } -} - -// List all of the indices that belong to a table, -// does not count: -// * UNIQUE indices -// * PRIMARY keys -function sql_list_index($dbms, $table_name) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - $index_array = array(); - - if ($dbms == 'mssql') - { - $sql = "EXEC sp_statistics '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index_array[] = $row['INDEX_NAME']; - } - } - $db->sql_freeresult($result); - } - else - { - switch ($dbms) - { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . " - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'SHOW KEYS - FROM ' . $table_name; - $col = 'Key_name'; - break; - - case 'oracle': - $sql = "SELECT index_name - FROM user_indexes - WHERE table_name = '" . $table_name . "' - AND generated = 'N'"; - break; - - case 'sqlite': - $sql = "PRAGMA index_info('" . $table_name . "');"; - $col = 'name'; break; } - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique']) - { - continue; - } - - switch ($dbms) - { - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - $row[$col] = substr($row[$col], strlen($table_name) + 1); - break; - } - - $index_array[] = $row[$col]; - } - $db->sql_freeresult($result); - } - - return array_map('strtolower', $index_array); -} - -// This is totally fake, never use it -// it exists only to mend bad update functions introduced -// * UNIQUE indices -// * PRIMARY keys -function sql_list_fake($dbms, $table_name) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - $index_array = array(); - - if ($dbms == 'mssql') - { - $sql = "EXEC sp_statistics '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index_array[] = $row['INDEX_NAME']; - } - } - $db->sql_freeresult($result); - } - else - { - switch ($dbms) - { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . " - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'SHOW KEYS - FROM ' . $table_name; - $col = 'Key_name'; - break; - - case 'oracle': - $sql = "SELECT index_name - FROM user_indexes - WHERE table_name = '" . $table_name . "' - AND generated = 'N'"; - break; - - case 'sqlite': - $sql = "PRAGMA index_info('" . $table_name . "');"; - $col = 'name'; - break; - } - - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique']) - { - continue; - } - - $index_array[] = $row[$col]; - } - $db->sql_freeresult($result); - } - - return array_map('strtolower', $index_array); -} - -/** -* Change column type (not name!) -*/ -function sql_column_change($dbms, $table_name, $column_name, $column_data) -{ - global $dbms_type_map, $db; - global $errored, $error_ary; - - $column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name); - - switch ($dbms) - { - case 'firebird': - // Change type... - $sql = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'mssql': - $sql = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'oracle': - $sql = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql']; - _sql($sql, $errored, $error_ary); - break; - - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' '; - - $sql_array = array(); - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type']; - - if (isset($column_data['null'])) - { - if ($column_data['null'] == 'NOT NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL'; - } - else if ($column_data['null'] == 'NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL'; - } - } - - if (isset($column_data['default'])) - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; - } - - // we don't want to double up on constraints if we change different number data types - if (isset($column_data['constraint'])) - { - $constraint_sql = "SELECT consrc as constraint_data - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '{$table_name}' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - - $constraint_exists = false; - - $result = $db->sql_query($constraint_sql); - while ($row = $db->sql_fetchrow($result)) - { - if (trim($row['constraint_data']) == trim($column_data['constraint'])) - { - $constraint_exists = true; - break; - } - } - $db->sql_freeresult($result); - - if (!$constraint_exists) - { - $sql_array[] = 'ADD ' . $column_data['constraint']; - } - } - - $sql .= implode(', ', $sql_array); - - _sql($sql, $errored, $error_ary); - break; - - case 'sqlite': - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = _sql($sql, $errored, $error_ary); - - if (!$result) - { - break; - } - - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $db->sql_transaction('begin'); - - // Create a temp table and populate it, destroy the existing one - $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql'])); - $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name); - $db->sql_query('DROP TABLE ' . $table_name); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $key => $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - $column_list[] = $entities[0]; - if ($entities[0] == $column_name) - { - $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql']; - } - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $db->sql_query('CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');'); - $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'); - $db->sql_query('DROP TABLE ' . $table_name . '_temp'); - - $db->sql_transaction('commit'); - - break; + return $this->_sql_run_sql($statements); } } -function utf8_new_clean_string($text) -{ - static $homographs = array(); - static $utf8_case_fold_nfkc = ''; - if (empty($homographs)) - { - global $phpbb_root_path, $phpEx; - if (!function_exists('utf8_case_fold_nfkc') || !file_exists($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx)) - { - if (!file_exists($phpbb_root_path . 'install/data/confusables.' . $phpEx)) - { - global $lang; - trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/confusables.' . $phpEx), E_USER_ERROR); - } - $homographs = include($phpbb_root_path . 'install/data/confusables.' . $phpEx); - $utf8_case_fold_nfkc = 'utf8_new_case_fold_nfkc'; - } - else - { - $homographs = include($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx); - $utf8_case_fold_nfkc = 'utf8_case_fold_nfkc'; - } - } - - $text = $utf8_case_fold_nfkc($text); - $text = strtr($text, $homographs); - // Other control characters - $text = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $text); - - $text = preg_replace('# {2,}#', ' ', $text); - - // we can use trim here as all the other space characters should have been turned - // into normal ASCII spaces by now - return trim($text); -} - -?> +?> \ No newline at end of file diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 8591446fea..adb0fb9623 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -543,7 +543,7 @@ class install_install extends module { if (!isset($available_dbms[$data['dbms']]) || !$available_dbms[$data['dbms']]['AVAILABLE']) { - $error['db'][] = $lang['INST_ERR_NO_DB']; + $error[] = $lang['INST_ERR_NO_DB']; $connect_test = false; } else @@ -2116,7 +2116,7 @@ class install_install extends module 'Heritrix [Crawler]' => array('heritrix/1.', ''), 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), - 'ichiro [Crawler]' => array('ichiro/2', ''), + 'ichiro [Crawler]' => array('ichiro/', ''), 'Majestic-12 [Bot]' => array('MJ12bot/', ''), 'Metager [Bot]' => array('MetagerBot/', ''), 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 8ff7427b09..ea87847fa2 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -183,6 +183,12 @@ class install_update extends module ); } + // Fill DB version + if (empty($config['dbms_version'])) + { + set_config('dbms_version', $db->sql_server_info(true)); + } + if ($this->test_update === false) { // Got the updater template itself updated? If so, we are able to directly use it - but only if all three files are present @@ -371,14 +377,14 @@ class install_update extends module continue; } - $template->assign_block_vars('files', array( +/* $template->assign_block_vars('files', array( 'S_STATUS' => true, 'STATUS' => $status, 'L_STATUS' => $user->lang['STATUS_' . strtoupper($status)], 'TITLE' => $user->lang['FILES_' . strtoupper($status)], 'EXPLAIN' => $user->lang['FILES_' . strtoupper($status) . '_EXPLAIN'], ) - ); + );*/ foreach ($filelist as $file_struct) { @@ -398,7 +404,7 @@ class install_update extends module $diff_url = append_sid($this->p_master->module_url, "mode=$mode&sub=file_check&action=diff&status=$status&file=" . urlencode($file_struct['filename'])); - $template->assign_block_vars('files', array( + $template->assign_block_vars($status, array( 'STATUS' => $status, 'FILENAME' => $filename, @@ -685,7 +691,7 @@ class install_update extends module default: $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename); - $contents = implode("\n", $diff->merged_output()); + $contents = implode("\n", $diff->merged_new_output()); unset($diff); break; } @@ -1053,7 +1059,7 @@ class install_update extends module $status = request_var('status', ''); $file = request_var('file', ''); - $diff_mode = request_var('diff_mode', 'side_by_side'); + $diff_mode = request_var('diff_mode', 'inline'); // First of all make sure the file is within our file update list with the correct status $found_entry = array(); @@ -1097,9 +1103,7 @@ class install_update extends module break; - case MERGE_NEW_FILE: - case MERGE_MOD_FILE: - +/* $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file); $tmp = array( @@ -1116,17 +1120,37 @@ class install_update extends module $this->page_title = 'VIEWING_FILE_CONTENTS'; break; - - default: +*/ + // Merge differences and use new phpBB code for conflicted blocks + case MERGE_NEW_FILE: + case MERGE_MOD_FILE: $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file); $template->assign_vars(array( 'S_DIFF_CONFLICT_FILE' => true, - 'NUM_CONFLICTS' => $diff->merged_output(false, false, false, true)) + 'NUM_CONFLICTS' => $diff->get_num_conflicts()) ); - $diff = $this->return_diff($phpbb_root_path . $file, $diff->merged_output()); + $diff = $this->return_diff($phpbb_root_path . $file, ($option == MERGE_NEW_FILE) ? $diff->merged_new_output() : $diff->merged_orig_output()); + break; + + // Download conflict file + default: + + $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file); + + header('Pragma: no-cache'); + header("Content-Type: application/octetstream; name=\"$file\""); + header("Content-disposition: attachment; filename=$file"); + + @set_time_limit(0); + + echo implode("\n", $diff->get_conflicts_content()); + + flush(); + exit; + break; } @@ -1433,9 +1457,9 @@ class install_update extends module unset($tmp); - if ($diff->merged_output(false, false, false, true)) + if ($diff->get_num_conflicts()) { - $update_ary['conflicts'] = $diff->_conflicting_blocks; + $update_ary['conflicts'] = $diff->get_num_conflicts(); // There is one special case... users having merged with a conflicting file... we need to check this $tmp = array( @@ -1462,7 +1486,7 @@ class install_update extends module $tmp = array( 'file1' => file_get_contents($phpbb_root_path . $file), - 'file2' => implode("\n", $diff->merged_output()), + 'file2' => implode("\n", $diff->merged_new_output()), ); // now compare the merged output with the original file to see if the modified file is up to date diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 8ac371b9ed..fecbc61dc1 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -65,7 +65,7 @@ CREATE TABLE phpbb_acl_options ( ALTER TABLE phpbb_acl_options ADD PRIMARY KEY (auth_option_id);; -CREATE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options(auth_option);; +CREATE UNIQUE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options(auth_option);; CREATE GENERATOR phpbb_acl_options_gen;; SET GENERATOR phpbb_acl_options_gen TO 0;; diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index 445a0eda08..8600fdb1e0 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -25,15 +25,15 @@ CREATE TABLE [phpbb_attachments] ( [mimetype] [varchar] (100) DEFAULT ('') NOT NULL , [filesize] [int] DEFAULT (0) NOT NULL , [filetime] [int] DEFAULT (0) NOT NULL , - [thumbnail] [int] DEFAULT (0) NOT NULL + [thumbnail] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_attachments] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_attachments] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_attachments] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_attachments] PRIMARY KEY CLUSTERED ( [attach_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [filetime] ON [phpbb_attachments]([filetime]) ON [PRIMARY] @@ -60,7 +60,7 @@ CREATE TABLE [phpbb_acl_groups] ( [forum_id] [int] DEFAULT (0) NOT NULL , [auth_option_id] [int] DEFAULT (0) NOT NULL , [auth_role_id] [int] DEFAULT (0) NOT NULL , - [auth_setting] [int] DEFAULT (0) NOT NULL + [auth_setting] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -82,18 +82,18 @@ CREATE TABLE [phpbb_acl_options] ( [auth_option] [varchar] (50) DEFAULT ('') NOT NULL , [is_global] [int] DEFAULT (0) NOT NULL , [is_local] [int] DEFAULT (0) NOT NULL , - [founder_only] [int] DEFAULT (0) NOT NULL + [founder_only] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_acl_options] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_acl_options] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_acl_options] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_acl_options] PRIMARY KEY CLUSTERED ( [auth_option_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO -CREATE INDEX [auth_option] ON [phpbb_acl_options]([auth_option]) ON [PRIMARY] +CREATE UNIQUE INDEX [auth_option] ON [phpbb_acl_options]([auth_option]) ON [PRIMARY] GO @@ -105,15 +105,15 @@ CREATE TABLE [phpbb_acl_roles] ( [role_name] [varchar] (255) DEFAULT ('') NOT NULL , [role_description] [varchar] (4000) DEFAULT ('') NOT NULL , [role_type] [varchar] (10) DEFAULT ('') NOT NULL , - [role_order] [int] DEFAULT (0) NOT NULL + [role_order] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_acl_roles] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_acl_roles] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_acl_roles] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_acl_roles] PRIMARY KEY CLUSTERED ( [role_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [role_type] ON [phpbb_acl_roles]([role_type]) ON [PRIMARY] @@ -129,16 +129,16 @@ GO CREATE TABLE [phpbb_acl_roles_data] ( [role_id] [int] DEFAULT (0) NOT NULL , [auth_option_id] [int] DEFAULT (0) NOT NULL , - [auth_setting] [int] DEFAULT (0) NOT NULL + [auth_setting] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_acl_roles_data] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_acl_roles_data] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_acl_roles_data] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_acl_roles_data] PRIMARY KEY CLUSTERED ( [role_id], [auth_option_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [ath_op_id] ON [phpbb_acl_roles_data]([auth_option_id]) ON [PRIMARY] @@ -153,7 +153,7 @@ CREATE TABLE [phpbb_acl_users] ( [forum_id] [int] DEFAULT (0) NOT NULL , [auth_option_id] [int] DEFAULT (0) NOT NULL , [auth_role_id] [int] DEFAULT (0) NOT NULL , - [auth_setting] [int] DEFAULT (0) NOT NULL + [auth_setting] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -179,15 +179,15 @@ CREATE TABLE [phpbb_banlist] ( [ban_end] [int] DEFAULT (0) NOT NULL , [ban_exclude] [int] DEFAULT (0) NOT NULL , [ban_reason] [varchar] (255) DEFAULT ('') NOT NULL , - [ban_give_reason] [varchar] (255) DEFAULT ('') NOT NULL + [ban_give_reason] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_banlist] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_banlist] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_banlist] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_banlist] PRIMARY KEY CLUSTERED ( [ban_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [ban_end] ON [phpbb_banlist]([ban_end]) ON [PRIMARY] @@ -216,15 +216,15 @@ CREATE TABLE [phpbb_bbcodes] ( [first_pass_match] [text] DEFAULT ('') NOT NULL , [first_pass_replace] [text] DEFAULT ('') NOT NULL , [second_pass_match] [text] DEFAULT ('') NOT NULL , - [second_pass_replace] [text] DEFAULT ('') NOT NULL + [second_pass_replace] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_bbcodes] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_bbcodes] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_bbcodes] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_bbcodes] PRIMARY KEY CLUSTERED ( [bbcode_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [display_on_post] ON [phpbb_bbcodes]([display_on_posting]) ON [PRIMARY] @@ -236,16 +236,16 @@ GO */ CREATE TABLE [phpbb_bookmarks] ( [topic_id] [int] DEFAULT (0) NOT NULL , - [user_id] [int] DEFAULT (0) NOT NULL + [user_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_bookmarks] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_bookmarks] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_bookmarks] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_bookmarks] PRIMARY KEY CLUSTERED ( [topic_id], [user_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -258,15 +258,15 @@ CREATE TABLE [phpbb_bots] ( [bot_name] [varchar] (255) DEFAULT ('') NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , [bot_agent] [varchar] (255) DEFAULT ('') NOT NULL , - [bot_ip] [varchar] (255) DEFAULT ('') NOT NULL + [bot_ip] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_bots] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_bots] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_bots] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_bots] PRIMARY KEY CLUSTERED ( [bot_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [bot_active] ON [phpbb_bots]([bot_active]) ON [PRIMARY] @@ -279,15 +279,15 @@ GO CREATE TABLE [phpbb_config] ( [config_name] [varchar] (255) DEFAULT ('') NOT NULL , [config_value] [varchar] (255) DEFAULT ('') NOT NULL , - [is_dynamic] [int] DEFAULT (0) NOT NULL + [is_dynamic] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_config] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_config] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_config] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_config] PRIMARY KEY CLUSTERED ( [config_name] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [is_dynamic] ON [phpbb_config]([is_dynamic]) ON [PRIMARY] @@ -302,16 +302,16 @@ CREATE TABLE [phpbb_confirm] ( [session_id] [char] (32) DEFAULT ('') NOT NULL , [confirm_type] [int] DEFAULT (0) NOT NULL , [code] [varchar] (8) DEFAULT ('') NOT NULL , - [seed] [int] DEFAULT (0) NOT NULL + [seed] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_confirm] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_confirm] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_confirm] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_confirm] PRIMARY KEY CLUSTERED ( [session_id], [confirm_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [confirm_type] ON [phpbb_confirm]([confirm_type]) ON [PRIMARY] @@ -323,15 +323,15 @@ GO */ CREATE TABLE [phpbb_disallow] ( [disallow_id] [int] IDENTITY (1, 1) NOT NULL , - [disallow_username] [varchar] (255) DEFAULT ('') NOT NULL + [disallow_username] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_disallow] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_disallow] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_disallow] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_disallow] PRIMARY KEY CLUSTERED ( [disallow_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -345,15 +345,15 @@ CREATE TABLE [phpbb_drafts] ( [forum_id] [int] DEFAULT (0) NOT NULL , [save_time] [int] DEFAULT (0) NOT NULL , [draft_subject] [varchar] (255) DEFAULT ('') NOT NULL , - [draft_message] [text] DEFAULT ('') NOT NULL + [draft_message] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_drafts] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_drafts] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_drafts] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_drafts] PRIMARY KEY CLUSTERED ( [draft_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [save_time] ON [phpbb_drafts]([save_time]) ON [PRIMARY] @@ -366,15 +366,15 @@ GO CREATE TABLE [phpbb_extensions] ( [extension_id] [int] IDENTITY (1, 1) NOT NULL , [group_id] [int] DEFAULT (0) NOT NULL , - [extension] [varchar] (100) DEFAULT ('') NOT NULL + [extension] [varchar] (100) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_extensions] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_extensions] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_extensions] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_extensions] PRIMARY KEY CLUSTERED ( [extension_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -390,15 +390,15 @@ CREATE TABLE [phpbb_extension_groups] ( [upload_icon] [varchar] (255) DEFAULT ('') NOT NULL , [max_filesize] [int] DEFAULT (0) NOT NULL , [allowed_forums] [varchar] (8000) DEFAULT ('') NOT NULL , - [allow_in_pm] [int] DEFAULT (0) NOT NULL + [allow_in_pm] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_extension_groups] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_extension_groups] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_extension_groups] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_extension_groups] PRIMARY KEY CLUSTERED ( [group_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -446,15 +446,15 @@ CREATE TABLE [phpbb_forums] ( [prune_next] [int] DEFAULT (0) NOT NULL , [prune_days] [int] DEFAULT (0) NOT NULL , [prune_viewed] [int] DEFAULT (0) NOT NULL , - [prune_freq] [int] DEFAULT (0) NOT NULL + [prune_freq] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_forums] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_forums] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_forums] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_forums] PRIMARY KEY CLUSTERED ( [forum_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [left_right_id] ON [phpbb_forums]([left_id], [right_id]) ON [PRIMARY] @@ -470,17 +470,17 @@ GO CREATE TABLE [phpbb_forums_access] ( [forum_id] [int] DEFAULT (0) NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , - [session_id] [char] (32) DEFAULT ('') NOT NULL + [session_id] [char] (32) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_forums_access] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_forums_access] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_forums_access] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_forums_access] PRIMARY KEY CLUSTERED ( [forum_id], [user_id], [session_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -490,16 +490,16 @@ GO CREATE TABLE [phpbb_forums_track] ( [user_id] [int] DEFAULT (0) NOT NULL , [forum_id] [int] DEFAULT (0) NOT NULL , - [mark_time] [int] DEFAULT (0) NOT NULL + [mark_time] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_forums_track] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_forums_track] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_forums_track] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_forums_track] PRIMARY KEY CLUSTERED ( [user_id], [forum_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -509,7 +509,7 @@ GO CREATE TABLE [phpbb_forums_watch] ( [forum_id] [int] DEFAULT (0) NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , - [notify_status] [int] DEFAULT (0) NOT NULL + [notify_status] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -546,15 +546,15 @@ CREATE TABLE [phpbb_groups] ( [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 + [group_legend] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_groups] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_groups] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_groups] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_groups] PRIMARY KEY CLUSTERED ( [group_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [group_legend_name] ON [phpbb_groups]([group_legend], [group_name]) ON [PRIMARY] @@ -570,15 +570,15 @@ CREATE TABLE [phpbb_icons] ( [icons_width] [int] DEFAULT (0) NOT NULL , [icons_height] [int] DEFAULT (0) NOT NULL , [icons_order] [int] DEFAULT (0) NOT NULL , - [display_on_posting] [int] DEFAULT (1) NOT NULL + [display_on_posting] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_icons] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_icons] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_icons] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_icons] PRIMARY KEY CLUSTERED ( [icons_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [display_on_posting] ON [phpbb_icons]([display_on_posting]) ON [PRIMARY] @@ -594,15 +594,15 @@ CREATE TABLE [phpbb_lang] ( [lang_dir] [varchar] (30) DEFAULT ('') NOT NULL , [lang_english_name] [varchar] (100) DEFAULT ('') NOT NULL , [lang_local_name] [varchar] (255) DEFAULT ('') NOT NULL , - [lang_author] [varchar] (255) DEFAULT ('') NOT NULL + [lang_author] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_lang] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_lang] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_lang] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_lang] PRIMARY KEY CLUSTERED ( [lang_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [lang_iso] ON [phpbb_lang]([lang_iso]) ON [PRIMARY] @@ -622,15 +622,15 @@ CREATE TABLE [phpbb_log] ( [log_ip] [varchar] (40) DEFAULT ('') NOT NULL , [log_time] [int] DEFAULT (0) NOT NULL , [log_operation] [varchar] (4000) DEFAULT ('') NOT NULL , - [log_data] [text] DEFAULT ('') NOT NULL + [log_data] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_log] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_log] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_log] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_log] PRIMARY KEY CLUSTERED ( [log_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [log_type] ON [phpbb_log]([log_type]) ON [PRIMARY] @@ -658,7 +658,7 @@ CREATE TABLE [phpbb_moderator_cache] ( [username] [varchar] (255) DEFAULT ('') NOT NULL , [group_id] [int] DEFAULT (0) NOT NULL , [group_name] [varchar] (255) DEFAULT ('') NOT NULL , - [display_on_index] [int] DEFAULT (1) NOT NULL + [display_on_index] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] GO @@ -683,15 +683,15 @@ CREATE TABLE [phpbb_modules] ( [right_id] [int] DEFAULT (0) NOT NULL , [module_langname] [varchar] (255) DEFAULT ('') NOT NULL , [module_mode] [varchar] (255) DEFAULT ('') NOT NULL , - [module_auth] [varchar] (255) DEFAULT ('') NOT NULL + [module_auth] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_modules] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_modules] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_modules] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_modules] PRIMARY KEY CLUSTERED ( [module_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [left_right_id] ON [phpbb_modules]([left_id], [right_id]) ON [PRIMARY] @@ -711,7 +711,7 @@ CREATE TABLE [phpbb_poll_options] ( [poll_option_id] [int] DEFAULT (0) NOT NULL , [topic_id] [int] DEFAULT (0) NOT NULL , [poll_option_text] [varchar] (4000) DEFAULT ('') NOT NULL , - [poll_option_total] [int] DEFAULT (0) NOT NULL + [poll_option_total] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -729,7 +729,7 @@ CREATE TABLE [phpbb_poll_votes] ( [topic_id] [int] DEFAULT (0) NOT NULL , [poll_option_id] [int] DEFAULT (0) NOT NULL , [vote_user_id] [int] DEFAULT (0) NOT NULL , - [vote_user_ip] [varchar] (40) DEFAULT ('') NOT NULL + [vote_user_ip] [varchar] (40) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO @@ -772,15 +772,15 @@ CREATE TABLE [phpbb_posts] ( [post_edit_reason] [varchar] (255) DEFAULT ('') NOT NULL , [post_edit_user] [int] DEFAULT (0) NOT NULL , [post_edit_count] [int] DEFAULT (0) NOT NULL , - [post_edit_locked] [int] DEFAULT (0) NOT NULL + [post_edit_locked] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_posts] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_posts] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_posts] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_posts] PRIMARY KEY CLUSTERED ( [post_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [forum_id] ON [phpbb_posts]([forum_id]) ON [PRIMARY] @@ -826,15 +826,15 @@ CREATE TABLE [phpbb_privmsgs] ( [message_edit_time] [int] DEFAULT (0) NOT NULL , [message_edit_count] [int] DEFAULT (0) NOT NULL , [to_address] [varchar] (4000) DEFAULT ('') NOT NULL , - [bcc_address] [varchar] (4000) DEFAULT ('') NOT NULL + [bcc_address] [varchar] (4000) DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_privmsgs] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_privmsgs] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_privmsgs] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_privmsgs] PRIMARY KEY CLUSTERED ( [msg_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [author_ip] ON [phpbb_privmsgs]([author_ip]) ON [PRIMARY] @@ -857,15 +857,15 @@ CREATE TABLE [phpbb_privmsgs_folder] ( [folder_id] [int] IDENTITY (1, 1) NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , [folder_name] [varchar] (255) DEFAULT ('') NOT NULL , - [pm_count] [int] DEFAULT (0) NOT NULL + [pm_count] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_privmsgs_folder] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_privmsgs_folder] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_privmsgs_folder] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_privmsgs_folder] PRIMARY KEY CLUSTERED ( [folder_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [user_id] ON [phpbb_privmsgs_folder]([user_id]) ON [PRIMARY] @@ -884,15 +884,15 @@ CREATE TABLE [phpbb_privmsgs_rules] ( [rule_user_id] [int] DEFAULT (0) NOT NULL , [rule_group_id] [int] DEFAULT (0) NOT NULL , [rule_action] [int] DEFAULT (0) NOT NULL , - [rule_folder_id] [int] DEFAULT (0) NOT NULL + [rule_folder_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_privmsgs_rules] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_privmsgs_rules] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_privmsgs_rules] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_privmsgs_rules] PRIMARY KEY CLUSTERED ( [rule_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [user_id] ON [phpbb_privmsgs_rules]([user_id]) ON [PRIMARY] @@ -912,7 +912,7 @@ CREATE TABLE [phpbb_privmsgs_to] ( [pm_replied] [int] DEFAULT (0) NOT NULL , [pm_marked] [int] DEFAULT (0) NOT NULL , [pm_forwarded] [int] DEFAULT (0) NOT NULL , - [folder_id] [int] DEFAULT (0) NOT NULL + [folder_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -946,15 +946,15 @@ CREATE TABLE [phpbb_profile_fields] ( [field_hide] [int] DEFAULT (0) NOT NULL , [field_no_view] [int] DEFAULT (0) NOT NULL , [field_active] [int] DEFAULT (0) NOT NULL , - [field_order] [int] DEFAULT (0) NOT NULL + [field_order] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_profile_fields] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_profile_fields] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_profile_fields] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_profile_fields] PRIMARY KEY CLUSTERED ( [field_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [fld_type] ON [phpbb_profile_fields]([field_type]) ON [PRIMARY] @@ -968,15 +968,15 @@ GO Table: 'phpbb_profile_fields_data' */ CREATE TABLE [phpbb_profile_fields_data] ( - [user_id] [int] DEFAULT (0) NOT NULL + [user_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_profile_fields_data] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_profile_fields_data] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_profile_fields_data] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_profile_fields_data] PRIMARY KEY CLUSTERED ( [user_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -988,17 +988,17 @@ CREATE TABLE [phpbb_profile_fields_lang] ( [lang_id] [int] DEFAULT (0) NOT NULL , [option_id] [int] DEFAULT (0) NOT NULL , [field_type] [int] DEFAULT (0) NOT NULL , - [lang_value] [varchar] (255) DEFAULT ('') NOT NULL + [lang_value] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_profile_fields_lang] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_profile_fields_lang] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_profile_fields_lang] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_profile_fields_lang] PRIMARY KEY CLUSTERED ( [field_id], [lang_id], [option_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1010,16 +1010,16 @@ CREATE TABLE [phpbb_profile_lang] ( [lang_id] [int] DEFAULT (0) NOT NULL , [lang_name] [varchar] (255) DEFAULT ('') NOT NULL , [lang_explain] [varchar] (4000) DEFAULT ('') NOT NULL , - [lang_default_value] [varchar] (255) DEFAULT ('') NOT NULL + [lang_default_value] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_profile_lang] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_profile_lang] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_profile_lang] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_profile_lang] PRIMARY KEY CLUSTERED ( [field_id], [lang_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1031,15 +1031,15 @@ CREATE TABLE [phpbb_ranks] ( [rank_title] [varchar] (255) DEFAULT ('') NOT NULL , [rank_min] [int] DEFAULT (0) NOT NULL , [rank_special] [int] DEFAULT (0) NOT NULL , - [rank_image] [varchar] (255) DEFAULT ('') NOT NULL + [rank_image] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_ranks] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_ranks] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_ranks] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_ranks] PRIMARY KEY CLUSTERED ( [rank_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1054,15 +1054,15 @@ CREATE TABLE [phpbb_reports] ( [user_notify] [int] DEFAULT (0) NOT NULL , [report_closed] [int] DEFAULT (0) NOT NULL , [report_time] [int] DEFAULT (0) NOT NULL , - [report_text] [text] DEFAULT ('') NOT NULL + [report_text] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_reports] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_reports] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_reports] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_reports] PRIMARY KEY CLUSTERED ( [report_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1073,15 +1073,15 @@ CREATE TABLE [phpbb_reports_reasons] ( [reason_id] [int] IDENTITY (1, 1) NOT NULL , [reason_title] [varchar] (255) DEFAULT ('') NOT NULL , [reason_description] [text] DEFAULT ('') NOT NULL , - [reason_order] [int] DEFAULT (0) NOT NULL + [reason_order] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_reports_reasons] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_reports_reasons] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_reports_reasons] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_reports_reasons] PRIMARY KEY CLUSTERED ( [reason_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1092,15 +1092,15 @@ CREATE TABLE [phpbb_search_results] ( [search_key] [varchar] (32) DEFAULT ('') NOT NULL , [search_time] [int] DEFAULT (0) NOT NULL , [search_keywords] [text] DEFAULT ('') NOT NULL , - [search_authors] [text] DEFAULT ('') NOT NULL + [search_authors] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_search_results] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_search_results] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_search_results] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_search_results] PRIMARY KEY CLUSTERED ( [search_key] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1111,15 +1111,15 @@ CREATE TABLE [phpbb_search_wordlist] ( [word_id] [int] IDENTITY (1, 1) NOT NULL , [word_text] [varchar] (255) DEFAULT ('') NOT NULL , [word_common] [int] DEFAULT (0) NOT NULL , - [word_count] [int] DEFAULT (0) NOT NULL + [word_count] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_search_wordlist] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_search_wordlist] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_search_wordlist] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_search_wordlist] PRIMARY KEY CLUSTERED ( [word_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE UNIQUE INDEX [wrd_txt] ON [phpbb_search_wordlist]([word_text]) ON [PRIMARY] @@ -1135,7 +1135,7 @@ GO CREATE TABLE [phpbb_search_wordmatch] ( [post_id] [int] DEFAULT (0) NOT NULL , [word_id] [int] DEFAULT (0) NOT NULL , - [title_match] [int] DEFAULT (0) NOT NULL + [title_match] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -1165,15 +1165,15 @@ CREATE TABLE [phpbb_sessions] ( [session_page] [varchar] (255) DEFAULT ('') NOT NULL , [session_viewonline] [int] DEFAULT (1) NOT NULL , [session_autologin] [int] DEFAULT (0) NOT NULL , - [session_admin] [int] DEFAULT (0) NOT NULL + [session_admin] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_sessions] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_sessions] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_sessions] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_sessions] PRIMARY KEY CLUSTERED ( [session_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [session_time] ON [phpbb_sessions]([session_time]) ON [PRIMARY] @@ -1193,16 +1193,16 @@ CREATE TABLE [phpbb_sessions_keys] ( [key_id] [char] (32) DEFAULT ('') NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , [last_ip] [varchar] (40) DEFAULT ('') NOT NULL , - [last_login] [int] DEFAULT (0) NOT NULL + [last_login] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_sessions_keys] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_sessions_keys] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_sessions_keys] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_sessions_keys] PRIMARY KEY CLUSTERED ( [key_id], [user_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [last_login] ON [phpbb_sessions_keys]([last_login]) ON [PRIMARY] @@ -1216,15 +1216,15 @@ CREATE TABLE [phpbb_sitelist] ( [site_id] [int] IDENTITY (1, 1) NOT NULL , [site_ip] [varchar] (40) DEFAULT ('') NOT NULL , [site_hostname] [varchar] (255) DEFAULT ('') NOT NULL , - [ip_exclude] [int] DEFAULT (0) NOT NULL + [ip_exclude] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_sitelist] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_sitelist] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_sitelist] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_sitelist] PRIMARY KEY CLUSTERED ( [site_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1239,15 +1239,15 @@ CREATE TABLE [phpbb_smilies] ( [smiley_width] [int] DEFAULT (0) NOT NULL , [smiley_height] [int] DEFAULT (0) NOT NULL , [smiley_order] [int] DEFAULT (0) NOT NULL , - [display_on_posting] [int] DEFAULT (1) NOT NULL + [display_on_posting] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_smilies] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_smilies] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_smilies] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_smilies] PRIMARY KEY CLUSTERED ( [smiley_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [display_on_post] ON [phpbb_smilies]([display_on_posting]) ON [PRIMARY] @@ -1264,15 +1264,15 @@ CREATE TABLE [phpbb_styles] ( [style_active] [int] DEFAULT (1) NOT NULL , [template_id] [int] DEFAULT (0) NOT NULL , [theme_id] [int] DEFAULT (0) NOT NULL , - [imageset_id] [int] DEFAULT (0) NOT NULL + [imageset_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_styles] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_styles] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_styles] PRIMARY KEY CLUSTERED ( [style_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE UNIQUE INDEX [style_name] ON [phpbb_styles]([style_name]) ON [PRIMARY] @@ -1299,15 +1299,15 @@ CREATE TABLE [phpbb_styles_template] ( [bbcode_bitfield] [varchar] (255) DEFAULT ('kNg=') 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 + [template_inherit_path] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_styles_template] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles_template] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_styles_template] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_styles_template] PRIMARY KEY CLUSTERED ( [template_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE UNIQUE INDEX [tmplte_nm] ON [phpbb_styles_template]([template_name]) ON [PRIMARY] @@ -1322,7 +1322,7 @@ CREATE TABLE [phpbb_styles_template_data] ( [template_filename] [varchar] (100) DEFAULT ('') NOT NULL , [template_included] [varchar] (8000) DEFAULT ('') NOT NULL , [template_mtime] [int] DEFAULT (0) NOT NULL , - [template_data] [text] DEFAULT ('') NOT NULL + [template_data] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO @@ -1343,15 +1343,15 @@ CREATE TABLE [phpbb_styles_theme] ( [theme_path] [varchar] (100) DEFAULT ('') NOT NULL , [theme_storedb] [int] DEFAULT (0) NOT NULL , [theme_mtime] [int] DEFAULT (0) NOT NULL , - [theme_data] [text] DEFAULT ('') NOT NULL + [theme_data] [text] DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_styles_theme] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles_theme] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_styles_theme] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_styles_theme] PRIMARY KEY CLUSTERED ( [theme_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE UNIQUE INDEX [theme_name] ON [phpbb_styles_theme]([theme_name]) ON [PRIMARY] @@ -1365,15 +1365,15 @@ CREATE TABLE [phpbb_styles_imageset] ( [imageset_id] [int] IDENTITY (1, 1) NOT NULL , [imageset_name] [varchar] (255) DEFAULT ('') NOT NULL , [imageset_copyright] [varchar] (255) DEFAULT ('') NOT NULL , - [imageset_path] [varchar] (100) DEFAULT ('') NOT NULL + [imageset_path] [varchar] (100) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_styles_imageset] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles_imageset] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_styles_imageset] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_styles_imageset] PRIMARY KEY CLUSTERED ( [imageset_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE UNIQUE INDEX [imgset_nm] ON [phpbb_styles_imageset]([imageset_name]) ON [PRIMARY] @@ -1390,15 +1390,15 @@ CREATE TABLE [phpbb_styles_imageset_data] ( [image_lang] [varchar] (30) DEFAULT ('') NOT NULL , [image_height] [int] DEFAULT (0) NOT NULL , [image_width] [int] DEFAULT (0) NOT NULL , - [imageset_id] [int] DEFAULT (0) NOT NULL + [imageset_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_styles_imageset_data] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles_imageset_data] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_styles_imageset_data] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_styles_imageset_data] PRIMARY KEY CLUSTERED ( [image_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [i_d] ON [phpbb_styles_imageset_data]([imageset_id]) ON [PRIMARY] @@ -1442,15 +1442,15 @@ CREATE TABLE [phpbb_topics] ( [poll_length] [int] DEFAULT (0) NOT NULL , [poll_max_options] [int] DEFAULT (1) NOT NULL , [poll_last_vote] [int] DEFAULT (0) NOT NULL , - [poll_vote_change] [int] DEFAULT (0) NOT NULL + [poll_vote_change] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_topics] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_topics] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_topics] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_topics] PRIMARY KEY CLUSTERED ( [topic_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [forum_id] ON [phpbb_topics]([forum_id]) ON [PRIMARY] @@ -1479,16 +1479,16 @@ CREATE TABLE [phpbb_topics_track] ( [user_id] [int] DEFAULT (0) NOT NULL , [topic_id] [int] DEFAULT (0) NOT NULL , [forum_id] [int] DEFAULT (0) NOT NULL , - [mark_time] [int] DEFAULT (0) NOT NULL + [mark_time] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_topics_track] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_topics_track] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_topics_track] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_topics_track] PRIMARY KEY CLUSTERED ( [user_id], [topic_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [forum_id] ON [phpbb_topics_track]([forum_id]) ON [PRIMARY] @@ -1501,16 +1501,16 @@ GO CREATE TABLE [phpbb_topics_posted] ( [user_id] [int] DEFAULT (0) NOT NULL , [topic_id] [int] DEFAULT (0) NOT NULL , - [topic_posted] [int] DEFAULT (0) NOT NULL + [topic_posted] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_topics_posted] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_topics_posted] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_topics_posted] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_topics_posted] PRIMARY KEY CLUSTERED ( [user_id], [topic_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1520,7 +1520,7 @@ GO CREATE TABLE [phpbb_topics_watch] ( [topic_id] [int] DEFAULT (0) NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , - [notify_status] [int] DEFAULT (0) NOT NULL + [notify_status] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO @@ -1541,7 +1541,7 @@ CREATE TABLE [phpbb_user_group] ( [group_id] [int] DEFAULT (0) NOT NULL , [user_id] [int] DEFAULT (0) NOT NULL , [group_leader] [int] DEFAULT (0) NOT NULL , - [user_pending] [int] DEFAULT (1) NOT NULL + [user_pending] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] GO @@ -1631,15 +1631,15 @@ CREATE TABLE [phpbb_users] ( [user_interests] [varchar] (4000) DEFAULT ('') NOT NULL , [user_actkey] [varchar] (32) DEFAULT ('') NOT NULL , [user_newpasswd] [varchar] (40) DEFAULT ('') NOT NULL , - [user_form_salt] [varchar] (32) DEFAULT ('') NOT NULL + [user_form_salt] [varchar] (32) DEFAULT ('') NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -ALTER TABLE [phpbb_users] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_users] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_users] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_users] PRIMARY KEY CLUSTERED ( [user_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO CREATE INDEX [user_birthday] ON [phpbb_users]([user_birthday]) ON [PRIMARY] @@ -1663,15 +1663,15 @@ CREATE TABLE [phpbb_warnings] ( [user_id] [int] DEFAULT (0) NOT NULL , [post_id] [int] DEFAULT (0) NOT NULL , [log_id] [int] DEFAULT (0) NOT NULL , - [warning_time] [int] DEFAULT (0) NOT NULL + [warning_time] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_warnings] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_warnings] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_warnings] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_warnings] PRIMARY KEY CLUSTERED ( [warning_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1681,15 +1681,15 @@ GO CREATE TABLE [phpbb_words] ( [word_id] [int] IDENTITY (1, 1) NOT NULL , [word] [varchar] (255) DEFAULT ('') NOT NULL , - [replacement] [varchar] (255) DEFAULT ('') NOT NULL + [replacement] [varchar] (255) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_words] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_words] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_words] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_words] PRIMARY KEY CLUSTERED ( [word_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO @@ -1700,16 +1700,16 @@ CREATE TABLE [phpbb_zebra] ( [user_id] [int] DEFAULT (0) NOT NULL , [zebra_id] [int] DEFAULT (0) NOT NULL , [friend] [int] DEFAULT (0) NOT NULL , - [foe] [int] DEFAULT (0) NOT NULL + [foe] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO -ALTER TABLE [phpbb_zebra] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_zebra] PRIMARY KEY CLUSTERED +ALTER TABLE [phpbb_zebra] WITH NOCHECK ADD + CONSTRAINT [PK_phpbb_zebra] PRIMARY KEY CLUSTERED ( [user_id], [zebra_id] - ) ON [PRIMARY] + ) ON [PRIMARY] GO diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index a18b99eecd..146c58904c 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -49,7 +49,7 @@ CREATE TABLE phpbb_acl_options ( is_local tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, founder_only tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (auth_option_id), - KEY auth_option (auth_option) + UNIQUE auth_option (auth_option) ); diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 8b001f4d1b..81f8266f4d 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -49,7 +49,7 @@ CREATE TABLE phpbb_acl_options ( is_local tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, founder_only tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, PRIMARY KEY (auth_option_id), - KEY auth_option (auth_option) + UNIQUE auth_option (auth_option) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index 401106ac83..50f3ee1f80 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -119,12 +119,11 @@ CREATE TABLE phpbb_acl_options ( is_global number(1) DEFAULT '0' NOT NULL, is_local number(1) DEFAULT '0' NOT NULL, founder_only number(1) DEFAULT '0' NOT NULL, - CONSTRAINT pk_phpbb_acl_options PRIMARY KEY (auth_option_id) + CONSTRAINT pk_phpbb_acl_options PRIMARY KEY (auth_option_id), + CONSTRAINT u_phpbb_auth_option UNIQUE (auth_option) ) / -CREATE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options (auth_option) -/ CREATE SEQUENCE phpbb_acl_options_seq / @@ -821,7 +820,7 @@ CREATE TABLE phpbb_poll_votes ( topic_id number(8) DEFAULT '0' NOT NULL, poll_option_id number(4) DEFAULT '0' NOT NULL, vote_user_id number(8) DEFAULT '0' NOT NULL, - vote_user_ip varchar2(40) DEFAULT '' + vote_user_ip varchar2(40) DEFAULT '' ) / @@ -1465,7 +1464,7 @@ CREATE TABLE phpbb_styles_template_data ( template_filename varchar2(100) DEFAULT '' , template_included clob DEFAULT '' , template_mtime number(11) DEFAULT '0' NOT NULL, - template_data clob DEFAULT '' + template_data clob DEFAULT '' ) / diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index 077078c40f..9736363104 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -140,7 +140,7 @@ CREATE TABLE phpbb_acl_options ( PRIMARY KEY (auth_option_id) ); -CREATE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options (auth_option); +CREATE UNIQUE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options (auth_option); /* Table: 'phpbb_acl_roles' diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 1e2669aeb5..6deebd9005 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -64,6 +64,10 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_foreground_noise', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_x_grid', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_wave', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_3d_noise', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_fonts', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('confirm_refresh', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_attachment_content', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_dnsbl', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('chg_passforce', '0'); @@ -156,6 +160,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize', '26 INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize_pm', '262144'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '3'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_name_chars', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_num_search_keywords', '10'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_pass_chars', '30'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_poll_options', '10'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_chars', '60000'); @@ -192,7 +197,6 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation INSERT INTO phpbb_config (config_name, config_value) VALUES ('script_path', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_block_size', '250'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_gc', '7200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_indexing_state', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_interval', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_anonymous_interval', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', 'fulltext_native'); @@ -218,7 +222,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.4'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.0.5-RC1'); 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'); @@ -237,6 +241,7 @@ INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_s INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed_last_update', '0', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_date', '0', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_users', '0', 1); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_indexing_state', '', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_last_gc', '0', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('session_last_gc', '0', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('upload_dir_size', '0', 1); diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index e60a194839..36686955a9 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -51,7 +51,7 @@ CREATE TABLE phpbb_acl_options ( founder_only INTEGER UNSIGNED NOT NULL DEFAULT '0' ); -CREATE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options (auth_option); +CREATE UNIQUE INDEX phpbb_acl_options_auth_option ON phpbb_acl_options (auth_option); # Table: 'phpbb_acl_roles' CREATE TABLE phpbb_acl_roles ( diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index fc61cd2eaa..7c2f3a24bb 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -243,6 +243,16 @@ $lang = array_merge($lang, array( 'CAPTCHA_GD_X_GRID_EXPLAIN' => 'Use lower settings of this to make the GD based CAPTCHA harder. 0 will disable x-axis background noise.', 'CAPTCHA_GD_Y_GRID' => 'GD CAPTCHA background noise y-axis', 'CAPTCHA_GD_Y_GRID_EXPLAIN' => 'Use lower settings of this to make the GD based CAPTCHA harder. 0 will disable y-axis background noise.', + 'CAPTCHA_GD_WAVE' => 'GD CAPTCHA wave distortion', + 'CAPTCHA_GD_WAVE_EXPLAIN' => 'This applies a wave distortion to the CAPTCHA.', + 'CAPTCHA_GD_3D_NOISE' => 'Add 3D-noise objects', + 'CAPTCHA_GD_3D_NOISE_EXPLAIN' => 'This adds additional objects to the CAPTCHA, over the letters.', + 'CAPTCHA_GD_FONTS' => 'Use different fonts', + 'CAPTCHA_GD_FONTS_EXPLAIN' => 'This setting controls how many different letter shapes are used. You can just use the default shapes or introduce altered letters. Adding lowercase letters is also possible.', + 'CAPTCHA_FONT_DEFAULT' => 'Default', + 'CAPTCHA_FONT_NEW' => 'New Shapes', + 'CAPTCHA_FONT_LOWER' => 'Also use lowercase', + 'CAPTCHA_PREVIEW_MSG' => 'Your changes to the visual confirmation setting were not saved. This is just a preview.', 'CAPTCHA_PREVIEW_EXPLAIN' => 'The CAPTCHA as it will look like using the current settings. Use the preview button to refresh. Note that captchas are randomized and will differ from one view to the next.', @@ -250,6 +260,8 @@ $lang = array_merge($lang, array( 'VISUAL_CONFIRM_POST_EXPLAIN' => 'Requires anonymous users to enter a random code matching an image to help prevent mass postings.', 'VISUAL_CONFIRM_REG' => 'Enable visual confirmation for registrations', 'VISUAL_CONFIRM_REG_EXPLAIN' => 'Requires new users to enter a random code matching an image to help prevent mass registrations.', + 'VISUAL_CONFIRM_REFRESH' => 'Enable users to refresh the confirmation image', + 'VISUAL_CONFIRM_REFRESH_EXPLAIN' => 'Allows users to request new confirmation codes, if they are unable to solve the VC during registration.', )); // Cookie Settings diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index c1317b4615..6cfcc44d21 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -201,7 +201,7 @@ $lang = array_merge($lang, array( 'ADMIN_INDEX' => 'Admin index', 'ADMIN_PANEL' => 'Administration Control Panel', - 'ADM_LOGOUT' => 'ACP Logout', + 'ADM_LOGOUT' => 'ACP Logout', 'ADM_LOGGED_OUT' => 'Successfully logged out from Administration Control Panel', 'BACK' => 'Back', @@ -515,11 +515,11 @@ $lang = array_merge($lang, array( 'LOG_FORUM_DEL_FORUMS' => 'Deleted forum and its subforums
          » %s', 'LOG_FORUM_DEL_MOVE_FORUMS' => 'Deleted forum and moved subforums to %1$s
          » %2$s', 'LOG_FORUM_DEL_MOVE_POSTS' => 'Deleted forum and moved posts to %1$s
          » %2$s', - 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS' => 'Deleted forum and its subforums, moved messages to %1$s
          » %2$s', + 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS' => 'Deleted forum and its subforums, moved posts to %1$s
          » %2$s', 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS' => 'Deleted forum, moved posts to %1$s and subforums to %2$s
          » %3$s', - 'LOG_FORUM_DEL_POSTS' => 'Deleted forum and its messages
          » %s', - 'LOG_FORUM_DEL_POSTS_FORUMS' => 'Deleted forum, its messages and subforums
          » %s', - 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS' => 'Deleted forum and its messages, moved subforums to %1$s
          » %2$s', + 'LOG_FORUM_DEL_POSTS' => 'Deleted forum and its posts
          » %s', + 'LOG_FORUM_DEL_POSTS_FORUMS' => 'Deleted forum, its posts and subforums
          » %s', + 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS' => 'Deleted forum and its posts, moved subforums to %1$s
          » %2$s', 'LOG_FORUM_EDIT' => 'Edited forum details
          » %s', 'LOG_FORUM_MOVE_DOWN' => 'Moved forum %1$s below %2$s', 'LOG_FORUM_MOVE_UP' => 'Moved forum %1$s above %2$s', diff --git a/phpBB/language/en/acp/forums.php b/phpBB/language/en/acp/forums.php index 84f280c779..52919f4f40 100644 --- a/phpBB/language/en/acp/forums.php +++ b/phpBB/language/en/acp/forums.php @@ -81,6 +81,7 @@ $lang = array_merge($lang, array( 'FORUM_EDIT_EXPLAIN' => 'The form below will allow you to customise this forum. Please note that moderation and post count controls are set via forum permissions for each user or usergroup.', 'FORUM_IMAGE' => 'Forum image', 'FORUM_IMAGE_EXPLAIN' => 'Location, relative to the phpBB root directory, of an additional image to associate with this forum.', + 'FORUM_IMAGE_NO_EXIST' => 'The specified forum image does not exist', 'FORUM_LINK_EXPLAIN' => 'Full URL (including the protocol, i.e.: http://) to the destination location that clicking this forum will take the user, e.g.: http://www.phpbb.com/.', 'FORUM_LINK_TRACK' => 'Track link redirects', 'FORUM_LINK_TRACK_EXPLAIN' => 'Records the number of times a forum link was clicked.', diff --git a/phpBB/language/en/acp/permissions.php b/phpBB/language/en/acp/permissions.php index bba425d076..920643d927 100644 --- a/phpBB/language/en/acp/permissions.php +++ b/phpBB/language/en/acp/permissions.php @@ -50,7 +50,7 @@ $lang = array_merge($lang, array(

          Permission Masks

          These are used to view the effective permissions assigned to Users, Moderators (Local and Global), Administrators or Forums.

          - +

          For further information on setting up and managing permissions on your phpBB3 board, please see Chapter 1.5 of our Quick Start Guide.

          @@ -71,7 +71,7 @@ $lang = array_merge($lang, array( 'ACL_TYPE_GLOBAL_M_' => 'Global Moderator permissions', 'ACL_TYPE_LOCAL_M_' => 'Forum Moderator permissions', 'ACL_TYPE_LOCAL_F_' => 'Forum permissions', - + 'ACL_NO' => 'No', 'ACL_VIEW' => 'Viewing permissions', 'ACL_VIEW_EXPLAIN' => 'Here you can see the effective permissions the user/group is having. A red square indicates that the user/group does not have the permission, a green square indicates that the user/group does have the permission.', @@ -83,10 +83,10 @@ $lang = array_merge($lang, array( 'ACP_GLOBAL_MODERATORS_EXPLAIN' => 'Here you can assign global moderator permissions to users or groups. These moderators are like ordinary moderators except they have access to every forum on your board.', 'ACP_GROUPS_FORUM_PERMISSIONS_EXPLAIN' => 'Here you can assign forum permissions to groups.', 'ACP_GROUPS_PERMISSIONS_EXPLAIN' => 'Here you can assign global permissions to groups - user permissions, global moderator permissions and administrator permissions. User permissions include capabilities such as the use of avatars, sending private messages, et cetera; global moderator permissions such as approving posts, manage topics, manage bans, et cetera and lastly administrator permissions such as altering permissions, define custom BBCodes, manage forums, et cetera. Individual users permissions should only be changed in rare occasions, the preferred method is putting users in groups and assigning the group’s permissions.', - 'ACP_ADMIN_ROLES_EXPLAIN' => 'Here you are able to manage the roles for administrative permissions. Roles are effective permissions, if you change a role the items having this role assigned will change it’s permissions too.', - 'ACP_FORUM_ROLES_EXPLAIN' => 'Here you are able to manage the roles for forum permissions. Roles are effective permissions, if you change a role the items having this role assigned will change it’s permissions too.', - 'ACP_MOD_ROLES_EXPLAIN' => 'Here you are able to manage the roles for moderative permissions. Roles are effective permissions, if you change a role the items having this role assigned will change it’s permissions too.', - 'ACP_USER_ROLES_EXPLAIN' => 'Here you are able to manage the roles for user permissions. Roles are effective permissions, if you change a role the items having this role assigned will change it’s permissions too.', + 'ACP_ADMIN_ROLES_EXPLAIN' => 'Here you are able to manage the roles for administrative permissions. Roles are effective permissions, if you change a role the items having this role assigned will change its permissions too.', + 'ACP_FORUM_ROLES_EXPLAIN' => 'Here you are able to manage the roles for forum permissions. Roles are effective permissions, if you change a role the items having this role assigned will change its permissions too.', + 'ACP_MOD_ROLES_EXPLAIN' => 'Here you are able to manage the roles for moderative permissions. Roles are effective permissions, if you change a role the items having this role assigned will change its permissions too.', + 'ACP_USER_ROLES_EXPLAIN' => 'Here you are able to manage the roles for user permissions. Roles are effective permissions, if you change a role the items having this role assigned will change its permissions too.', 'ACP_USERS_FORUM_PERMISSIONS_EXPLAIN' => 'Here you can assign forum permissions to users.', 'ACP_USERS_PERMISSIONS_EXPLAIN' => 'Here you can assign global permissions to users - user permissions, global moderator permissions and administrator permissions. User permissions include capabilities such as the use of avatars, sending private messages, et cetera; global moderator permissions such as approving posts, manage topics, manage bans, et cetera and lastly administrator permissions such as altering permissions, define custom BBCodes, manage forums, et cetera. To alter these settings for large numbers of users the Group permissions system is the preferred method. User’s permissions should only be changed in rare occasions, the preferred method is putting users in groups and assigning the group’s permissions.', 'ACP_VIEW_ADMIN_PERMISSIONS_EXPLAIN' => 'Here you can view the effective administrative permissions assigned to the selected users/groups.', @@ -196,7 +196,7 @@ $lang = array_merge($lang, array( 'ROLE_DESCRIPTION_USER_NOAVATAR' => 'Has a limited feature set and is not allowed to use the Avatar feature.', 'ROLE_DESCRIPTION_USER_NOPM' => 'Has a limited feature set, and is not allowed to use Private Messages.', 'ROLE_DESCRIPTION_USER_STANDARD' => 'Can access most but not all user features. Cannot change user name or ignore the flood limit, for instance.', - + 'ROLE_DESCRIPTION_EXPLAIN' => 'You are able to enter a short explanation of what the role is doing or for what it is meant for. The text you enter here will be displayed within the permissions screens too.', 'ROLE_DESCRIPTION_LONG' => 'The role description is too long, please limit it to 4000 characters.', 'ROLE_DETAILS' => 'Role details', diff --git a/phpBB/language/en/acp/posting.php b/phpBB/language/en/acp/posting.php index 66ce911ff6..01453b85ef 100644 --- a/phpBB/language/en/acp/posting.php +++ b/phpBB/language/en/acp/posting.php @@ -185,7 +185,7 @@ $lang = array_merge($lang, array( // Word censors $lang = array_merge($lang, array( - 'ACP_WORDS_EXPLAIN' => 'From this control panel you can add, edit, and remove words that will be automatically censored on your forums. In addition people will not be allowed to register with usernames containing these words. Wildcards (*) are accepted in the word field, e.g. *test* will match detestable, test* would match testing, *test would match detest.', + 'ACP_WORDS_EXPLAIN' => 'From this control panel you can add, edit, and remove words that will be automatically censored on your forums. People are still allowed to register with usernames containing these words. Wildcards (*) are accepted in the word field, e.g. *test* will match detestable, test* would match testing, *test would match detest.', 'ADD_WORD' => 'Add new word', 'EDIT_WORD' => 'Edit word censor', diff --git a/phpBB/language/en/acp/profile.php b/phpBB/language/en/acp/profile.php index 83e0fa06ca..ef291585bc 100644 --- a/phpBB/language/en/acp/profile.php +++ b/phpBB/language/en/acp/profile.php @@ -66,7 +66,7 @@ $lang = array_merge($lang, array( 'DISPLAY_AT_PROFILE_EXPLAIN' => 'The user is able to change this profile field within the user control panel.', 'DISPLAY_AT_REGISTER' => 'Display on registration screen', 'DISPLAY_AT_REGISTER_EXPLAIN' => 'If this option is enabled, the field will be displayed on registration.', - 'DISPLAY_PROFILE_FIELD' => 'Display profile field', + 'DISPLAY_PROFILE_FIELD' => 'Publicly display profile field', 'DISPLAY_PROFILE_FIELD_EXPLAIN' => 'The profile field will be shown in all locations allowed within the load settings. Setting this to “no” will hide the field from topic pages, profiles and the memberlist.', 'DROPDOWN_ENTRIES_EXPLAIN' => 'Enter your options now, every option in one line.', diff --git a/phpBB/language/en/acp/search.php b/phpBB/language/en/acp/search.php index 8d7efa3308..88eed9d948 100644 --- a/phpBB/language/en/acp/search.php +++ b/phpBB/language/en/acp/search.php @@ -72,6 +72,8 @@ $lang = array_merge($lang, array( 'MAX_SEARCH_CHARS' => 'Max characters indexed by search', 'MAX_SEARCH_CHARS_EXPLAIN' => 'Words with no more than this many characters will be indexed for searching.', + 'MAX_NUM_SEARCH_KEYWORDS' => 'Maximum number of allowed keywords', + 'MAX_NUM_SEARCH_KEYWORDS_EXPLAIN' => 'Maximum number of words the user is able to search for. A value of 0 allows an unlimited number of words.', 'MIN_SEARCH_CHARS' => 'Min characters indexed by search', 'MIN_SEARCH_CHARS_EXPLAIN' => 'Words with at least this many characters will be indexed for searching.', 'MIN_SEARCH_AUTHOR_CHARS' => 'Min author name characters', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 7e889db7d8..12510d5d5e 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -87,7 +87,7 @@ $lang = array_merge($lang, array( 'AVATAR_NO_SIZE' => 'The width or height of the linked avatar could not be determined. Please enter them manually.', 'AVATAR_PARTIAL_UPLOAD' => 'The specified file was only partially uploaded.', 'AVATAR_PHP_SIZE_NA' => 'The avatar’s filesize is too large.
          The maximum allowed filesize set in php.ini could not be determined.', - 'AVATAR_PHP_SIZE_OVERRUN' => 'The avatar’s filesize is too large. The maximum allowed upload size is %d MB.
          Please note this is set in php.ini and cannot be overridden.', + 'AVATAR_PHP_SIZE_OVERRUN' => 'The avatar’s filesize is too large. The maximum allowed upload size is %1$d %2$s.
          Please note this is set in php.ini and cannot be overridden.', 'AVATAR_URL_INVALID' => 'The URL you specified is invalid.', 'AVATAR_URL_NOT_FOUND' => 'The file specified could not be found.', 'AVATAR_WRONG_FILESIZE' => 'The avatar’s filesize must be between 0 and %1d %2s.', @@ -158,7 +158,7 @@ $lang = array_merge($lang, array( 'VIEWED_COUNT_NONE' => 'Not viewed yet', 'EDIT_POST' => 'Edit post', - 'EMAIL' => 'E-mail', + 'EMAIL' => 'E-mail', // Short form for EMAIL_ADDRESS 'EMAIL_ADDRESS' => 'E-mail address', 'EMAIL_SMTP_ERROR_RESPONSE' => 'Ran into problems sending e-mail at Line %1$s. Response: %2$s.', 'EMPTY_SUBJECT' => 'You must specify a subject when posting a new topic.', @@ -228,6 +228,8 @@ $lang = array_merge($lang, array( 'FTP_USERNAME_EXPLAIN' => 'Username used to connect to your server.', 'GENERAL_ERROR' => 'General Error', + 'GB' => 'GB', + 'GIB' => 'GiB', 'GO' => 'Go', 'GOTO_PAGE' => 'Go to page', 'GROUP' => 'Group', @@ -520,7 +522,7 @@ $lang = array_merge($lang, array( 'SELECT_ALL_CODE' => 'Select all', 'SELECT_DESTINATION_FORUM' => 'Please select a destination forum', 'SELECT_FORUM' => 'Select a forum', - 'SEND_EMAIL' => 'E-mail', + 'SEND_EMAIL' => 'E-mail', // Used for submit buttons 'SEND_EMAIL_USER' => 'E-mail', // Used as: {L_SEND_EMAIL_USER} {USERNAME} -> E-mail UserX 'SEND_PRIVATE_MESSAGE' => 'Send private message', 'SETTINGS' => 'Settings', diff --git a/phpBB/language/en/email/newtopic_notify.txt b/phpBB/language/en/email/newtopic_notify.txt index 1c471a3c01..529bbf0f8f 100644 --- a/phpBB/language/en/email/newtopic_notify.txt +++ b/phpBB/language/en/email/newtopic_notify.txt @@ -2,7 +2,7 @@ Subject: New topic notification - "{FORUM_NAME}" Hello {USERNAME}, -You are receiving this notification because you are watching the forum, "{FORUM_NAME}" at "{SITENAME}". This forum has received a new topic since your last visit, "{TOPIC_TITLE}". You can use the following link to view forum, no more notifications will be sent until you visit the forum. +You are receiving this notification because you are watching the forum, "{FORUM_NAME}" at "{SITENAME}". This forum has received a new topic since your last visit, "{TOPIC_TITLE}". You can use the following link to view the forum, no more notifications will be sent until you visit the forum. {U_FORUM} diff --git a/phpBB/language/en/help_bbcode.php b/phpBB/language/en/help_bbcode.php index 00b00c9e19..ed6fea96d3 100644 --- a/phpBB/language/en/help_bbcode.php +++ b/phpBB/language/en/help_bbcode.php @@ -76,7 +76,7 @@ $help = array( ), array( 0 => 'Creating an Ordered list', - 1 => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use [list=1][/list] to create a numbered list or alternatively [list=a][/list] for an alphabetical list. As with the unordered list, items are specified using [*]. For example:

          [list=1]
          [*]Go to the shops
          [*]Buy a new computer
          [*]Swear at computer when it crashes
          [/list]

          will generate the following:
          1. Go to the shops
          2. Buy a new computer
          3. Swear at computer when it crashes
          Whereas for an alphabetical list you would use:

          [list=a]
          [*]The first possible answer
          [*]The second possible answer
          [*]The third possible answer
          [/list]

          giving
          1. The first possible answer
          2. The second possible answer
          3. The third possible answer
          ' + 1 => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use [list=1][/list] to create a numbered list or alternatively [list=a][/list] for an alphabetical list. As with the unordered list, items are specified using [*]. For example:

          [list=1]
          [*]Go to the shops
          [*]Buy a new computer
          [*]Swear at computer when it crashes
          [/list]

          will generate the following:
          1. Go to the shops
          2. Buy a new computer
          3. Swear at computer when it crashes
          Whereas for an alphabetical list you would use:

          [list=a]
          [*]The first possible answer
          [*]The second possible answer
          [*]The third possible answer
          [/list]

          giving
          1. The first possible answer
          2. The second possible answer
          3. The third possible answer
          ' ), array( 0 => '--', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index ac3e90543b..d3fd8d5e26 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -269,6 +269,8 @@ $lang = array_merge($lang, array( 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:
          »%s.', 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:
          »%s.', + 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.
          Before you proceed the update, you need to upgrade the schema.

          Please refer to the Knowledge Base article about upgrading the MySQL schema. If you encounter problems, please use our support forums.', + 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases

          %s', 'NEXT_STEP' => 'Proceed to next step', 'NOT_FOUND' => 'Cannot find', @@ -381,7 +383,7 @@ $lang = array_merge($lang, array( 'COMPLETE_LOGIN_TO_BOARD' => 'You should now login to your board and check if everything is working fine. Do not forget to delete, rename or move your install directory!', 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished - 'CURRENT_FILE' => 'Beginning of current original file', + 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update', 'CURRENT_VERSION' => 'Current version', 'DATABASE_TYPE' => 'Database type', @@ -391,7 +393,7 @@ $lang = array_merge($lang, array( 'DESTINATION' => 'Destination file', 'DIFF_INLINE' => 'Inline', 'DIFF_RAW' => 'Raw unified diff', - 'DIFF_SEP_EXPLAIN' => 'End of current original file / Beginning of new updated file', + 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file', 'DIFF_SIDE_BY_SIDE' => 'Side by Side', 'DIFF_UNIFIED' => 'Unified diff', 'DO_NOT_UPDATE' => 'Do not update this file', @@ -399,6 +401,8 @@ $lang = array_merge($lang, array( 'DOWNLOAD' => 'Download', 'DOWNLOAD_AS' => 'Download as', 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)', + 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file', + 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for <<< to spot conflicts', 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive', 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.', @@ -443,13 +447,13 @@ $lang = array_merge($lang, array( 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file', 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file', - 'MERGE_MOD_FILE_OPTION' => 'Merge differences and use modified code within conflicting block', - 'MERGE_NEW_FILE_OPTION' => 'Merge differences and use new file code within conflicting block', + 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (Loose new phpBB code within conflicting block)', + 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (Loose modified code within conflicting block)', 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.', 'MERGING_FILES' => 'Merging differences', 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.

          Please wait until phpBB has completed all operations on changed files.', - 'NEW_FILE' => 'End of new updated file', + 'NEW_FILE' => 'End of Conflict', 'NEW_USERNAME' => 'New username', 'NO_AUTH_UPDATE' => 'Not authorised to update', 'NO_ERRORS' => 'No errors', diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php index f75837e96f..b3acb7f290 100644 --- a/phpBB/language/en/posting.php +++ b/phpBB/language/en/posting.php @@ -141,7 +141,7 @@ $lang = array_merge($lang, array( 'PARTIAL_UPLOAD' => 'The uploaded file was only partially uploaded.', 'PHP_SIZE_NA' => 'The attachment’s file size is too large.
          Could not determine the maximum size defined by PHP in php.ini.', - 'PHP_SIZE_OVERRUN' => 'The attachment’s file size is too large, the maximum upload size is %d MB.
          Please note this is set in php.ini and cannot be overridden.', + 'PHP_SIZE_OVERRUN' => 'The attachment’s file size is too large, the maximum upload size is %1$d %2$s.
          Please note this is set in php.ini and cannot be overridden.', 'PLACE_INLINE' => 'Place inline', 'POLL_DELETE' => 'Delete poll', 'POLL_FOR' => 'Run poll for', diff --git a/phpBB/language/en/search.php b/phpBB/language/en/search.php index 8e376b2602..4618a585b3 100644 --- a/phpBB/language/en/search.php +++ b/phpBB/language/en/search.php @@ -54,6 +54,8 @@ $lang = array_merge($lang, array( 'LOGIN_EXPLAIN_EGOSEARCH' => 'The board requires you to be registered and logged in to view your own posts.', + 'MAX_NUM_SEARCH_KEYWORDS_REFINE' => 'You specified too many words to search for. Please do not enter more than %1$d words.', + 'NO_KEYWORDS' => 'You must specify at least one word to search for. Each word must consist of at least %d characters and must not contain more than %d characters excluding wildcards.', 'NO_RECENT_SEARCHES' => 'No searches have been carried out recently.', 'NO_SEARCH' => 'Sorry but you are not permitted to use the search system.', diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 4ece142031..594a1dbe4f 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -122,6 +122,9 @@ $lang = array_merge($lang, array( 'CONFIRM_EMAIL' => 'Confirm e-mail address', 'CONFIRM_EMAIL_EXPLAIN' => 'You only need to specify this if you are changing your e-mail address.', 'CONFIRM_EXPLAIN' => 'To prevent automated registrations the board requires you to enter a confirmation code. The code is displayed in the image you should see below. If you are visually impaired or cannot otherwise read this code please contact the %sBoard Administrator%s.', + 'VC_REFRESH' => 'Refresh confirmation code', + 'VC_REFRESH_EXPLAIN' => 'If you cannot read the code you can request a new one by clicking the button.', + 'CONFIRM_PASSWORD' => 'Confirm password', 'CONFIRM_PASSWORD_EXPLAIN' => 'You only need to confirm your password if you changed it above.', 'COPPA_BIRTHDAY' => 'To continue with the registration procedure please tell us when you were born.', @@ -325,7 +328,7 @@ $lang = array_merge($lang, array( 'PASS_TYPE_SYMBOL_EXPLAIN' => 'Password must be between %1$d and %2$d characters long, must contain letters in mixed case, must contain numbers and must contain symbols.', 'PASSWORD' => 'Password', 'PASSWORD_ACTIVATED' => 'Your new password has been activated.', - 'PASSWORD_UPDATED' => 'Your password has been sent successfully to your original e-mail address.', + 'PASSWORD_UPDATED' => 'A new password was sent to your registered e-mail address.', 'PERMISSIONS_RESTORED' => 'Successfully restored original permissions.', 'PERMISSIONS_TRANSFERRED' => 'Successfully transferred permissions from %s, you are now able to browse the board with this user’s permissions.
          Please note that admin permissions were not transferred. You are able to revert to your permission set at any time.', 'PM_DISABLED' => 'Private messaging has been disabled on this board.', diff --git a/phpBB/mcp.php b/phpBB/mcp.php index 47578c3532..5f7aa3bd1f 100644 --- a/phpBB/mcp.php +++ b/phpBB/mcp.php @@ -170,6 +170,12 @@ if ($quickmod) break; case 'topic_logs': + // Reset start parameter if we jumped from the quickmod dropdown + if (request_var('start', 0)) + { + $_REQUEST['start'] = 0; + } + $module->set_active('logs', 'topic_logs'); break; diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 38d5efad2f..298164be9e 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -890,7 +890,10 @@ switch ($mode) } $template->assign_vars(array( - 'ERROR_MESSAGE' => (sizeof($error)) ? implode('
          ', $error) : '') + 'ERROR_MESSAGE' => (sizeof($error)) ? implode('
          ', $error) : '', + 'SUBJECT' => $subject, + 'MESSAGE' => $message, + ) ); break; @@ -1623,6 +1626,7 @@ function show_profile($data) 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($data['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $user_id) : '', 'U_EMAIL' => $email, 'U_WWW' => (!empty($data['user_website'])) ? $data['user_website'] : '', + 'U_SHORT_WWW' => (!empty($data['user_website'])) ? ((strlen($data['user_website']) > 55) ? substr($data['user_website'], 0, 39) . ' ... ' . substr($data['user_website'], -10) : $data['user_website']) : '', 'U_ICQ' => ($data['user_icq']) ? 'http://www.icq.com/people/webmsg.php?to=' . urlencode($data['user_icq']) : '', 'U_AIM' => ($data['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $user_id) : '', 'U_YIM' => ($data['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($data['user_yim']) . '&.src=pg' : '', diff --git a/phpBB/posting.php b/phpBB/posting.php index 1666342c9b..c16c55111a 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -49,7 +49,8 @@ $current_time = time(); // Was cancel pressed? If so then redirect to the appropriate page if ($cancel || ($current_time - $lastclick < 2 && $submit)) { - $redirect = ($post_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $post_id) . '#p' . $post_id : (($topic_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id) : (($forum_id) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) : append_sid("{$phpbb_root_path}index.$phpEx"))); + $f = ($forum_id) ? 'f=' . $forum_id . '&' : ''; + $redirect = ($post_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $f . 'p=' . $post_id) . '#p' . $post_id : (($topic_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $f . 't=' . $topic_id) : (($forum_id) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) : append_sid("{$phpbb_root_path}index.$phpEx"))); redirect($redirect); } @@ -74,6 +75,16 @@ switch ($mode) trigger_error('NO_TOPIC'); } + // Force forum id + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + $f_id = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + + $forum_id = (!$f_id) ? $forum_id : $f_id; + $sql = 'SELECT f.*, t.* FROM ' . TOPICS_TABLE . ' t, ' . FORUMS_TABLE . " f WHERE t.topic_id = $topic_id @@ -90,13 +101,24 @@ switch ($mode) trigger_error('NO_POST'); } + // Force forum id + $sql = 'SELECT forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id = ' . $post_id; + $result = $db->sql_query($sql); + $f_id = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + + $forum_id = (!$f_id) ? $forum_id : $f_id; + $sql = 'SELECT f.*, t.*, p.*, u.username, u.username_clean, u.user_sig, u.user_sig_bbcode_uid, u.user_sig_bbcode_bitfield FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . FORUMS_TABLE . ' f, ' . USERS_TABLE . " u WHERE p.post_id = $post_id AND t.topic_id = p.topic_id AND u.user_id = p.poster_id AND (f.forum_id = t.forum_id - OR f.forum_id = $forum_id)"; + OR f.forum_id = $forum_id)" . + (($auth->acl_get('m_approve', $forum_id)) ? '' : 'AND p.post_approved = 1'); break; case 'smilies': @@ -646,7 +668,7 @@ if ($submit || $preview || $refresh) $post_data['poll_length'] = request_var('poll_length', 0); $post_data['poll_option_text'] = utf8_normalize_nfc(request_var('poll_option_text', '', true)); $post_data['poll_max_options'] = request_var('poll_max_options', 1); - $post_data['poll_vote_change'] = ($auth->acl_get('f_votechg', $forum_id) && isset($_POST['poll_vote_change'])) ? 1 : 0; + $post_data['poll_vote_change'] = ($auth->acl_get('f_votechg', $forum_id) && $auth->acl_get('f_vote', $forum_id) && isset($_POST['poll_vote_change'])) ? 1 : 0; } // If replying/quoting and last post id has changed @@ -1227,7 +1249,7 @@ if ($config['enable_post_confirm'] && !$user->data['is_registered'] && $solved_c $db->sql_query($sql); // Generate code - $code = gen_rand_string(mt_rand(5, 8)); + $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); $confirm_id = md5(unique_id($user->ip)); $seed = hexdec(substr(unique_id(), 4, 10)); @@ -1286,6 +1308,7 @@ $template->assign_vars(array( 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'URL_STATUS' => ($bbcode_status && $url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + 'MAX_FONT_SIZE' => (int) $config['max_post_font_size'], 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), 'POST_DATE' => ($post_data['post_time']) ? $user->format_date($post_data['post_time']) : '', 'ERROR' => (sizeof($error)) ? implode('
          ', $error) : '', @@ -1340,7 +1363,7 @@ if (($mode == 'post' || ($mode == 'edit' && $post_id == $post_data['topic_first_ { $template->assign_vars(array( 'S_SHOW_POLL_BOX' => true, - 'S_POLL_VOTE_CHANGE' => ($auth->acl_get('f_votechg', $forum_id)), + 'S_POLL_VOTE_CHANGE' => ($auth->acl_get('f_votechg', $forum_id) && $auth->acl_get('f_vote', $forum_id)), 'S_POLL_DELETE' => ($mode == 'edit' && sizeof($post_data['poll_options']) && ((!$post_data['poll_last_vote'] && $post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) || $auth->acl_get('m_delete', $forum_id))), 'S_POLL_DELETE_CHECKED' => (!empty($poll_delete)) ? true : false, diff --git a/phpBB/search.php b/phpBB/search.php index 965c1a3c4b..cf2e8615c2 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -372,6 +372,20 @@ if ($keywords || $author || $author_id || $search_id || $submit) ' . str_replace(array('p.', 'post_'), array('t.', 'topic_'), $m_approve_fid_sql) . ' ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . " $sql_sort"; +/* + [Fix] queued replies missing from "view new posts" (Bug #42705 - Patch by Paul) + - Creates temporary table, query is far from optimized + + $sql = 'SELECT t.topic_id + FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p + WHERE p.post_time > ' . $user->data['user_lastvisit'] . ' + AND t.topic_id = p.topic_id + AND t.topic_moved_id = 0 + ' . $m_approve_fid_sql . ' + ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . " + GROUP BY t.topic_id + $sql_sort"; +*/ $field = 'topic_id'; } break; @@ -395,7 +409,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) while ($row = $db->sql_fetchrow($result)) { - $id_ary[] = $row[$field]; + $id_ary[] = (int) $row[$field]; } $db->sql_freeresult($result); @@ -767,7 +781,8 @@ if ($keywords || $author || $author_id || $search_id || $submit) $u_forum_id = $forum_id; } - $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$u_forum_id&t=$result_topic_id" . (($u_hilit) ? "&hilit=$u_hilit" : '')); + $view_topic_url_params = "f=$u_forum_id&t=$result_topic_id" . (($u_hilit) ? "&hilit=$u_hilit" : ''); + $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params); $replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; @@ -825,10 +840,10 @@ if ($keywords || $author || $author_id || $search_id || $submit) 'S_TOPIC_UNAPPROVED' => $topic_unapproved, 'S_POSTS_UNAPPROVED' => $posts_unapproved, - 'U_LAST_POST' => $view_topic_url . '&p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'], + 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), - 'U_NEWEST_POST' => $view_topic_url . '&view=unread#unread', + 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread', 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=reports&t=' . $result_topic_id, true, $user->session_id), 'U_MCP_QUEUE' => $u_mcp_queue, ); diff --git a/phpBB/store/index.htm b/phpBB/store/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/store/index.htm @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/phpBB/style.php b/phpBB/style.php index 843c18b88d..78fd2a91b4 100644 --- a/phpBB/style.php +++ b/phpBB/style.php @@ -118,10 +118,11 @@ if ($id) $user_image_lang = (file_exists($phpbb_root_path . 'styles/' . $theme['imageset_path'] . '/imageset/' . $user['user_lang'])) ? $user['user_lang'] : $config['default_lang']; + // Same query in session.php $sql = 'SELECT * FROM ' . STYLES_IMAGESET_DATA_TABLE . ' WHERE imageset_id = ' . $theme['imageset_id'] . " - AND image_filename <> '' + AND image_filename <> '' AND image_lang IN ('" . $db->sql_escape($user_image_lang) . "', '')"; $result = $db->sql_query($sql, 3600); @@ -257,11 +258,11 @@ if ($id) case 'SRC': $replace[] = $imgs[$img]['src']; break; - + case 'WIDTH': $replace[] = $imgs[$img]['width']; break; - + case 'HEIGHT': $replace[] = $imgs[$img]['height']; break; diff --git a/phpBB/styles/prosilver/imageset/imageset.cfg b/phpBB/styles/prosilver/imageset/imageset.cfg index 074631ea60..64b7f632c9 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.4 +version = 3.0.5 # Images img_site_logo = site_logo.gif*52*139 diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 1d87dc8cf1..7be43fb4fa 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.4 \ No newline at end of file +version = 3.0.5 \ No newline at end of file diff --git a/phpBB/styles/prosilver/template/attachment.html b/phpBB/styles/prosilver/template/attachment.html index 7472abaee6..cc5aacff2f 100644 --- a/phpBB/styles/prosilver/template/attachment.html +++ b/phpBB/styles/prosilver/template/attachment.html @@ -61,13 +61,13 @@ - + - + diff --git a/phpBB/styles/prosilver/template/editor.js b/phpBB/styles/prosilver/template/editor.js index 5631ab67d1..9610cf91d1 100644 --- a/phpBB/styles/prosilver/template/editor.js +++ b/phpBB/styles/prosilver/template/editor.js @@ -16,7 +16,6 @@ var is_ie = ((clientPC.indexOf('msie') != -1) && (clientPC.indexOf('opera') == - var is_win = ((clientPC.indexOf('win') != -1) || (clientPC.indexOf('16bit') != -1)); var baseHeight; -onload_functions.push('initInsertions()'); /** * Shows the help messages in the helpline window diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js index 6694dfb61b..c1b86bd064 100644 --- a/phpBB/styles/prosilver/template/forum_fn.js +++ b/phpBB/styles/prosilver/template/forum_fn.js @@ -23,9 +23,16 @@ function jumpto() { var page = prompt(jump_page, on_page); - if (page !== null && !isNaN(page) && page > 0) + if (page !== null && !isNaN(page) && page == Math.floor(page) && page > 0) { - document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + if (base_url.indexOf('?') == -1) + { + document.location.href = base_url + '?start=' + ((page - 1) * per_page); + } + else + { + document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + } } } @@ -200,6 +207,12 @@ function selectCode(a) // Firefox and Opera else { + // workaround for bug # 42885 + if (window.opera && e.innerHTML.substring(e.innerHTML.length - 4) == '
          ') + { + e.innerHTML = e.innerHTML + ' '; + } + var r = document.createRange(); r.selectNodeContents(e); s.removeAllRanges(); diff --git a/phpBB/styles/prosilver/template/mcp_notes_user.html b/phpBB/styles/prosilver/template/mcp_notes_user.html index a039aec04a..ce4df31866 100644 --- a/phpBB/styles/prosilver/template/mcp_notes_user.html +++ b/phpBB/styles/prosilver/template/mcp_notes_user.html @@ -7,7 +7,7 @@
          -

          {USERNAME}{USERNAME}

          +

          {USERNAME_FULL}

          diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html index 4ffd7dd4f1..7453c01ec1 100644 --- a/phpBB/styles/prosilver/template/mcp_topic.html +++ b/phpBB/styles/prosilver/template/mcp_topic.html @@ -160,7 +160,7 @@ onload_functions.push('subPanels()');   - + {S_HIDDEN_FIELDS} {S_FORM_TOKEN} diff --git a/phpBB/styles/prosilver/template/mcp_warn_user.html b/phpBB/styles/prosilver/template/mcp_warn_user.html index 5b5156f3a1..dfc167399f 100644 --- a/phpBB/styles/prosilver/template/mcp_warn_user.html +++ b/phpBB/styles/prosilver/template/mcp_warn_user.html @@ -7,7 +7,7 @@
          -

          {USERNAME}{USERNAME}

          +

          {USERNAME_FULL}

          diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html index 883f05b514..ab2be261a8 100644 --- a/phpBB/styles/prosilver/template/memberlist_body.html +++ b/phpBB/styles/prosilver/template/memberlist_body.html @@ -132,7 +132,7 @@ {memberrow.RANK_IMG}{memberrow.RANK_TITLE} {memberrow.USERNAME_FULL}
          {L_SELECT} ] {memberrow.POSTS}{memberrow.POSTS} -
          {memberrow.LOCATION}
            +
          {memberrow.LOCATION}
            {memberrow.JOINED} {memberrow.VISITED}  diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 21d536d4b3..c0f553dfee 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -11,6 +11,7 @@ + {META} {SITENAME} • <!-- IF S_IN_MCP -->{L_MCP} • <!-- ELSEIF S_IN_UCP -->{L_UCP} • <!-- ENDIF -->{PAGE_TITLE} @@ -102,7 +103,7 @@

          {SITENAME}

          {SITE_DESCRIPTION}

          -

          {L_SKIP}

          +
          diff --git a/phpBB/styles/prosilver/template/posting_buttons.html b/phpBB/styles/prosilver/template/posting_buttons.html index 40f9503ca1..4d866681f0 100644 --- a/phpBB/styles/prosilver/template/posting_buttons.html +++ b/phpBB/styles/prosilver/template/posting_buttons.html @@ -93,8 +93,12 @@ - - + + + + + + diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html index f255862430..248d1ea72c 100644 --- a/phpBB/styles/prosilver/template/posting_editor.html +++ b/phpBB/styles/prosilver/template/posting_editor.html @@ -61,7 +61,7 @@
          -
          +
          @@ -139,7 +139,7 @@
          - +
          @@ -160,8 +160,8 @@
          -
          -
          +
          +
          {attach_row.FILENAME}
            diff --git a/phpBB/styles/prosilver/template/posting_review.html b/phpBB/styles/prosilver/template/posting_review.html index 10616901b6..78b994c989 100644 --- a/phpBB/styles/prosilver/template/posting_review.html +++ b/phpBB/styles/prosilver/template/posting_review.html @@ -3,10 +3,16 @@

          {L_POST_REVIEW_EXPLAIN}

          -
          + +
          + {post_review_row.L_IGNORE_POST} + +
          +
          + -
          +

          {post_review_row.POST_SUBJECT}

          {post_review_row.MINI_POST_IMG}{post_review_row.MINI_POST_IMG} {L_POST_BY_AUTHOR} {post_review_row.POST_AUTHOR_FULL} » {post_review_row.POST_DATE}

          {post_review_row.MESSAGE}
          diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html index 3f9c25cb2a..428a830ef3 100644 --- a/phpBB/styles/prosilver/template/posting_topic_review.html +++ b/phpBB/styles/prosilver/template/posting_topic_review.html @@ -6,8 +6,15 @@
          + + +
          +
          + {topic_review_row.L_IGNORE_POST} +
          +
          diff --git a/phpBB/styles/prosilver/template/simple_header.html b/phpBB/styles/prosilver/template/simple_header.html index d14f89935e..0e2409586c 100644 --- a/phpBB/styles/prosilver/template/simple_header.html +++ b/phpBB/styles/prosilver/template/simple_header.html @@ -17,6 +17,11 @@ + diff --git a/phpBB/styles/prosilver/template/template.cfg b/phpBB/styles/prosilver/template/template.cfg index 372704e2b9..0e5e8f0530 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.4 +version = 3.0.5 # Defining a different template bitfield template_bitfield = lNg= diff --git a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html index e92242223d..9d7c4ce1aa 100644 --- a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html +++ b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html @@ -32,7 +32,7 @@
          -
          + style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;" title="{topicrow.TOPIC_FOLDER_IMG_ALT}"> {NEWEST_POST_IMG} {topicrow.TOPIC_TITLE} {topicrow.UNAPPROVED_IMG} {REPORTED_IMG}
          diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html index 49dc2d5625..210537ced8 100644 --- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html +++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html @@ -52,7 +52,7 @@
        • -
          + style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;" title="{topicrow.TOPIC_FOLDER_IMG_ALT}"> {NEWEST_POST_IMG} {topicrow.TOPIC_TITLE} {topicrow.UNAPPROVED_IMG} {REPORTED_IMG}
          diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html index 535641f33b..ef9807f88a 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html @@ -75,7 +75,7 @@
          • {L_PRIVATE_MESSAGE}
          • - +
          • {L_WEBSITE}
          • {L_MSNM}
          • {L_ICQ}
          • diff --git a/phpBB/styles/prosilver/template/ucp_register.html b/phpBB/styles/prosilver/template/ucp_register.html index 721028cef6..3aeb92a5b0 100644 --- a/phpBB/styles/prosilver/template/ucp_register.html +++ b/phpBB/styles/prosilver/template/ucp_register.html @@ -87,7 +87,8 @@
            {CONFIRM_IMG}
            -
            {L_CONFIRM_CODE_EXPLAIN}
            +
            {L_CONFIRM_CODE_EXPLAIN} {L_VC_REFRESH_EXPLAIN}
            +
          @@ -113,7 +114,7 @@
          {S_HIDDEN_FIELDS}   - + {S_FORM_TOKEN}
          diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 6c69341bc2..23c52a5ee0 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -75,7 +75,7 @@
        • - +
          diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index 2b8ce06ace..17088bb16a 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -114,7 +114,7 @@ -
          +
          @@ -200,7 +200,7 @@
          • {L_PRIVATE_MESSAGE}
          • - +
          • {L_WEBSITE}
          • {L_MSNM}
          • {L_ICQ}
          • diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html index 45c7010867..2946d7645c 100644 --- a/phpBB/styles/prosilver/template/viewtopic_print.html +++ b/phpBB/styles/prosilver/template/viewtopic_print.html @@ -11,7 +11,7 @@ - + {META} {SITENAME} • {PAGE_TITLE} diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index a5327bd0d1..561bba0717 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -719,4 +719,7 @@ * tweaks.css */ - +/** Reference: Bug #27155 */ +.rtl #wrap, .rtl .headerbar, .rtl #site-description, .rtl .navbar { + position: relative; +} diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 06a05b5616..d7ee0b21b7 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -882,7 +882,7 @@ dl.mini dt { border-color: #5D8FBD; } -pmlist li.pm_foe_colour, .pm_foe_colour { +.pmlist li.pm_foe_colour, .pm_foe_colour { border-color: #000000; } @@ -906,6 +906,7 @@ Colours and backgrounds for forms.css select { border-color: #666666; background-color: #FAFAFA; + color: #000; } label { diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index c3fa42115f..7178fa6e42 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -397,7 +397,7 @@ table.table1 .joined { text-align: left; width: 15%; } table.table1 .active { text-align: left; width: 15%; } table.table1 .mark { text-align: center; width: 7%; } table.table1 .info { text-align: left; width: 30%; } -table.table1 .info div { width: 100%; white-space: nowrap; overflow: hidden; } +table.table1 .info div { width: 100%; white-space: normal; overflow: hidden; } table.table1 .autocol { line-height: 2em; white-space: nowrap; } table.table1 thead .autocol { padding-left: 1em; } @@ -599,7 +599,7 @@ div.rules { font-size: 1.1em; } -div.rules ul { +div.rules ul, div.rules ol { margin-left: 20px; } diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 00342604bb..19f5dfdb3b 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -44,7 +44,9 @@ ul.topiclist dd { ul.topiclist dfn { /* Labels for post/view counts */ - display: none; + position: absolute; + left: -999px; + width: 990px; } ul.topiclist li.row dt a.subforum { @@ -280,6 +282,10 @@ div[class].topic-actions { border-bottom-width: 0; } +.post-ignore .postbody { + display: none; +} + /* Content container styles ----------------------------------------*/ .content { @@ -750,4 +756,4 @@ dl.pmlist dt textarea { dl.pmlist dd { margin-left: 61% !important; margin-bottom: 2px; -} +} \ No newline at end of file diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index 9f3b7e3ae7..0b23449bfb 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -198,3 +198,10 @@ a.right:hover { text-decoration: none; background-position: 100% 60%; } + +/* invisible skip link, used for accessibility */ +.skiplink { + position: absolute; + left: -999px; + width: 990px; +} diff --git a/phpBB/styles/prosilver/theme/theme.cfg b/phpBB/styles/prosilver/theme/theme.cfg index bbbf54109b..3a1dc6989a 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.4 +version = 3.0.5 # Some configuration options diff --git a/phpBB/styles/prosilver/theme/tweaks.css b/phpBB/styles/prosilver/theme/tweaks.css index 6d169f58e0..b6038f3f05 100644 --- a/phpBB/styles/prosilver/theme/tweaks.css +++ b/phpBB/styles/prosilver/theme/tweaks.css @@ -82,3 +82,6 @@ dl.icon { float: none; } +* html .forumbg table.table1 { + margin: 0 -2px 0px -1px; +} diff --git a/phpBB/styles/subsilver2/imageset/imageset.cfg b/phpBB/styles/subsilver2/imageset/imageset.cfg index 81aefed058..3462d3ae66 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.4 +version = 3.0.5 # Images img_site_logo = site_logo.gif*94*170 diff --git a/phpBB/styles/subsilver2/style.cfg b/phpBB/styles/subsilver2/style.cfg index da327e16de..da64a05e5a 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.4 +version = 3.0.5 diff --git a/phpBB/styles/subsilver2/template/editor.js b/phpBB/styles/subsilver2/template/editor.js index 53b8b6222f..ae062d65a7 100644 --- a/phpBB/styles/subsilver2/template/editor.js +++ b/phpBB/styles/subsilver2/template/editor.js @@ -16,7 +16,6 @@ var is_ie = ((clientPC.indexOf('msie') != -1) && (clientPC.indexOf('opera') == - var is_win = ((clientPC.indexOf('win') != -1) || (clientPC.indexOf('16bit') != -1)); var baseHeight; -window.onload = initInsertions; /** * Shows the help messages in the helpline window diff --git a/phpBB/styles/subsilver2/template/index_body.html b/phpBB/styles/subsilver2/template/index_body.html index bf523dc3f2..8b6c1167b3 100644 --- a/phpBB/styles/subsilver2/template/index_body.html +++ b/phpBB/styles/subsilver2/template/index_body.html @@ -67,11 +67,11 @@ - +
            - + diff --git a/phpBB/styles/subsilver2/template/mcp_notes_user.html b/phpBB/styles/subsilver2/template/mcp_notes_user.html index 80ac96edf2..5df3f50407 100644 --- a/phpBB/styles/subsilver2/template/mcp_notes_user.html +++ b/phpBB/styles/subsilver2/template/mcp_notes_user.html @@ -10,7 +10,7 @@

            {L_LOGIN_LOGOUT}

            - + diff --git a/phpBB/styles/subsilver2/template/mcp_warn_user.html b/phpBB/styles/subsilver2/template/mcp_warn_user.html index bb77c91654..4bf6cabad3 100644 --- a/phpBB/styles/subsilver2/template/mcp_warn_user.html +++ b/phpBB/styles/subsilver2/template/mcp_warn_user.html @@ -8,7 +8,7 @@
            {USERNAME}{USERNAME_FULL}
            - + diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html index 6db4f85690..6c12db897d 100644 --- a/phpBB/styles/subsilver2/template/overall_header.html +++ b/phpBB/styles/subsilver2/template/overall_header.html @@ -11,6 +11,7 @@ + {META} {SITENAME} • <!-- IF S_IN_MCP -->{L_MCP} • <!-- ELSEIF S_IN_UCP -->{L_UCP} • <!-- ENDIF -->{PAGE_TITLE} @@ -39,12 +40,19 @@ function popup(url, width, height, name) function jumpto() { var page = prompt('{LA_JUMP_PAGE}:', '{ON_PAGE}'); - var perpage = '{PER_PAGE}'; + var per_page = '{PER_PAGE}'; var base_url = '{A_BASE_URL}'; - if (page !== null && !isNaN(page) && page > 0) + if (page !== null && !isNaN(page) && page == Math.floor(page) && page > 0) { - document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * perpage); + if (base_url.indexOf('?') == -1) + { + document.location.href = base_url + '?start=' + ((page - 1) * per_page); + } + else + { + document.location.href = base_url.replace(/&/g, '&') + '&start=' + ((page - 1) * per_page); + } } } diff --git a/phpBB/styles/subsilver2/template/posting_body.html b/phpBB/styles/subsilver2/template/posting_body.html index d28923319c..da1fbf4e30 100644 --- a/phpBB/styles/subsilver2/template/posting_body.html +++ b/phpBB/styles/subsilver2/template/posting_body.html @@ -210,7 +210,7 @@
            {USERNAME}{USERNAME_FULL}
            - +