Index: version.php
===================================================================
RCS file: /cvsroot/moodle/moodle/version.php,v
retrieving revision 1.781
diff -u -r1.781 version.php
--- version.php	26 Aug 2008 07:20:56 -0000	1.781
+++ version.php	26 Aug 2008 14:50:14 -0000
@@ -6,7 +6,7 @@
 // This is compared against the values stored in the database to determine
 // whether upgrades should be performed (see lib/db/*.php)
 
-    $version = 2008082601;  // YYYYMMDD   = date of the last version bump
+    $version = 2008082602;  // YYYYMMDD   = date of the last version bump
                             //         XX = daily increments
 
     $release = '2.0 dev (Build: 20080826)';  // Human-friendly version name
Index: admin/settings/appearance.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/settings/appearance.php,v
retrieving revision 1.37
diff -u -r1.37 appearance.php
--- admin/settings/appearance.php	26 Jul 2008 15:15:25 -0000	1.37
+++ admin/settings/appearance.php	26 Aug 2008 14:50:14 -0000
@@ -44,6 +44,9 @@
     $temp->add(new admin_setting_special_calendar_weekend());
     $temp->add(new admin_setting_configtext('calendar_lookahead',get_string('configlookahead','admin'),get_string('helpupcominglookahead', 'admin'),21,PARAM_INT));
     $temp->add(new admin_setting_configtext('calendar_maxevents',get_string('configmaxevents','admin'),get_string('helpupcomingmaxevents', 'admin'),10,PARAM_INT));
+    $temp->add(new admin_setting_configcheckbox('calendar_enablerssfeeds', get_string('calendar_enablerssfeeds', 'admin'), get_string('configcalendarenablerssfeeds', 'admin'), 0));
+$temp->add(new admin_setting_configtext('calendarrssarticles', get_string('rssarticles'),
+                                        '', 25));
     $ADMIN->add('appearance', $temp);
 
     // "htmleditor" settingpage
Index: blocks/calendar_month/block_calendar_month.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/calendar_month/block_calendar_month.php,v
retrieving revision 1.35
diff -u -r1.35 block_calendar_month.php
--- blocks/calendar_month/block_calendar_month.php	3 Mar 2008 20:40:03 -0000	1.35
+++ blocks/calendar_month/block_calendar_month.php	26 Aug 2008 14:50:14 -0000
@@ -12,6 +12,7 @@
 
     function get_content() {
         global $USER, $CFG, $SESSION, $COURSE;
+        
         $cal_m = optional_param( 'cal_m', 0, PARAM_INT );
         $cal_y = optional_param( 'cal_y', 0, PARAM_INT );
 
@@ -75,6 +76,12 @@
             
         }
         
+        // RSS Feed icon - MDL-15162 (	MDL-15122 )
+        if ($CFG->enablerssfeeds && $CFG->calendar_enablerssfeeds && !empty($USER->id)) {
+                require_once($CFG->dirroot.'/lib/rsslib.php');   // We'll need this                                                              
+                $this->content->footer .= '<div>'.rss_get_link(get_context_instance(CONTEXT_COURSE,$courseshown), $USER->id, 'calendar', $courseshown).'</div>';
+            } 
+            
         // MDL-9059, unset this so that it doesn't stay in session
         if (!empty($courseset)) {
             unset($SESSION->cal_courses_shown[$COURSE->id]);
Index: blocks/calendar_upcoming/block_calendar_upcoming.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/calendar_upcoming/block_calendar_upcoming.php,v
retrieving revision 1.30
diff -u -r1.30 block_calendar_upcoming.php
--- blocks/calendar_upcoming/block_calendar_upcoming.php	17 Apr 2008 19:19:55 -0000	1.30
+++ blocks/calendar_upcoming/block_calendar_upcoming.php	26 Aug 2008 14:50:14 -0000
@@ -8,6 +8,7 @@
 
     function get_content() {
         global $USER, $CFG, $SESSION, $COURSE;
+       
         $cal_m = optional_param( 'cal_m', 0, PARAM_INT );
         $cal_y = optional_param( 'cal_y', 0, PARAM_INT );
 
@@ -25,20 +26,32 @@
         
             $courseshown = false;
             $filtercourse = array();
-            $this->content->footer = '';
+            /// If RSS is activated at site and calendar level show rss icon and link 
+            if ($CFG->enablerssfeeds && $CFG->calendar_enablerssfeeds && !empty($USER->id)) {
+                require_once($CFG->dirroot.'/lib/rsslib.php');   // We'll need this
+                                
+                $this->content->footer = '<div>'.rss_get_link(SYSCONTEXTID, $USER->id, 'calendar', SITEID).'</div>';
+            } 
 
         } else {
             $courseshown = $COURSE->id;
-            $this->content->footer = '<br /><a href="'.$CFG->wwwroot.
+            $this->content->footer = '<div><a href="'.$CFG->wwwroot.
                                      '/calendar/view.php?view=upcoming&amp;course='.$courseshown.'">'.
-                                      get_string('gotocalendar', 'calendar').'</a>...';
+                                      get_string('gotocalendar', 'calendar').'</a>...</div>';
             $context = get_context_instance(CONTEXT_COURSE, $courseshown);
             if (has_capability('moodle/calendar:manageentries', $context) ||
                 has_capability('moodle/calendar:manageownentries', $context)) {
-                $this->content->footer .= '<br /><a href="'.$CFG->wwwroot.
+                $this->content->footer .= '<div><a href="'.$CFG->wwwroot.
                                           '/calendar/event.php?action=new&amp;course='.$courseshown.'">'.
-                                           get_string('newevent', 'calendar').'</a>...';
+                                           get_string('newevent', 'calendar').'</a>...</div>';
+            } 
+            /// MDL-15162 (	MDL-15122 ): If RSS is activated at site and calendar level show rss icon and link 
+            if ($CFG->enablerssfeeds && $CFG->calendar_enablerssfeeds && !empty($USER->id)) {
+                require_once($CFG->dirroot.'/lib/rsslib.php');   // We'll need this
+                
+                $this->content->footer .= '<div>'.rss_get_link(get_context_instance(CONTEXT_COURSE,$courseshown), $USER->id, 'calendar', $courseshown).'</div>';
             } 
+            
             if ($courseshown == SITEID) {
                 // Being displayed at site level. This will cause the filter to fall back to auto-detecting
                 // the list of courses it will be grabbing events from.
Index: blocks/course_list/block_course_list.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/course_list/block_course_list.php,v
retrieving revision 1.52
diff -u -r1.52 block_course_list.php
--- blocks/course_list/block_course_list.php	2 Jun 2008 21:47:32 -0000	1.52
+++ blocks/course_list/block_course_list.php	26 Aug 2008 14:50:14 -0000
@@ -1,6 +1,7 @@
 <?PHP //$Id: block_course_list.php,v 1.52 2008/06/02 21:47:32 skodak Exp $
 
 include_once($CFG->dirroot . '/course/lib.php');
+include_once($CFG->dirroot.'/course/rsslib.php');
 
 class block_course_list extends block_list {
     function init() {
@@ -38,14 +39,21 @@
             !empty($USER->id) and 
             !(has_capability('moodle/course:update', get_context_instance(CONTEXT_SYSTEM)) and $adminseesall) and
             !isguest()) {    // Just print My Courses
-            if ($courses = get_my_courses($USER->id, 'visible DESC, fullname ASC')) {
+            if ($courses = get_my_courses($USER->id, 'visible DESC, fullname ASC','rsstype')) {
+                $rsspossible=0;
                 foreach ($courses as $course) {
                     if ($course->id == SITEID) {
                         continue;
                     }
                     $linkcss = $course->visible ? "" : " class=\"dimmed\" ";
+                    if ($CFG->enablerssfeeds && $course->rsstype) {
+                        $rss = recent_rss_link($course->id);
+                        $rsspossible=1;
+                    } else {
+                        $rss = '';
+                    }                               
                     $this->content->items[]="<a $linkcss title=\"" . format_string($course->shortname) . "\" ".
-                               "href=\"$CFG->wwwroot/course/view.php?id=$course->id\">" . format_string($course->fullname) . "</a>";
+                               "href=\"$CFG->wwwroot/course/view.php?id=$course->id\">" . format_string($course->fullname) . "</a>".$rss;
                     $this->content->icons[]=$icon;
                 }
                 $this->title = get_string('mycourses');
@@ -54,6 +62,9 @@
                     $this->content->footer = "<a href=\"$CFG->wwwroot/course/index.php\">".get_string("fulllistofcourses")."</a> ...";
                 }
                 $this->get_remote_courses();
+                if ($rsspossible) {
+                    $this->content->footer .= '<div>'.mymoodle_rss_link().'</div>';
+                }
                 if ($this->content->items) { // make sure we don't return an empty list
                     return $this->content;
                 }
@@ -75,16 +86,20 @@
                 $this->title = get_string('categories');
             } else {                          // Just print course names of single category
                 $category = array_shift($categories);
-                $courses = get_courses($category->id);
+                $courses = get_courses($category->id, 'c.sortorder ASC', 'c.rsstype');
 
                 if ($courses) {
                     foreach ($courses as $course) {
                         $linkcss = $course->visible ? "" : " class=\"dimmed\" ";
-
+                        if ($CFG->enablerssfeeds && $course->rsstype>0) {
+                            $rss = recent_rss_link($course->id);                            
+                        } else {
+                            $rss = '';
+                        }    
                         $this->content->items[]="<a $linkcss title=\""
                                    . format_string($course->shortname)."\" ".
                                    "href=\"$CFG->wwwroot/course/view.php?id=$course->id\">" 
-                                   .  format_string($course->fullname) . "</a>";
+                                   .  format_string($course->fullname) . "</a>".$rss;
                         $this->content->icons[]=$icon;
                     }
                 /// If we can update any course of the view all isn't hidden, show the view all courses link
Index: blocks/news_items/block_news_items.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/news_items/block_news_items.php,v
retrieving revision 1.26
diff -u -r1.26 block_news_items.php
--- blocks/news_items/block_news_items.php	3 Mar 2008 11:43:34 -0000	1.26
+++ blocks/news_items/block_news_items.php	26 Aug 2008 14:50:14 -0000
@@ -102,7 +102,7 @@
                 } else {
                     $userid = $USER->id;
                 }
-                $this->content->footer .= '<br />'.rss_get_link($COURSE->id, $userid, 'forum', $forum->id, $tooltiptext);
+                $this->content->footer .= '<div>'.rss_get_link($context, $userid, 'forum', $forum->id, $tooltiptext).'</div>';
             }
 
         }
Index: blocks/recent_activity/block_recent_activity.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/recent_activity/block_recent_activity.php,v
retrieving revision 1.11
diff -u -r1.11 block_recent_activity.php
--- blocks/recent_activity/block_recent_activity.php	3 Mar 2008 11:43:34 -0000	1.11
+++ blocks/recent_activity/block_recent_activity.php	26 Aug 2008 14:50:14 -0000
@@ -7,7 +7,7 @@
     }
 
     function get_content() {
-        global $COURSE;
+        global $COURSE,$CFG;
 
         if ($this->content !== NULL) {
             return $this->content;
@@ -20,7 +20,10 @@
 
         $this->content = new stdClass;
         $this->content->text = '';
-        $this->content->footer = '';
+        if ($CFG->enablerssfeeds && $COURSE->rsstype) {
+            require_once($CFG->dirroot.'/course/rsslib.php');
+            $this->content->footer = recent_rss_link($COURSE->id);
+        }         
 
         // Slightly hacky way to do it but...
         ob_start();
Index: blog/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/lib.php,v
retrieving revision 1.100
diff -u -r1.100 lib.php
--- blog/lib.php	31 Jul 2008 22:15:31 -0000	1.100
+++ blog/lib.php	26 Aug 2008 14:50:14 -0000
@@ -463,13 +463,18 @@
 
     /**
      * Main filter function.
+     * @param int $newsince fetch posts only since $newsince
+     * @param bool $checkonly if true, then this function just checks if non-empty result is possible       
      */
-    function blog_fetch_entries($postid='', $fetchlimit=10, $fetchstart='', $filtertype='', $filterselect='', $tagid='', $tag ='', $sort='lastmodified DESC', $limit=true) {
+    function blog_fetch_entries($postid='', $fetchlimit=10, $fetchstart='', $filtertype='', $filterselect='', $tagid='', $tag ='', $sort='lastmodified DESC', $limit=true,$newsince='',$checkonly=0) {
         global $CFG, $USER, $DB;
 
         /// the post table will be used for other things too
         $typesql = "AND p.module = 'blog'";
 
+        if (!empty($newsince)) {
+            $newsince = 'AND p.lastmodified = "'.$newsince.'"';
+        }
         /// set the tag id for searching
         if ($tagid) {
             $tag = $tagid;
@@ -487,7 +492,7 @@
         if ($postid) {
             if ($post = $DB->get_record('post', array('id'=>$postid))) {
 
-                if (blog_user_can_view_user_post($post->userid, $post)) {
+                if ($checkonly || blog_user_can_view_user_post($post->userid, $post)) {
 
                     if ($user = $DB->get_record('user', array('id'=>$post->userid))) {
                         $post->email = $user->email;
@@ -516,7 +521,7 @@
             $tagquerysql = '';
         }
 
-        if (isloggedin() && !has_capability('moodle/legacy:guest', get_context_instance(CONTEXT_SYSTEM), $USER->id, false)) {
+        if (!$checkonly && isloggedin() && !has_capability('moodle/legacy:guest', get_context_instance(CONTEXT_SYSTEM), $USER->id, false)) {
             $permissionsql = "AND (p.publishstate = 'site' OR p.publishstate = 'public' OR p.userid = :userid)";
             $params['userid'] = $USER->id;
         } else {
@@ -525,11 +530,16 @@
 
         // fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs
         // admins can see all blogs regardless of publish states, as described on the help page
-        if (has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_SYSTEM))) {
+        if (!$checkonly && has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_SYSTEM))) {
             $permissionsql = '';
-        } else if ($filtertype=='user' && has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_USER, $filterselect))) {
+        } else if (!$checkonly && $filtertype=='user' && has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_USER, $filterselect))) {
             $permissionsql = '';
         }
+                
+        // No permission test, if we are just checking
+        if ($checkonly) {
+            $permisssionsql = '';                           
+        }
         /****************************************
          * depending on the type, there are 4   *
          * different possible sqls              *
@@ -549,7 +559,7 @@
                           FROM {post} p, {user} u $tagtablesql
                          WHERE p.userid = u.id $tagquerysql
                                AND u.deleted = 0
-                               $permissionsql $typesql";
+                               $permissionsql $typesql $newsince";
 
             break;
 
@@ -558,7 +568,7 @@
                 $context = get_context_instance(CONTEXT_COURSE, $filterselect);
 
                 // MDL-10037, hidden users' blogs should not appear
-                if (has_capability('moodle/role:viewhiddenassigns', $context)) {
+                if (!$checkonly && has_capability('moodle/role:viewhiddenassigns', $context)) {
                     $hiddensql = '';
                 } else {
                     $hiddensql = 'AND ra.hidden = 0';
@@ -570,7 +580,7 @@
                                AND ra.contextid ".get_related_contexts_string($context)."
                                AND u.id = p.userid
                                AND u.deleted = 0
-                               $hiddensql $permissionsql $typesql";
+                               $hiddensql $permissionsql $typesql $newsince";
 
             break;
 
@@ -581,7 +591,7 @@
                          WHERE p.userid = gm.userid AND u.id = p.userid $tagquerysql
                                AND gm.groupid = :groupid
                                AND u.deleted = 0
-                               $permissionsql $typesql";
+                               $permissionsql $typesql $newsince";
                 $params['groupid'] = $filterselect;
             break;
 
@@ -592,7 +602,7 @@
                          WHERE p.userid = u.id $tagquerysql
                                AND u.id = :uid
                                AND u.deleted = 0
-                               $permissionsql $typesql";
+                               $permissionsql $typesql $newsince";
                $params['uid'] = $filterselect;
             break;
         }
@@ -609,6 +619,10 @@
 
         $records = $DB->get_records_sql("$SQL $orderby", $params, $limitfrom, $limitnum);
 
+        if ($checkonly) {
+            return (!empty($records));        
+        }
+        
         if (empty($records)) {
             return array();
         }
Index: blog/rsslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/rsslib.php,v
retrieving revision 1.15
diff -u -r1.15 rsslib.php
--- blog/rsslib.php	10 Jul 2008 09:55:11 -0000	1.15
+++ blog/rsslib.php	26 Aug 2008 14:50:14 -0000
@@ -4,67 +4,185 @@
     require_once($CFG->dirroot .'/blog/lib.php');
 
 
-    // This function returns the icon (from theme) with the link to rss/file.php
-    // needs some hacking to rss/file.php
+    /**
+     *     This function returns the icon (from theme) with the link to rss/file.php
+     */
     function blog_rss_print_link($filtertype, $filterselect, $tagid=0, $tooltiptext='') {
 
-        global $CFG, $USER;
+        global $CFG, $USER, $DB;
 
         if (empty($USER->id)) {
             $userid = 1;
+            $gen_hash_key=0;              
         } else {
             $userid = $USER->id;
+            $gen_hash_key=1;
+        }
+                
+        $courseid = SITEID;
+                            
+        $info = array($filterselect);
+           
+        if ($tagid) {        
+            $info[] = $tagid;
         }
 
         switch ($filtertype) {
             case 'site':
-                $path = SITEID.'/'.$userid.'/blog/site/'.SITEID;
+                $path = rss_get_url(SYSCONTEXTID,$userid,'blog','site',SITEID);                
             break;
             case 'course':
-                $path = $filterselect.'/'.$userid.'/blog/course/'.$filterselect;
+                $path = rss_get_url(SYSCONTEXTID,$userid,'blog','course',$info);                
+                $courseid = $filterselect;
             break;
             case 'group':
-                $path = SITEID.'/'.$userid.'/blog/group/'.$filterselect;  
+                $path = rss_get_url(SYSCONTEXTID,$userid,'blog','group',$info);                  
             break;
             case 'user':
-                $path = SITEID.'/'.$userid.'/blog/user/'.$filterselect;
+                $path = rss_get_url(SYSCONTEXTID,$userid,'blog','user',$info);                
             break;
         }
 
-        if ($tagid) {
-            $path .= '/'.$tagid;
-        }
 
-        $path .= '/rss.xml';
         $rsspix = $CFG->pixpath .'/i/rss.gif';
 
-        require_once($CFG->libdir.'/filelib.php');
-        $path = get_file_url($path, null, 'rssfile');
         print '<div align="right"><a href="'. $path .'"><img src="'. $rsspix .'" title="'. strip_tags($tooltiptext) .'" alt="'.get_string('rss').'" /></a></div>';
+    }
 
+    /**
+     *  This function returns true if there are new blog posts since $time 
+     *  Otherwise it returns false.
+     */         
+    function blog_rss_newstuff($type,$time,&$cache,$info) {    
+        $id=(int)$info[0];
+        if (isset($info[1])) {
+            $tagid=(int)$info[1];
+        }
+        else {
+            $tagid=0;
+        } 
+       $status = blog_fetch_entries('', 20, '', $type, $id, $tagid, '', 'lastmodified DESC', true, $time, 1);
+       $cache['time']=$time;
+       return $status;
     }
 
 
-    // Generate any blog RSS feed via one function (called by ../rss/file.php)
-    function blog_generate_rss_feed($type, $id, $tagid=0) {
-        global $CFG, $SITE, $DB;
 
-        if (empty($CFG->enablerssfeeds)) {
-            debugging('Sorry, RSS feeds are disabled on this site');
-            return '';
-        }
+    /**
+     * Generate any blog RSS feed via one function (called by ../rss/file.php)
+     * @param string $type
+     * @param mixed $info additional information about feed
+     * @return string XML code                       
+     */     
+    function blog_rss_generate_feed($type, $context, $info, &$cache) {
+        global $CFG, $SITE, $DB, $USER;
+        
+        $id=(int)$info[0];
+        if (isset($info[1])) {
+            $tagid=(int)$info[1];
+        }
+        else {
+            $tagid=0;
+        }
+
+        $sitecontext = get_context_instance(CONTEXT_SYSTEM);
+   
+        //Check access first     
+        switch ($type) {
+
+            case 'site':                
+                if ($CFG->bloglevel < BLOG_SITE_LEVEL) {                
+                    rss_error('siteblogdisable', 'blog');                   
+            }
+                
+                if (!has_capability('moodle/blog:view', $sitecontext)) {                
+                    rss_error('cannotviewsiteblog', 'blog');                    
+                }
+            break;
 
-        $filename = blog_rss_file_name($type, $id, $tagid);
+            case 'course':
+                if ($CFG->bloglevel < BLOG_COURSE_LEVEL) {
+                    rss_error('courseblogdisable', 'blog');                   
+                }
+                if (!$course = $DB->get_record('course', array('id'=>$id))) {
+                    rss_error('invalidcourseid');                    
+                }
+                $courseid = $course->id;
+                $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);                
+                if (!has_capability('moodle/blog:view', $coursecontext)) {
+                    rss_error('cannotviewcourseblog', 'blog');                    
+                }
+            break;
 
-        if (file_exists($filename)) {
-            if (filemtime($filename) + 3600 > time()) {
-                return $filename;   /// It's already done so we return cached version
+            case 'group':
+                if ($CFG->bloglevel < BLOG_GROUP_LEVEL) {
+                    rss_error('groupblogdisable', 'blog');
+                }
+               
+                if (! $group = groups_get_group($id)) { //TODO:check.
+                    rss_error('invalidgroupid');
+                }
+                if (!$course = $DB->get_record('course', array('id'=>$group->courseid))) {
+                    rss_error('invalidcourseid');
+                }
+                $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
+                $courseid = $course->id;
+                if (!has_capability('moodle/blog:view', $coursecontext)) {
+                    rss_error('cannotviewcourseorgroupblog', 'blog');
+                }
+                if (groups_get_course_groupmode($course) == SEPARATEGROUPS
+                    and !has_capability('moodle/site:accessallgroups', $coursecontext)) {
+                    if (!groups_is_member($id)) {
+                        rss_error('notmemberofgroup');
+                    }
+                }
+
+            break;
+
+            case 'user':
+                if ($CFG->bloglevel < BLOG_USER_LEVEL) {
+                    rss_error('blogdisable', 'blog');
+                }
+                if (!$user = $DB->get_record('user', array('id'=>$id))) {
+                    rss_error('invaliduserid');
+                }
+                if ($USER->id == $id) {
+                    if (!has_capability('moodle/blog:create', $sitecontext)
+                        and !has_capability('moodle/blog:view', $sitecontext)) {
+                        rss_error('donothaveblog', 'blog');
+                    }
+                } else {
+                    $personalcontext = get_context_instance(CONTEXT_USER, $id);
+                    if (!has_capability('moodle/blog:view', $sitecontext) 
+                        and !has_capability('moodle/user:readuserblogs', $personalcontext)) {
+                        rss_error('cannotviewuserblog', 'blog');
+                    }
+                    if (!blog_user_can_view_user_post($id)) {
+                        rss_error('cannotviewcourseblog', 'blog');
+                    }
+                }
+                $userid = $id;
+
+            
+            break;
+
+            default:
+                 rss_error('accessdenied');
+            break;
             }
+
+        if (!isset($cache['time'])) {
+            $cache['time'] = '';
+        }
+        
+        $limit = get_user_preferences( 'rss_maxitems', $CFG->blogrssarticles );
+        if (!$limit || $limit > $CFG->blogrssarticles) {
+        	  $limit = $CFG->blogrssarticles;
         }
 
     /// Get all the posts from the database
+        $blogposts = blog_fetch_entries('', $limit, '', $type, $id, $tagid, '', 'lastmodified DESC', true, $cache['time']);
 
-        $blogposts = blog_fetch_entries('', 20, '', $type, $id, $tagid);
 
     /// Now generate an array of RSS items
         if ($blogposts) {
@@ -84,7 +202,6 @@
         }
 
     /// Get header and footer information
-     
         switch ($type) {
             case 'user':
                 $info = fullname($DB->get_record('user', array('id'=>$id), 'firstname,lastname'));
@@ -119,42 +236,11 @@
 
         $rssdata = $header.$articles.$footer;
 
-        if (blog_rss_save_file($type,$id,$tagid,$rssdata)) {
-            return $filename;
-        } else {
-            return false;   // Couldn't find it or make it
-        }
+        return $rssdata;
     }
 
 
-    function blog_rss_file_name($type, $id, $tagid=0) {
-        global $CFG;
 
-        if ($tagid) {
-            return "$CFG->dataroot/rss/blog/$type/$id/$tagid.xml";
-        } else {
-            return "$CFG->dataroot/rss/blog/$type/$id.xml";
-        }
-    }
     
-    //This function saves to file the rss feed specified in the parameters
-    function blog_rss_save_file($type, $id, $tagid=0, $contents='') {
-        global $CFG;
-
-        if (! $basedir = make_upload_directory("rss/blog/$type/$id")) {
-            return false;
-        }
-
-        $file = blog_rss_file_name($type, $id, $tagid);
-        $rss_file = fopen($file, 'w');
-        if ($rss_file) {
-            $status = fwrite ($rss_file, $contents);
-            fclose($rss_file);
-        } else {
-            $status = false;
-        }
-
-        return $status;
-    }
 
 ?>
Index: calendar/view.php
===================================================================
RCS file: /cvsroot/moodle/moodle/calendar/view.php,v
retrieving revision 1.103
diff -u -r1.103 view.php
--- calendar/view.php	1 Jun 2008 14:25:06 -0000	1.103
+++ calendar/view.php	26 Aug 2008 14:50:15 -0000
@@ -137,8 +137,21 @@
 
     // Print title and header
     $navigation = build_navigation($navlinks);
+    
+    if (!empty($CFG->enablerssfeeds) && !empty($CFG->calendar_enablerssfeeds) && !empty($USER->id)) {
+        require_once($CFG->dirroot.'/lib/rsslib.php');    
+        $flt='';
+        if (intval(get_user_preferences('calendar_persistflt', 0))) {
+            $flt=calendar_get_filters_status();            
+        }                                          
+        $rsslink = rss_get_link(get_context_instance(CONTEXT_COURSE, $courseid), $USER->id, 'calendar', $courseid,get_string('rss'),$flt);
+        $rsspath = rss_get_url(get_context_instance(CONTEXT_COURSE, $courseid), $USER->id, 'calendar', $courseid,$flt);
+        $meta = '<link rel="alternate" type="application/rss+xml" ';
+        $meta .= 'title ="'. format_string($strcalendar) .' RSS" href="'.$rsspath.'" />';
+    }     
+    
     print_header("$site->shortname: $strcalendar: $pagetitle", $strcalendar, $navigation,
-                 '', '', true, $prefsbutton, user_login_string($site));
+                 '', $meta, true, $prefsbutton, user_login_string($site));
 
     echo calendar_overlib_html();
 
@@ -176,6 +189,9 @@
              .'alt="'.get_string('ical', 'calendar').'" '
              .'title="'.get_string('quickdownloadcalendar', 'calendar').'" />'
              .'</a>';
+        if (isset($CFG->enablerssfeeds) && isset($CFG->calendar_enablerssfeeds) && !empty($USER->id)) {
+                echo $rsslink;
+        } 
     }
 
     echo '</div>';
Index: course/edit_form.php
===================================================================
RCS file: /cvsroot/moodle/moodle/course/edit_form.php,v
retrieving revision 1.49
diff -u -r1.49 edit_form.php
--- course/edit_form.php	28 Jul 2008 12:31:31 -0000	1.49
+++ course/edit_form.php	26 Aug 2008 14:50:15 -0000
@@ -342,6 +342,32 @@
 
         }
 
+        if ($CFG->enablerssfeeds) {
+//-------------------------------------------------------------------------------
+            $mform->addElement('header', '', get_string('rss'));
+            $choices = array();
+            $choices[0] = get_string('disable');
+            $choices[1] = get_string('enable');            
+            $mform->addElement('select', 'rsstype', get_string('recentactivity'), $choices);
+            $choices = array();
+            $choices[0] = '0';
+            $choices[1] = '1';
+            $choices[2] = '2';
+            $choices[3] = '3';
+            $choices[4] = '4';
+            $choices[5] = '5';
+            $choices[10] = '10';
+            $choices[15] = '15';
+            $choices[20] = '20';
+            $choices[25] = '25';
+            $choices[30] = '30';
+            $choices[40] = '40';
+            $choices[50] = '50';
+            $mform->addElement('select', 'rssarticles', get_string('rssarticles'), $choices);
+            $mform->setHelpButton('rssarticles', array('rssarticles', get_string('rssarticles')),true);          
+        }
+
+//-------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
         $mform->addElement('header','', get_string('language'));
 
Index: course/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/course/lib.php,v
retrieving revision 1.614
diff -u -r1.614 lib.php
--- course/lib.php	22 Aug 2008 15:46:30 -0000	1.614
+++ course/lib.php	26 Aug 2008 14:50:16 -0000
@@ -1044,9 +1044,10 @@
  * Returns reference to full info about modules in course (including visibility).
  * Cached and as fast as possible (0 or 1 db query).
  * @param $course object or 'reset' string to reset caches, modinfo may be updated in db
+ * @param bool $checkonly if true skips has_capability tests. Needed for special no-content mode ( RSS )
  * @return mixed courseinfo object or nothing if resetting
  */
-function &get_fast_modinfo(&$course, $userid=0) {
+function &get_fast_modinfo(&$course, $userid=0, $checkonly=0) {
     global $CFG, $USER, $DB;
 
     static $cache = array();
@@ -1145,9 +1146,9 @@
         }
         $cm->modplural = $modlurals[$cm->modname];
 
+        if (!$checkonly) {
         if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $contexts[$cm->id], $userid)) {
             $cm->uservisible = false;
-
         } else if (!empty($CFG->enablegroupings) and !empty($cm->groupmembersonly)
                 and !has_capability('moodle/site:accessallgroups', $contexts[$cm->id], $userid)) {
             if (is_null($modinfo->groups)) {
@@ -1157,6 +1158,7 @@
                 $cm->uservisible = false;
             }
         }
+        }
 
         if (!isset($modinfo->instances[$cm->modname])) {
             $modinfo->instances[$cm->modname] = array();
@@ -1181,8 +1183,9 @@
 
 /**
  * Returns a number of useful structures for course displays
+ * @param bool $checkonly if true, then this function just checks if non-empty result is possible 
  */
-function get_all_mods($courseid, &$mods, &$modnames, &$modnamesplural, &$modnamesused) {
+function get_all_mods($courseid, &$mods, &$modnames, &$modnamesplural, &$modnamesused, $checkonly=0) {
     global $DB;
 
     $mods          = array();    // course modules indexed by id
@@ -1209,6 +1212,7 @@
             }
             $mods[$mod->id] = $mod;
             $mods[$mod->id]->modfullname = $modnames[$mod->modname];
+            if (!$checkonly) {
             if (!$mod->visible and !has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $courseid))) {
                 continue;
             }
@@ -1216,6 +1220,7 @@
             if (!groups_course_module_visible($mod)) {
                 continue;
             }
+            }
             $modnamesused[$mod->modname] = $modnames[$mod->modname];
         }
         if ($modnamesused) {
@@ -1828,7 +1833,7 @@
 
     echo "\n\n".'<table class="categorylist">';
 
-    $courses = get_courses($category->id, 'c.sortorder ASC', 'c.id,c.sortorder,c.visible,c.fullname,c.shortname,c.password,c.summary,c.guest,c.cost,c.currency');
+    $courses = get_courses($category->id, 'c.sortorder ASC', 'c.id,c.sortorder,c.visible,c.fullname,c.shortname,c.password,c.summary,c.guest,c.cost,c.currency,c.rsstype');
     if ($files and $coursecount) {
 
         echo '<tr>';
@@ -1854,6 +1859,10 @@
                 echo '<tr><td valign="top">&nbsp;';
                 echo '</td><td valign="top" class="course name">';
                 echo '<a '.$linkcss.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'. format_string($course->fullname).'</a>';
+                if ($CFG->enablerssfeeds && $course->rsstype) {
+                    require_once($CFG->dirroot.'/course/rsslib.php');
+                    echo recent_rss_link($course->id);
+                }    
                 echo '</td><td align="right" valign="top" class="course info">';
                 if ($course->guest ) {
                     echo '<a title="'.$strallowguests.'" href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">';
@@ -1914,17 +1923,17 @@
             $category   = array_shift($categories);
             $courses    = get_courses_wmanagers($category->id,
                                                 'c.sortorder ASC',
-                                                array('password','summary','currency'));
+                                                array('password','summary','currency','rsstype'));
         } else {
             $courses    = get_courses_wmanagers('all',
                                                 'c.sortorder ASC',
-                                                array('password','summary','currency'));
+                                                array('password','summary','currency','rsstype'));
         }
         unset($categories);
     } else {
         $courses    = get_courses_wmanagers($category->id,
                                             'c.sortorder ASC',
-                                            array('password','summary','currency'));
+                                            array('password','summary','currency','rsstype'));
     }
 
     if ($courses) {
@@ -1967,7 +1976,12 @@
     echo '<div class="info">';
     echo '<div class="name"><a title="'.get_string('entercourse').'"'.
          $linkcss.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.
-         format_string($course->fullname).'</a></div>';
+         format_string($course->fullname).'</a>';
+    if ($CFG->enablerssfeeds && $course->rsstype) {
+        require_once($CFG->dirroot.'/course/rsslib.php');
+        echo recent_rss_link($course->id);
+    } 
+    echo '</div>';
 
     /// first find all roles that are supposed to be displayed
 
@@ -2058,14 +2072,14 @@
         print_error('nopermissions', '', '', 'See My Moodle');
     }
 
-    $courses  = get_my_courses($USER->id, 'visible DESC,sortorder ASC', array('summary'));
+    $courses  = get_my_courses($USER->id, 'visible DESC,sortorder ASC', array('summary','rsstype'));
     $rhosts   = array();
     $rcourses = array();
     if (!empty($CFG->mnet_dispatcher_mode) && $CFG->mnet_dispatcher_mode==='strict') {
         $rcourses = get_my_remotecourses($USER->id);
         $rhosts   = get_my_remotehosts();
     }
-
+    $rsspossible=0; 
     if (!empty($courses) || !empty($rcourses) || !empty($rhosts)) {
 
         if (!empty($courses)) {
@@ -2074,6 +2088,9 @@
                 if ($course->id == SITEID) {
                     continue;
                 }
+                if ($course->rsstype > 0) {
+                    $rsspossible = 1;
+                }
                 echo '<li>';
                 print_course($course, "100%");
                 echo "</li>\n";
@@ -2101,6 +2118,9 @@
             print_course_search("", false, "short");
             echo "</td><td align=\"center\">";
             print_single_button("$CFG->wwwroot/course/index.php", NULL, get_string("fulllistofcourses"), "get");
+            if ($CFG->enablerssfeeds && $rsspossible) {
+                echo '</td><td>'.mymoodle_rss_link();
+            }
             echo "</td></tr></table>\n";
         }
 
@@ -3314,5 +3334,163 @@
 
     return false;
 }
+/**
+ * get_recent_activity() 
+ * @param object $course course object
+ * @param integer $user user filter  
+ * @param mixed $modid module filter
+ * @param integer $group group filter
+ * @param integer $time 
+ * @param bool $checkonly if true, then this function just checks if non-empty result is possible 
+ * @return array containing recent activities since $time     
+ **/  
+function get_recent_activity($course,$user,$modid,$group,$time, $returnsections=0, $checkonly = 0) {
+    global $USER,$DB,$CFG;      
+    
+    if (!$checkonly) {
+        $context = get_context_instance(CONTEXT_COURSE, $course->id);
+    }
+   
+
+    if (!empty($param->user)) {
+        if (!$u = $DB->get_record('user', array('id'=>$user))) {
+            print_error("That's an invalid user!");
+        }
+        $userinfo = fullname($u);
+    }
+
+    $modinfo =& get_fast_modinfo($course,$checkonly);
+    get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused,$checkonly);
+
+    if ($checkonly || has_capability('moodle/course:viewhiddensections', $context)) {
+        $hiddenfilter = "";
+    } else {
+        $hiddenfilter = "AND cs.visible = 1";
+    }
+    $sections = array();
+    if ($ss = $DB->get_records_sql("SELECT cs.id, cs.section, cs.sequence, cs.summary, cs.visible
+                                      FROM {course_sections} cs
+                                     WHERE cs.course = ? AND cs.section <= ?
+                                           $hiddenfilter
+                                  ORDER BY section", array($course->id, $course->numsections))) {
+        foreach ($ss as $section) {
+            $sections[$section->section] = $section;
+        }
+    }
+
+    if ($modid === 'all') {
+        // ok
+
+    } else if (strpos($modid, 'mod/') === 0) {
+        $modname = substr($modid, strlen('mod/'));
+        if (array_key_exists($modname, $modnames) and file_exists("$CFG->dirroot/mod/$modname/lib.php")) {
+            $filter = $modname;
+        }
+
+    } else if (strpos($modid, 'section/') === 0) {
+        $sectionid = substr($modid, strlen('section/'));
+        if (isset($sections[$sectionid])) {
+            $sections = array($sectionid=>$sections[$sectionid]);
+        }
+
+    } else if (is_numeric($modid)) {
+        $section = $sections[$modinfo->cms[$modid]->sectionnum];
+        $section->sequence = $modid;
+        $sections = array($section->sequence=>$section);
+    }
+
+    switch ($course->format) {
+        case 'weeks':  $sectiontitle = get_string('week'); break;
+        case 'topics': $sectiontitle = get_string('topic'); break;
+        default: $sectiontitle = get_string('section'); break;
+    }
+
+    if (is_null($modinfo->groups)) {
+        $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
+    }
+
+    $activities = array();
+    $index = 0;
+
+    foreach ($sections as $section) {
+        if ($returnsections) {
+            $activity = new object();
+            $activity->type = 'section';
+            if ($section->section > 0) {
+                $activity->name = $sectiontitle.' '.$section->section;
+            } else {
+                $activity->name = '';
+            }
+
+            $activity->visible = $section->visible;
+            $activities[$index++] = $activity;
+        }
+
+        if (empty($section->sequence)) {
+            continue;
+        }
+
+        $sectionmods = explode(",", $section->sequence);
+
+        foreach ($sectionmods as $cmid) {
+        
+                if (!isset($mods[$cmid]) or !isset($modinfo->cms[$cmid])) {
+                    continue;
+                }
+
+                $cm = $modinfo->cms[$cmid];                
+                if (!$cm->uservisible) {
+                    continue;
+                }
+
+                if (!empty($filter) and $cm->modname != $filter) {
+                    continue;
+                }
+           
+            $libfile = "$CFG->dirroot/mod/$cm->modname/lib.php";
+
+            if (file_exists($libfile)) {
+                require_once($libfile);
+                $get_recent_mod_activity = $cm->modname."_get_recent_mod_activity";
+
+                if (function_exists($get_recent_mod_activity)) {
+                    $activity = new object();
+                    $activity->type    = 'activity';
+                    $activity->cmid    = $cmid;
+                    $activities[$index++] = $activity;                
+                    $newstuff=$get_recent_mod_activity($activities, $index, $time, $course->id, $cmid, $user, $group, $checkonly);                 
+                    if ($newstuff && $checkonly) {
+                        return true;
+                    }                    
+                }
+            }            
+        }
+    }
+    if ($checkonly) {
+        return false;
+    }
+    return $activities;    
+}    
+
+function compare_activities_by_time_desc($a, $b) {
+    // make sure the activities actually have a timestamp property
+    if ((!array_key_exists('timestamp', $a)) or (!array_key_exists('timestamp', $b))) {
+      return 0;
+    }
+    if ($a->timestamp == $b->timestamp)
+        return 0;
+    return ($a->timestamp > $b->timestamp) ? -1 : 1;
+}
+
+function compare_activities_by_time_asc($a, $b) {
+    // make sure the activities actually have a timestamp property
+    if ((!array_key_exists('timestamp', $a)) or (!array_key_exists('timestamp', $b))) {
+      return 0;
+    }
+    if ($a->timestamp == $b->timestamp)
+        return 0;
+    return ($a->timestamp < $b->timestamp) ? -1 : 1;
+}
+
 
 ?>
Index: course/recent.php
===================================================================
RCS file: /cvsroot/moodle/moodle/course/recent.php,v
retrieving revision 1.40
diff -u -r1.40 recent.php
--- course/recent.php	5 Jul 2008 20:57:35 -0000	1.40
+++ course/recent.php	26 Aug 2008 14:50:16 -0000
@@ -5,6 +5,7 @@
     require_once('../config.php');
     require_once('lib.php');
     require_once('recent_form.php');
+    require_once('recent_rss_form.php');
 
     $id = required_param('id', PARAM_INT);
 
@@ -57,7 +58,15 @@
     $navlinks[] = array('name' => $userinfo, 'link' => null, 'type' => 'misc');
     $navigation = build_navigation($navlinks);
     print_header("$course->shortname: $strrecentactivity", $course->fullname, $navigation, '', $meta);
-    print_heading(format_string($course->fullname) . ": $userinfo", '', 3);
+    /// If rss are activated at site and forum level and this forum has rss defined, show link
+    if ($CFG->enablerssfeeds && $COURSE->rsstype) {
+        require_once('rsslib.php');
+        $rsslink=recent_rss_link($COURSE->id);
+    } else {
+        $rsslink='';
+    }   
+    
+    print_heading(format_string($course->fullname) . ": $userinfo $rsslink", '', 3);
 
     $mform->display();
 
@@ -260,24 +269,4 @@
     }
 
     print_footer($course);
-
-function compare_activities_by_time_desc($a, $b) {
-    // make sure the activities actually have a timestamp property
-    if ((!array_key_exists('timestamp', $a)) or (!array_key_exists('timestamp', $b))) {
-      return 0;
-    }
-    if ($a->timestamp == $b->timestamp)
-        return 0;
-    return ($a->timestamp > $b->timestamp) ? -1 : 1;
-}
-
-function compare_activities_by_time_asc($a, $b) {
-    // make sure the activities actually have a timestamp property
-    if ((!array_key_exists('timestamp', $a)) or (!array_key_exists('timestamp', $b))) {
-      return 0;
-    }
-    if ($a->timestamp == $b->timestamp)
-        return 0;
-    return ($a->timestamp < $b->timestamp) ? -1 : 1;
-}
 ?>
Index: lang/en_utf8/admin.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/admin.php,v
retrieving revision 1.223
diff -u -r1.223 admin.php
--- lang/en_utf8/admin.php	26 Aug 2008 05:45:09 -0000	1.223
+++ lang/en_utf8/admin.php	26 Aug 2008 14:50:18 -0000
@@ -39,6 +39,7 @@
 $string['bookmarkthispage'] = 'bookmark this page';
 $string['cachetext'] = 'Text cache lifetime';
 $string['cachetype'] = 'Cache Type';
+$string['calendar_enablerssfeeds'] = 'Enable RSS feeds for calendar';
 $string['calendar_weekend'] = 'Weekend Days';
 $string['calendarsettings'] = 'Calendar';
 $string['cfgwwwrootwarning'] = 'You have defined &#36;CFG->wwwroot incorrectly in your config.php file. It does not match the URL you are using to access this page. Please correct it, or you will experience strange bugs like <a href=\'http://tracker.moodle.org/browse/MDL-11061\'>MDL-11061</a>.';
@@ -73,6 +74,7 @@
 $string['configbloglevel'] = 'This setting allows you to restrict the level to which user blogs can be viewed on this site.  Note that they specify the maximum context of the VIEWER not the poster or the types of blog posts.  Blogs can also be disabled completely if you don\'t want them at all.';
 $string['configcachetext'] = 'For larger sites or sites that use text filters, this setting can really speed things up.  Copies of texts will be retained in their processed form for the time specified here.  Setting this too small may actually slow things down slightly,  but setting it too large may mean texts take too long to refresh (with new links, for example).';
 $string['configcachetype'] = 'Select a type of cache for Moodle to use. This will only configure the cache, remember to enable rcache so that the cache is used for something. Use <strong>only</strong> if you need to reduce the load on the database system -- otherwise Moodle will actually run slower. Medium-traffic sites may see benefits using \'internal\'. A single webserver with eAccelerator or Turckmmcache installed <em>with the shared memory options enabled</em> should try \'eaccelerator\'. If you have a multiple-server setup, and you have one or more memcached daemons running and the PHP-memcached extension, select \'memcached\' and configure the memached options below. <br /><strong>Note:</strong> make sure you test performance under load and tune accordingly -- the caches can make your site slower. In high-traffic situations, eAccelerator and memcached can yield the most benefits, but have the higher costs in CPU usage on the webserver.';
+$string['configcalendarenablerssfeeds'] = 'This switch will enable RSS feeds for calendar and upcoming events blocks.';
 $string['configclamactlikevirus'] = 'Treat files like viruses';
 $string['configclamdonothing'] = 'Treat files as OK';
 $string['configclamfailureonupload'] = 'If you have configured clam to scan uploaded files, but it is configured incorrectly or fails to run for some unknown reason, how should it behave?  If you choose \'Treat files like viruses\', they\'ll be moved into the quarantine area, or deleted. If you choose \'Treat files as OK\', the files will be moved to the destination directory like normal. Either way, admins will be alerted that clam has failed.  If you choose \'Treat files like viruses\' and for some reason clam fails to run (usually because you have entered an invalid pathtoclam), ALL files that are uploaded will be moved to the given quarantine area, or deleted. Be careful with this setting.';
@@ -121,6 +123,7 @@
 $string['configfiltermatchoneperpage'] = 'Automatic linking filters will only generate a single link for the first matching text instance found on the complete page. All others are ignored.';
 $string['configfiltermatchonepertext'] = 'Automatic linking filters will only generate a single link for the first matching text instance found in each item of text (e.g., resource, block) on the page. All others are ignored. This setting is ignored if the one per page setting is <i>yes</i>.';
 $string['configfilteruploadedfiles'] = 'Process all uploaded HTML and text files with the filters before displaying them, only uploaded HTML files or none at all.';
+$string['configforcehttpsforrss'] = 'Turning this on will make Moodle force a secure https connection for the RSS feeds.  CAUTION: this setting REQUIRES https to be specifically enabled on the web server - if it is not then YOU COULD LOCK YOURSELF OUT OF YOUR SITE.';
 $string['configforcelogin'] = 'Normally, the front page of the site and the course listings (but not courses) can be read by people without logging in to the site.  If you want to force people to log in before they do ANYTHING on the site, then you should enable this setting.';
 $string['configforceloginforprofiles'] = 'This setting forces people to login as a real (non-guest) account before viewing any user\'s profile. If you disabled this setting, you may find that some users post advertising (spam) or other inappropriate content in their profiles, which is then visible to the whole world.';
 $string['configframename'] = 'If you are embedding Moodle within a web frame, then put the name of this frame here.  Otherwise this value should remain as \'_top\'';
@@ -371,6 +374,7 @@
 $string['filtersettings'] = 'Manage filters';
 $string['filtersettingsgeneral'] = 'General filter settings';
 $string['filteruploadedfiles'] = 'Filter uploaded files';
+$string['forcehttpsforrss'] = 'Force https for RSS';
 $string['forcelogin'] = 'Force users to login';
 $string['forceloginforprofiles'] = 'Force users to login for profiles';
 $string['forcetimezone'] = 'Force default timezone';
Index: lang/en_utf8/error.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/error.php,v
retrieving revision 1.125
diff -u -r1.125 error.php
--- lang/en_utf8/error.php	17 Aug 2008 12:10:58 -0000	1.125
+++ lang/en_utf8/error.php	26 Aug 2008 14:50:18 -0000
@@ -372,6 +372,12 @@
 $string['restricteduser'] = 'Sorry, but your current account \"$a\" is restricted from doing that';
 $string['reportnotavailable'] = 'This type of report is only available for the site course';
 $string['rpcerror'] = 'RPC enrol/mnet/available_courses: ($a)';
+$string['rss20compat'] = 'This RSS URL is no longer valid. Please login into Moodle and re-subscribe.';
+$string['rssbrokenlink'] = 'Invalid URL.';
+$string['rssdisabled'] = 'RSS is disabled by administration';
+$string['rssnocontent'] = 'This RSS feed is empty at the moment.';
+$string['rssnoguests'] = 'No guests allowed.';
+$string['rssnotfound'] = 'RSS feed not found or URL is incorrect.';
 $string['scheduledbackupsdisabled'] = 'Scheduled backups have been disabled by the server admin';
 $string['sectionnotexist'] = 'This section does not exist';
 $string['secretalreadyused'] = 'Change password confirmation link was already used, password was not changed';
Index: lang/en_utf8/message.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/message.php,v
retrieving revision 1.11
diff -u -r1.11 message.php
--- lang/en_utf8/message.php	2 Aug 2008 00:13:10 -0000	1.11
+++ lang/en_utf8/message.php	26 Aug 2008 14:50:18 -0000
@@ -21,6 +21,7 @@
 $string['emailmessages'] = 'Email messages when I am offline';
 $string['emailtagline'] = 'This email is a copy of a message sent to you at \"$a\"';
 $string['emptysearchstring'] = 'You must search for something';
+$string['enablerssfeed'] = 'Enable RSS feed';
 $string['formorethan'] = 'For more than';
 $string['includeblockedusers'] = 'Include blocked users';
 $string['incomingcontacts'] = 'Incoming Contacts ($a)';
Index: lang/en_utf8/moodle.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/moodle.php,v
retrieving revision 1.193
diff -u -r1.193 moodle.php
--- lang/en_utf8/moodle.php	22 Aug 2008 03:32:49 -0000	1.193
+++ lang/en_utf8/moodle.php	26 Aug 2008 14:50:19 -0000
@@ -1287,7 +1287,12 @@
 $string['rss'] = 'RSS';
 $string['rssarticles'] = 'Number of RSS recent articles';
 $string['rsserror'] = 'Error reading RSS data';
+$string['rssfeedtype'] = 'RSS feed type';
+$string['rsspreferences'] = 'RSS feed preferences';
+$string['rsssubscribe'] = 'RSS feed';
 $string['rsstype'] = 'RSS feed for this activity';
+$string['rss_summary'] = 'Activity summary';
+$string['rss_separate'] = 'Separate RSS articles';
 $string['saveandnext'] = 'Save and show next';
 $string['savechanges'] = 'Save changes';
 $string['savechangesanddisplay'] = 'Save and display';
@@ -1466,6 +1471,7 @@
 $string['studentviewon'] = 'Turn student view on';
 $string['subcategories'] = 'Sub-categories';
 $string['submit'] = 'Submit';
+$string['subscribe_rss'] = 'Subscribe to RSS';
 $string['success'] = 'Success';
 $string['summary'] = 'Summary';
 $string['summaryof'] = 'Summary of $a';
Index: lib/filelib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/filelib.php,v
retrieving revision 1.86
diff -u -r1.86 filelib.php
--- lib/filelib.php	16 Aug 2008 17:23:19 -0000	1.86
+++ lib/filelib.php	26 Aug 2008 14:50:21 -0000
@@ -20,7 +20,7 @@
             $url = $CFG->wwwroot."/question/exportfile.php";
             break;
        case 'rssfile':
-            $url = $CFG->wwwroot."/rss/file.php";
+            $url = $CFG->wwwroot."/rss/rssfile.php";
             break;
         case 'user':
             $url = $CFG->wwwroot."/user/pix.php";
Index: lib/moodlelib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/moodlelib.php,v
retrieving revision 1.1098
diff -u -r1.1098 moodlelib.php
--- lib/moodlelib.php	25 Aug 2008 22:44:45 -0000	1.1098
+++ lib/moodlelib.php	26 Aug 2008 14:50:23 -0000
@@ -1797,7 +1797,7 @@
  *
  * @param mixed $courseorid id of the course or course object
  */
-function course_setup($courseorid=0) {
+function course_setup($courseorid=0, $notheme = 0) {
     global $COURSE, $SITE, $DB;
 
 /// Redefine global $COURSE if needed
@@ -1821,7 +1821,9 @@
 
 /// set locale and themes
     moodle_setlocale();
+    if (!$notheme) {
     theme_setup();
+    }
 
 }
 
@@ -2136,8 +2138,8 @@
  * @param string $script unique script identifier
  * @param int $instance optional instance id
  */
-function require_user_key_login($script, $instance=null) {
-    global $USER, $SESSION, $CFG, $DB;
+function require_user_key_login($script, $instance=null,$keyvalue=null) {
+    global $nomoodlecookie, $USER, $SESSION, $CFG,$DB;
 
     if (!NO_MOODLE_COOKIES) {
         print_error('sessioncookiesdisable');
@@ -2146,7 +2148,9 @@
 /// extra safety
     @session_write_close();
 
+    if($keyvalue === NULL) {
     $keyvalue = required_param('key', PARAM_ALPHANUM);
+    }
 
     if (!$key = $DB->get_record('user_private_key', array('script'=>$script, 'value'=>$keyvalue, 'instance'=>$instance))) {
         print_error('invalidkey');
Index: lib/rsslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/rsslib.php,v
retrieving revision 1.56
diff -u -r1.56 rsslib.php
--- lib/rsslib.php	10 Jul 2008 09:55:12 -0000	1.56
+++ lib/rsslib.php	26 Aug 2008 14:50:24 -0000
@@ -3,132 +3,107 @@
 
 /**
  * This function returns the icon (from theme) with the link to rss/file.php
+ * @param int $context context object or context id
+ * @param int $userid user id
+ * @param string $modulename module short name
+ * @param mixed $id module instance id
+ * @param string $tooltiptext tooltip text (optional)
+ * @return string html code, icon with link to rss
  */
-function rss_get_link($courseid, $userid, $modulename, $id, $tooltiptext='') {
+function rss_get_link($context, $userid, $modulename, $id, $tooltiptext='',$info=null) {
 
     global $CFG, $USER;
 
     static $pixpath = '';
     static $rsspath = '';
 
-    //In site course, if no logged (userid), use admin->id. Bug 2048.
-    if ($courseid == SITEID and empty($userid)) {
-        $admin = get_admin();
-        $userid = $admin->id;
-    }
 
-    $rsspath = rss_get_url($courseid, $userid, $modulename, $id);
+    $rsspath = rss_get_url($context, $userid, $modulename, $id,$info);
     $rsspix = $CFG->pixpath .'/i/rss.gif';
 
-    return '<a href="'. $rsspath .'"><img src="'. $rsspix .'" title="'. strip_tags($tooltiptext) .'" alt="'.get_string('rss').'" /></a>';
+    return '<a class="rsslink" href="'. $rsspath .'"><img src="'. $rsspix .'" title="'. strip_tags($tooltiptext) .'" alt="'.get_string('rss').'" /></a>';
 
 }
 
 /**
  * This function returns the URL for the RSS XML file.
+ * @param int $context context object or context id
+ * @param int $userid user id
+ * @param string $modulename module short name
+ * @param mixed $id module instance id
+ * @param mixed $info additional information about feed
+ * @return string link to rss feed
  */
-function rss_get_url($courseid, $userid, $modulename, $id) {
-    global $CFG;
-    require_once($CFG->libdir.'/filelib.php');
-    return get_file_url($courseid.'/'.$userid.'/'.$modulename.'/'.$id.'/rss.xml', null, 'rssfile');
-}
-
-/**
- * This function prints the icon (from theme) with the link to rss/file.php
- */
-function rss_print_link($courseid, $userid, $modulename, $id, $tooltiptext='') {
-    print rss_get_link($courseid, $userid, $modulename, $id, $tooltiptext);
-
-}
+function rss_get_url($context, $userid, $modulename, $id, $info = null) {
+    global $CFG,$COURSE;
 
-/**
- * This function iterates over each module in the server to see if
- * it supports generating rss feeds, searching for a MODULENAME_rss_feeds()
- * function and invoking it foreach activity as necessary
- */
-function cron_rss_feeds () {
-    global $CFG, $DB;
-
-    $status = true;
+    if (is_object($context)) {
+        $context=$context->id;
+    }
 
-    mtrace('    Generating rssfeeds...');
+    if (empty($userid) || isguestuser($userid)) {  /// User is a guest?
+        //Check course policy about guests
 
-    //Check for required functions...
-    if(!function_exists('utf8_encode')) {
-        mtrace('        ERROR: You need to add XML support to your PHP installation!');
-        return true;
-    }
-
-    if ($allmods = $DB->get_records('modules') ) {
-        foreach ($allmods as $mod) {
-            mtrace('        '.$mod->name.': ', '');
-            $modname = $mod->name;
-            $modfile = "$CFG->dirroot/mod/$modname/rsslib.php";
-            //If file exists and we have selected to restore that type of module
-            if (file_exists($modfile)) {
-                include_once($modfile);
-                $generaterssfeeds = $modname.'_rss_feeds';
-                if (function_exists($generaterssfeeds)) {
-                    if ($status) {
-                        mtrace('generating ', '');;
-                        $status = $generaterssfeeds();
-                        if (!empty($status)) {
-                            mtrace('...OK');
+        if($COURSE->guest == 2) {/// Guests allowed with key
+            $hash_key='/'.sha1(md5($COURSE->password)); ///Use course key as a hash_key
                         } else {
-                            mtrace('...FAILED');
+            $hash_key = "";
                         }
-                    } else {
-                        mtrace('...SKIPPED (failed above)');
-                    }
-                } else {
-                    mtrace('...NOT SUPPORTED (function)');
-                }
-            } else {
-                mtrace('...NOT SUPPORTED (file)');
             }
+    else {
+        $hash_key = '/'.rss_get_url_key($userid,$context,$modulename,$id, $info);
         }
+    if (!empty($info)) {
+        if (is_array($info)) {
+            $info=implode('/',$info).'/';
+        } else if($info !== null) {
+            $info.='/';
     }
-    mtrace('    Ending  rssfeeds...', '');
-    if (!empty($status)) {
-        mtrace('...OK');
     } else {
-        mtrace('...FAILED');
+        $info='';
     }
 
-    return $status;
+    $rsspath = "$hash_key/$context/$userid/$modulename/$id/".$info."rss.xml";
+    require_once($CFG->libdir.'/filelib.php');
+    $rsspath = get_file_url($rsspath, null, 'rssfile');
+    if (!empty($CFG->forcehttpsforrss)) {
+        $rsspath = str_replace('http:', 'https:', $rsspath);
+    }
+    return $rsspath;
 }
 
 /**
- * This function saves to file the rss feed specified in the parameters
+ * This function prints the icon (from theme) with the link to rss/rssfile.php
  */
-function rss_save_file($modname, $mod, $result) {
-    global $CFG;
-
-    $status = true;
+function rss_print_link($context, $userid, $modulename, $id, $tooltiptext='', $info = null) {
+    print rss_get_link($context, $userid, $modulename, $id, $tooltiptext, $info);
 
-    if (! $basedir = make_upload_directory ('rss/'. $modname)) {
-        //Cannot be created, so error
-        $status = false;
     }
 
-    if ($status) {
-        $file = rss_file_name($modname, $mod);
-        $rss_file = fopen($file, "w");
-        if ($rss_file) {
-            $status = fwrite ($rss_file, $result);
-            fclose($rss_file);
-        } else {
-            $status = false;
-        }
-    }
-    return $status;
-}
+/**
+ * This function iterates over each module in the server to see if
+ * it supports generating rss feeds, searching for a MODULENAME_rss_feeds()
+ * function and invoking it foreach activity as necessary
+ */
+function cron_rss_feeds () {
 
+    mtrace('    Cron rss feeds deprecated');
 
-function rss_file_name($modname, $mod) {
-    global $CFG;
+    return true;
+}
 
-    return "$CFG->dataroot/rss/$modname/$mod->id.xml";
+/**
+ * This function sends generated RSS feed to user
+ */
+function rss_output($rss,$time) {
+    //set headers
+    header('Last-Modified: '.date("D, d M Y H:i:s T", $time));
+    header('ETag: "'.$time.'"');
+    header('Content-Type: application/rss+xml');
+    //output content
+    echo $rss;
+    //bye!
+    exit;
 }
 
 /**
@@ -175,7 +150,7 @@
             $result .= rss_full_tag('language', 2, false, substr($USER->lang,0,2));
         }
         $today = getdate();
-        $result .= rss_full_tag('copyright', 2, false, '&#169; '. $today['year'] .' '. format_string($site->fullname));
+        $result .= rss_full_tag('copyright', 2, false, $today['year'] .' '. format_string($site->fullname));
         /*
        if (!empty($USER->email)) {
             $result .= rss_full_tag('managingEditor', 2, false, fullname($USER));
@@ -203,68 +178,13 @@
     }
 }
 
-//This function returns the rss XML code for every item passed in the array
-//item->title: The title of the item
-//item->author: The author of the item. Optional !!
-//item->pubdate: The pubdate of the item
-//item->link: The link url of the item
-//item->description: The content of the item
-function rss_add_items($items) {
-    global $CFG;
-
-    $result = '';
-
-    if (!empty($items)) {
-        foreach ($items as $item) {
-            $result .= rss_start_tag('item',2,true);
-            //Include the category if exists (some rss readers will use it to group items)
-            if (isset($item->category)) {
-                $result .= rss_full_tag('category',3,false,$item->category);
-            }
-            $result .= rss_full_tag('title',3,false,strip_tags($item->title));
-            $result .= rss_full_tag('link',3,false,$item->link);
-            $result .= rss_add_enclosures($item);
-            $result .= rss_full_tag('pubDate',3,false,date('D, d M Y H:i:s T',$item->pubdate));
-            //Include the author if exists
-            if (isset($item->author)) {
-                //$result .= rss_full_tag('author',3,false,$item->author);
-                //We put it in the description instead because it's more important
-                //for moodle than most other feeds, and most rss software seems to ignore
-                //the author field ...
-                $item->description = get_string('byname','',$item->author).'. &nbsp;<p>'.$item->description.'</p>';
-            }
-            $result .= rss_full_tag('description',3,false,$item->description);
-            $result .= rss_full_tag('guid',3,false,$item->link,array('isPermaLink' => 'true'));
-            $result .= rss_end_tag('item',2,true);
-
-        }
-    } else {
-        $result = false;
-    }
-    return $result;
-}
-
-/**
- * This function return all the common footers for every rss feed in the site
- */
-function rss_standard_footer($title = NULL, $link = NULL, $description = NULL) {
-    $status = true;
-    $result = '';
-
-    //Close the chanel
-    $result .= rss_end_tag('channel', 1, true);
-    ////Close the rss tag
-    $result .= '</rss>';
-
-    return $result;
-}
 
 /**
  * This function return an error xml file (string)
  * to be sent when a rss is required (file.php)
  * and something goes wrong
  */
-function rss_geterrorxmlfile() {
+function rss_geterrorxml($msg) {
     global $CFG;
 
     $return = '';
@@ -278,8 +198,8 @@
         $item->title       = "RSS Error";
         $item->link        = $CFG->wwwroot;
         $item->pubdate     = time();
-        $item->description = get_string("rsserror");
-        $return .= rss_add_items(array($item));
+        $item->description = $msg;
+        $return .= rss_add_items(array($item),1);
     }
 
     //XML Footer
@@ -337,6 +257,18 @@
     return $st.$co.$et;
 }
 
+/**
+ * Return the start tag, the contents inside CDATA and the end tag
+ */
+function rss_fullcdata_tag($tag,$level=0,$endline=true,$content,$attributes=null) {
+    $st = rss_start_tag($tag,$level,$endline,$attributes);
+    $co="";
+    $co = '<![CDATA['.$content.']]>';
+    $et = rss_end_tag($tag,0,true);
+
+    return $st.$co.$et;
+}
+
 //////////////////// LIBRARY FUNCTIONS FOR RSS_CLIENT BLOCK ////////////////
 
 //initialize default config vars for rss_client block if needed
@@ -453,6 +385,7 @@
 }
 
 
+
 /**
  * Prints or returns a form for managing rss feed entries.
  * @param string $act The current action. If "rssedit" then and "update" button is used, otherwise "add" is used.
@@ -604,4 +537,328 @@
 
     return $returnstring;
 }
+
+
+//This function returns the rss XML code for every item passed in the array
+//item->title: The title of the item
+//item->author: The author of the item. Optional !!
+//item->pubdate: The pubdate of the item
+//item->link: The link url of the item. Optional
+//item->guid: The guid for the item. Optional if item->link is present
+//item->description: The content of the item
+function rss_add_items($items,$cdatadesc = 0) {
+    global $CFG;
+
+    $result = '';
+
+    if (!empty($items)) {
+        foreach ($items as $item) {
+            $result .= rss_start_tag('item',2,true);
+            //Include the category if exists (some rss readers will use it to group items)
+            if (isset($item->category)) {
+                $result .= rss_full_tag('category',3,false,$item->category);
+            }
+            $result .= rss_full_tag('title',3,false,strip_tags($item->title));
+            if (isset($item->link)) {
+                $result .= rss_full_tag('link',3,false,$item->link);
+            }
+            $result .= rss_add_enclosures($item);
+            $result .= rss_full_tag('pubDate',3,false,date(DATE_RFC2822,$item->pubdate)); // Fix for MDL-12563
+            //Include the author if exists
+            if (isset($item->author)) {
+                //$result .= rss_full_tag('author',3,false,$item->author);
+                //We put it in the description instead because it's more important
+                //for moodle than most other feeds, and most rss software seems to ignore
+                //the author field ...
+                $item->description = get_string('byname','',$item->author).'. &nbsp;<p>'.$item->description.'</p>';
+            }
+            if ($cdatadesc) {
+                $result .= rss_fullcdata_tag('description',3,false,$item->description);
+            }
+            else {
+                $result .= rss_full_tag('description',3,false,$item->description);
+            }
+            if (!isset($item->guid)) {
+                $result .= rss_full_tag('guid',3,false,$item->link,array('isPermaLink' => 'true'));
+            } else {
+                $result .= rss_full_tag('guid',3,false,$item->guid,array('isPermaLink' => 'false'));
+            }
+            $result .= rss_end_tag('item',2,true);
+
+        }
+    } else {
+        $result = false;
+    }
+    return $result;
+}
+
+/**
+ * This function return all the common footers for every rss feed in the site
+ */
+function rss_standard_footer($title = NULL, $link = NULL, $description = NULL) {
+    $status = true;
+    $result = '';
+
+    //Close the chanel
+    $result .= rss_end_tag('channel', 1, true);
+    ////Close the rss tag
+    $result .= '</rss>';
+
+    return $result;
+}
+
+/**
+ * Setup global course variables.
+ * ( This function actually is a wrapper for course_setup() in moodlelib.php )
+ * @param int $course_id id of the course
+ */
+function rss_course_setup($courseid) {
+    ob_start();
+    course_setup($courseid,1);
+    $err=ob_get_contents();
+    if (!empty($err)) {
+        rss_error('invalidcourse','error');
+    }
+    ob_end_clean();
+}
+
+/**
+ * Authenticates user by hash-string in URL, sets up $USER and other necessary stuff
+ * Checks if the user can access particular course and module.
+ * Function terminates with error if user doesn't have access to course\module.
+ * @param string $hash_key Long hash-like string from URL.
+ * @param int $user_id User id from URL
+ * @param int $course_id The id of the course this feeds belongs to
+ * @param int $context_id The id of the context this feeds belongs to
+ * @param string $module Module name or course module object this feeds belongs to
+ * @param string $instance Instance id. Could be blogid, forumid etc
+ * @param string $info Additonal information, which is used to accurately identify RSS feed. Can be array.
+ * @author Askar Salimbaev
+ */
+function rss_auth($hash_key, $user_id, $course_id, $context_id, $module, $instance, $info = null ) {
+    global $USER, $DB,$COURSE,$CFG;
+
+    if (is_object($module)) {
+        $modulename=$module->modname;
+    } else {
+        $modulename=$module;
+        $module=null;
+    }
+
+    //Interpret $info
+    if (!empty($info) && is_array($info)) {
+        $info = implode('_',$info);
+    } else if (empty($info)) {
+        $info = '';
+    }
+
+
+    //Check if hash_key is present
+    if( !empty($hash_key) ) {
+
+        if ($key = $DB->get_record('user_private_key', array('script' => 'rss', 'userid' => $user_id, 'instance' => $context_id))) {
+            $genuine_hash_key = md5($user_id.$modulename.($key->value).$instance.$info);
+            //Compare
+            if ($genuine_hash_key == $hash_key) {
+                require_user_key_login('rss', $context_id, $key->value);
+            }
+        }
+    }
+
+    if (isset($USER->isDummy)) {
+        if (!empty($CFG->forcelogin)) {
+            rss_error('rssnoguests');
+        }
+        $USER = guest_user(); //Still not logged in, consider as guest
+    }
+
+
+    //Check access
+    rss_checkcaps($COURSE,$module,$hash_key);
+}
+
+
+/**
+ * Checks if the user can access particular course and module.
+ * Function terminates with error if user doesn't have access to course\module.
+ * @param object $course course object
+ * @param object $cm course module object
+ * @param string $key guest's enrollment key
+ * @author Askar Salimbaev
+ * TODO: This code is merely a copy-paste. Consider reusing existing code
+ */
+function rss_checkcaps($course,$cm,$key) {
+    global $CFG, $USER;
+
+// Fetch the system context, we are going to use it a lot.
+    $sysctx = get_context_instance(CONTEXT_SYSTEM);
+
+/// If the site is currently under maintenance, then print a message
+    if (!has_capability('moodle/site:config', $sysctx)) {
+        if (file_exists($CFG->dataroot.'/'.SITEID.'/maintenance.html')) {
+                rss_not_found();
+        }
+    }
+
+/// groupmembersonly access control
+    if (!empty($CFG->enablegroupings) and $cm and $cm->groupmembersonly and !has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) {
+        if (isguestuser() or !groups_has_membership($cm)) {
+               rss_not_found();
+        }
+    }
+
+    // Fetch the course context, and prefetch its child contexts
+    if (!isset($course->context)) {
+        if ( ! $course->context = get_context_instance(CONTEXT_COURSE, $course->id) ) {
+            rss_not_found();
+        }
+    }
+    if ($course->id == SITEID) {
+        /// Eliminate hidden site activities straight away
+        if (!empty($cm) && !$cm->visible
+            && !has_capability('moodle/course:viewhiddenactivities', $course->context)) {
+            rss_not_found();
+        }
+
+        return;
+
+    } else {
+
+        /// Check if the user can be in a particular course
+        if (empty($USER->access['rsw'][$course->context->path])) {
+            //
+            // and the user hasn't the 'course:viewhiddencourses' capability, prevent access
+            //
+            if ( !($course->visible && course_parent_visible($course)) &&
+                   !has_capability('moodle/course:viewhiddencourses', $course->context)) {
+                rss_not_found();
+            }
+        }
+
+    /// Non-guests who don't currently have access, check if they can be allowed in as a guest
+
+        if ($USER->username != 'guest' and !has_capability('moodle/course:view', $course->context)) {
+            if ($course->guest == 1) {
+                 // Temporarily assign them guest role for this context, if it fails later user is asked to enrol
+                 $USER->access = load_temp_role($course->context, $CFG->guestroleid, $USER->access);
+            }
+        }
+
+    /// If the user is a guest then treat them according to the course policy about guests
+
+        if (has_capability('moodle/legacy:guest', $course->context, NULL, false)) {
+            if (has_capability('moodle/site:doanything', $sysctx)) {
+                // administrators must be able to access any course - even if somebody gives them guest access
+                return;
+            }
+
+            if($course->guest == 1 && !empty($CFG->guestloginbutton)) {
+                if (!has_capability('moodle/course:view', $course->context)) {    // Prohibited by capability
+                     rss_not_found();
+                }
+                if (!empty($cm) and !$cm->visible) { // Not allowed to see module, send to course page
+                         rss_not_found();
+                }
+
+                return;   // User is allowed to see this course
+            }
+            else if(isguestuser() && $course->guest == 2 & !empty($CFG->guestloginbutton)) {
+                if (sha1(md5($course->password)) == $key)
+                    return;   // User is allowed to see this course
+                else
+                    rss_not_found();
+            }
+            else {
+                rss_not_found();
+            }
+
+    /// For non-guests, check if they have course view access
+
+        } else if (has_capability('moodle/course:view', $course->context)) {
+            if (!empty($USER->realuser)) {   // Make sure the REAL person can also access this course
+                if (!has_capability('moodle/course:view', $course->context, $USER->realuser)) {
+                     rss_not_found();
+                }
+            }
+
+        /// Make sure they can read this activity too, if specified
+
+            if (!empty($cm) and !$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $course->context)) {
+                 rss_not_found();
+            }
+
+            return;   // User is allowed to see this course
+        }
+    }
+}
+
+
+
+/**
+ * Function returns long hash-like string, which can be used later to access specific RSS feed. Used when printing links.
+ * @param mixed $userid user id.
+ * @param int $contextid the id of the context this feeds belongs to
+ * @param string $modulename module name this feeds belongs to
+ * @param string $instance Instance id. Could be blogid, forumid etc
+ * @param string $info Additonal information, which is used to accurately identify RSS feed. Can be array.
+ * @return string hash_key
+ * @author Askar Salimbaev
+ */
+function rss_get_url_key( $userid, $contextid, $modulename, $instance, $info = '') {
+    global $DB;
+
+    //Load prefs
+    $rss_iprestriction = get_user_preferences( 'rss_iprestriction', '');
+
+    if (empty($info)) {
+        $info = '';
+    }else if (is_array($info)) {
+        $info = implode('_',$info);
+    }
+    if (!$key = $DB->get_record('user_private_key', array('script' => "rss", 'userid' => $userid, 'instance' => $contextid))) {
+        //Create new key
+        $key->value = create_user_key('rss',$userid,$contextid, $rss_iprestriction);
+    } else {
+        if (!empty($rss_iprestriction) && empty($key->iprestriction)) {
+            $key->iprestriction = $rss_iprestriction;
+            $DB->update_record('user_private_key', $key);
+        }
+    }
+
+     return md5($userid.$modulename.($key->value).$instance.$info);
+}
+
+
+/**
+* Generates RSS feed containing an error message.
+*
+* @uses $CFG
+* @param string $errorcode The name of the string from error.php to print
+* @param string $modname Module name
+* @param object $a Extra words and phrases that might be required in the error string
+*/
+function rss_error ($errorcode, $module='error', $a=NULL) {
+    global $CFG;
+
+    if (!empty($CFG->errordocroot)) {
+        $errordocroot = $CFG->errordocroot;
+    } else if (!empty($CFG->docroot)) {
+        $errordocroot = $CFG->docroot;
+    } else {
+        $errordocroot = 'http://docs.moodle.org';
+    }
+
+    $message = get_string($errorcode, $module, $a).'<br />
+               <a href="'.$errordocroot.'/en/error/rss/'.$errorcode.'">'.
+               get_string('moreinformation').'</a>';
+    rss_output(rss_geterrorxml($message),time());
+}
+
+
+/**
+ * Returns RSS with error message
+ */
+function rss_not_found() {
+        rss_error('rssnotfound');
+}
 ?>
Index: lib/sessionlib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/sessionlib.php,v
retrieving revision 1.2
diff -u -r1.2 sessionlib.php
--- lib/sessionlib.php	22 Jun 2008 11:56:01 -0000	1.2
+++ lib/sessionlib.php	26 Aug 2008 14:50:24 -0000
@@ -55,7 +55,7 @@
         global $CFG;
 
     /// disable checks when working in cookieless mode
-        if (empty($CFG->usesid) || !empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+        if (!NO_MOODLE_COOKIES && (empty($CFG->usesid) || !empty($_COOKIE['MoodleSession'.$CFG->sessioncookie]))) {
             if ($this->session != NULL) {
                 if (empty($_COOKIE['MoodleSessionTest'.$CFG->sessioncookie])) {
                     $this->report_session_error();
Index: lib/db/install.xml
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/install.xml,v
retrieving revision 1.168
diff -u -r1.168 install.xml
--- lib/db/install.xml	26 Aug 2008 07:20:58 -0000	1.168
+++ lib/db/install.xml	26 Aug 2008 14:50:26 -0000
@@ -74,7 +74,9 @@
         <FIELD NAME="enrolenddate" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="enrolstartdate" NEXT="enrol"/>
         <FIELD NAME="enrol" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="enrolenddate" NEXT="defaultrole"/>
         <FIELD NAME="defaultrole" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="The default role given to participants who self-enrol" PREVIOUS="enrol" NEXT="enablecompletion"/>
-        <FIELD NAME="enablecompletion" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="1 = allow use of 'completion' progress-tracking on this course. 0 = disable completion tracking on this course." PREVIOUS="defaultrole"/>
+        <FIELD NAME="enablecompletion" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="1 = allow use of 'completion' progress-tracking on this course. 0 = disable completion tracking on this course." PREVIOUS="defaultrole" NEXT="rsstype"/>
+        <FIELD NAME="rsstype" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Enable/disable course recent activity RSS feed" PREVIOUS="enablecompletion" NEXT="rssarticles"/>
+        <FIELD NAME="rssarticles" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Number of recent articles in RSS feed" PREVIOUS="rsstype"/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Index: lib/db/upgrade.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/upgrade.php,v
retrieving revision 1.230
diff -u -r1.230 upgrade.php
--- lib/db/upgrade.php	26 Aug 2008 07:20:58 -0000	1.230
+++ lib/db/upgrade.php	26 Aug 2008 14:50:26 -0000
@@ -768,6 +768,32 @@
         upgrade_main_savepoint($result, 2008082600);
     }
 
+    ///Enable Course Recent activity RSS setting
+    if ($result && $oldversion < 	2008082602) {
+
+    /// Define field enablerss to be added to course
+        $table = new xmldb_table('course');
+        $field = new xmldb_field('rsstype', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'enablecompletion');
+
+    /// Conditionally launch add field enablerss
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Define field rssarticles to be added to course
+        $table = new xmldb_table('course');
+        $field = new xmldb_field('rssarticles', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'rsstype');
+
+    /// Conditionally launch add field rssarticles
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+    /// Main savepoint reached
+        upgrade_main_savepoint($result, 2008082602);
+    }
+
+
 
     return $result;
 }
Index: message/discussion.php
===================================================================
RCS file: /cvsroot/moodle/moodle/message/discussion.php,v
retrieving revision 1.24
diff -u -r1.24 discussion.php
--- message/discussion.php	5 Jul 2008 14:52:40 -0000	1.24
+++ message/discussion.php	26 Aug 2008 14:50:28 -0000
@@ -190,7 +190,12 @@
     echo '</div>';
 
     echo '<div id="messages">';
-    echo '<h1>'.get_string('messages', 'message').'</h1>';
+    if (!empty($CFG->enablerssfeeds) && get_user_preferences('message_enablerss', 1)=='1' ) {
+        include_once($CFG->libdir.'/rsslib.php');
+        $rss = rss_get_link(SYSCONTEXTID,$USER->id,'message','unread');
+    }
+    
+    echo '<h1>'.get_string('messages', 'message').$rss.'</h1>';
 
     $allmessages = array();
     $playbeep = false;
Index: message/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/message/index.php,v
retrieving revision 1.22
diff -u -r1.22 index.php
--- message/index.php	13 Jun 2008 06:55:26 -0000	1.22
+++ message/index.php	26 Aug 2008 14:50:28 -0000
@@ -87,6 +87,10 @@
         $tabprintfunction();
     }
 
+    if (!empty($CFG->enablerssfeeds) && get_user_preferences('message_enablerss', 1)=='1' ) {
+        include_once($CFG->libdir.'/rsslib.php');
+        echo '<div class="note">'.rss_get_link(SYSCONTEXTID,$USER->id,'message','unread').'</div>';
+    }
     echo '</td> </tr> </table>';
     print_footer('none');
 
Index: message/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/message/lib.php,v
retrieving revision 1.78
diff -u -r1.78 lib.php
--- message/lib.php	24 Jul 2008 08:38:05 -0000	1.78
+++ message/lib.php	26 Aug 2008 14:50:28 -0000
@@ -213,6 +213,8 @@
         $pref['message_blocknoncontacts'] = (isset($frm->blocknoncontacts)) ? '1' : '0';
         $pref['message_usehtmleditor'] = (isset($frm->usehtmleditor)) ? '1' : '0';
         $pref['message_noframesjs'] = (isset($frm->noframesjs)) ? '1' : '0';
+        $pref['message_enablerss'] = (isset($frm->enablerss)) ? '1' : '0';
+        $pref['message_rssarticles'] = (isset($frm->rssarticles)) ? (int)$frm->rssarticles : '10';
         $pref['message_emailmessages'] = (isset($frm->emailmessages)) ? '1' : '0';
         $pref['message_emailtimenosee'] = ((int)$frm->emailtimenosee > 0) ? (int)$frm->emailtimenosee : '10';
         $pref['message_emailaddress'] = (!empty($frm->emailaddress)) ? $frm->emailaddress : $USER->email;
@@ -228,6 +230,8 @@
     $cbblocknoncontacts = (get_user_preferences('message_blocknoncontacts', 0) == '1') ? 'checked="checked"' : '';
     $cbusehtmleditor = (get_user_preferences('message_usehtmleditor', 0) == '1') ? 'checked="checked"' : '';
     $cbnoframesjs = (get_user_preferences('message_noframesjs', 0) == '1') ? 'checked="checked"' : '';
+    $cbenablerss= (get_user_preferences('message_enablerss', 1) == '1') ? 'checked="checked"' : '';
+    $txrssarticles = get_user_preferences('message_rssarticles', 10);
     $cbemailmessages = (get_user_preferences('message_emailmessages', 1) == '1') ? 'checked="checked"' : '';
     $txemailaddress = get_user_preferences('message_emailaddress', $USER->email);
     $txemailtimenosee = get_user_preferences('message_emailtimenosee', 10);
Index: message/settings.html
===================================================================
RCS file: /cvsroot/moodle/moodle/message/settings.html,v
retrieving revision 1.10
diff -u -r1.10 settings.html
--- message/settings.html	2 May 2008 05:15:27 -0000	1.10
+++ message/settings.html	26 Aug 2008 14:50:28 -0000
@@ -24,6 +24,21 @@
         <td align="right"><input type="checkbox" name="noframesjs" id="noframesjs" <?php echo $cbnoframesjs ?>  /></td>
         <td colspan="2"><label for="noframesjs"><?php print_string('noframesjs', 'message') ?></label></td>
     </tr>
+    <?php
+        global $CFG;
+        if (!empty($CFG->enablerssfeeds)) {
+            echo '<tr valign="top"> 
+                      <td align="right"><input type="checkbox" name="enablerss" id="enablerss" '.$cbenablerss.' /></td>
+                      <td colspan="2"><label for="enablerss">'.get_string('enablerssfeed', 'message').'</label></td>
+                  </tr>
+                  <tr valign="top">
+                      <td>&nbsp;</td>
+                      <td align="right"><label for="rssarticles">'.get_string('rssarticles').'</label></td>
+                      <td><input type="text" name="rssarticles" id="rssarticles" size="2" value="'.($txrssarticles).'" /></td>
+                  </tr>
+                  ';
+        }
+    ?>
 
 
     <tr valign="top">
Index: message/user.php
===================================================================
RCS file: /cvsroot/moodle/moodle/message/user.php,v
retrieving revision 1.35
diff -u -r1.35 user.php
--- message/user.php	13 Jun 2008 06:55:26 -0000	1.35
+++ message/user.php	26 Aug 2008 14:50:28 -0000
@@ -85,7 +85,11 @@
     message_history_link($user->id, 0, false, '', '', 'both');
     echo '</div>';
 
-    echo '</td></tr></table>';
+    if (!empty($CFG->enablerssfeeds) && get_user_preferences('message_enablerss', 1)=='1' ) {
+        include_once($CFG->libdir.'/rsslib.php');
+        $rss = '<td>'.rss_get_link(SYSCONTEXTID,$USER->id,'message','unread').'</td>';
+    }
+    echo '</td>'.$rss.'</tr></table>';
 
     print_footer('empty');
 
Index: mod/assignment/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/assignment/index.php,v
retrieving revision 1.44
diff -u -r1.44 index.php
--- mod/assignment/index.php	1 Jun 2008 18:12:25 -0000	1.44
+++ mod/assignment/index.php	26 Aug 2008 14:50:28 -0000
@@ -27,7 +27,15 @@
     $navlinks[] = array('name' => $strassignments, 'link' => '', 'type' => 'activity');
     $navigation = build_navigation($navlinks);
 
-    print_header_simple($strassignments, "", $navigation, "", "", true, "", navmenu($course));
+    if (!empty($CFG->enablerssfeeds)) {
+            include_once($CFG->libdir.'/rsslib.php');
+            $rsspath = rss_get_url(get_context_instance(CONTEXT_COURSE,$course->id), $USER->id, 'assignment', $course->id, 'index');
+            $meta = '<link rel="alternate" type="application/rss+xml" ';
+            $meta .= 'title ="'. format_string($course->shortname) .': '.$strassignments.' RSS" href="'.$rsspath.'" />';            
+        } else {
+            $meta ='';
+        }     
+    print_header_simple($strassignments, "", $navigation, "", $meta, true, "", navmenu($course));
 
     if (!$cms = get_coursemodules_in_course('assignment', $course->id, 'm.assignmenttype, m.timedue')) {
         notice(get_string('noassignments', 'assignment'), "../../course/view.php?id=$course->id");
@@ -113,7 +121,10 @@
     }
 
     echo "<br />";
-
+    if (!empty($CFG->enablerssfeeds)) {
+            include_once($CFG->libdir.'/rsslib.php');
+            echo rss_get_link(get_context_instance(CONTEXT_COURSE,$course->id), $USER->id, 'assignment',  $course->id, 'RSS', 'index');
+    } 
     print_table($table);
 
     print_footer($course);
Index: mod/assignment/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/assignment/lib.php,v
retrieving revision 1.354
diff -u -r1.354 lib.php
--- mod/assignment/lib.php	18 Aug 2008 06:33:26 -0000	1.354
+++ mod/assignment/lib.php	26 Aug 2008 14:50:30 -0000
@@ -130,7 +130,7 @@
      */
     function view_header($subpage='') {
 
-        global $CFG;
+        global $CFG,$USER;
 
 
         if ($subpage) {
@@ -138,8 +138,17 @@
         } else {
             $navigation = build_navigation('', $this->cm);
         }
+        if (!empty($CFG->enablerssfeeds) && $this->assignment->rsstype>0) {
+            include_once($CFG->libdir.'/rsslib.php');
+            $rsspath = rss_get_url($this->context, $USER->id, 'assignment', $this->assignment->id);
+            $meta = '<link rel="alternate" type="application/rss+xml" ';
+            $meta .= 'title ="'. format_string($this->course->shortname) .': '.format_string($this->assignment->name,true).' RSS" href="'.$rsspath.'" />';            
+        } else {
+            $meta ='';
+        }        
+        
 
-        print_header($this->pagetitle, $this->course->fullname, $navigation, '', '',
+        print_header($this->pagetitle, $this->course->fullname, $navigation, '', $meta,
                      true, update_module_button($this->cm->id, $this->course->id, $this->strassignment),
                      navmenu($this->course, $this->cm));
 
@@ -147,6 +156,10 @@
 
         echo '<div class="reportlink">'.$this->submittedlink().'</div>';
         echo '<div class="clearer"></div>';
+        if (!empty($CFG->enablerssfeeds) && $this->assignment->rsstype>0) {   
+            $rsspath = rss_get_link($this->context, $USER->id, 'assignment', $this->assignment->id);       
+            echo $rsspath;
+        }
     }
 
 
@@ -2569,8 +2582,9 @@
 
 /**
  * Returns all assignments since a given time in specified forum.
+ * @param bool $checkonly if true, then this function just checks if non-empty result is possible  
  */
-function assignment_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0)  {
+function assignment_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0,$checkonly=0)  {
     global $CFG, $COURSE, $USER, $DB;
 
     if ($COURSE->id == $courseid) {
@@ -2579,8 +2593,7 @@
         $course = $DB->get_record('course', array('id'=>$courseid));
     }
 
-    $modinfo =& get_fast_modinfo($course);
-
+    $modinfo =& get_fast_modinfo($course,$checkonly);
     $cm = $modinfo->cms[$cmid];
 
     $params = array();
@@ -2612,7 +2625,10 @@
                                                WHERE asb.timemodified > :timestart AND a.id = :cminstance
                                                      $userselect $groupselect
                                             ORDER BY asb.timemodified ASC", $params)) {
-         return;
+         return false;
+    }         
+    if ($checkonly) {
+        return true;
     }
 
     $groupmode       = groups_get_activity_groupmode($cm, $course);
@@ -2663,7 +2679,7 @@
     }
 
     if (empty($show)) {
-        return;
+        return false;
     }
 
     if ($grader) {
@@ -2697,7 +2713,18 @@
         $activities[$index++] = $tmpactivity;
     }
 
-    return;
+    return false;
+}
+
+/**
+ * Returns link for the recent activity 
+ *
+ * This is used by Recent Activity RSS feed
+ */
+function assignment_get_recent_activity_link($activity, $courseid)  {
+    global $CFG;
+
+    return "$CFG->wwwroot/mod/assignment/view.php?id={$activity->cmid}";    
 }
 
 /**
Index: mod/assignment/mod_form.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/assignment/mod_form.php,v
retrieving revision 1.10
diff -u -r1.10 mod_form.php
--- mod/assignment/mod_form.php	26 Jul 2008 15:15:26 -0000	1.10
+++ mod/assignment/mod_form.php	26 Aug 2008 14:50:30 -0000
@@ -57,6 +57,34 @@
         $mform->addElement('select', 'preventlate', get_string('preventlate', 'assignment'), $ynoptions);
         $mform->setDefault('preventlate', 0);
 
+        if ($CFG->enablerssfeeds) {
+//-------------------------------------------------------------------------------
+            $mform->addElement('header', '', get_string('rss'));
+            $choices = array();
+            $choices[0] = get_string('none');
+            $choices[1] = get_string('submissions', 'assignment');            
+            $mform->addElement('select', 'rsstype', get_string('rsstype'), $choices);
+            $mform->setHelpButton('rsstype', array('rsstype', get_string('rsstype'), 'assignment'));  
+            $choices = array();
+            $choices[0] = '0';
+            $choices[1] = '1';
+            $choices[2] = '2';
+            $choices[3] = '3';
+            $choices[4] = '4';
+            $choices[5] = '5';
+            $choices[10] = '10';
+            $choices[15] = '15';
+            $choices[20] = '20';
+            $choices[25] = '25';
+            $choices[30] = '30';
+            $choices[40] = '40';
+            $choices[50] = '50';
+            $mform->addElement('select', 'rssarticles', get_string('rssarticles'), $choices);
+            $mform->setHelpButton('rssarticles', array('rssarticles', get_string('rssarticles'), 'assignment'));        
+        }
+
+//-------------------------------------------------------------------------------
+
         $mform->addElement('header', 'typedesc', get_string('type'.$type,'assignment'));
         $assignmentinstance->setup_elements($mform);
 
Index: mod/assignment/db/install.xml
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/assignment/db/install.xml,v
retrieving revision 1.4
diff -u -r1.4 install.xml
--- mod/assignment/db/install.xml	24 Sep 2007 22:17:05 -0000	1.4
+++ mod/assignment/db/install.xml	26 Aug 2008 14:50:30 -0000
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/assignment/db" VERSION="20070919" COMMENT="XMLDB file for Moodle mod/assignment"
+<XMLDB PATH="mod/assignment/db" VERSION="20080802" COMMENT="XMLDB file for Moodle mod/assignment"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
 >
@@ -24,7 +24,9 @@
         <FIELD NAME="timedue" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="maxbytes" NEXT="timeavailable"/>
         <FIELD NAME="timeavailable" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timedue" NEXT="grade"/>
         <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timeavailable" NEXT="timemodified"/>
-        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="grade"/>
+        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="grade" NEXT="rsstype"/>
+        <FIELD NAME="rsstype" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="RSS feed type" PREVIOUS="timemodified" NEXT="rssarticles"/>
+        <FIELD NAME="rssarticles" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Number of recent articles in RSS feed" PREVIOUS="rsstype"/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id" />
Index: mod/assignment/db/upgrade.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/assignment/db/upgrade.php,v
retrieving revision 1.27
diff -u -r1.27 upgrade.php
--- mod/assignment/db/upgrade.php	18 Aug 2008 22:36:33 -0000	1.27
+++ mod/assignment/db/upgrade.php	26 Aug 2008 14:50:30 -0000
@@ -135,6 +135,31 @@
         upgrade_mod_savepoint($result, 2008081900, 'assignment');
     }
 
+    /// Enable assigment submission RSS setting
+    if ($result && $oldversion < 2008082602) {
+
+    /// Define field rsstype to be added to assignment
+        $table = new xmldb_table('assignment');
+        $field = new xmldb_field('rsstype', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'timemodified');
+
+    /// Conditionally launch add field rsstype
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+            
+    /// Define field rssarticles to be added to assignment
+        $table = new xmldb_table('assignment');
+        $field = new xmldb_field('rssarticles', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'rsstype');
+
+    /// Conditionally launch add field rssarticles
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+    /// assignment savepoint reached
+        upgrade_mod_savepoint($result, 2008082602, 'assignment');
+    }
+
     return $result;
 }
 
Index: mod/data/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/data/index.php,v
retrieving revision 1.28
diff -u -r1.28 index.php
--- mod/data/index.php	25 Jun 2008 14:52:39 -0000	1.28
+++ mod/data/index.php	26 Aug 2008 14:50:30 -0000
@@ -110,7 +110,7 @@
 
         $rsslink = '';
         if ($rss && $data->rssarticles > 0) {
-            $rsslink = rss_get_link($course->id, $USER->id, 'data', $data->id, 'RSS');
+            $rsslink = rss_get_link($context, $USER->id, 'data', $data->id, 'RSS');
         }
 
         if ($course->format == 'weeks' or $course->format == 'topics') {
Index: mod/data/rsslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/data/rsslib.php,v
retrieving revision 1.13
diff -u -r1.13 rsslib.php
--- mod/data/rsslib.php	6 Jun 2008 07:36:17 -0000	1.13
+++ mod/data/rsslib.php	26 Aug 2008 14:50:30 -0000
@@ -1,67 +1,98 @@
 <?php
     // This file adds support to rss feeds generation
 
-    // This function is the main entry point to database module
-    // rss feeds generation. Foreach database with rss enabled
-    // build one XML rss structure.
-
-
-    function data_rss_feeds() {
-        global $CFG, $DB;
+    include_once($CFG->dirroot.'/mod/data/lib.php');
+    /**
+     * This functions setups data rss generation cache
+     */         
+    function data_rss_init_cache($data, &$cache) {
+        global $DB;
+        $cache['data'] =  $DB->get_record('data',array('id'=>$data->instance));
+        $cache['newstuff']=array();         
+    }
 
-        $status = true;
 
-        // Check CFG->enablerssfeeds.
-        if (empty($CFG->enablerssfeeds)) {
-            debugging("DISABLED (admin variables)");
-        }
-        // Check CFG->data_enablerssfeeds.
-        else if (empty($CFG->data_enablerssfeeds)) {
-            debugging("DISABLED (module configuration)");
+    /**
+     * If there is new stuff since $time then this returns
+     * true.  Otherwise it returns false.
+     */ 
+    function data_rss_newstuff($data, $time,&$cache, $info,$context=0) {
+        global $DB;
+        data_rss_init_cache($data,$cache);
+        
+        if ($time) {
+            $time = " AND dr.timemodified > '$time'";
+        } else {
+            $time = '';
         }
-        // It's working so we start...
-        else {
-            // Iterate over all data.
-            if ($datas = $DB->get_records('data')) {
-                foreach ($datas as $data) {
 
-                    if ($data->rssarticles > 0) {
 
-                        // Get the first field in the list  (a hack for now until we have a selector)
+        if ($cache['data']->rssarticles > 0) {
+            $params=array($cache['data']->id);
+            $groupmode    = groups_get_activity_groupmode($data);            
+
+            if ($groupmode && $context) {           
+                $currentgroup = groups_get_activity_group($data);
+
+                if ($groupmode == VISIBLEGROUPS || has_capability('moodle/site:accessallgroups', $context)) {
+                    if ($currentgroup) {
+                        $groupselect = "AND (dr.groupid = ? OR dr.groupid = -1)";
+                        $params[] = $currentgroup;
+                    } else {
+                        $groupselect = "";
+                    }
 
-                        if (!$firstfield = $DB->get_record_sql('SELECT id,name FROM {data_fields} WHERE dataid = ? ORDER by id', array($data->id), true)) {
-                            continue;
+                } else {
+                    //seprate groups without access all
+                    if ($currentgroup) {
+                         $groupselect = "AND (dr.groupid = ? OR dr.groupid = -1)";
+                         $params[] = $currentgroup;
+                     } else {
+                         $groupselect = "AND dr.groupid = -1";
+        }
+        }
+            } else {
+                 $groupselect = "";
                         }
 
-
                         // Get the data_records out.
-                        $approved = ($data->approval) ? ' AND dr.approved = 1 ' : ' ';
+            $approved = ($cache['data']->approval) ? ' AND dr.approved = 1 ' : ' ';
 
                         $sql = "SELECT dr.*, u.firstname, u.lastname
                                   FROM {data_records} dr, {user} u
                                  WHERE dr.dataid = ? $approved
-                                       AND dr.userid = u.id
+                             AND dr.userid = u.id $time $groupselect                            
                               ORDER BY dr.timecreated DESC";
+            $limit = get_user_preferences( 'rss_maxitems', $cache['data']->rssarticles );
+            if (!$limit ||  $limit > $cache['data']->rssarticles) {
+                $limit = $cache['data']->rssarticles;
+            } 
+            if (!$cache['newstuff'] = $DB->get_records_sql($sql, $params, 0, $limit)) {                        
+                return false;
+            }
+        }
 
-                        if (!$records = $DB->get_records_sql($sql, array($data->id), 0, $data->rssarticles)) {
-                            continue;
+        return (!empty($cache['newstuff']));
                         }
 
-                        $firstrecord = array_shift($records);  // Get the first and put it back
-                        array_unshift($records, $firstrecord);
+    /**
+     *  This function return the XML rss contents about the data module record passed as parameter
+     *  It returns false if something is wrong     
+     */ 
+    function data_rss_generate_feed($data, $context, $info, &$cache) {
 
-                        $filename = rss_file_name('data', $data);
-                        if (file_exists($filename)) {
-                            if (filemtime($filename) >= $firstrecord->timemodified) {
-                                continue;
-                            }
+        global $CFG, $DB;
+        
+        $rss=false;
+        
+        if (empty($cache['data'])) {           
+            data_rss_newstuff($data, 0, $cache,$info,$context);
                         }
 
-                        // Now create all the articles
-                        mtrace('Creating feed for '.$data->name);
+        $firstfield = $DB->get_record_sql('SELECT id,name FROM {data_fields} WHERE dataid = ? ORDER by id', array($cache['data']->id), true); 
 
                         $items = array();
-                        foreach ($records as $record) {
+        foreach ($cache['newstuff'] as $record) {
 
                             $recordarray = array();
                             array_push($recordarray, $record);
@@ -69,24 +100,24 @@
                             $item = null;
 
                             // guess title or not
-                            if (!empty($data->rsstitletemplate)) {
-                                $item->title = data_print_template('rsstitletemplate', $recordarray, $data, '', 0, true);
+            if (!empty($cache['data']->rsstitletemplate)) {
+                $item->title = data_print_template('rsstitletemplate', $recordarray, $cache['data'], '', 0, true);
                             } else { // else we guess
                                 $item->title   = strip_tags($DB->get_field('data_content', 'content',
                                                                   array('fieldid'=>$firstfield->id, 'recordid'=>$record->id)));
                             }
-                            $item->description = data_print_template('rsstemplate', $recordarray, $data, '', 0, true);
+            $item->description = data_print_template('rsstemplate', $recordarray, $cache['data'], '', 0, true);
                             $item->pubdate = $record->timecreated;
-                            $item->link = $CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&rid='.$record->id;
+            $item->link = $CFG->wwwroot.'/mod/data/view.php?d='.$cache['data']->id.'&rid='.$record->id;
 
                             array_push($items, $item);
                         }
-                        $course = $DB->get_record('course', array('id'=>$data->course));
+        $course = $DB->get_record('course', array('id'=>$cache['data']->course));
 
                         // First all rss feeds common headers.
-                        $header = rss_standard_header($course->shortname.': '.format_string($data->name,true),
-                                                      $CFG->wwwroot."/mod/data/view.php?d=".$data->id,
-                                                      format_string($data->intro,true));
+        $header = rss_standard_header($course->shortname.': '.format_string($cache['data']->name,true),
+                                      $CFG->wwwroot."/mod/data/view.php?d=".$cache['data']->id,
+                                      format_string($cache['data']->intro,true));
 
                         if (!empty($header)) {
                             $articles = rss_add_items($items);
@@ -99,18 +130,9 @@
                         // Now, if everything is ok, concatenate it.
                         if (!empty($header) && !empty($articles) && !empty($footer)) {
                             $rss = $header.$articles.$footer;
-
-                            //Save the XML contents to file.
-                            $status = rss_save_file('data', $data, $rss);
                         }
-                        else {
-                            $status = false;
-                        }
-                    }
-                }
-            }
-        }
-        return $status;
+        
+        return $rss;    
     }
 
 ?>
Index: mod/data/view.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/data/view.php,v
retrieving revision 1.98
diff -u -r1.98 view.php
--- mod/data/view.php	29 Jul 2008 17:22:48 -0000	1.98
+++ mod/data/view.php	26 Aug 2008 14:50:30 -0000
@@ -262,7 +262,7 @@
 /// RSS and CSS and JS meta
     $meta = '';
     if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) {
-        $rsspath = rss_get_url($course->id, $USER->id, 'data', $data->id);
+        $rsspath = rss_get_url($context, $USER->id, 'data', $data->id);
         $meta .= '<link rel="alternate" type="application/rss+xml" ';
         $meta .= 'title ="'. format_string($course->shortname) .': %fullname%" href="'.$rsspath.'" />';
     }
@@ -303,7 +303,7 @@
     // Do we need to show a link to the RSS feed for the records?
     if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) {
         echo '<div style="float:right;">';
-        rss_print_link($course->id, $USER->id, 'data', $data->id, get_string('rsstype'));
+        rss_print_link($context, $USER->id, 'data', $data->id, get_string('rsstype'));
         echo '</div>';
         echo '<div style="clear:both;"></div>';
     }
Index: mod/forum/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/index.php,v
retrieving revision 1.116
diff -u -r1.116 index.php
--- mod/forum/index.php	21 Jul 2008 09:20:40 -0000	1.116
+++ mod/forum/index.php	26 Aug 2008 14:50:31 -0000
@@ -228,7 +228,7 @@
                         $tooltiptext = get_string('rsssubscriberssposts', 'forum', format_string($forum->name));
                     }
                     //Get html code for RSS link
-                    $row[] = rss_get_link($course->id, $USER->id, 'forum', $forum->id, $tooltiptext);
+                    $row[] = rss_get_link($context, $USER->id, 'forum', $forum->id, $tooltiptext);
                 } else {
                     $row[] = '&nbsp;';
                 }
Index: mod/forum/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/lib.php,v
retrieving revision 1.716
diff -u -r1.716 lib.php
--- mod/forum/lib.php	23 Aug 2008 07:01:44 -0000	1.716
+++ mod/forum/lib.php	26 Aug 2008 14:50:33 -0000
@@ -5345,8 +5345,9 @@
 
 /**
  * Returns all forum posts since a given time in specified forum.
+ * @param bool $checkonly if true, then this function just checks if non-empty result is possible 
  */
-function forum_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0)  {
+function forum_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0,$checkonly=0)  {
     global $CFG, $COURSE, $USER, $DB;
 
     if ($COURSE->id == $courseid) {
@@ -5387,9 +5388,12 @@
                                         WHERE p.created > ? AND f.id = ?
                                               $userselect $groupselect
                                      ORDER BY p.id ASC", $params)) { // order by initial posting date
-         return;
-    }
 
+         return false;
+    }
+    if ($checkonly) {    
+    	  return true;
+    }
     $groupmode       = groups_get_activity_groupmode($cm, $course);
     $cm_context      = get_context_instance(CONTEXT_MODULE, $cm->id);
     $viewhiddentimed = has_capability('mod/forum:viewhiddentimedposts', $cm_context);
@@ -5429,7 +5433,7 @@
     }
 
     if (!$printposts) {
-        return;
+        return false;
     }
 
     $aname = format_string($cm->name,true);
@@ -5460,9 +5464,23 @@
         $activities[$index++] = $tmpactivity;
     }
 
-    return;
+    return false;
 }
 
+
+
+/**
+ *
+ */
+function forum_get_recent_activity_link($activity, $courseid) {
+    global $CFG;
+ 
+    return "$CFG->wwwroot/mod/forum/discuss.php?d={$activity->content->discussion}"
+         ."#p{$activity->content->id}";
+}
+
+
+
 /**
  *
  */
Index: mod/forum/rsslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/rsslib.php,v
retrieving revision 1.28
diff -u -r1.28 rsslib.php
--- mod/forum/rsslib.php	16 Aug 2008 21:24:05 -0000	1.28
+++ mod/forum/rsslib.php	26 Aug 2008 14:50:33 -0000
@@ -1,128 +1,225 @@
 <?php  // $Id: rsslib.php,v 1.28 2008/08/16 21:24:05 skodak Exp $
     //This file adds support to rss feeds generation
 
-    //This function is the main entry point to forum
-    //rss feeds generation. Foreach site forum with rss enabled
-    //build one XML rss structure.
-    function forum_rss_feeds() {
 
-        global $CFG, $DB;
+    /**
+     * This functions setups forum rss generation cache
+     */         
+    function forum_rss_init_cache($forum, &$items) {
+        global $DB;
+        $items['forum'] =  $DB->get_record('forum',array('id'=>$forum->instance));         
+    }
+    
+    /**
+     * If there is new stuff in the forum since $time then this returns
+     * true.  Otherwise it returns false.
+     */         
+    function forum_rss_newstuff($forum, $time,&$items, $info) {    
+        forum_rss_init_cache($forum,$items);
+        if ($items['forum']->rsstype == 1) {
+            $items['newstuff'] = forum_rss_newstuff_discussions($items['forum'], $time,$forum);
+        } else {
+            $items['newstuff'] = forum_rss_newstuff_posts($items['forum'], $time,$forum);
+        }
+        return (!empty($items['newstuff']));
+    }
 
-        $status = true;
+    /**
+     * Returns new discussions since $newsince
+     */         
+    function forum_rss_newstuff_discussions($forum,$newsince=0, $cm, $context=0) {
+        global $DB,$USER;        
 
-        //Check CFG->enablerssfeeds
-        if (empty($CFG->enablerssfeeds)) {
-            debugging('DISABLED (admin variables)');
-        //Check CFG->forum_enablerssfeeds
-        } else if (empty($CFG->forum_enablerssfeeds)) {
-            debugging('DISABLED (module configuration)');
-        //It's working so we start...
+        if ($newsince) {
+            $newsince = " AND p.modified > '$newsince'";
         } else {
-            //Iterate over all forums
-            if ($forums = $DB->get_records("forum")) {
-                foreach ($forums as $forum) {
-                    if (!empty($forum->rsstype) && !empty($forum->rssarticles) && $status) {
-
-                        $filename = rss_file_name('forum', $forum);  // RSS file
-
-                        //First let's make sure there is work to do by checking existing files
-                        if (file_exists($filename)) {
-                            if ($lastmodified = filemtime($filename)) {
-                                if (!forum_rss_newstuff($forum, $lastmodified)) {
-                                    continue;
-                                }
+            $newsince = "";
                             }
+
+        $limit = get_user_preferences( 'rss_maxitems', $forum->rssarticles );
+        if (!$limit || $limit > $forum->rssarticles) {
+            $limit = $forum->rssarticles;
                         }
 
-                        //Ignore hidden forums
-                        if (!instance_is_visible('forum',$forum)) {
-                            if (file_exists($filename)) {
-                                @unlink($filename);
+        $timelimit = '';
+
+        $now = round(time(), -2);
+        $params = array($forum->id, $newsince);
+        if (!empty($CFG->forum_enabletimedposts)) {            
+
+            if ($context && !has_capability('mod/forum:viewhiddentimedposts', $context)) {
+                $timelimit = " AND ((d.timestart <= ? AND (d.timeend = 0 OR d.timeend > ?))";
+                $params[] = $now;
+                $params[] = $now;
+                if (isloggedin()) {
+                    $timelimit .= " OR d.userid = ?";
+                    $params[] = $USER->id;
+                }
+                $timelimit .= ")";
                             }
-                            continue;
                         }
 
-                        mtrace("Updating RSS feed for ".format_string($forum->name,true).", ID: $forum->id");
+        $groupmode    = groups_get_activity_groupmode($cm);        
 
-                        //Get the XML contents
-                        $result = forum_rss_feed($forum);
-                        //Save the XML contents to file
-                        if (!empty($result)) {
-                            $status = rss_save_file("forum",$forum,$result);
+        if ($groupmode && $context) {           
+            $currentgroup = groups_get_activity_group($cm);
+            if ($groupmode == VISIBLEGROUPS || has_capability('moodle/site:accessallgroups', $context)) {
+                if ($currentgroup) {
+                    $groupselect = "AND (d.groupid = ? OR d.groupid = -1)";
+                    $params[] = $currentgroup;
+                } else {
+                    $groupselect = "";
                         }
-                        if (debugging()) {
-                            if (empty($result)) {
-                                echo "ID: $forum->id-> (empty) ";
+
                             } else {
-                                if (!empty($status)) {
-                                    echo "ID: $forum->id-> OK ";
+                //seprate groups without access all
+                if ($currentgroup) {
+                    $groupselect = "AND (d.groupid = ? OR d.groupid = -1)";
+                    $params[] = $currentgroup;
                                 } else {
-                                    echo "ID: $forum->id-> FAIL ";
-                                }
+                    $groupselect = "AND d.groupid = -1";
                             }
                         }
+        } else {
+            $groupselect = "";
                     }
+   
+        if ($recs = $DB->get_records_sql ("SELECT d.id AS discussionid,
+                                             d.name AS discussionname,
+                                             u.id AS userid,
+                                             u.firstname AS userfirstname,
+                                             u.lastname AS userlastname,
+                                             p.message AS postmessage,
+                                             p.created AS postcreated,
+                                             p.format AS postformat
+                                      FROM {forum_discussions} d,
+                                           {forum_posts} p,
+                                           {user} u
+                                      WHERE d.forum = '$forum->id' AND
+                                            p.discussion = d.id AND
+                                            p.parent = 0 AND
+                                            u.id = p.userid $newsince $timelimit $groupselect
+                                      ORDER BY p.created desc",
+                                      $params, 0, $limit)) {
+            return $recs;
                 }
+        return array();
             }
+    
+    /**
+     * Returns new posts since $newsince
+     */ 
+    function forum_rss_newstuff_posts($forum,$newsince=0,$cm,$context=0) {
+        global $DB,$USER;
+        
+        if ($newsince) {
+            $newsince = " AND p.modified > '$newsince'";
+        } else {
+            $newsince = "";
         }
-        return $status;
+        
+        $limit = get_user_preferences( 'rss_maxitems', $forum->rssarticles );
+        if (!$limit || $limit > $forum->rssarticles) {
+                $limit = $forum->rssarticles;
     }
+        $timelimit = '';
 
-
-    // Given a forum object, deletes the RSS file
-    function forum_rss_delete_file($forum) {
-        global $CFG;
-        $rssfile = rss_file_name('forum', $forum);
-        if (file_exists($rssfile)) {
-            return unlink($rssfile);
-        } else {
-            return true;
+        $now = round(time(), -2);
+        $params = array($forum->id, $newsince);
+        if (!empty($CFG->forum_enabletimedposts)) {            
+
+            if ($context && !has_capability('mod/forum:viewhiddentimedposts', $context)) {
+                $timelimit = " AND ((d.timestart <= ? AND (d.timeend = 0 OR d.timeend > ?))";
+                $params[] = $now;
+                $params[] = $now;
+                if (isloggedin()) {
+                    $timelimit .= " OR d.userid = ?";
+                    $params[] = $USER->id;
         }
+                $timelimit .= ")";
     }
+        }
+        
+        $groupmode    = groups_get_activity_groupmode($cm);
+        $currentgroup = groups_get_activity_group($cm);
+
+        if ($groupmode) {           
+
+            if ($groupmode == VISIBLEGROUPS || !$context || has_capability('moodle/site:accessallgroups', $context)) {
+                if ($currentgroup) {
+                    $groupselect = "AND (d.groupid = ? OR d.groupid = -1)";
+                    $params[] = $currentgroup;
+        } else {
+                    $groupselect = "";
+                }
 
-
-    function forum_rss_newstuff($forum, $time) {
-    // If there is new stuff in the forum since $time then this returns
-    // true.  Otherwise it returns false.
-        if ($forum->rsstype == 1) {
-            $items = forum_rss_feed_discussions($forum, $time);
+            } else {
+                //seprate groups without access all
+                if ($currentgroup) {
+                    $groupselect = "AND (d.groupid = ? OR d.groupid = -1)";
+                    $params[] = $currentgroup;
+                } else {
+                    $groupselect = "AND d.groupid = -1";
+                }
+            }
         } else {
-            $items = forum_rss_feed_posts($forum, $time);
+            $groupselect = "";
         }
-        return (!empty($items));
+        if ($recs = $DB->get_records_sql ("SELECT p.id AS postid,
+                                             d.id AS discussionid,
+                                             d.name AS discussionname,
+                                             u.id AS userid,
+                                             u.firstname AS userfirstname,
+                                             u.lastname AS userlastname,
+                                             p.subject AS postsubject,
+                                             p.message AS postmessage,
+                                             p.created AS postcreated,
+                                             p.format AS postformat
+                                      FROM {forum_discussions} d,
+                                           {forum_posts} p,
+                                           {user} u
+                                      WHERE d.forum = '$forum->id' AND
+                                            p.discussion = d.id AND                                            
+                                            u.id = p.userid $timelimit $newsince $groupselect
+                                      ORDER BY p.created desc", $params, 0, $limit)) {                                     
+            return $recs;
+        }
+       
+        return array();
     }
 
-    //This function return the XML rss contents about the forum record passed as parameter
-    //It returns false if something is wrong
-    function forum_rss_feed($forum) {
+    /**
+     *  This function return the XML rss contents about the forum record passed as parameter
+     *  It returns false if something is wrong
+     */ 
+    function forum_rss_generate_feed($forum, $context, $info, &$cache) {
 
         global $CFG;
 
-        $status = true;
+        if (empty($cache['forum'])) {
+            forum_rss_init_cache($forum,$cache);
+        }
+        
+        $status = false;
 
-        //Check CFG->enablerssfeeds
-        if (empty($CFG->enablerssfeeds)) {
-            debugging("DISABLED (admin variables)");
-        //Check CFG->forum_enablerssfeeds
-        } else if (empty($CFG->forum_enablerssfeeds)) {
+        if (empty($CFG->forum_enablerssfeeds)) {
             debugging("DISABLED (module configuration)");
         //It's working so we start...
         } else {
             //Check the forum has rss activated
-            if (!empty($forum->rsstype) && !empty($forum->rssarticles)) {
+            if (!empty($cache['forum']->rsstype) && !empty($cache['forum']->rssarticles)) {
                 //Depending of the forum->rsstype, we are going to execute, different sqls
-                if ($forum->rsstype == 1) {    //Discussion RSS
-                    $items = forum_rss_feed_discussions($forum);
+                if ($cache['forum']->rsstype == 1) {    //Discussion RSS
+                    $items = forum_rss_feed_discussions($cache['forum'],$cache,$forum,$context);
                 } else {                //Post RSS
-                    $items = forum_rss_feed_posts($forum);
-
+                    $items = forum_rss_feed_posts($cache['forum'],$cache,$forum,$context);
                 }
                 //Now, if items, we begin building the structure
                 if (!empty($items)) {
                     //First all rss feeds common headers
-                    $header = rss_standard_header(strip_tags(format_string($forum->name,true)),
+                    $header = rss_standard_header(strip_tags(format_string($cache['forum']->name,true)),
                                                   $CFG->wwwroot."/mod/forum/view.php?f=".$forum->id,
-                                                  format_string($forum->intro,true));
+                                                  format_string($cache['forum']->intro,true));
                     //Now all the rss items
                     if (!empty($header)) {
                         $articles = rss_add_items($items);
@@ -145,45 +242,26 @@
         return $status;
     }
 
-    //This function returns "items" record array to be used to build the rss feed
-    //for a Type=discussions forum
-    function forum_rss_feed_discussions($forum, $newsince=0) {
+    /**
+     *    This function returns "items" record array to be used to build the rss feed
+     *    for a Type=discussions forum
+     */     
+    function forum_rss_feed_discussions($forum, &$cache,$cm,$context) {
 
         global $CFG, $DB;
 
-        $items = array();
-
-        if ($newsince) {
-            $newsince = " AND p.modified > '$newsince'";
-        } else {
-            $newsince = "";
+        if (empty($cache['newstuff'])) { 
+            $cache['newstuff'] = forum_rss_newstuff_discussions($cache['forum'],0,$cm,$context);
         }
 
-        if ($recs = $DB->get_records_sql ("SELECT d.id AS discussionid,
-                                             d.name AS discussionname,
-                                             u.id AS userid,
-                                             u.firstname AS userfirstname,
-                                             u.lastname AS userlastname,
-                                             p.message AS postmessage,
-                                             p.created AS postcreated,
-                                             p.format AS postformat
-                                      FROM {forum_discussions} d,
-                                           {forum_posts} p,
-                                           {user} u
-                                      WHERE d.forum = '$forum->id' AND
-                                            p.discussion = d.id AND
-                                            p.parent = 0 AND
-                                            u.id = p.userid $newsince
-                                      ORDER BY p.created desc",
-                                      array($forum->id, $newsince), 0, $forum->rssarticles)) {
-
+        $items = array();
             $item = NULL;
             $user = NULL;
 
             $formatoptions = new object;
             $formatoptions->trusttext = true;
 
-            foreach ($recs as $rec) {
+        foreach ($cache['newstuff'] as $rec) {
                 unset($item);
                 unset($user);
                 $item->title = format_string($rec->discussionname);
@@ -195,49 +273,29 @@
                 $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course);
                 $items[] = $item;
             }
-        }
+        
         return $items;
     }
 
-    //This function returns "items" record array to be used to build the rss feed
-    //for a Type=posts forum
-    function forum_rss_feed_posts($forum, $newsince=0) {
+    /** This function returns "items" record array to be used to build the rss feed 
+     *    for a Type=posts forum
+     */     
+    function forum_rss_feed_posts($forum, &$cache,$cm,$context) {
 
         global $CFG, $DB;
 
-        $items = array();
-
-        if ($newsince) {
-            $newsince = " AND p.modified > '$newsince'";
-        } else {
-            $newsince = "";
+        if (empty($cache['newstuff'])) { 
+            $cache['newstuff'] = forum_rss_newstuff_posts($cache['forum'],0,$cm,$context);
         }
 
-        if ($recs = $DB->get_records_sql ("SELECT p.id AS postid,
-                                             d.id AS discussionid,
-                                             d.name AS discussionname,
-                                             u.id AS userid,
-                                             u.firstname AS userfirstname,
-                                             u.lastname AS userlastname,
-                                             p.subject AS postsubject,
-                                             p.message AS postmessage,
-                                             p.created AS postcreated,
-                                             p.format AS postformat
-                                      FROM {forum_discussions} d,
-                                           {forum_posts} p,
-                                           {user} u
-                                      WHERE d.forum = ? AND
-                                            p.discussion = d.id AND
-                                            u.id = p.userid ?
-                                      ORDER BY p.created desc", array($forum->id, $newsince), 0, $forum->rssarticles)) {
-
+        $items = array();
             $item = NULL;
             $user = NULL;
 
             $formatoptions = new object;
             $formatoptions->trusttext = true;
 
-            foreach ($recs as $rec) {
+        foreach ($cache['newstuff'] as $rec) {
                 unset($item);
                 unset($user);
                 $item->category = $rec->discussionname;
@@ -260,7 +318,7 @@
 
                 $items[] = $item;
             }
-        }
+ 
         return $items;
     }
 ?>
Index: mod/forum/view.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/view.php,v
retrieving revision 1.125
diff -u -r1.125 view.php
--- mod/forum/view.php	28 Jul 2008 12:31:32 -0000	1.125
+++ mod/forum/view.php	26 Aug 2008 14:50:33 -0000
@@ -63,8 +63,16 @@
 
 /// Print header.
     $navigation = build_navigation('', $cm);
+    if (isset($CFG->enablerssfeeds) && isset($CFG->forum_enablerssfeeds) &&
+        $CFG->enablerssfeeds && $CFG->forum_enablerssfeeds && $forum->rsstype and $forum->rssarticles) {
+        $rsspath = rss_get_url($context, $USER->id, "forum", $forum->id);
+        $meta = '<link rel="alternate" type="application/rss+xml" ';
+        $meta .= 'title ="'. format_string($forum->name) .' '.get_string('RSS').'" href="'.$rsspath.'" />';
+    } else {
+        $meta = ''; 
+    }
     print_header_simple(format_string($forum->name), "",
-                 $navigation, "", "", true, $buttontext, navmenu($course, $cm));
+                 $navigation, "", $meta, true, $buttontext, navmenu($course, $cm));
 
 /// Some capability checks.
     if (empty($cm->visible) and !has_capability('moodle/course:viewhiddenactivities', $context)) {
@@ -178,7 +186,7 @@
         }
 //        print_box_start('rsslink');
         echo '<span class="wrap rsslink">';
-        rss_print_link($course->id, $userid, "forum", $forum->id, $tooltiptext);
+        rss_print_link($context, $userid, "forum", $forum->id, $tooltiptext);
         echo '</span>';
 //        print_box_end(); // subscription
 
Index: mod/glossary/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/glossary/index.php,v
retrieving revision 1.34
diff -u -r1.34 index.php
--- mod/glossary/index.php	8 Jun 2008 10:43:39 -0000	1.34
+++ mod/glossary/index.php	26 Aug 2008 14:50:33 -0000
@@ -106,7 +106,7 @@
                     $userid = $USER->id;
                 }
                 //Get html code for RSS link
-                $rsslink = rss_get_link($course->id, $userid, "glossary", $glossary->id, $tooltiptext);
+                $rsslink = rss_get_link(get_context_instance(CONTEXT_COURSE,$course->id), $userid, "glossary", $glossary->id, $tooltiptext);
             }
         }
 
Index: mod/glossary/rsslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/glossary/rsslib.php,v
retrieving revision 1.12
diff -u -r1.12 rsslib.php
--- mod/glossary/rsslib.php	8 Jun 2008 10:43:39 -0000	1.12
+++ mod/glossary/rsslib.php	26 Aug 2008 14:50:33 -0000
@@ -1,106 +1,54 @@
-<?php  // $Id: rsslib.php,v 1.12 2008/06/08 10:43:39 skodak Exp $
+<?php  
     //This file adds support to rss feeds generation
 
-    //This function is the main entry point to glossary
-    //rss feeds generation. Foreach site glossary with rss enabled
-    //build one XML rss structure.
-    function glossary_rss_feeds() {
-        global $CFG, $DB;
-
-        $status = true;
-
-        //Check CFG->enablerssfeeds
-        if (empty($CFG->enablerssfeeds)) {
-            debugging("DISABLED (admin variables)");
-        //Check CFG->glossary_enablerssfeeds
-        } else if (empty($CFG->glossary_enablerssfeeds)) {
-            debugging("DISABLED (module configuration)");
-        //It's working so we start...
-        } else {
-            //Iterate over all glossaries
-            if ($glossaries = $DB->get_records("glossary")) {
-                foreach ($glossaries as $glossary) {
-                    if (!empty($glossary->rsstype) && !empty($glossary->rssarticles) && $status) {
-
-                        $filename = rss_file_name('glossary', $glossary);  // RSS file
-
-                        //First let's make sure there is work to do by checking existing files
-                        if (file_exists($filename)) {
-                            if ($lastmodified = filemtime($filename)) {
-                                if (!glossary_rss_newstuff($glossary, $lastmodified)) {
-                                    continue;
-                                }
-                            }
-                        }
-
-                        //Ignore hidden forums
-                        if (!instance_is_visible('glossary',$glossary)) {
-                            if (file_exists($filename)) {
-                                @unlink($filename);
-                            }
-                            continue;
-                        }
-
-                        mtrace("Updating RSS feed for ".format_string($glossary->name,true).", ID: $glossary->id");
-
-                        //Get the XML contents
-                        $result = glossary_rss_feed($glossary);
-                        //Save the XML contents to file
-                        if (!empty($result)) {
-                            $status = rss_save_file("glossary",$glossary,$result);
-                        }
-                        //Some debug...
-                        if (debugging()) {
-                            if (empty($result)) {
-                                echo "ID: $glossary->id-> (empty) ";
-                            } else {
-                                if (!empty($status)) {
-                                    echo "ID: $glossary->id-> OK ";
-                                } else {
-                                    echo "ID: $glossary->id-> FAIL ";
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return $status;
-    }
-
-    function glossary_rss_newstuff($glossary, $time) {
-    // If there is new stuff in the glossary since $time then this returns
-    // true.  Otherwise it returns false.
-        if ($glossary->rsstype == 1) {
-            $items = glossary_rss_feed_withauthor($glossary, $time);
+    /**
+     * Initialize glossary RSS cache
+     */         
+    function glossary_rss_init_cache($glossary,&$cache) {
+        global $DB;
+        $cache['glossary'] =  $DB->get_record('glossary',array('id'=>$glossary->instance));
+        $cache['newstuff'] = array();     
+    }  
+    
+    /**     
+     *  If there is new stuff in the glossary since $time then this returns
+     *  true.  Otherwise it returns false.
+     */     
+    function glossary_rss_newstuff($glossary, $time,&$cache, $info) {
+        glossary_rss_init_cache($glossary,$cache);
+    
+        if ($cache['glossary']->rsstype == 1) {
+            $cache['newstuff'] = glossary_rss_newstuff_withauthor($cache['glossary'], $time);
         } else {
-            $items = glossary_rss_feed_withoutauthor($glossary, $time);
+            $cache['newstuff'] = glossary_rss_newstuff_withoutauthor($cache['glossary'], $time);
         }
-        return (!empty($items));
+        return (!empty($cache['newstuff']));
     }
 
-    //This function return the XML rss contents about the glossary record passed as parameter
-    //It returns false if something is wrong
-    function glossary_rss_feed($glossary) {
+    /**
+     * This function return the XML rss contents about the glossary record passed as parameter
+     * It returns false if something is wrong
+     */     
+    function glossary_rss_generate_feed($glossary, $context, $info, &$cache) {
         global $CFG, $DB;
 
-        $status = true;
+        $status = false;
 
-        //Check CFG->enablerssfeeds
-        if (empty($CFG->enablerssfeeds)) {
-            debugging("DISABLED (admin variables)");
-        //Check CFG->glossary_enablerssfeeds
-        } else if (empty($CFG->glossary_enablerssfeeds)) {
+        if (empty($cache['glossary'])) {
+            glossary_rss_init_cache($glossary,$cache);
+    }
+
+        if (empty($CFG->glossary_enablerssfeeds)) {
             debugging("DISABLED (module configuration)");
         //It's working so we start...
         } else {
             //Check the glossary has rss activated
-            if (!empty($glossary->rsstype) && !empty($glossary->rssarticles)) {
+            if (!empty($cache['glossary']->rsstype) && !empty($cache['glossary']->rssarticles)) {
                 //Depending of the glossary->rsstype, we are going to execute, different sqls
-                if ($glossary->rsstype == 1) {    //With author RSS
-                    $items = glossary_rss_feed_withauthor($glossary);
+                if ($cache['glossary']->rsstype == 1) {    //With author RSS
+                    $items = glossary_rss_feed_withauthor($cache['glossary'],$cache);
                 } else {                //Without author RSS
-                    $items = glossary_rss_feed_withoutauthor($glossary);
+                    $items = glossary_rss_feed_withoutauthor($cache['glossary'],$cache);
 
                 }
                 //Now, if items, we begin building the structure
@@ -108,7 +56,7 @@
                     //First all rss feeds common headers
                     $header = rss_standard_header(format_string($glossary->name,true),
                                                   $CFG->wwwroot."/mod/glossary/view.php?g=".$glossary->id,
-                                                  format_string($glossary->intro,true));
+                                                  get_string("entries", "glossary"));
                     //Now all the rss items
                     if (!empty($header)) {
                         $articles = rss_add_items($items);
@@ -131,13 +79,11 @@
         return $status;
     }
 
-    //This function returns "items" record array to be used to build the rss feed
-    //for a Type=with author glossary
-    function glossary_rss_feed_withauthor($glossary, $newsince=0) {
-        global $CFG, $DB;
-
-        $items = array();
-
+    /**
+     * Returns new entries since $newsince
+     */         
+    function glossary_rss_newstuff_withauthor($glossary, $newsince) {
+        global $DB;
         $params = array('gid'=>$glossary->id, 'newsince'=>$newsince); 
 
         if ($newsince) {
@@ -160,43 +106,58 @@
                                                   u.id = e.userid AND
                                                   e.approved = 1 $newsince
                                          ORDER BY e.timecreated desc", $params)) {
+            return $recs;
+        }
+        return array();
+    } 
+
+    /** 
+     *    This function returns "items" record array to be used to build the rss feed
+     *    for a Type=with author glossary
+     */     
+    function glossary_rss_feed_withauthor($glossary, &$cache) {
+        global $CFG;
 
-            //Are we just looking for new ones?  If so, then return now.
-            if ($newsince) {
-                return true;
+        if (empty($cache['newstuff'])) {
+            $cache['newstuff'] = glossary_rss_newstuff_withauthor($cache['glossary'], 0);
+        }
+        
+        $items = array();
+
+        //Get rss article limit
+        $limit = get_user_preferences( 'rss_maxitems', $cache['glossary']->rssarticles );
+        if (!$limit || $limit > $cache['glossary']->rssarticles) {
+            $limit = $cache['glossary']->rssarticles;
             }
-            //Iterate over each entry to get glossary->rssarticles records
-            $articlesleft = $glossary->rssarticles;
 
             $formatoptions = new object;
             $formatoptions->trusttext = true;
 
-            foreach ($recs as $rec) {
+        foreach ($cache['newstuff'] as $rec) {
                 $item = new object();
-                $user = new user();
+            $user = NULL;
                 $item->title = $rec->entryconcept;
                 $user->firstname = $rec->userfirstname;
                 $user->lastname = $rec->userlastname;
                 $item->author = fullname($user);
                 $item->pubdate = $rec->entrytimecreated;
-                $item->link = $CFG->wwwroot."/mod/glossary/showentry.php?courseid=".$glossary->course."&eid=".$rec->entryid;
-                $item->description = format_text($rec->entrydefinition,$rec->entryformat,$formatoptions,$glossary->course);
+            $item->link = $CFG->wwwroot."/mod/glossary/showentry.php?courseid=".$cache['glossary']->course."&eid=".$rec->entryid;
+            $item->description = format_text($rec->entrydefinition,$rec->entryformat,$formatoptions,$cache['glossary']->course);
                 $items[] = $item;
-                $articlesleft--;
-                if ($articlesleft < 1) {
+            $limit--;
+            if ($limit < 1) {
                     break;
                 }
             }
-        }
+        
         return $items;
     }
 
-    //This function returns "items" record array to be used to build the rss feed
-    //for a Type=without author glossary
-    function glossary_rss_feed_withoutauthor($glossary, $newsince=0) {
-        global $CFG, $DB;
-
-        $items = array();
+    /**
+     * Returns new glossary entries since $newsince
+     */         
+    function glossary_rss_newstuff_withoutauthor($glossary, $newsince=0) {
+        global $DB;
 
         $params = array('gid'=>$glossary->id, 'newsince'=>$newsince); 
 
@@ -220,19 +181,33 @@
                                                   u.id = e.userid AND
                                                   e.approved = 1 $newsince
                                          ORDER BY e.timecreated desc", $params)) {
+            return $recs;
+        }
+        return array();
+    }
 
-            //Are we just looking for new ones?  If so, then return now.
-            if ($newsince) {
-                return true;
+    /** This function returns "items" record array to be used to build the rss feed
+     *  for a Type=without author glossary
+     */       
+    function glossary_rss_feed_withoutauthor($glossary, &$cache) {
+        global $CFG;
+
+        $items = array();
+        
+        if (empty($cache['newstuff'])) {
+            $cache['newstuff'] = glossary_rss_newstuff_withoutauthor($cache['glossary'], 0);
             }
 
-            //Iterate over each entry to get glossary->rssarticles records
-            $articlesleft = $glossary->rssarticles;
+        //Get rss article limit
+        $limit = get_user_preferences( 'rss_maxitems', $cache['glossary']->rssarticles );
+        if (!$limit || $limit > $cache['glossary']->rssarticles) {
+            $limit = $cache['glossary']->rssarticles;
+        }
 
             $formatoptions = new object;
             $formatoptions->trusttext = true;
 
-            foreach ($recs as $rec) {
+        foreach ($cache['newstuff'] as $rec) {
                 $item = new object();
                 $user = new object();
                 $item->title = $rec->entryconcept;
@@ -240,15 +215,15 @@
                 $user->lastname = $rec->userlastname;
                 //$item->author = fullname($user);
                 $item->pubdate = $rec->entrytimecreated;
-                $item->link = $CFG->wwwroot."/mod/glossary/showentry.php?courseid=".$glossary->course."&eid=".$rec->entryid;
+            $item->link = $CFG->wwwroot."/mod/glossary/showentry.php?courseid=".$cache['glossary']->course."&eid=".$rec->entryid;
                 $item->description = format_text($rec->entrydefinition,$rec->entryformat,$formatoptions,$glossary->course);
                 $items[] = $item;
-                $articlesleft--;
-                if ($articlesleft < 1) {
+            $limit--;
+            if ($limit < 1) {
                     break;
                 }
             }
-        }
+    
         return $items;
     }
 
Index: mod/glossary/view.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/glossary/view.php,v
retrieving revision 1.140
diff -u -r1.140 view.php
--- mod/glossary/view.php	17 Aug 2008 21:27:43 -0000	1.140
+++ mod/glossary/view.php	26 Aug 2008 14:50:34 -0000
@@ -225,18 +225,26 @@
     $strsearch = get_string("search");
     $strwaitingapproval = get_string('waitingapproval', 'glossary');
 
+    if (isset($CFG->enablerssfeeds) && isset($CFG->glossary_enablerssfeeds) &&
+            $CFG->enablerssfeeds && $CFG->glossary_enablerssfeeds && $glossary->rsstype && $glossary->rssarticles) {
+        $rsspath = rss_get_url($context, $userid, "glossary", $glossary->id);
+        $meta = '<link rel="alternate" type="application/rss+xml" ';
+        $meta .= 'title ="'. format_string($glossary->name) .' '.get_string('RSS').'" href="'.$rsspath.'" />';
+    } else {
+        $meta = ''; 
+    }
 /// If we are in approval mode, prit special header
     if ($tab == GLOSSARY_APPROVAL_VIEW) {
         require_capability('mod/glossary:approve', $context);
 
         $navigation = build_navigation($strwaitingapproval, $cm);
-        print_header_simple(format_string($glossary->name), "", $navigation, "", "", true,
+        print_header_simple(format_string($glossary->name), "", $navigation, "", $meta, true,
             update_module_button($cm->id, $course->id, $strglossary), navmenu($course, $cm));
 
         print_heading($strwaitingapproval);
     } else { /// Print standard header
         $navigation = build_navigation('', $cm);
-        print_header_simple(format_string($glossary->name), "", $navigation, "", "", true,
+        print_header_simple(format_string($glossary->name), "", $navigation, "", $meta, true,
             update_module_button($cm->id, $course->id, $strglossary), navmenu($course, $cm));
     }
 
@@ -299,7 +307,7 @@
             }
 //            print_box_start('rsslink');
             echo '<span class="wrap rsslink">';
-            rss_print_link($course->id, $userid, "glossary", $glossary->id, $tooltiptext);
+            rss_print_link($context, $userid, "glossary", $glossary->id, $tooltiptext);
             echo '</span>';
 //            print_box_end();
         }
Index: mod/hotpot/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/hotpot/lib.php,v
retrieving revision 1.105
diff -u -r1.105 lib.php
--- mod/hotpot/lib.php	16 Aug 2008 12:16:08 -0000	1.105
+++ mod/hotpot/lib.php	26 Aug 2008 14:50:35 -0000
@@ -1040,7 +1040,11 @@
     return $result;  //  True if anything was printed, otherwise false
 }
 
-function hotpot_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $cmid="", $userid="", $groupid="") {
+/**
+ * Returns all records since a given time in instance.
+ * @param bool $checkonly if true, then this function just checks if non-empty result is possible 
+ */
+function hotpot_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $cmid="", $userid="", $groupid="",$checkonly=0) {
 // Returns all quizzes since a given time.
     global $CFG, $DB;
 
@@ -1074,6 +1078,9 @@
     ", $params);
 
     if (!empty($records)) {
+        if ($checkonly) {
+            return true;
+        }
         foreach ($records as $record) {
             if (empty($groupid) || groups_is_member($groupid, $record->userid)) {
 
@@ -1104,6 +1111,15 @@
             }
         } // end foreach
     }
+    return false;
+}
+
+/// Used by Recent Activity RSS feed. 
+function hotpot_get_recent_activity_link($activity, $courseid) {
+
+    global $CFG;
+    
+    return "$CFG->wwwroot/mod/hotpot/view.php?hp=$activity->instance";            
 }
 
 function hotpot_print_recent_mod_activity($activity, $course, $detail=false) {
Index: mod/quiz/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/quiz/lib.php,v
retrieving revision 1.314
diff -u -r1.314 lib.php
--- mod/quiz/lib.php	26 Aug 2008 01:05:01 -0000	1.314
+++ mod/quiz/lib.php	26 Aug 2008 14:50:35 -0000
@@ -583,8 +583,9 @@
 
 /**
  * Returns all quiz graded users since a given time for specified quiz
+ * @param bool $checkonly if true, then this function just checks if non-empty result is possible 
  */
-function quiz_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0)  {
+function quiz_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0,$checkonly=0)  {
     global $CFG, $COURSE, $USER, $DB;
 
     if ($COURSE->id == $courseid) {
@@ -593,7 +594,7 @@
         $course = $DB->get_record('course', array('id' => $courseid));
     }
 
-    $modinfo =& get_fast_modinfo($course);
+    $modinfo =& get_fast_modinfo($course,$checkonly);
 
     $cm = $modinfo->cms[$cmid];
 
@@ -624,7 +625,10 @@
                                        WHERE qa.timefinish > $timestart AND q.id = $cm->instance
                                              $userselect $groupselect
                                     ORDER BY qa.timefinish ASC", $params)) {
-         return;
+         return false;
+    }
+    if ($checkonly) {    
+    	  return true;
     }
 
 
@@ -680,9 +684,14 @@
         $activities[$index++] = $tmpactivity;
     }
 
-  return;
+  return false;
 }
 
+function quiz_get_recent_activity_link($activity, $courseid) {
+    global $CFG;
+               
+    return "$CFG->wwwroot/mod/quiz/review.php?attempt={$activity->content->attemptid}";  
+}
 
 function quiz_print_recent_mod_activity($activity, $courseid, $detail, $modnames) {
     global $CFG;
Index: rss/file.php
===================================================================
RCS file: /cvsroot/moodle/moodle/rss/file.php,v
retrieving revision 1.22
diff -u -r1.22 file.php
--- rss/file.php	19 Jun 2008 22:27:14 -0000	1.22
+++ rss/file.php	26 Aug 2008 14:50:38 -0000
@@ -1,17 +1,6 @@
 <?PHP //$Id: file.php,v 1.22 2008/06/19 22:27:14 skodak Exp $
-    //This file returns the required rss feeds
-    //The URL format MUST include:
-    //    course: the course id
-    //    user:   the user id
-    //    name:   the name of the module (forum...)
-    //    id:     the id (instance) of the module (forumid...)
-    //If the course has a password or it doesn't
-    //allow guest access then the user field is
-    //required to see that the user is enrolled
-    //in the course, else no check is performed.
-    //This allows to limit a bit the rss access
-    //to correct users. It isn't unbreakable,
-    //obviously, but its the best I've thought!!
+    //This file is for compatibility only. 
+    //RSS feed generation is moved to rssfile.php    
 
     define('NO_MOODLE_COOKIES', true); // session not used here
 
@@ -19,100 +8,54 @@
     require_once($CFG->libdir.'/filelib.php');
     require_once($CFG->libdir.'/rsslib.php');
 
-    $lifetime = 3600;  // Seconds for files to remain in caches - 1 hour
-
-    // hack for problems with concurrent use of NO_MOODLE_COOKIES and capabilities MDL-7243
-    // it should be replaced once we get to codes in urls 
-    $USER = new object();
-    $USER->id = 0;
-
-    // disable moodle specific debug messages
-    disable_debugging();
-
     $relativepath = get_file_argument('file.php');
 
 
-    if (!$relativepath) {
-        rss_not_found();
-    }
-
+    $link = $CFG->wwwroot; 
+    if ($relativepath) {
     // extract relative path components
     $args = explode('/', trim($relativepath, '/'));
 
-    if (count($args) < 5) {
-        rss_not_found();
-    }
-
     $courseid   = (int)$args[0];
     $userid     = (int)$args[1];
     $modulename = clean_param($args[2], PARAM_FILE);
     $instance   = $args[3];
     $filename   = 'rss.xml';
 
-    if ($isblog = $modulename == 'blog') {
+        if ($modulename == 'blog') {
        $blogid   = (int)$args[4];  // could be groupid / courseid  / userid  depending on $instance
        if ($args[5] != 'rss.xml') {
-           $tagid = (int)$args[5];
-       } else {
-           $tagid = 0;
+                $adv='tagid='.((int)$args[5]).'&';  
        }
+            $adv.='filtertype='.$args[3].'&filterselect='.$args[4];
+            $link .= '/blog/index.php?'.$adv;
     } else {
-        $instance = (int)$instance;  // we know it's an id number
-    }
-
-
-    if (!$course = $DB->get_record('course', array('id'=>$courseid))) {
-        rss_not_found();
+            if ($cm = get_coursemodule_from_instance($modulename,(int)$instance)) {
+                $link .= '/mod/'.$modulename.'/view.php?id='.$cm->id;
     }
-
-    //Check name of module
-    if (!$isblog) {
-        $mods = get_list_of_plugins('mod');
-        if (!in_array(strtolower($modulename), $mods)) {
-            rss_not_found();
-        }
-        //Get course_module to check it's visible
-        if (!$cm = get_coursemodule_from_instance($modulename,$instance,$courseid)) {
-            rss_not_found();
         }
-        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-        $isuser = has_capability('moodle/course:view', $context, $userid);   // Not ideal, this should be module-specific, but deferring until RSS gets a revamp with codes in the URLs
-    } else {
-        $context = get_context_instance(CONTEXT_COURSE, $course->id);
-        $isuser = has_capability('moodle/course:view', $context, $userid);
     }
     
-    //Check for "security" if !course->guest or course->password
-    if ($course->id != SITEID) {
-        if ((!$course->guest || $course->password) && (!$isuser)) {
-            rss_not_found();
-        }
-    }
 
-    //Check for "security" if the course is hidden or the activity is hidden
-    if (!$isblog and (!$course->visible || !$cm->visible) && (!has_capability('moodle/course:viewhiddenactivities', $context))) {
-        rss_not_found();
-    }
+     //XML Header
+    $content = rss_standard_header();
 
-    //Work out the filename of the RSS file
-    if ($isblog) {
-        require_once($CFG->dirroot.'/blog/rsslib.php');
-        $pathname = blog_generate_rss_feed($instance, $blogid, $tagid);
-    } else {
-        $pathname = $CFG->dataroot.'/rss/'.$modulename.'/'.$instance.'.xml';
+    //XML item
+    if ($content) {
+        $item = new object();
+        $item->title       = "RSS Error";
+        $item->link        = $link;
+        $item->pubdate     = time();
+        $item->description = get_string('rss20compat','rss').'<br /><a>'.$link.'</a>';        
+        $content .= rss_add_items(array($item),1);
+    }
+
+    //XML Footer
+    if ($content) {
+        $content .= rss_standard_footer();
     }
 
-    //Check that file exists
-    if (!file_exists($pathname)) {
-        rss_not_found();
-    }
+    rss_output($content,time());
+        
 
-    //Send it to user!
-    send_file($pathname, $filename, $lifetime);
-
-    function rss_not_found() {
-        /// error, send some XML with error message
-        global $lifetime, $filename;
-        send_file(rss_geterrorxmlfile(), $filename, $lifetime, false, true);
-    }
 ?>
Index: user/tabs.php
===================================================================
RCS file: /cvsroot/moodle/moodle/user/tabs.php,v
retrieving revision 1.61
diff -u -r1.61 tabs.php
--- user/tabs.php	26 Aug 2008 05:45:08 -0000	1.61
+++ user/tabs.php	26 Aug 2008 14:50:39 -0000
@@ -262,6 +262,11 @@
         $toprow[] = new tabobject('editmessage', $CFG->wwwroot.'/message/edit.php?id='.$user->id.'&amp;course='.$course->id, get_string('editmymessage', 'message'));
     }
 
+    /// RSS tab
+    if ($user->id == $USER->id) {
+        $toprow[] = new tabobject('editrss', $CFG->wwwroot.'/rss/edit.php?id='.$user->id.'&amp;course='.$course->id, get_string('rss'));
+    }
+
 
 /// Add second row to display if there is one
 
