aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--phpBB/adm/style/acp_update.html6
-rw-r--r--phpBB/adm/style/acp_users_signature.html2
-rw-r--r--phpBB/common.php6
-rw-r--r--phpBB/config.php0
-rw-r--r--phpBB/docs/AUTHORS2
-rw-r--r--phpBB/docs/auth_api.html50
-rw-r--r--phpBB/docs/coding-guidelines.html126
-rw-r--r--phpBB/docs/hook_system.html2
-rw-r--r--phpBB/includes/.htaccess4
-rw-r--r--phpBB/includes/acp/acp_database.php54
-rw-r--r--phpBB/includes/acp/acp_groups.php9
-rw-r--r--phpBB/includes/acp/acp_update.php10
-rw-r--r--phpBB/includes/auth/auth_db.php6
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php5
-rw-r--r--phpBB/includes/constants.php4
-rw-r--r--phpBB/includes/db/mssqlnative.php46
-rw-r--r--phpBB/includes/functions.php4
-rw-r--r--phpBB/includes/functions_admin.php2
-rw-r--r--phpBB/includes/functions_messenger.php87
-rw-r--r--phpBB/includes/functions_profile_fields.php5
-rw-r--r--phpBB/includes/search/fulltext_mysql.php8
-rw-r--r--phpBB/includes/ucp/info/ucp_profile.php2
-rw-r--r--phpBB/install/database_update.php8
-rw-r--r--phpBB/language/en/acp/board.php64
-rw-r--r--phpBB/language/en/acp/common.php4
-rw-r--r--phpBB/language/en/acp/search.php2
-rw-r--r--phpBB/language/en/acp/styles.php8
-rw-r--r--phpBB/language/en/captcha_qa.php14
-rw-r--r--phpBB/language/en/captcha_recaptcha.php2
-rw-r--r--phpBB/language/en/common.php10
-rw-r--r--phpBB/language/en/install.php1
-rw-r--r--phpBB/posting.php2
-rw-r--r--phpBB/styles/prosilver/template/captcha_recaptcha.html1
-rw-r--r--phpBB/styles/prosilver/template/index_body.html2
-rw-r--r--phpBB/styles/prosilver/template/login_body.html6
-rw-r--r--phpBB/styles/prosilver/template/mcp_post.html2
-rw-r--r--phpBB/styles/prosilver/template/overall_header.html2
-rw-r--r--phpBB/styles/prosilver/template/posting_buttons.html2
-rw-r--r--phpBB/styles/prosilver/template/posting_editor.html4
-rw-r--r--phpBB/styles/prosilver/template/search_body.html8
-rw-r--r--phpBB/styles/prosilver/theme/content.css5
-rw-r--r--phpBB/styles/prosilver/theme/print.css2
-rw-r--r--phpBB/styles/subsilver2/template/captcha_default.html2
-rw-r--r--phpBB/styles/subsilver2/template/captcha_recaptcha.html1
-rw-r--r--phpBB/styles/subsilver2/template/login_body.html19
-rw-r--r--phpBB/styles/subsilver2/template/overall_header.html6
-rw-r--r--phpBB/styles/subsilver2/template/posting_body.html8
-rw-r--r--phpBB/styles/subsilver2/template/posting_buttons.html2
-rw-r--r--phpBB/styles/subsilver2/template/search_body.html19
-rw-r--r--tests/RUNNING_TESTS.txt38
-rw-r--r--tests/all_tests.php9
-rw-r--r--tests/dbal/all_tests.php6
-rw-r--r--tests/dbal/fixtures/config.xml18
-rw-r--r--tests/dbal/select.php (renamed from tests/dbal/dbal.php)172
-rw-r--r--tests/dbal/write.php172
-rw-r--r--tests/template/template.php1
-rw-r--r--tests/test_framework/framework.php8
-rw-r--r--tests/test_framework/phpbb_database_test_case.php283
-rw-r--r--tests/test_framework/phpbb_test_case.php7
-rw-r--r--tests/test_framework/phpbb_test_case_helpers.php68
61 files changed, 877 insertions, 557 deletions
diff --git a/.gitignore b/.gitignore
index 2b9eef7fce..871d17b386 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,8 @@
+*~
phpBB/cache/*.php
+phpBB/config.php
+phpBB/files/*
+phpBB/images/avatars/upload/*
+phpBB/store/*
tests/phpbb_unit_tests.sqlite2
tests/test_config.php
-*~
diff --git a/phpBB/adm/style/acp_update.html b/phpBB/adm/style/acp_update.html
index 34d4f6934e..a87366a78b 100644
--- a/phpBB/adm/style/acp_update.html
+++ b/phpBB/adm/style/acp_update.html
@@ -18,6 +18,12 @@
</div>
<!-- ENDIF -->
+ <!-- IF NEXT_FEATURE_VERSION -->
+ <div class="errorbox">
+ <p>{UPGRADE_INSTRUCTIONS}</p>
+ </div>
+ <!-- ENDIF -->
+
<fieldset>
<legend></legend>
<dl>
diff --git a/phpBB/adm/style/acp_users_signature.html b/phpBB/adm/style/acp_users_signature.html
index 6317a375b4..69c6d8f3fb 100644
--- a/phpBB/adm/style/acp_users_signature.html
+++ b/phpBB/adm/style/acp_users_signature.html
@@ -56,7 +56,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="t" name="addlitsitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('e')" 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')" />
<!-- 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/common.php b/phpBB/common.php
index 9b6913e95f..c8b2fb9609 100644
--- a/phpBB/common.php
+++ b/phpBB/common.php
@@ -123,13 +123,11 @@ if (defined('IN_CRON'))
$phpbb_root_path = dirname(__FILE__) . DIRECTORY_SEPARATOR;
}
-if (!file_exists($phpbb_root_path . 'config.' . $phpEx))
+if (file_exists($phpbb_root_path . 'config.' . $phpEx))
{
- die("<p>The config.$phpEx file could not be found.</p><p><a href=\"{$phpbb_root_path}install/index.$phpEx\">Click here to install phpBB</a></p>");
+ require($phpbb_root_path . 'config.' . $phpEx);
}
-require($phpbb_root_path . 'config.' . $phpEx);
-
if (!defined('PHPBB_INSTALLED'))
{
// Redirect the user to the installer
diff --git a/phpBB/config.php b/phpBB/config.php
deleted file mode 100644
index e69de29bb2..0000000000
--- a/phpBB/config.php
+++ /dev/null
diff --git a/phpBB/docs/AUTHORS b/phpBB/docs/AUTHORS
index d6af9d1db9..b3166313c3 100644
--- a/phpBB/docs/AUTHORS
+++ b/phpBB/docs/AUTHORS
@@ -27,7 +27,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody)
APTX (Marek A. R.)
bantu (Andreas Fischer)
dhn (Dominik Dröscher)
- evil<3 (Igor Wiedler)
+ igorw (Igor Wiedler)
kellanved (Henry Sudhof)
nickvergessen (Joas Schilling)
rxu (Ruslan Uzdenov)
diff --git a/phpBB/docs/auth_api.html b/phpBB/docs/auth_api.html
index c83aaadc2d..8973582bdb 100644
--- a/phpBB/docs/auth_api.html
+++ b/phpBB/docs/auth_api.html
@@ -61,6 +61,9 @@
<li><a href="#acl_getf">acl_getf</a></li>
<li><a href="#acl_getf_global">acl_getf_global</a></li>
<li><a href="#acl_cache">acl_cache</a></li>
+ <li><a href="#acl_clear_prefetch">acl_clear_prefetch</a></li>
+ <li><a href="#acl_get_list">acl_get_list</a></li>
+ <li><a href="#misc">Miscellaneous</a></li>
</ol>
</li>
<li><a href="#admin_related">Admin related functions</a></li>
@@ -176,7 +179,7 @@ array(<em>forum_id1</em> =&gt; array(<em>option</em> =&gt; <em>integer</em>), <e
<p>This method is used to find out whether a user has a permission in at least one forum or globally. This method is similar to checking whether <code>acl_getf(option, true)</code> returned one or more forums but it's faster. It should be called in the following way:</p>
<div class="codebox"><pre>
-$result = acl_getf_global(<code>option</code>)
+$result = $auth-&gt;acl_getf_global(<code>option</code>)
</pre></div>
<p>As with the previous methods option is a string specifying the permission which has to be checked.</p>
@@ -187,6 +190,49 @@ $result = acl_getf_global(<code>option</code>)
<p>This should be considered a private method and not be called externally. It handles the generation of the user_permissions data from the basic user and group authorisation data. When necessary this method is called automatically by <code>acl</code>.</p>
+ <a name="acl_clear_prefetch"></a><h3>2.vii. acl_clear_prefetch</h3>
+
+ <p>This method clears the user_permissions column in the users table for the given user. If the user ID passed is zero, the permissions cache is cleared for all users. This method should be called whenever permissions are set.</p>
+
+ <div class="codebox"><pre>
+// clear stored permissions for user 2
+$user_id = 2;
+$auth->acl_clear_prefetch($user_id);
+</pre></div>
+
+ <p>This method returns void.</p>
+
+ <a name="acl_get_list"></a><h3>2.viii. acl_get_list</h3>
+
+ <p>This method returns an an array describing which users have permissions in given fora. The resultant array contains an entry for permission that every user has in every forum when no arguments are passed.</p>
+
+ <div class="codebox"><pre>
+$user_id = array(2, 53);
+$permissions = array('f_list', 'f_read');
+$forum_id = array(1, 2, 3);
+$result = $auth-&gt;acl_get_list($user_id, $permissions, $forum_id);
+</pre></div>
+
+ <p>The parameters may be of the following legal types:</p>
+ <ul>
+ <li><strong>$user_id</strong>: <code>false</code>, int, array(int, int, int, ...)</li>
+ <li><strong>$permissions</strong>: <code>false</code>, string, array(string, string, ...)</li>
+ <li><strong>$forum_id</strong>: <code>false</code>, int, array(int, int, int, ...)</li>
+ </ul>
+
+ <a name="misc"></a><h3>2.ix. Miscellaneous</h3>
+
+ <p>There are other methods defined in the auth class which serve mostly as private methods, but are available for use if needed. Each of them is used to pull data directly from the database tables. They are:</p>
+ <ul>
+ <li><pre>function acl_group_raw_data($group_id = false, $opts = false, $forum_id = false)</pre></li>
+ <li><pre>function acl_user_raw_data($user_id = false, $opts = false, $forum_id = false)</pre></li>
+ <li><pre>function acl_raw_data_single_user($user_id)</pre></li>
+ <li><pre>function acl_raw_data($user_id = false, $opts = false, $forum_id = false)</pre></li>
+ <li><pre>function acl_role_data($user_type, $role_type, $ug_id = false, $forum_id = false)</pre></li>
+ </ul>
+
+ <p>Of these, <code>acl_raw_data</code> is the most general, but the others will be faster if you need a smaller amount of data.</p>
+
</div>
<div class="back2top"><a href="#wrap" class="top">Back to Top</a></div>
@@ -241,7 +287,7 @@ $auth_admin = new auth_admin();
<!-- END DOCUMENT -->
<div id="page-footer">
- <div class="version"> $Id$ </div>
+ <div class="version">&nbsp;</div>
</div>
</div></div>
diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html
index 1978a0a307..76afc79f99 100644
--- a/phpBB/docs/coding-guidelines.html
+++ b/phpBB/docs/coding-guidelines.html
@@ -90,10 +90,9 @@
<li><a href="#vcs">VCS Guidelines</a>
<ol style="list-style-type: lower-roman;">
<li><a href="#repostruct">Repository structure</a></li>
- <li><a href="#commitmessage">Commit messages</a></li>
+ <li><a href="#commitmessage">Commit Messages and Repository Rules</a></li>
</ol>
</li>
- <li><a href="#changes">Guidelines Changelog</a></li>
<li><a href="#disclaimer">Copyright and disclaimer</a></li>
</ol>
@@ -2326,126 +2325,33 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
<div class="content">
- <p>The version control system for phpBB3 is subversion. The repository is available at <a href="http://code.phpbb.com/svn/phpbb" title="repository">http://code.phpbb.com/svn/phpbb</a>.</p>
+ <p>The version control system for phpBB3 is git. The repository is available at <a href="http://github.com/phpbb/phpbb3" title="repository">http://github.com/phpbb/phpbb3</a>.</p>
<a name="repostruct"></a><h3>7.i. Repository Structure</h3>
<ul>
- <li><strong>trunk</strong><br />The latest unstable development version with new features etc. Contains the actual board in <code>/trunk/phpBB</code></li>
- <li><strong>branches</strong><br />Development branches of stable phpBB releases. Copied from <code>/trunk</code> at the time of release.
+ <li><strong>develop</strong><br />The latest unstable development version with new features etc.</li>
+ <li><strong>develop-*</strong><br />Development branches of stable phpBB releases. Branched off of <code>develop</code> at the time of feature freeze.
<ul>
- <li><strong>phpBB3.0</strong><code>/branches/phpBB-3_0_0/phpBB</code><br />Development branch of the stable 3.0 line. Bug fixes are applied here.</li>
- <li><strong>phpBB2</strong><code>/branches/phpBB-2_0_0/phpBB</code><br />Old phpBB2 development branch.</li>
+ <li><strong>phpBB3.0</strong><code>develop-olympus</code><br />Development branch of the stable 3.0 line. Bug fixes are applied here.</li>
+ <li><strong>phpBB3.1</strong><code>develop-ascraeus</code><br />Development branch of the stable 3.1 line. Bug fixes are applied here.</li>
</ul>
</li>
- <li><strong>tags</strong><br />Released versions. Copies of trunk or the respective branch, made at the time of release.
+ <li><strong>master</strong><br />A branch containing all stable phpBB3 release points</li>
+ <li><strong>tags</strong><br />Released versions. Stable ones get merged into the master branch.
<ul>
- <li><code>/tags/release_3_0_BX</code><br />Beta release X of the 3.0 line.</li>
- <li><code>/tags/release_3_0_RCX</code><br />Release candidate X of the 3.0 line.</li>
- <li><code>/tags/release_3_0_X-RCY</code><br />Release candidate Y of the stable 3.0.X release.</li>
- <li><code>/tags/release_3_0_X</code><br />Stable <strong>3.0.X</strong> release.</li>
- <li><code>/tags/release_2_0_X</code><br />Old stable 2.0.X release.</li>
+ <li><code>release-3.Y-BX</code><br />Beta release X of the 3.Y line.</li>
+ <li><code>release-3.Y-RCX</code><br />Release candidate X of the 3.Y line.</li>
+ <li><code>release-3.Y.Z-RCX</code><br />Release candidate X of the stable 3.Y.Z release.</li>
+ <li><code>release-3.0.X</code><br />Stable <strong>3.0.X</strong> release.</li>
+ <li><code>release-2.0.X</code><br />Old stable 2.0.X release.</li>
</ul>
</li>
</ul>
- <a name="commitmessage"></a><h3>7.ii. Commit Messages</h3>
-
- <p>The commit message should contain a brief explanation of all changes made within the commit. Often identical to the changelog entry. A bug ticket can be referenced by specifying the ticket ID with a hash, e.g. #12345. A reference to another revision should simply be prefixed with r, e.g. r12345.</p>
-
- <p>Junior Developers need to have their patches approved by a development team member first. The commit message must end in a line with the following format:</p>
-
- <div class="codebox"><pre>
-Authorised by: developer1[, developer2[, ...]]
- </pre></div>
-
- </div>
-
- <div class="back2top"><a href="#wrap" class="top">Back to Top</a></div>
-
- <span class="corners-bottom"><span></span></span></div>
- </div>
-
- <hr />
-
-<a name="changes"></a><h2>8. Guidelines Changelog</h2>
- <div class="paragraph">
- <div class="inner"><span class="corners-top"><span></span></span>
-
- <div class="content">
-<h3>Revision 10007</h3>
-
-<ul>
- <li>Added <a href="#constants">Special Constants</a> section.</li>
-</ul>
-
-<h3>Revision 9817</h3>
-
-<ul>
- <li>Added VCS section.</li>
-</ul>
-
-<h3>Revision 8732</h3>
-
-<ul>
- <li>Added cfg files.</li>
- <li>Added template <a href="#inheritance">inheritance</a>.</li>
-</ul>
-
-<h3>Revision 8596+</h3>
-
-<ul>
- <li>Removed sql_build_array('MULTI_INSERT'... statements.</li>
- <li>Added sql_multi_insert() explanation.</li>
-</ul>
-
-<h3>Revision 1.31</h3>
-
-<ul>
- <li>Added add_form_key and check_form_key. </li>
-</ul>
-
-<h3>Revision 1.24</h3>
-
-<ul>
- <li>Added <a href="#translation">5. Character Sets and Encodings</a> section to explain the recommended treatment of strings in phpBB.</li>
-</ul>
-
-<h3>Revision 1.16</h3>
-
-<ul>
- <li>Added <a href="#translation">6. Translation (<abbr title="Internationalisation">i18n</abbr>/<abbr title="Localisation">L10n</abbr>) Guidelines</a> section to explain expected format and authoring considerations for language packs that are to be created for phpBB.</li>
-</ul>
-
-<h3>Revision 1.11-1.15</h3>
-
-<ul>
- <li>Various document formatting, spelling, punctuation, grammar bugs.</li>
-</ul>
-
-<h3>Revision 1.9-1.10</h3>
-
-<ul>
- <li>Added sql_query_limit to <a href="#sql">2.iii. SQL/SQL Layout</a>.</li>
-</ul>
-
-<h3>Revision 1.8</h3>
-
-<ul>
- <li>Some adjustements to wordings</li>
- <li>Updated paragraph <a href="#locations">1.iii. File Locations</a> to reflect recent changes</li>
- <li>Extended paragraph <a href="#codelayout">2.ii. Code Layout</a>.</li>
- <li>Added sql_in_set and sql_build_query explanation to <a href="#sql">2.iii. SQL/SQL Layout</a>.</li>
- <li>Updated paragraph <a href="#styling">3. Styling</a>.</li>
- <li>Updated paragraph <a href="#templating">4. Templating</a> to explain loop checking, loop breaking and other changes we recently made.</li>
-</ul>
-
-<h3>Revision 1.5</h3>
-
-<ul>
- <li>Changed General function usage paragraph in <a href="#general">2.v. General Guidelines</a></li>
-</ul>
+ <a name="commitmessage"></a><h3>7.ii. Commit Messages and Reposiory Rules</h3>
+ <p>Information on repository rules, such as commit messages can be found at <a href="http://wiki.phpbb.com/display/DEV/Git" title="phpBB Git Information">http://wiki.phpbb.com/display/DEV/Git</a></p>.
</div>
@@ -2475,7 +2381,7 @@ Authorised by: developer1[, developer2[, ...]]
<!-- END DOCUMENT -->
<div id="page-footer">
- <div class="version"> $Id$ </div>
+ <div class="version">&nbsp;</div>
</div>
</div></div>
diff --git a/phpBB/docs/hook_system.html b/phpBB/docs/hook_system.html
index b23ebab869..1bf4630a9f 100644
--- a/phpBB/docs/hook_system.html
+++ b/phpBB/docs/hook_system.html
@@ -875,7 +875,7 @@ function phpbb_hook_register(&amp;$hook)
</div>
<div id="page-footer">
- <div class="version">$Id$</div>
+ <div class="version">&nbsp;</div>
</div>
</div></div>
diff --git a/phpBB/includes/.htaccess b/phpBB/includes/.htaccess
new file mode 100644
index 0000000000..4128d345ab
--- /dev/null
+++ b/phpBB/includes/.htaccess
@@ -0,0 +1,4 @@
+<Files *>
+ Order Allow,Deny
+ Deny from All
+</Files>
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php
index 0582d6204e..193dd001c0 100644
--- a/phpBB/includes/acp/acp_database.php
+++ b/phpBB/includes/acp/acp_database.php
@@ -1619,41 +1619,48 @@ class mssql_extractor extends base_extractor
function write_data_mssqlnative($table_name)
{
global $db;
- $ary_type = $ary_name = $meta_array = array();
+ $ary_type = $ary_name = array();
$ident_set = false;
$sql_data = '';
// Grab all of the data from current table.
$sql = "SELECT * FROM $table_name";
+ $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
$result = $db->sql_query($sql);
- $retrieved_data = $db->mssqlnative_num_rows($result);
+ $retrieved_data = $db->mssqlnative_num_rows($result);
- $meta_array = sqlsrv_field_metadata($result);
- $i_num_fields = sqlsrv_num_fields($result);
-
+ if (!$retrieved_data)
+ {
+ $db->sql_freeresult($result);
+ return;
+ }
+
+ $sql = "SELECT * FROM $table_name";
+ $result_fields = $db->sql_query_limit($sql, 1);
+
+ $row = new result_mssqlnative($result_fields);
+ $i_num_fields = $row->num_fields();
+
for ($i = 0; $i < $i_num_fields; $i++)
{
- $info = $db->mssqlnative_fieldInfo($table_name, $meta_array[$i]['Name']);
- $ary_type[$i] = $info->type();
- $ary_name[$i] = $info->name();
+ $ary_type[$i] = $row->field_type($i);
+ $ary_name[$i] = $row->field_name($i);
}
+ $db->sql_freeresult($result_fields);
+
+ $sql = "SELECT 1 as has_identity
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
+ $result2 = $db->sql_query($sql);
+ $row2 = $db->sql_fetchrow($result2);
- if ($retrieved_data)
+ if (!empty($row2['has_identity']))
{
- $sql = "SELECT 1 as has_identity
- FROM INFORMATION_SCHEMA.COLUMNS
- WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
- $result2 = $db->sql_query($sql);
- $row2 = $db->sql_fetchrow($result2);
-
- if (!empty($row2['has_identity']))
- {
- $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
- $ident_set = true;
- }
- $db->sql_freeresult($result2);
+ $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
+ $ident_set = true;
}
+ $db->sql_freeresult($result2);
while ($row = $db->sql_fetchrow($result))
{
@@ -1664,7 +1671,8 @@ class mssql_extractor extends base_extractor
{
$str_val = $row[$ary_name[$i]];
- if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
+ // defaults to type number - better quote just to be safe, so check for is_int too
+ if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
{
$str_quote = '';
$str_empty = "''";
@@ -1705,7 +1713,7 @@ class mssql_extractor extends base_extractor
}
$db->sql_freeresult($result);
- if ($retrieved_data && $ident_set)
+ if ($ident_set)
{
$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
}
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 60512c67b8..486616c33d 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -394,6 +394,15 @@ class acp_groups
}
}
+ // Validate the length of "Maximum number of allowed recipients per private message" setting.
+ // We use 16777215 as a maximum because it matches MySQL unsigned mediumint maximum value
+ // which is the lowest amongst DBMSes supported by phpBB3
+ if ($max_recipients_error = validate_data($submit_ary, array('max_recipients' => array('num', false, 0, 16777215))))
+ {
+ // Replace "error" string with its real, localised form
+ $error = array_merge($error, array_map(array(&$user, 'lang'), $max_recipients_error));
+ }
+
if (!sizeof($error))
{
// Only set the rank, colour, etc. if it's changed or if we're adding a new
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
index 3204e0204e..b0ce8f1084 100644
--- a/phpBB/includes/acp/acp_update.php
+++ b/phpBB/includes/acp/acp_update.php
@@ -51,6 +51,14 @@ class acp_update
$announcement_url = (strpos($announcement_url, '&amp;') === false) ? str_replace('&', '&amp;', $announcement_url) : $announcement_url;
$update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update');
+ // next feature release
+ $next_feature_version = $next_feature_announcement_url = false;
+ if (isset($info[2]) && trim($info[2]) !== '')
+ {
+ $next_feature_version = trim($info[2]);
+ $next_feature_announcement_url = trim($info[3]);
+ }
+
// Determine automatic update...
$sql = 'SELECT config_value
FROM ' . CONFIG_TABLE . "
@@ -74,8 +82,10 @@ class acp_update
'LATEST_VERSION' => $latest_version,
'CURRENT_VERSION' => $config['version'],
'AUTO_VERSION' => $version_update_from,
+ 'NEXT_FEATURE_VERSION' => $next_feature_version,
'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $announcement_url, $update_link),
+ 'UPGRADE_INSTRUCTIONS' => $next_feature_version ? $user->lang('UPGRADE_INSTRUCTIONS', $next_feature_version, $next_feature_announcement_url) : false,
));
}
}
diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php
index 73c4f92976..e04a6307e9 100644
--- a/phpBB/includes/auth/auth_db.php
+++ b/phpBB/includes/auth/auth_db.php
@@ -134,7 +134,8 @@ function login_db(&$username, &$password)
// increase login attempt count to make sure this cannot be exploited
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . $row['user_id'];
+ WHERE user_id = ' . (int) $row['user_id'] . '
+ AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
$db->sql_query($sql);
return array(
@@ -194,7 +195,8 @@ function login_db(&$username, &$password)
// Password incorrect - increase login attempts
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . $row['user_id'];
+ WHERE user_id = ' . (int) $row['user_id'] . '
+ AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
$db->sql_query($sql);
// Give status about wrong password...
diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
index 0f0bfc4156..ea171dbe2c 100644
--- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
+++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
@@ -314,10 +314,7 @@ class phpbb_recaptcha extends phpbb_default_captcha
}
else
{
- if ($answers[1] === 'incorrect-captcha-sol')
- {
- return $user->lang['RECAPTCHA_INCORRECT'];
- }
+ return $user->lang['RECAPTCHA_INCORRECT'];
}
}
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index ff572869e2..ebaa342f54 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -69,6 +69,10 @@ define('LOGIN_ERROR_ATTEMPTS', 13);
define('LOGIN_ERROR_EXTERNAL_AUTH', 14);
define('LOGIN_ERROR_PASSWORD_CONVERT', 15);
+// Maximum login attempts
+// The value is arbitrary, but it has to fit into the user_login_attempts field.
+define('LOGIN_ATTEMPTS_MAX', 100);
+
// Group settings
define('GROUP_OPEN', 0);
define('GROUP_CLOSED', 1);
diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php
index 44d5722e4f..7ed4146f27 100644
--- a/phpBB/includes/db/mssqlnative.php
+++ b/phpBB/includes/db/mssqlnative.php
@@ -51,7 +51,6 @@ class result_mssqlnative
}
$this->m_row_count = count($this->m_rows);
- sqlsrv_free_stmt($queryresult);
}
private function array_to_obj($array, &$obj)
@@ -199,6 +198,7 @@ class dbal_mssqlnative extends dbal
{
var $m_insert_id = NULL;
var $last_query_text = '';
+ var $query_options = array();
/**
* Connect to server
@@ -308,10 +308,12 @@ class dbal_mssqlnative extends dbal
if ($this->query_result === false)
{
- if (($this->query_result = @sqlsrv_query($this->db_connect_id, $query)) === false)
+ if (($this->query_result = @sqlsrv_query($this->db_connect_id, $query, array(), $this->query_options)) === false)
{
$this->sql_error($query);
}
+ // reset options for next query
+ $this->query_options = array();
if (defined('DEBUG_EXTRA'))
{
@@ -347,7 +349,8 @@ class dbal_mssqlnative extends dbal
{
$this->query_result = false;
- if ($offset === false || $offset == 0)
+ // total == 0 means all results - not zero results
+ if ($offset == 0 && $total !== 0)
{
if (strpos($query, "SELECT") === false)
{
@@ -358,13 +361,21 @@ class dbal_mssqlnative extends dbal
$query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query);
}
}
- else
+ else if ($offset > 0)
{
$query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query);
$query = 'SELECT *
FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3
- FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3
- WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total);
+ FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3';
+
+ if ($total > 0)
+ {
+ $query .= ' WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total);
+ }
+ else
+ {
+ $query .= ' WHERE line3 > ' . $offset;
+ }
}
$result = $this->sql_query($query, $cache_ttl);
@@ -404,13 +415,18 @@ class dbal_mssqlnative extends dbal
$row = @sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC);
- // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug
if ($row)
{
foreach ($row as $key => $value)
{
$row[$key] = ($value === ' ' || $value === NULL) ? '' : $value;
}
+
+ // remove helper values from LIMIT queries
+ if (isset($row['line2']))
+ {
+ unset($row['line2'], $row['line3']);
+ }
}
return $row;
}
@@ -598,20 +614,28 @@ class dbal_mssqlnative extends dbal
* Utility method used to retrieve number of rows
* Emulates mysql_num_rows
* Used in acp_database.php -> write_data_mssqlnative()
+ * Requires a static or keyset cursor to be definde via
+ * mssqlnative_set_query_options()
*/
function mssqlnative_num_rows($res)
{
if ($res !== false)
{
- $row = new result_mssqlnative($res);
- $num_rows = $row->num_rows();
- return $num_rows;
+ return sqlsrv_num_rows($res);
}
else
{
return false;
}
}
+
+ /**
+ * Allows setting mssqlnative specific query options passed to sqlsrv_query as 4th parameter.
+ */
+ function mssqlnative_set_query_options($options)
+ {
+ $this->query_options = $options;
+ }
}
-?> \ No newline at end of file
+?>
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 9aec98dce2..561a9906c4 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -1052,7 +1052,7 @@ function phpbb_own_realpath($path)
// @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
// because we must be inside that basedir, the question is where...
// @internal The slash in is_dir() gets around an open_basedir restriction
- if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved)))
+ if (!@file_exists($resolved) || (!@is_dir($resolved . '/') && !is_file($resolved)))
{
return false;
}
@@ -4466,7 +4466,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_ENABLE_FEEDS_TOPICS_ACTIVE' => ($config['feed_topics_active']) ? true : false,
'S_ENABLE_FEEDS_NEWS' => ($s_feed_news) ? true : false,
- 'S_LOAD_UNREADS' => ($config['load_unreads_search']) ? true : false,
+ 'S_LOAD_UNREADS' => ($config['load_unreads_search'] && ($config['load_anon_lastread'] || $user->data['is_registered'])) ? true : false,
'T_THEME_PATH' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme',
'T_TEMPLATE_PATH' => "{$web_path}styles/" . $user->theme['template_path'] . '/template',
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 3178d35c34..2aa12adb2e 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -3299,7 +3299,7 @@ function obtain_latest_version_info($force_update = false, $warn_fail = false, $
$errstr = '';
$errno = 0;
- $info = get_remote_file('www.phpbb.com', '/updatecheck',
+ $info = get_remote_file('version.phpbb.com', '/phpbb',
((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
if ($info === false)
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index bb0d88ec1b..b5c87094c0 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -632,6 +632,64 @@ class queue
}
/**
+ * Obtains exclusive lock on queue cache file.
+ * Returns resource representing the lock
+ */
+ function lock()
+ {
+ // For systems that can't have two processes opening
+ // one file for writing simultaneously
+ if (file_exists($this->cache_file . '.lock'))
+ {
+ $mode = 'rb';
+ }
+ else
+ {
+ $mode = 'wb';
+ }
+
+ $lock_fp = @fopen($this->cache_file . '.lock', $mode);
+
+ if ($mode == 'wb')
+ {
+ if (!$lock_fp)
+ {
+ // Two processes may attempt to create lock file at the same time.
+ // Have the losing process try opening the lock file again for reading
+ // on the assumption that the winning process created it
+ $mode = 'rb';
+ $lock_fp = @fopen($this->cache_file . '.lock', $mode);
+ }
+ else
+ {
+ // Only need to set mode when the lock file is written
+ @chmod($this->cache_file . '.lock', 0666);
+ }
+ }
+
+ if ($lock_fp)
+ {
+ @flock($lock_fp, LOCK_EX);
+ }
+
+ return $lock_fp;
+ }
+
+ /**
+ * Releases lock on queue cache file, using resource obtained from lock()
+ */
+ function unlock($lock_fp)
+ {
+ // lock() will return null if opening lock file, and thus locking, failed.
+ // Accept null values here so that client code does not need to check them
+ if ($lock_fp)
+ {
+ @flock($lock_fp, LOCK_UN);
+ fclose($lock_fp);
+ }
+ }
+
+ /**
* Process queue
* Using lock file
*/
@@ -639,24 +697,16 @@ class queue
{
global $db, $config, $phpEx, $phpbb_root_path, $user;
- set_config('last_queue_run', time(), true);
+ $lock_fp = $this->lock();
- // Delete stale lock file
- if (file_exists($this->cache_file . '.lock') && !file_exists($this->cache_file))
- {
- @unlink($this->cache_file . '.lock');
- return;
- }
+ set_config('last_queue_run', time(), true);
- if (!file_exists($this->cache_file) || (file_exists($this->cache_file . '.lock') && filemtime($this->cache_file) > time() - $config['queue_interval']))
+ if (!file_exists($this->cache_file) || filemtime($this->cache_file) > time() - $config['queue_interval'])
{
+ $this->unlock($lock_fp);
return;
}
- $fp = @fopen($this->cache_file . '.lock', 'wb');
- fclose($fp);
- @chmod($this->cache_file . '.lock', 0777);
-
include($this->cache_file);
foreach ($this->queue_data as $object => $data_ary)
@@ -720,6 +770,7 @@ class queue
break;
default:
+ $this->unlock($lock_fp);
return;
}
@@ -745,8 +796,6 @@ class queue
if (!$result)
{
- @unlink($this->cache_file . '.lock');
-
messenger::error('EMAIL', $err_msg);
continue 2;
}
@@ -790,16 +839,14 @@ class queue
{
if ($fp = @fopen($this->cache_file, 'wb'))
{
- @flock($fp, LOCK_EX);
fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>");
- @flock($fp, LOCK_UN);
fclose($fp);
phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
}
}
- @unlink($this->cache_file . '.lock');
+ $this->unlock($lock_fp);
}
/**
@@ -812,6 +859,8 @@ class queue
return;
}
+ $lock_fp = $this->lock();
+
if (file_exists($this->cache_file))
{
include($this->cache_file);
@@ -831,13 +880,13 @@ class queue
if ($fp = @fopen($this->cache_file, 'w'))
{
- @flock($fp, LOCK_EX);
fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>");
- @flock($fp, LOCK_UN);
fclose($fp);
phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE);
}
+
+ $this->unlock($lock_fp);
}
}
diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php
index 3937cf9c21..78fe049f40 100644
--- a/phpBB/includes/functions_profile_fields.php
+++ b/phpBB/includes/functions_profile_fields.php
@@ -878,6 +878,11 @@ class custom_profile
$now = getdate();
$row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']);
}
+ else if ($row['field_default_value'] === '' && $row['field_type'] == FIELD_INT)
+ {
+ // We cannot insert an empty string into an integer column.
+ $row['field_default_value'] = NULL;
+ }
$cp_data['pf_' . $row['field_ident']] = (in_array($row['field_type'], array(FIELD_TEXT, FIELD_STRING))) ? $row['lang_default_value'] : $row['field_default_value'];
}
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index 0be3a10e5f..29cdd8ee9a 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -919,6 +919,14 @@ class fulltext_mysql extends search_backend
<dt><label>' . $user->lang['FULLTEXT_MYSQL_MBSTRING'] . '</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MBSTRING_EXPLAIN'] . '</span></dt>
<dd>' . (($this->mbstring_regex) ? $user->lang['YES'] : $user->lang['NO']). '</dd>
</dl>
+ <dl>
+ <dt><label>' . $user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
+ <dd>' . $config['fulltext_mysql_min_word_len'] . '</dd>
+ </dl>
+ <dl>
+ <dt><label>' . $user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
+ <dd>' . $config['fulltext_mysql_max_word_len'] . '</dd>
+ </dl>
';
// These are fields required in the config table
diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php
index 03a4c81f46..d19b80f4c0 100644
--- a/phpBB/includes/ucp/info/ucp_profile.php
+++ b/phpBB/includes/ucp/info/ucp_profile.php
@@ -22,7 +22,7 @@ class ucp_profile_info
'modes' => array(
'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => '', 'cat' => array('UCP_PROFILE')),
'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => '', 'cat' => array('UCP_PROFILE')),
- 'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => '', 'cat' => array('UCP_PROFILE')),
+ 'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => 'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)', 'cat' => array('UCP_PROFILE')),
'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')),
),
);
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index ca4ef817be..e65237266b 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -1698,6 +1698,14 @@ function change_database_data(&$no_updates, $version)
_add_modules($modules_to_install);
+ // update
+ $sql = 'UPDATE ' . MODULES_TABLE . '
+ SET module_auth = \'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)\'
+ WHERE module_class = \'ucp\'
+ AND module_basename = \'profile\'
+ AND module_mode = \'avatar\'';
+ _sql($sql, $errored, $error_ary);
+
// add Bing Bot
$sql = 'SELECT group_id, group_colour
FROM ' . GROUPS_TABLE . "
diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php
index 77deba6e19..e76009a063 100644
--- a/phpBB/language/en/acp/board.php
+++ b/phpBB/language/en/acp/board.php
@@ -233,7 +233,7 @@ $lang = array_merge($lang, array(
'PASSWORD_LENGTH' => 'Password length',
'PASSWORD_LENGTH_EXPLAIN' => 'Minimum and maximum number of characters in passwords.',
'REG_LIMIT' => 'Registration attempts',
- 'REG_LIMIT_EXPLAIN' => 'Number of attempts users can make at the confirmation code before being locked out that session.',
+ 'REG_LIMIT_EXPLAIN' => 'Number of attempts users can make at solving the anti-spambot task before being locked out of that session.',
'USERNAME_ALPHA_ONLY' => 'Alphanumeric only',
'USERNAME_ALPHA_SPACERS' => 'Alphanumeric and spacers',
'USERNAME_ASCII' => 'ASCII (no international unicode)',
@@ -288,44 +288,44 @@ $lang = array_merge($lang, array(
// Visual Confirmation Settings
$lang = array_merge($lang, array(
- 'ACP_VC_SETTINGS_EXPLAIN' => 'Here you can select and configure CAPTCHA plugins, which implement various ways to reject registration attempts from so-called spambots.',
+ 'ACP_VC_SETTINGS_EXPLAIN' => 'Here you can select and configure plugins, which are designed to block automated form submissions by spambots. These plugins typically work by challenging the user with a <em>CAPTCHA</em>, a test which is designed to be difficult for computers to solve.',
'AVAILABLE_CAPTCHAS' => 'Available plugins',
- 'CAPTCHA_UNAVAILABLE' => 'The CAPTCHA cannot be selected as its requirements are not met.',
- 'CAPTCHA_GD' => 'GD CAPTCHA',
- 'CAPTCHA_GD_3D' => 'GD 3D Captcha',
- 'CAPTCHA_GD_FOREGROUND_NOISE' => 'GD CAPTCHA foreground noise',
- 'CAPTCHA_GD_EXPLAIN' => 'Use GD to make a more advanced CAPTCHA.',
- 'CAPTCHA_GD_FOREGROUND_NOISE_EXPLAIN' => 'Use foreground noise to make the GD based CAPTCHA harder.',
- 'CAPTCHA_GD_X_GRID' => 'GD CAPTCHA background noise x-axis',
- 'CAPTCHA_GD_X_GRID_EXPLAIN' => 'Use lower settings of this to make the GD based CAPTCHA harder. 0 will disable x-axis background noise.',
- 'CAPTCHA_GD_Y_GRID' => 'GD CAPTCHA background noise y-axis',
- 'CAPTCHA_GD_Y_GRID_EXPLAIN' => 'Use lower settings of this to make the GD based CAPTCHA harder. 0 will disable y-axis background noise.',
- 'CAPTCHA_GD_WAVE' => 'GD CAPTCHA wave distortion',
- 'CAPTCHA_GD_WAVE_EXPLAIN' => 'This applies a wave distortion to the CAPTCHA.',
+ 'CAPTCHA_UNAVAILABLE' => 'The plugin cannot be selected as its requirements are not met.',
+ 'CAPTCHA_GD' => 'GD image',
+ 'CAPTCHA_GD_3D' => 'GD 3D image',
+ 'CAPTCHA_GD_FOREGROUND_NOISE' => 'Foreground noise',
+ 'CAPTCHA_GD_EXPLAIN' => 'Uses GD to make a more advanced anti-spambot image.',
+ 'CAPTCHA_GD_FOREGROUND_NOISE_EXPLAIN' => 'Use foreground noise to make the image harder to read.',
+ 'CAPTCHA_GD_X_GRID' => 'Background noise x-axis',
+ 'CAPTCHA_GD_X_GRID_EXPLAIN' => 'Use lower settings of this to make the image harder to read. 0 will disable x-axis background noise.',
+ 'CAPTCHA_GD_Y_GRID' => 'Background noise y-axis',
+ 'CAPTCHA_GD_Y_GRID_EXPLAIN' => 'Use lower settings of this to make the image harder to read. 0 will disable y-axis background noise.',
+ 'CAPTCHA_GD_WAVE' => 'Wave distortion',
+ 'CAPTCHA_GD_WAVE_EXPLAIN' => 'This applies a wave distortion to the image.',
'CAPTCHA_GD_3D_NOISE' => 'Add 3D-noise objects',
- 'CAPTCHA_GD_3D_NOISE_EXPLAIN' => 'This adds additional objects to the CAPTCHA, over the letters.',
+ 'CAPTCHA_GD_3D_NOISE_EXPLAIN' => 'This adds additional objects to the image, over the letters.',
'CAPTCHA_GD_FONTS' => 'Use different fonts',
'CAPTCHA_GD_FONTS_EXPLAIN' => 'This setting controls how many different letter shapes are used. You can just use the default shapes or introduce altered letters. Adding lowercase letters is also possible.',
'CAPTCHA_FONT_DEFAULT' => 'Default',
'CAPTCHA_FONT_NEW' => 'New Shapes',
'CAPTCHA_FONT_LOWER' => 'Also use lowercase',
- 'CAPTCHA_NO_GD' => 'CAPTCHA without GD',
- 'CAPTCHA_PREVIEW_MSG' => 'Your changes to the visual confirmation setting were not saved. This is just a preview.',
- 'CAPTCHA_PREVIEW_EXPLAIN' => 'The CAPTCHA as it would look like using the current selection.',
-
- 'CAPTCHA_SELECT' => 'Installed CAPTCHA plugins',
- 'CAPTCHA_SELECT_EXPLAIN' => 'The dropdown holds the CAPTCHA plugins recognized by the board. Gray entries are not available right now and might need configuration prior to use.',
- 'CAPTCHA_CONFIGURE' => 'Configure CAPTCHAs',
- 'CAPTCHA_CONFIGURE_EXPLAIN' => 'Change the settings for the selected CAPTCHA.',
+ 'CAPTCHA_NO_GD' => 'Simple image',
+ 'CAPTCHA_PREVIEW_MSG' => 'Your changes have not been saved, this is just a preview.',
+ 'CAPTCHA_PREVIEW_EXPLAIN' => 'The plugin as it would look like using the current selection.',
+
+ 'CAPTCHA_SELECT' => 'Installed plugins',
+ 'CAPTCHA_SELECT_EXPLAIN' => 'The dropdown holds the plugins recognized by the board. Grey entries are not available right now and might need configuration prior to use.',
+ 'CAPTCHA_CONFIGURE' => 'Configure plugins',
+ 'CAPTCHA_CONFIGURE_EXPLAIN' => 'Change the settings for the selected plugin.',
'CONFIGURE' => 'Configure',
- 'CAPTCHA_NO_OPTIONS' => 'This CAPTCHA has no configuration options.',
-
- 'VISUAL_CONFIRM_POST' => 'Enable visual confirmation for guest postings',
- 'VISUAL_CONFIRM_POST_EXPLAIN' => 'Requires anonymous users to enter a random code matching an image to help prevent mass postings.',
- 'VISUAL_CONFIRM_REG' => 'Enable visual confirmation for registrations',
- 'VISUAL_CONFIRM_REG_EXPLAIN' => 'Requires new users to enter a random code matching an image to help prevent mass registrations.',
- 'VISUAL_CONFIRM_REFRESH' => 'Enable users to refresh the confirmation image',
- 'VISUAL_CONFIRM_REFRESH_EXPLAIN' => 'Allows users to request new confirmation codes, if they are unable to solve the VC during registration. Some plugins might not support this option.',
+ 'CAPTCHA_NO_OPTIONS' => 'This plugin has no configuration options.',
+
+ 'VISUAL_CONFIRM_POST' => 'Enable spambot countermeasures for guest postings',
+ 'VISUAL_CONFIRM_POST_EXPLAIN' => 'Requires guest users to pass the anti-spambot task to help prevent automated postings.',
+ 'VISUAL_CONFIRM_REG' => 'Enable spambot countermeasures for registrations',
+ 'VISUAL_CONFIRM_REG_EXPLAIN' => 'Requires new users to pass the anti-spambot task to help prevent automated registrations.',
+ 'VISUAL_CONFIRM_REFRESH' => 'Allow users to refresh the anti-spambot task',
+ 'VISUAL_CONFIRM_REFRESH_EXPLAIN' => 'Allows users to request a new anti-spambot task if they are unable to solve the currunt task during registration. Some plugins might not support this option.',
));
// Cookie Settings
@@ -463,7 +463,7 @@ $lang = array_merge($lang, array(
'IP_VALID' => 'Session IP validation',
'IP_VALID_EXPLAIN' => 'Determines how much of the users IP is used to validate a session; <samp>All</samp> compares the complete address, <samp>A.B.C</samp> the first x.x.x, <samp>A.B</samp> the first x.x, <samp>None</samp> disables checking. On IPv6 addresses <samp>A.B.C</samp> compares the first 4 blocks and <samp>A.B</samp> the first 3 blocks.',
'MAX_LOGIN_ATTEMPTS' => 'Maximum number of login attempts',
- 'MAX_LOGIN_ATTEMPTS_EXPLAIN' => 'After this number of failed logins the user needs to additionally confirm his login visually (visual confirmation).',
+ 'MAX_LOGIN_ATTEMPTS_EXPLAIN' => 'After this number of failed logins the user needs to additionally solve the anti-spambot task.',
'NO_IP_VALIDATION' => 'None',
'NO_REF_VALIDATION' => 'None',
'PASSWORD_TYPE' => 'Password complexity',
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index bca19c7f12..2c549f8130 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -190,7 +190,7 @@ $lang = array_merge($lang, array(
'ACP_USER_SIG' => 'Signature',
'ACP_USER_WARNINGS' => 'Warnings',
- 'ACP_VC_SETTINGS' => 'CAPTCHA module settings',
+ 'ACP_VC_SETTINGS' => 'Spambot countermeasures',
'ACP_VC_CAPTCHA_DISPLAY' => 'CAPTCHA image preview',
'ACP_VERSION_CHECK' => 'Check for updates',
'ACP_VIEW_ADMIN_PERMISSIONS' => 'View administrative permissions',
@@ -503,7 +503,7 @@ $lang = array_merge($lang, array(
'LOG_CONFIG_SERVER' => '<strong>Altered server settings</strong>',
'LOG_CONFIG_SETTINGS' => '<strong>Altered board settings</strong>',
'LOG_CONFIG_SIGNATURE' => '<strong>Altered signature settings</strong>',
- 'LOG_CONFIG_VISUAL' => '<strong>Altered antibot settings</strong>',
+ 'LOG_CONFIG_VISUAL' => '<strong>Altered anti-spambot settings</strong>',
'LOG_APPROVE_TOPIC' => '<strong>Approved topic</strong><br />» %s',
'LOG_BUMP_TOPIC' => '<strong>User bumped topic</strong><br />» %s',
diff --git a/phpBB/language/en/acp/search.php b/phpBB/language/en/acp/search.php
index 88eed9d948..a7d687d7c2 100644
--- a/phpBB/language/en/acp/search.php
+++ b/phpBB/language/en/acp/search.php
@@ -59,6 +59,8 @@ $lang = array_merge($lang, array(
'FULLTEXT_MYSQL_PCRE' => 'Support for non-latin UTF-8 characters using PCRE:',
'FULLTEXT_MYSQL_MBSTRING_EXPLAIN' => 'If PCRE does not have unicode character properties, the search backend will try to use mbstring’s regular expression engine.',
'FULLTEXT_MYSQL_PCRE_EXPLAIN' => 'This search backend requires PCRE unicode character properties, only available in PHP 4.4, 5.1 and above, if you want to search for non-latin characters.',
+ 'FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN' => 'Words with at least this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
+ 'FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN' => 'Words with no more than this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
'GENERAL_SEARCH_SETTINGS' => 'General search settings',
'GO_TO_SEARCH_INDEX' => 'Go to search index page',
diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php
index 951c69f915..f161a7e6e6 100644
--- a/phpBB/language/en/acp/styles.php
+++ b/phpBB/language/en/acp/styles.php
@@ -76,13 +76,13 @@ $lang = array_merge($lang, array(
'DEACTIVATE_DEFAULT' => 'You cannot deactivate the default style.',
'DELETE_FROM_FS' => 'Delete from filesystem',
'DELETE_IMAGESET' => 'Delete imageset',
- 'DELETE_IMAGESET_EXPLAIN' => 'Here you can remove the selected imageset from the database. Additionally, if you have permission you can elect to remove the set from the filesystem. Please note that there is no undo capability. When the imageset is deleted it is gone for good. It is recommended that you first export your set for possible future use.',
+ 'DELETE_IMAGESET_EXPLAIN' => 'Here you can remove the selected imageset from the database. Please note that there is no undo capability. It is recommended that you first export your set for possible future use.',
'DELETE_STYLE' => 'Delete style',
- 'DELETE_STYLE_EXPLAIN' => 'Here you can remove the selected style. You cannot remove all the style elements from here. These must be deleted individually via their respective forms. Take care in deleting styles there is no undo facility.',
+ 'DELETE_STYLE_EXPLAIN' => 'Here you can remove the selected style. You cannot remove all the style elements from here. These must be deleted individually via their respective forms. Take care when deleting styles, there is no undo facility.',
'DELETE_TEMPLATE' => 'Delete template',
- 'DELETE_TEMPLATE_EXPLAIN' => 'Here you can remove the selected template set from the database. Additionally, if you have permission you can elect to remove the set from the filesystem. Please note that there is no undo capability. When the templates are deleted they are gone for good. It is recommended that you first export your set for possible future use.',
+ 'DELETE_TEMPLATE_EXPLAIN' => 'Here you can remove the selected template set from the database. Please note that there is no undo capability. It is recommended that you first export your set for possible future use.',
'DELETE_THEME' => 'Delete theme',
- 'DELETE_THEME_EXPLAIN' => 'Here you can remove the selected theme from the database. Additionally, if you have permission you can elect to remove the theme from the filesystem. Please note that there is no undo capability. When the theme is deleted it is gone for good. It is recommended that you first export your theme for possible future use.',
+ 'DELETE_THEME_EXPLAIN' => 'Here you can remove the selected theme from the database. Please note that there is no undo capability. It is recommended that you first export your theme for possible future use.',
'DETAILS' => 'Details',
'DIMENSIONS_EXPLAIN' => 'Selecting yes here will include width/height parameters.',
diff --git a/phpBB/language/en/captcha_qa.php b/phpBB/language/en/captcha_qa.php
index 5cd822b3c4..42c8df2d6d 100644
--- a/phpBB/language/en/captcha_qa.php
+++ b/phpBB/language/en/captcha_qa.php
@@ -36,9 +36,9 @@ if (empty($lang) || !is_array($lang))
// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
$lang = array_merge($lang, array(
- 'CAPTCHA_QA' => 'Q&amp;A CAPTCHA',
- 'CONFIRM_QUESTION_EXPLAIN' => 'This question is a means of identifying and preventing automated submissions.',
- 'CONFIRM_QUESTION_WRONG' => 'You have provided an invalid answer to the confirmation question.',
+ 'CAPTCHA_QA' => 'Q&amp;A',
+ 'CONFIRM_QUESTION_EXPLAIN' => 'This question is a means of preventing automated form submissions by spambots.',
+ 'CONFIRM_QUESTION_WRONG' => 'You have provided an invalid answer to the question.',
'QUESTION_ANSWERS' => 'Answers',
'ANSWERS_EXPLAIN' => 'Please enter valid answers to the question, one per line.',
@@ -47,15 +47,15 @@ $lang = array_merge($lang, array(
'ANSWER' => 'Answer',
'EDIT_QUESTION' => 'Edit Question',
'QUESTIONS' => 'Questions',
- 'QUESTIONS_EXPLAIN' => 'During registration, users will be asked one of the questions specified here. To use this plugin, at least one question must be set in the default language. These questions should be easy for your target audience to answer, but beyond the ability of a bot capable of running a Googleâ„¢ search. Using a large and regulary changed set of questions will yield the best results. Enable the strict setting if your question relies on punctuation or capitalisation.',
+ 'QUESTIONS_EXPLAIN' => 'For every form submission where you have enabled the Q&amp;A plugin, users will be asked one of the questions specified here. To use this plugin at least one question must be set in the default language. These questions should be easy for your target audience to answer but beyond the ability of a bot capable of running a Googleâ„¢ search. Using a large and regularly changed set of questions will yield the best results. Enable the strict setting if your question relies on mixed case, punctuation or whitespace.',
'QUESTION_DELETED' => 'Question deleted',
'QUESTION_LANG' => 'Language',
- 'QUESTION_LANG_EXPLAIN' => 'The language that this question and its answers are written in.',
+ 'QUESTION_LANG_EXPLAIN' => 'The language this question and its answers are written in.',
'QUESTION_STRICT' => 'Strict check',
- 'QUESTION_STRICT_EXPLAIN' => 'If enabled, capitalisation and whitespace will also be enforced.',
+ 'QUESTION_STRICT_EXPLAIN' => 'Enable to enforce mixed case, punctuation and whitespace.',
'QUESTION_TEXT' => 'Question',
- 'QUESTION_TEXT_EXPLAIN' => 'The question that will be asked on registration.',
+ 'QUESTION_TEXT_EXPLAIN' => 'The question presented to the user.',
'QA_ERROR_MSG' => 'Please fill in all fields and enter at least one answer.',
'QA_LAST_QUESTION' => 'You cannot delete all questions while the plugin is active.',
diff --git a/phpBB/language/en/captcha_recaptcha.php b/phpBB/language/en/captcha_recaptcha.php
index 897e8a4979..463bfffe0d 100644
--- a/phpBB/language/en/captcha_recaptcha.php
+++ b/phpBB/language/en/captcha_recaptcha.php
@@ -46,7 +46,7 @@ $lang = array_merge($lang, array(
'RECAPTCHA_PRIVATE' => 'Private reCaptcha key',
'RECAPTCHA_PRIVATE_EXPLAIN' => 'Your private reCaptcha key. Keys can be obtained on <a href="http://recaptcha.net">reCaptcha.net</a>.',
- 'RECAPTCHA_EXPLAIN' => 'In an effort to prevent automatic submissions, we require that you enter both of the words displayed below into the text field underneath.',
+ 'RECAPTCHA_EXPLAIN' => 'In an effort to prevent automatic submissions, we require that you enter both of the words displayed into the text field underneath.',
));
?> \ No newline at end of file
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index bc38c1563d..db60cbf227 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -304,8 +304,8 @@ $lang = array_merge($lang, array(
'LOGIN' => 'Login',
'LOGIN_CHECK_PM' => 'Log in to check your private messages.',
'LOGIN_CONFIRMATION' => 'Confirmation of login',
- 'LOGIN_CONFIRM_EXPLAIN' => 'To prevent brute forcing accounts the board requires you to enter a confirmation code after a maximum amount of failed logins. The code is displayed in the image you should see below. If you are visually impaired or cannot otherwise read this code please contact the %sBoard Administrator%s.',
- 'LOGIN_ERROR_ATTEMPTS' => 'You exceeded the maximum allowed number of login attempts. In addition to your username and password you now also have to enter the confirm code from the image you see below.',
+ 'LOGIN_CONFIRM_EXPLAIN' => 'To prevent brute forcing accounts the board requires you to enter a confirmation code after a maximum amount of failed logins. The code is displayed in the image you should see below. If you are visually impaired or cannot otherwise read this code please contact the %sBoard Administrator%s.', // unused
+ 'LOGIN_ERROR_ATTEMPTS' => 'You exceeded the maximum allowed number of login attempts. In addition to your username and password you now also have to solve the CAPTCHA below.',
'LOGIN_ERROR_EXTERNAL_AUTH_APACHE' => 'You have not been authenticated by Apache.',
'LOGIN_ERROR_PASSWORD' => 'You have specified an incorrect password. Please check your password and try again. If you continue to have problems please contact the %sBoard Administrator%s.',
'LOGIN_ERROR_PASSWORD_CONVERT' => 'It was not possible to convert your password when updating this bulletin board’s software. Please %srequest a new password%s. If you continue to have problems please contact the %sBoard Administrator%s.',
@@ -566,6 +566,9 @@ $lang = array_merge($lang, array(
'TEST_CONNECTION' => 'Test connection',
'THE_TEAM' => 'The team',
'TIME' => 'Time',
+
+ 'TOO_LARGE' => 'The value you entered is too large.',
+ 'TOO_LARGE_MAX_RECIPIENTS' => 'The value of <strong>Maximum number of allowed recipients per private message</strong> setting you entered is too large.',
'TOO_LONG' => 'The value you entered is too long.',
@@ -608,6 +611,9 @@ $lang = array_merge($lang, array(
'TOO_SHORT_EMAIL_CONFIRM' => 'The e-mail address confirmation you entered is too short.',
'TOO_SHORT_WEBSITE' => 'The website address you entered is too short.',
'TOO_SHORT_YIM' => 'The Yahoo! Messenger name you entered is too short.',
+
+ 'TOO_SMALL' => 'The value you entered is too small.',
+ 'TOO_SMALL_MAX_RECIPIENTS' => 'The value of <strong>Maximum number of allowed recipients per private message</strong> setting you entered is too small.',
'TOPIC' => 'Topic',
'TOPICS' => 'Topics',
diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php
index 4e58de8d90..14923e836e 100644
--- a/phpBB/language/en/install.php
+++ b/phpBB/language/en/install.php
@@ -559,6 +559,7 @@ $lang = array_merge($lang, array(
'UPDATING_DATA' => 'Updating data',
'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release',
'UPDATED_VERSION' => 'Updated version',
+ 'UPGRADE_INSTRUCTIONS' => 'A new feature release <strong>%1$s</strong> is available. Please read <a href="%2$s" title="%2$s"><strong>the release announcement</strong></a> to learn about what it has to offer, and how to upgrade.',
'UPLOAD_METHOD' => 'Upload method',
'UPDATE_DB_SUCCESS' => 'Database update was successful.',
diff --git a/phpBB/posting.php b/phpBB/posting.php
index 853ac18aad..f775699cee 100644
--- a/phpBB/posting.php
+++ b/phpBB/posting.php
@@ -1300,7 +1300,7 @@ $attachment_data = $message_parser->attachment_data;
$filename_data = $message_parser->filename_data;
$post_data['post_text'] = $message_parser->message;
-if (sizeof($post_data['poll_options']) || $post_data['poll_title'])
+if (sizeof($post_data['poll_options']) || !empty($post_data['poll_title']))
{
$message_parser->message = $post_data['poll_title'];
$message_parser->bbcode_uid = $post_data['bbcode_uid'];
diff --git a/phpBB/styles/prosilver/template/captcha_recaptcha.html b/phpBB/styles/prosilver/template/captcha_recaptcha.html
index 97d2cda28e..51a1615bd5 100644
--- a/phpBB/styles/prosilver/template/captcha_recaptcha.html
+++ b/phpBB/styles/prosilver/template/captcha_recaptcha.html
@@ -16,6 +16,7 @@
// <![CDATA[
var RecaptchaOptions = {
lang : '{LA_RECAPTCHA_LANG}',
+ theme : 'clean',
tabindex : <!-- IF $CAPTCHA_TAB_INDEX -->{$CAPTCHA_TAB_INDEX}<!-- ELSE -->10<!-- ENDIF -->
};
// ]]>
diff --git a/phpBB/styles/prosilver/template/index_body.html b/phpBB/styles/prosilver/template/index_body.html
index af2077141c..d4d50a11c0 100644
--- a/phpBB/styles/prosilver/template/index_body.html
+++ b/phpBB/styles/prosilver/template/index_body.html
@@ -6,7 +6,7 @@
<!-- IF S_DISPLAY_SEARCH or (S_USER_LOGGED_IN and not S_IS_BOT) -->
<ul class="linklist">
<!-- IF S_DISPLAY_SEARCH -->
- <li><a href="{U_SEARCH_UNANSWERED}">{L_SEARCH_UNANSWERED}</a><!-- IF S_USER_LOGGED_IN --><!-- IF S_LOAD_UNREADS --> &bull; <a href="{U_SEARCH_UNREAD}">{L_SEARCH_UNREAD}</a><!-- ENDIF --> &bull; <a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a><!-- ENDIF --> &bull; <a href="{U_SEARCH_ACTIVE_TOPICS}">{L_SEARCH_ACTIVE_TOPICS}</a></li>
+ <li><a href="{U_SEARCH_UNANSWERED}">{L_SEARCH_UNANSWERED}</a><!-- IF S_LOAD_UNREADS --> &bull; <a href="{U_SEARCH_UNREAD}">{L_SEARCH_UNREAD}</a><!-- ENDIF --><!-- IF S_USER_LOGGED_IN --> &bull; <a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a><!-- ENDIF --> &bull; <a href="{U_SEARCH_ACTIVE_TOPICS}">{L_SEARCH_ACTIVE_TOPICS}</a></li>
<!-- ENDIF -->
<!-- IF not S_IS_BOT and U_MARK_FORUMS --><li class="rightside"><a href="{U_MARK_FORUMS}" accesskey="m">{L_MARK_FORUMS_READ}</a></li><!-- ENDIF -->
</ul>
diff --git a/phpBB/styles/prosilver/template/login_body.html b/phpBB/styles/prosilver/template/login_body.html
index e52ccd6434..26e425a1d0 100644
--- a/phpBB/styles/prosilver/template/login_body.html
+++ b/phpBB/styles/prosilver/template/login_body.html
@@ -1,5 +1,11 @@
<!-- INCLUDE overall_header.html -->
+<script type="text/javascript">
+// <![CDATA[
+ onload_functions.push('document.getElementById("{USERNAME_CREDENTIAL}").focus();');
+// ]]>
+</script>
+
<form action="{S_LOGIN_ACTION}" method="post" id="login">
<div class="panel">
<div class="inner"><span class="corners-top"><span></span></span>
diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html
index dab2d572a9..04e24cd1f9 100644
--- a/phpBB/styles/prosilver/template/mcp_post.html
+++ b/phpBB/styles/prosilver/template/mcp_post.html
@@ -54,7 +54,7 @@
</ul>
<!-- ENDIF -->
- <span class="right-box clear" id="expand"><a href="#post_details" onclick="viewableArea(getElementById('post_details'), true); var rev_text = getElementById('expand').getElementsByTagName('a').item(0).firstChild; if (rev_text.data == '{LA_EXPAND_VIEW}'){rev_text.data = '{LA_COLLAPSE_VIEW}'; } else if (rev_text.data == '{LA_COLLAPSE_VIEW}'){rev_text.data = '{LA_EXPAND_VIEW}'}; return false;">{L_EXPAND_VIEW}</a></span>
+ <span class="right-box" id="expand"><a href="#post_details" onclick="viewableArea(getElementById('post_details'), true); var rev_text = getElementById('expand').getElementsByTagName('a').item(0).firstChild; if (rev_text.data == '{LA_EXPAND_VIEW}'){rev_text.data = '{LA_COLLAPSE_VIEW}'; } else if (rev_text.data == '{LA_COLLAPSE_VIEW}'){rev_text.data = '{LA_EXPAND_VIEW}'}; return false;">{L_EXPAND_VIEW}</a></span>
<h3><a href="{U_VIEW_POST}">{POST_SUBJECT}</a></h3>
<!-- IF S_PM -->
diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html
index 8f4ac19fb8..44857dbc41 100644
--- a/phpBB/styles/prosilver/template/overall_header.html
+++ b/phpBB/styles/prosilver/template/overall_header.html
@@ -11,7 +11,7 @@
<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" />
<meta name="keywords" content="" />
<meta name="description" content="" />
-<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9" />
{META}
<title>{SITENAME} &bull; <!-- IF S_IN_MCP -->{L_MCP} &bull; <!-- ELSEIF S_IN_UCP -->{L_UCP} &bull; <!-- ENDIF -->{PAGE_TITLE}</title>
diff --git a/phpBB/styles/prosilver/template/posting_buttons.html b/phpBB/styles/prosilver/template/posting_buttons.html
index 4d866681f0..5d21229611 100644
--- a/phpBB/styles/prosilver/template/posting_buttons.html
+++ b/phpBB/styles/prosilver/template/posting_buttons.html
@@ -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="t" name="addlitsitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}" />
+ <input type="button" class="button2" accesskey="y" name="addlitsitem" 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/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html
index 9476242d11..5f7fb8408e 100644
--- a/phpBB/styles/prosilver/template/posting_editor.html
+++ b/phpBB/styles/prosilver/template/posting_editor.html
@@ -187,8 +187,8 @@
<fieldset class="submit-buttons">
{S_HIDDEN_ADDRESS_FIELD}
{S_HIDDEN_FIELDS}
- <!-- IF S_HAS_DRAFTS --><input type="submit" accesskey="d" tabindex="8" name="load" value="{L_LOAD}" class="button2" onclick="load_draft = true;" />&nbsp; <!-- ENDIF -->
- <!-- IF S_SAVE_ALLOWED --><input type="submit" accesskey="k" tabindex="7" name="save" value="{L_SAVE}" class="button2" />&nbsp; <!-- ENDIF -->
+ <!-- IF S_HAS_DRAFTS --><input type="submit" accesskey="d" tabindex="8" name="load" value="{L_LOAD_DRAFT}" class="button2" onclick="load_draft = true;" />&nbsp; <!-- ENDIF -->
+ <!-- IF S_SAVE_ALLOWED --><input type="submit" accesskey="k" tabindex="7" name="save" value="{L_SAVE_DRAFT}" class="button2" />&nbsp; <!-- ENDIF -->
<input type="submit" tabindex="5" name="preview" value="{L_PREVIEW}" class="button1"<!-- IF not S_PRIVMSGS --> onclick="document.getElementById('postform').action += '#preview';"<!-- ENDIF --> />&nbsp;
<input type="submit" accesskey="s" tabindex="6" name="post" value="{L_SUBMIT}" class="button1 default-submit-action" />&nbsp;
diff --git a/phpBB/styles/prosilver/template/search_body.html b/phpBB/styles/prosilver/template/search_body.html
index 612641b141..6616b95a73 100644
--- a/phpBB/styles/prosilver/template/search_body.html
+++ b/phpBB/styles/prosilver/template/search_body.html
@@ -1,5 +1,11 @@
<!-- INCLUDE overall_header.html -->
+<script type="text/javascript">
+// <![CDATA[
+ onload_functions.push('document.getElementById("keywords").focus();');
+// ]]>
+</script>
+
<h2 class="solo">{L_SEARCH}</h2>
<form method="get" action="{S_SEARCH_ACTION}">
@@ -119,4 +125,4 @@
</div>
<!-- ENDIF -->
-<!-- INCLUDE overall_footer.html --> \ No newline at end of file
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css
index dfe00371e4..64beb97a37 100644
--- a/phpBB/styles/prosilver/theme/content.css
+++ b/phpBB/styles/prosilver/theme/content.css
@@ -307,6 +307,11 @@ div[class].topic-actions {
max-height: 300px;
}
+#expand
+{
+ clear: both;
+}
+
/* Content container styles
----------------------------------------*/
.content {
diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css
index 6dfb5c4726..68600b030b 100644
--- a/phpBB/styles/prosilver/theme/print.css
+++ b/phpBB/styles/prosilver/theme/print.css
@@ -140,3 +140,5 @@ div.spacer { clear: both; }
/* Accessibility tweaks: Mozilla.org */
.skip_link { display: none; }
+
+dl.codebox dt { display: none; } \ No newline at end of file
diff --git a/phpBB/styles/subsilver2/template/captcha_default.html b/phpBB/styles/subsilver2/template/captcha_default.html
index e0116ae42c..4c65f81643 100644
--- a/phpBB/styles/subsilver2/template/captcha_default.html
+++ b/phpBB/styles/subsilver2/template/captcha_default.html
@@ -1,9 +1,11 @@
<tr>
<th colspan="2" valign="middle">{L_CONFIRM_CODE}</th>
</tr>
+ <!-- IF S_TYPE == 1 -->
<tr>
<td class="row3" colspan="2"><span class="gensmall">{L_CONFIRM_EXPLAIN}</span></td>
</tr>
+ <!-- ENDIF -->
<tr>
<td class="row1" colspan="2" align="center"><img src="{CONFIRM_IMAGE_LINK}" alt="{L_CONFIRM_CODE}" />
<input type="hidden" name="confirm_id" id="confirm_id" value="{CONFIRM_ID}" /></td>
diff --git a/phpBB/styles/subsilver2/template/captcha_recaptcha.html b/phpBB/styles/subsilver2/template/captcha_recaptcha.html
index 3776c77ea4..ec09b28ef5 100644
--- a/phpBB/styles/subsilver2/template/captcha_recaptcha.html
+++ b/phpBB/styles/subsilver2/template/captcha_recaptcha.html
@@ -9,6 +9,7 @@
// <![CDATA[
var RecaptchaOptions = {
lang : '{LA_RECAPTCHA_LANG}',
+ theme : 'clean',
tabindex : <!-- IF $CAPTCHA_TAB_INDEX -->{$CAPTCHA_TAB_INDEX}<!-- ELSE -->10<!-- ENDIF -->
};
// ]]>
diff --git a/phpBB/styles/subsilver2/template/login_body.html b/phpBB/styles/subsilver2/template/login_body.html
index 503de9e69e..90bbf8c139 100644
--- a/phpBB/styles/subsilver2/template/login_body.html
+++ b/phpBB/styles/subsilver2/template/login_body.html
@@ -88,4 +88,21 @@
<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-<!-- INCLUDE overall_footer.html --> \ No newline at end of file
+<script type="text/javascript">
+// <![CDATA[
+ (function()
+ {
+ var elements = document.getElementsByName("{USERNAME_CREDENTIAL}");
+ for (var i = 0; i < elements.length; ++i)
+ {
+ if (elements[i].tagName.toLowerCase() == 'input')
+ {
+ elements[i].focus();
+ break;
+ }
+ }
+ })();
+// ]]>
+</script>
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html
index 37691d4f1c..874beb8e2b 100644
--- a/phpBB/styles/subsilver2/template/overall_header.html
+++ b/phpBB/styles/subsilver2/template/overall_header.html
@@ -11,7 +11,7 @@
<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" />
<meta name="keywords" content="" />
<meta name="description" content="" />
-<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9" />
{META}
<title>{SITENAME} &bull; <!-- IF S_IN_MCP -->{L_MCP} &bull; <!-- ELSEIF S_IN_UCP -->{L_UCP} &bull; <!-- ENDIF -->{PAGE_TITLE}</title>
@@ -201,8 +201,8 @@ function marklist(id, name, state)
<!-- IF S_DISPLAY_SEARCH -->
<p class="searchbar">
<span style="float: {S_CONTENT_FLOW_BEGIN};"><a href="{U_SEARCH_UNANSWERED}">{L_SEARCH_UNANSWERED}</a> | <a href="{U_SEARCH_ACTIVE_TOPICS}">{L_SEARCH_ACTIVE_TOPICS}</a></span>
- <!-- IF S_USER_LOGGED_IN -->
- <span style="float: {S_CONTENT_FLOW_END};"><!-- IF S_LOAD_UNREADS --><a href="{U_SEARCH_UNREAD}">{L_SEARCH_UNREAD}</a> | <!-- ENDIF --><a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a> | <a href="{U_SEARCH_SELF}">{L_SEARCH_SELF}</a></span>
+ <!-- IF S_USER_LOGGED_IN or S_LOAD_UNREADS -->
+ <span style="float: {S_CONTENT_FLOW_END};"><!-- IF S_LOAD_UNREADS --><a href="{U_SEARCH_UNREAD}">{L_SEARCH_UNREAD}</a><!-- IF S_USER_LOGGED_IN --> | <!-- ENDIF --><!-- ENDIF --><!-- IF S_USER_LOGGED_IN --><a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a> | <a href="{U_SEARCH_SELF}">{L_SEARCH_SELF}</a><!-- ENDIF --></span>
<!-- ENDIF -->
</p>
<!-- ENDIF -->
diff --git a/phpBB/styles/subsilver2/template/posting_body.html b/phpBB/styles/subsilver2/template/posting_body.html
index 963e6fe966..0021cd2eb3 100644
--- a/phpBB/styles/subsilver2/template/posting_body.html
+++ b/phpBB/styles/subsilver2/template/posting_body.html
@@ -342,8 +342,8 @@
<td class="cat" colspan="2" align="center">
<input class="btnlite" type="submit" tabindex="5" name="preview" value="{L_PREVIEW}" />
&nbsp; <input class="btnmain" type="submit" accesskey="s" tabindex="6" name="post" value="{L_SUBMIT}" />
- <!-- IF S_SAVE_ALLOWED -->&nbsp; <input class="btnlite" type="submit" accesskey="k" tabindex="7" name="save" value="{L_SAVE}" /><!-- ENDIF -->
- <!-- IF S_HAS_DRAFTS -->&nbsp; <input class="btnlite" type="submit" accesskey="d" tabindex="8" name="load" value="{L_LOAD}" /><!-- ENDIF -->
+ <!-- IF S_SAVE_ALLOWED -->&nbsp; <input class="btnlite" type="submit" accesskey="k" tabindex="7" name="save" value="{L_SAVE_DRAFT}" /><!-- ENDIF -->
+ <!-- IF S_HAS_DRAFTS -->&nbsp; <input class="btnlite" type="submit" accesskey="d" tabindex="8" name="load" value="{L_LOAD_DRAFT}" /><!-- ENDIF -->
&nbsp; <input class="btnlite" type="submit" accesskey="c" tabindex="9" name="cancel" value="{L_CANCEL}" />
</td>
</tr>
@@ -365,8 +365,8 @@
<input class="btnlite" type="submit" tabindex="10" name="preview" value="{L_PREVIEW}" />
&nbsp; <input class="btnmain" type="submit" accesskey="s" tabindex="11" name="post" value="{L_SUBMIT}" />
<!-- IF not S_SHOW_ATTACH_BOX and not S_SHOW_POLL_BOX -->
- <!-- IF S_SAVE_ALLOWED -->&nbsp; <input class="btnlite" type="submit" accesskey="k" tabindex="12" name="save" value="{L_SAVE}" /><!-- ENDIF -->
- <!-- IF S_HAS_DRAFTS -->&nbsp; <input class="btnlite" type="submit" accesskey="d" tabindex="13" name="load" value="{L_LOAD}" /><!-- ENDIF -->
+ <!-- IF S_SAVE_ALLOWED -->&nbsp; <input class="btnlite" type="submit" accesskey="k" tabindex="12" name="save" value="{L_SAVE_DRAFT}" /><!-- ENDIF -->
+ <!-- IF S_HAS_DRAFTS -->&nbsp; <input class="btnlite" type="submit" accesskey="d" tabindex="13" name="load" value="{L_LOAD_DRAFT}" /><!-- ENDIF -->
<!-- ENDIF -->
&nbsp; <input class="btnlite" type="submit" accesskey="c" tabindex="14" name="cancel" value="{L_CANCEL}" />
</td>
diff --git a/phpBB/styles/subsilver2/template/posting_buttons.html b/phpBB/styles/subsilver2/template/posting_buttons.html
index 2fff9c1991..621fa87fd4 100644
--- a/phpBB/styles/subsilver2/template/posting_buttons.html
+++ b/phpBB/styles/subsilver2/template/posting_buttons.html
@@ -45,7 +45,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="t" name="addlitsitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" onmouseover="helpline('e')" 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')" />
<!-- 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/search_body.html b/phpBB/styles/subsilver2/template/search_body.html
index a0ec30e9ba..763a229c83 100644
--- a/phpBB/styles/subsilver2/template/search_body.html
+++ b/phpBB/styles/subsilver2/template/search_body.html
@@ -75,4 +75,21 @@
<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
-<!-- INCLUDE overall_footer.html --> \ No newline at end of file
+<script type="text/javascript">
+// <![CDATA[
+ (function()
+ {
+ var elements = document.getElementsByName("keywords");
+ for (var i = 0; i < elements.length; ++i)
+ {
+ if (elements[i].tagName.toLowerCase() == 'input')
+ {
+ elements[i].focus();
+ break;
+ }
+ }
+ })();
+// ]]>
+</script>
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/tests/RUNNING_TESTS.txt b/tests/RUNNING_TESTS.txt
index f1b40f71ad..74a0635c1a 100644
--- a/tests/RUNNING_TESTS.txt
+++ b/tests/RUNNING_TESTS.txt
@@ -1,33 +1,57 @@
Running Tests
--------------
+=============
Prerequisites
--------------
+=============
PHPUnit
-=======
+-------
phpBB unit tests use PHPUnit framework. Version 3.3 or better is required
to run the tests. PHPUnit prefers to be installed via PEAR; refer to
http://www.phpunit.de/ for more information.
PHP extensions
-==============
+--------------
Unit tests use several PHP extensions that board code does not use. Currently
the following PHP extensions must be installed and enabled to run unit tests:
- ctype
+Database Tests
+--------------
+By default all tests requiring a database connection will use sqlite. If you
+do not have sqlite installed the tests will be skipped. If you wish to run the
+tests on a different database you have to create a test_config.php file within
+your tests directory following the same format as phpBB's config.php. An example
+for mysqli can be found below. More information on configuration options can be
+found on the wiki (see below).
+
+ <?php
+ $dbms = 'mysqli';
+ $dbhost = 'localhost';
+ $dbport = '';
+ $dbname = 'database';
+ $dbuser = 'user';
+ $dbpasswd = 'password';
+
+Alternatively you can specify parameters in the environment, so e.g. the following
+will run phpunit with the same parameters as in the shown test_config.php file:
+
+ $ PHPBB_TEST_DBMS='mysqli' PHPBB_TEST_DBHOST='localhost' \
+ PHPBB_TEST_DBNAME='database' PHPBB_TEST_DBUSER='user' \
+ PHPBB_TEST_DBPASSWD='password' phpunit all_tests.php
+
Running
--------
+=======
Once the prerequisites are installed, run the tests from tests directory:
-$ phpunit all_tests.php
+ $ phpunit all_tests.php
More Information
-----------------
+================
Further information is available on phpbb wiki:
http://wiki.phpbb.com/display/DEV/Unit+Tests
diff --git a/tests/all_tests.php b/tests/all_tests.php
index bae7725ee7..d1d711c4d7 100644
--- a/tests/all_tests.php
+++ b/tests/all_tests.php
@@ -28,7 +28,14 @@ require_once 'network/all_tests.php';
require_once 'random/all_tests.php';
// exclude the test directory from code coverage reports
-PHPUnit_Util_Filter::addDirectoryToFilter('./');
+if (version_compare(PHPUnit_Runner_Version::id(), '3.5.0') >= 0)
+{
+ PHP_CodeCoverage_Filter::getInstance()->addDirectoryToBlacklist('./');
+}
+else
+{
+ PHPUnit_Util_Filter::addDirectoryToFilter('./');
+}
class phpbb_all_tests
{
diff --git a/tests/dbal/all_tests.php b/tests/dbal/all_tests.php
index 7aee0f6b16..cfa8176246 100644
--- a/tests/dbal/all_tests.php
+++ b/tests/dbal/all_tests.php
@@ -15,7 +15,8 @@ if (!defined('PHPUnit_MAIN_METHOD'))
require_once 'test_framework/framework.php';
require_once 'PHPUnit/TextUI/TestRunner.php';
-require_once 'dbal/dbal.php';
+require_once 'dbal/select.php';
+require_once 'dbal/write.php';
class phpbb_dbal_all_tests
{
@@ -28,7 +29,8 @@ class phpbb_dbal_all_tests
{
$suite = new PHPUnit_Framework_TestSuite('phpBB Database Abstraction Layer');
- $suite->addTestSuite('phpbb_dbal_test');
+ $suite->addTestSuite('phpbb_dbal_select_test');
+ $suite->addTestSuite('phpbb_dbal_write_test');
return $suite;
}
diff --git a/tests/dbal/fixtures/config.xml b/tests/dbal/fixtures/config.xml
new file mode 100644
index 0000000000..019f582a91
--- /dev/null
+++ b/tests/dbal/fixtures/config.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_config">
+ <column>config_name</column>
+ <column>config_value</column>
+ <column>is_dynamic</column>
+ <row>
+ <value>config1</value>
+ <value>foo</value>
+ <value>0</value>
+ </row>
+ <row>
+ <value>config2</value>
+ <value>bar</value>
+ <value>1</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/dbal/dbal.php b/tests/dbal/select.php
index 663323ad61..70f27549d2 100644
--- a/tests/dbal/dbal.php
+++ b/tests/dbal/select.php
@@ -10,7 +10,7 @@
require_once 'test_framework/framework.php';
require_once '../phpBB/includes/functions.php';
-class phpbb_dbal_test extends phpbb_database_test_case
+class phpbb_dbal_select_test extends phpbb_database_test_case
{
public function getDataSet()
{
@@ -318,174 +318,4 @@ class phpbb_dbal_test extends phpbb_database_test_case
$db->sql_freeresult($result);
}
-
- public static function build_array_insert_data()
- {
- return array(
- array(array(
- 'config_name' => 'test_version',
- 'config_value' => '0.0.0',
- 'is_dynamic' => 1,
- )),
- array(array(
- 'config_name' => 'second config',
- 'config_value' => '10',
- 'is_dynamic' => 0,
- )),
- );
- }
-
- /**
- * @dataProvider build_array_insert_data
- */
- public function test_build_array_insert($sql_ary)
- {
- $db = $this->new_dbal();
-
- $sql = 'INSERT INTO phpbb_config ' . $db->sql_build_array('INSERT', $sql_ary);
- $result = $db->sql_query($sql);
-
- $sql = "SELECT *
- FROM phpbb_config
- WHERE config_name = '" . $sql_ary['config_name'] . "'";
- $result = $db->sql_query_limit($sql, 1);
-
- $this->assertEquals($sql_ary, $db->sql_fetchrow($result));
-
- $db->sql_freeresult($result);
- }
-
- public static function delete_data()
- {
- return array(
- array(
- "WHERE config_name = 'test_version'",
- array(
- array(
- 'config_name' => 'second config',
- 'config_value' => '10',
- 'is_dynamic' => 0,
- ),
- ),
- ),
- array(
- '',
- array(),
- ),
- );
- }
-
- /**
- * @dataProvider delete_data
- */
- public function test_delete($where, $expected)
- {
- $db = $this->new_dbal();
-
- $sql = 'DELETE FROM phpbb_config
- ' . $where;
- $result = $db->sql_query($sql);
-
- $sql = 'SELECT *
- FROM phpbb_config';
- $result = $db->sql_query($sql);
-
- $this->assertEquals($expected, $db->sql_fetchrowset($result));
-
- $db->sql_freeresult($result);
- }
-
- public function test_multiple_insert()
- {
- $db = $this->new_dbal();
-
- $batch_ary = array(
- array(
- 'config_name' => 'batch one',
- 'config_value' => 'b1',
- 'is_dynamic' => 0,
- ),
- array(
- 'config_name' => 'batch two',
- 'config_value' => 'b2',
- 'is_dynamic' => 1,
- ),
- );
-
- $result = $db->sql_multi_insert('phpbb_config', $batch_ary);
-
- $sql = 'SELECT *
- FROM phpbb_config
- ORDER BY config_name ASC';
- $result = $db->sql_query($sql);
-
- $this->assertEquals($batch_ary, $db->sql_fetchrowset($result));
-
- $db->sql_freeresult($result);
- }
-
- public static function update_data()
- {
- return array(
- array(
- array(
- 'config_value' => '20',
- 'is_dynamic' => 0,
- ),
- " WHERE config_name = 'batch one'",
- array(
- array(
- 'config_name' => 'batch one',
- 'config_value' => '20',
- 'is_dynamic' => 0,
- ),
- array(
- 'config_name' => 'batch two',
- 'config_value' => 'b2',
- 'is_dynamic' => 1,
- ),
- ),
- ),
- array(
- array(
- 'config_value' => '0',
- 'is_dynamic' => 1,
- ),
- '',
- array(
- array(
- 'config_name' => 'batch one',
- 'config_value' => '0',
- 'is_dynamic' => 1,
- ),
- array(
- 'config_name' => 'batch two',
- 'config_value' => '0',
- 'is_dynamic' => 1,
- ),
- ),
- ),
- );
- }
-
- /**
- * @dataProvider update_data
- */
- public function test_update($sql_ary, $where, $expected)
- {
- $db = $this->new_dbal();
-
- $sql = 'UPDATE phpbb_config
- SET ' . $db->sql_build_array('UPDATE', $sql_ary) . $where;
- $result = $db->sql_query($sql);
-
- $sql = 'SELECT *
- FROM phpbb_config
- ORDER BY config_name ASC';
- $result = $db->sql_query($sql);
-
- $this->assertEquals($expected, $db->sql_fetchrowset($result));
-
- $db->sql_freeresult($result);
- }
}
diff --git a/tests/dbal/write.php b/tests/dbal/write.php
new file mode 100644
index 0000000000..01deacda69
--- /dev/null
+++ b/tests/dbal/write.php
@@ -0,0 +1,172 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/functions.php';
+
+class phpbb_dbal_write_test extends phpbb_database_test_case
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/config.xml');
+ }
+
+ public static function build_array_insert_data()
+ {
+ return array(
+ array(array(
+ 'config_name' => 'test_version',
+ 'config_value' => '0.0.0',
+ 'is_dynamic' => 1,
+ )),
+ array(array(
+ 'config_name' => 'second config',
+ 'config_value' => '10',
+ 'is_dynamic' => 0,
+ )),
+ );
+ }
+
+ /**
+ * @dataProvider build_array_insert_data
+ */
+ public function test_build_array_insert($sql_ary)
+ {
+ $db = $this->new_dbal();
+
+ $sql = 'INSERT INTO phpbb_config ' . $db->sql_build_array('INSERT', $sql_ary);
+ $result = $db->sql_query($sql);
+
+ $sql = "SELECT *
+ FROM phpbb_config
+ WHERE config_name = '" . $sql_ary['config_name'] . "'";
+ $result = $db->sql_query_limit($sql, 1);
+
+ $this->assertEquals($sql_ary, $db->sql_fetchrow($result));
+
+ $db->sql_freeresult($result);
+ }
+
+ public function test_delete()
+ {
+ $db = $this->new_dbal();
+
+ $sql = "DELETE FROM phpbb_config
+ WHERE config_name = 'config1'";
+ $result = $db->sql_query($sql);
+
+ $sql = 'SELECT *
+ FROM phpbb_config';
+ $result = $db->sql_query($sql);
+ $rows = $db->sql_fetchrowset($result);
+
+ $this->assertEquals(1, sizeof($rows));
+ $this->assertEquals('config2', $rows[0]['config_name']);
+
+ $db->sql_freeresult($result);
+ }
+
+ public function test_multiple_insert()
+ {
+ $db = $this->new_dbal();
+
+ // empty the table
+ $sql = 'DELETE FROM phpbb_config';
+ $db->sql_query($sql);
+
+ $batch_ary = array(
+ array(
+ 'config_name' => 'batch one',
+ 'config_value' => 'b1',
+ 'is_dynamic' => 0,
+ ),
+ array(
+ 'config_name' => 'batch two',
+ 'config_value' => 'b2',
+ 'is_dynamic' => 1,
+ ),
+ );
+
+ $result = $db->sql_multi_insert('phpbb_config', $batch_ary);
+
+ $sql = 'SELECT *
+ FROM phpbb_config
+ ORDER BY config_name ASC';
+ $result = $db->sql_query($sql);
+
+ $this->assertEquals($batch_ary, $db->sql_fetchrowset($result));
+
+ $db->sql_freeresult($result);
+ }
+
+ public static function update_data()
+ {
+ return array(
+ array(
+ array(
+ 'config_value' => '23',
+ 'is_dynamic' => 0,
+ ),
+ " WHERE config_name = 'config1'",
+ array(
+ array(
+ 'config_name' => 'config1',
+ 'config_value' => '23',
+ 'is_dynamic' => 0,
+ ),
+ array(
+ 'config_name' => 'config2',
+ 'config_value' => 'bar',
+ 'is_dynamic' => 1,
+ ),
+ ),
+ ),
+ array(
+ array(
+ 'config_value' => '0',
+ 'is_dynamic' => 1,
+ ),
+ '',
+ array(
+ array(
+ 'config_name' => 'config1',
+ 'config_value' => '0',
+ 'is_dynamic' => 1,
+ ),
+ array(
+ 'config_name' => 'config2',
+ 'config_value' => '0',
+ 'is_dynamic' => 1,
+ ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider update_data
+ */
+ public function test_update($sql_ary, $where, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $sql = 'UPDATE phpbb_config
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . $where;
+ $result = $db->sql_query($sql);
+
+ $sql = 'SELECT *
+ FROM phpbb_config
+ ORDER BY config_name ASC';
+ $result = $db->sql_query($sql);
+
+ $this->assertEquals($expected, $db->sql_fetchrowset($result));
+
+ $db->sql_freeresult($result);
+ }
+}
diff --git a/tests/template/template.php b/tests/template/template.php
index 024d3712f7..0c2ca8a032 100644
--- a/tests/template/template.php
+++ b/tests/template/template.php
@@ -36,6 +36,7 @@ class phpbb_template_template_test extends phpbb_test_case
// reset the error level even when an error occured
// PHPUnit turns trigger_error into exceptions as well
error_reporting($error_level);
+ ob_end_clean();
throw $exception;
}
diff --git a/tests/test_framework/framework.php b/tests/test_framework/framework.php
index abdcd1ad79..3a11cc6df9 100644
--- a/tests/test_framework/framework.php
+++ b/tests/test_framework/framework.php
@@ -32,8 +32,12 @@ if (version_compare(PHPUnit_Runner_Version::id(), '3.3.0', '<'))
trigger_error('PHPUnit >= 3.3.0 required');
}
-require_once 'PHPUnit/Framework.php';
-require_once 'PHPUnit/Extensions/Database/TestCase.php';
+if (version_compare(PHPUnit_Runner_Version::id(), '3.5.0', '<'))
+{
+ require_once 'PHPUnit/Framework.php';
+ require_once 'PHPUnit/Extensions/Database/TestCase.php';
+}
+
require_once 'test_framework/phpbb_test_case_helpers.php';
require_once 'test_framework/phpbb_test_case.php';
require_once 'test_framework/phpbb_database_test_case.php';
diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php
index f6bf420ebc..a64bae8c57 100644
--- a/tests/test_framework/phpbb_database_test_case.php
+++ b/tests/test_framework/phpbb_database_test_case.php
@@ -9,14 +9,18 @@
abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_TestCase
{
+ private static $already_connected;
+
protected $test_case_helpers;
- public function init_test_case_helpers()
+ public function get_test_case_helpers()
{
if (!$this->test_case_helpers)
{
$this->test_case_helpers = new phpbb_test_case_helpers($this);
}
+
+ return $this->test_case_helpers;
}
public function get_dbms_data($dbms)
@@ -50,7 +54,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
'mssqlnative' => array(
'SCHEMA' => 'mssql',
'DELIM' => 'GO',
- 'PDO' => 'odbc',
+ 'PDO' => 'sqlsrv',
),
'oracle' => array(
'SCHEMA' => 'oracle',
@@ -79,6 +83,50 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
}
}
+ public function get_database_config()
+ {
+ if (isset($_SERVER['PHPBB_TEST_DBMS']))
+ {
+ return array(
+ 'dbms' => isset($_SERVER['PHPBB_TEST_DBMS']) ? $_SERVER['PHPBB_TEST_DBMS'] : '',
+ 'dbhost' => isset($_SERVER['PHPBB_TEST_DBHOST']) ? $_SERVER['PHPBB_TEST_DBHOST'] : '',
+ 'dbport' => isset($_SERVER['PHPBB_TEST_DBPORT']) ? $_SERVER['PHPBB_TEST_DBPORT'] : '',
+ 'dbname' => isset($_SERVER['PHPBB_TEST_DBNAME']) ? $_SERVER['PHPBB_TEST_DBNAME'] : '',
+ 'dbuser' => isset($_SERVER['PHPBB_TEST_DBUSER']) ? $_SERVER['PHPBB_TEST_DBUSER'] : '',
+ 'dbpasswd' => isset($_SERVER['PHPBB_TEST_DBPASSWD']) ? $_SERVER['PHPBB_TEST_DBPASSWD'] : '',
+ );
+ }
+ else if (file_exists('test_config.php'))
+ {
+ include('test_config.php');
+
+ return array(
+ 'dbms' => $dbms,
+ 'dbhost' => $dbhost,
+ 'dbport' => $dbport,
+ 'dbname' => $dbname,
+ 'dbuser' => $dbuser,
+ 'dbpasswd' => $dbpasswd,
+ );
+ }
+ else if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>='))
+ {
+ // Silently use sqlite
+ return array(
+ 'dbms' => 'sqlite',
+ 'dbhost' => 'phpbb_unit_tests.sqlite2', // filename
+ 'dbport' => '',
+ 'dbname' => '',
+ 'dbuser' => '',
+ 'dbpasswd' => '',
+ );
+ }
+ else
+ {
+ $this->markTestSkipped('Missing test_config.php: See first error.');
+ }
+ }
+
// NOTE: This function is not the same as split_sql_file from functions_install
public function split_sql_file($sql, $dbms)
{
@@ -99,7 +147,8 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
if ($dbms == 'sqlite')
{
- // trim # off query to satisfy sqlite
+ // remove comment lines starting with # - they are not proper sqlite
+ // syntax and break sqlite2
foreach ($data as $i => $query)
{
$data[$i] = preg_replace('/^#.*$/m', "\n", $query);
@@ -109,79 +158,198 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
return $data;
}
- public function getConnection()
+ /**
+ * Retrieves a list of all tables from the database.
+ *
+ * @param PDO $pdo
+ * @param string $dbms
+ * @return array(string)
+ */
+ function get_tables($pdo, $dbms)
{
- static $already_connected;
+ switch ($pdo)
+ {
+ case 'mysql':
+ case 'mysql4':
+ case 'mysqli':
+ $sql = 'SHOW TABLES';
+ break;
+
+ case 'sqlite':
+ $sql = 'SELECT name
+ FROM sqlite_master
+ WHERE type = "table"';
+ break;
- $this->init_test_case_helpers();
- $database_config = $this->test_case_helpers->get_database_config();
+ case 'mssql':
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $sql = "SELECT name
+ FROM sysobjects
+ WHERE type='U'";
+ break;
- $dbms_data = $this->get_dbms_data($database_config['dbms']);
+ case 'postgres':
+ $sql = 'SELECT relname
+ FROM pg_stat_user_tables';
+ break;
- if ($already_connected)
+ case 'firebird':
+ $sql = 'SELECT rdb$relation_name
+ FROM rdb$relations
+ WHERE rdb$view_source is null
+ AND rdb$system_flag = 0';
+ break;
+
+ case 'oracle':
+ $sql = 'SELECT table_name
+ FROM USER_TABLES';
+ break;
+ }
+
+ $result = $pdo->query($sql);
+
+ $tables = array();
+ while ($row = $result->fetch(PDO::FETCH_NUM))
{
- if ($database_config['dbms'] == 'sqlite')
- {
- $pdo = new PDO($dbms_data['PDO'] . ':' . $database_config['dbhost']);
- }
- else
- {
- $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';dbname=' . $database_config['dbname'], $database_config['dbuser'], $database_config['dbpasswd']);
- }
+ $tables[] = current($row);
}
- else
+
+ return $tables;
+ }
+
+ /**
+ * Returns a PDO connection for the configured database.
+ *
+ * @param array $config The database configuration
+ * @param array $dbms Information on the used DBMS.
+ * @param bool $use_db Whether the DSN should be tied to a
+ * particular database making it impossible
+ * to delete that database.
+ * @return PDO The PDO database connection.
+ */
+ public function new_pdo($config, $dbms, $use_db)
+ {
+ $dsn = $dbms['PDO'] . ':';
+
+ switch ($dbms['PDO'])
{
- if ($database_config['dbms'] == 'sqlite')
- {
- // delete existing database
- if (file_exists($database_config['dbhost']))
+ case 'sqlite2':
+ $dsn .= $config['dbhost'];
+ break;
+
+ case 'sqlsrv':
+ // prefix the hostname (or DSN) with Server= so using just (local)\SQLExpress
+ // works for example, further parameters can still be appended using ;x=y
+ $dsn .= 'Server=';
+ // no break -> rest like ODBC
+ case 'odbc':
+ // for ODBC assume dbhost is a suitable DSN
+ // e.g. Driver={SQL Server Native Client 10.0};Server=(local)\SQLExpress;
+ $dsn .= $config['dbhost'];
+
+ if ($use_db)
{
- unlink($database_config['dbhost']);
+ $dsn .= ';Database=' . $config['dbname'];
}
+ break;
- $pdo = new PDO($dbms_data['PDO'] . ':' . $database_config['dbhost']);
- }
- else
- {
- $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';', $database_config['dbuser'], $database_config['dbpasswd']);try
+ default:
+ $dsn .= 'host=' . $config['dbhost'];
+
+ if ($use_db)
{
- $pdo->exec('DROP DATABASE ' . $database_config['dbname']);
+ $dsn .= ';dbname=' . $config['dbname'];
}
- catch (PDOException $e){} // ignore non existent db
-
- $pdo->exec('CREATE DATABASE ' . $database_config['dbname']);
+ break;
+ }
- $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';dbname=' . $database_config['dbname'], $database_config['dbuser'], $database_config['dbpasswd']);
- }
+ $pdo = new PDO($dsn, $config['dbuser'], $config['dbpasswd']);;
- // good for debug
- // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ // good for debug
+ // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- if ($database_config['dbms'] == 'mysql')
- {
- $sth = $pdo->query('SELECT VERSION() AS version');
- $row = $sth->fetch(PDO::FETCH_ASSOC);
+ return $pdo;
+ }
- if (version_compare($row['version'], '4.1.3', '>='))
+ private function recreate_db($config, $dbms)
+ {
+ switch ($config['dbms'])
+ {
+ case 'sqlite':
+ if (file_exists($config['dbhost']))
{
- $dbms_data['SCHEMA'] .= '_41';
+ unlink($config['dbhost']);
}
- else
+ break;
+
+ default:
+ $pdo = $this->new_pdo($config, $dbms, false);
+
+ try
{
- $dbms_data['SCHEMA'] .= '_40';
+ $pdo->exec('DROP DATABASE ' . $config['dbname']);
}
+ catch (PDOException $e)
+ {
+ // try to delete all tables if dropping the database was not possible.
+ foreach ($this->get_tables() as $table)
+ {
+ try
+ {
+ $pdo->exec('DROP TABLE ' . $table);
+ }
+ catch (PDOException $e){} // ignore non-existent tables
+ }
+ }
- unset($row, $sth);
- }
+ $pdo->exec('CREATE DATABASE ' . $config['dbname']);
+ break;
+ }
+ }
- $sql_query = $this->split_sql_file(file_get_contents("../phpBB/install/schemas/{$dbms_data['SCHEMA']}_schema.sql"), $database_config['dbms']);
+ private function load_schema($pdo, $config, $dbms)
+ {
+ if ($config['dbms'] == 'mysql')
+ {
+ $sth = $pdo->query('SELECT VERSION() AS version');
+ $row = $sth->fetch(PDO::FETCH_ASSOC);
- foreach ($sql_query as $sql)
+ if (version_compare($row['version'], '4.1.3', '>='))
+ {
+ $dbms['SCHEMA'] .= '_41';
+ }
+ else
{
- $pdo->exec($sql);
+ $dbms['SCHEMA'] .= '_40';
}
+ }
+
+ $sql = $this->split_sql_file(file_get_contents("../phpBB/install/schemas/{$dbms['SCHEMA']}_schema.sql"), $config['dbms']);
- $already_connected = true;
+ foreach ($sql as $query)
+ {
+ $pdo->exec($query);
+ }
+ }
+
+ public function getConnection()
+ {
+ $config = $this->get_database_config();
+ $dbms = $this->get_dbms_data($config['dbms']);
+
+ if (!self::$already_connected)
+ {
+ $this->recreate_db($config, $dbms);
+ }
+
+ $pdo = $this->new_pdo($config, $dbms, true);
+
+ if (!self::$already_connected)
+ {
+ $this->load_schema($pdo, $config, $dbms);
+
+ self::$already_connected = true;
}
return $this->createDefaultDBConnection($pdo, 'testdb');
@@ -189,13 +357,20 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
public function new_dbal()
{
- $this->init_test_case_helpers();
- return $this->test_case_helpers->new_dbal();
+ global $phpbb_root_path, $phpEx;
+
+ $config = $this->get_database_config();
+
+ require_once '../phpBB/includes/db/' . $config['dbms'] . '.php';
+ $dbal = 'dbal_' . $config['dbms'];
+ $db = new $dbal();
+ $db->sql_connect($config['dbhost'], $config['dbuser'], $config['dbpasswd'], $config['dbname'], $config['dbport']);
+
+ return $db;
}
public function setExpectedTriggerError($errno, $message = '')
{
- $this->init_test_case_helpers();
- $this->test_case_helpers->setExpectedTriggerError($errno, $message);
+ $this->get_test_case_helpers()->setExpectedTriggerError($errno, $message);
}
}
diff --git a/tests/test_framework/phpbb_test_case.php b/tests/test_framework/phpbb_test_case.php
index af867b29ff..fe90d321dc 100644
--- a/tests/test_framework/phpbb_test_case.php
+++ b/tests/test_framework/phpbb_test_case.php
@@ -11,17 +11,18 @@ class phpbb_test_case extends PHPUnit_Framework_TestCase
{
protected $test_case_helpers;
- public function init_test_case_helpers()
+ public function get_test_case_helpers()
{
if (!$this->test_case_helpers)
{
$this->test_case_helpers = new phpbb_test_case_helpers($this);
}
+
+ return $this->test_case_helpers;
}
public function setExpectedTriggerError($errno, $message = '')
{
- $this->init_test_case_helpers();
- $this->test_case_helpers->setExpectedTriggerError($errno, $message);
+ $this->get_test_case_helpers()->setExpectedTriggerError($errno, $message);
}
}
diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php
index 7c026e496e..0acdce32e0 100644
--- a/tests/test_framework/phpbb_test_case_helpers.php
+++ b/tests/test_framework/phpbb_test_case_helpers.php
@@ -18,74 +18,6 @@ class phpbb_test_case_helpers
$this->test_case = $test_case;
}
- public function get_database_config()
- {
- static $show_error = true;
-
- if (file_exists('test_config.php'))
- {
- include('test_config.php');
-
- return array(
- 'dbms' => $dbms,
- 'dbhost' => $dbhost,
- 'dbport' => $dbport,
- 'dbname' => $dbname,
- 'dbuser' => $dbuser,
- 'dbpasswd' => $dbpasswd,
- );
- }
- else if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>='))
- {
- // Silently use sqlite
- return array(
- 'dbms' => 'sqlite',
- 'dbhost' => 'phpbb_unit_tests.sqlite2', // filename
- 'dbport' => '',
- 'dbname' => '',
- 'dbuser' => '',
- 'dbpasswd' => '',
- );
- }
- else
- {
- if ($show_error)
- {
- $show_error = false;
- }
- else
- {
- $this->test_case->markTestSkipped('Missing test_config.php: See first error.');
- return;
- }
-
- trigger_error("You have to create a test_config.php like this:
-\"<?php
-\$dbms = 'mysqli';
-\$dbhost = 'localhost';
-\$dbport = '';
-\$dbname = 'database';
-\$dbuser = 'user';
-\$dbpasswd = 'password';
-\"
-
-NOTE: The database is dropped and recreated with the phpbb-db-schema! Do NOT specify a database with important data.", E_USER_ERROR);
- }
- }
-
- public function new_dbal()
- {
- global $phpbb_root_path, $phpEx;
- $config = $this->get_database_config();
-
- require_once '../phpBB/includes/db/' . $config['dbms'] . '.php';
- $dbal = 'dbal_' . $config['dbms'];
- $db = new $dbal();
- $db->sql_connect($config['dbhost'], $config['dbuser'], $config['dbpasswd'], $config['dbname'], $config['dbport']);
-
- return $db;
- }
-
public function setExpectedTriggerError($errno, $message = '')
{
$exceptionName = '';