aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore22
-rw-r--r--build/build.xml32
-rw-r--r--phpBB/adm/style/acp_ranks.html2
-rw-r--r--phpBB/adm/style/acp_users_signature.html5
-rw-r--r--phpBB/adm/style/install_footer.html2
-rw-r--r--phpBB/adm/style/overall_footer.html2
-rw-r--r--phpBB/adm/style/simple_footer.html2
-rw-r--r--phpBB/develop/create_variable_overview.php6
-rw-r--r--phpBB/docs/CHANGELOG.html2
-rw-r--r--phpBB/feed.php31
-rw-r--r--phpBB/includes/acp/acp_inactive.php2
-rw-r--r--phpBB/includes/acp/acp_logs.php4
-rw-r--r--phpBB/includes/acp/acp_main.php7
-rw-r--r--phpBB/includes/acp/acp_php_info.php8
-rw-r--r--phpBB/includes/acp/acp_styles.php1
-rw-r--r--phpBB/includes/acp/acp_update.php7
-rw-r--r--phpBB/includes/acp/acp_users.php2
-rw-r--r--phpBB/includes/auth.php8
-rw-r--r--phpBB/includes/bbcode.php7
-rw-r--r--phpBB/includes/db/db_tools.php4
-rw-r--r--phpBB/includes/db/dbal.php2
-rw-r--r--phpBB/includes/db/mysqli.php18
-rw-r--r--phpBB/includes/functions.php74
-rw-r--r--phpBB/includes/functions_admin.php47
-rw-r--r--phpBB/includes/functions_content.php2
-rw-r--r--phpBB/includes/functions_display.php132
-rw-r--r--phpBB/includes/functions_transfer.php55
-rw-r--r--phpBB/includes/mcp/mcp_logs.php4
-rw-r--r--phpBB/includes/mcp/mcp_notes.php2
-rw-r--r--phpBB/includes/session.php70
-rw-r--r--phpBB/index.php14
-rw-r--r--phpBB/install/database_update.php2259
-rw-r--r--phpBB/install/index.php2
-rw-r--r--phpBB/language/en/acp/board.php2
-rw-r--r--phpBB/language/en/common.php8
-rw-r--r--phpBB/language/en/install.php2
-rw-r--r--phpBB/language/en/posting.php4
-rw-r--r--phpBB/memberlist.php38
-rw-r--r--phpBB/report.php7
-rw-r--r--phpBB/styles/prosilver/imageset/site_logo.gifbin3430 -> 5070 bytes
-rw-r--r--phpBB/styles/prosilver/template/forumlist_body.html6
-rw-r--r--phpBB/styles/prosilver/template/jumpbox.html2
-rw-r--r--phpBB/styles/prosilver/template/memberlist_body.html33
-rw-r--r--phpBB/styles/prosilver/template/memberlist_view.html2
-rw-r--r--phpBB/styles/prosilver/template/overall_footer.html2
-rw-r--r--phpBB/styles/prosilver/template/overall_header.html4
-rw-r--r--phpBB/styles/prosilver/template/posting_buttons.html4
-rw-r--r--phpBB/styles/prosilver/template/simple_footer.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html2
-rw-r--r--phpBB/styles/prosilver/template/viewforum_body.html6
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_print.html2
-rw-r--r--phpBB/styles/prosilver/theme/content.css12
-rw-r--r--phpBB/styles/subsilver2/template/attachment.html2
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_body.html7
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_view.html4
-rw-r--r--phpBB/styles/subsilver2/template/overall_footer.html2
-rw-r--r--phpBB/styles/subsilver2/template/posting_buttons.html5
-rw-r--r--phpBB/styles/subsilver2/template/simple_footer.html2
-rw-r--r--phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html2
-rw-r--r--phpBB/styles/subsilver2/template/viewtopic_print.html2
-rw-r--r--phpBB/viewforum.php2
-rw-r--r--phpBB/viewtopic.php25
-rw-r--r--tests/network/ftp_fsock_pasv_epsv_test.php63
-rw-r--r--tests/tmp/.gitkeep (renamed from tests/utf/data/.gitkeep)0
-rw-r--r--tests/utf/normalizer_test.php11
-rw-r--r--tests/wrapper/gmgetdate_test.php49
-rw-r--r--tests/wrapper/mt_rand_test.php (renamed from tests/random/mt_rand.php)2
-rw-r--r--tests/wrapper/version_compare_test.php130
68 files changed, 792 insertions, 2491 deletions
diff --git a/.gitignore b/.gitignore
index 8298f5a894..7d789c59a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,12 @@
*~
-phpunit.xml
-phpBB/cache/*.php
-phpBB/cache/queue.php.lock
-phpBB/config.php
-phpBB/files/*
-phpBB/images/avatars/gallery/*
-phpBB/images/avatars/upload/*
-phpBB/store/*
-tests/phpbb_unit_tests.sqlite2
-tests/test_config.php
-tests/utf/data/*.txt
+/phpunit.xml
+/phpBB/cache/*.php
+/phpBB/cache/queue.php.lock
+/phpBB/config.php
+/phpBB/files/*
+/phpBB/images/avatars/gallery/*
+/phpBB/images/avatars/upload/*
+/phpBB/store/*
+/tests/phpbb_unit_tests.sqlite2
+/tests/test_config.php
+/tests/tmp/*
diff --git a/build/build.xml b/build/build.xml
index 42642dcefa..eb63bde034 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -4,7 +4,7 @@
<!-- a few settings for the build -->
<property name="newversion" value="3.0.9" />
<property name="prevversion" value="3.0.8" />
- <property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.9-RC1, 3.0.9-RC2, 3.0.9-RC3" />
+ <property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.9-RC1, 3.0.9-RC2, 3.0.9-RC3, 3.0.9-RC4" />
<!-- no configuration should be needed beyond this point -->
<property name="oldversions" value="${olderversions}, ${prevversion}" />
@@ -49,19 +49,16 @@
--coverage-clover build/logs/clover.xml
--coverage-html build/coverage"
passthru="true" />
+ </target>
-
- <!-- Does not allow changing the working directory to tests/
- so this approach does not work for us unfortunately
- <phpunit codecoverage="true" haltonfailure="true">
- <formatter todir="build/logs" type="xml"/>
- <batchtest>
- <fileset dir="tests">
- <include name="all_tests.php"/>
- </fileset>
- </batchtest>
- </phpunit>
- -->
+ <target name="test-slow" depends="clean,prepare">
+ <exec dir="."
+ command="phpunit --log-junit build/logs/phpunit.xml
+ --configuration phpunit.xml.all
+ --group slow
+ --coverage-clover build/logs/clover-slow.xml
+ --coverage-html build/coverage-slow"
+ passthru="true" />
</target>
<target name="docs">
@@ -122,6 +119,15 @@
<target name="create-package" depends="prepare-new-version,old-version-diffs">
<exec dir="build" command="php -f package.php '${versions}' > logs/package.log" escape="false" />
<exec dir="build" command="php -f build_diff.php '${prevversion}' '${newversion}' > logs/build_diff.log" escape="false" />
+ <exec dir="build" escape="false"
+ command="diff -crNEBwd old_versions/release-${prevversion}/language new_version/phpBB3/language >
+ save/save_${prevversion}_to_${newversion}/language/phpbb-${prevversion}_to_${newversion}_language.patch" />
+ <exec dir="build" escape="false"
+ command="diff -crNEBwd old_versions/release-${prevversion}/styles/prosilver new_version/phpBB3/styles/prosilver >
+ save/save_${prevversion}_to_${newversion}/prosilver/phpbb-${prevversion}_to_${newversion}_prosilver.patch" />
+ <exec dir="build" escape="false"
+ command="diff -crNEBwd old_versions/release-${prevversion}/styles/subsilver2 new_version/phpBB3/styles/subsilver2 >
+ save/save_${prevversion}_to_${newversion}/subsilver2/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" />
</target>
<!--
diff --git a/phpBB/adm/style/acp_ranks.html b/phpBB/adm/style/acp_ranks.html
index 2ad8b3e8aa..1f45109517 100644
--- a/phpBB/adm/style/acp_ranks.html
+++ b/phpBB/adm/style/acp_ranks.html
@@ -35,7 +35,7 @@
</dl>
<dl>
<dt><label for="special_rank">{L_RANK_SPECIAL}:</label></dt>
- <dd><label><input onclick="dE('posts', -1)" type="radio" class="radio" name="special_rank" value="1" id="special_rank"<!-- IF S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> />{L_YES}</label>
+ <dd><label><input onclick="dE('posts', -1)" type="radio" class="radio" name="special_rank" value="1" id="special_rank"<!-- IF S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input onclick="dE('posts', 1)" type="radio" class="radio" name="special_rank" value="0"<!-- IF not S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<!-- IF S_SPECIAL_RANK --><div id="posts" style="display: none;"><!-- ELSE --><div id="posts"><!-- ENDIF -->
diff --git a/phpBB/adm/style/acp_users_signature.html b/phpBB/adm/style/acp_users_signature.html
index 69c6d8f3fb..0fd6c04fa5 100644
--- a/phpBB/adm/style/acp_users_signature.html
+++ b/phpBB/adm/style/acp_users_signature.html
@@ -22,9 +22,8 @@
w: '{LA_BBCODE_W_HELP}',
s: '{LA_BBCODE_S_HELP}',
f: '{LA_BBCODE_F_HELP}',
- e: '{LA_BBCODE_E_HELP}',
+ y: '{LA_BBCODE_Y_HELP}',
d: '{LA_BBCODE_D_HELP}',
- t: '{LA_BBCODE_T_HELP}',
tip: '{L_STYLES_TIP}'
<!-- BEGIN custom_tags -->
,cb_{custom_tags.BBCODE_ID}: '{custom_tags.A_BBCODE_HELPLINE}'
@@ -56,7 +55,7 @@
<input type="button" class="button2" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" onmouseover="helpline('c')" onmouseout="helpline('tip')" />
<input type="button" class="button2" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" onmouseover="helpline('l')" onmouseout="helpline('tip')" />
<input type="button" class="button2" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" onmouseover="helpline('o')" onmouseout="helpline('tip')" />
- <input type="button" class="button2" accesskey="y" name="addlitsitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('e')" onmouseout="helpline('tip')" />
+ <input type="button" class="button2" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('y')" onmouseout="helpline('tip')" />
<!-- IF S_BBCODE_IMG -->
<input type="button" class="button2" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" onmouseover="helpline('p')" onmouseout="helpline('tip')" />
<!-- ENDIF -->
diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html
index 9b5494b8b6..26a3c6ab3d 100644
--- a/phpBB/adm/style/install_footer.html
+++ b/phpBB/adm/style/install_footer.html
@@ -8,7 +8,7 @@
</div>
<div id="page-footer">
- Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
</div>
</div>
diff --git a/phpBB/adm/style/overall_footer.html b/phpBB/adm/style/overall_footer.html
index 03ca369562..b48b449597 100644
--- a/phpBB/adm/style/overall_footer.html
+++ b/phpBB/adm/style/overall_footer.html
@@ -9,7 +9,7 @@
<div id="page-footer">
<!-- IF S_COPYRIGHT_HTML -->
- Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
<!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF -->
<!-- ENDIF -->
diff --git a/phpBB/adm/style/simple_footer.html b/phpBB/adm/style/simple_footer.html
index 7276fb4b63..ac9c26a690 100644
--- a/phpBB/adm/style/simple_footer.html
+++ b/phpBB/adm/style/simple_footer.html
@@ -5,7 +5,7 @@
<div id="page-footer">
<!-- IF S_COPYRIGHT_HTML -->
- <br />Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ <br />Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
<!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF -->
<!-- ENDIF -->
diff --git a/phpBB/develop/create_variable_overview.php b/phpBB/develop/create_variable_overview.php
index b5ed090a75..fe7cacf0d1 100644
--- a/phpBB/develop/create_variable_overview.php
+++ b/phpBB/develop/create_variable_overview.php
@@ -83,7 +83,7 @@ $html_skeleton .= '<br><br><a name="ref"></a><b>References: </b>{SEE_FILES}';
$html_skeleton .= '
<br><br>
-<div class="copyright" align="center">Powered by phpBB 2.2 &copy; <a href="http://www.phpbb.com/" target="_phpbb" class="copyright">phpBB Group</a>, 2003</div>
+<div class="copyright" align="center">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group</div>
<br clear="all" /></td>
</tr>
@@ -405,7 +405,7 @@ $html_data .= '<br><li><a href="./lang_index.html" class="gen">Appendix A: Langu
$html_data .= '
</ol><br><br>
-<div class="copyright" align="center">Powered by phpBB 2.2 &copy; <a href="http://www.phpbb.com/" target="_phpbb" class="copyright">phpBB Group</a>, 2003</div>
+<div class="copyright" align="center">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group</div>
<br clear="all" /></td>
</tr>
@@ -528,7 +528,7 @@ foreach ($lang_fp as $filepointer)
$html_data .= '
<br><br>
-<div class="copyright" align="center">Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group</div>
+<div class="copyright" align="center">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group</div>
<br clear="all" /></td>
</tr>
diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index c0ec93cafb..6437fef1d5 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -335,6 +335,8 @@
</li>
<li>[<a href='http://tracker.phpbb.com/browse/PHPBB3-10247'>PHPBB3-10247</a>] - mediumint(8) too small for phpbb_login_attempts.attempt_id
</li>
+<li>[<a href='http://tracker.phpbb.com/browse/PHPBB3-10250'>PHPBB3-10250</a>] - phpBB Logo needs the Registered Trademark Symbol
+</li>
</ul>
<h4> Improvement
diff --git a/phpBB/feed.php b/phpBB/feed.php
index d737b8e10c..9816f0f303 100644
--- a/phpBB/feed.php
+++ b/phpBB/feed.php
@@ -173,6 +173,12 @@ if (defined('DEBUG_EXTRA') && request_var('explain', 0) && $auth->acl_get('a_'))
header("Content-Type: application/atom+xml; charset=UTF-8");
header("Last-Modified: " . gmdate('D, d M Y H:i:s', $feed_updated_time) . ' GMT');
+if (!empty($user->data['is_bot']))
+{
+ // Let reverse proxies know we detected a bot.
+ header('X-PHPBB-IS-BOT: yes');
+}
+
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
echo '<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="' . $global_vars['FEED_LANG'] . '">' . "\n";
echo '<link rel="self" type="application/atom+xml" href="' . $global_vars['SELF_LINK'] . '" />' . "\n\n";
@@ -604,30 +610,9 @@ class phpbb_feed_base
function get_passworded_forums()
{
- global $db, $user;
-
- // Exclude passworded forums
- $sql = 'SELECT f.forum_id, fa.user_id
- FROM ' . FORUMS_TABLE . ' f
- LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa
- ON (fa.forum_id = f.forum_id
- AND fa.session_id = '" . $db->sql_escape($user->session_id) . "')
- WHERE f.forum_password <> ''";
- $result = $db->sql_query($sql);
-
- $forum_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $forum_id = (int) $row['forum_id'];
-
- if ($row['user_id'] != $user->data['user_id'])
- {
- $forum_ids[$forum_id] = $forum_id;
- }
- }
- $db->sql_freeresult($result);
+ global $user;
- return $forum_ids;
+ return $user->get_passworded_forums();
}
function get_item()
diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php
index 1a12c4967c..c93cbc457f 100644
--- a/phpBB/includes/acp/acp_inactive.php
+++ b/phpBB/includes/acp/acp_inactive.php
@@ -301,7 +301,7 @@ class acp_inactive
'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param&amp;users_per_page=$per_page", $inactive_count, $per_page, $start, true),
'USERS_PER_PAGE' => $per_page,
- 'U_ACTION' => $this->u_action . '&amp;start=' . $start,
+ 'U_ACTION' => $this->u_action . "&amp;$u_sort_param&amp;users_per_page=$per_page&amp;start=$start",
));
$this->tpl_name = 'acp_inactive';
diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php
index 0f4f78fcdd..2fc86e325f 100644
--- a/phpBB/includes/acp/acp_logs.php
+++ b/phpBB/includes/acp/acp_logs.php
@@ -127,12 +127,12 @@ class acp_logs
// Grab log data
$log_data = array();
$log_count = 0;
- view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords);
+ $start = view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords);
$template->assign_vars(array(
'L_TITLE' => $l_title,
'L_EXPLAIN' => $l_title_explain,
- 'U_ACTION' => $this->u_action,
+ 'U_ACTION' => $this->u_action . "&amp;$u_sort_param$keywords_param&amp;start=$start",
'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start),
'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true),
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index 60cebe3c08..6d1c02248a 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -415,11 +415,8 @@ class acp_main
{
$latest_version_info = explode("\n", $latest_version_info);
- $latest_version = str_replace('rc', 'RC', strtolower(trim($latest_version_info[0])));
- $current_version = str_replace('rc', 'RC', strtolower($config['version']));
-
$template->assign_vars(array(
- 'S_VERSION_UP_TO_DATE' => version_compare($current_version, $latest_version, '<') ? false : true,
+ 'S_VERSION_UP_TO_DATE' => phpbb_version_compare(trim($latest_version_info[0]), $config['version'], '<='),
));
}
@@ -521,7 +518,7 @@ class acp_main
'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&amp;mode=admin'),
'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&amp;mode=list'),
'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&amp;mode=version_check'),
- 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=1&amp;versioncheck_force=1'),
+ 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'versioncheck_force=1'),
'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false,
'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false,
diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php
index 0499095004..7dd345971a 100644
--- a/phpBB/includes/acp/acp_php_info.php
+++ b/phpBB/includes/acp/acp_php_info.php
@@ -67,6 +67,9 @@ class acp_php_info
$output = preg_replace('#<img border="0"#i', '<img', $output);
$output = str_replace(array('class="e"', 'class="v"', 'class="h"', '<hr />', '<font', '</font>'), array('class="row1"', 'class="row2"', '', '', '<span', '</span>'), $output);
+ // Fix invalid anchor names (eg "module_Zend Optimizer")
+ $output = preg_replace_callback('#<a name="([^"]+)">#', array($this, 'remove_spaces'), $output);
+
if (empty($output))
{
trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING);
@@ -79,6 +82,11 @@ class acp_php_info
$template->assign_var('PHPINFO', $output);
}
+
+ function remove_spaces($matches)
+ {
+ return '<a name="' . str_replace(' ', '_', $matches[1]) . '">';
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index 37cf8d1f72..3bc8c86500 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -510,6 +510,7 @@ parse_css_file = {PARSE_CSS_FILE}
$db->sql_transaction('commit');
$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
+ $cache->destroy('imageset_site_logo_md5');
add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']);
trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action));
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
index b0ce8f1084..931fa53165 100644
--- a/phpBB/includes/acp/acp_update.php
+++ b/phpBB/includes/acp/acp_update.php
@@ -69,12 +69,9 @@ class acp_update
$current_version = (!empty($version_update_from)) ? $version_update_from : $config['version'];
- $up_to_date_automatic = (version_compare(str_replace('rc', 'RC', strtolower($current_version)), str_replace('rc', 'RC', strtolower($latest_version)), '<')) ? false : true;
- $up_to_date = (version_compare(str_replace('rc', 'RC', strtolower($config['version'])), str_replace('rc', 'RC', strtolower($latest_version)), '<')) ? false : true;
-
$template->assign_vars(array(
- 'S_UP_TO_DATE' => $up_to_date,
- 'S_UP_TO_DATE_AUTO' => $up_to_date_automatic,
+ 'S_UP_TO_DATE' => phpbb_version_compare($latest_version, $config['version'], '<='),
+ 'S_UP_TO_DATE_AUTO' => phpbb_version_compare($latest_version, $current_version, '<='),
'S_VERSION_CHECK' => true,
'U_ACTION' => $this->u_action,
'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&amp;versioncheck_force=1'),
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index 6be0760be0..789003e31b 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -1124,7 +1124,7 @@ class acp_users
// Grab log data
$log_data = array();
$log_count = 0;
- view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort);
+ $start = view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort);
$template->assign_vars(array(
'S_FEEDBACK' => true,
diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php
index 5564de2943..0585921426 100644
--- a/phpBB/includes/auth.php
+++ b/phpBB/includes/auth.php
@@ -349,6 +349,14 @@ class auth
/**
* Get permission listing based on user_id/options/forum_ids
+ *
+ * Be careful when using this function with permissions a_, m_, u_ and f_ !
+ * It may not work correctly. When a user group grants an a_* permission,
+ * e.g. a_foo, but the user's a_foo permission is set to "Never", then
+ * the user does not in fact have the a_ permission.
+ * But the user will still be listed as having the a_ permission.
+ *
+ * For more information see: http://tracker.phpbb.com/browse/PHPBB3-10252
*/
function acl_get_list($user_id = false, $opts = false, $forum_id = false)
{
diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php
index d77bb3c4a7..9356e3e9b4 100644
--- a/phpBB/includes/bbcode.php
+++ b/phpBB/includes/bbcode.php
@@ -584,6 +584,13 @@ class bbcode
$code = str_replace("\t", '&nbsp; &nbsp;', $code);
$code = str_replace(' ', '&nbsp; ', $code);
$code = str_replace(' ', ' &nbsp;', $code);
+ $code = str_replace("\n ", "\n&nbsp;", $code);
+
+ // keep space at the beginning
+ if (!empty($code) && $code[0] == ' ')
+ {
+ $code = '&nbsp;' . substr($code, 1);
+ }
// remove newline at the beginning
if (!empty($code) && $code[0] == "\n")
diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php
index 50e308dea2..d23323a5b1 100644
--- a/phpBB/includes/db/db_tools.php
+++ b/phpBB/includes/db/db_tools.php
@@ -2059,7 +2059,7 @@ class phpbb_db_tools
$table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
{
- $max_length = $table_prefix + 24;
+ $max_length = strlen($table_prefix) + 24;
trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
}
@@ -2096,7 +2096,7 @@ class phpbb_db_tools
$table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
{
- $max_length = $table_prefix + 24;
+ $max_length = strlen($table_prefix) + 24;
trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
}
diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php
index 2f9619c8ea..9b45c085a2 100644
--- a/phpBB/includes/db/dbal.php
+++ b/phpBB/includes/db/dbal.php
@@ -777,7 +777,7 @@ class dbal
</div>
</div>
<div id="page-footer">
- Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
</div>
</div>
</body>
diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php
index dcf8727e18..46c2f9210b 100644
--- a/phpBB/includes/db/mysqli.php
+++ b/phpBB/includes/db/mysqli.php
@@ -43,7 +43,23 @@ class dbal_mysqli extends dbal
$this->dbname = $database;
$port = (!$port) ? NULL : $port;
- $this->db_connect_id = @mysqli_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port);
+ // If port is set and it is not numeric, most likely mysqli socket is set.
+ // Try to map it to the $socket parameter.
+ $socket = NULL;
+ if ($port)
+ {
+ if (is_numeric($port))
+ {
+ $port = (int) $port;
+ }
+ else
+ {
+ $socket = $port;
+ $port = NULL;
+ }
+ }
+
+ $this->db_connect_id = @mysqli_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket);
if ($this->db_connect_id && $this->dbname != '')
{
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index d05cccc440..df49bdf637 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -266,6 +266,27 @@ function phpbb_mt_rand($min, $max)
}
/**
+* Wrapper for getdate() which returns the equivalent array for UTC timestamps.
+*
+* @param int $time Unix timestamp (optional)
+*
+* @return array Returns an associative array of information related to the timestamp.
+* See http://www.php.net/manual/en/function.getdate.php
+*/
+function phpbb_gmgetdate($time = false)
+{
+ if ($time === false)
+ {
+ $time = time();
+ }
+
+ // getdate() interprets timestamps in local time.
+ // What follows uses the fact that getdate() and
+ // date('Z') balance each other out.
+ return getdate($time - date('Z'));
+}
+
+/**
* Return formatted string for filesizes
*
* @param int $value filesize in bytes
@@ -599,6 +620,34 @@ function phpbb_email_hash($email)
}
/**
+* Wrapper for version_compare() that allows using uppercase A and B
+* for alpha and beta releases.
+*
+* See http://www.php.net/manual/en/function.version-compare.php
+*
+* @param string $version1 First version number
+* @param string $version2 Second version number
+* @param string $operator Comparison operator (optional)
+*
+* @return mixed Boolean (true, false) if comparison operator is specified.
+* Integer (-1, 0, 1) otherwise.
+*/
+function phpbb_version_compare($version1, $version2, $operator = null)
+{
+ $version1 = strtolower($version1);
+ $version2 = strtolower($version2);
+
+ if (is_null($operator))
+ {
+ return version_compare($version1, $version2);
+ }
+ else
+ {
+ return version_compare($version1, $version2, $operator);
+ }
+}
+
+/**
* 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.
@@ -2659,12 +2708,6 @@ function send_status_line($code, $message)
{
$version = $_SERVER['SERVER_PROTOCOL'];
}
- else if (!empty($_SERVER['HTTP_VERSION']))
- {
- // I cannot remember where I got this from.
- // This code path may never be reachable in reality.
- $version = $_SERVER['HTTP_VERSION'];
- }
else
{
$version = 'HTTP/1.0';
@@ -3686,10 +3729,19 @@ function phpbb_checkdnsrr($host, $type = 'MX')
{
return true;
}
+ break;
default:
- case 'A':
case 'AAAA':
+ // AAAA records returned by nslookup on Windows XP/2003 have this format.
+ // Later Windows versions use the A record format below for AAAA records.
+ if (stripos($line, "$host AAAA IPv6 address") === 0)
+ {
+ return true;
+ }
+ // No break
+
+ case 'A':
if (!empty($host_matches))
{
// Second line
@@ -3851,7 +3903,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
echo ' </div>';
echo ' </div>';
echo ' <div id="page-footer">';
- echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group';
+ echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group';
echo ' </div>';
echo '</div>';
echo '</body>';
@@ -4589,6 +4641,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
header('Expires: 0');
header('Pragma: no-cache');
+ if (!empty($user->data['is_bot']))
+ {
+ // Let reverse proxies know we detected a bot.
+ header('X-PHPBB-IS-BOT: yes');
+ }
+
return;
}
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index cb0cf34e69..f7e19f3e7d 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -2595,6 +2595,31 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
$sql_keywords .= 'LOWER(l.log_data) ' . implode(' OR LOWER(l.log_data) ', $keywords) . ')';
}
+ if ($log_count !== false)
+ {
+ $sql = 'SELECT COUNT(l.log_id) AS total_entries
+ FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u
+ WHERE l.log_type = $log_type
+ AND l.user_id = u.user_id
+ AND l.log_time >= $limit_days
+ $sql_keywords
+ $sql_forum";
+ $result = $db->sql_query($sql);
+ $log_count = (int) $db->sql_fetchfield('total_entries');
+ $db->sql_freeresult($result);
+ }
+
+ if ($log_count == 0)
+ {
+ // Save the queries, because there are no logs to display
+ return 0;
+ }
+
+ if ($offset >= $log_count)
+ {
+ $offset = ($offset - $limit < 0) ? 0 : $offset - $limit;
+ }
+
$sql = "SELECT l.*, u.username, u.username_clean, u.user_colour
FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u
WHERE l.log_type = $log_type
@@ -2762,21 +2787,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
}
}
- if ($log_count !== false)
- {
- $sql = 'SELECT COUNT(l.log_id) AS total_entries
- FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u
- WHERE l.log_type = $log_type
- AND l.user_id = u.user_id
- AND l.log_time >= $limit_days
- $sql_keywords
- $sql_forum";
- $result = $db->sql_query($sql);
- $log_count = (int) $db->sql_fetchfield('total_entries');
- $db->sql_freeresult($result);
- }
-
- return;
+ return $offset;
}
/**
@@ -2908,6 +2919,12 @@ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $li
$user_count = (int) $db->sql_fetchfield('user_count');
$db->sql_freeresult($result);
+ if ($user_count == 0)
+ {
+ // Save the queries, because there are no users to display
+ return 0;
+ }
+
if ($offset >= $user_count)
{
$offset = ($offset - $limit < 0) ? 0 : $offset - $limit;
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index faff9dd0de..b7650ecd6a 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -1107,7 +1107,7 @@ function extension_allowed($forum_id, $extension, &$extensions)
* @param int $max_length Maximum length of string (multibyte character count as 1 char / Html entity count as 1 char)
* @param int $max_store_length Maximum character length of string (multibyte character count as 1 char / Html entity count as entity chars).
* @param bool $allow_reply Allow Re: in front of string
-* NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_legnth) and is deprecated.
+* NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_length) and is deprecated.
* @param string $append String to be appended
*/
function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = false, $append = '')
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index d7422aa2c9..14d0c44dcf 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -51,6 +51,27 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$sql_where = 'left_id > ' . $root_data['left_id'] . ' AND left_id < ' . $root_data['right_id'];
}
+ // Handle marking everything read
+ if ($mark_read == 'all')
+ {
+ $redirect = build_url(array('mark', 'hash'));
+ meta_refresh(3, $redirect);
+
+ if (check_link_hash(request_var('hash', ''), 'global'))
+ {
+ markread('all');
+
+ trigger_error(
+ $user->lang['FORUMS_MARKED'] . '<br /><br />' .
+ sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>')
+ );
+ }
+ else
+ {
+ trigger_error(sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'));
+ }
+ }
+
// Display list of active topics for this category?
$show_active = (isset($root_data['forum_flags']) && ($root_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false;
@@ -120,13 +141,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_id = $row['forum_id'];
// Mark forums read?
- if ($mark_read == 'forums' || $mark_read == 'all')
+ if ($mark_read == 'forums')
{
if ($auth->acl_get('f_list', $forum_id))
{
$forum_ids[] = $forum_id;
- continue;
}
+
+ continue;
}
// Category with no members
@@ -152,8 +174,6 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
continue;
}
- $forum_ids[] = $forum_id;
-
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
$forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark'];
@@ -255,24 +275,16 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$db->sql_freeresult($result);
// Handle marking posts
- if ($mark_read == 'forums' || $mark_read == 'all')
+ if ($mark_read == 'forums')
{
$redirect = build_url(array('mark', 'hash'));
$token = request_var('hash', '');
if (check_link_hash($token, 'global'))
{
- if ($mark_read == 'all')
- {
- markread('all');
- $message = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>');
- }
- else
- {
- // Add 0 to forums array to mark global announcements correctly
- $forum_ids[] = 0;
- markread('topics', $forum_ids);
- $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
- }
+ // Add 0 to forums array to mark global announcements correctly
+ $forum_ids[] = 0;
+ markread('topics', $forum_ids);
+ $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
meta_refresh(3, $redirect);
trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message);
}
@@ -996,13 +1008,17 @@ function display_user_activity(&$userdata)
}
// Obtain active topic
+ // We need to exclude passworded forums here so we do not leak the topic title
+ $forum_ary_topic = array_unique(array_merge($forum_ary, $user->get_passworded_forums()));
+ $forum_sql_topic = (!empty($forum_ary_topic)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary_topic, true) : '';
+
$sql = 'SELECT topic_id, COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . '
WHERE poster_id = ' . $userdata['user_id'] . "
AND post_postcount = 1
AND (post_approved = 1
$sql_m_approve)
- $forum_sql
+ $forum_sql_topic
GROUP BY topic_id
ORDER BY num_posts DESC";
$result = $db->sql_query_limit($sql, 1);
@@ -1058,7 +1074,7 @@ function display_user_activity(&$userdata)
/**
* Topic and forum watching common code
*/
-function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $notify_status = 'unset', $start = 0)
+function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $notify_status = 'unset', $start = 0, $item_title = '')
{
global $template, $db, $user, $phpEx, $start, $phpbb_root_path;
@@ -1091,28 +1107,43 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
if (isset($_GET['unwatch']))
{
$uid = request_var('uid', 0);
- if ($uid != $user_id)
- {
- $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
- $message = $user->lang['ERR_UNWATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
- trigger_error($message);
- }
- if ($_GET['unwatch'] == $mode)
+ $token = request_var('hash', '');
+
+ if (($token && check_link_hash($token, "{$mode}_$match_id")) || confirm_box(true))
{
- $is_watching = 0;
+ if (($uid != $user_id) || ($_GET['unwatch'] != $mode))
+ {
+ $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
+ $message = $user->lang['ERR_UNWATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
+ trigger_error($message);
+ }
$sql = 'DELETE FROM ' . $table_sql . "
WHERE $where_sql = $match_id
AND user_id = $user_id";
$db->sql_query($sql);
- }
-
- $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
- meta_refresh(3, $redirect_url);
+ $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
+ $message = $user->lang['NOT_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
+ meta_refresh(3, $redirect_url);
+ trigger_error($message);
+ }
+ else
+ {
+ $s_hidden_fields = array(
+ 'uid' => $user->data['user_id'],
+ 'unwatch' => $mode,
+ 'start' => $start,
+ 'f' => $forum_id,
+ );
+ if ($mode != 'forum')
+ {
+ $s_hidden_fields['t'] = $topic_id;
+ }
- $message = $user->lang['NOT_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
- trigger_error($message);
+ $confirm_box_message = (($item_title == '') ? 'UNWATCH_' . strtoupper($mode) : $user->lang('UNWATCH_' . strtoupper($mode) . '_DETAILED', $item_title));
+ confirm_box(false, $confirm_box_message, build_hidden_fields($s_hidden_fields));
+ }
}
else
{
@@ -1132,26 +1163,45 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
{
if (isset($_GET['watch']))
{
+ $uid = request_var('uid', 0);
$token = request_var('hash', '');
- $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
- if ($_GET['watch'] == $mode && check_link_hash($token, "{$mode}_$match_id"))
+ if (($token && check_link_hash($token, "{$mode}_$match_id")) || confirm_box(true))
{
+ if (($uid != $user_id) || ($_GET['watch'] != $mode))
+ {
+ $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
+ $message = $user->lang['ERR_WATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
+ trigger_error($message);
+ }
+
$is_watching = true;
$sql = 'INSERT INTO ' . $table_sql . " (user_id, $where_sql, notify_status)
VALUES ($user_id, $match_id, " . NOTIFY_YES . ')';
$db->sql_query($sql);
+
+ $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;start=$start");
$message = $user->lang['ARE_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
+ meta_refresh(3, $redirect_url);
+ trigger_error($message);
}
else
{
- $message = $user->lang['ERR_WATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>');
- }
-
- meta_refresh(3, $redirect_url);
+ $s_hidden_fields = array(
+ 'uid' => $user->data['user_id'],
+ 'watch' => $mode,
+ 'start' => $start,
+ 'f' => $forum_id,
+ );
+ if ($mode != 'forum')
+ {
+ $s_hidden_fields['t'] = $topic_id;
+ }
- trigger_error($message);
+ $confirm_box_message = (($item_title == '') ? 'WATCH_' . strtoupper($mode) : $user->lang('WATCH_' . strtoupper($mode) . '_DETAILED', $item_title));
+ confirm_box(false, $confirm_box_message, build_hidden_fields($s_hidden_fields));
+ }
}
else
{
@@ -1161,7 +1211,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
}
else
{
- if (isset($_GET['unwatch']) && $_GET['unwatch'] == $mode)
+ if ((isset($_GET['unwatch']) && $_GET['unwatch'] == $mode) || (isset($_GET['watch']) && $_GET['watch'] == $mode))
{
login_box();
}
diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php
index 046abede8e..5ab7a87efd 100644
--- a/phpBB/includes/functions_transfer.php
+++ b/phpBB/includes/functions_transfer.php
@@ -808,23 +808,56 @@ class ftp_fsock extends transfer
*/
function _open_data_connection()
{
- $this->_send_command('PASV', '', false);
-
- if (!$ip_port = $this->_check_command(true))
+ // Try to find out whether we have a IPv4 or IPv6 (control) connection
+ if (function_exists('stream_socket_get_name'))
{
- return false;
+ $socket_name = stream_socket_get_name($this->connection, true);
+ $server_ip = substr($socket_name, 0, strrpos($socket_name, ':'));
}
- // open the connection to start sending the file
- if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp))
+ if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip))
{
- // bad ip and port
- return false;
+ // Passive mode
+ $this->_send_command('PASV', '', false);
+
+ if (!$ip_port = $this->_check_command(true))
+ {
+ return false;
+ }
+
+ // open the connection to start sending the file
+ if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp))
+ {
+ // bad ip and port
+ return false;
+ }
+
+ $temp = explode(',', $temp[0]);
+ $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
+ $server_port = $temp[4] * 256 + $temp[5];
+ }
+ else
+ {
+ // Extended Passive Mode - RFC2428
+ $this->_send_command('EPSV', '', false);
+
+ if (!$epsv_response = $this->_check_command(true))
+ {
+ return false;
+ }
+
+ // Response looks like "229 Entering Extended Passive Mode (|||12345|)"
+ // where 12345 is the tcp port for the data connection
+ if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match))
+ {
+ return false;
+ }
+ $server_port = (int) $match[1];
+
+ // fsockopen expects IPv6 address in square brackets
+ $server_ip = "[$server_ip]";
}
- $temp = explode(',', $temp[0]);
- $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
- $server_port = $temp[4] * 256 + $temp[5];
$errno = 0;
$errstr = '';
diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php
index 6da810a489..73ff72c177 100644
--- a/phpBB/includes/mcp/mcp_logs.php
+++ b/phpBB/includes/mcp/mcp_logs.php
@@ -170,7 +170,7 @@ class mcp_logs
// Grab log data
$log_data = array();
$log_count = 0;
- view_log('mod', $log_data, $log_count, $config['topics_per_page'], $start, $forum_list, $topic_id, 0, $sql_where, $sql_sort, $keywords);
+ $start = view_log('mod', $log_data, $log_count, $config['topics_per_page'], $start, $forum_list, $topic_id, 0, $sql_where, $sql_sort, $keywords);
$template->assign_vars(array(
'PAGE_NUMBER' => on_page($log_count, $config['topics_per_page'], $start),
@@ -179,7 +179,7 @@ class mcp_logs
'L_TITLE' => $user->lang['MCP_LOGS'],
- 'U_POST_ACTION' => $this->u_action,
+ 'U_POST_ACTION' => $this->u_action . "&amp;$u_sort_param$keywords_param&amp;start=$start",
'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false,
'S_SELECT_SORT_DIR' => $s_sort_dir,
'S_SELECT_SORT_KEY' => $s_sort_key,
diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php
index c684eb6f52..02a89c0251 100644
--- a/phpBB/includes/mcp/mcp_notes.php
+++ b/phpBB/includes/mcp/mcp_notes.php
@@ -198,7 +198,7 @@ class mcp_notes
$log_data = array();
$log_count = 0;
- view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort, $keywords);
+ $start = view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort, $keywords);
if ($log_count)
{
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 7ef6e02a8d..caadcbafaa 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -2272,9 +2272,44 @@ class user extends session
// Use URL if told so
$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
- $img_data['src'] = $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'];
+ $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['src'] = $root_path . $path;
$img_data['width'] = $this->img_array[$img]['image_width'];
$img_data['height'] = $this->img_array[$img]['image_height'];
+
+ // We overwrite the width and height to the phpbb logo's width
+ // and height here if the contents of the site_logo file are
+ // really equal to the phpbb_logo
+ // This allows us to change the dimensions of the phpbb_logo without
+ // modifying the imageset.cfg and causing a conflict for everyone
+ // who modified it for their custom logo on updating
+ if ($img == 'site_logo' && file_exists($phpbb_root_path . $path))
+ {
+ global $cache;
+
+ $img_file_hashes = $cache->get('imageset_site_logo_md5');
+
+ if ($img_file_hashes === false)
+ {
+ $img_file_hashes = array();
+ }
+
+ $key = $this->theme['imageset_path'] . '::' . $this->img_array[$img]['image_lang'];
+ if (!isset($img_file_hashes[$key]))
+ {
+ $img_file_hashes[$key] = md5(file_get_contents($phpbb_root_path . $path));
+ $cache->put('imageset_site_logo_md5', $img_file_hashes);
+ }
+
+ $phpbb_logo_hash = '0c461a32cd3621643105f0d02a772c10';
+
+ if ($phpbb_logo_hash == $img_file_hashes[$key])
+ {
+ $img_data['width'] = '149';
+ $img_data['height'] = '52';
+ }
+ }
}
$alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;
@@ -2375,6 +2410,39 @@ class user extends session
return true;
}
+
+ /**
+ * Returns all password protected forum ids the user is currently NOT authenticated for.
+ *
+ * @return array Array of forum ids
+ * @access public
+ */
+ function get_passworded_forums()
+ {
+ global $db;
+
+ $sql = 'SELECT f.forum_id, fa.user_id
+ FROM ' . FORUMS_TABLE . ' f
+ LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa
+ ON (fa.forum_id = f.forum_id
+ AND fa.session_id = '" . $db->sql_escape($this->session_id) . "')
+ WHERE f.forum_password <> ''";
+ $result = $db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $forum_id = (int) $row['forum_id'];
+
+ if ($row['user_id'] != $this->data['user_id'])
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ return $forum_ids;
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/index.php b/phpBB/index.php
index cc83641acd..c3f7c871d3 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -83,13 +83,21 @@ $legend = implode(', ', $legend);
$birthday_list = '';
if ($config['load_birthdays'] && $config['allow_birthdays'])
{
- $now = getdate(time() + $user->timezone + $user->dst - date('Z'));
+ $now = phpbb_gmgetdate(time() + $user->timezone + $user->dst);
+
+ // Display birthdays of 29th february on 28th february in non-leap-years
+ $leap_year_birthdays = '';
+ if ($now['mday'] == 28 && $now['mon'] == 2 && !$user->format_date(time(), 'L'))
+ {
+ $leap_year_birthdays = " OR user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', 29, 2)) . "%'";
+ }
+
$sql = 'SELECT u.user_id, u.username, u.user_colour, u.user_birthday
FROM ' . USERS_TABLE . ' u
LEFT JOIN ' . BANLIST_TABLE . " b ON (u.user_id = b.ban_userid)
WHERE (b.ban_id IS NULL
OR b.ban_exclude = 1)
- AND u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%'
+ AND (u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%' $leap_year_birthdays)
AND u.user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')';
$result = $db->sql_query($sql);
@@ -99,7 +107,7 @@ if ($config['load_birthdays'] && $config['allow_birthdays'])
if ($age = (int) substr($row['user_birthday'], -4))
{
- $birthday_list .= ' (' . ($now['year'] - $age) . ')';
+ $birthday_list .= ' (' . max(0, $now['year'] - $age) . ')';
}
}
$db->sql_freeresult($result);
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index fe2946501f..a167e79308 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -99,6 +99,8 @@ require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
+phpbb_require_updated('includes/db/db_tools.' . $phpEx);
+
// new table constants are separately defined here in case the updater is run
// before the files are updated
if (!defined('LOGIN_ATTEMPT_TABLE'))
@@ -178,9 +180,9 @@ while ($row = $db->sql_fetchrow($result))
}
$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);
+// phpbb_db_tools will be taken from new files (under install/update/new)
+// if possible, falling back to the board's copy.
+$db_tools = new phpbb_db_tools($db, true);
$database_update_info = database_update_info();
@@ -525,7 +527,7 @@ function _print_footer()
</div>
<div id="page-footer">
- Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
</div>
</div>
@@ -960,7 +962,7 @@ function database_update_info()
'username' => array('VCHAR_UNI:255', 0),
'username_clean' => array('VCHAR_CI', 0),
),
- 'PRIMARY_KEY' => 'attempt_id',
+ //'PRIMARY_KEY' => 'attempt_id',
'KEYS' => array(
'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')),
'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')),
@@ -979,8 +981,10 @@ function database_update_info()
'3.0.9-RC1' => array(),
// No changes from 3.0.9-RC2 to 3.0.9-RC3
'3.0.9-RC2' => array(),
- // No changes from 3.0.9-RC3 to 3.0.9
+ // No changes from 3.0.9-RC3 to 3.0.9-RC4
'3.0.9-RC3' => array(),
+ // No changes from 3.0.9-RC4 to 3.0.9
+ '3.0.9-RC4' => array(),
/** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.10-RC1 */
);
@@ -1983,2248 +1987,13 @@ function change_database_data(&$no_updates, $version)
case '3.0.9-RC2':
break;
- // No changes from 3.0.9-RC3 to 3.0.9
+ // No changes from 3.0.9-RC3 to 3.0.9-RC4
case '3.0.9-RC3':
break;
- }
-}
-
-
-/**
-* Database Tools for handling cross-db actions such as altering columns, etc.
-* Currently not supported is returning SQL for creating tables.
-*
-* @package dbal
-*/
-class updater_db_tools
-{
- /**
- * Current sql layer
- */
- var $sql_layer = '';
-
- /**
- * @var object DB object
- */
- var $db = NULL;
-
- /**
- * The Column types for every database we support
- * @var array
- */
- var $dbms_type_map = array(
- '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)',
- ),
-
- 'mssqlnative' => array(
- 'INT:' => '[int]',
- 'BINT' => '[float]',
- 'UINT' => '[int]',
- 'UINT:' => '[int]',
- 'TINT:' => '[int]',
- 'USINT' => '[int]',
- 'BOOL' => '[int]',
- 'VCHAR' => '[varchar] (255)',
- 'VCHAR:' => '[varchar] (%d)',
- 'CHAR:' => '[char] (%d)',
- 'XSTEXT' => '[varchar] (1000)',
- 'STEXT' => '[varchar] (3000)',
- 'TEXT' => '[varchar] (8000)',
- 'MTEXT' => '[text]',
- 'XSTEXT_UNI'=> '[varchar] (100)',
- 'STEXT_UNI' => '[varchar] (255)',
- 'TEXT_UNI' => '[varchar] (4000)',
- 'MTEXT_UNI' => '[text]',
- 'TIMESTAMP' => '[int]',
- 'DECIMAL' => '[float]',
- 'DECIMAL:' => '[float]',
- 'PDECIMAL' => '[float]',
- 'PDECIMAL:' => '[float]',
- 'VCHAR_UNI' => '[varchar] (255)',
- 'VCHAR_UNI:'=> '[varchar] (%d)',
- 'VCHAR_CI' => '[varchar] (255)',
- 'VARBINARY' => '[varchar] (255)',
- ),
-
- 'oracle' => array(
- 'INT:' => 'number(%d)',
- 'BINT' => 'number(20)',
- 'UINT' => 'number(8)',
- 'UINT:' => 'number(%d)',
- 'TINT:' => 'number(%d)',
- 'USINT' => 'number(4)',
- 'BOOL' => 'number(1)',
- 'VCHAR' => 'varchar2(255)',
- 'VCHAR:' => 'varchar2(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'varchar2(1000)',
- 'STEXT' => 'varchar2(3000)',
- 'TEXT' => 'clob',
- 'MTEXT' => 'clob',
- 'XSTEXT_UNI'=> 'varchar2(300)',
- 'STEXT_UNI' => 'varchar2(765)',
- 'TEXT_UNI' => 'clob',
- 'MTEXT_UNI' => 'clob',
- 'TIMESTAMP' => 'number(11)',
- 'DECIMAL' => 'number(5, 2)',
- 'DECIMAL:' => 'number(%d, 2)',
- 'PDECIMAL' => 'number(6, 3)',
- 'PDECIMAL:' => 'number(%d, 3)',
- 'VCHAR_UNI' => 'varchar2(765)',
- 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
- 'VCHAR_CI' => 'varchar2(255)',
- 'VARBINARY' => 'raw(255)',
- ),
-
- 'sqlite' => array(
- 'INT:' => 'int(%d)',
- 'BINT' => 'bigint(20)',
- 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED',
- 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED',
- 'TINT:' => 'tinyint(%d)',
- 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED',
- 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED',
- 'VCHAR' => 'varchar(255)',
- 'VCHAR:' => 'varchar(%d)',
- 'CHAR:' => 'char(%d)',
- 'XSTEXT' => 'text(65535)',
- 'STEXT' => 'text(65535)',
- 'TEXT' => 'text(65535)',
- 'MTEXT' => 'mediumtext(16777215)',
- 'XSTEXT_UNI'=> 'text(65535)',
- 'STEXT_UNI' => 'text(65535)',
- 'TEXT_UNI' => 'text(65535)',
- 'MTEXT_UNI' => 'mediumtext(16777215)',
- 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
- 'DECIMAL' => 'decimal(5,2)',
- 'DECIMAL:' => 'decimal(%d,2)',
- 'PDECIMAL' => 'decimal(6,3)',
- 'PDECIMAL:' => 'decimal(%d,3)',
- 'VCHAR_UNI' => 'varchar(255)',
- 'VCHAR_UNI:'=> 'varchar(%d)',
- 'VCHAR_CI' => 'varchar(255)',
- 'VARBINARY' => 'blob',
- ),
-
- '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', 'mssqlnative', '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)
- {
- $this->db = $db;
- $this->return_statements = $return_statements;
-
- // Determine mapping database type
- switch ($this->db->sql_layer)
- {
- case 'mysql':
- $this->sql_layer = 'mysql_40';
- break;
-
- case 'mysql4':
- if (version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
- {
- $this->sql_layer = 'mysql_41';
- }
- else
- {
- $this->sql_layer = 'mysql_40';
- }
- break;
-
- case 'mysqli':
- $this->sql_layer = 'mysql_41';
- break;
-
- case 'mssql':
- case 'mssql_odbc':
- $this->sql_layer = 'mssql';
- break;
-
- case 'mssqlnative':
- $this->sql_layer = 'mssqlnative';
- break;
-
- default:
- $this->sql_layer = $this->db->sql_layer;
- break;
- }
- }
-
- /**
- * Check if table exists
- *
- *
- * @param string $table_name The table name to check for
- * @return bool true if table exists, else false
- */
- function sql_table_exists($table_name)
- {
- $this->db->sql_return_on_error(true);
- $result = $this->db->sql_query_limit('SELECT * FROM ' . $table_name, 1);
- $this->db->sql_return_on_error(false);
-
- if ($result)
- {
- $this->db->sql_freeresult($result);
- return true;
- }
-
- return false;
- }
-
- /**
- * Create SQL Table
- *
- * @param string $table_name The table name to create
- * @param array $table_data Array containing table data.
- * @return array Statements if $return_statements is true.
- */
- function sql_create_table($table_name, $table_data)
- {
- // holds the DDL for a column
- $columns = $statements = array();
-
- if ($this->sql_table_exists($table_name))
- {
- return $this->_sql_run_sql($statements);
- }
-
- // Begin transaction
- $statements[] = 'begin';
-
- // Determine if we have created a PRIMARY KEY in the earliest
- $primary_key_gen = false;
-
- // Determine if the table 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':
- case 'mssqlnative':
- $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);
-
- if (isset($prepared_column['auto_increment']) && strlen($column_name) > 26) // "${column_name}_gen"
- {
- trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
- }
-
- // here we add the definition of the new column to the list of columns
- switch ($this->sql_layer)
- {
- case 'mssql':
- case 'mssqlnative':
- $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default'];
- break;
-
- default:
- $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
- break;
- }
-
- // see if we have found a primary key set due to a column definition if we have found it, we can stop looking
- if (!$primary_key_gen)
- {
- $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
- }
-
- // create 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':
- case 'mssqlnative':
- $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':
- case 'mssqlnative':
- // We need the data here
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']);
- foreach ($primary_key_stmts as $pk_stmt)
- {
- $statements[] = $pk_stmt;
- }
-
- $this->return_statements = $old_return_statements;
- break;
-
- case 'oracle':
- $table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
- break;
- }
- }
- }
-
- // close the table
- switch ($this->sql_layer)
- {
- case 'mysql_41':
- // make sure the table is in UTF-8 mode
- $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;";
- $statements[] = $table_sql;
- break;
-
- case 'mysql_40':
- case 'sqlite':
- $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 GENERATOR {$table_name}_gen;";
- $statements[] = "SET GENERATOR {$table_name}_gen TO 0;";
-
- $trigger = "CREATE TRIGGER t_$table_name FOR $table_name\n";
- $trigger .= "BEFORE INSERT\nAS\nBEGIN\n";
- $trigger .= "\tNEW.{$create_sequence} = GEN_ID({$table_name}_gen, 1);\nEND;";
- $statements[] = $trigger;
- }
- break;
- }
-
- // Write Keys
- if (isset($table_data['KEYS']))
- {
- foreach ($table_data['KEYS'] as $key_name => $key_data)
- {
- if (!is_array($key_data[1]))
- {
- $key_data[1] = array($key_data[1]);
- }
-
- $old_return_statements = $this->return_statements;
- $this->return_statements = true;
-
- $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
-
- foreach ($key_stmts as $key_stmt)
- {
- $statements[] = $key_stmt;
- }
-
- $this->return_statements = $old_return_statements;
- }
- }
-
- // Commit Transaction
- $statements[] = 'commit';
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Handle passed database update array.
- * Expected structure...
- * Key being one of the following
- * change_columns: Column changes (only type, not name)
- * add_columns: Add columns to a table
- * drop_keys: Dropping keys
- * drop_columns: Removing/Dropping columns
- * add_primary_keys: adding primary keys
- * add_unique_index: adding an unique index
- * add_index: adding an index (can be column:index_size if you need to provide size)
- *
- * The values are in this format:
- * {TABLE NAME} => array(
- * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}),
- * {KEY/INDEX NAME} => array({COLUMN NAMES}),
- * )
- *
- * For more information have a look at /develop/create_schema_files.php (only available through SVN)
- */
- function perform_schema_changes($schema_changes)
- {
- if (empty($schema_changes))
- {
- return;
- }
-
- $statements = array();
- $sqlite = false;
-
- // For SQLite we need to perform the schema changes in a much more different way
- if ($this->db->sql_layer == 'sqlite' && $this->return_statements)
- {
- $sqlite_data = array();
- $sqlite = true;
- }
-
- // Add tables?
- if (!empty($schema_changes['add_tables']))
- {
- foreach ($schema_changes['add_tables'] as $table => $table_data)
- {
- $result = $this->sql_create_table($table, $table_data);
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
-
- // Change columns?
- if (!empty($schema_changes['change_columns']))
- {
- foreach ($schema_changes['change_columns'] as $table => $columns)
- {
- foreach ($columns as $column_name => $column_data)
- {
- // If the column exists we change it, else we add it ;)
- if ($column_exists = $this->sql_column_exists($table, $column_name))
- {
- $result = $this->sql_column_change($table, $column_name, $column_data, true);
- }
- else
- {
- $result = $this->sql_column_add($table, $column_name, $column_data, true);
- }
-
- if ($sqlite)
- {
- if ($column_exists)
- {
- $sqlite_data[$table]['change_columns'][] = $result;
- }
- else
- {
- $sqlite_data[$table]['add_columns'][] = $result;
- }
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Add columns?
- if (!empty($schema_changes['add_columns']))
- {
- foreach ($schema_changes['add_columns'] as $table => $columns)
- {
- foreach ($columns as $column_name => $column_data)
- {
- // Only add the column if it does not exist yet
- if ($column_exists = $this->sql_column_exists($table, $column_name))
- {
- continue;
- // This is commented out here because it can take tremendous time on updates
-// $result = $this->sql_column_change($table, $column_name, $column_data, true);
- }
- else
- {
- $result = $this->sql_column_add($table, $column_name, $column_data, true);
- }
-
- if ($sqlite)
- {
- if ($column_exists)
- {
- continue;
-// $sqlite_data[$table]['change_columns'][] = $result;
- }
- else
- {
- $sqlite_data[$table]['add_columns'][] = $result;
- }
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Remove keys?
- if (!empty($schema_changes['drop_keys']))
- {
- foreach ($schema_changes['drop_keys'] as $table => $indexes)
- {
- foreach ($indexes as $index_name)
- {
- if (!$this->sql_index_exists($table, $index_name))
- {
- continue;
- }
-
- $result = $this->sql_index_drop($table, $index_name);
-
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Drop columns?
- if (!empty($schema_changes['drop_columns']))
- {
- foreach ($schema_changes['drop_columns'] as $table => $columns)
- {
- foreach ($columns as $column)
- {
- // Only remove the column if it exists...
- if ($this->sql_column_exists($table, $column))
- {
- $result = $this->sql_column_remove($table, $column, true);
-
- if ($sqlite)
- {
- $sqlite_data[$table]['drop_columns'][] = $result;
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
- }
-
- // Add primary keys?
- if (!empty($schema_changes['add_primary_keys']))
- {
- foreach ($schema_changes['add_primary_keys'] as $table => $columns)
- {
- $result = $this->sql_create_primary_key($table, $columns, true);
-
- if ($sqlite)
- {
- $sqlite_data[$table]['primary_key'] = $result;
- }
- else if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
-
- // Add 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)
- {
- if ($this->sql_unique_index_exists($table, $index_name))
- {
- continue;
- }
-
- $result = $this->sql_create_unique_index($table, $index_name, $column);
-
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- // Add indexes?
- if (!empty($schema_changes['add_index']))
- {
- foreach ($schema_changes['add_index'] as $table => $index_array)
- {
- foreach ($index_array as $index_name => $column)
- {
- if ($this->sql_index_exists($table, $index_name))
- {
- continue;
- }
-
- $result = $this->sql_create_index($table, $index_name, $column);
-
- if ($this->return_statements)
- {
- $statements = array_merge($statements, $result);
- }
- }
- }
- }
-
- if ($sqlite)
- {
- foreach ($sqlite_data as $table_name => $sql_schema_changes)
- {
- // Create temporary table with original data
- $statements[] = 'begin';
-
- $sql = "SELECT sql
- FROM sqlite_master
- WHERE type = 'table'
- AND name = '{$table_name}'
- ORDER BY type DESC, name;";
- $result = $this->db->sql_query($sql);
-
- if (!$result)
- {
- continue;
- }
-
- $row = $this->db->sql_fetchrow($result);
- $this->db->sql_freeresult($result);
-
- // Create a backup table and populate it, destroy the existing one
- $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']);
- $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
- $statements[] = 'DROP TABLE ' . $table_name;
-
- // Get the columns...
- preg_match('#\((.*)\)#s', $row['sql'], $matches);
-
- $plain_table_cols = trim($matches[1]);
- $new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols);
- $column_list = array();
-
- foreach ($new_table_cols as $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- continue;
- }
- $column_list[] = $entities[0];
- }
-
- // note down the primary key notation because sqlite only supports adding it to the end for the new table
- $primary_key = false;
- $_new_cols = array();
-
- foreach ($new_table_cols as $key => $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] == 'PRIMARY')
- {
- $primary_key = $declaration;
- continue;
- }
- $_new_cols[] = $declaration;
- }
-
- $new_table_cols = $_new_cols;
-
- // First of all... change columns
- if (!empty($sql_schema_changes['change_columns']))
- {
- foreach ($sql_schema_changes['change_columns'] as $column_sql)
- {
- foreach ($new_table_cols as $key => $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if (strpos($column_sql, $entities[0] . ' ') === 0)
- {
- $new_table_cols[$key] = $column_sql;
- }
- }
- }
- }
-
- if (!empty($sql_schema_changes['add_columns']))
- {
- foreach ($sql_schema_changes['add_columns'] as $column_sql)
- {
- $new_table_cols[] = $column_sql;
- }
- }
-
- // Now drop them...
- if (!empty($sql_schema_changes['drop_columns']))
- {
- foreach ($sql_schema_changes['drop_columns'] as $column_name)
- {
- // Remove from column list...
- $new_column_list = array();
- foreach ($column_list as $key => $value)
- {
- if ($value === $column_name)
- {
- continue;
- }
-
- $new_column_list[] = $value;
- }
-
- $column_list = $new_column_list;
-
- // Remove from table...
- $_new_cols = array();
- foreach ($new_table_cols as $key => $declaration)
- {
- $entities = preg_split('#\s+#', trim($declaration));
- if (strpos($column_name . ' ', $entities[0] . ' ') === 0)
- {
- continue;
- }
- $_new_cols[] = $declaration;
- }
- $new_table_cols = $_new_cols;
- }
- }
-
- // Primary key...
- if (!empty($sql_schema_changes['primary_key']))
- {
- $new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')';
- }
- // Add a new one or the old primary key
- else if ($primary_key !== false)
- {
- $new_table_cols[] = $primary_key;
- }
-
- $columns = implode(',', $column_list);
-
- // create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');';
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
- }
- }
-
- if ($this->return_statements)
- {
- return $statements;
- }
- }
-
- /**
- * 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':
- case 'mssqlnative':
- $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 LOWER(table_name) = '" . strtolower($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 = '" . strtoupper($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;
- }
- }
-
- /**
- * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes.
- *
- * @param string $table_name Table to check the index at
- * @param string $index_name The index name to check
- *
- * @return bool True if index exists, else false
- */
- function sql_index_exists($table_name, $index_name)
- {
- if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- if ($row['TYPE'] == 3)
- {
- if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- }
- $this->db->sql_freeresult($result);
-
- return false;
- }
-
- switch ($this->sql_layer)
- {
- case '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' || $this->sql_layer == 'mssqlnative')
- {
- $sql = "EXEC sp_statistics '$table_name'";
- $result = $this->db->sql_query($sql);
-
- while ($row = $this->db->sql_fetchrow($result))
- {
- // Usually NON_UNIQUE is the column we want to check, but we allow for both
- if ($row['TYPE'] == 3)
- {
- if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
- {
- $this->db->sql_freeresult($result);
- return true;
- }
- }
- }
- $this->db->sql_freeresult($result);
- return false;
- }
-
- switch ($this->sql_layer)
- {
- case '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'";
- $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'] || $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':
- // Two cases here... prefixed with U_[table_owner] and not prefixed with table_name
- if (strpos($row[$col], 'U_') === 0)
- {
- $row[$col] = substr($row[$col], strlen('U_' . $row['table_owner']) + 1);
- }
- else if (strpos($row[$col], strtoupper($table_name)) === 0)
- {
- $row[$col] = substr($row[$col], strlen($table_name) + 1);
- }
- break;
-
- case '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
- */
- function _sql_run_sql($statements)
- {
- if ($this->return_statements)
- {
- return $statements;
- }
-
- // We could add error handling here...
- foreach ($statements as $sql)
- {
- if ($sql === 'begin')
- {
- $this->db->sql_transaction('begin');
- }
- else if ($sql === 'commit')
- {
- $this->db->sql_transaction('commit');
- }
- else
- {
- $this->db->sql_query($sql);
- }
- }
-
- return true;
- }
-
- /**
- * Function to prepare some column information for better usage
- * @access private
- */
- function sql_prepare_column_data($table_name, $column_name, $column_data)
- {
- if (strlen($column_name) > 30)
- {
- trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
- }
-
- // Get type
- 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);
- }
- 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} ";
- $return_array['column_type_sql_type'] = " {$column_type} ";
-
- if (!is_null($column_data[1]))
- {
- $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
- $return_array['column_type_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':
- case 'mssqlnative':
- $sql .= " {$column_type} ";
- $sql_default = " {$column_type} ";
- // For adding columns we need the default definition
- if (!is_null($column_data[1]))
- {
- // For hexadecimal values do not use single quotes
- if (strpos($column_data[1], '0x') === 0)
- {
- $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') ';
- $sql_default .= $return_array['default'];
- }
- else
- {
- $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
- $sql_default .= $return_array['default'];
- }
- }
-
- if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
- {
-// $sql .= 'IDENTITY (1, 1) ';
- $sql_default .= 'IDENTITY (1, 1) ';
- }
-
- $return_array['textimage'] = $column_type === '[text]';
-
- $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, $inline = false)
- {
- $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'firebird':
- // Does not support AFTER statement, only POSITION (and there you need the column position)
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD "' . strtoupper($column_name) . '" ' . $column_data['column_type_sql'];
- break;
-
- case 'mssql':
- case 'mssqlnative':
- // Does not support AFTER, only through temporary table
- $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $after = (!empty($column_data['after'])) ? ' AFTER ' . $column_data['after'] : '';
- $statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'] . $after;
- break;
-
- case 'oracle':
- // Does not support AFTER, only through temporary table
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
- break;
-
- case 'postgres':
- // Does not support AFTER, only through temporary table
-
- if (version_compare($this->db->sql_server_info(true), '8.0', '>='))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
- }
- else
- {
- // old versions cannot add columns with default and null information
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint'];
-
- if (isset($column_data['null']))
- {
- if ($column_data['null'] == 'NOT NULL')
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL';
- }
- }
-
- if (isset($column_data['default']))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
- }
- }
- break;
-
- case 'sqlite':
-
- if ($inline && $this->return_statements)
- {
- return $column_name . ' ' . $column_data['column_type_sql'];
- }
-
- 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, $inline = false)
- {
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'firebird':
- $statements[] = 'ALTER TABLE ' . $table_name . ' DROP "' . strtoupper($column_name) . '"';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $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 ($inline && $this->return_statements)
- {
- return $column_name;
- }
-
- 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':
- case 'mssqlnative':
- $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name;
- break;
-
- case 'mysql_40':
- case 'mysql_41':
- $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
- break;
-
- case '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, $inline = false)
- {
- $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':
- case 'mssqlnative':
- $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
- $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
- $sql .= '[' . implode("],\n\t\t[", $column) . ']';
- $sql .= ') ON [PRIMARY]';
-
- $statements[] = $sql;
- break;
-
- case 'oracle':
- $statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
- break;
-
- case 'sqlite':
-
- if ($inline && $this->return_statements)
- {
- return $column;
- }
-
- $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);
-
- // create a new table and fill it up. destroy the temp one
- $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));';
- $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
- $statements[] = 'DROP TABLE ' . $table_name . '_temp';
-
- $statements[] = 'commit';
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Add unique index
- */
- function sql_create_unique_index($table_name, $index_name, $column)
- {
- $statements = array();
-
- $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
- if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
- {
- $max_length = $table_prefix + 24;
- trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
- }
-
- switch ($this->sql_layer)
- {
- case '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':
- $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
- break;
- }
-
- return $this->_sql_run_sql($statements);
- }
-
- /**
- * Add index
- */
- function sql_create_index($table_name, $index_name, $column)
- {
- $statements = array();
-
- $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config)
- if (strlen($table_name . $index_name) - strlen($table_prefix) > 24)
- {
- $max_length = $table_prefix + 24;
- trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR);
- }
-
- // remove index length unless MySQL4
- if ('mysql_40' != $this->sql_layer)
- {
- $column = preg_replace('#:.*$#', '', $column);
- }
-
- switch ($this->sql_layer)
- {
- case 'firebird':
- case 'postgres':
- case 'oracle':
- case 'sqlite':
- $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
- break;
-
- case 'mysql_40':
- // add index size to definition as required by MySQL4
- foreach ($column as $i => $col)
- {
- if (false !== strpos($col, ':'))
- {
- list($col, $index_size) = explode(':', $col);
- $column[$i] = "$col($index_size)";
- }
- }
- // no break
- case 'mysql_41':
- $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $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, $inline = false)
- {
- $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
- $statements = array();
-
- switch ($this->sql_layer)
- {
- case 'firebird':
- // Change type...
- if (!empty($column_data['column_type_sql_default']))
- {
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type'];
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" SET DEFAULT ' . ' ' . $column_data['column_type_sql_default'];
- }
- else
- {
- // TODO: try to change pkey without removing trigger, generator or constraints. ATM this query may fail.
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type'];
- }
- break;
-
- case 'mssql':
- case 'mssqlnative':
- $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':
- 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':
-
- if ($inline && $this->return_statements)
- {
- return $column_name . ' ' . $column_data['column_type_sql'];
- }
-
- $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 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);
-
- $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
- $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';
-
- $statements[] = 'commit';
-
- break;
- }
-
- return $this->_sql_run_sql($statements);
+ // No changes from 3.0.9-RC4 to 3.0.9
+ case '3.0.9-RC4':
+ break;
}
}
diff --git a/phpBB/install/index.php b/phpBB/install/index.php
index f534980389..5135e2dbd8 100644
--- a/phpBB/install/index.php
+++ b/phpBB/install/index.php
@@ -569,7 +569,7 @@ class module
echo ' </div>';
echo ' </div>';
echo ' <div id="page-footer">';
- echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group';
+ echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group';
echo ' </div>';
echo '</div>';
echo '</body>';
diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php
index 0254bff992..5a9ca6231d 100644
--- a/phpBB/language/en/acp/board.php
+++ b/phpBB/language/en/acp/board.php
@@ -53,7 +53,7 @@ $lang = array_merge($lang, array(
'SYSTEM_TIMEZONE' => 'Guest timezone',
'SYSTEM_TIMEZONE_EXPLAIN' => 'Timezone to use for displaying times to users who are not logged in (guests, bots). Logged in users set their timezone during registration and can change it in their user control panel.',
'WARNINGS_EXPIRE' => 'Warning duration',
- 'WARNINGS_EXPIRE_EXPLAIN' => 'Number of days that will elapse before the warning will automatically expire from a user’s record.',
+ 'WARNINGS_EXPIRE_EXPLAIN' => 'Number of days that will elapse before the warning will automatically expire from a user’s record. Set this value to 0 to make warnings permanent.',
));
// Board Features
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index 078a280223..1c96818346 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -652,6 +652,10 @@ $lang = array_merge($lang, array(
'UNREAD_PMS' => '<strong>%d</strong> unread messages',
'UNREAD_POST' => 'Unread post',
'UNREAD_POSTS' => 'Unread posts',
+ 'UNWATCH_FORUM_CONFIRM' => 'Are you sure you wish to unsubscribe from this forum?',
+ 'UNWATCH_FORUM_DETAILED' => 'Are you sure you wish to unsubscribe from the forum “%s”?',
+ 'UNWATCH_TOPIC_CONFIRM' => 'Are you sure you wish to unsubscribe from this topic?',
+ 'UNWATCH_TOPIC_DETAILED' => 'Are you sure you wish to unsubscribe from the topic “%s”?',
'UNWATCHED_FORUMS' => 'You are no longer subscribed to the selected forums.',
'UNWATCHED_TOPICS' => 'You are no longer subscribed to the selected topics.',
'UNWATCHED_FORUMS_TOPICS' => 'You are no longer subscribed to the selected entries.',
@@ -700,6 +704,10 @@ $lang = array_merge($lang, array(
'WARNINGS' => 'Warnings',
'WARN_USER' => 'Warn user',
+ 'WATCH_FORUM_CONFIRM' => 'Are you sure you wish to subscribe to this forum?',
+ 'WATCH_FORUM_DETAILED' => 'Are you sure you wish to subscribe to the forum “%s”?',
+ 'WATCH_TOPIC_CONFIRM' => 'Are you sure you wish to subscribe to this topic?',
+ 'WATCH_TOPIC_DETAILED' => 'Are you sure you wish to subscribe to the topic “%s”?',
'WELCOME_SUBJECT' => 'Welcome to %s forums',
'WEBSITE' => 'Website',
'WHOIS' => 'Whois',
diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php
index 37147cc6a0..befa7c6f40 100644
--- a/phpBB/language/en/install.php
+++ b/phpBB/language/en/install.php
@@ -494,7 +494,7 @@ $lang = array_merge($lang, array(
'SHOW_DIFF_NEW' => 'Show file contents',
'SHOW_DIFF_NEW_CONFLICT' => 'Show differences',
'SHOW_DIFF_NOT_MODIFIED' => 'Show differences',
- 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listing below.',
+ 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.',
'SQL' => 'SQL',
'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See <a href="../docs/README.html">README</a> for details on how to obtain advice.',
'STAGE_FILE_CHECK' => 'Check files',
diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php
index 8016a233fd..f8d265dddd 100644
--- a/phpBB/language/en/posting.php
+++ b/phpBB/language/en/posting.php
@@ -48,7 +48,7 @@ $lang = array_merge($lang, array(
'BBCODE_A_HELP' => 'Inline uploaded attachment: [attachment=]filename.ext[/attachment]',
'BBCODE_B_HELP' => 'Bold text: [b]text[/b]',
'BBCODE_C_HELP' => 'Code display: [code]code[/code]',
- 'BBCODE_E_HELP' => 'List: Add list element',
+ 'BBCODE_D_HELP' => 'Flash: [flash=width,height]http://url[/flash]',
'BBCODE_F_HELP' => 'Font size: [size=85]small text[/size]',
'BBCODE_IS_OFF' => '%sBBCode%s is <em>OFF</em>',
'BBCODE_IS_ON' => '%sBBCode%s is <em>ON</em>',
@@ -61,7 +61,7 @@ $lang = array_merge($lang, array(
'BBCODE_S_HELP' => 'Font colour: [color=red]text[/color] Tip: you can also use color=#FF0000',
'BBCODE_U_HELP' => 'Underline text: [u]text[/u]',
'BBCODE_W_HELP' => 'Insert URL: [url]http://url[/url] or [url=http://url]URL text[/url]',
- 'BBCODE_D_HELP' => 'Flash: [flash=width,height]http://url[/flash]',
+ 'BBCODE_Y_HELP' => 'List: Add list element',
'BUMP_ERROR' => 'You cannot bump this topic so soon after the last post.',
'CANNOT_DELETE_REPLIED' => 'Sorry but you may only delete posts which have not been replied to.',
diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php
index 589877305f..8169ee7a3e 100644
--- a/phpBB/memberlist.php
+++ b/phpBB/memberlist.php
@@ -1293,13 +1293,6 @@ switch ($mode)
$total_users = $config['num_users'];
}
- $s_char_options = '<option value=""' . ((!$first_char) ? ' selected="selected"' : '') . '>&nbsp; &nbsp;</option>';
- for ($i = 97; $i < 123; $i++)
- {
- $s_char_options .= '<option value="' . chr($i) . '"' . (($first_char == chr($i)) ? ' selected="selected"' : '') . '>' . chr($i-32) . '</option>';
- }
- $s_char_options .= '<option value="other"' . (($first_char == 'other') ? ' selected="selected"' : '') . '>' . $user->lang['OTHER'] . '</option>';
-
// Build a relevant pagination_url
$params = $sort_params = array();
@@ -1329,6 +1322,7 @@ switch ($mode)
'first_char' => array('first_char', ''),
);
+ $u_first_char_params = array();
foreach ($check_params as $key => $call)
{
if (!isset($_REQUEST[$key]))
@@ -1340,6 +1334,10 @@ switch ($mode)
$param = urlencode($key) . '=' . ((is_string($param)) ? urlencode($param) : $param);
$params[] = $param;
+ if ($key != 'first_char')
+ {
+ $u_first_char_params[] = $param;
+ }
if ($key != 'sk' && $key != 'sd')
{
$sort_params[] = $param;
@@ -1359,6 +1357,27 @@ switch ($mode)
unset($search_params, $sort_params);
+ $u_first_char_params = implode('&amp;', $u_first_char_params);
+ $u_first_char_params .= ($u_first_char_params) ? '&amp;' : '';
+
+ $first_characters = array();
+ $first_characters[''] = $user->lang['ALL'];
+ for ($i = 97; $i < 123; $i++)
+ {
+ $first_characters[chr($i)] = chr($i - 32);
+ }
+ $first_characters['other'] = $user->lang['OTHER'];
+
+ foreach ($first_characters as $char => $desc)
+ {
+ $template->assign_block_vars('first_char', array(
+ 'DESC' => $desc,
+ 'VALUE' => $char,
+ 'S_SELECTED' => ($first_char == $char) ? true : false,
+ 'U_SORT' => append_sid("{$phpbb_root_path}memberlist.$phpEx", $u_first_char_params . 'first_char=' . $char) . '#memberlist',
+ ));
+ }
+
// Some search user specific data
if ($mode == 'searchuser' && ($config['load_search'] || $auth->acl_get('a_')))
{
@@ -1603,7 +1622,6 @@ switch ($mode)
'S_LEADERS_SET' => $leaders_set,
'S_MODE_SELECT' => $s_sort_key,
'S_ORDER_SELECT' => $s_sort_dir,
- 'S_CHAR_OPTIONS' => $s_char_options,
'S_MODE_ACTION' => $pagination_url)
);
}
@@ -1667,7 +1685,7 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f
if ($bday_year)
{
- $now = getdate(time() + $user->timezone + $user->dst - date('Z'));
+ $now = phpbb_gmgetdate(time() + $user->timezone + $user->dst);
$diff = $now['mon'] - $bday_month;
if ($diff == 0)
@@ -1679,7 +1697,7 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f
$diff = ($diff < 0) ? 1 : 0;
}
- $age = (int) ($now['year'] - $bday_year - $diff);
+ $age = max(0, (int) ($now['year'] - $bday_year - $diff));
}
}
diff --git a/phpBB/report.php b/phpBB/report.php
index ca8c7bbd0e..c1172ec1d5 100644
--- a/phpBB/report.php
+++ b/phpBB/report.php
@@ -39,11 +39,13 @@ if (!$post_id && (!$pm_id || !$config['allow_pm_report']))
if ($post_id)
{
$redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;p=$post_id") . "#p$post_id";
+ $return_forum_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id");
$pm_id = 0;
}
else
{
$redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&p=$pm_id");
+ $return_forum_url = '';
$post_id = 0;
$forum_id = 0;
}
@@ -101,6 +103,7 @@ if ($post_id)
{
$message = $user->lang['ALREADY_REPORTED'];
$message .= '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
+ $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . $return_forum_url . '">', '</a>');
trigger_error($message);
}
}
@@ -209,6 +212,10 @@ if ($submit && $reason_id)
meta_refresh(3, $redirect_url);
$message = $lang_success . '<br /><br />' . sprintf($lang_return, '<a href="' . $redirect_url . '">', '</a>');
+ if ($return_forum_url)
+ {
+ $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . $return_forum_url . '">', '</a>');
+ }
trigger_error($message);
}
diff --git a/phpBB/styles/prosilver/imageset/site_logo.gif b/phpBB/styles/prosilver/imageset/site_logo.gif
index 909114c377..2517fbedd6 100644
--- a/phpBB/styles/prosilver/imageset/site_logo.gif
+++ b/phpBB/styles/prosilver/imageset/site_logo.gif
Binary files differ
diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html
index e9ed5d9daf..2c2a242a9f 100644
--- a/phpBB/styles/prosilver/template/forumlist_body.html
+++ b/phpBB/styles/prosilver/template/forumlist_body.html
@@ -13,7 +13,7 @@
<ul class="topiclist">
<li class="header">
<dl class="icon">
- <dt><!-- IF forumrow.S_IS_CAT --><a href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a><!-- ELSE -->{L_FORUM}<!-- ENDIF --></dt>
+ <dt><div class="wrap-content"><!-- IF forumrow.S_IS_CAT --><a href="{forumrow.U_VIEWFORUM}">{forumrow.FORUM_NAME}</a><!-- ELSE -->{L_FORUM}<!-- ENDIF --></div></dt>
<dd class="topics">{L_TOPICS}</dd>
<dd class="posts">{L_POSTS}</dd>
<dd class="lastpost"><span>{L_LAST_POST}</span></dd>
@@ -26,7 +26,7 @@
<!-- IF not forumrow.S_IS_CAT -->
<li class="row">
<dl class="icon" style="background-image: url({forumrow.FORUM_FOLDER_IMG_SRC}); background-repeat: no-repeat;">
- <dt title="{forumrow.FORUM_FOLDER_IMG_ALT}">
+ <dt title="{forumrow.FORUM_FOLDER_IMG_ALT}"><div class="wrap-content">
<!-- IF S_ENABLE_FEEDS and forumrow.S_FEED_ENABLED --><!-- <a class="feed-icon-forum" title="{L_FEED} - {forumrow.FORUM_NAME}" href="{U_FEED}?f={forumrow.FORUM_ID}"><img src="{T_THEME_PATH}/images/feed.gif" alt="{L_FEED} - {forumrow.FORUM_NAME}" /></a> --><!-- ENDIF -->
<!-- IF forumrow.FORUM_IMAGE --><span class="forum-image">{forumrow.FORUM_IMAGE}</span><!-- ENDIF -->
@@ -36,7 +36,7 @@
<br /><strong>{forumrow.L_MODERATOR_STR}:</strong> {forumrow.MODERATORS}
<!-- ENDIF -->
<!-- IF forumrow.SUBFORUMS and forumrow.S_LIST_SUBFORUMS --><br /><strong>{forumrow.L_SUBFORUM_STR}</strong> {forumrow.SUBFORUMS}<!-- ENDIF -->
- </dt>
+ </div></dt>
<!-- IF forumrow.CLICKS -->
<dd class="redirect"><span>{L_REDIRECTS}: {forumrow.CLICKS}</span></dd>
<!-- ELSEIF not forumrow.S_IS_LINK -->
diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html
index f7b4fca609..1029627561 100644
--- a/phpBB/styles/prosilver/template/jumpbox.html
+++ b/phpBB/styles/prosilver/template/jumpbox.html
@@ -10,7 +10,7 @@
<!-- ENDIF -->
<!-- IF S_DISPLAY_JUMPBOX -->
- <form method="post" id="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(document.jumpbox.f.value == -1){return false;}">
+ <form method="post" id="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(this.f.value == -1){return false;}">
<!-- IF $CUSTOM_FIELDSET_CLASS -->
<fieldset class="{$CUSTOM_FIELDSET_CLASS}">
diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html
index 197cbd4a0c..9e6f8c3aab 100644
--- a/phpBB/styles/prosilver/template/memberlist_body.html
+++ b/phpBB/styles/prosilver/template/memberlist_body.html
@@ -34,34 +34,11 @@
<li>
<!-- IF U_FIND_MEMBER and not S_SEARCH_USER --><a href="{U_FIND_MEMBER}">{L_FIND_USERNAME}</a> &bull; <!-- ELSEIF S_SEARCH_USER and U_HIDE_FIND_MEMBER and not S_IN_SEARCH_POPUP --><a href="{U_HIDE_FIND_MEMBER}">{L_HIDE_MEMBER_SEARCH}</a> &bull; <!-- ENDIF -->
- <strong style="font-size: 0.95em;"><a href="{S_MODE_ACTION}&amp;first_char=">{L_ALL}</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=a#memberlist">A</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=b#memberlist">B</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=c#memberlist">C</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=d#memberlist">D</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=e#memberlist">E</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=f#memberlist">F</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=g#memberlist">G</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=h#memberlist">H</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=i#memberlist">I</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=j#memberlist">J</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=k#memberlist">K</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=l#memberlist">L</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=m#memberlist">M</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=n#memberlist">N</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=o#memberlist">O</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=p#memberlist">P</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=q#memberlist">Q</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=r#memberlist">R</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=s#memberlist">S</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=t#memberlist">T</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=u#memberlist">U</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=v#memberlist">V</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=w#memberlist">W</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=x#memberlist">X</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=y#memberlist">Y</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=z#memberlist">Z</a>&nbsp;
- <a href="{S_MODE_ACTION}&amp;first_char=other">#</a></strong>
+ <strong style="font-size: 0.95em;">
+ <!-- BEGIN first_char -->
+ <a href="{first_char.U_SORT}">{first_char.DESC}</a>&nbsp;
+ <!-- END first_char -->
+ </strong>
</li>
<li class="rightside pagination">
{TOTAL_USERS} &bull;
diff --git a/phpBB/styles/prosilver/template/memberlist_view.html b/phpBB/styles/prosilver/template/memberlist_view.html
index 031bfec6ff..3398bb5e9e 100644
--- a/phpBB/styles/prosilver/template/memberlist_view.html
+++ b/phpBB/styles/prosilver/template/memberlist_view.html
@@ -28,7 +28,7 @@
<!-- ENDIF -->
<!-- IF S_USER_INACTIVE --><dt>{L_USER_IS_INACTIVE}:</dt> <dd>{USER_INACTIVE_REASON}</dd><!-- ENDIF -->
<!-- IF LOCATION --><dt>{L_LOCATION}:</dt> <dd>{LOCATION}</dd><!-- ENDIF -->
- <!-- IF AGE --><dt>{L_AGE}:</dt> <dd>{AGE}</dd><!-- ENDIF -->
+ <!-- IF AGE !== '' --><dt>{L_AGE}:</dt> <dd>{AGE}</dd><!-- ENDIF -->
<!-- IF OCCUPATION --><dt>{L_OCCUPATION}:</dt> <dd>{OCCUPATION}</dd><!-- ENDIF -->
<!-- IF INTERESTS --><dt>{L_INTERESTS}:</dt> <dd>{INTERESTS}</dd><!-- ENDIF -->
<!-- IF S_GROUP_OPTIONS --><dt>{L_USERGROUPS}:</dt> <dd><select name="g">{S_GROUP_OPTIONS}</select> <input type="submit" name="submit" value="{L_GO}" class="button2" /></dd><!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html
index 1a044b0ca1..b252ff0de9 100644
--- a/phpBB/styles/prosilver/template/overall_footer.html
+++ b/phpBB/styles/prosilver/template/overall_footer.html
@@ -19,7 +19,7 @@
<span class="corners-bottom"><span></span></span></div>
</div>
- <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
<!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF -->
<!-- IF DEBUG_OUTPUT --><br />{DEBUG_OUTPUT}<!-- ENDIF -->
<!-- IF U_ACP --><br /><strong><a href="{U_ACP}">{L_ACP}</a></strong><!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html
index e13c49b59a..a46c161542 100644
--- a/phpBB/styles/prosilver/template/overall_header.html
+++ b/phpBB/styles/prosilver/template/overall_header.html
@@ -68,7 +68,7 @@
{
eval(onload_functions[i]);
}
- }
+ };
window.onunload = function()
{
@@ -76,7 +76,7 @@
{
eval(onunload_functions[i]);
}
- }
+ };
// ]]>
</script>
diff --git a/phpBB/styles/prosilver/template/posting_buttons.html b/phpBB/styles/prosilver/template/posting_buttons.html
index 19d55d1a4a..78c2a0d9f2 100644
--- a/phpBB/styles/prosilver/template/posting_buttons.html
+++ b/phpBB/styles/prosilver/template/posting_buttons.html
@@ -25,7 +25,7 @@
a: '{LA_BBCODE_A_HELP}',
s: '{LA_BBCODE_S_HELP}',
f: '{LA_BBCODE_F_HELP}',
- e: '{LA_BBCODE_E_HELP}',
+ y: '{LA_BBCODE_Y_HELP}',
d: '{LA_BBCODE_D_HELP}'
<!-- BEGIN custom_tags -->
,cb_{custom_tags.BBCODE_ID}: '{custom_tags.A_BBCODE_HELPLINE}'
@@ -79,7 +79,7 @@
<input type="button" class="button2" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" title="{L_BBCODE_C_HELP}" />
<input type="button" class="button2" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" title="{L_BBCODE_L_HELP}" />
<input type="button" class="button2" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" title="{L_BBCODE_O_HELP}" />
- <input type="button" class="button2" accesskey="y" name="addlitsitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}" />
+ <input type="button" class="button2" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}" />
<!-- IF S_BBCODE_IMG -->
<input type="button" class="button2" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" title="{L_BBCODE_P_HELP}" />
<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html
index daeb786fcb..9795140c47 100644
--- a/phpBB/styles/prosilver/template/simple_footer.html
+++ b/phpBB/styles/prosilver/template/simple_footer.html
@@ -1,6 +1,6 @@
</div>
- <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
<!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF -->
<!-- IF DEBUG_OUTPUT --><br />{DEBUG_OUTPUT}<!-- ENDIF -->
</div>
diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html
index c69bb82382..b1a93296bd 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html
@@ -112,7 +112,7 @@ hr.sep {
<td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td>
</tr>
<tr>
- <td colspan="2" align="center"><span class="gensmall">Powered by phpBB &copy; phpBB Group<br />http://www.phpbb.com/</span></td>
+ <td colspan="2" align="center"><span class="gensmall">Powered by phpBB&reg; Forum Software &copy; phpBB Group<br />http://www.phpbb.com/</span></td>
</tr>
</table>
diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html
index 02f42fa097..4ad0990d98 100644
--- a/phpBB/styles/prosilver/template/viewforum_body.html
+++ b/phpBB/styles/prosilver/template/viewforum_body.html
@@ -127,7 +127,7 @@
<ul class="topiclist">
<li class="header">
<dl class="icon">
- <dt><!-- IF S_DISPLAY_ACTIVE -->{L_ACTIVE_TOPICS}<!-- ELSEIF topicrow.S_TOPIC_TYPE_SWITCH and (topicrow.S_POST_ANNOUNCE or topicrow.S_POST_GLOBAL) -->{L_ANNOUNCEMENTS}<!-- ELSE -->{L_TOPICS}<!-- ENDIF --></dt>
+ <dt><div class="wrap-content"><!-- IF S_DISPLAY_ACTIVE -->{L_ACTIVE_TOPICS}<!-- ELSEIF topicrow.S_TOPIC_TYPE_SWITCH and (topicrow.S_POST_ANNOUNCE or topicrow.S_POST_GLOBAL) -->{L_ANNOUNCEMENTS}<!-- ELSE -->{L_TOPICS}<!-- ENDIF --></div></dt>
<dd class="posts">{L_REPLIES}</dd>
<dd class="views">{L_VIEWS}</dd>
<dd class="lastpost"><span>{L_LAST_POST}</span></dd>
@@ -139,12 +139,12 @@
<li class="row<!-- IF topicrow.S_ROW_COUNT is even --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- IF topicrow.S_POST_GLOBAL --> global-announce<!-- ENDIF --><!-- IF topicrow.S_POST_ANNOUNCE --> announce<!-- ENDIF --><!-- IF topicrow.S_POST_STICKY --> sticky<!-- ENDIF --><!-- IF topicrow.S_TOPIC_REPORTED --> reported<!-- ENDIF -->">
<dl class="icon" style="background-image: url({topicrow.TOPIC_FOLDER_IMG_SRC}); background-repeat: no-repeat;">
- <dt<!-- IF topicrow.TOPIC_ICON_IMG and S_TOPIC_ICONS --> style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{topicrow.TOPIC_FOLDER_IMG_ALT}"><!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
+ <dt<!-- IF topicrow.TOPIC_ICON_IMG and S_TOPIC_ICONS --> style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{topicrow.TOPIC_FOLDER_IMG_ALT}"><div class="wrap-content"><!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}">{NEWEST_POST_IMG}</a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
<!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --><a href="{topicrow.U_MCP_QUEUE}">{topicrow.UNAPPROVED_IMG}</a> <!-- ENDIF -->
<!-- IF topicrow.S_TOPIC_REPORTED --><a href="{topicrow.U_MCP_REPORT}">{REPORTED_IMG}</a><!-- ENDIF --><br />
<!-- IF topicrow.PAGINATION --><strong class="pagination"><span>{topicrow.PAGINATION}</span></strong><!-- ENDIF -->
<!-- IF topicrow.ATTACH_ICON_IMG -->{topicrow.ATTACH_ICON_IMG} <!-- ENDIF -->{L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} &raquo; {topicrow.FIRST_POST_TIME}
- </dt>
+ </div></dt>
<dd class="posts">{topicrow.REPLIES} <dfn>{L_REPLIES}</dfn></dd>
<dd class="views">{topicrow.VIEWS} <dfn>{L_VIEWS}</dfn></dd>
<dd class="lastpost"><span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL}
diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html
index 541c48a53d..0fd0e6dfa6 100644
--- a/phpBB/styles/prosilver/template/viewtopic_print.html
+++ b/phpBB/styles/prosilver/template/viewtopic_print.html
@@ -44,7 +44,7 @@
<div id="page-footer">
<div class="page-number">{S_TIMEZONE}<br />{PAGE_NUMBER}</div>
- <div class="copyright">Powered by phpBB &copy; phpBB Group<br />http://www.phpbb.com/</div>
+ <div class="copyright">Powered by phpBB&reg; Forum Software &copy; phpBB Group<br />http://www.phpbb.com/</div>
</div>
</div>
diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css
index 64beb97a37..2dad706bf5 100644
--- a/phpBB/styles/prosilver/theme/content.css
+++ b/phpBB/styles/prosilver/theme/content.css
@@ -29,10 +29,15 @@ ul.topiclist li.row dl {
ul.topiclist dt {
display: block;
float: left;
- width: 50%;
+ width: 100%;
font-size: 1.1em;
padding-left: 5px;
padding-right: 5px;
+ margin-right: -465px;
+}
+
+ul.topiclist dt .wrap-content {
+ padding-right: 465px;
}
ul.topiclist dd {
@@ -96,6 +101,7 @@ li.header dt, li.header dd {
li.header dt {
font-weight: bold;
+ margin-right: -465px;
}
li.header dd {
@@ -126,7 +132,7 @@ dl.icon dt {
}
dd.posts, dd.topics, dd.views {
- width: 8%;
+ width: 90px;
text-align: center;
line-height: 2.2em;
font-size: 1.2em;
@@ -145,7 +151,7 @@ dl.icon dt li {
}
dd.lastpost {
- width: 25%;
+ width: 230px;
font-size: 1.1em;
}
diff --git a/phpBB/styles/subsilver2/template/attachment.html b/phpBB/styles/subsilver2/template/attachment.html
index b5b547b2e6..fca620b481 100644
--- a/phpBB/styles/subsilver2/template/attachment.html
+++ b/phpBB/styles/subsilver2/template/attachment.html
@@ -72,7 +72,7 @@
<param name="controller" value="true">
<param name="autoplay" value="false" />
<param name="type" value="video/quicktime">
- <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="320" height="285" type="video/quicktime" autoplay="false">
+ <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="320" height="285" type="video/quicktime" autoplay="false"></embed>
</object>
<!-- ELSEIF _file.S_RM_FILE -->
<object id="rmstream_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="200" height="50">
diff --git a/phpBB/styles/subsilver2/template/memberlist_body.html b/phpBB/styles/subsilver2/template/memberlist_body.html
index cb7a7b20c7..800162b7b0 100644
--- a/phpBB/styles/subsilver2/template/memberlist_body.html
+++ b/phpBB/styles/subsilver2/template/memberlist_body.html
@@ -14,7 +14,12 @@
<form method="post" name="charsearch" action="{S_MODE_ACTION}">
<table width="100%" cellspacing="1">
<tr>
- <td align="{S_CONTENT_FLOW_BEGIN}"><span class="genmed">{L_USERNAME_BEGINS_WITH}: </span><select name="first_char" onchange="this.form.submit();">{S_CHAR_OPTIONS}</select>&nbsp;<input type="submit" name="char" value="{L_DISPLAY}" class="btnlite" /></td>
+ <td align="{S_CONTENT_FLOW_BEGIN}"><span class="genmed">{L_USERNAME_BEGINS_WITH}: </span>
+ <select name="first_char" onchange="this.form.submit();">
+ <!-- BEGIN first_char -->
+ <option value="{first_char.VALUE}"<!-- IF first_char.S_SELECTED --> selected="selected"<!-- ENDIF -->>{first_char.DESC}</option>
+ <!-- END first_char -->
+ </select>&nbsp;<input type="submit" name="char" value="{L_DISPLAY}" class="btnlite" /></td>
<!-- IF U_FIND_MEMBER and not S_SEARCH_USER -->
<td class="genmed" align="{S_CONTENT_FLOW_END}"><a href="{U_FIND_MEMBER}">{L_FIND_USERNAME}</a></td>
<!-- ELSEIF S_SEARCH_USER and U_HIDE_FIND_MEMBER and not S_IN_SEARCH_POPUP -->
diff --git a/phpBB/styles/subsilver2/template/memberlist_view.html b/phpBB/styles/subsilver2/template/memberlist_view.html
index 9ef2b85878..0afa750c79 100644
--- a/phpBB/styles/subsilver2/template/memberlist_view.html
+++ b/phpBB/styles/subsilver2/template/memberlist_view.html
@@ -148,10 +148,10 @@
<td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_LOCATION}: </td>
<td><!-- IF LOCATION --><b class="genmed">{LOCATION}</b><!-- ENDIF --></td>
</tr>
- <!-- IF AGE -->
+ <!-- IF AGE !== '' -->
<tr>
<td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_AGE}: </td>
- <td><b class="genmed"><!-- IF AGE -->{AGE}<!-- ELSE --> - <!-- ENDIF --></b></td>
+ <td><b class="genmed">{AGE}</b></td>
</tr>
<!-- ENDIF -->
<tr>
diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html
index b53fff9f7f..5d6b63986f 100644
--- a/phpBB/styles/subsilver2/template/overall_footer.html
+++ b/phpBB/styles/subsilver2/template/overall_footer.html
@@ -3,7 +3,7 @@
<div id="wrapfooter">
<!-- IF U_ACP --><span class="gensmall">[ <a href="{U_ACP}">{L_ACP}</a> ]</span><br /><br /><!-- ENDIF -->
- <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group
+ <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group
<!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF -->
<!-- IF DEBUG_OUTPUT --><br /><bdo dir="ltr">[ {DEBUG_OUTPUT} ]</bdo><!-- ENDIF --></span>
</div>
diff --git a/phpBB/styles/subsilver2/template/posting_buttons.html b/phpBB/styles/subsilver2/template/posting_buttons.html
index 92b4bd3e39..a9105b5eec 100644
--- a/phpBB/styles/subsilver2/template/posting_buttons.html
+++ b/phpBB/styles/subsilver2/template/posting_buttons.html
@@ -22,9 +22,8 @@
a: '{LA_BBCODE_A_HELP}',
s: '{LA_BBCODE_S_HELP}',
f: '{LA_BBCODE_F_HELP}',
- e: '{LA_BBCODE_E_HELP}',
+ y: '{LA_BBCODE_Y_HELP}',
d: '{LA_BBCODE_D_HELP}',
- t: '{LA_BBCODE_T_HELP}',
tip: '{L_STYLES_TIP}'
<!-- BEGIN custom_tags -->
,cb_{custom_tags.BBCODE_ID}: '{custom_tags.A_BBCODE_HELPLINE}'
@@ -45,7 +44,7 @@
<input type="button" class="btnbbcode" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" onmouseover="helpline('c')" onmouseout="helpline('tip')" />
<input type="button" class="btnbbcode" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" onmouseover="helpline('l')" onmouseout="helpline('tip')" />
<input type="button" class="btnbbcode" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" onmouseover="helpline('o')" onmouseout="helpline('tip')" />
- <input type="button" class="btnbbcode" accesskey="y" name="addlitsitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('e')" onmouseout="helpline('tip')" />
+ <input type="button" class="btnbbcode" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('e')" onmouseout="helpline('tip')" />
<!-- IF S_BBCODE_IMG -->
<input type="button" class="btnbbcode" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" onmouseover="helpline('p')" onmouseout="helpline('tip')" />
<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/simple_footer.html b/phpBB/styles/subsilver2/template/simple_footer.html
index 1bd146b599..043be16cdb 100644
--- a/phpBB/styles/subsilver2/template/simple_footer.html
+++ b/phpBB/styles/subsilver2/template/simple_footer.html
@@ -2,7 +2,7 @@
</div>
<div id="wrapfooter">
- <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group</span>
+ <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group</span>
</div>
</body>
diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html
index eff4a2a7dd..6753a5bc33 100644
--- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html
+++ b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html
@@ -114,7 +114,7 @@ hr.sep {
<td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td>
</tr>
<tr>
- <td colspan="2" align="center"><span class="gensmall">Powered by phpBB &copy; phpBB Group<br />http://www.phpbb.com/</span></td>
+ <td colspan="2" align="center"><span class="gensmall">Powered by phpBB&reg; Forum Software &copy; phpBB Group<br />http://www.phpbb.com/</span></td>
</tr>
</table>
diff --git a/phpBB/styles/subsilver2/template/viewtopic_print.html b/phpBB/styles/subsilver2/template/viewtopic_print.html
index 38ec10fad8..964c95f677 100644
--- a/phpBB/styles/subsilver2/template/viewtopic_print.html
+++ b/phpBB/styles/subsilver2/template/viewtopic_print.html
@@ -128,7 +128,7 @@ hr.sep {
<td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td>
</tr>
<tr>
- <td colspan="2" align="center"><span class="gensmall">Powered by phpBB &copy; phpBB Group<br />http://www.phpbb.com/</span></td>
+ <td colspan="2" align="center"><span class="gensmall">Powered by phpBB&reg; Forum Software &copy; phpBB Group<br />http://www.phpbb.com/</span></td>
</tr>
</table>
diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php
index 61ec27ed79..e0b51bf782 100644
--- a/phpBB/viewforum.php
+++ b/phpBB/viewforum.php
@@ -208,7 +208,7 @@ $s_watching_forum = array(
if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'] && $forum_data['forum_type'] == FORUM_POST && $auth->acl_get('f_subscribe', $forum_id))
{
$notify_status = (isset($forum_data['notify_status'])) ? $forum_data['notify_status'] : NULL;
- watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0, $notify_status);
+ watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0, $notify_status, $start, $forum_data['forum_name']);
}
$s_forum_rules = '';
diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php
index 08e82591de..203b8586ce 100644
--- a/phpBB/viewtopic.php
+++ b/phpBB/viewtopic.php
@@ -196,7 +196,7 @@ if ($db->sql_layer === 'firebird')
// The FROM-Order is quite important here, else t.* columns can not be correctly bound.
if ($post_id)
{
- $sql_array['SELECT'] .= ', p.post_approved';
+ $sql_array['SELECT'] .= ', p.post_approved, p.post_time, p.post_id';
$sql_array['FROM'][POSTS_TABLE] = 'p';
}
@@ -314,12 +314,19 @@ if ($post_id)
}
else
{
- $sql = 'SELECT COUNT(p1.post_id) AS prev_posts
- FROM ' . POSTS_TABLE . ' p1, ' . POSTS_TABLE . " p2
- WHERE p1.topic_id = {$topic_data['topic_id']}
- AND p2.post_id = {$post_id}
- " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p1.post_approved = 1' : '') . '
- AND ' . (($sort_dir == 'd') ? 'p1.post_time >= p2.post_time' : 'p1.post_time <= p2.post_time');
+ $sql = 'SELECT COUNT(p.post_id) AS prev_posts
+ FROM ' . POSTS_TABLE . " p
+ WHERE p.topic_id = {$topic_data['topic_id']}
+ " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '');
+
+ if ($sort_dir == 'd')
+ {
+ $sql .= " AND (p.post_time > {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id >= {$topic_data['post_id']}))";
+ }
+ else
+ {
+ $sql .= " AND (p.post_time < {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id <= {$topic_data['post_id']}))";
+ }
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
@@ -488,7 +495,7 @@ $s_watching_topic = array(
if (($config['email_enable'] || $config['jab_enable']) && $config['allow_topic_notify'] && $user->data['is_registered'])
{
- watch_topic_forum('topic', $s_watching_topic, $user->data['user_id'], $forum_id, $topic_id, $topic_data['notify_status'], $start);
+ watch_topic_forum('topic', $s_watching_topic, $user->data['user_id'], $forum_id, $topic_id, $topic_data['notify_status'], $start, $topic_data['topic_title']);
// Reset forum notification if forum notify is set
if ($config['allow_forum_notify'] && $auth->acl_get('f_subscribe', $forum_id))
@@ -995,7 +1002,7 @@ $sql = $db->sql_build_query('SELECT', array(
$result = $db->sql_query($sql);
-$now = getdate(time() + $user->timezone + $user->dst - date('Z'));
+$now = phpbb_gmgetdate(time() + $user->timezone + $user->dst);
// Posts are stored in the $rowset array while $attach_list, $user_cache
// and the global bbcode_bitfield are built
diff --git a/tests/network/ftp_fsock_pasv_epsv_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php
new file mode 100644
index 0000000000..6ad811e3ca
--- /dev/null
+++ b/tests/network/ftp_fsock_pasv_epsv_test.php
@@ -0,0 +1,63 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php';
+
+/**
+* @group slow
+*/
+class phpbb_network_ftp_fsock_pasv_epsv_test extends phpbb_test_case
+{
+ static protected $ipv4;
+
+ static public function setUpBeforeClass()
+ {
+ $hostname = 'ftp.debian.org.';
+ self::$ipv4 = gethostbyname($hostname);
+
+ if (self::$ipv4 == $hostname)
+ {
+ self::markTestSkipped("Got no A record back from DNS query for $hostname");
+ }
+ }
+
+ public function test_pasv()
+ {
+ // PASV
+ $this->assert_ls_contains_debian(self::$ipv4);
+ }
+
+ public function test_epsv()
+ {
+ $ipv4 = self::$ipv4;
+ // EPSV
+ $this->assert_ls_contains_debian("[::ffff:$ipv4]");
+ }
+
+ protected function assert_ls_contains_debian($hostname)
+ {
+ $o = $this->get_object($hostname);
+ $result = $o->_init();
+ // This test may fail on IPv6 addresses if IPv6 support is
+ // not available. PHP must be compiled with IPv6 support enabled,
+ // and your operating system must be configured for IPv6 as well.
+ if ($result !== true)
+ {
+ $this->markTestSkipped("Failed to connect to $hostname: $result");
+ }
+ $this->assertContains('debian', $o->_ls());
+ $o->_close();
+ }
+
+ protected function get_object($hostname)
+ {
+ return new ftp_fsock($hostname, 'anonymous', 'anonymous@localhost.tld', '/');
+ }
+}
diff --git a/tests/utf/data/.gitkeep b/tests/tmp/.gitkeep
index e69de29bb2..e69de29bb2 100644
--- a/tests/utf/data/.gitkeep
+++ b/tests/tmp/.gitkeep
diff --git a/tests/utf/normalizer_test.php b/tests/utf/normalizer_test.php
index f78dba8004..a0ba470416 100644
--- a/tests/utf/normalizer_test.php
+++ b/tests/utf/normalizer_test.php
@@ -14,10 +14,13 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_normalizer.php';
*/
class phpbb_utf_normalizer_test extends phpbb_test_case
{
+ static private $data_dir;
+
static public function setUpBeforeClass()
{
- self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', dirname(__FILE__).'/data');
- self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', dirname(__FILE__).'/data');
+ self::$data_dir = dirname(__file__) . '/../tmp';
+ self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', self::$data_dir);
+ self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', self::$data_dir);
}
public function test_normalizer()
@@ -62,7 +65,7 @@ class phpbb_utf_normalizer_test extends phpbb_test_case
$tested_chars = array();
- $fp = fopen(dirname(__FILE__).'/data/NormalizationTest.txt', 'rb');
+ $fp = fopen(self::$data_dir . '/NormalizationTest.txt', 'rb');
while (!feof($fp))
{
$line = fgets($fp);
@@ -117,7 +120,7 @@ class phpbb_utf_normalizer_test extends phpbb_test_case
*/
public function test_invariants(array $tested_chars)
{
- $fp = fopen(dirname(__FILE__).'/data/UnicodeData.txt', 'rb');
+ $fp = fopen(self::$data_dir . '/UnicodeData.txt', 'rb');
while (!feof($fp))
{
diff --git a/tests/wrapper/gmgetdate_test.php b/tests/wrapper/gmgetdate_test.php
new file mode 100644
index 0000000000..0b4c3378a9
--- /dev/null
+++ b/tests/wrapper/gmgetdate_test.php
@@ -0,0 +1,49 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+
+class phpbb_wrapper_gmgetdate_test extends phpbb_test_case
+{
+ public function test_gmgetdate()
+ {
+ $this->run_gmgetdate_assertion();
+ $this->run_test_with_timezone('UTC');
+ $this->run_test_with_timezone('Europe/Berlin');
+ $this->run_test_with_timezone('America/Los_Angeles');
+ $this->run_test_with_timezone('Antarctica/South_Pole');
+ }
+
+ protected function run_test_with_timezone($timezone_identifier)
+ {
+ $current_timezone = date_default_timezone_get();
+
+ date_default_timezone_set($timezone_identifier);
+ $this->run_gmgetdate_assertion();
+ date_default_timezone_set($current_timezone);
+ }
+
+ protected function run_gmgetdate_assertion()
+ {
+ $expected = time();
+
+ $date_array = phpbb_gmgetdate($expected);
+
+ $actual = gmmktime(
+ $date_array['hours'],
+ $date_array['minutes'],
+ $date_array['seconds'],
+ $date_array['mon'],
+ $date_array['mday'],
+ $date_array['year']
+ );
+
+ $this->assertEquals($expected, $actual);
+ }
+}
diff --git a/tests/random/mt_rand.php b/tests/wrapper/mt_rand_test.php
index d6502c4e80..c8bcb3d14c 100644
--- a/tests/random/mt_rand.php
+++ b/tests/wrapper/mt_rand_test.php
@@ -9,7 +9,7 @@
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-class phpbb_random_mt_rand_test extends phpbb_test_case
+class phpbb_wrapper_mt_rand_test extends phpbb_test_case
{
public function test_max_equals_min()
{
diff --git a/tests/wrapper/version_compare_test.php b/tests/wrapper/version_compare_test.php
new file mode 100644
index 0000000000..f718cfd16b
--- /dev/null
+++ b/tests/wrapper/version_compare_test.php
@@ -0,0 +1,130 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+
+class phpbb_wrapper_version_compare_test extends phpbb_test_case
+{
+ public function test_two_parameters()
+ {
+ $this->assertEquals(-1, phpbb_version_compare('1.0.0', '1.0.1'));
+ $this->assertEquals(0, phpbb_version_compare('1.0.0', '1.0.0'));
+ $this->assertEquals(1, phpbb_version_compare('1.0.1', '1.0.0'));
+ }
+
+ public function test_three_parameters()
+ {
+ $this->assertEquals(true, phpbb_version_compare('1.0.0', '1.0.1', '<'));
+ $this->assertEquals(true, phpbb_version_compare('1.0.0', '1.0.0', '<='));
+ $this->assertEquals(true, phpbb_version_compare('1.0.0', '1.0.0', '='));
+ $this->assertEquals(true, phpbb_version_compare('1.0.0', '1.0.0', '>='));
+ $this->assertEquals(true, phpbb_version_compare('1.0.1', '1.0.0', '>'));
+ }
+
+ public function test_strict_order()
+ {
+ $releases = array(
+ '2.0.0',
+ '2.0.1',
+ // Those are not version_compare() compatible
+ //'2.0.6a',
+ //'2.0.6b',
+ //'2.0.6c',
+ //'2.0.6d',
+ '2.0.7',
+ '2.0.23',
+ '3.0.A1',
+ '3.0.A2',
+ '3.0.A3',
+ '3.0.B1',
+ '3.0.B2',
+ '3.0.B4',
+ '3.0.B5',
+ '3.0.RC1',
+ '3.0.RC5',
+ '3.0.0',
+ '3.0.1',
+ '3.0.2',
+ '3.0.7',
+ '3.0.7-PL1',
+ '3.0.8-RC1',
+ '3.0.8',
+ '3.0.9-dev',
+ '3.0.9-RC1',
+ '3.0.9-RC2',
+ '3.0.9-RC4',
+ '3.0.10-RC1',
+ '3.1-dev',
+ '3.2-A1',
+ );
+
+ for ($i = 0, $size = sizeof($releases); $i < $size - 1; ++$i)
+ {
+ $version1 = $releases[$i];
+ $version2 = $releases[$i + 1];
+
+ $this->assertEquals(
+ true,
+ phpbb_version_compare($version1, $version2, '<'),
+ "Result of version comparison $version1 < $version2 is incorrect."
+ );
+ }
+ }
+
+ /**
+ * @dataProvider equality_test_data
+ */
+ public function test_equality($version1, $version2)
+ {
+ $this->assertEquals(
+ 0,
+ phpbb_version_compare($version1, $version2),
+ "Result of version comparison $version1 = $version2 is incorrect."
+ );
+
+ $this->assertEquals(
+ true,
+ phpbb_version_compare($version1, $version2, '='),
+ "Result of version comparison $version1 = $version2 is incorrect."
+ );
+ }
+
+ public function equality_test_data()
+ {
+ return array(
+ array('1.1.0-A2', '1.1.0-a2'),
+ array('1.1.0-B1', '1.1.0-b1'),
+ );
+ }
+
+ /**
+ * @dataProvider alpha_beta_test_data
+ */
+ public function test_alpha_beta($expected, $version1, $version2)
+ {
+ $this->assertEquals(
+ $expected,
+ phpbb_version_compare($version1, $version2),
+ "Result of version comparison ($version1, $version2) = $expected is incorrect."
+ );
+
+ }
+
+ public function alpha_beta_test_data()
+ {
+ return array(
+ array(-1, '1.1.0-A2', '1.1.0-B1'),
+ array(-1, '1.1.0-a2', '1.1.0-b1'),
+
+ array(-1, '1.1.0-a2', '1.1.0-B1'),
+ array(-1, '1.1.0-A2', '1.1.0-b1'),
+ );
+ }
+
+}