--- lib.php.orig	2012-01-24 13:13:40.000000000 -0800
+++ lib.php	2012-02-14 11:16:37.905604074 -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,47 @@
 
                     // 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);
+                        // iterate through each category to get to the last
+                        // one, create it if necessary (and allowed)
+                        $catid = 0;
+                        $t_catname = '';
+                        foreach ($matches as $catname) {
+                            $catname = trim($catname);
+                            if (strlen($t_catname)) {
+                                $t_catname .= ' / ';
+                            }
+                            $t_catname .= $catname;
+                            $parentid = $catid;
+                            if ($catid = $DB->get_field('course_categories', 'id', array('name'=>$catname,'parent'=>$parentid))) {
+                                $course->category = $catid;
+                                continue; // This category exists, skip to the next one
+                            }
+                            if ($createnewcategories) {
+                                // Create this category
+                                $newcat = new stdClass();
+                            	$newcat->name = $catname;
+                            	$newcat->visible = 0;
+								$newcat->parent = $parentid;
+                          		$catid = $DB->insert_record('course_categories', $newcat);
+                                $course->category = $catid;
+                            	$this->log_line("Created new (hidden) category '$t_catname'");
+                            } else {
+                            	// we encountered a category that doesn't
+                            	// exist and we can't create it; set the
+                            	// default category for this course.
+                            	$course->category = 1; // Miscellaneous
+                            	$this->log_line("Cannot create requested category '$group->category'; setting to Miscellaneous.");
+                            	break;
+							}
+						}
+					} else {
+					    // If no category was specified, set to Misc
+					    $course->category = 1; // Miscellaneous
                     }
+
                     $course->timecreated = time();
                     $course->startdate = time();
                     // Choose a sort order that puts us at the start of the list!
@@ -417,9 +443,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 +478,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 +490,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 +533,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 +541,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 +566,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;
