--- loncom/lonnet/perl/lonnet.pm	2010/03/24 03:29:56	1.1056.2.1
+++ loncom/lonnet/perl/lonnet.pm	2010/08/20 20:47:18	1.1056.2.6
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1056.2.1 2010/03/24 03:29:56 raeburn Exp $
+# $Id: lonnet.pm,v 1.1056.2.6 2010/08/20 20:47:18 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -3059,7 +3059,7 @@ sub courseiddump {
     my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,
         $coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,
         $selfenrollonly,$catfilter,$showhidden,$caller,$cloner,$cc_clone,
-        $cloneonly,$createdbefore,$createdafter,$creationcontext)=@_;
+        $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner)=@_;
     my $as_hash = 1;
     my %returnhash;
     if (!$domfilter) { $domfilter=''; }
@@ -3081,7 +3081,8 @@ sub courseiddump {
                          $showhidden.':'.$caller.':'.&escape($cloner).':'.
                          &escape($cc_clone).':'.$cloneonly.':'.
                          &escape($createdbefore).':'.&escape($createdafter).':'.
-                         &escape($creationcontext),$tryserver);
+                         &escape($creationcontext).':'.$domcloner,
+                         $tryserver);
                 my @pairs=split(/\&/,$rep);
                 foreach my $item (@pairs) {
                     my ($key,$value)=split(/\=/,$item,2);
@@ -4028,23 +4029,36 @@ sub standard_roleprivs {
 }
 
 sub set_userprivs {
-    my ($userroles,$allroles,$allgroups) = @_; 
+    my ($userroles,$allroles,$allgroups,$groups_roles) = @_; 
     my $author=0;
     my $adv=0;
     my %grouproles = ();
     if (keys(%{$allgroups}) > 0) {
+        my @groupkeys;
         foreach my $role (keys(%{$allroles})) {
-            my ($trole,$area,$sec,$extendedarea);
-            if ($role =~ m-^(\w+|cr/$match_domain/$match_username/\w+)\.(/$match_domain/$match_courseid)(/?\w*)\.-) {
-                $trole = $1;
-                $area = $2;
-                $sec = $3;
-                $extendedarea = $area.$sec;
-                if (exists($$allgroups{$area})) {
-                    foreach my $group (keys(%{$$allgroups{$area}})) {
-                        my $spec = $trole.'.'.$extendedarea;
-                        $grouproles{$spec.'.'.$area.'/'.$group} = 
-                                                $$allgroups{$area}{$group};
+            push(@groupkeys,$role);
+        }
+        if (ref($groups_roles) eq 'HASH') {
+            foreach my $key (keys(%{$groups_roles})) {
+                unless (grep(/^\Q$key\E$/,@groupkeys)) {
+                    push(@groupkeys,$key);
+                }
+            }
+        }
+        if (@groupkeys > 0) {
+            foreach my $role (@groupkeys) {
+                my ($trole,$area,$sec,$extendedarea);
+                if ($role =~ m-^(\w+|cr/$match_domain/$match_username/\w+)\.(/$match_domain/$match_courseid)(/?\w*)\.-) {
+                    $trole = $1;
+                    $area = $2;
+                    $sec = $3;
+                    $extendedarea = $area.$sec;
+                    if (exists($$allgroups{$area})) {
+                        foreach my $group (keys(%{$$allgroups{$area}})) {
+                            my $spec = $trole.'.'.$extendedarea;
+                            $grouproles{$spec.'.'.$area.'/'.$group} = 
+                                                  $$allgroups{$area}{$group};
+                        }
                     }
                 }
             }
@@ -4091,26 +4105,58 @@ sub role_status {
                 if ($$tstart<$now) {
                     if ($$tstart && $$tstart>$refresh) {
                         if (($$where ne '') && ($$role ne '')) {
-                            my (%allroles,%allgroups,$group_privs);
+                            my (%allroles,%allgroups,$group_privs,
+                                %groups_roles,@rolecodes);
                             my %userroles = (
                                 'user.role.'.$$role.'.'.$$where => $$tstart.'.'.$$tend
                             );
+                            @rolecodes = ('cm');
                             my $spec=$$role.'.'.$$where;
                             my ($tdummy,$tdomain,$trest)=split(/\//,$$where);
                             if ($$role =~ /^cr\//) {
                                 &custom_roleprivs(\%allroles,$$role,$tdomain,$trest,$spec,$$where);
+                                push(@rolecodes,'cr');
                             } elsif ($$role eq 'gr') {
+                                push(@rolecodes,$$role);
                                 my %rolehash = &get('roles',[$$where.'_'.$$role],$env{'user.domain'},
                                                     $env{'user.name'});
-                                my $trole = split('_',$rolehash{$$where.'_'.$$role},1);
+                                my ($trole) = split('_',$rolehash{$$where.'_'.$$role},2);
                                 (undef,my $group_privs) = split(/\//,$trole);
                                 $group_privs = &unescape($group_privs);
                                 &group_roleprivs(\%allgroups,$$where,$group_privs,$$tend,$$tstart);
+                                my %course_roles = &get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',['active'],['cc','co','in','ta','ep','ad','st','cr'],[$tdomain],1);
+                                if (keys(%course_roles) > 0) {
+                                    my ($tnum) = ($trest =~ /^($match_courseid)/);
+                                    if ($tdomain ne '' && $tnum ne '') {
+                                        foreach my $key (keys(%course_roles)) {
+                                            if ($key =~ /^\Q$tnum\E:\Q$tdomain\E:([^:]+):?([^:]*)/) {
+                                                my $crsrole = $1;
+                                                my $crssec = $2;
+                                                if ($crsrole =~ /^cr/) {
+                                                    unless (grep(/^cr$/,@rolecodes)) {
+                                                        push(@rolecodes,'cr');
+                                                    }
+                                                } else {
+                                                    unless(grep(/^\Q$crsrole\E$/,@rolecodes)) {
+                                                        push(@rolecodes,$crsrole);
+                                                    }
+                                                }
+                                                my $rolekey = $crsrole.'./'.$tdomain.'/'.$tnum;
+                                                if ($crssec ne '') {
+                                                    $rolekey .= '/'.$crssec;
+                                                }
+                                                $rolekey .= './';
+                                                $groups_roles{$rolekey} = \@rolecodes;
+                                            }
+                                        }
+                                    }
+                                }
                             } else {
+                                push(@rolecodes,$$role);
                                 &standard_roleprivs(\%allroles,$$role,$tdomain,$spec,$trest,$$where);
                             }
-                            my ($author,$adv)= &set_userprivs(\%userroles,\%allroles,\%allgroups);
-                            &appenv(\%userroles,[$$role,'cm']);
+                            my ($author,$adv)= &set_userprivs(\%userroles,\%allroles,\%allgroups,\%groups_roles);
+                            &appenv(\%userroles,\@rolecodes);
                             &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$role);
                         }
                     }
@@ -4624,7 +4670,7 @@ sub get_portfolio_access {
                 my (%allgroups,%allroles); 
                 my ($start,$end,$role,$sec,$group);
                 foreach my $envkey (%env) {
-                    if ($envkey =~ m-^user\.role\.(gr|cc|in|ta|ep|st)\./($match_domain)/($match_courseid)/?([^/]*)$-) {
+                    if ($envkey =~ m-^user\.role\.(gr|cc|co|in|ta|ep|ad|st)\./($match_domain)/($match_courseid)/?([^/]*)$-) {
                         my $cid = $2.'_'.$3; 
                         if ($1 eq 'gr') {
                             $group = $4;
@@ -5617,8 +5663,7 @@ sub update_allusers_table {
                'generation='.&escape($names->{'generation'}).'%%'.
                'permanentemail='.&escape($names->{'permanentemail'}).'%%'.
                'id='.&escape($names->{'id'}),$homeserver);
-    my $reply = &get_query_reply($queryid);
-    return $reply;
+    return;
 }
 
 # ------- Request retrieval of institutional classlists for course(s)
@@ -5812,8 +5857,8 @@ sub auto_validate_instcode {
             $homeserver = &domain($cdom,'primary');
         }
     }
-    my $response=&unescape(&reply('autovalidateinstcode:'.$cdom.':'.
-                           &escape($instcode).':'.&escape($owner),$homeserver));
+    $response=&unescape(&reply('autovalidateinstcode:'.$cdom.':'.
+                        &escape($instcode).':'.&escape($owner),$homeserver));
     my ($outcome,$description) = map { &unescape($_); } split('&',$response,2);
     return ($outcome,$description);
 }
@@ -6541,6 +6586,10 @@ sub modifyuser {
              ' by '.$env{'user.name'}.' at '.$env{'user.domain'}.
              ' in domain '.$env{'request.role.domain'});
     my $uhome=&homeserver($uname,$udom,'true');
+    my $newuser;
+    if ($uhome eq 'no_host') {
+        $newuser = 1;
+    }
 # ----------------------------------------------------------------- Create User
     if (($uhome eq 'no_host') && 
 	(($umode && $upass) || ($umode eq 'localauth'))) {
@@ -6593,11 +6642,12 @@ sub modifyuser {
 		   ['firstname','middlename','lastname','generation','id',
                     'permanentemail','inststatus'],
 		   $udom,$uname);
-    my %names;
+    my (%names,%oldnames);
     if ($tmp[0] =~ m/^error:.*/) { 
         %names=(); 
     } else {
         %names = @tmp;
+        %oldnames = %names;
     }
 #
 # If name, email and/or uid are blank (e.g., because an uploaded file
@@ -6651,11 +6701,7 @@ sub modifyuser {
             }
         }
     }
-    my $reply = &put('environment', \%names, $udom,$uname);
-    if ($reply ne 'ok') { return 'error: '.$reply; }
-    my $sqlresult = &update_allusers_table($uname,$udom,\%names);
-    &devalidate_cache_new('namescache',$uname.':'.$udom);
-    my $logmsg = 'Success modifying user '.$udom.', '.$uname.', '.$uid.', '.
+    my $logmsg = $udom.', '.$uname.', '.$uid.', '.
                  $umode.', '.$first.', '.$middle.', '.
 	         $last.', '.$gene.', '.$email.', '.$inststatus;
     if ($env{'user.name'} ne '' && $env{'user.domain'}) {
@@ -6663,6 +6709,29 @@ sub modifyuser {
     } else {
         $logmsg .= ' during self creation';
     }
+    my $changed;
+    if ($newuser) {
+        $changed = 1;
+    } else {
+        foreach my $field (@fields) {
+            if ($names{$field} ne $oldnames{$field}) {
+                $changed = 1;
+                last;
+            }
+        }
+    }
+    unless ($changed) {
+        $logmsg = 'No changes in user information needed for: '.$logmsg;
+        &logthis($logmsg);
+        return 'ok';
+    }
+    my $reply = &put('environment', \%names, $udom,$uname);
+    if ($reply ne 'ok') {
+        return 'error: '.$reply;
+    }
+    my $sqlresult = &update_allusers_table($uname,$udom,\%names);
+    &devalidate_cache_new('namescache',$uname.':'.$udom);
+    $logmsg = 'Success modifying user '.$logmsg;
     &logthis($logmsg);
     return 'ok';
 }