--- loncom/lonnet/perl/lonnet.pm 2001/12/07 20:17:44 1.188 +++ loncom/lonnet/perl/lonnet.pm 2001/12/18 20:59:38 1.191 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.188 2001/12/07 20:17:44 www Exp $ +# $Id: lonnet.pm,v 1.191 2001/12/18 20:59:38 harris41 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -62,109 +62,11 @@ # 11/17,11/20,11/22,11/29 Gerd Kortemeyer # 12/5 Matthew Hall # 12/5 Guy Albertelli -# 12/6,12/7 Gerd Kortemeyer -# -# $Id: lonnet.pm,v 1.188 2001/12/07 20:17:44 www Exp $ +# 12/6,12/7,12/12 Gerd Kortemeyer +# 12/18 Scott Harrison # ### -# Functions for use by content handlers: -# -# metadata_query(sql-query-string,custom-metadata-regex) : -# returns file handle of where sql and -# regex results will be stored for query -# plaintext(short) : plain text explanation of short term -# fileembstyle(ext) : embed style in page for file extension -# filedescription(ext) : descriptor text for file extension -# allowed(short,url) : returns codes for allowed actions -# F: full access -# U,I,K: authentication modes (cxx only) -# '': forbidden -# 1: user needs to choose course -# 2: browse allowed -# definerole(rolename,sys,dom,cou) : define a custom role rolename -# set privileges in format of lonTabs/roles.tab for -# system, domain and course level, -# assignrole(udom,uname,url,role,end,start) : give a role to a user for the -# level given by url. Optional start and end dates -# (leave empty string or zero for "no date") -# assigncustomrole (udom,uname,url,rdom,rnam,rolename,end,start) : give a -# custom role to a user for the level given by url. -# Specify name and domain of role author, and role name -# revokerole (udom,uname,url,role) : Revoke a role for url -# revokecustomrole (udom,uname,url,rdom,rnam,rolename) : Revoke a custom role -# appenv(hash) : adds hash to session environment -# delenv(varname) : deletes all environment entries starting with varname -# store(hashref,symb,courseid,udom,uname) -# : stores hash permanently for this url -# hashref needs to be given, and should be a \%hashname -# the remaining args aren't required and if they aren't -# passed or are '' they will be derived from the ENV -# cstore(hashref,symb,courseid,udom,uname) -# : same as store but uses the critical interface to -# guarentee a store -# restore(symb,courseid,udom,uname) -# : returns hash for this symb, all args are optional -# if they aren't given they will be derived from the -# current enviroment -# -# -# for the next 6 functions udom and uname are optional -# if supplied they use udom as the domain and uname -# as the username for the function (supply a courseid -# for the uname if you want a course database) -# if not supplied it uses %ENV and looks at -# user. attribute for the values -# -# eget(namesp,arrayref,udom,uname) -# : returns hash with keys from array reference filled -# in from namesp (encrypts the return communication) -# get(namesp,arrayref,udom,uname) -# : returns hash with keys from array reference filled -# in from namesp -# dump(namesp,udom,uname) : dumps the complete namespace into a hash -# del(namesp,array,udom,uname) : deletes keys out of array from namesp -# put(namesp,hash,udom,uname) : stores hash in namesp -# cput(namesp,hash,udom,uname) : critical put -# -# -# ssi(url,hash) : does a complete request cycle on url to localhost, posts -# hash -# coursedescription(id) : returns and caches course description for id -# repcopy(filename) : replicate file -# dirlist(url) : gets a directory listing -# directcondval(index) : reading condition value of single condition from -# state string -# condval(index) : value of condition index based on state -# EXT(name) : value of a variable -# symblist(map,hash) : Updates symbolic storage links -# symbread([filename]) : returns the data handle (filename optional) -# rndseed([symb,courseid,domain,uname]) -# : returns a random seed, all arguments are optional, -# if they aren't sent it use the environment to derive -# them -# Note: if symb isn't sent and it can't get one from -# &symbread it will use the current time as it's return -# receipt() : returns a receipt to be given out to users -# getfile(filename) : returns the contents of filename, or a -1 if it can't -# be found, replicates and subscribes to the file -# filelocation(dir,file) : returns a fairly clean absolute reference to file -# from the directory dir -# hreflocation(dir,file) : same as filelocation, but for hrefs -# log(domain,user,home,msg) : write to permanent log for user -# usection(domain,user,courseid) : output of section name/number or '' for -# "not in course" and '-1' for "no section" -# userenvironment(domain,user,what) : puts out any environment parameter -# for a user -# idput(domain,hash) : writes IDs for users from hash (name=>id,name=>id) -# idget(domain,array): returns hash with usernames (id=>name,id=>name) for -# an array of IDs -# idrget(domain,array): returns hash with IDs for usernames (name=>id,...) for -# an array of names -# metadata(file,entry): returns the metadata entry for a file. entry='keys' -# returns a comma separated list of keys -# - package Apache::lonnet; use strict; @@ -327,7 +229,7 @@ sub critical { sub appenv { my %newenv=@_; - map { + foreach (keys %newenv) { if (($newenv{$_}=~/^user\.role/) || ($newenv{$_}=~/^user\.priv/)) { &logthis("WARNING: ". "Attempt to modify environment ".$_." to ".$newenv{$_} @@ -336,7 +238,7 @@ sub appenv { } else { $ENV{$_}=$newenv{$_}; } - } keys %newenv; + } my $lockfh; unless ($lockfh=Apache::File->new("$ENV{'user.environment'}")) { @@ -418,9 +320,9 @@ sub delenv { $fh->close(); return 'error: '.$!; } - map { + foreach (@oldenv) { unless ($_=~/^$delthis/) { print $fh $_; } - } @oldenv; + } $fh->close(); } return 'ok'; @@ -573,9 +475,9 @@ sub idget { sub idrget { my ($udom,@unames)=@_; my %returnhash=(); - map { + foreach (@unames) { $returnhash{$_}=(&userenvironment($udom,$_,'id'))[1]; - } @unames; + } return %returnhash; } @@ -584,7 +486,7 @@ sub idrget { sub idput { my ($udom,%ids)=@_; my %servers=(); - map { + foreach (keys %ids) { my $uhom=&homeserver($_,$udom); if ($uhom ne 'no_host') { my $id=&escape($ids{$_}); @@ -597,10 +499,10 @@ sub idput { } &critical('put:'.$udom.':'.$unam.':environment:id='.$id,$uhom); } - } keys %ids; - map { + } + foreach (keys %servers) { &critical('idput:'.$udom.':'.$servers{$_},$_); - } keys %servers; + } } # ------------------------------------- Find the section of student in a course @@ -609,7 +511,8 @@ sub usection { my ($udom,$unam,$courseid)=@_; $courseid=~s/\_/\//g; $courseid=~s/^(\w)/\/$1/; - map { + foreach (split(/\&/,&reply('dump:'.$udom.':'.$unam.':roles', + &homeserver($unam,$udom)))) { my ($key,$value)=split(/\=/,$_); $key=&unescape($key); if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) { @@ -626,8 +529,7 @@ sub usection { } unless ($notactive) { return $section; } } - } split(/\&/,&reply('dump:'.$udom.':'.$unam.':roles', - &homeserver($unam,$udom))); + } return '-1'; } @@ -756,7 +658,7 @@ sub log { sub flushcourselogs { &logthis('Flushing course log buffers'); - map { + foreach (keys %courselogs) { my $crsid=$_; if (&reply('log:'.$coursedombuf{$crsid}.':'. &escape($courselogs{$crsid}), @@ -770,16 +672,16 @@ sub flushcourselogs { delete $courselogs{$crsid}; } } - } keys %courselogs; + } &logthis('Flushing access logs'); - map { + foreach (keys %accesshash) { my $entry=$_; $entry=~/\_\_\_(\w+)\/(\w+)\/(.*)\_\_\_(\w+)$/; my %temphash=($entry => $accesshash{$entry}); if (&Apache::lonnet::put('resevaldata',\%temphash,$1,$2) eq 'ok') { delete $accesshash{$entry}; } - } keys %accesshash; + } $dumpcount++; } @@ -808,11 +710,11 @@ sub courseacclog { my $what=$fnsymb.':'.$ENV{'user.name'}.':'.$ENV{'user.domain'}; if ($what=~/(problem|exam|quiz|assess|survey|form)$/) { $what.=':POST'; - map { + foreach (keys %ENV) { if ($_=~/^form\.(.*)/) { $what.=':'.$1.'='.$ENV{$_}; } - } keys %ENV; + } } &courselog($what); } @@ -958,7 +860,7 @@ sub devalidate { sub hash2str { my (%hash)=@_; my $result=''; - map { $result.=escape($_).'='.escape($hash{$_}).'&'; } keys %hash; + foreach (keys %hash) { $result.=escape($_).'='.escape($hash{$_}).'&'; } $result=~s/\&$//; return $result; } @@ -966,10 +868,10 @@ sub hash2str { sub str2hash { my ($string) = @_; my %returnhash; - map { + foreach (split(/\&/,$string)) { my ($name,$value)=split(/\=/,$_); $returnhash{&unescape($name)}=&unescape($value); - } split(/\&/,$string); + } return %returnhash; } @@ -1119,9 +1021,9 @@ sub store { if (!$stuname) { $stuname=$ENV{'user.name'}; } if (!$home) { $home=$ENV{'user.home'}; } my $namevalue=''; - map { + foreach (keys %$storehash) { $namevalue.=escape($_).'='.escape($$storehash{$_}).'&'; - } keys %$storehash; + } $namevalue=~s/\&$//; &courselog($symb.':'.$stuname.':'.$domain.':STORE:'.$namevalue); return reply("store:$domain:$stuname:$namespace:$symb:$namevalue","$home"); @@ -1150,9 +1052,9 @@ sub cstore { if (!$home) { $home=$ENV{'user.home'}; } my $namevalue=''; - map { + foreach (keys %$storehash) { $namevalue.=escape($_).'='.escape($$storehash{$_}).'&'; - } keys %$storehash; + } $namevalue=~s/\&$//; &courselog($symb.':'.$stuname.':'.$domain.':CSTORE:'.$namevalue); return critical @@ -1183,15 +1085,15 @@ sub restore { my $answer=&reply("restore:$domain:$stuname:$namespace:$symb","$home"); my %returnhash=(); - map { + foreach (split(/\&/,$answer)) { my ($name,$value)=split(/\=/,$_); $returnhash{&unescape($name)}=&unescape($value); - } split(/\&/,$answer); + } my $version; for ($version=1;$version<=$returnhash{'version'};$version++) { - map { + foreach (split(/\:/,$returnhash{$version.':keys'})) { $returnhash{$_}=$returnhash{$version.':'.$_}; - } split(/\:/,$returnhash{$version.':keys'}); + } } return %returnhash; } @@ -1242,7 +1144,7 @@ sub rolesinit { my $thesestr; if ($rolesdump ne '') { - map { + foreach (split(/&/,$rolesdump)) { if ($_!~/^rolesdef\&/) { my ($area,$role)=split(/=/,$_); $area=~s/\_\w\w$//; @@ -1298,14 +1200,14 @@ sub rolesinit { } } } - } split(/&/,$rolesdump); + } my $adv=0; my $author=0; - map { + foreach (keys %allroles) { %thesepriv=(); if (($_!~/^st/) && ($_!~/^ta/) && ($_!~/^cm/)) { $adv=1; } if (($_=~/^au/) || ($_=~/^ca/)) { $author=1; } - map { + foreach (split(/:/,$allroles{$_})) { if ($_ ne '') { my ($privilege,$restrictions)=split(/&/,$_); if ($restrictions eq '') { @@ -1316,11 +1218,11 @@ sub rolesinit { } } } - } split(/:/,$allroles{$_}); + } $thesestr=''; - map { $thesestr.=':'.$_.'&'.$thesepriv{$_}; } keys %thesepriv; + foreach (keys %thesepriv) { $thesestr.=':'.$_.'&'.$thesepriv{$_}; } $userroles.='user.priv.'.$_.'='.$thesestr."\n"; - } keys %allroles; + } $userroles.='user.adv='.$adv."\n". 'user.author='.$author."\n"; $ENV{'user.adv'}=$adv; @@ -1333,9 +1235,9 @@ sub rolesinit { sub get { my ($namespace,$storearr,$udomain,$uname)=@_; my $items=''; - map { + foreach (@$storearr) { $items.=escape($_).'&'; - } @$storearr; + } $items=~s/\&$//; if (!$udomain) { $udomain=$ENV{'user.domain'}; } if (!$uname) { $uname=$ENV{'user.name'}; } @@ -1345,10 +1247,10 @@ sub get { my @pairs=split(/\&/,$rep); my %returnhash=(); my $i=0; - map { + foreach (@$storearr) { $returnhash{$_}=unescape($pairs[$i]); $i++; - } @$storearr; + } return %returnhash; } @@ -1357,9 +1259,9 @@ sub get { sub del { my ($namespace,$storearr,$udomain,$uname)=@_; my $items=''; - map { + foreach (@$storearr) { $items.=escape($_).'&'; - } @$storearr; + } $items=~s/\&$//; if (!$udomain) { $udomain=$ENV{'user.domain'}; } if (!$uname) { $uname=$ENV{'user.name'}; } @@ -1378,10 +1280,10 @@ sub dump { my $rep=reply("dump:$udomain:$uname:$namespace",$uhome); my @pairs=split(/\&/,$rep); my %returnhash=(); - map { + foreach (@pairs) { my ($key,$value)=split(/=/,$_); $returnhash{unescape($key)}=unescape($value); - } @pairs; + } return %returnhash; } @@ -1393,9 +1295,9 @@ sub put { if (!$uname) { $uname=$ENV{'user.name'}; } my $uhome=&homeserver($uname,$udomain); my $items=''; - map { + foreach (keys %$storehash) { $items.=&escape($_).'='.&escape($$storehash{$_}).'&'; - } keys %$storehash; + } $items=~s/\&$//; return &reply("put:$udomain:$uname:$namespace:$items",$uhome); } @@ -1408,9 +1310,9 @@ sub cput { if (!$uname) { $uname=$ENV{'user.name'}; } my $uhome=&homeserver($uname,$udomain); my $items=''; - map { + foreach (keys %$storehash) { $items.=escape($_).'='.escape($$storehash{$_}).'&'; - } keys %$storehash; + } $items=~s/\&$//; return &critical("put:$udomain:$uname:$namespace:$items",$uhome); } @@ -1420,9 +1322,9 @@ sub cput { sub eget { my ($namespace,$storearr,$udomain,$uname)=@_; my $items=''; - map { + foreach (@$storearr) { $items.=escape($_).'&'; - } @$storearr; + } $items=~s/\&$//; if (!$udomain) { $udomain=$ENV{'user.domain'}; } if (!$uname) { $uname=$ENV{'user.name'}; } @@ -1431,10 +1333,10 @@ sub eget { my @pairs=split(/\&/,$rep); my %returnhash=(); my $i=0; - map { + foreach (@$storearr) { $returnhash{$_}=unescape($pairs[$i]); $i++; - } @$storearr; + } return %returnhash; } @@ -1527,7 +1429,7 @@ sub allowed { my $refuri=$ENV{'httpref.'.$orguri}; unless ($refuri) { - map { + foreach (keys %ENV) { if ($_=~/^httpref\..*\*/) { my $pattern=$_; $pattern=~s/^httpref\.\/res\///; @@ -1537,7 +1439,7 @@ sub allowed { $refuri=$ENV{$_}; } } - } keys %ENV; + } } if ($refuri) { $refuri=&declutter($refuri); @@ -1693,7 +1595,7 @@ sub allowed { sub definerole { if (allowed('mcr','/')) { my ($rolename,$sysrole,$domrole,$courole)=@_; - map { + foreach (split('/',$sysrole)) { my ($crole,$cqual)=split(/\&/,$_); if ($pr{'cr:s'}!~/$crole/) { return "refused:s:$crole"; } if ($pr{'cr:s'}=~/$crole\&/) { @@ -1701,8 +1603,8 @@ sub definerole { return "refused:s:$crole&$cqual"; } } - } split('/',$sysrole); - map { + } + foreach (split('/',$domrole)) { my ($crole,$cqual)=split(/\&/,$_); if ($pr{'cr:d'}!~/$crole/) { return "refused:d:$crole"; } if ($pr{'cr:d'}=~/$crole\&/) { @@ -1710,8 +1612,8 @@ sub definerole { return "refused:d:$crole&$cqual"; } } - } split('/',$domrole); - map { + } + foreach (split('/',$courole)) { my ($crole,$cqual)=split(/\&/,$_); if ($pr{'cr:c'}!~/$crole/) { return "refused:c:$crole"; } if ($pr{'cr:c'}=~/$crole\&/) { @@ -1719,7 +1621,7 @@ sub definerole { return "refused:c:$crole&$cqual"; } } - } split('/',$courole); + } my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:". "$ENV{'user.domain'}:$ENV{'user.name'}:". "rolesdef_$rolename=". @@ -1757,20 +1659,6 @@ sub plaintext { return $prp{$short}; } -# ------------------------------------------------------------------ Plain Text - -sub fileembstyle { - my $ending=lc(shift); - return $fe{$ending}; -} - -# ------------------------------------------------------------ Description Text - -sub filedescription { - my $ending=lc(shift); - return $fd{$ending}; -} - # ----------------------------------------------------------------- Assign Role sub assignrole { @@ -1939,9 +1827,9 @@ sub writecoursepref { return 'error: no such course'; } my $cstring=''; - map { + foreach (keys %prefs) { $cstring.=escape($_).'='.escape($prefs{$_}).'&'; - } keys %prefs; + } $cstring=~s/\&$//; return reply('put:'.$cdomain.':'.$cnum.':environment:'.$cstring,$chome); } @@ -2030,17 +1918,17 @@ sub dirlist { $tryserver); if (($listing ne 'no_such_dir') && ($listing ne 'empty') && ($listing ne 'con_lost')) { - map { + foreach (split(/:/,$listing)) { my ($entry,@stat)=split(/&/,$_); $allusers{$entry}=1; - } split(/:/,$listing); + } } } } my $alluserstr=''; - map { + foreach (sort keys %allusers) { $alluserstr.=$_.'&user:'; - } sort keys %allusers; + } $alluserstr=~s/:$//; return split(/:/,$alluserstr); } @@ -2051,9 +1939,9 @@ sub dirlist { $alldom{$hostdom{$tryserver}}=1; } my $alldomstr=''; - map { + foreach (sort keys %alldom) { $alldomstr.=$perlvar{'lonDocRoot'}.'/res/'.$_.'&domain:'; - } sort keys %alldom; + } $alldomstr=~s/:$//; return split(/:/,$alldomstr); } @@ -2074,18 +1962,18 @@ sub condval { my $condidx=shift; my $result=0; my $allpathcond=''; - map { + foreach (split(/\|/,$condidx)) { if (defined($ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$_})) { $allpathcond.= '('.$ENV{'acc.cond.'.$ENV{'request.course.id'}.'.'.$_}.')|'; } - } split(/\|/,$condidx); + } $allpathcond=~s/\|$//; if ($ENV{'request.course.id'}) { if ($allpathcond) { my $operand='|'; my @stack; - map { + foreach ($allpathcond=~/(\d+|\(|\)|\&|\|)/g) { if ($_ eq '(') { push @stack,($operand,$result) } elsif ($_ eq ')') { @@ -2103,9 +1991,9 @@ sub condval { $result=$result>$new?$new:$result; } else { $result=$result>$new?$result:$new; - } + } } - } ($allpathcond=~/(\d+|\(|\)|\&|\|)/g); + } } } return $result; @@ -2239,9 +2127,9 @@ sub EXT { &escape($courselevelr).'&'.&escape($courselevelm).'&'.&escape($courselevel), $ENV{'course.'.$ENV{'request.course.id'}.'.home'}); if ($reply!~/^error\:/) { - map { + foreach (split(/\&/,$reply)) { if ($_) { return &unescape($_); } - } split(/\&/,$reply); + } } if (($reply=~/^con_lost/) || ($reply=~/^error\:/)) { &logthis("WARNING:". @@ -2351,7 +2239,7 @@ sub metadata { } else { $metacache{$uri.':packages'}=$package.$keyroot; } - map { + foreach (keys %packagetab) { if ($_=~/^$package\&/) { my ($pack,$name,$subp)=split(/\&/,$_); my $value=$packagetab{$_}; @@ -2368,7 +2256,7 @@ sub metadata { $metacache{$uri.':'.$unikey.'.'.$subp}=$value; } } - } keys %packagetab; + } } else { # # This is not a package - some other kind of start tag @@ -2398,11 +2286,11 @@ sub metadata { if (defined($depthcount)) { $depthcount++; } else { $depthcount=0; } if ($depthcount<20) { - map { - $metathesekeys{$_}=1; - } split(/\,/,&metadata($uri,'keys', + foreach (split(/\,/,&metadata($uri,'keys', $parser->get_text('/import'),$unikey, - $depthcount)); + $depthcount))) { + $metathesekeys{$_}=1; + } } } else { @@ -2410,9 +2298,9 @@ sub metadata { $unikey.='_'.$token->[2]->{'name'}; } $metathesekeys{$unikey}=1; - map { + foreach (@{$token->[3]}) { $metacache{$uri.':'.$unikey.'.'.$_}=$token->[2]->{$_}; - } @{$token->[3]}; + } unless ( $metacache{$uri.':'.$unikey}=$parser->get_text('/'.$entry) ) { $metacache{$uri.':'.$unikey}= @@ -2441,9 +2329,9 @@ sub symblist { if (($ENV{'request.course.fn'}) && (%newhash)) { if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db', &GDBM_WRCREAT,0640)) { - map { + foreach (keys %newhash) { $hash{declutter($_)}=$mapname.'___'.$newhash{$_}; - } keys %newhash; + } if (untie(%hash)) { return 'ok'; } @@ -2498,7 +2386,7 @@ sub symbread { } else { # ------------------------------------------ There is more than one possibility my $realpossible=0; - map { + foreach (@possibilities) { my $file=$bighash{'src_'.$_}; if (&allowed('bre',$file)) { my ($mapid,$resid)=split(/\./,$_); @@ -2508,7 +2396,7 @@ sub symbread { '___'.$resid; } } - } @possibilities; + } if ($realpossible!=1) { $syval=''; } } } @@ -2617,7 +2505,7 @@ sub filelocation { sub hreflocation { my ($dir,$file)=@_; - unless (($_=~/^http:\/\//i) || ($_=~/^\//)) { + unless (($file=~/^http:\/\//i) || ($file=~/^\//)) { my $finalpath=filelocation($dir,$file); $finalpath=~s/^\/home\/httpd\/html//; return $finalpath; @@ -2764,3 +2652,394 @@ $dumpcount=0; } 1; +__END__ + +=head1 NAME + +Apache::lonnet - TCP networking package + +=head1 SYNOPSIS + +Invoked by other LON-CAPA modules. + + &Apache::lonnet::SUBROUTINENAME(ARGUMENTS); + +=head1 INTRODUCTION + +This module provides subroutines which interact with the +lonc/lond (TCP) network layer of LON-CAPA. + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + +=head1 HANDLER SUBROUTINE + +There is no handler routine for this module. + +=head1 OTHER SUBROUTINES + +=over 4 + +=item * + +logtouch() : make sure the logfile, lonnet.log, exists + +=item * + +logthis() : append message to lonnet.log + +=item * + +logperm() : append a permanent message to lonnet.perm.log + +=item * + +subreply() : non-critical communication, called by &reply + +=item * + +reply() : makes two attempts to pass message; logs refusals and rejections + +=item * + +reconlonc() : tries to reconnect lonc client processes. + +=item * + +critical() : passes a critical message to another server; if cannot get +through then place message in connection buffer + +=item * + +appenv(%hash) : read in current user environment, append new environment +values to make new user environment + +=item * + +delenv($varname) : read in current user environment, remove all values +beginning with $varname, write new user environment (note: flock is used +to prevent conflicting shared read/writes with file) + +=item * + +spareserver() : find server with least workload from spare.tab + +=item * + +queryauthenticate($uname,$udom) : try to determine user's current +authentication scheme + +=item * + +authenticate($uname,$upass,$udom) : try to authenticate user from domain's lib +servers (first use the current one) + +=item * + +homeserver($uname,$udom) : find the homebase for a user from domain's lib +servers + +=item * + +idget($udom,@ids) : find the usernames behind a list of IDs (returns hash: +id=>name,id=>name) + +=item * + +idrget($udom,@unames) : find the IDs behind a list of usernames (returns hash: +name=>id,name=>id) + +=item * + +idput($udom,%ids) : store away a list of names and associated IDs + +=item * + +usection($domain,$user,$courseid) : output of section name/number or '' for +"not in course" and '-1' for "no section" + +=item * + +userenvironment($domain,$user,$what) : puts out any environment parameter +for a user + +=item * + +subscribe($fname) : subscribe to a resource, return URL if possible + +=item * + +repcopy($filename) : replicate file + +=item * + +ssi($url,%hash) : server side include, does a complete request cycle on url to +localhost, posts hash + +=item * + +log($domain,$name,$home,$message) : write to permanent log for user; use +critical subroutine + +=item * + +flushcourselogs() : flush (save) buffer logs and access logs + +=item * + +courselog($what) : save message for course in hash + +=item * + +courseacclog($what) : save message for course using &courselog(). Perform +special processing for specific resource types (problems, exams, quizzes, etc). + +=item * + +countacc($url) : count the number of accesses to a given URL + +=item * + +sub checkout($symb,$tuname,$tudom,$tcrsid) : check out an item + +=item * + +sub checkin($token) : check in an item + +=item * + +sub expirespread($uname,$udom,$stype,$usymb) : set expire date for spreadsheet + +=item * + +devalidate($symb) : devalidate spreadsheets + +=item * + +hash2str(%hash) : convert a hash into a string complete with escaping and '=' +and '&' separators + +=item * + +str2hash($string) : convert string to hash using unescaping and splitting on +'=' and '&' + +=item * + +tmpreset($symb,$namespace,$domain,$stuname) : temporary storage + +=item * + +tmprestore($symb,$namespace,$domain,$stuname) : temporary restore + +=item * + +store($storehash,$symb,$namespace,$domain,$stuname) : stores hash permanently +for this url; hashref needs to be given and should be a \%hashname; the +remaining args aren't required and if they aren't passed or are '' they will +be derived from the ENV + +=item * + +cstore($storehash,$symb,$namespace,$domain,$stuname) : same as store but +uses critical subroutine + +=item * + +restore($symb,$namespace,$domain,$stuname) : returns hash for this symb; +all args are optional + +=item * + +coursedescription($courseid) : course description + +=item * + +rolesinit($domain,$username,$authhost) : get user privileges + +=item * + +get($namespace,$storearr,$udomain,$uname) : returns hash with keys from array +reference filled in from namesp ($udomain and $uname are optional) + +=item * + +del($namespace,$storearr,$udomain,$uname) : deletes keys out of array from +namesp ($udomain and $uname are optional) + +=item * + +dump($namespace,$udomain,$uname) : dumps the complete namespace into a hash +($udomain and $uname are optional) + +=item * + +put($namespace,$storehash,$udomain,$uname) : stores hash in namesp +($udomain and $uname are optional) + +=item * + +cput($namespace,$storehash,$udomain,$uname) : critical put +($udomain and $uname are optional) + +=item * + +eget($namespace,$storearr,$udomain,$uname) : returns hash with keys from array +reference filled in from namesp (encrypts the return communication) +($udomain and $uname are optional) + +=item * + +allowed($priv,$uri) : check for a user privilege; returns codes for allowed +actions + F: full access + U,I,K: authentication modes (cxx only) + '': forbidden + 1: user needs to choose course + 2: browse allowed + +=item * + +definerole($rolename,$sysrole,$domrole,$courole) : define role; define a custom +role rolename set privileges in format of lonTabs/roles.tab for system, domain, +and course level + +=item * + +metadata_query($query,$custom,$customshow) : make a metadata query against the +network of library servers; returns file handle of where SQL and regex results +will be stored for query + +=item * + +plaintext($short) : return value in %prp hash (rolesplain.tab); plain text +explanation of a user role term + +=item * + +assignrole($udom,$uname,$url,$role,$end,$start) : assign role; give a role to a +user for the level given by URL. Optional start and end dates (leave empty +string or zero for "no date") + +=item * + +modifyuserauth($udom,$uname,$umode,$upass) : modify user authentication + +=item * + +modifyuser($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene) : +modify user + +=item * + +modifystudent($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene,$usec, +$end,$start) : modify student + +=item * + +writecoursepref($courseid,%prefs) : write preferences for a course + +=item * + +createcourse($udom,$description,$url) : make/modify course + +=item * + +assigncustomrole($udom,$uname,$url,$rdom,$rnam,$rolename,$end,$start) : assign +custom role; give a custom role to a user for the level given by URL. Specify +name and domain of role author, and role name + +=item * + +revokerole($udom,$uname,$url,$role) : revoke a role for url + +=item * + +revokecustomrole($udom,$uname,$url,$role) : revoke a custom role + +=item * + +dirlist($uri) : return directory list based on URI + +=item * + +directcondval($number) : get current value of a condition; reads from a state +string + +=item * + +condval($condidx) : value of condition index based on state + +=item * + +EXT($varname,$symbparm) : value of a variable + +=item * + +metadata($uri,$what,$liburi,$prefix,$depthcount) : get metadata; returns the +metadata entry for a file; entry='keys', returns a comma separated list of keys + +=item * + +symblist($mapname,%newhash) : update symbolic storage links + +=item * + +symbread($filename) : return symbolic list entry (filename argument optional); +returns the data handle + +=item * + +numval($salt) : return random seed value (addend for rndseed) + +=item * + +rndseed($symb,$courseid,$domain,$username) : create a random sum; returns +a random seed, all arguments are optional, if they aren't sent it uses the +environment to derive them. Note: if symb isn't sent and it can't get one +from &symbread it will use the current time as its return value + +=item * + +ireceipt($funame,$fudom,$fucourseid,$fusymb) : return unique, +unfakeable, receipt + +=item * + +receipt() : API to ireceipt working off of ENV values; given out to users + +=item * + +getfile($file) : serves up a file, returns the contents of a file or -1; +replicates and subscribes to the file + +=item * + +filelocation($dir,$file) : returns file system location of a file based on URI; +meant to be "fairly clean" absolute reference + +=item * + +hreflocation($dir,$file) : returns file system location or a URL; same as +filelocation except for hrefs + +=item * + +declutter() : declutters URLs (remove docroot, beginning slashes, 'res' etc) + +=item * + +escape() : unpack non-word characters into CGI-compatible hex codes + +=item * + +unescape() : pack CGI-compatible hex codes into actual non-word ASCII character + +=item * + +goodbye() : flush course logs and log shutting down; it is called in srm.conf +as a PerlChildExitHandler + +=back + +=cut