--- lib.php.orig	2012-01-24 13:13:40.061620347 -0800
+++ lib.php	2012-01-25 08:01:04.621602745 -0800
@@ -308,7 +308,11 @@
     // Get configs
     $truncatecoursecodes    = $this->get_config('truncatecoursecodes');
     $createnewcourses       = $this->get_config('createnewcourses');
+    $updatecourses          = $this->get_config('updatecourses');
     $createnewcategories    = $this->get_config('createnewcategories');
+    $categoryseparator      = trim($this->get_config('categoryseparator'));
+
+    if (!$categoryseparator) { $categoryseparator = '|'; }
 
     // Process tag contents
     $group = new stdClass();
@@ -377,25 +381,36 @@
 
                     // Handle course categorisation (taken from the group.org.orgunit field if present)
                     if (strlen($group->category)>0) {
-                        // If the category is defined and exists in Moodle, we want to store it in that one
-                        if ($catid = $DB->get_field('course_categories', 'id', array('name'=>$group->category))) {
-                            $course->category = $catid;
-                        } else if ($createnewcategories) {
-                            // Else if we're allowed to create new categories, let's create this one
-                            $newcat = new stdClass();
-                            $newcat->name = $group->category;
-                            $newcat->visible = 0;
-                            $catid = $DB->insert_record('course_categories', $newcat);
-                            $course->category = $catid;
-                            $this->log_line("Created new (hidden) category, #$catid: $newcat->name");
-                        } else {
-                            // If not found and not allowed to create, stick with default
-                            $this->log_line('Category '.$group->category.' not found in Moodle database, so using default category instead.');
-                            $course->category = 1;
-                        }
-                    } else {
-                        $course->category = 1;
-                    }
+						// Categories can be nested now...
+                        $sep = '{\\'.$categoryseparator.'}';
+						$matches = preg_split($sep, $group->category, -1, PREG_SPLIT_NO_EMPTY);
+						if ($catid = $DB->get_field('course_categories', 'id', array('name'=>trim(end($matches))))) {
+							// If the last category specified exists, use it
+							$course->category = $catid;
+						} else if ($createnewcategories) {
+							// If we can create categories, iterate through each one and create it if necessary
+							$catid = 0;
+							foreach ($matches as $catname) {
+								$catname = trim($catname);
+								$parentid = $catid;
+								if ($catid = $DB->get_field('course_categories', 'id', array('name'=>$catname))) {
+									continue; // This category exists, skip to the next one
+								}
+                            	// Create this category
+                            	$newcat = new stdClass();
+                            	$newcat->name = $catname;
+                            	$newcat->visible = 0;
+								$newcat->parent = $parentid;  
+                          		$catid = $DB->insert_record('course_categories', $newcat);
+                            	$this->log_line("Created new (hidden) category, #$catid: $newcat->name");
+							}
+							// put this course into the last category in the list
+							$course->category = $catid;
+						} else {
+							// Otherwise default
+							$course->category = 1;
+						}
+					}
                     $course->timecreated = time();
                     $course->startdate = time();
                     // Choose a sort order that puts us at the start of the list!
@@ -417,9 +432,23 @@
 
                     $this->log_line("Created course $coursecode in Moodle (Moodle ID is $course->id)");
                 }
+			} else if ($recstatus==2 && ($courseid = $DB->get_field('course', 'id', array('idnumber'=>$coursecode)))) {
+			    if ($updatecourses) {
+				    // Update - the only thing to update is 'fullname'...
+				    $fullname = $DB->get_field('course', 'fullname', array('idnumber'=>$coursecode));
+				    if ($fullname != $group->description) {
+					    $DB->set_field('course', 'fullname', $group->description, array('idnumber'=>$coursecode));
+					    add_to_log(SITEID, "course", "update", "view.php?id=$courseid", "$group->description (ID $courseid)");
+					    $this->log_line("Updated course $coursecode in Moodle (Moodle ID is $courseid)");
+                    }
+				} else {
+				    $this->log_line("Ignoring update to course $coursecode");
+                }
             } else if ($recstatus==3 && ($courseid = $DB->get_field('course', 'id', array('idnumber'=>$coursecode)))) {
                 // If course does exist, but recstatus==3 (delete), then set the course as hidden
                 $DB->set_field('course', 'visible', '0', array('id'=>$courseid));
+                add_to_log(SITEID, "course", "delete", "view.php?id=$courseid", "$group->description (ID $courseid)");
+                $this->log_line("Deleted (set to not visible) course $coursecode in Moodle (Moodle ID is $courseid)");
             }
         } // End of foreach(coursecode)
     }
@@ -438,6 +467,7 @@
     $fixcasepersonalnames   = $this->get_config('fixcasepersonalnames');
     $imsdeleteusers         = $this->get_config('imsdeleteusers');
     $createnewusers         = $this->get_config('createnewusers');
+    $imsupdateusers         = $this->get_config('imsupdateusers');
 
     $person = new stdClass();
     if(preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $tagcontents, $matches)){
@@ -449,7 +479,10 @@
     if(preg_match('{<name>.*?<n>.*?<family>(.+?)</family>.*?</n>.*?</name>}is', $tagcontents, $matches)){
         $person->lastname = trim($matches[1]);
     }
-    if(preg_match('{<userid>(.*?)</userid>}is', $tagcontents, $matches)){
+    if(preg_match('{<userid\s+authenticationtype\s*=\s*"*(.+?)"*>.*?</userid>}is', $tagcontents, $matches)){
+        $person->auth = trim($matches[1]);
+    }
+    if(preg_match('{<userid.*?>(.*?)</userid>}is', $tagcontents, $matches)){
         $person->username = trim($matches[1]);
     }
     if($imssourcedidfallback && trim($person->username)==''){
@@ -489,7 +522,6 @@
     // Now if the recstatus is 3, we should delete the user if-and-only-if the setting for delete users is turned on
     // In the "users" table we can do this by setting deleted=1
     if($recstatus==3){
-
         if($imsdeleteusers){ // If we're allowed to delete user records
             // Make sure their "deleted" field is set to one
             $DB->set_field('user', 'deleted', 1, array('username'=>$person->username));
@@ -498,9 +530,19 @@
             $this->log_line("Ignoring deletion request for user '$person->username' (ID number $person->idnumber).");
         }
 
-    }else{ // Add or update record
-
-
+    } else if ($recstatus==2) { // Update
+        if ($imsupdateusers) {
+		    if ($id = $DB->get_field('user', 'id', array('idnumber'=>$person->idnumber))) {
+			    $person->id = $id;
+			    $DB->update_record('user', $person);
+			    $this->log_line("Updated user $person->username");
+            } else {
+			    $this->log_line("Ignoring update request for non-existent user $person->username");
+            }
+        } else {
+            $this->log_line("Ignoring update request for user $person->username");
+        }
+	}else{ // Add record
         // If the user exists (matching sourcedid) then we don't need to do anything.
         if(!$DB->get_field('user', 'id', array('idnumber'=>$person->idnumber)) && $createnewusers){
             // If they don't exist and haven't a defined username, we log this as a potential problem.
@@ -513,7 +555,7 @@
 
             // If they don't exist and they have a defined username, and $createnewusers == true, we create them.
             $person->lang = 'manual'; //TODO: this needs more work due tu multiauth changes
-            $person->auth = $CFG->auth;
+			if (!$person->auth) { $person->auth = $CFG->auth; }
             $person->confirmed = 1;
             $person->timemodified = time();
             $person->mnethostid = $CFG->mnet_localhost_id;
