--- loncom/lonnet/perl/lonnet.pm 2012/02/01 18:27:09 1.1056.4.33.2.1 +++ loncom/lonnet/perl/lonnet.pm 2011/02/24 23:55:58 1.1104 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.1056.4.33.2.1 2012/02/01 18:27:09 raeburn Exp $ +# $Id: lonnet.pm,v 1.1104 2011/02/24 23:55:58 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -76,8 +76,7 @@ use HTTP::Date; use Image::Magick; use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir - $_64bit %env %protocol %loncaparevs %serverhomeIDs %needsrelease - %managerstab); + $_64bit %env %protocol %loncaparevs %serverhomeIDs %needsrelease); my (%badServerCache, $memcache, %courselogs, %accesshash, %domainrolehash, %userrolehash, $processmarker, $dumpcount, %coursedombuf, @@ -197,29 +196,6 @@ sub get_server_timezone { } } -sub get_server_distarch { - my ($lonhost,$ignore_cache) = @_; - if (defined($lonhost)) { - if (!defined(&hostname($lonhost))) { - return; - } - my $cachetime = 12*3600; - if (!$ignore_cache) { - my ($distarch,$cached)=&is_cached_new('serverdistarch',$lonhost); - if (defined($cached)) { - return $distarch; - } - } - my $rep = &reply('serverdistarch',$lonhost); - unless ($rep eq 'unknown_command' || $rep eq 'no_such_host' || - $rep eq 'con_lost' || $rep eq 'rejected' || $rep eq 'refused' || - $rep eq '') { - return &do_cache_new('serverdistarch',$lonhost,$rep,$cachetime); - } - } - return; -} - sub get_server_loncaparev { my ($dom,$lonhost,$ignore_cache,$caller) = @_; if (defined($lonhost)) { @@ -288,7 +264,7 @@ sub get_server_homeID { } my $cachetime = 12*3600; my $serverhomeID; - if ($caller eq 'loncron') { + if ($caller eq 'loncron') { my @machine_ids = &machine_ids($hostname); foreach my $id (@machine_ids) { my $response = &reply('serverhomeID',$id); @@ -636,11 +612,20 @@ sub appenv { # ----------------------------------------------------- Delete from Environment sub delenv { - my ($delthis,$regexp) = @_; - if (($delthis=~/user\.role/) || ($delthis=~/user\.priv/)) { - &logthis("WARNING: ". - "Attempt to delete from environment ".$delthis); - return 'error'; + my ($delthis,$regexp,$roles) = @_; + if (($delthis=~/^user\.role/) || ($delthis=~/^user\.priv/)) { + my $refused = 1; + if (ref($roles) eq 'ARRAY') { + my ($type,$role) = ($delthis =~ /^user\.(role|priv)\.([^.]+)\./); + if (grep(/^\Q$role\E$/,@{$roles})) { + $refused = 0; + } + } + if ($refused) { + &logthis("WARNING: ". + "Attempt to delete from environment ".$delthis); + return 'error'; + } } my $opened = open(my $env_file,'+<',$env{'user.environment'}); if ($opened @@ -749,30 +734,6 @@ sub userload { return $userloadpercent; } -# ------------------------------------------ Fight off request when overloaded - -sub overloaderror { - my ($r,$checkserver)=@_; - unless ($checkserver) { $checkserver=$perlvar{'lonHostID'}; } - my $loadavg; - if ($checkserver eq $perlvar{'lonHostID'}) { - open(my $loadfile,'/proc/loadavg'); - $loadavg=<$loadfile>; - $loadavg =~ s/\s.*//g; - $loadavg = 100*$loadavg/$perlvar{'lonLoadLim'}; - close($loadfile); - } else { - $loadavg=&reply('load',$checkserver); - } - my $overload=$loadavg-100; - if ($overload>0) { - $r->err_headers_out->{'Retry-After'}=$overload; - $r->log_error('Overload of '.$overload.' on '.$checkserver); - return 413; - } - return ''; -} - # ------------------------------ Find server with least workload from spare.tab sub spareserver { @@ -790,8 +751,8 @@ sub spareserver { } foreach my $try_server (@{ $spareid{'primary'} }) { if ($uint_dom) { - next unless (&spare_can_host($udom,$uint_dom,$remotesessions, - $try_server)); + next unless (&spare_can_host($udom,$uint_dom,$remotesessions, + $try_server)); } ($spare_server, $lowest_load) = &compare_server_load($try_server, $spare_server, $lowest_load); @@ -832,7 +793,7 @@ sub compare_server_load { my $userloadans = &reply('userload',$try_server); if ($loadans !~ /\d/ && $userloadans !~ /\d/) { - return ($spare_server, $lowest_load); #didn't get a number from the server + return; #didn't get a number from the server } my $load; @@ -878,40 +839,22 @@ sub has_user_session { # --------- determine least loaded server in a user's domain which allows login sub choose_server { - my ($udom,$checkloginvia) = @_; + my ($udom) = @_; my %domconfhash = &Apache::loncommon::get_domainconf($udom); my %servers = &get_servers($udom); my $lowest_load = 30000; - my ($login_host,$hostname,$portal_path,$isredirect); + my ($login_host,$hostname); foreach my $lonhost (keys(%servers)) { - my $loginvia; - if ($checkloginvia) { - $loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost}; - if ($loginvia) { - my ($server,$path) = split(/:/,$loginvia); - ($login_host, $lowest_load) = - &compare_server_load($lonhost, $login_host, $lowest_load); - if ($login_host eq $server) { - $portal_path = $path; - $isredirect = 1; - } - } else { - ($login_host, $lowest_load) = - &compare_server_load($lonhost, $login_host, $lowest_load); - if ($login_host eq $lonhost) { - $portal_path = ''; - $isredirect = ''; - } - } - } else { + my $loginvia = $domconfhash{$udom.'.login.loginvia_'.$lonhost}; + if ($loginvia eq '') { ($login_host, $lowest_load) = - &compare_server_load($lonhost, $login_host, $lowest_load); + &compare_server_load($lonhost, $login_host, $lowest_load); } } if ($login_host ne '') { - $hostname = &hostname($login_host); + $hostname = $servers{$login_host}; } - return ($login_host,$hostname,$portal_path,$isredirect); + return ($login_host,$hostname); } # --------------------------------------------- Try to change a user's password @@ -1052,19 +995,15 @@ sub can_host_session { } if ($canhost) { if (ref($hostedsessions) eq 'HASH') { - my $uprimary_id = &Apache::lonnet::domain($udom,'primary'); - my $uint_dom = &Apache::lonnet::internet_dom($uprimary_id); if (ref($hostedsessions->{'excludedomain'}) eq 'ARRAY') { - if (($uint_dom ne '') && - (grep(/^\Q$uint_dom\E$/,@{$hostedsessions->{'excludedomain'}}))) { + if (grep(/^\Q$udom\E$/,@{$hostedsessions->{'excludedomain'}})) { $canhost = 0; } else { $canhost = 1; } } if (ref($hostedsessions->{'includedomain'}) eq 'ARRAY') { - if (($uint_dom ne '') && - (grep(/^\Q$uint_dom\E$/,@{$hostedsessions->{'includedomain'}}))) { + if (grep(/^\Q$udom\E$/,@{$hostedsessions->{'includedomain'}})) { $canhost = 1; } else { $canhost = 0; @@ -1578,7 +1517,6 @@ sub get_domain_defaults { $domdefaults{'auth_arg_def'} = $domconfig{'defaults'}{'auth_arg_def'}; $domdefaults{'timezone_def'} = $domconfig{'defaults'}{'timezone_def'}; $domdefaults{'datelocale_def'} = $domconfig{'defaults'}{'datelocale_def'}; - $domdefaults{'portal_def'} = $domconfig{'defaults'}{'portal_def'}; } else { $domdefaults{'lang_def'} = &domain($domain,'lang_def'); $domdefaults{'auth_def'} = &domain($domain,'auth_def'); @@ -2313,7 +2251,7 @@ sub process_coursefile { } if (ref($mimetype)) { $$mimetype = $type; - } + } } $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file, $home); @@ -2431,11 +2369,11 @@ sub resizeImage { # input: $formname - the contents of the file are in $env{"form.$formname"} # the desired filename is in $env{"form.$formname.filename"} # $context - possible values: coursedoc, existingfile, overwrite, -# canceloverwrite, or ''. +# canceloverwrite, or ''. # if 'coursedoc': upload to the current course -# if 'existingfile': write file to tmp/overwrites directory +# if 'existingfile': write file to tmp/overwrites directory # if 'canceloverwrite': delete file written to tmp/overwrites directory -# $context is passed as argument to &finishuserfileupload +# $context is passed as argument to &finishuserfileupload # $subdir - directory in userfile to store the file into # $parser - instruction to parse file for objects ($parser = parse) # $allfiles - reference to hash for embedded objects @@ -2591,7 +2529,7 @@ sub finishuserfileupload { my $target = $filepath.'/'.$file; if (-e $source) { my @info = stat($source); - if ($info[9] eq $env{'form.timestamp'}) { + if ($info[9] eq $env{'form.timestamp'}) { unless (&File::Copy::move($source,$target)) { &logthis('Failed to overwrite '.$filepath.'/'.$file); return "Moving from $source failed"; @@ -2602,7 +2540,7 @@ sub finishuserfileupload { } else { return "Temporary file: $source missing"; } - } elsif (!print FH ($env{'form.'.$formname})) { + } elsif (!print FH ($env{'form.'.$formname})) { &logthis('Failed to write to '.$filepath.'/'.$file); print STDERR ('Failed to write to '.$filepath.'/'.$file."\n"); return '/adm/notfound.html'; @@ -3163,7 +3101,7 @@ sub get_my_roles { unless (defined($uname)) { $uname=$env{'user.name'}; } unless (defined($udom)) { $udom=$env{'user.domain'}; } my (%dumphash,%nothide); - if ($context eq 'userroles') { + if ($context eq 'userroles') { my $extra = &freeze_escape({'skipcheck' => 1}); %dumphash = &dump('roles',$udom,$uname,'.',undef,$extra); } else { @@ -3225,6 +3163,10 @@ sub get_my_roles { if (!grep(/^cr$/,@{$roles})) { next; } + } elsif ($role =~ /^gr\//) { + if (!grep(/^gr$/,@{$roles})) { + next; + } } else { next; } @@ -3493,7 +3435,7 @@ sub get_domain_roles { return %personnel; } -# ----------------------------------------------------------- Check out an item +# ----------------------------------------------------------- Interval timing sub get_first_access { my ($type,$argsymb)=@_; @@ -3529,91 +3471,6 @@ sub set_first_access { return 'already_set'; } -sub checkout { - my ($symb,$tuname,$tudom,$tcrsid)=@_; - my $now=time; - my $lonhost=$perlvar{'lonHostID'}; - my $infostr=&escape( - 'CHECKOUTTOKEN&'. - $tuname.'&'. - $tudom.'&'. - $tcrsid.'&'. - $symb.'&'. - $now.'&'.$ENV{'REMOTE_ADDR'}); - my $token=&reply('tmpput:'.$infostr,$lonhost); - if ($token=~/^error\:/) { - &logthis("WARNING: ". - "Checkout tmpput failed ".$tudom.' - '.$tuname.' - '.$symb. - ""); - return ''; - } - - $token=~s/^(\d+)\_.*\_(\d+)$/$1\*$2\*$lonhost/; - $token=~tr/a-z/A-Z/; - - my %infohash=('resource.0.outtoken' => $token, - 'resource.0.checkouttime' => $now, - 'resource.0.outremote' => $ENV{'REMOTE_ADDR'}); - - unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') { - return ''; - } else { - &logthis("WARNING: ". - "Checkout cstore failed ".$tudom.' - '.$tuname.' - '.$symb. - ""); - } - - if (&log($tudom,$tuname,&homeserver($tuname,$tudom), - &escape('Checkout '.$infostr.' - '. - $token)) ne 'ok') { - return ''; - } else { - &logthis("WARNING: ". - "Checkout log failed ".$tudom.' - '.$tuname.' - '.$symb. - ""); - } - return $token; -} - -# ------------------------------------------------------------ Check in an item - -sub checkin { - my $token=shift; - my $now=time; - my ($ta,$tb,$lonhost)=split(/\*/,$token); - $lonhost=~tr/A-Z/a-z/; - my $dtoken=$ta.'_'.&hostname($lonhost).'_'.$tb; - $dtoken=~s/\W/\_/g; - my ($dummy,$tuname,$tudom,$tcrsid,$symb,$chtim,$rmaddr)= - split(/\&/,&unescape(&reply('tmpget:'.$dtoken,$lonhost))); - - unless (($tuname) && ($tudom)) { - &logthis('Check in '.$token.' ('.$dtoken.') failed'); - return ''; - } - - unless (&allowed('mgr',$tcrsid)) { - &logthis('Check in '.$token.' ('.$dtoken.') unauthorized: '. - $env{'user.name'}.' - '.$env{'user.domain'}); - return ''; - } - - my %infohash=('resource.0.intoken' => $token, - 'resource.0.checkintime' => $now, - 'resource.0.inremote' => $ENV{'REMOTE_ADDR'}); - - unless (&cstore(\%infohash,$symb,$tcrsid,$tudom,$tuname) eq 'ok') { - return ''; - } - - if (&log($tudom,$tuname,&homeserver($tuname,$tudom), - &escape('Checkin - '.$token)) ne 'ok') { - return ''; - } - - return ($symb,$tuname,$tudom,$tcrsid); -} - # --------------------------------------------- Set Expire Date for Spreadsheet sub expirespread { @@ -3718,7 +3575,7 @@ sub hashref2str { $result.='='; #print("Got a ref of ".(ref($key))." skipping."); } else { - if (defined($key)) {$result.=&escape($key).'=';} else { last; } + if ($key) {$result.=&escape($key).'=';} else { last; } } if(ref($hashref->{$key}) eq 'ARRAY') { @@ -4237,7 +4094,6 @@ sub rolesinit { } my %allroles=(); my %allgroups=(); - my $group_privs; if ($rolesdump ne '') { foreach my $entry (split(/&/,$rolesdump)) { @@ -4254,6 +4110,7 @@ sub rolesinit { } } elsif ($role =~ m|^gr/|) { ($trole,$tend,$tstart) = split(/_/,$role); + next if ($tstart eq '-1'); ($trole,$group_privs) = split(/\//,$trole); $group_privs = &unescape($group_privs); } else { @@ -4358,7 +4215,7 @@ sub set_userprivs { my $adv=0; my %grouproles = (); if (keys(%{$allgroups}) > 0) { - my @groupkeys; + my @groupkeys; foreach my $role (keys(%{$allroles})) { push(@groupkeys,$role); } @@ -4406,7 +4263,7 @@ sub set_userprivs { } } my $thesestr=''; - foreach my $priv (keys(%thesepriv)) { + foreach my $priv (sort(keys(%thesepriv))) { $thesestr.=':'.$priv.'&'.$thesepriv{$priv}; } $userroles->{'user.priv.'.$role} = $thesestr; @@ -4415,7 +4272,7 @@ sub set_userprivs { } sub role_status { - my ($rolekey,$then,$refresh,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_; + my ($rolekey,$update,$refresh,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_; my @pwhere = (); if (exists($env{$rolekey}) && $env{$rolekey} ne '') { (undef,undef,$$role,@pwhere)=split(/\./,$rolekey); @@ -4424,7 +4281,7 @@ sub role_status { $$trolecode=$$role.'.'.$$where; ($$tstart,$$tend)=split(/\./,$env{$rolekey}); $$tstatus='is'; - if ($$tstart && $$tstart>$then) { + if ($$tstart && $$tstart>$update) { $$tstatus='future'; if ($$tstart<$now) { if ($$tstart && $$tstart>$refresh) { @@ -4434,7 +4291,7 @@ sub role_status { my %userroles = ( 'user.role.'.$$role.'.'.$$where => $$tstart.'.'.$$tend ); - @rolecodes = ('cm'); + @rolecodes = ('cm'); my $spec=$$role.'.'.$$where; my ($tdummy,$tdomain,$trest)=split(/\//,$$where); if ($$role =~ /^cr\//) { @@ -4449,32 +4306,9 @@ sub role_status { $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; - } - } - } - } + &get_groups_roles($tdomain,$trest, + \%course_roles,\@rolecodes, + \%groups_roles); } else { push(@rolecodes,$$role); &standard_roleprivs(\%allroles,$$role,$tdomain,$spec,$trest,$$where); @@ -4488,7 +4322,7 @@ sub role_status { } } if ($$tend) { - if ($$tend<$then) { + if ($$tend<$update) { $$tstatus='expired'; } elsif ($$tend<$now) { $$tstatus='will_not'; @@ -4498,12 +4332,70 @@ sub role_status { } } +sub get_groups_roles { + my ($cdom,$rest,$cdom_courseroles,$rolecodes,$groups_roles) = @_; + return unless((ref($cdom_courseroles) eq 'HASH') && + (ref($rolecodes) eq 'ARRAY') && + (ref($groups_roles) eq 'HASH')); + if (keys(%{$cdom_courseroles}) > 0) { + my ($cnum) = ($rest =~ /^($match_courseid)/); + if ($cdom ne '' && $cnum ne '') { + foreach my $key (keys(%{$cdom_courseroles})) { + if ($key =~ /^\Q$cnum\E:\Q$cdom\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./$cdom/$cnum"; + if ($crssec ne '') { + $rolekey .= "/$crssec"; + } + $rolekey .= './'; + $groups_roles->{$rolekey} = $rolecodes; + } + } + } + } + return; +} + +sub delete_env_groupprivs { + my ($where,$courseroles,$possroles) = @_; + return unless((ref($courseroles) eq 'HASH') && (ref($possroles) eq 'ARRAY')); + my ($dummy,$udom,$uname,$group) = split(/\//,$where); + unless (ref($courseroles->{$udom}) eq 'HASH') { + %{$courseroles->{$udom}} = + &get_my_roles('','','userroles',['active'], + $possroles,[$udom],1); + } + if (ref($courseroles->{$udom}) eq 'HASH') { + foreach my $item (keys(%{$courseroles->{$udom}})) { + my ($cnum,$cdom,$crsrole,$crssec) = split(/:/,$item); + my $area = '/'.$cdom.'/'.$cnum; + my $privkey = "user.priv.$crsrole.$area"; + if ($crssec ne '') { + $privkey .= '/'.$crssec; + } + $privkey .= ".$area/$group"; + &Apache::lonnet::delenv($privkey,undef,[$crsrole]); + } + } + return; +} + sub check_adhoc_privs { - my ($cdom,$cnum,$then,$refresh,$now,$checkrole,$caller) = @_; + my ($cdom,$cnum,$update,$refresh,$now,$checkrole,$caller) = @_; my $cckey = 'user.role.'.$checkrole.'./'.$cdom.'/'.$cnum; if ($env{$cckey}) { my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend); - &role_status($cckey,$then,$refresh,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend); + &role_status($cckey,$update,$refresh,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend); unless (($tstatus eq 'is') || ($tstatus eq 'will_not')) { &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller); } @@ -4594,15 +4486,18 @@ sub dump { my $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range:$extra",$uhome); my @pairs=split(/\&/,$rep); my %returnhash=(); - foreach my $item (@pairs) { - my ($key,$value)=split(/=/,$item,2); - $key = &unescape($key); - next if ($key =~ /^error: 2 /); - $returnhash{$key}=&thaw_unescape($value); + if (!($rep =~ /^error/ )) { + foreach my $item (@pairs) { + my ($key,$value)=split(/=/,$item,2); + $key = &unescape($key); + next if ($key =~ /^error: 2 /); + $returnhash{$key}=&thaw_unescape($value); + } } return %returnhash; } + # --------------------------------------------------------- dumpstore interface sub dumpstore { @@ -5136,7 +5031,7 @@ sub is_portfolio_file { } sub usertools_access { - my ($uname,$udom,$tool,$action,$context,$userenvref,$domdefref,$is_advref) = @_; + my ($uname,$udom,$tool,$action,$context,$userenvref,$domdefref,$is_advref)=@_; my ($access,%tools); if ($context eq '') { $context = 'tools'; @@ -5283,7 +5178,7 @@ sub is_advanced_user { my ($udom,$uname) = @_; if ($udom ne '' && $uname ne '') { if (($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) { - return $env{'user.adv'}; + return $env{'user.adv'}; } } my %roleshash = &get_my_roles($uname,$udom,'userroles',undef,undef,undef,1); @@ -5801,7 +5696,7 @@ sub allowed { my $unamedom=$env{'user.name'}.':'.$env{'user.domain'}; if ($env{'course.'.$env{'request.course.id'}.'.'.$priv.'.roles.denied'} =~/\Q$rolecode\E/) { - if (($priv ne 'pch') && ($priv ne 'plc')) { + if (($priv ne 'pch') && ($priv ne 'plc')) { &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}.':'. 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '. $env{'request.course.id'}); @@ -5811,7 +5706,7 @@ sub allowed { if ($env{'course.'.$env{'request.course.id'}.'.'.$priv.'.users.denied'} =~/\Q$unamedom\E/) { - if (($priv ne 'pch') && ($priv ne 'plc')) { + if (($priv ne 'pch') && ($priv ne 'plc')) { &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}. 'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '. $env{'request.course.id'}); @@ -5825,7 +5720,7 @@ sub allowed { if ($thisallowed=~/R/) { my $rolecode=(split(/\./,$env{'request.role'}))[0]; if (&metadata($uri,'roledeny')=~/\Q$rolecode\E/) { - if (($priv ne 'pch') && ($priv ne 'plc')) { + if (($priv ne 'pch') && ($priv ne 'plc')) { &logthis($env{'user.domain'}.':'.$env{'user.name'}.':'.$env{'user.home'}.':'. 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode); } @@ -6752,13 +6647,6 @@ sub assignrole { return 'refused'; } } - } elsif ($role eq 'au') { - if ($url ne '/'.$udom.'/') { - &logthis('Attempt by '.$env{'user.name'}.':'.$env{'user.domain'}. - ' to assign author role for '.$uname.':'.$udom. - ' in domain: '.$url.' refused (wrong domain).'); - return 'refused'; - } } $mrole=$role; } @@ -6933,7 +6821,7 @@ sub modifyuser { } &logthis('Call to modify user '.$udom.', '.$uname.', '.$uid.', '. $umode.', '.$first.', '.$middle.', '. - $last.', '.$gene.'(forceid: '.$forceid.'; candelete: '.$showcandelete.')'. + $last.', '.$gene.'(forceid: '.$forceid.'; candelete: '.$showcandelete.')'. (defined($desiredhome) ? ' desiredhome = '.$desiredhome : ' desiredhome not specified'). ' by '.$env{'user.name'}.' at '.$env{'user.domain'}. @@ -7079,7 +6967,7 @@ sub modifyuser { return 'ok'; } my $reply = &put('environment', \%names, $udom,$uname); - if ($reply ne 'ok') { + if ($reply ne 'ok') { return 'error: '.$reply; } if ($names{'permanentemail'} ne $oldnames{'permanentemail'}) { @@ -7404,8 +7292,8 @@ sub store_userdata { $namevalue.=&escape($key).'='.&freeze_escape($$storehash{$key}).'&'; } $namevalue=~s/\&$//; - $result = &reply("store:$udom:$uname:$namespace:$datakey:". - $namevalue,$uhome); + $result = &reply("store:$env{'user.domain'}:$env{'user.name'}:". + "$namespace:$datakey:$namevalue",$uhome); } } else { $result = 'error: data to store was not a hash reference'; @@ -7461,7 +7349,7 @@ sub is_locked { my ($file_name, $domain, $user, $which) = @_; my @check; my $is_locked; - push(@check,$file_name); + push (@check,$file_name); my %locked = &get('file_permissions',\@check, $env{'user.domain'},$env{'user.name'}); my ($tmp)=keys(%locked); @@ -8625,6 +8513,7 @@ sub add_prefix_and_part { # ---------------------------------------------------------------- Get metadata my %metaentry; +my %importedpartids; sub metadata { my ($uri,$what,$liburi,$prefix,$depthcount)=@_; $uri=&declutter($uri); @@ -8632,7 +8521,7 @@ sub metadata { if (($uri eq '') || (($uri =~ m|^/*adm/|) && ($uri !~ m|^adm/includes|) && ($uri !~ m|/bulletinboard$|)) || - ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ m{^/*uploaded/.+\.sequence$})) { + ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ m{^/*uploaded/.+\.sequence$}) || ($uri =~ m{^/*uploaded/$match_domain/$match_courseid/docs/})) { return undef; } if (($uri =~ /^~/ || $uri =~ m{home/$match_username/public_html/}) @@ -8651,6 +8540,10 @@ sub metadata { if (defined($cached)) { return $result->{':'.$what}; } } { +# Imported parts would go here + my %importedids=(); + my @origfileimportpartids=(); + my $importedparts=0; # # Is this a recursive call for a library? # @@ -8674,8 +8567,7 @@ sub metadata { &Apache::lonnet::ssi_body($which, ('grade_target' => 'meta')); $cachetime = 1; # only want this cached in the child not long term - } elsif (($uri !~ m -^(editupload)/-) && - ($uri !~ m{^/*uploaded/$match_domain/$match_courseid/docs/})) { + } elsif ($uri !~ m -^(editupload)/-) { my $file=&filelocation('',&clutter($filename)); #push(@{$metaentry{$uri.'.file'}},$file); $metastring=&getfile($file); @@ -8735,27 +8627,55 @@ sub metadata { # This is not a package - some other kind of start tag # my $entry=$token->[1]; - my $unikey; - if ($entry eq 'import') { - $unikey=''; - } else { - $unikey=$entry; - } - $unikey.=&add_prefix_and_part($prefix,$token->[2]->{'part'}); - - if (defined($token->[2]->{'id'})) { - $unikey.='_'.$token->[2]->{'id'}; - } + my $unikey=''; if ($entry eq 'import') { # # Importing a library here # + my $location=$parser->get_text('/import'); + my $dir=$filename; + $dir=~s|[^/]*$||; + $location=&filelocation($dir,$location); + + my $importmode=$token->[2]->{'importmode'}; + if ($importmode eq 'problem') { +# Import as problem/response + $unikey=&add_prefix_and_part($prefix,$token->[2]->{'part'}); + } elsif ($importmode eq 'part') { +# Import as part(s) + $importedparts=1; +# We need to get the original file and the imported file to get the part order correct +# Good news: we do not need to worry about nested libraries, since parts cannot be nested +# Load and inspect original file + if ($#origfileimportpartids<0) { + undef(%importedpartids); + my $origfilelocation=$perlvar{'lonDocRoot'}.&clutter($uri); + my $origfile=&getfile($origfilelocation); + @origfileimportpartids=($origfile=~/<(part|import)[^>]*id\s*=\s*[\"\']([^\"\']+)[\"\'][^>]*>/gs); + } + +# Load and inspect imported file + my $impfile=&getfile($location); + my @impfilepartids=($impfile=~/]*id\s*=\s*[\"\']([^\"\']+)[\"\'][^>]*>/gs); + if ($#impfilepartids>=0) { +# This problem had parts + $importedpartids{$token->[2]->{'id'}}=join(',',@impfilepartids); + } else { +# Importing by turning a single problem into a problem part +# It gets the import-tags ID as part-ID + $unikey=&add_prefix_and_part($prefix,$token->[2]->{'id'}); + $importedpartids{$token->[2]->{'id'}}=$token->[2]->{'id'}; + } + } else { +# Normal import + $unikey=&add_prefix_and_part($prefix,$token->[2]->{'part'}); + if (defined($token->[2]->{'id'})) { + $unikey.='_'.$token->[2]->{'id'}; + } + } + if ($depthcount<20) { - my $location=$parser->get_text('/import'); - my $dir=$filename; - $dir=~s|[^/]*$||; - $location=&filelocation($dir,$location); my $metadata = &metadata($uri,'keys', $location,$unikey, $depthcount+1); @@ -8763,8 +8683,16 @@ sub metadata { $metaentry{':'.$meta}=$metaentry{':'.$meta}; $metathesekeys{$meta}=1; } - } - } else { + + } + } else { +# +# Not importing, some other kind of non-package, non-library start tag +# + $unikey=$entry.&add_prefix_and_part($prefix,$token->[2]->{'part'}); + if (defined($token->[2]->{'id'})) { + $unikey.='_'.$token->[2]->{'id'}; + } if (defined($token->[2]->{'name'})) { $unikey.='_'.$token->[2]->{'name'}; } @@ -8838,6 +8766,22 @@ sub metadata { grep { ! $seen{$_} ++ } (split(',',$metaentry{':packages'})); $metaentry{':packages'} = join(',',@uniq_packages); + if ($importedparts) { +# We had imported parts and need to rebuild partorder + $metaentry{':partorder'}=''; + $metathesekeys{'partorder'}=1; + for (my $index=0;$index<$#origfileimportpartids;$index+=2) { + if ($origfileimportpartids[$index] eq 'part') { +# original part, part of the problem + $metaentry{':partorder'}.=','.$origfileimportpartids[$index+1]; + } else { +# we have imported parts at this position + $metaentry{':partorder'}.=','.$importedpartids{$origfileimportpartids[$index+1]}; + } + } + $metaentry{':partorder'}=~s/^\,//; + } + $metaentry{':keys'} = join(',',keys(%metathesekeys)); &metadata_generate_part0(\%metathesekeys,\%metaentry,$uri); $metaentry{':allpossiblekeys'}=join(',',keys %metathesekeys); @@ -9022,9 +8966,9 @@ sub symbverify { $thisurl =~ s/\?.+$//; } my $ids=$bighash{'ids_'.&clutter($thisurl)}; - unless ($ids) { - my $idkey = 'ids_'.($thisurl =~ m{^/}? '' : '/').$thisurl; - $ids=$bighash{$idkey}; + unless ($ids) { + my $idkey = 'ids_'.($thisurl =~ m{^/}? '' : '/').$thisurl; + $ids=$bighash{$idkey}; } if ($ids) { # ------------------------------------------------------------------- Has ID(s) @@ -9038,7 +8982,7 @@ sub symbverify { eq $symb) { if (($env{'request.role.adv'}) || ($bighash{'encrypted_'.$id} eq $env{'request.enc'}) || - ($thisurl eq '/adm/navmaps')) { + ($thisurl eq '/adm/navmaps')) { $okay=1; } } @@ -10033,7 +9977,6 @@ sub get_dns { while (%alldns) { my ($dns) = keys(%alldns); my $ua=new LWP::UserAgent; - $ua->timeout(30); my $request=new HTTP::Request('GET',"$alldns{$dns}://$dns$url"); my $response=$ua->request($request); delete($alldns{$dns}); @@ -10118,19 +10061,13 @@ sub get_dns { my $loaded; my %name_to_host; my %internetdom; - my %LC_dns_serv; sub parse_hosts_tab { my ($file) = @_; foreach my $configline (@$file) { next if ($configline =~ /^(\#|\s*$ )/x); - chomp($configline); - if ($configline =~ /^\^/) { - if ($configline =~ /^\^([\w.\-]+)/) { - $LC_dns_serv{$1} = 1; - } - next; - } + next if ($configline =~ /^\^/); + chomp($configline); my ($id,$domain,$role,$name,$protocol,$intdom)=split(/:/,$configline); $name=~s/\s//g; if ($id && $domain && $role && $name) { @@ -10212,7 +10149,7 @@ sub get_dns { } sub unique_library { - #2x reverse removes all hostnames that appear more than once + #2x reverse removes all hostnames that appear more than once my %unique = reverse &all_library(); return reverse %unique; } @@ -10242,7 +10179,7 @@ sub get_dns { sub get_unique_servers { my %unique = reverse &get_servers(@_); - return reverse %unique; + return reverse %unique; } sub host_domain { @@ -10266,14 +10203,6 @@ sub get_dns { my ($lonid) = @_; return $internetdom{$lonid}; } - - sub is_LC_dns { - &load_hosts_tab() if (!$loaded); - - my ($hostname) = @_; - return exists($LC_dns_serv{$hostname}); - } - } { @@ -10549,22 +10478,6 @@ BEGIN { } } -# ---------------------------------------------------------- Read managers table -{ - if (-e "$perlvar{'lonTabDir'}/managers.tab") { - if (open(my $config,"<$perlvar{'lonTabDir'}/managers.tab")) { - while (my $configline=<$config>) { - chomp($configline); - next if ($configline =~ /^\#/); - if (($configline =~ /^[\w\-]+$/) || ($configline =~ /^[\w\-]+\:[\w\-]+$/)) { - $managerstab{$configline} = 1; - } - } - close($config); - } - } -} - # ------------- set up temporary directory { $tmpdir = $perlvar{'lonDaemons'}.'/tmp/'; @@ -10802,7 +10715,7 @@ $checkdefauth is optional (value is 1 if authenticate user using default authentication method, and allow account creation if username does not have account in the domain). $clientcancheckhost is optional (value is 1 if checking whether the - server can host will occur on the client side in lonauth.pm). + server can host will occur on the client side in lonauth.pm). =item * X @@ -11458,11 +11371,11 @@ splitting on '&', supports elements that =head2 Logging Routines +=over 4 + These routines allow one to make log messages in the lonnet.log and lonnet.perm logfiles. -=over 4 - =item * logtouch() : make sure the logfile, lonnet.log, exists @@ -11552,7 +11465,7 @@ userfileupload(): main rotine for puttin the filename is in $env{'form.'.$formname.'.filename'} and the contents of the file is located in $env{'form.'.$formname} context - if coursedoc, store the file in the course of the active role - of the current user; + of the current user; if 'existingfile': store in 'overwrites' in /home/httpd/perl/tmp if 'canceloverwrite': delete file in tmp/overwrites directory subdir - required - subdirectory to put the file in under ../userfiles/ @@ -11598,7 +11511,7 @@ userspace, probably shouldn't be called returns either the url of the uploaded file (/uploaded/....) if successful and /adm/notfound.html if unsuccessful (or an error message if context was 'overwrite'). - + =item *