Compare commits

..

47 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 0bd0ee444a Moodle release 3.0.10 2017-05-07 21:32:44 +02:00
Marina Glancy 887f2449a2 MDL-58740 block_course_overview: check session key
Thanks to Kukas Schmidt for initial patch
2017-05-04 08:56:01 +08:00
Marina Glancy 40adce7f08 MDL-58670 blog: respect capability to search entries 2017-05-04 08:56:00 +08:00
Marina Glancy 27795d1eed MDL-58635 blogs: check edited blog belongs to current user 2017-05-04 08:56:00 +08:00
David Monllao 5743df7428 weekly release 3.0.9+ 2017-05-03 10:27:40 +08:00
Andrew Nicols c31d886c8f MDL-58746 core: Simplify environment check 2017-05-03 08:37:05 +08:00
Andrew Nicols 943c9c3c9a MDL-58746 core: Add environment check for finfo 2017-05-01 13:23:46 +08:00
Eloy Lafuente (stronk7) 6b2d3d3e6a MDL-54901 environment: pg93 & openssl 2017-04-18 04:04:52 +02:00
Eloy Lafuente (stronk7) a8b89c6120 MDL-54901 environment: 3.3 base information
This is a direct copy of the 3.2 branch to
have changes under control easier in next commits.
2017-04-18 03:06:29 +02:00
Eloy Lafuente (stronk7) cbfee05d7f Moodle release 3.0.9 2017-03-11 22:15:54 +01:00
Marina Glancy 0833e7cfc7 MDL-58010 user: allow to update only whitelisted preferences 2017-03-10 18:10:44 +00:00
Eloy Lafuente (stronk7) 10d80cd64c weekly release 3.0.8+ 2017-01-27 00:27:49 +01:00
Dan Poltawski 024f0b702a Merge branch 'MDL-57639-30' of git://github.com/andrewnicols/moodle into MOODLE_30_STABLE 2017-01-24 10:11:26 +00:00
Dan Poltawski 68529165cd Merge branch 'MDL-57677-30-usermodified' of git://github.com/mudrd8mz/moodle into MOODLE_30_STABLE 2017-01-23 09:49:49 +00:00
Andrew Nicols 87f6a483c3 MDL-57639 mod_forum: Update to use correct variable name
This addresses a regression where unnecessary attributes were removed
from the old variable. This one was missed.
2017-01-19 14:01:37 +08:00
David Mudrák c4fabc91e1 MDL-57677 mod_forum: Fix wrong user displayed as the last post's author
In the recent issue MDL-56225, we started to record the current user as
the usermodified in the forum_discussions table when updating a forum
post. It made sense but it was a mistake.

Even if the current user really modifies the discussion by updating the
post, the field usermodified has actually been always interpreted and
displayed as the last post' author. Not as the last user who touched the
discussion.

This patch reverts that particular change to the previous behaviour and
adds explicit unit test for it.
2017-01-17 20:07:54 +01:00
Eloy Lafuente (stronk7) 25c75f9b99 Moodle release 3.0.8 2017-01-08 11:04:22 +01:00
Eloy Lafuente (stronk7) 517cc1f9a7 Merge branch 'install_30_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_30_STABLE 2017-01-08 11:04:18 +01:00
David Mudrák 00e928271b MDL-57580 mod_assign: Fix the incorrect type of some input parameters
The PARAM_TEXT has been misused in certain cases here. The 'action'
parameter seems to always be alphabetic, with values like
savesubmission, editsubmission and others as handled in assign::view().

Fixing the action handling fixes the reported XSS issue. While working
on it, I spotted two more places where PARAM_TEXT does not seem
appropriate. I include changes for them too, even if they are no
strictly related to the reported bug and there are no known ways to
abuse it.

* The 'plugin' looks like PARAM_PLUGIN and is even declared as such in
  some other parts of the assignment code (such as feedback forms).

* The 'workflowstate' is one of the ASSIGN_MARKING_WORKFLOW_STATE
  constants and is supposed to be alpha in external function input
  parameters handling, too.
2017-01-05 17:40:26 +01:00
Rajesh Taneja 824965d5dc MDL-57531 behat: Set noreplyaddress to valid address
noreplyaddress should be a valid address, else
it will not be saved. For behat we don't send
email, so set it to noreply@example.com, to
avoid failing validation on localhost
2017-01-05 06:53:23 +00:00
David Mudrák ae375cfcdc MDL-57531 mail: Validate the sender's email address
The patch adds validation for the noreplyaddress setting variable, for
the explicit $replyto parameter and for the sender's email. In case of
misconfigured noreplyaddress setting, it falls back to the default
noreply address value. In case of invalid email in the user's record,
the email is not sent.

The patch also adds unit test for the value returned by the function
generate_email_processing_address() so that it can be considered as a
valid email, too.

This is supposed to significantly minimise the risk of exploiting the
vulnerability in PHPMailer's Sender field.
2017-01-04 13:35:07 +00:00
David Mudrák 1c25f894ef MDL-57531 mail: Do not let admins set invalid email addresses
The noreply and support emails should always be valid.
2017-01-04 13:34:09 +00:00
David Mudrák ef7442df5b MDL-56225 mod_forum: Fix inability to edit attachments
The 'attachments' is not a real DB field here. It comes from the form's
filepicker and holds the id of the attachments filearea. The function
forum_add_attachment() expects it as a property of the first argument.

There were two possible approaches here. Either to pass the raw $newpost
to forum_add_attachment(), or add the attachments into the list
modifiable fields. The second approach is safer.
2017-01-04 10:36:40 +00:00
Andrew Nicols a1fadacb86 MDL-56225 mod_forum: Remove unnecessary attributes from update 2017-01-03 16:58:33 +00:00
AMOS bot 8f6cefd57d Automatically generated installer lang files 2016-12-08 00:05:43 +08:00
Dan Poltawski f7b04c388e weekly release 3.0.7+ 2016-12-02 15:18:06 +00:00
Dan Poltawski a6ec5b6ff6 Merge branch 'install_30_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_30_STABLE 2016-12-02 15:18:05 +00:00
Eloy Lafuente (stronk7) 589c0fbd88 Merge branch 'MDL-57193-30-notest' of git://github.com/FMCorz/moodle into MOODLE_30_STABLE 2016-12-02 11:41:25 +01:00
Frederic Massart fe5264217d MDL-57193 auth_db: Flip the array outside the loop for better perf
Also as the recent changes where affecting the whitespaces quite
a lot, I took the liberty of aligning a few lines which weren't.
2016-12-02 16:30:17 +08:00
John Okely fdaea8ad64 MDL-57193 auth_db: Use a recordset and array_key_exists 2016-12-02 16:30:17 +08:00
Josh Willcock 4f22f01fe4 MDL-57193 auth_db: Fixed bug suspends all users if external DB has > 10k 2016-12-02 16:30:17 +08:00
AMOS bot 842db4fd37 Automatically generated installer lang files 2016-12-01 00:06:02 +08:00
AMOS bot f2066cb88f Merge branch 'MOODLE_30_STABLE' into install_30_STABLE 2016-12-01 00:06:02 +08:00
AMOS bot 0ae9cfc1c2 Automatically generated installer lang files 2016-11-30 00:05:00 +08:00
Dan Poltawski 8dfbc3a822 weekly release 3.0.7+ 2016-11-29 13:32:27 +00:00
Dan Poltawski 6c0d5df3a2 Merge branch 'install_30_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_30_STABLE 2016-11-29 13:32:25 +00:00
David Monllao fb92dba76f Merge branch 'MDL-57163-30' of https://github.com/vvzh/moodle into MOODLE_30_STABLE 2016-11-29 11:43:31 +08:00
Tim Lock b80b3d0237 MDL-57170 repository_dropbox: Ensure Dropbox Legacy continues to work 2016-11-28 10:31:31 +08:00
Vladimir Zhirov a0f554f012 MDL-57163 installation: fixed "Call to undefined function curl_version" 2016-11-27 12:13:53 +04:00
AMOS bot 44c7ab2121 Automatically generated installer lang files 2016-11-27 00:06:05 +08:00
AMOS bot 8690bb8068 Merge branch 'MOODLE_30_STABLE' into install_30_STABLE 2016-11-26 00:04:47 +08:00
David Monllao 60b566037a weekly release 3.0.7+ 2016-11-25 15:56:29 +08:00
Tony Butler 7d6c55bfc1 MDL-56948 mod_assign: Don't call get_grade_item() unless we have one 2016-11-24 15:58:44 +00:00
Damyon Wiese 1cf01e8add MDL-57100 JS: Exceptions give exceptions
Exceptions returned from ajax are not in the format expected by the JS, so
an error occurs and the exception popups are not appearing.

Conflicts:
	lib/amd/build/notification.min.js
	lib/amd/src/notification.js
2016-11-23 18:08:17 +00:00
AMOS bot dd9f8fae09 Automatically generated installer lang files 2016-11-23 00:05:30 +08:00
AMOS bot 2a3c0ef415 Automatically generated installer lang files 2016-11-18 00:07:02 +08:00
AMOS bot c6135d8d46 Automatically generated installer lang files 2016-11-17 00:04:55 +08:00
34 changed files with 593 additions and 89 deletions
+176
View File
@@ -1870,4 +1870,180 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.3" requires="2.7">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="5.5.31" />
<VENDOR name="mysql" version="5.5.31" />
<VENDOR name="postgres" version="9.3" />
<VENDOR name="mssql" version="10.0" />
<VENDOR name="oracle" version="10.2" />
</DATABASE>
<PHP version="5.6.5" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="optional">
<FEEDBACK>
<ON_CHECK message="mbstringrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="optional">
<FEEDBACK>
<ON_CHECK message="intlrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+6 -3
View File
@@ -27,9 +27,12 @@ if ($primaryadmin) {
$primaryadminemail = NULL;
$primaryadminname = NULL;
}
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'), new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
$temp->add(new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'), new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_NOTAGS));
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'), new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
$temp->add(new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL));
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'),
new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
$ADMIN->add('server', $temp);
+21 -17
View File
@@ -302,18 +302,24 @@ class auth_plugin_db extends auth_plugin_base {
// Find obsolete users.
if (count($userlist)) {
$remove_users = array();
// All the drivers can cope with chunks of 10,000. See line 4491 of lib/dml/tests/dml_est.php
$userlistchunks = array_chunk($userlist , 10000);
foreach($userlistchunks as $userlistchunk) {
list($notin_sql, $params) = $DB->get_in_or_equal($userlistchunk, SQL_PARAMS_NAMED, 'u', false);
$params['authtype'] = $this->authtype;
$sql = "SELECT u.id, u.username
$removeusers = array();
$params['authtype'] = $this->authtype;
$sql = "SELECT u.id, u.username
FROM {user} u
WHERE u.auth=:authtype AND u.deleted=0 AND u.mnethostid=:mnethostid $suspendselect AND u.username $notin_sql";
$params['mnethostid'] = $CFG->mnet_localhost_id;
$remove_users = $remove_users + $DB->get_records_sql($sql, $params);
WHERE u.auth=:authtype
AND u.deleted=0
AND u.mnethostid=:mnethostid
$suspendselect";
$params['mnethostid'] = $CFG->mnet_localhost_id;
$internalusersrs = $DB->get_recordset_sql($sql, $params);
$usernamelist = array_flip($userlist);
foreach ($internalusersrs as $internaluser) {
if (!array_key_exists($internaluser->username, $usernamelist)) {
$removeusers[] = $internaluser;
}
}
$internalusersrs->close();
} else {
$sql = "SELECT u.id, u.username
FROM {user} u
@@ -321,13 +327,13 @@ class auth_plugin_db extends auth_plugin_base {
$params = array();
$params['authtype'] = $this->authtype;
$params['mnethostid'] = $CFG->mnet_localhost_id;
$remove_users = $DB->get_records_sql($sql, $params);
$removeusers = $DB->get_records_sql($sql, $params);
}
if (!empty($remove_users)) {
$trace->output(get_string('auth_dbuserstoremove','auth_db', count($remove_users)));
if (!empty($removeusers)) {
$trace->output(get_string('auth_dbuserstoremove', 'auth_db', count($removeusers)));
foreach ($remove_users as $user) {
foreach ($removeusers as $user) {
if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
delete_user($user);
$trace->output(get_string('auth_dbdeleteuser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)), 1);
@@ -341,7 +347,7 @@ class auth_plugin_db extends auth_plugin_base {
}
}
}
unset($remove_users);
unset($removeusers);
}
if (!count($userlist)) {
@@ -950,5 +956,3 @@ class auth_plugin_db extends auth_plugin_base {
return $user;
}
}
@@ -64,7 +64,7 @@ class block_course_overview extends block_base {
$content = array();
$updatemynumber = optional_param('mynumber', -1, PARAM_INT);
if ($updatemynumber >= 0) {
if ($updatemynumber >= 0 && optional_param('sesskey', '', PARAM_RAW) && confirm_sesskey()) {
block_course_overview_update_mynumber($updatemynumber);
}
+1 -1
View File
@@ -86,7 +86,7 @@ function block_course_overview_get_myorder() {
// If preference was not found, look in the old location and convert if found.
$order = array();
if ($value = get_user_preferences('course_overview_course_order')) {
$order = unserialize($value);
$order = unserialize_array($value);
block_course_overview_update_myorder($order);
unset_user_preference('course_overview_course_order');
}
+1 -1
View File
@@ -213,7 +213,7 @@ class block_course_overview_renderer extends plugin_renderer_base {
for ($i = 1; $i <= $max; $i++) {
$options[$i] = $i;
}
$url = new moodle_url('/my/index.php');
$url = new moodle_url('/my/index.php', ['sesskey' => sesskey()]);
$select = new single_select($url, 'mynumber', $options, block_course_overview_get_max_user_courses(), array());
$select->set_label(get_string('numtodisplay', 'block_course_overview'));
$output .= $this->output->render($select);
+5 -5
View File
@@ -53,11 +53,11 @@ $action = (empty($id)) ? 'add' : 'edit';
$external = new stdClass();
// Check that this id exists.
if (!empty($id) && !$DB->record_exists('blog_external', array('id' => $id))) {
print_error('wrongexternalid', 'blog');
} else if (!empty($id)) {
$external = $DB->get_record('blog_external', array('id' => $id));
// Retrieve the external blog record.
if (!empty($id)) {
if (!$external = $DB->get_record('blog_external', array('id' => $id, 'userid' => $USER->id))) {
print_error('wrongexternalid', 'blog');
}
}
$strformheading = ($action == 'edit') ? get_string('editexternalblog', 'blog') : get_string('addnewexternalblog', 'blog');
+1 -1
View File
@@ -873,7 +873,7 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu
}
// Append Search info.
if (!empty($search)) {
if (!empty($search) && has_capability('moodle/blog:search', $sitecontext)) {
$headers['filters']['search'] = $search;
$blogurl->param('search', $search);
$PAGE->navbar->add(get_string('searchterm', 'blog', $search), $blogurl->out());
+1 -1
View File
@@ -1758,7 +1758,7 @@ class grade_report_grader extends grade_report {
// Try looking for old location of user setting that used to store all courses in one serialized user preference.
if (($oldcollapsedpref = get_user_preferences('grade_report_grader_collapsed_categories')) !== null) {
if ($collapsedall = @unserialize($oldcollapsedpref)) {
if ($collapsedall = unserialize_array($oldcollapsedpref)) {
// We found the old-style preference, filter out only categories that belong to this course and update the prefs.
$collapsed = static::filter_collapsed_categories($courseid, $collapsedall);
if (!empty($collapsed['aggregatesonly']) || !empty($collapsed['gradesonly'])) {
+8 -2
View File
@@ -69,9 +69,15 @@ $string['pathshead'] = 'Potvrdit cesty';
$string['pathsrodataroot'] = 'Do datového adresáře nelze zapisovat.';
$string['pathsroparentdataroot'] = 'Do nadřazeného adresáře ({$a->parent}) nelze zapisovat. Datový adresář ({$a->dataroot}) nemůže být tímto průvodcem instalací vytvořen.';
$string['pathssubadmindir'] = 'Na některých serverech je URL adresa /admin vyhrazena pro speciální účely (např. pro ovládací panel). Na takových serverech může dojít ke kolizi se standardním umístěním stránek pro správu Moodle. Máte-li tento problém, přejmenujte adresář <eM>admin</em> ve vaší instalaci Moodle a sem zadejte jeho nový název - například <em>moodleadmin</em>. Všechny generované odkazy na stránky správy Moodle budou používat tento nový název.';
$string['pathssubdataroot'] = 'Moodle potřebuje prostor, kam si bude ukládat nahrané soubory a další údaje. K tomuto adresáři musí mít proces webového serveru právo ke čtení i k zápisu (webový server bývá většinou spouštěn pod uživatelem "www-data" nebo "apache"). Tento adresář ale zároveň nesmí být dostupný přímo přes webové rozhraní. Instalační skript se pokusí tento adresář vytvořit, pokud nebude existovat.';
$string['pathssubdataroot'] = '<p>Moodle potřebuje prostor, kam si bude ukládat nahrané soubory a další údaje. .</p>
<p>K tomuto adresáři musí mít proces webového serveru právo ke čtení i k zápisu (webový server bývá většinou spouštěn pod uživatelem "www-data" nebo "apache"). .</p>
<p>Tento adresář ale zároveň nesmí být dostupný přímo přes webové rozhraní. .</p>
<p>Instalační skript se pokusí tento adresář vytvořit, pokud nebude existovat..</p>';
$string['pathssubdirroot'] = 'Absolutní cesta k adresáři s instalací Moodle';
$string['pathssubwwwroot'] = 'Zadejte úplnou webovou adresu, na níž bude Moodle dostupný. Moodle potřebuje jedinečnou adresu, není možné jej provozovat na několika URL současně. Používáte-li několik veřejných domén, musíte si sami nastavit permanentní přesměrování na jednu z nich a tu pak použít. Pokud je váš server dostupný z vnější a z vnitřní sítě pod různými IP adresami, použijte jeho veřejnou adresu a nastavte si váš DNS server tak, že ji mohou používat i uživatelé z vnitřní sítě.';
$string['pathssubwwwroot'] = '<p>Zadejte úplnou webovou adresu, na níž bude Moodle dostupný, t.j. adresa, kterou zadají uživatelé do adresního řádku svého prohlížeče, aby spustili Moodle.</p>
<p>Moodle potřebuje jedinečnou adresu, není možné jej provozovat na několika URL současně. Používáte-li několik veřejných domén, musíte si sami nastavit permanentní přesměrování na jednu z nich a tu pak použít.</p>
<p> Pokud je váš server dostupný z vnější a z vnitřní sítě pod různými IP adresami, použijte jeho veřejnou adresu a nastavte si váš DNS server tak, že ji mohou používat i uživatelé z vnitřní sítě.</p>
<p>Pokud aktuální adresa není správná, změňte URL adresu v adresním řádku prohlížeče a spusťte instalaci.</p>';
$string['pathsunsecuredataroot'] = 'Umístění datového adresáře není bezpečné';
$string['pathswrongadmindir'] = 'Adresář pro správu serveru (admin) neexistuje';
$string['phpextension'] = '{$a} PHP rozšíření';
+13 -11
View File
@@ -72,13 +72,15 @@ $string['pathshead'] = 'Bekræft stier';
$string['pathsrodataroot'] = 'Datamappen er skrivebeskyttet.';
$string['pathsroparentdataroot'] = 'Den overordnede mappe ({$a->parent}) er skrivebeskyttet. Datamappen ({$a->dataroot}) kan ikke oprettes af installationsprogrammet.';
$string['pathssubadmindir'] = 'Enkelte webhoteller bruger /admin som speciel URL til kontrolpanelet el. lign. Desværre konflikter det med Moodles standardplacering af admin-sider. Du kan klare dette ved at give admin-mappen et andet navn i din installation og skrive det her. Det kan f.eks. være <em>moodleadmin</em>. Det vil fikse admin-links i Moodle.';
$string['pathssubdataroot'] = 'Du har brug for et sted, hvor Moodle kan gemme uploadede filer. Denne mappe skal kunne læses OG SKRIVES I af webserverbrugeren (oftest \'ingen\' eller \'apache\'), men må ikke være tilgængelig direkte via internettet. Installationsprogrammet vil forsøge at oprette mappen, hvis ikke den allerede eksisterer.';
$string['pathssubdirroot'] = 'Den fulde sti til Moodleinstallationen.';
$string['pathssubwwwroot'] = 'Moodles fulde web-adresse.
Det er ikke muligt at komme ind på Moodle fra mere end en adresse.
Hvis dit websted har flere offentlige adresser skal du opsætte permanent viderestilling til dem alle undtagen denne.
Hvis dit websted er tilgængeligt fra både internet og intranet skal du bruge internetadressen her og opsætte din DNS sådan at intranet-brugerne kan bruge den offentlige adresse også.
Hvis ikke adressen er korrekt må du ændre URL\'en i din browser og genstarte installationen med den rigtige adresse.';
$string['pathssubdataroot'] = '<p>En mappe hvori Moodle kan gemme uploadede filer.</p>
<p>Webserver-brugeren (som regel \'www-data\', \'nobody\', eller \'apache\') skal have læse- og skriveadgang til den.</p>
<p>Mappen må ikke være tilgængelig direkte fra internettet.</p>
<p>Hvis ikke den allerede eksisterer, vil Installationsprogrammet forsøge at oprette den</p>';
$string['pathssubdirroot'] = '<p>Den fulde sti mappen med til Moodlekoden.</p>';
$string['pathssubwwwroot'] = '<p>Moodles fulde web-adresse, dvs. adressen som den skal stå i browserens adressefelt for at komme ind på Moodle.</p>
<p>Moodle kan ikke bruges fra flere adresser. Hvis dit websted kan tilgås fra flere adresser, skal du vælge den enkleste og opsætte permanent viderestilling for hver af de øvrige.</p>
<p>Hvis dit websted er tilgængeligt fra både internettet og et internt net (nogen gange kaldet intranet), skal du bruge den offentlige adresse her</p>
<p>Hvis ikke adressen er korrekt, skal du ændre URL\'en i din browser og genstarte installationen.</p>';
$string['pathsunsecuredataroot'] = 'Datamappen er ikke sikret';
$string['pathswrongadmindir'] = 'Adminmappe eksisterer ikke';
$string['phpextension'] = '{$a} PHP-extension';
@@ -88,11 +90,11 @@ $string['phpversionhelp'] = '<p>Moodle kræver mindst PHP version 4.3.0. eller 5
<p>Du bliver nødt til at opdatere PHP eller flytte systemet over på en anden webserver der har en nyere version af PHP!</p>
(Har du ver. 5.0.x kan du også nedgradere til 4.4.x)</p>';
$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
$string['welcomep20'] = 'Du ser denne side fordi du med succes har installeret og åbnet pakken <strong>{$a->packname} {$a->packversion}</strong> på din computer.
$string['welcomep20'] = 'Du ser denne side fordi du har installeret og åbnet pakken <strong>{$a->packname} {$a->packversion}</strong> på din computer.
Tillykke med det!';
$string['welcomep30'] = 'Denne udgave af <strong>{$a->installername}</strong> indeholder programmerne til at oprette et miljø, hvori <strong>Moodle</strong> vil operere, nemlig:';
$string['welcomep30'] = 'Denne version af <strong>{$a->installername}</strong> indeholder programmerne til at oprette et miljø, hvori <strong>Moodle</strong> vil operere, nemlig:';
$string['welcomep40'] = 'Pakken indeholder også <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
$string['welcomep50'] = 'Brugen af programmerne i denne pakke er styret af deres respektive licenser. Hele <strong>{$a->installername}</strong>-pakken er <a href="http://www.opensource.org/docs/definition_plain.html">open source</a> og distribueret under <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>-licensen.';
$string['welcomep60'] = 'De følgende sider vil hjælpe dig gennem nogle nemme trin til konfiguration og opsætning af <strong>Moodle</strong> på din computer. Du kan acceptere standardindstillingerne eller vælge at ændre dem så de bedre svarer til dine egne behov.';
$string['welcomep50'] = 'Brugen af programmerne i denne pakke reguleres af deres respektive licenser. Hele <strong>{$a->installername}</strong>-pakken er <a href="http://www.opensource.org/docs/definition_plain.html">open source</a> og distribueret under <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>-licensen.';
$string['welcomep60'] = 'De følgende sider vil hjælpe dig gennem nogle nemme trin til konfiguration og opsætning af <strong>Moodle</strong> på din computer. Du kan acceptere standardindstillingerne, eller vælge at ændre dem så de bedre svarer til dine egne behov.';
$string['welcomep70'] = 'Klik på "Næste" herunder for at forsætte opsætningen af <strong>Moodle</strong>.';
$string['wwwroot'] = 'Webadresse';
+1 -1
View File
@@ -88,6 +88,6 @@ $string['welcomep30'] = 'Deze uitgave van <strong>{$a->installername}</strong> b
$string['welcomep40'] = 'Dit pakket bevat ook <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
$string['welcomep50'] = 'Het gebruik van alle programma\'s in dit pakket wordt geregeld door hun respectievelijke licenties. Het complete <strong>{$a->installername}</strong> pakket is
<a href="http://www.opensource.org/docs/definition_plain.html">open source</a> en wordt verdeeld onder de <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a> licentie.';
$string['welcomep60'] = 'De volgende pagina\'s leiden je door een aantal makkelijk te volgen stappen om <strong>Moodle</strong> te installeren op je computer. Je kunt de standaardinstellingen overnemen of, optionneel, ze aanpassen aan je noden.';
$string['welcomep60'] = 'De volgende pagina\'s leiden je door een aantal makkelijk te volgen stappen om <strong>Moodle</strong> te installeren op je computer. Je kunt de standaardinstellingen overnemen of, optioneel, ze aanpassen aan je noden.';
$string['welcomep70'] = 'Klik op de "volgende"-knop om verder te gaan met de installatie van <strong>Moodle</strong>';
$string['wwwroot'] = 'Web adres';
+2 -2
View File
@@ -34,8 +34,8 @@ $string['admindirname'] = 'Katalog admin';
$string['availablelangs'] = 'Dostępne paczki językowe';
$string['chooselanguagehead'] = 'Wybierz język';
$string['chooselanguagesub'] = 'Proszę wybrać język do instalacji. Ten język będzie również użyty jako domyślny język witryny, przy czym może być później zmieniony.';
$string['clialreadyconfigured'] = 'Plik config.php już istnieje, użyj admin/cli/install_database.php jeśli chcesz zainstalować tę witrynę.';
$string['clialreadyinstalled'] = 'Plik config.php już istnieje, użyj admin/cli/upgrade.php, jeśli chcesz uaktualnić witrynę.';
$string['clialreadyconfigured'] = 'Plik config.php już istnieje. Użyj admin/cli/install_database.php jeśli chcesz zainstalować Moodle dla tej strony.';
$string['clialreadyinstalled'] = 'Plik config.php już istnieje. Użyj admin/cli/install_database.php jeśli chcesz zaktualizować Moodle dla tej strony.';
$string['cliinstallheader'] = 'Program instalacyjny Moodle {$a} z linii poleceń';
$string['databasehost'] = 'Host bazy danych';
$string['databasename'] = 'Nazwa bazy danych';
+7
View File
@@ -54,6 +54,10 @@ $string['paths'] = 'Căi';
$string['pathserrcreatedataroot'] = 'Data directory ({$a->dataroot}) nu poate fi creat de către installer.';
$string['pathshead'] = 'Confirmare căi';
$string['pathsrodataroot'] = 'Directorul dataroot nu poate fi scris.';
$string['pathssubdataroot'] = '<p>Un director unde Moodle va stoca tot conținutul unui fișier încărcat de către utilizatori.</p>
<p>Acest director trebuie să poată fi citit și scris de către utilizatrii serverului web (de obicei \'www-data\', \'nobody\', or \'apache\').</p>
<p>Nu trebuie să fie direct accesibil de pe web.</p>
<p>Dacă directorul nu există în prezent, procesul de instalare va încerca să îl creeze.</p>';
$string['pathssubdirroot'] = '<p>Calea completă către directorul care conține codul Moodle .</p>';
$string['pathsunsecuredataroot'] = 'Locația dataroot nu este sigură';
$string['pathswrongadmindir'] = 'Directorul admin nu există';
@@ -65,5 +69,8 @@ $string['phpversionhelp'] = '<p>Moodle necesită o versiune PHP de cel puțin 4
(În cazul 5.0.x puteți, de asemenea, să downgradați la versiunea 4.4.x)</p>';
$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
$string['welcomep20'] = 'Vedeți această pagină deoarece ați instalat și lansat cu succes pachetul <strong>{$a->packname} {$a->packversion}</strong> în computerul dumneavoastră. Felicitări!';
$string['welcomep30'] = 'Lansarea <strong>{$a->installername}</strong> include aplicațiile
pentru a crea un mediu în care <strong>Moodle</strong> va funcționa, și anume:';
$string['welcomep40'] = 'Pachetul include și <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
$string['welcomep70'] = 'Click pe butonul "Next" de mai jos pentru a continua setarea <strong>Moodle</strong>.';
$string['wwwroot'] = 'Adresă Web';
+1
View File
@@ -769,6 +769,7 @@ $string['numberofmissingstrings'] = 'Number of missing strings: {$a}';
$string['numberofstrings'] = 'Total number of strings: {$a->strings}<br />Missing: {$a->missing} ({$a->missingpercent}&nbsp;%)';
$string['opcacherecommended'] = 'PHP opcode caching improves performance and lowers memory requirements, OPcache extension is recommended and fully supported.';
$string['opensslrecommended'] = 'Installing the optional OpenSSL library is highly recommended -- it enables Moodle Networking functionality.';
$string['opensslrequired'] = 'The OpenSSL PHP extension is now required by Moodle to provide stronger cryptographic services.';
$string['opentogoogle'] = 'Open to Google';
$string['optionalmaintenancemessage'] = 'Optional maintenance message';
$string['order1'] = 'First';
+1
View File
@@ -180,6 +180,7 @@ $string['viewmyentriesaboutcourse'] = 'View my entries about this course';
$string['viewsiteentries'] = 'View all entries';
$string['viewuserentries'] = 'View all entries by {$a}';
$string['worldblogs'] = 'The world can read entries set to be world-accessible';
$string['wrongexternalid'] = 'Wrong external blog id';
$string['wrongpostid'] = 'Wrong blog post id';
$string['page-blog-edit'] = 'Blog editing pages';
$string['page-blog-index'] = 'Blog listing pages';
+1 -1
View File
@@ -1 +1 @@
define(["core/yui"],function(a){return{alert:function(b,c,d){a.use("moodle-core-notification-alert",function(){var a=new M.core.alert({title:b,message:c,yesLabel:d});a.show()})},confirm:function(b,c,d,e,f){a.use("moodle-core-notification-confirm",function(){var a=new M.core.confirm({title:b,question:c,yesLabel:d,noLabel:e});a.on("complete-yes",function(){f()}),a.show()})},exception:function(b){b.backtrace&&(b.lineNumber=b.backtrace[0].line,b.fileName=b.backtrace[0].file,b.fileName="..."+b.fileName.substr(b.fileName.length-20),b.stack=b.debuginfo,b.name=b.errorcode),a.use("moodle-core-notification-exception",function(){var a=new M.core.exception(b);a.show()})}}});
define(["core/yui"],function(a){return{alert:function(b,c,d){a.use("moodle-core-notification-alert",function(){var a=new M.core.alert({title:b,message:c,yesLabel:d});a.show()})},confirm:function(b,c,d,e,f){a.use("moodle-core-notification-confirm",function(){var a=new M.core.confirm({title:b,question:c,yesLabel:d,noLabel:e});a.on("complete-yes",function(){f()}),a.show()})},exception:function(b){if("undefined"==typeof b.stack&&(b.stack=""),b.debuginfo&&(b.stack+=b.debuginfo+"\n"),b.backtrace){b.stack+=b.backtrace;var c=b.backtrace.match(/line ([^ ]*) of/),d=b.backtrace.match(/ of ([^:]*): /);c&&c[1]&&(b.lineNumber=c[1]),d&&d[1]&&(b.fileName=d[1],b.fileName.length>30&&(b.fileName="..."+b.fileName.substr(b.fileName.length-27)))}"undefined"==typeof b.name&&b.errorcode&&(b.name=b.errorcode),a.use("moodle-core-notification-exception",function(){var a=new M.core.exception(b);a.show()})}}});
+22 -5
View File
@@ -88,14 +88,31 @@ define(['core/yui'], function(Y) {
*/
exception: function(ex) {
// Fudge some parameters.
if (typeof ex.stack == 'undefined') {
ex.stack = '';
}
if (ex.debuginfo) {
ex.stack += ex.debuginfo + '\n';
}
if (ex.backtrace) {
ex.lineNumber = ex.backtrace[0].line;
ex.fileName = ex.backtrace[0].file;
ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 20);
ex.stack = ex.debuginfo;
ex.stack += ex.backtrace;
var ln = ex.backtrace.match(/line ([^ ]*) of/);
var fn = ex.backtrace.match(/ of ([^:]*): /);
if (ln && ln[1]) {
ex.lineNumber = ln[1];
}
if (fn && fn[1]) {
ex.fileName = fn[1];
if (ex.fileName.length > 30) {
ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 27);
}
}
}
if (typeof ex.name == 'undefined' && ex.errorcode) {
ex.name = ex.errorcode;
}
Y.use('moodle-core-notification-exception', function () {
Y.use('moodle-core-notification-exception', function() {
var modal = new M.core.exception(ex);
modal.show();
+3
View File
@@ -114,6 +114,9 @@ class behat_util extends testing_util {
// Enable web cron.
set_config('cronclionly', 0);
// Set noreplyaddress to an example domain, as it should be valid email address and test site can be a localhost.
set_config('noreplyaddress', 'noreply@example.com');
// Keeps the current version of database and dataroot.
self::store_versions_hash();
+78 -3
View File
@@ -5579,6 +5579,18 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
$tempreplyto = array();
$supportuser = core_user::get_support_user();
$noreplyaddressdefault = 'noreply@' . get_host_from_url($CFG->wwwroot);
$noreplyaddress = empty($CFG->noreplyaddress) ? $noreplyaddressdefault : $CFG->noreplyaddress;
if (!validate_email($noreplyaddress)) {
debugging('email_to_user: Invalid noreply-email '.s($noreplyaddress));
$noreplyaddress = $noreplyaddressdefault;
}
if (!validate_email($supportuser->email)) {
debugging('email_to_user: Invalid support-email '.s($supportuser->email));
$supportuser->email = $noreplyaddress;
}
// Make up an email address for handling bounces.
if (!empty($CFG->handlebounces)) {
@@ -5596,17 +5608,28 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
}
}
// Make sure that the explicit replyto is valid, fall back to the implicit one.
if (!empty($replyto) && !validate_email($replyto)) {
debugging('email_to_user: Invalid replyto-email '.s($replyto));
$replyto = $noreplyaddress;
}
if (is_string($from)) { // So we can pass whatever we want if there is need.
$mail->From = $CFG->noreplyaddress;
$mail->From = $noreplyaddress;
$mail->FromName = $from;
} else if ($usetrueaddress and $from->maildisplay) {
if (!validate_email($from->email)) {
debugging('email_to_user: Invalid from-email '.s($from->email).' - not sending');
// Better not to use $noreplyaddress in this case.
return false;
}
$mail->From = $from->email;
$mail->FromName = fullname($from);
} else {
$mail->From = $CFG->noreplyaddress;
$mail->From = $noreplyaddress;
$mail->FromName = fullname($from);
if (empty($replyto)) {
$tempreplyto[] = array($CFG->noreplyaddress, get_string('noreplyname'));
$tempreplyto[] = array($noreplyaddress, get_string('noreplyname'));
}
}
@@ -9489,6 +9512,58 @@ function get_course_display_name_for_list($course) {
}
}
/**
* Safe analogue of unserialize() that can only parse arrays
*
* Arrays may contain only integers or strings as both keys and values. Nested arrays are allowed.
* Note: If any string (key or value) has semicolon (;) as part of the string parsing will fail.
* This is a simple method to substitute unnecessary unserialize() in code and not intended to cover all possible cases.
*
* @param string $expression
* @return array|bool either parsed array or false if parsing was impossible.
*/
function unserialize_array($expression) {
$subs = [];
// Find nested arrays, parse them and store in $subs , substitute with special string.
while (preg_match('/([\^;\}])(a:\d+:\{[^\{\}]*\})/', $expression, $matches) && strlen($matches[2]) < strlen($expression)) {
$key = '--SUB' . count($subs) . '--';
$subs[$key] = unserialize_array($matches[2]);
if ($subs[$key] === false) {
return false;
}
$expression = str_replace($matches[2], $key . ';', $expression);
}
// Check the expression is an array.
if (!preg_match('/^a:(\d+):\{([^\}]*)\}$/', $expression, $matches1)) {
return false;
}
// Get the size and elements of an array (key;value;key;value;....).
$parts = explode(';', $matches1[2]);
$size = intval($matches1[1]);
if (count($parts) < $size * 2 + 1) {
return false;
}
// Analyze each part and make sure it is an integer or string or a substitute.
$value = [];
for ($i = 0; $i < $size * 2; $i++) {
if (preg_match('/^i:(\d+)$/', $parts[$i], $matches2)) {
$parts[$i] = (int)$matches2[1];
} else if (preg_match('/^s:(\d+):"(.*)"$/', $parts[$i], $matches3) && strlen($matches3[2]) == (int)$matches3[1]) {
$parts[$i] = $matches3[2];
} else if (preg_match('/^--SUB\d+--$/', $parts[$i])) {
$parts[$i] = $subs[$parts[$i]];
} else {
return false;
}
}
// Combine keys and values.
for ($i = 0; $i < $size * 2; $i += 2) {
$value[$parts[$i]] = $parts[$i+1];
}
return $value;
}
/**
* The lang_string class
*
+53
View File
@@ -3013,4 +3013,57 @@ class core_moodlelib_testcase extends advanced_testcase {
$this->assertSame('', $result);
$this->assertDebuggingCalled();
}
/**
* Test that generate_email_processing_address() returns valid email address.
*/
public function test_generate_email_processing_address() {
global $CFG;
$this->resetAfterTest();
$data = (object)[
'id' => 42,
'email' => 'my.email+from_moodle@example.com',
];
$modargs = 'B'.base64_encode(pack('V', $data->id)).substr(md5($data->email), 0, 16);
$CFG->maildomain = 'example.com';
$CFG->mailprefix = 'mdl+';
$this->assertEquals(1, validate_email(generate_email_processing_address(0, $modargs)));
$CFG->maildomain = 'mail.example.com';
$CFG->mailprefix = 'mdl-';
$this->assertEquals(1, validate_email(generate_email_processing_address(23, $modargs)));
}
/**
* Test safe method unserialize_array().
*/
public function test_unserialize_array() {
$a = [1, 2, 3];
$this->assertEquals($a, unserialize_array(serialize($a)));
$this->assertEquals($a, unserialize_array(serialize($a)));
$a = ['a' => 1, 2 => 2, 'b' => 'cde'];
$this->assertEquals($a, unserialize_array(serialize($a)));
$this->assertEquals($a, unserialize_array(serialize($a)));
$a = ['a' => 1, 2 => 2, 'b' => 'c"d"e'];
$this->assertEquals($a, unserialize_array(serialize($a)));
$a = ['a' => 1, 2 => ['c' => 'd', 'e' => 'f'], 'b' => 'cde'];
$this->assertEquals($a, unserialize_array(serialize($a)));
// Can not unserialize if any string contains semicolons.
$a = ['a' => 1, 2 => 2, 'b' => 'c"d";e'];
$this->assertEquals(false, unserialize_array(serialize($a)));
// Can not unserialize if there are any objects.
$a = (object)['a' => 1, 2 => 2, 'b' => 'cde'];
$this->assertEquals(false, unserialize_array(serialize($a)));
$a = ['a' => 1, 2 => 2, 'b' => (object)['a' => 'cde']];
$this->assertEquals(false, unserialize_array(serialize($a)));
// Array used in the grader report.
$a = array('aggregatesonly' => [51, 34], 'gradesonly' => [21, 45, 78]);
$this->assertEquals($a, unserialize_array(serialize($a)));
}
}
+15
View File
@@ -583,4 +583,19 @@ EXPECTED;
}
/**
* Tests for validate_email() function.
*/
public function test_validate_email() {
$this->assertEquals(1, validate_email('moodle@example.com'));
$this->assertEquals(1, validate_email('moodle@localhost.local'));
$this->assertEquals(1, validate_email('verp_email+is=mighty@moodle.org'));
$this->assertEquals(1, validate_email("but_potentially'dangerous'too@example.org"));
$this->assertEquals(1, validate_email('posts+AAAAAAAAAAIAAAAAAAAGQQAAAAABFSXz1eM/P/lR2bYyljM+@posts.moodle.org'));
$this->assertEquals(0, validate_email('moodle@localhost'));
$this->assertEquals(0, validate_email('"attacker\\" -oQ/tmp/ -X/var/www/vhost/moodle/backdoor.php some"@email.com'));
$this->assertEquals(0, validate_email("moodle@example.com>\r\nRCPT TO:<victim@example.com"));
}
}
+6
View File
@@ -2453,6 +2453,12 @@ function upgrade_install_plugins(array $installable, $confirmed, $heading='', $c
*/
function check_libcurl_version(environment_results $result) {
if (!function_exists('curl_version')) {
$result->setInfo('cURL PHP extension is not installed');
$result->setStatus(false);
return $result;
}
// Supported version and version number.
$supportedversion = 0x071304;
$supportedversionstring = "7.19.4";
+2 -1
View File
@@ -33,7 +33,8 @@ if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configtext('smtpuser', get_string('smtpuser', 'message_email'), get_string('configsmtpuser', 'message_email'), '', PARAM_NOTAGS));
$settings->add(new admin_setting_configpasswordunmask('smtppass', get_string('smtppass', 'message_email'), get_string('configsmtpuser', 'message_email'), ''));
$settings->add(new admin_setting_configtext('smtpmaxbulk', get_string('smtpmaxbulk', 'message_email'), get_string('configsmtpmaxbulk', 'message_email'), 1, PARAM_INT));
$settings->add(new admin_setting_configtext('noreplyaddress', get_string('noreplyaddress', 'message_email'), get_string('confignoreplyaddress', 'message_email'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_NOTAGS));
$settings->add(new admin_setting_configtext('noreplyaddress', get_string('noreplyaddress', 'message_email'),
get_string('confignoreplyaddress', 'message_email'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
$settings->add(new admin_setting_configcheckbox('emailonlyfromnoreplyaddress',
get_string('emailonlyfromnoreplyaddress', 'message_email'),
get_string('configemailonlyfromnoreplyaddress', 'message_email'), 0));
+2 -2
View File
@@ -825,7 +825,7 @@ class mod_assign_external extends external_api {
'locked' => new external_value(PARAM_INT, 'locked', VALUE_OPTIONAL),
'mailed' => new external_value(PARAM_INT, 'mailed', VALUE_OPTIONAL),
'extensionduedate' => new external_value(PARAM_INT, 'extension due date', VALUE_OPTIONAL),
'workflowstate' => new external_value(PARAM_TEXT, 'marking workflow state', VALUE_OPTIONAL),
'workflowstate' => new external_value(PARAM_ALPHA, 'marking workflow state', VALUE_OPTIONAL),
'allocatedmarker' => new external_value(PARAM_INT, 'allocated marker', VALUE_OPTIONAL)
)
)
@@ -1081,7 +1081,7 @@ class mod_assign_external extends external_api {
'locked' => new external_value(PARAM_INT, 'locked'),
'mailed' => new external_value(PARAM_INT, 'mailed'),
'extensionduedate' => new external_value(PARAM_INT, 'extension due date'),
'workflowstate' => new external_value(PARAM_TEXT, 'marking workflow state', VALUE_OPTIONAL),
'workflowstate' => new external_value(PARAM_ALPHA, 'marking workflow state', VALUE_OPTIONAL),
'allocatedmarker' => new external_value(PARAM_INT, 'allocated marker')
)
)
+7 -8
View File
@@ -1329,7 +1329,6 @@ class assign {
static $scalegrades = array();
$decimals = $this->get_grade_item()->get_decimals();
$o = '';
if ($this->get_instance()->grade >= 0) {
@@ -1338,7 +1337,7 @@ class assign {
if ($grade < 0) {
$displaygrade = '';
} else {
$displaygrade = format_float($grade, $decimals);
$displaygrade = format_float($grade, $this->get_grade_item()->get_decimals());
}
$o .= '<label class="accesshide" for="quickgrade_' . $userid . '">' .
get_string('usergrade', 'assign') .
@@ -1350,7 +1349,7 @@ class assign {
size="6"
maxlength="10"
class="quickgrade"/>';
$o .= '&nbsp;/&nbsp;' . format_float($this->get_instance()->grade, $decimals);
$o .= '&nbsp;/&nbsp;' . format_float($this->get_instance()->grade, $this->get_grade_item()->get_decimals());
return $o;
} else {
if ($grade == -1 || $grade === null) {
@@ -1360,7 +1359,7 @@ class assign {
$o .= grade_format_gradevalue($grade, $item);
if ($item->get_displaytype() == GRADE_DISPLAY_TYPE_REAL) {
// If displaying the raw grade, also display the total value.
$o .= '&nbsp;/&nbsp;' . format_float($this->get_instance()->grade, $decimals);
$o .= '&nbsp;/&nbsp;' . format_float($this->get_instance()->grade, $item->get_decimals());
}
}
return $o;
@@ -2298,7 +2297,7 @@ class assign {
$o = '';
$pluginsubtype = required_param('pluginsubtype', PARAM_ALPHA);
$plugintype = required_param('plugin', PARAM_TEXT);
$plugintype = required_param('plugin', PARAM_PLUGIN);
$pluginaction = required_param('pluginaction', PARAM_ALPHA);
$plugin = $this->get_plugin_by_type($pluginsubtype, $plugintype);
@@ -2372,7 +2371,7 @@ class assign {
$submissionid = optional_param('sid', 0, PARAM_INT);
$gradeid = optional_param('gid', 0, PARAM_INT);
$plugintype = required_param('plugin', PARAM_TEXT);
$plugintype = required_param('plugin', PARAM_PLUGIN);
$item = null;
if ($pluginsubtype == 'assignsubmission') {
$plugin = $this->get_submission_plugin_by_type($plugintype);
@@ -5381,7 +5380,7 @@ class assign {
$record->userid = $userid;
if ($modified >= 0) {
$record->grade = unformat_float(optional_param('quickgrade_' . $record->userid, -1, PARAM_TEXT));
$record->workflowstate = optional_param('quickgrade_' . $record->userid.'_workflowstate', false, PARAM_TEXT);
$record->workflowstate = optional_param('quickgrade_' . $record->userid.'_workflowstate', false, PARAM_ALPHA);
$record->allocatedmarker = optional_param('quickgrade_' . $record->userid.'_allocatedmarker', false, PARAM_INT);
} else {
// This user was not in the grading table.
@@ -6511,7 +6510,7 @@ class assign {
$mform->setType('userid', PARAM_INT);
$mform->addElement('hidden', 'action', 'savesubmission');
$mform->setType('action', PARAM_TEXT);
$mform->setType('action', PARAM_ALPHA);
}
/**
+2 -2
View File
@@ -37,7 +37,7 @@ require_capability('mod/assign:view', $context);
$assign = new assign($context, $cm, $course);
$urlparams = array('id' => $id,
'action' => optional_param('action', '', PARAM_TEXT),
'action' => optional_param('action', '', PARAM_ALPHA),
'rownum' => optional_param('rownum', 0, PARAM_INT),
'useridlistid' => optional_param('useridlistid', $assign->get_useridlist_key_id(), PARAM_ALPHANUM));
@@ -49,4 +49,4 @@ $completion->set_module_viewed($cm);
// Get the assign class to
// render the page.
echo $assign->view(optional_param('action', '', PARAM_TEXT));
echo $assign->view(optional_param('action', '', PARAM_ALPHA));
-3
View File
@@ -254,9 +254,6 @@ class mod_forum_post_form extends moodleform {
$mform->addElement('hidden', 'parent');
$mform->setType('parent', PARAM_INT);
$mform->addElement('hidden', 'userid');
$mform->setType('userid', PARAM_INT);
$mform->addElement('hidden', 'groupid');
$mform->setType('groupid', PARAM_INT);
+26 -11
View File
@@ -4341,41 +4341,56 @@ function forum_add_new_post($post, $mform, $unused = null) {
/**
* Update a post.
*
* @param stdClass $post The post to update
* @param stdClass $newpost The post to update
* @param mixed $mform The submitted form
* @param string $unused
* @return bool
*/
function forum_update_post($post, $mform, $unused = null) {
global $DB;
function forum_update_post($newpost, $mform, $unused = null) {
global $DB, $USER;
$post = $DB->get_record('forum_posts', array('id' => $newpost->id));
$discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion));
$forum = $DB->get_record('forum', array('id' => $discussion->forum));
$cm = get_coursemodule_from_instance('forum', $forum->id);
$context = context_module::instance($cm->id);
// Allowed modifiable fields.
$modifiablefields = [
'subject',
'message',
'messageformat',
'messagetrust',
'timestart',
'timeend',
'pinned',
'attachments',
];
foreach ($modifiablefields as $field) {
if (isset($newpost->{$field})) {
$post->{$field} = $newpost->{$field};
}
}
$post->modified = time();
$DB->update_record('forum_posts', $post);
$discussion->timemodified = $post->modified; // last modified tracking
$discussion->usermodified = $post->userid; // last modified tracking
// Last post modified tracking.
$discussion->timemodified = $post->modified;
$discussion->usermodified = $post->userid;
if (!$post->parent) { // Post is a discussion starter - update discussion title and times too
$discussion->name = $post->subject;
$discussion->timestart = $post->timestart;
$discussion->timeend = $post->timeend;
}
$post->message = file_save_draft_area_files($post->itemid, $context->id, 'mod_forum', 'post', $post->id,
$post->message = file_save_draft_area_files($newpost->itemid, $context->id, 'mod_forum', 'post', $post->id,
mod_forum_post_form::editor_options($context, $post->id), $post->message);
$DB->set_field('forum_posts', 'message', $post->message, array('id'=>$post->id));
$DB->update_record('forum_posts', $post);
$DB->update_record('forum_discussions', $discussion);
forum_add_attachment($post, $forum, $cm, $mform);
if (forum_tp_can_track_forums($forum) && forum_tp_is_tracked($forum)) {
forum_tp_mark_post_read($post->userid, $post, $post->forum);
forum_tp_mark_post_read($USER->id, $post, $forum->id);
}
// Let Moodle know that assessable content is uploaded (eg for plagiarism detection)
+54
View File
@@ -2690,4 +2690,58 @@ class mod_forum_lib_testcase extends advanced_testcase {
],
];
}
/**
* Test that {@link forum_update_post()} keeps correct forum_discussions usermodified.
*/
public function test_forum_update_post_keeps_discussions_usermodified() {
global $DB;
$this->resetAfterTest();
// Let there be light.
$teacher = self::getDataGenerator()->create_user();
$student = self::getDataGenerator()->create_user();
$course = self::getDataGenerator()->create_course();
$forum = self::getDataGenerator()->create_module('forum', (object)[
'course' => $course->id,
]);
$generator = self::getDataGenerator()->get_plugin_generator('mod_forum');
// Let the teacher start a discussion.
$discussion = $generator->create_discussion((object)[
'course' => $course->id,
'userid' => $teacher->id,
'forum' => $forum->id,
]);
// On this freshly created discussion, the teacher is the author of the last post.
$this->assertEquals($teacher->id, $DB->get_field('forum_discussions', 'usermodified', ['id' => $discussion->id]));
// Let the student reply to the teacher's post.
$reply = $generator->create_post((object)[
'course' => $course->id,
'userid' => $student->id,
'forum' => $forum->id,
'discussion' => $discussion->id,
'parent' => $discussion->firstpost,
]);
// The student should now be the last post's author.
$this->assertEquals($student->id, $DB->get_field('forum_discussions', 'usermodified', ['id' => $discussion->id]));
// Let the teacher edit the student's reply.
$this->setUser($teacher->id);
$newpost = (object)[
'id' => $reply->id,
'itemid' => 0,
'subject' => 'Amended subject',
];
forum_update_post($newpost, null);
// The student should be still the last post's author.
$this->assertEquals($student->id, $DB->get_field('forum_discussions', 'usermodified', ['id' => $discussion->id]));
}
}
+22
View File
@@ -651,4 +651,26 @@ class repository_dropbox_legacy extends repository {
} catch (moodle_exception $e) {}
}
}
/**
* Get dropbox options
* @param string $config
* @return mixed
*/
public function get_option($config = '') {
if ($config === 'dropbox_key') {
return trim(get_config('dropbox', 'dropbox_key'));
} else if ($config === 'dropbox_secret') {
return trim(get_config('dropbox', 'dropbox_secret'));
} else if ($config === 'dropbox_cachelimit') {
return $this->max_cache_bytes();
} else {
$options = parent::get_option();
$options['dropbox_key'] = trim(get_config('dropbox', 'dropbox_key'));
$options['dropbox_secret'] = trim(get_config('dropbox', 'dropbox_secret'));
$options['dropbox_cachelimit'] = $this->max_cache_bytes();
}
return $options;
}
}
+32 -3
View File
@@ -217,8 +217,8 @@ class core_user_external extends external_api {
profile_save_data((object) $user);
}
$userobject = (object)$user;
if ($createpassword) {
$userobject = (object)$user;
setnew_password_and_mail($userobject);
unset_user_preference('create_password', $userobject);
set_user_preference('auth_forcepasswordchange', 1, $userobject);
@@ -230,7 +230,7 @@ class core_user_external extends external_api {
// Preferences.
if (!empty($user['preferences'])) {
foreach ($user['preferences'] as $preference) {
set_user_preference($preference['type'], $preference['value'], $user['id']);
self::set_user_preference($preference['type'], $preference['value'], $userobject);
}
}
@@ -459,7 +459,7 @@ class core_user_external extends external_api {
// Preferences.
if (!empty($user['preferences'])) {
foreach ($user['preferences'] as $preference) {
set_user_preference($preference['type'], $preference['value'], $user['id']);
self::set_user_preference($preference['type'], $preference['value'], $existinguser);
}
}
}
@@ -1453,6 +1453,35 @@ class core_user_external extends external_api {
);
}
/**
* Validates preference value and updates the user preference
*
* @param string $name
* @param string $value
* @param stdClass $user
*/
protected static function set_user_preference($name, $value, $user) {
$preferences = array(
'auth_forcepasswordchange' => PARAM_BOOL,
'htmleditor' => PARAM_COMPONENT,
'usemodchooser' => PARAM_BOOL,
'badgeprivacysetting' => PARAM_BOOL,
'blogpagesize' => PARAM_INT,
'forum_markasreadonnotification' => PARAM_INT,
'calendar_timeformat' => PARAM_NOTAGS,
'calendar_startwday' => PARAM_INT,
'calendar_maxevents' => PARAM_INT,
'calendar_lookahead' => PARAM_INT,
'calendar_persistflt' => PARAM_INT
);
if (isset($preferences[$name])) {
$value = clean_param($value, $preferences[$name]);
if ($preferences[$name] == PARAM_BOOL) {
$value = (int)$value;
}
set_user_preference($name, $value, $user);
}
}
}
/**
+20 -2
View File
@@ -497,7 +497,14 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
'email' => 'usertest1@example.com',
'description' => 'This is a description for user 1',
'city' => 'Perth',
'country' => 'au'
'country' => 'au',
'preferences' => [[
'type' => 'htmleditor',
'value' => 'atto'
], [
'type' => 'invalidpreference',
'value' => 'abcd'
]]
);
$context = context_system::instance();
@@ -522,6 +529,8 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals($dbuser->description, $user1['description']);
$this->assertEquals($dbuser->city, $user1['city']);
$this->assertEquals($dbuser->country, $user1['country']);
$this->assertEquals('atto', get_user_preferences('htmleditor', null, $dbuser));
$this->assertEquals(null, get_user_preferences('invalidpreference', null, $dbuser));
}
// Call without required capability
@@ -676,7 +685,14 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
'email' => 'usertest1@example.com',
'description' => 'This is a description for user 1',
'city' => 'Perth',
'country' => 'au'
'country' => 'au',
'preferences' => [[
'type' => 'htmleditor',
'value' => 'atto'
], [
'type' => 'invalidpreference',
'value' => 'abcd'
]]
);
$context = context_system::instance();
@@ -712,6 +728,8 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals($dbuser->description, $user1['description']);
$this->assertEquals($dbuser->city, $user1['city']);
$this->assertEquals($dbuser->country, $user1['country']);
$this->assertEquals('atto', get_user_preferences('htmleditor', null, $dbuser));
$this->assertEquals(null, get_user_preferences('invalidpreference', null, $dbuser));
// Call without required capability.
$this->unassignUserCapability('moodle/user:update', $context->id, $roleid);
+2 -2
View File
@@ -29,11 +29,11 @@
defined('MOODLE_INTERNAL') || die();
$version = 2015111607.00; // 20151116 = branching date YYYYMMDD - do not modify!
$version = 2015111610.00; // 20151116 = branching date YYYYMMDD - do not modify!
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '3.0.7 (Build: 20161114)'; // Human-friendly version name
$release = '3.0.10 (Build: 20170508)'; // Human-friendly version name
$branch = '30'; // This version's branch.
$maturity = MATURITY_STABLE; // This version's maturity level.