diff --git a/phpBB/adm/style/acp_captcha.html b/phpBB/adm/style/acp_captcha.html index 12f2251ab5..d31527b64d 100644 --- a/phpBB/adm/style/acp_captcha.html +++ b/phpBB/adm/style/acp_captcha.html @@ -54,10 +54,12 @@ -
- {L_SUBMIT} -   -   +
+ {L_ACP_SUBMIT_CHANGES} +

+   +   +

{S_FORM_TOKEN}
diff --git a/phpBB/adm/style/acp_database.html b/phpBB/adm/style/acp_database.html index e839fb1bda..de02ac6dbe 100644 --- a/phpBB/adm/style/acp_database.html +++ b/phpBB/adm/style/acp_database.html @@ -71,8 +71,9 @@
- -
+ + +
diff --git a/phpBB/adm/style/acp_inactive.html b/phpBB/adm/style/acp_inactive.html index ca65416421..3b20043dd9 100644 --- a/phpBB/adm/style/acp_inactive.html +++ b/phpBB/adm/style/acp_inactive.html @@ -41,6 +41,7 @@ {inactive.REASON}
{inactive.REMINDED_EXPLAIN} +    @@ -67,7 +68,7 @@
-

{L_MARK_ALL}{L_UNMARK_ALL}

+

{L_MARK_ALL}{L_UNMARK_ALL}

{S_FORM_TOKEN}
diff --git a/phpBB/adm/style/acp_logs.html b/phpBB/adm/style/acp_logs.html index 6e93dba940..f2fa5dbc26 100644 --- a/phpBB/adm/style/acp_logs.html +++ b/phpBB/adm/style/acp_logs.html @@ -14,11 +14,12 @@ -
 

+
 
+

diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 139dc825c1..46d65df7a2 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -232,6 +232,7 @@ diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index c93d8b7d2d..5bde4008ad 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -20,7 +20,7 @@

{L_REPLACE_EXPLAIN}
-
+

@@ -135,11 +135,11 @@


{L_AUTOMATIC_EXPLAIN}
-
+

{L_AUTOMATIC_EXPLAIN}
-
+
@@ -266,7 +266,7 @@

{L_TEMPLATE_CACHE_EXPLAIN}

- +
{L_TEMPLATE_CACHE} diff --git a/phpBB/adm/style/acp_users_warnings.html b/phpBB/adm/style/acp_users_warnings.html index be9ef06825..d27f3800fc 100644 --- a/phpBB/adm/style/acp_users_warnings.html +++ b/phpBB/adm/style/acp_users_warnings.html @@ -7,17 +7,16 @@
- + - - + @@ -28,12 +27,10 @@ - -
-   - -

{L_MARK_ALL}{L_UNMARK_ALL}

-
- +
+   + +

{L_MARK_ALL}{L_UNMARK_ALL}

+
{S_FORM_TOKEN} diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index ad15036daa..9888ad3797 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -69,8 +69,8 @@ h2, caption { h3, h4 { font-family: "Trebuchet MS", Helvetica, sans-serif; font-size: 1.20em; - text-decoration: none; - line-height: 1.20em; + text-decoration: none; + line-height: 1.20em; margin-top: 25px; } @@ -97,8 +97,8 @@ hr { height: 1px; } -.small { - font-size: 0.85em; +.small { + font-size: 0.85em; } /* General links */ @@ -195,7 +195,7 @@ li { width: 76%; margin: 0 0 0 3%; min-height: 350px; - overflow-y: auto; + overflow-x: auto; } .rtl #main { @@ -203,8 +203,9 @@ li { margin: 0 3% 0 0; } -* html #main { - height: 350px; +* html #main { + height: 350px; + overflow-x: visible; } #page-body.simple-page-body { @@ -316,7 +317,7 @@ li { padding: 0; } -span.corners-top, span.corners-bottom, +span.corners-top, span.corners-bottom, span.corners-top span, span.corners-bottom span { font-size: 1px; line-height: 1px; @@ -795,7 +796,7 @@ label img { fieldset.quick, p.quick { margin: 0 0 5px; - padding: 5px 0 0; + padding: 5px 0 0; border: none; background-color: transparent; text-align: right; @@ -848,7 +849,7 @@ select option.disabled { } /* Special case inputs */ -select#board_timezone, +select#board_timezone, select#full_folder_action { width: 95%; } @@ -1245,12 +1246,12 @@ input.disabled { } /* Nice method for clearing floated blocks without having to insert any extra markup - From http://www.positioniseverything.net/easyclearing.html + From http://www.positioniseverything.net/easyclearing.html .clearfix:after, #tabs:after, .row:after, #content:after, fieldset dl:after, #page-body:after { - content: "."; - display: block; - height: 0; - clear: both; + content: "."; + display: block; + height: 0; + clear: both; visibility: hidden; }*/ @@ -1317,7 +1318,7 @@ fieldset.permissions legend input{ height: 1.1em; } -/* Permission sections */ +/* Permission sections */ fieldset.permissions .permissions-simple { text-align: left; padding-top: 3px; @@ -1528,7 +1529,7 @@ fieldset.permissions .padding { background-image: url("../images/corners_right2.gif"); } -.permissions-panel span.corners-top, .permissions-panel span.corners-bottom, +.permissions-panel span.corners-top, .permissions-panel span.corners-bottom, .permissions-panel span.corners-top span, .permissions-panel span.corners-bottom span { font-size: 1px; line-height: 1px; @@ -1606,7 +1607,7 @@ fieldset.permissions .padding { } .permissions-panel th.row4 { - background-image: none; + background-image: none; background-color: #E4E8EB; color: #536482; border: none; @@ -1614,8 +1615,8 @@ fieldset.permissions .padding { .permissions-panel th a:link, .permissions-panel th a:hover, .permissions-panel th a:visited { display: block; - color: #FFFFFF; - text-decoration: underline; + color: #FFFFFF; + text-decoration: underline; } .permissions-panel td.permissions-yes label:hover { diff --git a/phpBB/adm/style/captcha_gd_acp.html b/phpBB/adm/style/captcha_gd_acp.html index be715401db..d0bb758cfe 100644 --- a/phpBB/adm/style/captcha_gd_acp.html +++ b/phpBB/adm/style/captcha_gd_acp.html @@ -56,11 +56,13 @@ -
- {L_SUBMIT} -   -   -   +
+ {L_ACP_SUBMIT_CHANGES} +

+   +   +   +

diff --git a/phpBB/adm/style/captcha_recaptcha_acp.html b/phpBB/adm/style/captcha_recaptcha_acp.html index fba59a9647..5b97cff984 100644 --- a/phpBB/adm/style/captcha_recaptcha_acp.html +++ b/phpBB/adm/style/captcha_recaptcha_acp.html @@ -34,10 +34,12 @@
-
- {L_SUBMIT} -   -   +
+ {L_ACP_SUBMIT_CHANGES} +

+   +   +

diff --git a/phpBB/adm/style/install_update_diff.html b/phpBB/adm/style/install_update_diff.html index d794c5c516..b65a014312 100644 --- a/phpBB/adm/style/install_update_diff.html +++ b/phpBB/adm/style/install_update_diff.html @@ -15,9 +15,9 @@ // -div#codepanel { +div#codepanel { background-color: #eee; } @@ -149,10 +149,10 @@ table.hrdiff tbody th { table.hrdiff tbody td.old { border-left: 1px solid #999; - border-right: 1px solid #999; + border-right: 1px solid #999; } table.hrdiff tbody td.new { - border-right: 1px solid #999; + border-right: 1px solid #999; } table.hrdiff td pre { @@ -237,19 +237,19 @@ table.hrdiff caption span {
+ + +
{L_NUM_CONFLICTS}: {NUM_CONFLICTS}
+
- +
- - -
{L_NUM_CONFLICTS}: {NUM_CONFLICTS}
- {DIFF_CONTENT}
@@ -257,6 +257,6 @@ table.hrdiff caption span {
- + \ No newline at end of file diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index ca791ef155..6a947d259c 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -210,9 +210,12 @@
  • [Fix] Do not display links to user/post search if search is disabled. (Bug #50685 - Patch by HardStyle)
  • [Fix] Fix icon alignment for forums with large descriptions in subsilver2. (Bug #50445)
  • [Fix] Correctly display underlined links placed in last line in viewtopic. (Bug #14811 - Patch by primehalo)
  • +
  • [Fix] Only check whether forum image exists if forum image is specified. (Bug #51905)
  • +
  • [Fix] Fixed database backup and restore with Oracle DBMS.
  • +
  • [Fix] Fixed database updater for changes to columns having default value in MSSQL (adding/dropping constraints)
  • +
  • [Change] Database updater now supports checking for existing/missing indexes.
  • [Change] submit_post() now accepts force_approved_state key passed to $data to indicate new posts being approved (true) or unapproved (false).
  • [Change] Change the data format of the default file ACM to be more secure from tampering and have better performance.
  • -
  • [Change] Add index on log_time to the log table to prevent slowdown on boards with many log entries. (Bug #44665 - Patch by bantu)
  • [Change] Template engine now permits to a limited extent variable includes.
  • [Change] Quote BBCode no longer requires the f_reply permission. (Bug #16079)
  • [Change] Banning/unbanning users now generates an entry in their user notes (Bug #21825 - Patch by nickvergessen)
  • @@ -243,7 +246,8 @@
  • [Change] Do not take edit post time into account for determining permission to delete last post in topic. (Bug #48615)
  • [Change] Resize oversized Topic icons (Bug #44415)
  • [Change] Banned IPs are now sorted (Bug #43045 - Patch by DavidIQ)
  • -
  • [Change] phpBB updater now skips sole whitespace changes. This reduces the chance of conflicts tremendously.
  • +
  • [Change] phpBB updater now skips sole whitespace/tab changes while computing differences. This reduces the chance of conflicts tremendously.
  • +
  • [Change] phpBB updater now solves common conflicts on it's own. This further reduces the chance of conflicts.
  • [Feature] Add language selection on the registration terms page (Bug #15085 - Patch by leviatan21)
  • [Feature] Backported 3.2 captcha plugins.
      @@ -300,6 +304,7 @@
    • [Feature] Added function to generate Email hash. (Bug #49195)
    • [Feature] Style authors are now able to define the default submit button used for form submission on ENTER keypress on forms using more than one. Prosilver uses this for the posting page(s) and registration screen.
    • [Feature] Ability to specify amount of time user is able to delete his last post in topic.
    • +
    • [Feature] Send anonymous statistical information to phpBB on installation and update (optional).

    1.ii. Changes since 3.0.4

    diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 6e86f412fb..e1fa764191 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -30,10 +30,13 @@ class acp_captcha $user->add_lang('acp/board'); include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + $captchas = phpbb_captcha_factory::get_captcha_types(); $selected = request_var('select_captcha', $config['captcha_plugin']); + $selected = (isset($captchas['available'][$selected]) || isset($captchas['unavailable'][$selected])) ? $selected : $config['captcha_plugin']; $configure = request_var('configure', false); + // Oh, they are just here for the view if (isset($_GET['captcha_demo'])) { @@ -45,12 +48,9 @@ class acp_captcha { $config_captcha =& phpbb_captcha_factory::get_instance($selected); $config_captcha->acp_page($id, $this); - add_log('admin', 'LOG_CONFIG_VISUAL'); } else { - $captchas = phpbb_captcha_factory::get_captcha_types(); - $config_vars = array( 'enable_confirm' => array('tpl' => 'REG_ENABLE', 'default' => false), 'enable_post_confirm' => array('tpl' => 'POST_ENABLE', 'default' => false), diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index b25518e1c4..5d7450bdfd 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -142,7 +142,7 @@ class acp_database break; case 'oracle': - $extractor->flush('TRUNCATE TABLE ' . $table_name . "\\\n"); + $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); break; default: @@ -1716,8 +1716,7 @@ class oracle_extractor extends base_extractor { global $db; $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - $sql_data .= '\\' . "\n"; + $sql_data .= "DROP TABLE $table_name\n/\n"; $sql_data .= "\nCREATE TABLE $table_name (\n"; $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT @@ -1732,7 +1731,7 @@ class oracle_extractor extends base_extractor if ($row['data_type'] !== 'CLOB') { - if ($row['data_type'] !== 'VARCHAR2') + if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR') { $line .= '(' . $row['data_precision'] . ')'; } @@ -1762,12 +1761,20 @@ class oracle_extractor extends base_extractor AND A.TABLE_NAME = '{$table_name}'"; $result = $db->sql_query($sql); + $primary_key = array(); + $contraint_name = ''; while ($row = $db->sql_fetchrow($result)) { - $rows[] = " CONSTRAINT {$row['constraint_name']} PRIMARY KEY ({$row['column_name']})"; + $constraint_name = '"' . $row['constraint_name'] . '"'; + $primary_key[] = '"' . $row['column_name'] . '"'; } $db->sql_freeresult($result); + if (sizeof($primary_key)) + { + $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; + } + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME @@ -1775,24 +1782,44 @@ class oracle_extractor extends base_extractor AND A.TABLE_NAME = '{$table_name}'"; $result = $db->sql_query($sql); + $unique = array(); + $contraint_name = ''; while ($row = $db->sql_fetchrow($result)) { - $rows[] = " CONSTRAINT {$row['constraint_name']} UNIQUE ({$row['column_name']})"; + $constraint_name = '"' . $row['constraint_name'] . '"'; + $unique[] = '"' . $row['column_name'] . '"'; } $db->sql_freeresult($result); - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n)\n\\"; + if (sizeof($unique)) + { + $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; + } - $sql = "SELECT A.REFERENCED_NAME - FROM USER_DEPENDENCIES A, USER_TRIGGERS B + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n)\n/\n"; + + $sql = "SELECT A.REFERENCED_NAME, C.* + FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C WHERE A.REFERENCED_TYPE = 'SEQUENCE' AND A.NAME = B.TRIGGER_NAME - AND B. TABLE_NAME = '{$table_name}'"; + AND B.TABLE_NAME = '{$table_name}' + AND C.SEQUENCE_NAME = A.REFERENCED_NAME"; $result = $db->sql_query($sql); + + $type = request_var('type', ''); + while ($row = $db->sql_fetchrow($result)) { - $sql_data .= "\nCREATE SEQUENCE {$row['referenced_name']}\\\n"; + $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n"; + $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\""; + + if ($type == 'full') + { + $sql_data .= ' START WITH ' . $row['last_number']; + } + + $sql_data .= "\n/\n"; } $db->sql_freeresult($result); @@ -1802,7 +1829,7 @@ class oracle_extractor extends base_extractor $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { - $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\\"; + $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n"; } $db->sql_freeresult($result); @@ -1822,7 +1849,7 @@ class oracle_extractor extends base_extractor foreach ($index as $index_name => $column_names) { - $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n\\"; + $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n"; } $db->sql_freeresult($result); $this->flush($sql_data); @@ -1858,7 +1885,7 @@ class oracle_extractor extends base_extractor // Oracle uses uppercase - we use lowercase $str_val = $row[strtolower($ary_name[$i])]; - if (preg_match('#char|text|bool|raw#i', $ary_type[$i])) + if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i])) { $str_quote = ''; $str_empty = "''"; @@ -1892,7 +1919,7 @@ class oracle_extractor extends base_extractor // Take the ordered fields and their associated data and build it // into a valid sql statement to recreate that field in the data. - $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n"; $this->flush($sql_data); } @@ -2211,8 +2238,10 @@ function sanitize_data_mssql($text) function sanitize_data_oracle($text) { - $data = preg_split('/[\0\n\t\r\b\f\'"\\\]/', $text); - preg_match_all('/[\0\n\t\r\b\f\'"\\\]/', $text, $matches); +// $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text); +// preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches); + $data = preg_split('/[\0\b\f\'\/]/', $text); + preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches); $val = array(); diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 045d8a2e8e..62ccbdb68e 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -171,7 +171,7 @@ class acp_forums $forum_data['forum_status'] = ITEM_UNLOCKED; } - $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? request_var('display_recent', false) : request_var('display_active', false); + $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? request_var('display_recent', true) : request_var('display_active', true); // Get data for forum rules if specified... if ($forum_data['forum_rules']) @@ -443,7 +443,7 @@ class acp_forums 'prune_days' => 7, 'prune_viewed' => 7, 'prune_freq' => 1, - 'forum_flags' => FORUM_FLAG_POST_REVIEW, + 'forum_flags' => FORUM_FLAG_POST_REVIEW + FORUM_FLAG_ACTIVE_TOPICS, 'forum_options' => 0, 'forum_password' => '', 'forum_password_confirm'=> '', @@ -907,7 +907,7 @@ 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'])) + if (!empty($forum_data['forum_image']) && !file_exists($phpbb_root_path . $forum_data['forum_image'])) { $errors[] = $user->lang['FORUM_IMAGE_NO_EXIST']; } diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 121c72aeb3..0d75b7ceb1 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -43,6 +43,7 @@ class acp_update $latest_version = trim($info[0]); $announcement_url = trim($info[1]); + $announcement_url = (strpos($announcement_url, '&') === false) ? str_replace('&', '&', $announcement_url) : $announcement_url; $update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update'); // Determine automatic update... diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 1afec6183a..614b58e7a9 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1167,13 +1167,7 @@ class acp_users $deleteall = request_var('delall', 0); if ($deletemark && $marked) { - $sql_in = array(); - foreach ($marked as $mark) - { - $sql_in[] = $mark; - } - $where_sql = ' AND ' . $db->sql_in_set('warning_id', $sql_in); - unset($sql_in); + $where_sql = ' AND ' . $db->sql_in_set('warning_id', array_values($marked)); } if ($where_sql || $deleteall) @@ -1291,7 +1285,6 @@ class acp_users $template->assign_vars(array( 'S_WARNINGS' => true, - 'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'), )); break; @@ -1715,6 +1708,7 @@ class acp_users $template->assign_vars(array( 'S_AVATAR' => true, + 'S_CAN_UPLOAD' => $can_upload, 'S_UPLOAD_FILE' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_upload']) ? true : false, 'S_REMOTE_UPLOAD' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_remote_upload']) ? true : false, 'S_ALLOW_REMOTE' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false, diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index 5dc141ff77..71f8a7c082 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -67,10 +67,12 @@ function login_db(&$username, &$password) // Every auth module is able to define what to do by itself... if ($config['max_login_attempts'] && $row['user_login_attempts'] >= $config['max_login_attempts']) { - $confirm_id = request_var('confirm_id', ''); - // Visual Confirmation handling - if (!$confirm_id) + + $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + $vc_response = $captcha->validate(); + if ($vc_response) { return array( 'status' => LOGIN_ERROR_ATTEMPTS, @@ -78,21 +80,7 @@ function login_db(&$username, &$password) 'user_row' => $row, ); } - else - { - $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); - $captcha->init(CONFIRM_LOGIN); - $vc_response = $captcha->validate(); - - if ($vc_response) - { - return array( - 'status' => LOGIN_ERROR_ATTEMPTS, - 'error_msg' => 'LOGIN_ERROR_ATTEMPTS', - 'user_row' => $row, - ); - } - } + } // If the password convert flag is set we need to convert it diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 693523dcbb..f58852c00b 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -128,7 +128,7 @@ class bbcode */ function bbcode_cache_init() { - global $user, $phpbb_root_path; + global $phpbb_root_path, $template, $user; if (empty($this->template_filename)) { @@ -137,7 +137,7 @@ class bbcode if (!@file_exists($this->template_filename)) { - if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) + if (isset($template->orig_tpl_inherits_id) && $template->orig_tpl_inherits_id) { $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template/bbcode.html'; if (!@file_exists($this->template_filename)) diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php index a85566deff..6e899adc16 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php @@ -80,7 +80,7 @@ class phpbb_captcha_gd extends phpbb_default_captcha { return true; } - + function get_name() { return 'CAPTCHA_GD'; @@ -123,6 +123,8 @@ class phpbb_captcha_gd extends phpbb_default_captcha set_config($captcha_var, $value); } } + + add_log('admin', 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); } else if ($submit) @@ -148,7 +150,7 @@ class phpbb_captcha_gd extends phpbb_default_captcha function execute_demo() { global $config; - + $config_old = $config; foreach ($this->captcha_vars as $captcha_var => $template_var) { diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php index 6f53e8c5ad..411d1366fa 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php @@ -56,13 +56,13 @@ class phpbb_captcha_qa $this->answer = request_var('qa_answer', '', true); $this->type = (int) $type; - $this->question_lang = $user->data['user_lang']; + $this->question_lang = $user->lang_name; // we need all defined questions - shouldn't be too many, so we can just grab them // try the user's lang first $sql = 'SELECT question_id FROM ' . CAPTCHA_QUESTIONS_TABLE . " - WHERE lang_iso = '" . $db->sql_escape($user->data['user_lang']) . "'"; + WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'"; $result = $db->sql_query($sql, 3600); while ($row = $db->sql_fetchrow($result)) @@ -685,6 +685,7 @@ class phpbb_captcha_qa $this->acp_add_question($data); } + add_log('admin', 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url)); } } diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php index 2d37b13a4f..d4543dddfc 100644 --- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php @@ -100,6 +100,8 @@ class phpbb_recaptcha extends phpbb_default_captcha set_config($captcha_var, $value); } } + + add_log('admin', 'LOG_CONFIG_VISUAL'); trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); } else if ($submit) diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index a526b9bf71..3bb9467bbf 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.6-RC1'); +define('PHPBB_VERSION', '3.0.6-RC2'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index ddc633c6d1..eabcfd818e 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -1190,11 +1190,13 @@ class phpbb_db_tools // For hexadecimal values do not use single quotes if (strpos($column_data[1], '0x') === 0) { - $sql_default .= 'DEFAULT (' . $column_data[1] . ') '; + $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') '; + $sql_default .= $return_array['default']; } else { - $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + $sql_default .= $return_array['default']; } } @@ -1781,7 +1783,7 @@ class phpbb_db_tools case 'firebird': $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . " + WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' AND RDB\$UNIQUE_FLAG IS NULL AND RDB\$FOREIGN_KEY IS NULL"; $col = 'index_name'; @@ -1808,8 +1810,9 @@ class phpbb_db_tools case 'oracle': $sql = "SELECT index_name FROM user_indexes - WHERE table_name = '" . $table_name . "' - AND generated = 'N'"; + WHERE table_name = '" . strtoupper($table_name) . "' + AND generated = 'N' + AND uniqueness = 'NONUNIQUE'"; $col = 'index_name'; break; @@ -1870,6 +1873,27 @@ class phpbb_db_tools case 'mssql': $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; + + if (!empty($column_data['default'])) + { + // Using TRANSACT-SQL for this statement because we do not want to have colliding data if statements are executed at a later stage + $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) + SET @drop_default_name = + (SELECT so.name FROM sysobjects so + JOIN sysconstraints sc ON so.id = sc.constid + WHERE object_name(so.parent_obj) = '{$table_name}' + AND so.xtype = 'D' + AND sc.colid = (SELECT colid FROM syscolumns + WHERE id = object_id('{$table_name}') + AND name = '{$column_name}')) + IF @drop_default_name <> '' + BEGIN + SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' + EXEC(@cmd) + END + SET @cmd = 'ALTER TABLE [{$table_name}] ADD CONSTRAINT [DF_{$table_name}_{$column_name}_1] {$column_data['default']} FOR [{$column_name}]' + EXEC(@cmd)"; + } break; case 'mysql_40': diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index 10f4a1a7a7..f7180029b5 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -255,13 +255,62 @@ class dbal_oracle extends dbal // We overcome Oracle's 4000 char limit by binding vars if (strlen($query) > 4000) { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) + if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/sU', $query, $regs)) { if (strlen($regs[3]) > 4000) { $cols = explode(', ', $regs[2]); + preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); + if (sizeof($cols) !== sizeof($vals)) + { + // Try to replace some common data we know is from our restore script or from other sources + $regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]); + $_vals = explode(', ', $regs[3]); + + $vals = array(); + $is_in_val = false; + $i = 0; + $string = ''; + + foreach ($_vals as $value) + { + if (strpos($value, "'") === false && !$is_in_val) + { + $vals[$i++] = $value; + continue; + } + + if (substr($value, -1) === "'") + { + $vals[$i] = $string . (($is_in_val) ? ', ' : '') . $value; + $string = ''; + $is_in_val = false; + + if ($vals[$i][0] !== "'") + { + $vals[$i] = "''" . $vals[$i]; + } + $i++; + continue; + } + else + { + $string .= (($is_in_val) ? ', ' : '') . $value; + $is_in_val = true; + } + } + + if ($string) + { + // New value if cols != value + $vals[(sizeof($cols) !== sizeof($vals)) ? $i : $i - 1] .= $string; + } + + $vals = array(0 => $vals); + } + $inserts = $vals[0]; unset($vals); diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php index 2adc3a3e6e..60af574b78 100644 --- a/phpBB/includes/diff/diff.php +++ b/phpBB/includes/diff/diff.php @@ -71,8 +71,10 @@ class diff { $count = 0; - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if (is_a($edit, 'diff_op_add') || is_a($edit, 'diff_op_change')) { $count += $edit->nfinal(); @@ -92,8 +94,10 @@ class diff { $count = 0; - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_change')) { $count += $edit->norig(); @@ -128,8 +132,9 @@ class diff $rev->_edits = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; $rev->_edits[] = $edit->reverse(); } @@ -143,13 +148,36 @@ class diff */ function is_empty() { - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { - if (!is_a($edit, 'diff_op_copy')) + $edit = $this->_edits[$i]; + + // skip diff_op_copy + if (is_a($edit, 'diff_op_copy')) { + continue; + } + + if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_add')) + { + $orig = $edit->orig; + $final = $edit->final; + + // We can simplify one case where the array is usually supposed to be empty... + if (sizeof($orig) == 1 && trim($orig[0]) === '') $orig = array(); + if (sizeof($final) == 1 && trim($final[0]) === '') $final = array(); + + if (!$orig && !$final) + { + continue; + } + return false; } + + return false; } + return true; } @@ -164,8 +192,10 @@ class diff { $lcs = 0; - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if (is_a($edit, 'diff_op_copy')) { $lcs += sizeof($edit->orig); @@ -185,8 +215,10 @@ class diff { $lines = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->orig) { array_splice($lines, sizeof($lines), 0, $edit->orig); @@ -206,8 +238,10 @@ class diff { $lines = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->final) { array_splice($lines, sizeof($lines), 0, $edit->final); @@ -258,8 +292,10 @@ class diff $prevtype = null; - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($prevtype == get_class($edit)) { trigger_error("[diff] Edit sequence is non-optimal", E_USER_ERROR); @@ -456,14 +492,14 @@ class diff3 extends diff * @param array $final1 The first version to compare to. * @param array $final2 The second version to compare to. */ - function diff3(&$orig, &$final1, &$final2) + function diff3(&$orig, &$final1, &$final2, $preserve_cr = true) { $diff_engine = new diff_engine(); - $diff_1 = $diff_engine->diff($orig, $final1); - $diff_2 = $diff_engine->diff($orig, $final2); + $diff_1 = $diff_engine->diff($orig, $final1, $preserve_cr); + $diff_2 = $diff_engine->diff($orig, $final2, $preserve_cr); - unset($engine); + unset($diff_engine); $this->_edits = $this->_diff3($diff_1, $diff_2); } @@ -475,8 +511,10 @@ class diff3 extends diff { $conflicts = 0; - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->is_conflict()) { $conflicts++; @@ -506,8 +544,10 @@ class diff3 extends diff $lines = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->is_conflict()) { // Start conflict label @@ -544,8 +584,10 @@ class diff3 extends diff { $lines = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->is_conflict()) { $lines = array_merge($lines, $edit->final2); @@ -566,8 +608,10 @@ class diff3 extends diff { $lines = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->is_conflict()) { $lines = array_merge($lines, $edit->final1); @@ -588,8 +632,10 @@ class diff3 extends diff { $conflicts = array(); - foreach ($this->_edits as $edit) + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) { + $edit = $this->_edits[$i]; + if ($edit->is_conflict()) { $conflicts[] = array($edit->final1, $edit->final2); @@ -713,6 +759,9 @@ class diff3_op { if (!isset($this->_merged)) { + // Prepare the arrays before we compare them. ;) + $this->solve_prepare(); + if ($this->final1 === $this->final2) { $this->_merged = &$this->final1; @@ -727,7 +776,9 @@ class diff3_op } else { + // The following tries to aggressively solve conflicts... $this->_merged = false; + $this->solve_conflict(); } } @@ -738,6 +789,267 @@ class diff3_op { return ($this->merged() === false) ? true : false; } + + /** + * Function to prepare the arrays for comparing - we want to skip over newline changes + * @author acydburn + */ + function solve_prepare() + { + // We can simplify one case where the array is usually supposed to be empty... + if (sizeof($this->orig) == 1 && trim($this->orig[0]) === '') $this->orig = array(); + if (sizeof($this->final1) == 1 && trim($this->final1[0]) === '') $this->final1 = array(); + if (sizeof($this->final2) == 1 && trim($this->final2[0]) === '') $this->final2 = array(); + + // Now we only can have the case where the only difference between arrays are newlines, so compare all cases + + // First, some strings we can compare... + $orig = $final1 = $final2 = ''; + + foreach ($this->orig as $null => $line) $orig .= trim($line); + foreach ($this->final1 as $null => $line) $final1 .= trim($line); + foreach ($this->final2 as $null => $line) $final2 .= trim($line); + + // final1 === final2 + if ($final1 === $final2) + { + // We preserve the part which will be used in the merge later + $this->final2 = $this->final1; + } + // final1 === orig + else if ($final1 === $orig) + { + // Here it does not really matter what we choose, but we will use the new code + $this->orig = $this->final1; + } + // final2 === orig + else if ($final2 === $orig) + { + // Here it does not really matter too (final1 will be used), but we will use the new code + $this->orig = $this->final2; + } + } + + /** + * Find code portions from $orig in $final1 and use $final2 as merged instance if provided + * @author acydburn + */ + function _compare_conflict_seq($orig, $final1, $final2 = false) + { + $result = array('merge_found' => false, 'merge' => array()); + + $_orig = &$this->$orig; + $_final1 = &$this->$final1; + + // Ok, we basically search for $orig in $final1 + $compare_seq = sizeof($_orig); + + // Go through the conflict code + for ($i = 0, $j = 0, $size = sizeof($_final1); $i < $size; $i++, $j = $i) + { + $line = $_final1[$i]; + $skip = 0; + + for ($x = 0; $x < $compare_seq; $x++) + { + // Try to skip all matching lines + if (trim($line) === trim($_orig[$x])) + { + $line = (++$j < $size) ? $_final1[$j] : $line; + $skip++; + } + } + + if ($skip === $compare_seq) + { + $result['merge_found'] = true; + + if ($final2 !== false) + { + $result['merge'] = array_merge($result['merge'], $this->$final2); + } + $i += ($skip - 1); + } + else if ($final2 !== false) + { + $result['merge'][] = $line; + } + } + + return $result; + } + + /** + * Tries to solve conflicts aggressively based on typical "assumptions" + * @author acydburn + */ + function solve_conflict() + { + $this->_merged = false; + + // CASE ONE: orig changed into final2, but modified/unknown code in final1. + // IF orig is found "as is" in final1 we replace the code directly in final1 and populate this as final2/merge + if (sizeof($this->orig) && sizeof($this->final2)) + { + $result = $this->_compare_conflict_seq('orig', 'final1', 'final2'); + + if ($result['merge_found']) + { + $this->final2 = $result['merge']; + $this->_merged = &$this->final2; + return; + } + + $result = $this->_compare_conflict_seq('final2', 'final1'); + + if ($result['merge_found']) + { + $this->_merged = &$this->final1; + return; + } + + // Try to solve $Id$ issues. ;) + if (sizeof($this->orig) == 1 && sizeof($this->final1) == 1 && sizeof($this->final2) == 1) + { + $match = '#^' . preg_quote('* @version $Id: ', '#') . '[a-z\._\- ]+[0-9]+ [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9\:Z]+ [a-z0-9_\- ]+\$$#'; + + if (preg_match($match, $this->orig[0]) && preg_match($match, $this->final1[0]) && preg_match($match, $this->final2[0])) + { + $this->_merged = &$this->final2; + return; + } + } + + $second_run = false; + + // Try to solve issues where the only reason why the above did not work is a newline being removed in the final1 code but exist in the orig/final2 code + if (trim($this->orig[0]) === '' && trim($this->final2[0]) === '') + { + unset($this->orig[0], $this->final2[0]); + $this->orig = array_values($this->orig); + $this->final2 = array_values($this->final2); + + $second_run = true; + } + + // The same is true for a line at the end. ;) + if (sizeof($this->orig) && sizeof($this->final2) && sizeof($this->orig) === sizeof($this->final2) && trim($this->orig[sizeof($this->orig)-1]) === '' && trim($this->final2[sizeof($this->final2)-1]) === '') + { + unset($this->orig[sizeof($this->orig)-1], $this->final2[sizeof($this->final2)-1]); + $this->orig = array_values($this->orig); + $this->final2 = array_values($this->final2); + + $second_run = true; + } + + if ($second_run) + { + $result = $this->_compare_conflict_seq('orig', 'final1', 'final2'); + + if ($result['merge_found']) + { + $this->final2 = $result['merge']; + $this->_merged = &$this->final2; + return; + } + + $result = $this->_compare_conflict_seq('final2', 'final1'); + + if ($result['merge_found']) + { + $this->_merged = &$this->final1; + return; + } + } + + return; + } + + // CASE TWO: Added lines from orig to final2 but final1 had added lines too. Just merge them. + if (!sizeof($this->orig) && $this->final1 !== $this->final2 && sizeof($this->final1) && sizeof($this->final2)) + { + $result = $this->_compare_conflict_seq('final2', 'final1'); + + if ($result['merge_found']) + { + $this->final2 = $this->final1; + $this->_merged = &$this->final1; + } + else + { + $result = $this->_compare_conflict_seq('final1', 'final2'); + + if (!$result['merge_found']) + { + $this->final2 = array_merge($this->final1, $this->final2); + $this->_merged = &$this->final2; + } + else + { + $this->final2 = $this->final1; + $this->_merged = &$this->final1; + } + } + + return; + } + + // CASE THREE: Removed lines (orig has the to-remove line(s), but final1 has additional lines which does not need to be removed). Just remove orig from final1 and then use final1 as final2/merge + if (!sizeof($this->final2) && sizeof($this->orig) && sizeof($this->final1) && $this->orig !== $this->final1) + { + $result = $this->_compare_conflict_seq('orig', 'final1'); + + if (!$result['merge_found']) + { + return; + } + + // First of all, try to find the code in orig in final1. ;) + $compare_seq = sizeof($this->orig); + $begin = $end = -1; + $j = 0; + + for ($i = 0, $size = sizeof($this->final1); $i < $size; $i++) + { + $line = $this->final1[$i]; + + if (trim($line) === trim($this->orig[$j])) + { + // Mark begin + if ($begin === -1) + { + $begin = $i; + } + + // End is always $i, the last found line + $end = $i; + + if (isset($this->orig[$j+1])) + { + $j++; + } + } + } + + if ($begin !== -1 && $begin + ($compare_seq - 1) == $end) + { + foreach ($this->final1 as $i => $line) + { + if ($i < $begin || $i > $end) + { + $merged[] = $line; + } + } + + $this->final2 = $merged; + $this->_merged = &$this->final2; + } + + return; + } + + return; + } } /** diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php index e9f0e41b75..982149457d 100644 --- a/phpBB/includes/diff/engine.php +++ b/phpBB/includes/diff/engine.php @@ -49,6 +49,9 @@ if (!defined('IN_PHPBB')) */ class diff_engine { + /** + * If set to true we trim all lines before we compare them. This ensures that sole space/tab changes do not trigger diffs. + */ var $skip_whitespace_changes = true; function diff(&$from_lines, &$to_lines, $preserve_cr = true) @@ -87,7 +90,7 @@ class diff_engine // Skip leading common lines. for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { - if ($from_lines[$skip] !== $to_lines[$skip]) + if (trim($from_lines[$skip]) !== trim($to_lines[$skip])) { break; } @@ -100,7 +103,7 @@ class diff_engine for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { - if ($from_lines[$xi] !== $to_lines[$yi]) + if (trim($from_lines[$xi]) !== trim($to_lines[$yi])) { break; } @@ -110,12 +113,12 @@ class diff_engine // Ignore lines which do not exist in both files. for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { - $xhash[$from_lines[$xi]] = 1; + if ($this->skip_whitespace_changes) $xhash[trim($from_lines[$xi])] = 1; else $xhash[$from_lines[$xi]] = 1; } for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { - $line = $to_lines[$yi]; + $line = ($this->skip_whitespace_changes) ? trim($to_lines[$yi]) : $to_lines[$yi]; if (($this->ychanged[$yi] = empty($xhash[$line]))) { @@ -128,7 +131,7 @@ class diff_engine for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { - $line = $from_lines[$xi]; + $line = ($this->skip_whitespace_changes) ? trim($from_lines[$xi]) : $from_lines[$xi]; if (($this->xchanged[$xi] = empty($yhash[$line]))) { @@ -142,8 +145,21 @@ class diff_engine $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); // Merge edits when possible. - $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged); - $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged); + if ($this->skip_whitespace_changes) + { + $from_lines_clean = array_map('trim', $from_lines); + $to_lines_clean = array_map('trim', $to_lines); + + $this->_shift_boundaries($from_lines_clean, $this->xchanged, $this->ychanged); + $this->_shift_boundaries($to_lines_clean, $this->ychanged, $this->xchanged); + + unset($from_lines_clean, $to_lines_clean); + } + else + { + $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged); + $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged); + } // Compute the edit operations. $edits = array(); @@ -178,20 +194,6 @@ class diff_engine $add[] = $to_lines[$yi++]; } - // Here we are a bit naughty. Naughty Boy... Naughty Boy... - // We check if delete and add is filled and only consist of one item - if ($this->skip_whitespace_changes && sizeof($delete) == 1 && sizeof($add) == 1) - { - // Now we simply trim the string and see if the lines are identical - // If they are identical we do not need to take them into account for the merge (less conflicts in phpBB) - if (trim($delete[0]) === trim($add[0])) - { - // This line ensures the line found here is correctly copied later (remember: we naughty boys like loops) - $xi--; $yi--; $this->xchanged[$xi] = $this->ychanged[$yi] = false; - $delete = $add = array(); - } - } - if ($delete && $add) { $edits[] = new diff_op_change($delete, $add); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 092a5d5d86..e787932441 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1693,11 +1693,11 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s 'LEFT_JOIN' => array( array( 'FROM' => array(TOPICS_TRACK_TABLE => 'tt'), - 'ON' => "tt.user_id = $user_id AND t.topic_id = tt.topic_id AND tt.mark_time > $last_mark", + 'ON' => "tt.user_id = $user_id AND t.topic_id = tt.topic_id", ), array( 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), - 'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id AND ft.mark_time > $last_mark", + 'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id", ), ), @@ -1705,10 +1705,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s ( (tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR (tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR - ( - ((tt.mark_time IS NULL AND ft.mark_time IS NULL) OR (tt.mark_time < $last_mark AND ft.mark_time < $last_mark)) - AND t.topic_last_post_time > $last_mark - ) + (tt.mark_time IS NULL AND ft.mark_time IS NULL AND t.topic_last_post_time > $last_mark) ) $sql_extra $sql_sort", @@ -3050,6 +3047,7 @@ function login_forum_box($forum_data) page_header($user->lang['LOGIN'], false); $template->assign_vars(array( + 'S_LOGIN_ACTION' => build_url(array('f')), 'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id']))) ); @@ -4034,16 +4032,6 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 } } - // Which timezone? - $tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone'])); - - // Send a proper content-language to the output - $user_lang = $user->lang['USER_LANG']; - if (strpos($user_lang, '-x-') !== false) - { - $user_lang = substr($user_lang, 0, strpos($user_lang, '-x-')); - } - $forum_id = request_var('f', 0); $topic_id = request_var('t', 0); @@ -4064,6 +4052,16 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 $board_url = generate_board_url() . '/'; $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path; + // Which timezone? + $tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone'])); + + // Send a proper content-language to the output + $user_lang = $user->lang['USER_LANG']; + if (strpos($user_lang, '-x-') !== false) + { + $user_lang = substr($user_lang, 0, strpos($user_lang, '-x-')); + } + // The following assigns all _common_ variables that may be used at any point in a template. $template->assign_vars(array( 'SITENAME' => $config['sitename'], diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index d42a81fa35..c0db64dbfb 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -254,7 +254,7 @@ function get_forum_list($acl_list = 'f_list', $id_only = true, $postable_only = if ($acl_list == '' || ($acl_list != '' && $auth->acl_gets($acl_list, $row['forum_id']))) { - $rowset[] = ($id_only) ? $row['forum_id'] : $row; + $rowset[] = ($id_only) ? (int) $row['forum_id'] : $row; } } @@ -2514,6 +2514,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id case 'mod': $log_type = LOG_MOD; + $sql_forum = ''; if ($topic_id) { diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 0fcf33f999..8f4e582b3c 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -199,7 +199,7 @@ class messenger $template_path .= $template_lang . '/email'; } - $tpl->set_custom_template($template_path, $template_lang . '_email'); + $tpl->set_custom_template($template_path, $template_lang . '_email', 'email'); $tpl->set_filenames(array( 'body' => $template_file . '.txt', @@ -1134,7 +1134,24 @@ class smtp_class global $user; $err_msg = ''; - $local_host = (function_exists('php_uname')) ? gethostbyaddr(gethostbyname(php_uname('n'))) : $user->host; + + // Here we try to determine the *real* hostname (reverse DNS entry preferrably) + $local_host = $user->host; + + if (function_exists('php_uname')) + { + $local_host = php_uname('n'); + + // Able to resolve name to IP + if (($addr = @gethostbyname($local_host)) !== $local_host) + { + // Able to resolve IP back to name + if (($name = @gethostbyaddr($addr)) !== $addr) + { + $local_host = $name; + } + } + } // If we are authenticating through pop-before-smtp, we // have to login ones before we get authenticated diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 848218ca83..c93b6a6bba 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1900,7 +1900,7 @@ function set_user_message_limit() */ function get_recipient_strings($pm_by_id) { - global $user, $db; + global $db, $phpbb_root_path, $phpEx, $user; $address_list = $recipient_list = $address = array(); diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index a7abb06674..054af29045 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -349,7 +349,6 @@ class filespec } phpbb_chmod($this->destination_file, $chmod); - return true; } // Try to get real filesize from destination folder diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 270b0055d9..7bed20187a 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -593,7 +593,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) $db->sql_query($sql); if ($action == 'delete') - {echo "aha"; + { delete_pm(ANONYMOUS, $close_report_posts, PRIVMSGS_INBOX); } } diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index e73cccce1e..eb3d6d3970 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -259,7 +259,7 @@ function mcp_topic_view($id, $mode, $action) // Display topic icons for split topic $s_topic_icons = false; - if ($auth->acl_get('m_split', $topic_info['forum_id'])) + if ($auth->acl_gets('m_split', 'm_merge', (int) $topic_info['forum_id'])) { include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); $s_topic_icons = posting_gen_topic_icons('', $icon_id); diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 72c101f7a3..3df582d640 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1345,7 +1345,7 @@ class parse_message extends bbcode_firstpass /** * Parse Attachments */ - function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false, $post_msg_id = 0, $topic_id = 0) + function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false) { global $config, $auth, $user, $phpbb_root_path, $phpEx, $db; @@ -1498,25 +1498,16 @@ class parse_message extends bbcode_firstpass 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'thumbnail' => $filedata['thumbnail'], - 'is_orphan' => ($post_msg_id) ? 0 : 1, + 'is_orphan' => 1, 'in_message' => ($is_message) ? 1 : 0, 'poster_id' => $user->data['user_id'], ); - if ($post_msg_id) - { - $sql_ary['post_msg_id'] = $post_msg_id; - if ($topic_id) - { - $sql_ary['topic_id'] = $topic_id; - } - } - $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); $new_entry = array( 'attach_id' => $db->sql_nextid(), - 'is_orphan' => ($post_msg_id) ? 0 : 1, + 'is_orphan' => 1, 'real_filename' => $filedata['real_filename'], 'attach_comment'=> $this->filename_data['filecomment'], ); diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index dcfde14159..bf41fea7de 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')) ? gethostbyaddr(gethostbyname(php_uname('n'))) : 'localhost'; + $host = (function_exists('php_uname')) ? php_uname('n') : 'localhost'; } } diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php index 80434aca4c..648af61c00 100644 --- a/phpBB/includes/template.php +++ b/phpBB/includes/template.php @@ -90,7 +90,7 @@ class template * Set custom template location (able to use directory outside of phpBB) * @access public */ - function set_custom_template($template_path, $template_name) + function set_custom_template($template_path, $template_name, $template_mode = 'template') { global $phpbb_root_path, $user; @@ -102,8 +102,13 @@ class template $this->root = $template_path; $this->cachepath = $phpbb_root_path . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_'; - $user->theme['template_storedb'] = false; - $user->theme['template_inherits_id'] = false; + + // As the template-engine is used for more than the template (emails, etc.), we should not set $user->theme in all cases, but only on the real template. + if ($template_mode == 'template') + { + $user->theme['template_storedb'] = false; + $user->theme['template_inherits_id'] = false; + } $this->_rootref = &$this->_tpldata['.'][0]; diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index ea57246527..423d9b718a 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -708,7 +708,6 @@ class ucp_groups 'S_UPLOAD_AVATAR_FILE' => ($config['allow_avatar'] && $config['allow_avatar_upload'] && $can_upload) ? true : false, 'S_UPLOAD_AVATAR_URL' => ($config['allow_avatar'] && $config['allow_avatar_remote_upload'] && $can_upload) ? true : false, 'S_LINK_AVATAR' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false, - 'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local']) ? true : false, 'ERROR_MSG' => (sizeof($error)) ? implode('
    ', $error) : '', 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 1d428ce92e..fba3bfeb32 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -669,22 +669,7 @@ function compose_pm($id, $mode, $action) } // Parse Attachments - before checksum is calculated - if ($action == 'edit') - { - $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true, $msg_id); - if (sizeof($message_parser->attachment_data)) - { - // Update attachment indicators for pms having attachments now, as a precaution if the pm does not get stored by submit - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET message_attachment = 1 - WHERE msg_id = ' . $msg_id; - $db->sql_query($sql); - } - } - else - { - $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); - } + $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); if (sizeof($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc)) { diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index f4fc466ac7..5a6603883b 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -31,8 +31,8 @@ unset($dbpasswd); */ $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', - 'version' => '1.0.2', - 'phpbb_version' => '3.0.4', + 'version' => '1.0.3', + 'phpbb_version' => '3.0.6', 'author' => 'phpBB Group', 'dbms' => $dbms, 'dbhost' => $dbhost, @@ -129,7 +129,7 @@ $config_schema = array( 'board_timezone' => 'board_timezone', 'allow_privmsg' => 'not(privmsg_disable)', 'gzip_compress' => 'gzip_compress', - 'coppa_enable' => 'is_empty(coppa_mail)', + 'coppa_enable' => '!is_empty(coppa_mail)', 'coppa_fax' => 'coppa_fax', 'coppa_mail' => 'coppa_mail', 'record_online_users' => 'record_online_users', diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 41983400fc..7ef76535d3 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -8,7 +8,7 @@ * */ -$updates_to_version = '3.0.6-RC1'; +$updates_to_version = '3.0.6-RC2'; // Enter any version to update from to test updates. The version within the db will not be updated. $debug_from_version = false; @@ -868,9 +868,6 @@ function database_update_info() ), ), 'add_index' => array( - LOG_TABLE => array( - 'log_time' => array('log_time'), - ), REPORTS_TABLE => array( 'post_id' => array('post_id'), 'pm_id' => array('pm_id'), @@ -880,6 +877,12 @@ function database_update_info() ), ), ), + // Changes from 3.0.6-RC1 to 3.0.6-RC2 + '3.0.6-RC1' => array( + 'drop_keys' => array( + LOG_TABLE => array('log_time'), + ), + ), ); } @@ -1506,6 +1509,10 @@ function change_database_data(&$no_updates, $version) $no_updates = false; break; + + // No changes from 3.0.6-RC1 to 3.0.6-RC2 + case '3.0.6-RC1': + break; } } @@ -1902,7 +1909,8 @@ class updater_db_tools { if ($column_exists) { - $sqlite_data[$table]['change_columns'][] = $result; + continue; +// $sqlite_data[$table]['change_columns'][] = $result; } else { @@ -1924,6 +1932,11 @@ class updater_db_tools { foreach ($indexes as $index_name) { + if (!$this->sql_index_exists($table, $index_name)) + { + continue; + } + $result = $this->sql_index_drop($table, $index_name); if ($this->return_statements) @@ -1984,6 +1997,11 @@ class updater_db_tools { foreach ($index_array as $index_name => $column) { + if ($this->sql_unique_index_exists($table, $index_name)) + { + continue; + } + $result = $this->sql_create_unique_index($table, $index_name, $column); if ($this->return_statements) @@ -2001,6 +2019,11 @@ class updater_db_tools { foreach ($index_array as $index_name => $column) { + if ($this->sql_index_exists($table, $index_name)) + { + continue; + } + $result = $this->sql_create_index($table, $index_name, $column); if ($this->return_statements) @@ -2308,6 +2331,229 @@ class updater_db_tools } } + /** + * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes. + * + * @param string $table_name Table to check the index at + * @param string $index_name The index name to check + * + * @return bool True if index exists, else false + */ + function sql_index_exists($table_name, $index_name) + { + if ($this->sql_layer == 'mssql') + { + $sql = "EXEC sp_statistics '$table_name'"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + if ($row['TYPE'] == 3) + { + if (strtolower($row['INDEX_NAME']) == strtolower($index_name)) + { + $this->db->sql_freeresult($result); + return true; + } + } + } + $this->db->sql_freeresult($result); + + return false; + } + + switch ($this->sql_layer) + { + case '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 = '" . strtoupper($table_name) . "' + AND generated = 'N' + AND uniqueness = 'NONUNIQUE'"; + $col = 'index_name'; + break; + + case 'sqlite': + $sql = "PRAGMA index_list('" . $table_name . "');"; + $col = 'name'; + break; + } + + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique']) + { + continue; + } + + // These DBMS prefix index name with the table name + switch ($this->sql_layer) + { + case 'firebird': + case 'oracle': + case 'postgres': + case 'sqlite': + $row[$col] = substr($row[$col], strlen($table_name) + 1); + break; + } + + if (strtolower($row[$col]) == strtolower($index_name)) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + + return false; + } + + /** + * Check if a specified UNIQUE index exists in table. + * + * @param string $table_name Table to check the index at + * @param string $index_name The index name to check + * + * @return bool True if index exists, else false + */ + function sql_unique_index_exists($table_name, $index_name) + { + if ($this->sql_layer == 'mssql') + { + $sql = "EXEC sp_statistics '$table_name'"; + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + // Usually NON_UNIQUE is the column we want to check, but we allow for both + if ($row['TYPE'] == 3) + { + if (strtolower($row['INDEX_NAME']) == strtolower($index_name)) + { + $this->db->sql_freeresult($result); + return true; + } + } + } + $this->db->sql_freeresult($result); + return false; + } + + switch ($this->sql_layer) + { + case '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 NOT NULL + AND RDB\$FOREIGN_KEY IS NULL"; + $col = 'index_name'; + break; + + case 'postgres': + $sql = "SELECT ic.relname as index_name, i.indisunique + FROM pg_class bc, pg_class ic, pg_index i + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (bc.relname = '" . $table_name . "') + AND (i.indisprimary != 't')"; + $col = 'index_name'; + break; + + case 'mysql_40': + case 'mysql_41': + $sql = 'SHOW KEYS + FROM ' . $table_name; + $col = 'Key_name'; + break; + + case 'oracle': + $sql = "SELECT index_name, table_owner + FROM user_indexes + WHERE table_name = '" . strtoupper($table_name) . "' + AND generated = 'N' + AND uniqueness = 'UNIQUE' + AND index_name LIKE 'U_%'"; + $col = 'index_name'; + break; + + case 'sqlite': + $sql = "PRAGMA index_list('" . $table_name . "') WHERE unique = 1;"; + $col = 'name'; + break; + } + + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && ($row['Non_unique'] || $row[$col] == 'PRIMARY')) + { + continue; + } + + if ($this->sql_layer == 'sqlite' && !$row['unique']) + { + continue; + } + + if ($this->sql_layer == 'postgres' && $row['indisunique'] != 't') + { + continue; + } + + // These DBMS prefix index name with the table name + switch ($this->sql_layer) + { + case 'oracle': + $row[$col] = substr($row[$col], strlen('U_' . $row['table_owner']) + 1); + break; + + case 'firebird': + case 'postgres': + case 'sqlite': + $row[$col] = substr($row[$col], strlen($table_name) + 1); + break; + } + + if (strtolower($row[$col]) == strtolower($index_name)) + { + $this->db->sql_freeresult($result); + return true; + } + } + $this->db->sql_freeresult($result); + + return false; + } + /** * Private method for performing sql statements (either execute them or return them) * @access private @@ -2441,11 +2687,13 @@ class updater_db_tools // For hexadecimal values do not use single quotes if (strpos($column_data[1], '0x') === 0) { - $sql_default .= 'DEFAULT (' . $column_data[1] . ') '; + $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') '; + $sql_default .= $return_array['default']; } else { - $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + $sql_default .= $return_array['default']; } } @@ -2965,6 +3213,27 @@ class updater_db_tools case 'mssql': $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; + + if (!empty($column_data['default'])) + { + // Using TRANSACT-SQL for this statement because we do not want to have colliding data if statements are executed at a later stage + $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) + SET @drop_default_name = + (SELECT so.name FROM sysobjects so + JOIN sysconstraints sc ON so.id = sc.constid + WHERE object_name(so.parent_obj) = '{$table_name}' + AND so.xtype = 'D' + AND sc.colid = (SELECT colid FROM syscolumns + WHERE id = object_id('{$table_name}') + AND name = '{$column_name}')) + IF @drop_default_name <> '' + BEGIN + SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' + EXEC(@cmd) + END + SET @cmd = 'ALTER TABLE [{$table_name}] ADD CONSTRAINT [DF_{$table_name}_{$column_name}_1] {$column_data['default']} FOR [{$column_name}]' + EXEC(@cmd)"; + } break; case 'mysql_40': diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index ad72652e97..ab7ec35705 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -687,7 +687,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_new_output()); + $contents = implode("\n", $diff->merged_output()); unset($diff); break; } @@ -1104,24 +1104,6 @@ class install_update extends module break; -/* - $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file); - - $tmp = array( - 'file1' => array(), - 'file2' => ($option == MERGE_NEW_FILE) ? implode("\n", $diff->merged_new_output()) : implode("\n", $diff->merged_orig_output()), - ); - - $diff = new diff($tmp['file1'], $tmp['file2']); - - unset($tmp); - - $template->assign_var('S_DIFF_NEW_FILE', true); - $diff_mode = 'inline'; - $this->page_title = 'VIEWING_FILE_CONTENTS'; - - break; -*/ // Merge differences and use new phpBB code for conflicted blocks case MERGE_NEW_FILE: case MERGE_MOD_FILE: @@ -1175,6 +1157,7 @@ class install_update extends module default: $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $original_file, $this->new_location . $file); + $diff = $this->return_diff($phpbb_root_path . $file, $diff->merged_output()); break; } break; @@ -1362,6 +1345,9 @@ class install_update extends module $update_ary['original'] = $original_file; } + // we only want to know if the files are successfully merged and newlines could result in errors (duplicate addition of lines and such things) + // Therefore we check for empty diffs with two methods, preserving newlines and not preserving them (which mostly works best, therefore the first option) + // On a successfull update the new location file exists but the old one does not exist. // Check for this circumstance, the new file need to be up-to-date with the current file then... if (!file_exists($this->old_location . $original_file) && file_exists($this->new_location . $original_file) && file_exists($phpbb_root_path . $file)) @@ -1401,104 +1387,141 @@ class install_update extends module trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR); } - $tmp = array( - 'file1' => file_get_contents($this->old_location . $original_file), - 'file2' => file_get_contents($phpbb_root_path . $file), - ); + $preserve_cr_ary = array(false, true); - // We need to diff the contents here to make sure the file is really the one we expect - $diff = new diff($tmp['file1'], $tmp['file2'], false); - $empty_1 = $diff->is_empty(); - - unset($tmp, $diff); - - $tmp = array( - 'file1' => file_get_contents($this->new_location . $original_file), - 'file2' => file_get_contents($phpbb_root_path . $file), - ); - - // We need to diff the contents here to make sure the file is really the one we expect - $diff = new diff($tmp['file1'], $tmp['file2'], false); - $empty_2 = $diff->is_empty(); - - unset($tmp, $diff); - - // If the file is not modified we are finished here... - if ($empty_1) + foreach ($preserve_cr_ary as $preserve_cr) { - // Further check if it is already up to date - it could happen that non-modified files - // slip through + $tmp = array( + 'file1' => file_get_contents($this->old_location . $original_file), + 'file2' => file_get_contents($phpbb_root_path . $file), + ); + + // We need to diff the contents here to make sure the file is really the one we expect + $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr); + $empty_1 = $diff->is_empty(); + + unset($tmp, $diff); + + $tmp = array( + 'file1' => file_get_contents($this->new_location . $original_file), + 'file2' => file_get_contents($phpbb_root_path . $file), + ); + + $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr); + $empty_2 = $diff->is_empty(); + + unset($tmp, $diff); + + // If the file is not modified we are finished here... + if ($empty_1) + { + // Further check if it is already up to date - it could happen that non-modified files + // slip through + if ($empty_2) + { + $update_list['up_to_date'][] = $update_ary; + return; + } + + $update_list['not_modified'][] = $update_ary; + return; + } + + // If the file had been modified then we need to check if it is already up to date + + // if there are no differences we have an up-to-date file... if ($empty_2) { $update_list['up_to_date'][] = $update_ary; return; } - - $update_list['not_modified'][] = $update_ary; - return; } - // If the file had been modified then we need to check if it is already up to date + $conflicts = false; - // if there are no differences we have an up-to-date file... - if ($empty_2) + foreach ($preserve_cr_ary as $preserve_cr) { - $update_list['up_to_date'][] = $update_ary; - return; - } - - // if the file is modified we try to make sure a merge succeed - $tmp = array( - 'file1' => file_get_contents($this->old_location . $original_file), - 'file2' => file_get_contents($phpbb_root_path . $file), - 'file3' => file_get_contents($this->new_location . $original_file), - ); - - $diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3'], false); - - unset($tmp); - - if ($diff->get_num_conflicts()) - { - $update_ary['conflicts'] = $diff->get_num_conflicts(); - - // There is one special case... users having merged with a conflicting file... we need to check this + // if the file is modified we try to make sure a merge succeed $tmp = array( - 'file1' => file_get_contents($phpbb_root_path . $file), - 'file2' => implode("\n", $diff->merged_orig_output()), + 'orig' => file_get_contents($this->old_location . $original_file), + 'final1' => file_get_contents($phpbb_root_path . $file), + 'final2' => file_get_contents($this->new_location . $original_file), ); - $diff = new diff($tmp['file1'], $tmp['file2'], false); - $empty = $diff->is_empty(); + $diff = new diff3($tmp['orig'], $tmp['final1'], $tmp['final2'], $preserve_cr); + unset($tmp); - if ($empty) + if (!$diff->get_num_conflicts()) { - unset($update_ary['conflicts']); - unset($diff); - $update_list['up_to_date'][] = $update_ary; - return; + $tmp = array( + 'file1' => file_get_contents($phpbb_root_path . $file), + 'file2' => implode("\n", $diff->merged_output()), + ); + + // now compare the merged output with the original file to see if the modified file is up to date + $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr); + $empty = $diff2->is_empty(); + + unset($diff, $diff2); + + if ($empty) + { + $update_list['up_to_date'][] = $update_ary; + return; + } + + // If we preserve cr tag it as modified because the conflict would not show in this mode anyway + if ($preserve_cr) + { + $update_list['modified'][] = $update_ary; + return; + } } + else + { + // There is one special case... users having merged with a conflicting file... we need to check this + $tmp = array( + 'file1' => file_get_contents($phpbb_root_path . $file), + 'file2' => implode("\n", $diff->merged_new_output()), + ); - $update_list['conflict'][] = $update_ary; - unset($diff); + $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr); + $empty = $diff2->is_empty(); - return; + if (!$empty) + { + unset($tmp, $diff2); + + // We check if the user merged with his output + $tmp = array( + 'file1' => file_get_contents($phpbb_root_path . $file), + 'file2' => implode("\n", $diff->merged_orig_output()), + ); + + $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr); + $empty = $diff2->is_empty(); + } + + if (!$empty) + { + $conflicts = $diff->get_num_conflicts(); + } + + unset($diff, $diff2); + + if ($empty) + { + // A conflict got resolved... + $update_list['up_to_date'][] = $update_ary; + return; + } + } } - $tmp = array( - 'file1' => file_get_contents($phpbb_root_path . $file), - '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 = new diff($tmp['file1'], $tmp['file2'], false); - $empty = $diff->is_empty(); - - if ($empty) + if ($conflicts !== false) { - unset($diff); - - $update_list['up_to_date'][] = $update_ary; + $update_ary['conflicts'] = $conflicts; + $update_list['conflict'][] = $update_ary; return; } @@ -1650,7 +1673,7 @@ class install_update extends module /** * Wrapper for returning a diff object */ - function &return_diff() + function return_diff() { $args = func_get_args(); $three_way_diff = (func_num_args() > 2) ? true : false; diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 5c653afc41..18bd8d8e9a 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -239,7 +239,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.6-RC1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.0.6-RC2'); 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'); diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index b653d54318..9543c712da 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -451,8 +451,8 @@ $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 modifications (Loose new phpBB code within conflicting block)', - 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (Loose modified code within conflicting block)', + 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)', + 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)', 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.', 'MERGING_FILES' => 'Merging differences', 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.

    Please wait until phpBB has completed all operations on changed files.', diff --git a/phpBB/posting.php b/phpBB/posting.php index b241da2eab..1c7cd95b81 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -742,28 +742,7 @@ if ($submit || $preview || $refresh) } // Parse Attachments - before checksum is calculated - if ($mode == 'edit') - { - $message_parser->parse_attachments('fileupload', $mode, $forum_id, $submit, $preview, $refresh, false, $post_id, $topic_id); - if (sizeof($message_parser->attachment_data)) - { - // Update attachment indicators for post/topic having attachments now, as a precaution if the post does not get stored by submit - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_attachment = 1 - WHERE post_id = ' . $post_id; - $db->sql_query($sql); - - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_attachment = 1 - WHERE topic_id = ' . $topic_id; - $db->sql_query($sql); - } - } - else - { - $message_parser->parse_attachments('fileupload', $mode, $forum_id, $submit, $preview, $refresh); - } - + $message_parser->parse_attachments('fileupload', $mode, $forum_id, $submit, $preview, $refresh); // Grab md5 'checksum' of new message $message_md5 = md5($message_parser->message); @@ -1121,13 +1100,13 @@ if ($submit || $preview || $refresh) // The last parameter tells submit_post if search indexer has to be run $redirect_url = submit_post($mode, $post_data['post_subject'], $post_data['username'], $post_data['topic_type'], $poll, $data, $update_message, ($update_message || $update_subject) ? true : false); - if ($config['enable_post_confirm'] && !$user->data['is_registered'] && (isset($captcha) && $captcha->is_solved() === true) && ($mode == 'post' || $mode == 'reply' || $mode == 'quote')) { $captcha->reset(); } + // Check the permissions for post approval. Moderators are not affected. - if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) + if ((!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) || !empty($post_data['force_approved_state'])) { meta_refresh(10, $redirect_url); $message = ($mode == 'edit') ? $user->lang['POST_EDITED_MOD'] : $user->lang['POST_STORED_MOD']; @@ -1569,17 +1548,18 @@ function handle_post_delete($forum_id, $topic_id, $post_id, &$post_data) ); $next_post_id = delete_post($forum_id, $topic_id, $post_id, $data); + $post_username = ($post_data['poster_id'] == ANONYMOUS && !empty($post_data['post_username'])) ? $post_data['post_username'] : $post_data['username']; if ($next_post_id === false) { - add_log('mod', $forum_id, $topic_id, 'LOG_DELETE_TOPIC', $post_data['topic_title'], $post_data['username']); + add_log('mod', $forum_id, $topic_id, 'LOG_DELETE_TOPIC', $post_data['topic_title'], $post_username); $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id"); $message = $user->lang['POST_DELETED']; } else { - add_log('mod', $forum_id, $topic_id, 'LOG_DELETE_POST', $post_data['post_subject'], $post_data['username']); + add_log('mod', $forum_id, $topic_id, 'LOG_DELETE_POST', $post_data['post_subject'], $post_username); $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p=$next_post_id") . "#p$next_post_id"; $message = $user->lang['POST_DELETED'] . '

    ' . sprintf($user->lang['RETURN_TOPIC'], '', ''); diff --git a/phpBB/report.php b/phpBB/report.php index db9c957ea8..d154acf03b 100644 --- a/phpBB/report.php +++ b/phpBB/report.php @@ -118,7 +118,8 @@ else if (!$report_data) { - trigger_error('PM_NOT_EXIST'); + $user->add_lang('ucp'); + trigger_error('NO_MESSAGE'); } if ($report_data['message_reported']) diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index 9fcafee34a..e9ed5d9daf 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -27,7 +27,7 @@
  • - + {forumrow.FORUM_IMAGE} {forumrow.FORUM_NAME}
    diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index e7522841e3..7fb954017d 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -1678,7 +1678,8 @@ else if (!$all_marked_read) } // let's set up quick_reply -$s_quick_reply = $user->data['is_registered'] && $config['allow_quick_reply'] && ($topic_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) && $auth->acl_get('f_reply', $forum_id); +$s_allowed_reply = ((!$auth->acl_get('f_reply', $forum_id) || ($topic_data['forum_status'] == ITEM_LOCKED) || ($topic_data['topic_status'] == ITEM_LOCKED)) && !$auth->acl_get('m_edit', $forum_id)) ? false : true; +$s_quick_reply = $s_allowed_reply && $user->data['is_registered'] && $config['allow_quick_reply'] && ($topic_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY); if ($s_can_vote || $s_quick_reply) { @@ -1704,6 +1705,7 @@ if ($s_can_vote || $s_quick_reply) (!$config['allow_post_links']) ? $qr_hidden_fields['disable_magic_url'] = 1 : true; ($s_attach_sig) ? $qr_hidden_fields['attach_sig'] = 1 : true; ($s_notify) ? $qr_hidden_fields['notify'] = 1 : true; + ($topic_data['topic_status'] == ITEM_LOCKED) ? $qr_hidden_fields['lock_topic'] = 1 : true; $template->assign_vars(array( 'S_QUICK_REPLY' => true,
  • {inactive.REASON}
    {inactive.REMINDED_EXPLAIN} +
    {L_REPORT_BY} {L_TIME} {L_FEEDBACK}{L_MARK}{L_MARK}
    {warn.USERNAME} {warn.DATE} {warn.ACTION}