MDL-24561 forum subscription checks sesskey
authorDavid Mudrak <david@moodle.com>
Wed, 5 Jan 2011 11:40:38 +0000 (12:40 +0100)
committerDavid Mudrak <david@moodle.com>
Wed, 5 Jan 2011 12:01:46 +0000 (13:01 +0100)
The only case when sesskey is not available is when we came to
subscribe.php from a link in email. In that case, we display a
confirmation page that redirects back providing the sesskey.
All other links to subscribe.php are fixed now so they provide sesskey
as a parameter.
I also polished $mode parameter handling a bit because the check
against empty string was not correct as the value is cast to PARAM_INT.

index.php
mod/forum/forum.js
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/subscribe.php

index f871c9f..8aa5b3a 100644 (file)
--- a/index.php
+++ b/index.php
                             $subtext = get_string('subscribe', 'forum');
                         }
                         echo $OUTPUT->heading($newsforum->name, 2, 'headingblock header');
-                        echo '<div class="subscribelink"><a href="mod/forum/subscribe.php?id='.$newsforum->id.'">'.$subtext.'</a></div>';
+                        $suburl = new moodle_url('/mod/forum/subscribe.php', array('id' => $newsforum->id, 'sesskey' => sesskey()));
+                        echo html_writer::tag('div', html_writer::link($suburl, $subtext), array('class' => 'subscribelink'));
                     } else {
                         echo $OUTPUT->heading($newsforum->name, 2, 'headingblock header');
                     }
index 3d47538..749b043 100644 (file)
@@ -5,7 +5,7 @@ function forum_produce_subscribe_link(forumid, backtoindex, ltext, ltitle) {
     var elementid = "subscriptionlink";
     var subs_link = document.getElementById(elementid);
     if(subs_link){
-        subs_link.innerHTML = "<a title="+ltitle+" href='"+M.cfg.wwwroot+"/mod/forum/subscribe.php?id="+forumid+backtoindex+"'>"+ltext+"<\/a>";
+        subs_link.innerHTML = "<a title='"+ltitle+"' href='"+M.cfg.wwwroot+"/mod/forum/subscribe.php?id="+forumid+backtoindex+"&amp;sesskey="+M.cfg.sesskey+"'>"+ltext+"<\/a>";
     }
 }
 
@@ -13,7 +13,7 @@ function forum_produce_tracking_link(forumid, ltext, ltitle) {
     var elementid = "trackinglink";
     var subs_link = document.getElementById(elementid);
     if(subs_link){
-        subs_link.innerHTML = "<a title="+ltitle+" href='"+M.cfg.wwwroot+"/mod/forum/settracking.php?id="+forumid+"'>"+ltext+"<\/a>";
+        subs_link.innerHTML = "<a title='"+ltitle+"' href='"+M.cfg.wwwroot+"/mod/forum/settracking.php?id="+forumid+"'>"+ltext+"<\/a>";
     }
 }
 
@@ -56,4 +56,4 @@ function unlockoption(form,item) {
     if (form.elements['h'+item]) {
         form.elements['h'+item].value=0;
     }
-}
\ No newline at end of file
+}
index 684390a..6985b4e 100644 (file)
@@ -96,6 +96,8 @@ $string['configreplytouser'] = 'When a forum post is mailed out, should it conta
 $string['configshortpost'] = 'Any post under this length (in characters not including HTML) is considered short (see below).';
 $string['configtrackreadposts'] = 'Set to \'yes\' if you want to track read/unread for each user.';
 $string['configusermarksread'] = 'If \'yes\', the user must manually mark a post as read. If \'no\', when the post is viewed it is marked as read.';
+$string['confirmsubscribe'] = 'Do you really want to subscribe to forum \'{$a}\'?';
+$string['confirmunsubscribe'] = 'Do you really want to unsubscribe from forum \'{$a}\'?';
 $string['couldnotadd'] = 'Could not add your post due to an unknown error';
 $string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it';
 $string['couldnotupdate'] = 'Could not update your post due to an unknown error';
index c5b5bcc..08269f6 100644 (file)
@@ -4504,10 +4504,11 @@ function forum_get_subscribe_link($forum, $context, $messages = array(), $cantac
 
         if ($fakelink) {
             $PAGE->requires->js('/mod/forum/forum.js');
-            $PAGE->requires->js_function_call('forum_produce_subscribe_link', Array($forum->id, $backtoindexlink, $linktext, $linktitle));
+            $PAGE->requires->js_function_call('forum_produce_subscribe_link', array($forum->id, $backtoindexlink, $linktext, $linktitle));
             $link = "<noscript>";
         }
-        $options ['id'] = $forum->id;
+        $options['id'] = $forum->id;
+        $options['sesskey'] = sesskey();
         $url = new moodle_url('/mod/forum/subscribe.php', $options);
         $link .= $OUTPUT->single_button($url, $linktext, 'get', array('title'=>$linktitle));
         if ($fakelink) {
@@ -7496,10 +7497,10 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi
     if ($canmanage) {
         $mode = $forumnode->add(get_string('subscriptionmode', 'forum'), null, navigation_node::TYPE_CONTAINER);
 
-        $allowchoice = $mode->add(get_string('subscriptionoptional', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'0')), navigation_node::TYPE_SETTING);
-        $forceforever = $mode->add(get_string("subscriptionforced", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'1')), navigation_node::TYPE_SETTING);
-        $forceinitially = $mode->add(get_string("subscriptionauto", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'2')), navigation_node::TYPE_SETTING);
-        $disallowchoice = $mode->add(get_string('subscriptiondisabled', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'3')), navigation_node::TYPE_SETTING);
+        $allowchoice = $mode->add(get_string('subscriptionoptional', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_CHOOSESUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
+        $forceforever = $mode->add(get_string("subscriptionforced", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_FORCESUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
+        $forceinitially = $mode->add(get_string("subscriptionauto", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_INITIALSUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
+        $disallowchoice = $mode->add(get_string('subscriptiondisabled', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_DISALLOWSUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
 
         switch ($subscriptionmode) {
             case FORUM_CHOOSESUBSCRIBE : // 0
@@ -7544,7 +7545,7 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi
         } else {
             $linktext = get_string('subscribe', 'forum');
         }
-        $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id));
+        $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'sesskey'=>sesskey()));
         $forumnode->add($linktext, $url, navigation_node::TYPE_SETTING);
     }
 
index 75efa7b..021c1d7 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Subscribe to or unsubscribe from a forum.
+ * Subscribe to or unsubscribe from a forum or manage forum subscription mode
  *
- * @package mod-forum
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * This script can be used by either individual users to subscribe to or
+ * unsubscribe from a forum (no 'mode' param provided), or by forum managers
+ * to control the subscription mode (by 'mode' param).
+ * This script can be called from a link in email so the sesskey is not
+ * required parameter. However, if sesskey is missing, the user has to go
+ * through a confirmation page that redirects the user back with the
+ * sesskey.
+ *
+ * @package    mod
+ * @subpackage forum
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once("../../config.php");
-require_once("lib.php");
+require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+require_once($CFG->dirroot.'/mod/forum/lib.php');
 
-$id = required_param('id',PARAM_INT);      // The forum to subscribe or unsubscribe to
-$mode = optional_param('mode',false,PARAM_INT);  // Force everyone to be subscribed to this forum?
-$user = optional_param('user',0,PARAM_INT);
+$id      = required_param('id', PARAM_INT);             // the forum to subscribe or unsubscribe to
+$mode    = optional_param('mode', null, PARAM_INT);     // the forum's subscription mode
+$user    = optional_param('user', 0, PARAM_INT);        // userid of the user to subscribe, defaults to $USER
+$sesskey = optional_param('sesskey', null, PARAM_RAW);  // sesskey
 
 $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$id));
-if ($mode !== '') {
+if (!is_null($mode)) {
     $url->param('mode', $mode);
 }
 if ($user !== 0) {
     $url->param('user', $user);
 }
-$PAGE->set_url($url);
-
-if (! $forum = $DB->get_record("forum", array("id" => $id))) {
-    print_error('invalidforumid', 'forum');
-}
-
-if (! $course = $DB->get_record("course", array("id" => $forum->course))) {
-    print_error('invalidcoursemodule');
+if (!is_null($sesskey)) {
+    $url->param('sesskey', $sesskey);
 }
+$PAGE->set_url($url);
 
-$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id, false, MUST_EXIST);
+$forum   = $DB->get_record('forum', array('id' => $id), '*', MUST_EXIST);
+$course  = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST);
+$cm      = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST);
 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
 if ($user) {
+    require_sesskey();
     if (!has_capability('mod/forum:managesubscriptions', $context)) {
         print_error('nopermissiontosubscribe', 'forum');
     }
-    if (!$user = $DB->get_record("user", array("id" => $user))) {
-        print_error('invaliduserid');
-    }
+    $user = $DB->get_record('user', array('id' => $user), MUST_EXIST);
 } else {
     $user = $USER;
 }
 
 if (isset($cm->groupmode) && empty($course->groupmodeforce)) {
-    $groupmode =  $cm->groupmode;
+    $groupmode = $cm->groupmode;
 } else {
     $groupmode = $course->groupmode;
 }
@@ -74,7 +80,7 @@ if ($groupmode && !forum_is_subscribed($user->id, $forum) && !has_capability('mo
 
 require_login($course->id, false, $cm);
 
-if (!is_enrolled($context)) {   // Guests and visitors can't subscribe - only enrolled
+if (is_null($mode) and !is_enrolled($context)) {   // Guests and visitors can't subscribe - only enrolled
     $PAGE->set_title($course->shortname);
     $PAGE->set_heading($course->fullname);
     echo $OUTPUT->header();
@@ -88,7 +94,8 @@ $returnto = optional_param('backtoindex',0,PARAM_INT)
     ? "index.php?id=".$course->id
     : "view.php?f=$id";
 
-if ($mode !== false && has_capability('mod/forum:managesubscriptions', $context)) {
+if (!is_null($mode) and has_capability('mod/forum:managesubscriptions', $context)) {
+    require_sesskey();
     switch ($mode) {
         case FORUM_CHOOSESUBSCRIBE : // 0
             forum_forcesubscribe($forum->id, 0);
@@ -119,6 +126,16 @@ $info->name  = fullname($user);
 $info->forum = format_string($forum->name);
 
 if (forum_is_subscribed($user->id, $forum->id)) {
+    if (is_null($sesskey)) {    // we came here via link in email
+        $PAGE->set_title($course->shortname);
+        $PAGE->set_heading($course->fullname);
+        echo $OUTPUT->header();
+        echo $OUTPUT->confirm(get_string('confirmunsubscribe', 'forum', format_string($forum->name)),
+                new moodle_url($PAGE->url, array('sesskey' => sesskey())), new moodle_url('/mod/forum/view.php', array('f' => $id)));
+        echo $OUTPUT->footer();
+        exit;
+    }
+    require_sesskey();
     if (forum_unsubscribe($user->id, $forum->id)) {
         add_to_log($course->id, "forum", "unsubscribe", "view.php?f=$forum->id", $forum->id, $cm->id);
         redirect($returnto, get_string("nownotsubscribed", "forum", $info), 1);
@@ -134,6 +151,16 @@ if (forum_is_subscribed($user->id, $forum->id)) {
     if (!has_capability('mod/forum:viewdiscussion', $context)) {
         print_error('noviewdiscussionspermission', 'forum', $_SERVER["HTTP_REFERER"]);
     }
+    if (is_null($sesskey)) {    // we came here via link in email
+        $PAGE->set_title($course->shortname);
+        $PAGE->set_heading($course->fullname);
+        echo $OUTPUT->header();
+        echo $OUTPUT->confirm(get_string('confirmsubscribe', 'forum', format_string($forum->name)),
+                new moodle_url($PAGE->url, array('sesskey' => sesskey())), new moodle_url('/mod/forum/view.php', array('f' => $id)));
+        echo $OUTPUT->footer();
+        exit;
+    }
+    require_sesskey();
     forum_subscribe($user->id, $forum->id);
     add_to_log($course->id, "forum", "subscribe", "view.php?f=$forum->id", $forum->id, $cm->id);
     redirect($returnto, get_string("nowsubscribed", "forum", $info), 1);