Annotation of loncom/lonnet/perl/lonnet.pm, revision 1.23
1.1 albertel 1: # The LearningOnline Network
2: # TCP networking package
1.12 www 3: #
4: # Functions for use by content handlers:
5: #
6: # plaintext(short) : plain text explanation of short term
1.21 www 7: # allowed(short,url) : returns codes for allowed actions F,R,S,C
8: # definerole(rolename,sys,dom,cou) : define a custom role rolename
9: # set priviledges in format of lonTabs/roles.tab for
10: # system, domain and course level,
11: # assignrole(udom,uname,url,role,end,start) : give a role to a user for the
12: # level given by url. Optional start and end dates
13: # (leave empty string or zero for "no date")
14: # assigncustomrole (udom,uname,url,rdom,rnam,rolename,end,start) : give a
15: # custom role to a user for the level given by url.
16: # Specify name and domain of role author, and role name
17: # revokerole (udom,uname,url,role) : Revoke a role for url
18: # revokecustomrole (udom,uname,url,rdom,rnam,rolename) : Revoke a custom role
1.12 www 19: # appendenv(hash) : adds hash to session environment
20: # store(hash) : stores hash permanently for this url
21: # restore : returns hash for this url
22: # eget(namesp,array) : returns hash with keys from array filled in from namesp
23: # get(namesp,array) : returns hash with keys from array filled in from namesp
24: # put(namesp,hash) : stores hash in namesp
1.15 www 25: # dump(namesp) : dumps the complete namespace into a hash
1.23 ! www 26: # ssi(url,hash) : does a complete request cycle on url to localhost, posts
! 27: # hash
1.17 www 28: # repcopy(filename) : replicate file
29: # dirlist(url) : gets a directory listing
1.12 www 30: #
1.1 albertel 31: # 6/1/99,6/2,6/10,6/11,6/12,6/14,6/26,6/28,6/29,6/30,
1.5 www 32: # 7/1,7/2,7/9,7/10,7/12,7/14,7/15,7/19,
1.8 www 33: # 11/8,11/16,11/18,11/22,11/23,12/22,
1.12 www 34: # 01/06,01/13,02/24,02/28,02/29,
35: # 03/01,03/02,03/06,03/07,03/13,
1.15 www 36: # 04/05,05/29,05/31,06/01,
37: # 06/05,06/26 Gerd Kortemeyer
38: # 06/26 Ben Tyszka
1.22 www 39: # 06/30,07/15,07/17,07/18,07/20,07/21,07/22,07/25 Gerd Kortemeyer
1.23 ! www 40: # 08/14 Ben Tyszka
1.1 albertel 41:
42: package Apache::lonnet;
43:
44: use strict;
45: use Apache::File;
1.8 www 46: use LWP::UserAgent();
1.15 www 47: use HTTP::Headers;
1.11 www 48: use vars
49: qw(%perlvar %hostname %homecache %spareid %hostdom %libserv %pr %prp $readit);
1.1 albertel 50: use IO::Socket;
1.8 www 51: use Apache::Constants qw(:common :http);
1.1 albertel 52:
53: # --------------------------------------------------------------------- Logging
54:
55: sub logthis {
56: my $message=shift;
57: my $execdir=$perlvar{'lonDaemons'};
58: my $now=time;
59: my $local=localtime($now);
60: my $fh=Apache::File->new(">>$execdir/logs/lonnet.log");
61: print $fh "$local ($$): $message\n";
62: return 1;
63: }
64:
65: sub logperm {
66: my $message=shift;
67: my $execdir=$perlvar{'lonDaemons'};
68: my $now=time;
69: my $local=localtime($now);
70: my $fh=Apache::File->new(">>$execdir/logs/lonnet.perm.log");
71: print $fh "$now:$message:$local\n";
72: return 1;
73: }
74:
75: # -------------------------------------------------- Non-critical communication
76: sub subreply {
77: my ($cmd,$server)=@_;
78: my $peerfile="$perlvar{'lonSockDir'}/$server";
79: my $client=IO::Socket::UNIX->new(Peer =>"$peerfile",
80: Type => SOCK_STREAM,
81: Timeout => 10)
82: or return "con_lost";
83: print $client "$cmd\n";
84: my $answer=<$client>;
1.9 www 85: if (!$answer) { $answer="con_lost"; }
1.1 albertel 86: chomp($answer);
87: return $answer;
88: }
89:
90: sub reply {
91: my ($cmd,$server)=@_;
92: my $answer=subreply($cmd,$server);
93: if ($answer eq 'con_lost') { $answer=subreply($cmd,$server); }
1.12 www 94: if (($answer=~/^error:/) || ($answer=~/^refused/) ||
95: ($answer=~/^rejected/)) {
96: &logthis("<font color=blue>WARNING:".
97: " $cmd to $server returned $answer</font>");
98: }
1.1 albertel 99: return $answer;
100: }
101:
102: # ----------------------------------------------------------- Send USR1 to lonc
103:
104: sub reconlonc {
105: my $peerfile=shift;
106: &logthis("Trying to reconnect for $peerfile");
107: my $loncfile="$perlvar{'lonDaemons'}/logs/lonc.pid";
108: if (my $fh=Apache::File->new("$loncfile")) {
109: my $loncpid=<$fh>;
110: chomp($loncpid);
111: if (kill 0 => $loncpid) {
112: &logthis("lonc at pid $loncpid responding, sending USR1");
113: kill USR1 => $loncpid;
114: sleep 1;
115: if (-e "$peerfile") { return; }
116: &logthis("$peerfile still not there, give it another try");
117: sleep 5;
118: if (-e "$peerfile") { return; }
1.12 www 119: &logthis(
120: "<font color=blue>WARNING: $peerfile still not there, giving up</font>");
1.1 albertel 121: } else {
1.12 www 122: &logthis(
123: "<font color=blue>WARNING:".
124: " lonc at pid $loncpid not responding, giving up</font>");
1.1 albertel 125: }
126: } else {
1.12 www 127: &logthis('<font color=blue>WARNING: lonc not running, giving up</font>');
1.1 albertel 128: }
129: }
130:
131: # ------------------------------------------------------ Critical communication
1.12 www 132:
1.1 albertel 133: sub critical {
134: my ($cmd,$server)=@_;
135: my $answer=reply($cmd,$server);
136: if ($answer eq 'con_lost') {
137: my $pingreply=reply('ping',$server);
138: &reconlonc("$perlvar{'lonSockDir'}/$server");
139: my $pongreply=reply('pong',$server);
140: &logthis("Ping/Pong for $server: $pingreply/$pongreply");
141: $answer=reply($cmd,$server);
142: if ($answer eq 'con_lost') {
143: my $now=time;
144: my $middlename=$cmd;
1.5 www 145: $middlename=substr($middlename,0,16);
1.1 albertel 146: $middlename=~s/\W//g;
147: my $dfilename=
148: "$perlvar{'lonSockDir'}/delayed/$now.$middlename.$server";
149: {
150: my $dfh;
151: if ($dfh=Apache::File->new(">$dfilename")) {
1.7 www 152: print $dfh "$cmd\n";
1.1 albertel 153: }
154: }
155: sleep 2;
156: my $wcmd='';
157: {
158: my $dfh;
159: if ($dfh=Apache::File->new("$dfilename")) {
160: $wcmd=<$dfh>;
161: }
162: }
163: chomp($wcmd);
1.7 www 164: if ($wcmd eq $cmd) {
1.12 www 165: &logthis("<font color=blue>WARNING: ".
166: "Connection buffer $dfilename: $cmd</font>");
1.1 albertel 167: &logperm("D:$server:$cmd");
168: return 'con_delayed';
169: } else {
1.12 www 170: &logthis("<font color=red>CRITICAL:"
171: ." Critical connection failed: $server $cmd</font>");
1.1 albertel 172: &logperm("F:$server:$cmd");
173: return 'con_failed';
174: }
175: }
176: }
177: return $answer;
178: }
179:
1.5 www 180: # ---------------------------------------------------------- Append Environment
181:
182: sub appenv {
1.6 www 183: my %newenv=@_;
184: my @oldenv;
185: {
186: my $fh;
187: unless ($fh=Apache::File->new("$ENV{'user.environment'}")) {
1.5 www 188: return 'error';
1.6 www 189: }
190: @oldenv=<$fh>;
191: }
192: for (my $i=0; $i<=$#oldenv; $i++) {
193: chomp($oldenv[$i]);
1.9 www 194: if ($oldenv[$i] ne '') {
195: my ($name,$value)=split(/=/,$oldenv[$i]);
196: $newenv{$name}=$value;
197: }
1.6 www 198: }
199: {
200: my $fh;
201: unless ($fh=Apache::File->new(">$ENV{'user.environment'}")) {
202: return 'error';
203: }
204: my $newname;
205: foreach $newname (keys %newenv) {
206: print $fh "$newname=$newenv{$newname}\n";
207: }
1.5 www 208: }
209: return 'ok';
210: }
1.1 albertel 211:
212: # ------------------------------ Find server with least workload from spare.tab
1.11 www 213:
1.1 albertel 214: sub spareserver {
215: my $tryserver;
216: my $spareserver='';
217: my $lowestserver=100;
218: foreach $tryserver (keys %spareid) {
219: my $answer=reply('load',$tryserver);
220: if (($answer =~ /\d/) && ($answer<$lowestserver)) {
221: $spareserver="http://$hostname{$tryserver}";
222: $lowestserver=$answer;
223: }
224: }
225: return $spareserver;
226: }
227:
228: # --------- Try to authenticate user from domain's lib servers (first this one)
1.11 www 229:
1.1 albertel 230: sub authenticate {
231: my ($uname,$upass,$udom)=@_;
1.12 www 232: $upass=escape($upass);
1.1 albertel 233: if (($perlvar{'lonRole'} eq 'library') &&
234: ($udom eq $perlvar{'lonDefDomain'})) {
1.3 www 235: my $answer=reply("encrypt:auth:$udom:$uname:$upass",$perlvar{'lonHostID'});
1.2 www 236: if ($answer =~ /authorized/) {
1.9 www 237: if ($answer eq 'authorized') {
238: &logthis("User $uname at $udom authorized by local server");
239: return $perlvar{'lonHostID'};
240: }
241: if ($answer eq 'non_authorized') {
242: &logthis("User $uname at $udom rejected by local server");
243: return 'no_host';
244: }
1.2 www 245: }
1.1 albertel 246: }
247:
248: my $tryserver;
249: foreach $tryserver (keys %libserv) {
250: if ($hostdom{$tryserver} eq $udom) {
1.10 www 251: my $answer=reply("encrypt:auth:$udom:$uname:$upass",$tryserver);
1.1 albertel 252: if ($answer =~ /authorized/) {
1.9 www 253: if ($answer eq 'authorized') {
254: &logthis("User $uname at $udom authorized by $tryserver");
255: return $tryserver;
256: }
257: if ($answer eq 'non_authorized') {
258: &logthis("User $uname at $udom rejected by $tryserver");
259: return 'no_host';
260: }
1.1 albertel 261: }
262: }
1.9 www 263: }
264: &logthis("User $uname at $udom could not be authenticated");
1.1 albertel 265: return 'no_host';
266: }
267:
268: # ---------------------- Find the homebase for a user from domain's lib servers
1.11 www 269:
1.1 albertel 270: sub homeserver {
271: my ($uname,$udom)=@_;
272:
273: my $index="$uname:$udom";
274: if ($homecache{$index}) { return "$homecache{$index}"; }
275:
276: my $tryserver;
277: foreach $tryserver (keys %libserv) {
278: if ($hostdom{$tryserver} eq $udom) {
279: my $answer=reply("home:$udom:$uname",$tryserver);
280: if ($answer eq 'found') {
281: $homecache{$index}=$tryserver;
282: return $tryserver;
283: }
284: }
285: }
286: return 'no_host';
287: }
288:
289: # ----------------------------- Subscribe to a resource, return URL if possible
1.11 www 290:
1.1 albertel 291: sub subscribe {
292: my $fname=shift;
293: my $author=$fname;
294: $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
295: my ($udom,$uname)=split(/\//,$author);
296: my $home=homeserver($uname,$udom);
297: if (($home eq 'no_host') || ($home eq $perlvar{'lonHostID'})) {
298: return 'not_found';
299: }
300: my $answer=reply("sub:$fname",$home);
301: return $answer;
302: }
303:
1.8 www 304: # -------------------------------------------------------------- Replicate file
305:
306: sub repcopy {
307: my $filename=shift;
1.23 ! www 308: $filename=~s/\/+/\//g;
1.8 www 309: my $transname="$filename.in.transfer";
1.17 www 310: if ((-e $filename) || (-e $transname)) { return OK; }
1.8 www 311: my $remoteurl=subscribe($filename);
312: if ($remoteurl eq 'con_lost') {
313: &logthis("Subscribe returned con_lost: $filename");
314: return HTTP_SERVICE_UNAVAILABLE;
315: } elsif ($remoteurl eq 'not_found') {
316: &logthis("Subscribe returned not_found: $filename");
317: return HTTP_NOT_FOUND;
1.20 www 318: } elsif ($remoteurl eq 'rejected') {
319: &logthis("Subscribe returned rejected: $filename");
1.8 www 320: return FORBIDDEN;
1.20 www 321: } elsif ($remoteurl eq 'directory') {
322: return OK;
1.8 www 323: } else {
324: my @parts=split(/\//,$filename);
325: my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
326: if ($path ne "$perlvar{'lonDocRoot'}/res") {
327: &logthis("Malconfiguration for replication: $filename");
328: return HTTP_BAD_REQUEST;
329: }
330: my $count;
331: for ($count=5;$count<$#parts;$count++) {
332: $path.="/$parts[$count]";
333: if ((-e $path)!=1) {
334: mkdir($path,0777);
335: }
336: }
337: my $ua=new LWP::UserAgent;
338: my $request=new HTTP::Request('GET',"$remoteurl");
339: my $response=$ua->request($request,$transname);
340: if ($response->is_error()) {
341: unlink($transname);
342: my $message=$response->status_line;
1.12 www 343: &logthis("<font color=blue>WARNING:"
344: ." LWP get: $message: $filename</font>");
1.8 www 345: return HTTP_SERVICE_UNAVAILABLE;
346: } else {
1.16 www 347: if ($remoteurl!~/\.meta$/) {
348: my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta');
349: my $mresponse=$ua->request($mrequest,$filename.'.meta');
350: if ($mresponse->is_error()) {
351: unlink($filename.'.meta');
352: &logthis(
353: "<font color=yellow>INFO: No metadata: $filename</font>");
354: }
355: }
1.8 www 356: rename($transname,$filename);
357: return OK;
358: }
359: }
360: }
361:
1.15 www 362: # --------------------------------------------------------- Server Side Include
363:
364: sub ssi {
365:
1.23 ! www 366: my ($fn,%form)=@_;
1.15 www 367:
368: my $ua=new LWP::UserAgent;
1.23 ! www 369:
! 370: my $request;
! 371:
! 372: if (%form) {
! 373: $request=new HTTP::Request('POST',"http://".$ENV{'HTTP_HOST'}.$fn);
! 374: $request->content(join '&', map { "$_=$form{$_}" } keys %form);
! 375: } else {
! 376: $request=new HTTP::Request('GET',"http://".$ENV{'HTTP_HOST'}.$fn);
! 377: }
! 378:
1.15 www 379: $request->header(Cookie => $ENV{'HTTP_COOKIE'});
380: my $response=$ua->request($request);
381:
382: return $response->content;
383: }
384:
1.14 www 385: # ------------------------------------------------------------------------- Log
386:
387: sub log {
388: my ($dom,$nam,$hom,$what)=@_;
389: return reply("log:$dom:$nam:$what",$hom);
390: }
391:
1.9 www 392: # ----------------------------------------------------------------------- Store
393:
394: sub store {
395: my %storehash=shift;
1.12 www 396: my $namevalue='';
397: map {
398: $namevalue.=escape($_).'='.escape($storehash{$_}).'&';
399: } keys %storehash;
400: $namevalue=~s/\&$//;
401: return reply("store:$ENV{'user.domain'}:$ENV{'user.name'}:"
402: ."$ENV{'user.class'}:$ENV{'request.filename'}:$namevalue",
403: "$ENV{'user.home'}");
1.9 www 404: }
405:
406: # --------------------------------------------------------------------- Restore
407:
408: sub restore {
1.12 www 409: my $answer=reply("restore:$ENV{'user.domain'}:$ENV{'user.name'}:"
410: ."$ENV{'user.class'}:$ENV{'request.filename'}",
411: "$ENV{'user.home'}");
412: my %returnhash=();
413: map {
414: my ($name,$value)=split(/\=/,$_);
415: $returnhash{&unescape($name)}=&unescape($value);
416: } split(/\&/,$answer);
1.13 www 417: return %returnhash;
1.9 www 418: }
1.1 albertel 419:
1.11 www 420: # -------------------------------------------------------- Get user priviledges
421:
422: sub rolesinit {
423: my ($domain,$username,$authhost)=@_;
424: my $rolesdump=reply("dump:$domain:$username:roles",$authhost);
1.12 www 425: if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return ''; }
1.11 www 426: my %allroles=();
427: my %thesepriv=();
428: my $now=time;
1.21 www 429: my $userroles="user.login.time=$now\n";
1.11 www 430: my $thesestr;
431:
432: if ($rolesdump ne '') {
433: map {
1.21 www 434: if ($_!~/^rolesdef\&/) {
1.11 www 435: my ($area,$role)=split(/=/,$_);
1.21 www 436: $area=~s/\_\w\w$//;
1.11 www 437: my ($trole,$tend,$tstart)=split(/_/,$role);
1.21 www 438: $userroles.='user.role.'.$trole.'.'.$area.'='.
439: $tstart.'.'.$tend."\n";
1.11 www 440: if ($tend!=0) {
441: if ($tend<$now) {
442: $trole='';
443: }
444: }
445: if ($tstart!=0) {
446: if ($tstart>$now) {
447: $trole='';
448: }
449: }
450: if (($area ne '') && ($trole ne '')) {
1.12 www 451: my ($tdummy,$tdomain,$trest)=split(/\//,$area);
452: if ($trole =~ /^cr\//) {
453: my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$trole);
454: my $homsvr=homeserver($rauthor,$rdomain);
455: if ($hostname{$homsvr} ne '') {
456: my $roledef=
1.21 www 457: reply("get:$rdomain:$rauthor:roles:rolesdef_$rrole",
1.12 www 458: $homsvr);
459: if (($roledef ne 'con_lost') && ($roledef ne '')) {
460: my ($syspriv,$dompriv,$coursepriv)=
1.21 www 461: split(/\_/,unescape($roledef));
1.12 www 462: $allroles{'/'}.=':'.$syspriv;
463: if ($tdomain ne '') {
464: $allroles{'/'.$tdomain.'/'}.=':'.$dompriv;
465: if ($trest ne '') {
466: $allroles{$area}.=':'.$coursepriv;
467: }
468: }
469: }
1.11 www 470: }
1.12 www 471: } else {
472: $allroles{'/'}.=':'.$pr{$trole.':s'};
473: if ($tdomain ne '') {
474: $allroles{'/'.$tdomain.'/'}.=':'.$pr{$trole.':d'};
475: if ($trest ne '') {
476: $allroles{$area}.=':'.$pr{$trole.':c'};
477: }
478: }
1.11 www 479: }
1.12 www 480: }
481: }
1.11 www 482: } split(/&/,$rolesdump);
483: map {
484: %thesepriv=();
485: map {
486: if ($_ ne '') {
487: my ($priviledge,$restrictions)=split(/&/,$_);
488: if ($restrictions eq '') {
489: $thesepriv{$priviledge}='F';
490: } else {
491: if ($thesepriv{$priviledge} ne 'F') {
492: $thesepriv{$priviledge}.=$restrictions;
493: }
494: }
495: }
496: } split(/:/,$allroles{$_});
497: $thesestr='';
498: map { $thesestr.=':'.$_.'&'.$thesepriv{$_}; } keys %thesepriv;
499: $userroles.='user.priv.'.$_.'='.$thesestr."\n";
500: } keys %allroles;
501: }
502: return $userroles;
503: }
504:
1.12 www 505: # --------------------------------------------------------------- get interface
506:
507: sub get {
508: my ($namespace,@storearr)=@_;
509: my $items='';
510: map {
511: $items.=escape($_).'&';
512: } @storearr;
513: $items=~s/\&$//;
514: my $rep=reply("get:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$items",
515: $ENV{'user.home'});
1.15 www 516: my @pairs=split(/\&/,$rep);
517: my %returnhash=();
518: map {
519: my ($key,$value)=split(/=/,$_);
520: $returnhash{unespace($key)}=unescape($value);
521: } @pairs;
522: return %returnhash;
523: }
524:
525: # -------------------------------------------------------------- dump interface
526:
527: sub dump {
528: my $namespace=shift;
529: my $rep=reply("dump:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace",
530: $ENV{'user.home'});
1.12 www 531: my @pairs=split(/\&/,$rep);
532: my %returnhash=();
533: map {
534: my ($key,$value)=split(/=/,$_);
535: $returnhash{unespace($key)}=unescape($value);
536: } @pairs;
537: return %returnhash;
538: }
539:
540: # --------------------------------------------------------------- put interface
541:
542: sub put {
543: my ($namespace,%storehash)=@_;
544: my $items='';
545: map {
546: $items.=escape($_).'='.escape($storehash{$_}).'&';
547: } keys %storehash;
548: $items=~s/\&$//;
549: return reply("put:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$items",
550: $ENV{'user.home'});
551: }
552:
553: # -------------------------------------------------------------- eget interface
554:
555: sub eget {
556: my ($namespace,@storearr)=@_;
557: my $items='';
558: map {
559: $items.=escape($_).'&';
560: } @storearr;
561: $items=~s/\&$//;
562: my $rep=reply("eget:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$items",
563: $ENV{'user.home'});
564: my @pairs=split(/\&/,$rep);
565: my %returnhash=();
566: map {
567: my ($key,$value)=split(/=/,$_);
568: $returnhash{unespace($key)}=unescape($value);
569: } @pairs;
570: return %returnhash;
571: }
572:
573: # ------------------------------------------------- Check for a user priviledge
574:
575: sub allowed {
576: my ($priv,$uri)=@_;
577: $uri=~s/^\/res//;
578: $uri=~s/^\///;
1.14 www 579: if ($uri=~/^adm\//) {
580: return 'F';
581: }
1.12 www 582: my $thisallowed='';
583: if ($ENV{'user.priv./'}=~/$priv\&([^\:]*)/) {
584: $thisallowed.=$1;
585: }
586: if ($ENV{'user.priv./'.(split(/\//,$uri))[0].'/'}=~/$priv\&([^\:]*)/) {
587: $thisallowed.=$1;
588: }
589: if ($ENV{'user.priv./'.$uri}=~/$priv\&([^\:]*)/) {
590: $thisallowed.=$1;
591: }
592: return $thisallowed;
593: }
594:
595: # ----------------------------------------------------------------- Define Role
596:
597: sub definerole {
598: if (allowed('mcr','/')) {
599: my ($rolename,$sysrole,$domrole,$courole)=@_;
1.21 www 600: map {
601: my ($crole,$cqual)=split(/\&/,$_);
602: if ($pr{'cr:s'}!~/$crole/) { return "refused:s:$crole"; }
603: if ($pr{'cr:s'}=~/$crole\&/) {
604: if ($pr{'cr:s'}!~/$crole\&\w*$cqual/) {
605: return "refused:s:$crole&$cqual";
606: }
607: }
608: } split('/',$sysrole);
609: map {
610: my ($crole,$cqual)=split(/\&/,$_);
611: if ($pr{'cr:d'}!~/$crole/) { return "refused:d:$crole"; }
612: if ($pr{'cr:d'}=~/$crole\&/) {
613: if ($pr{'cr:d'}!~/$crole\&\w*$cqual/) {
614: return "refused:d:$crole&$cqual";
615: }
616: }
617: } split('/',$domrole);
618: map {
619: my ($crole,$cqual)=split(/\&/,$_);
620: if ($pr{'cr:c'}!~/$crole/) { return "refused:c:$crole"; }
621: if ($pr{'cr:c'}=~/$crole\&/) {
622: if ($pr{'cr:c'}!~/$crole\&\w*$cqual/) {
623: return "refused:c:$crole&$cqual";
624: }
625: }
626: } split('/',$courole);
1.12 www 627: my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:".
628: "$ENV{'user.domain'}:$ENV{'user.name'}:".
1.21 www 629: "rolesdef_$rolename=".
630: escape($sysrole.'_'.$domrole.'_'.$courole);
1.12 www 631: return reply($command,$ENV{'user.home'});
632: } else {
633: return 'refused';
634: }
635: }
636:
637: # ------------------------------------------------------------------ Plain Text
638:
639: sub plaintext {
1.22 www 640: my $short=shift;
641: return $prp{$short};
1.12 www 642: }
643:
644: # ----------------------------------------------------------------- Assign Role
645:
646: sub assignrole {
1.21 www 647: my ($udom,$uname,$url,$role,$end,$start)=@_;
648: my $mrole;
649: if ($role =~ /^cr\//) {
650: unless ($url=~/\.course$/) { return 'invalid'; }
651: unless (allowed('ccr',$url)) { return 'refused'; }
652: $mrole='cr';
653: } else {
654: unless (($url=~/\.course$/) || ($url=~/\/$/)) { return 'invalid'; }
655: unless (allowed('c'+$role)) { return 'refused'; }
656: $mrole=$role;
657: }
658: my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:".
659: "$udom:$uname:$url".'_'."$mrole=$role";
660: if ($end) { $command.='_$end'; }
661: if ($start) {
662: if ($end) {
663: $command.='_$start';
664: } else {
665: $command.='_0_$start';
666: }
667: }
668: return &reply($command,&homeserver($uname,$udom));
669: }
670:
671: # ---------------------------------------------------------- Assign Custom Role
672:
673: sub assigncustomrole {
674: my ($udom,$uname,$url,$rdom,$rnam,$rolename,$end,$start)=@_;
675: return &assignrole($udom,$uname,$url,'cr/'.$rdom.'/'.$rnam.'/'.$rolename,
676: $end,$start);
677: }
678:
679: # ----------------------------------------------------------------- Revoke Role
680:
681: sub revokerole {
682: my ($udom,$uname,$url,$role)=@_;
683: my $now=time;
684: return &assignrole($udom,$uname,$url,$role,$now);
685: }
686:
687: # ---------------------------------------------------------- Revoke Custom Role
688:
689: sub revokecustomrole {
690: my ($udom,$uname,$url,$rdom,$rnam,$rolename)=@_;
691: my $now=time;
692: return &assigncustomrole($udom,$uname,$url,$rdom,$rnam,$rolename,$now);
1.17 www 693: }
694:
695: # ------------------------------------------------------------ Directory lister
696:
697: sub dirlist {
698: my $uri=shift;
1.18 www 699: $uri=~s/^\///;
700: $uri=~s/\/$//;
1.19 www 701: my ($res,$udom,$uname,@rest)=split(/\//,$uri);
702: if ($udom) {
703: if ($uname) {
704: my $listing=reply('ls:'.$perlvar{'lonDocRoot'}.'/'.$uri,
705: homeserver($uname,$udom));
706: return split(/:/,$listing);
707: } else {
708: my $tryserver;
709: my %allusers=();
710: foreach $tryserver (keys %libserv) {
711: if ($hostdom{$tryserver} eq $udom) {
712: my $listing=reply('ls:'.$perlvar{'lonDocRoot'}.'/res/'.$udom,
713: $tryserver);
714: if (($listing ne 'no_such_dir') && ($listing ne 'empty')
715: && ($listing ne 'con_lost')) {
716: map {
717: my ($entry,@stat)=split(/&/,$_);
718: $allusers{$entry}=1;
719: } split(/:/,$listing);
720: }
721: }
722: }
723: my $alluserstr='';
724: map {
725: $alluserstr.=$_.'&user:';
726: } sort keys %allusers;
727: $alluserstr=~s/:$//;
728: return split(/:/,$alluserstr);
729: }
730: } else {
731: my $tryserver;
732: my %alldom=();
733: foreach $tryserver (keys %libserv) {
734: $alldom{$hostdom{$tryserver}}=1;
735: }
736: my $alldomstr='';
737: map {
738: $alldomstr.=$perlvar{'lonDocRoot'}.'/res/'.$_.'&domain:';
739: } sort keys %alldom;
740: $alldomstr=~s/:$//;
741: return split(/:/,$alldomstr);
742: }
1.12 www 743: }
744:
745: # -------------------------------------------------------- Escape Special Chars
746:
747: sub escape {
748: my $str=shift;
749: $str =~ s/(\W)/"%".unpack('H2',$1)/eg;
750: return $str;
751: }
752:
753: # ----------------------------------------------------- Un-Escape Special Chars
754:
755: sub unescape {
756: my $str=shift;
757: $str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
758: return $str;
759: }
1.11 www 760:
1.1 albertel 761: # ================================================================ Main Program
762:
763: sub BEGIN {
764: if ($readit ne 'done') {
765: # ------------------------------------------------------------ Read access.conf
766: {
767: my $config=Apache::File->new("/etc/httpd/conf/access.conf");
768:
769: while (my $configline=<$config>) {
770: if ($configline =~ /PerlSetVar/) {
771: my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);
1.8 www 772: chomp($varvalue);
1.1 albertel 773: $perlvar{$varname}=$varvalue;
774: }
775: }
776: }
777:
778: # ------------------------------------------------------------- Read hosts file
779: {
780: my $config=Apache::File->new("$perlvar{'lonTabDir'}/hosts.tab");
781:
782: while (my $configline=<$config>) {
783: my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
784: $hostname{$id}=$name;
785: $hostdom{$id}=$domain;
786: if ($role eq 'library') { $libserv{$id}=$name; }
787: }
788: }
789:
790: # ------------------------------------------------------ Read spare server file
791: {
792: my $config=Apache::File->new("$perlvar{'lonTabDir'}/spare.tab");
793:
794: while (my $configline=<$config>) {
795: chomp($configline);
796: if (($configline) && ($configline ne $perlvar{'lonHostID'})) {
797: $spareid{$configline}=1;
798: }
799: }
800: }
1.11 www 801: # ------------------------------------------------------------ Read permissions
802: {
803: my $config=Apache::File->new("$perlvar{'lonTabDir'}/roles.tab");
804:
805: while (my $configline=<$config>) {
806: chomp($configline);
807: my ($role,$perm)=split(/ /,$configline);
808: if ($perm ne '') { $pr{$role}=$perm; }
809: }
810: }
811:
812: # -------------------------------------------- Read plain texts for permissions
813: {
814: my $config=Apache::File->new("$perlvar{'lonTabDir'}/rolesplain.tab");
815:
816: while (my $configline=<$config>) {
817: chomp($configline);
818: my ($short,$plain)=split(/:/,$configline);
819: if ($plain ne '') { $prp{$short}=$plain; }
820: }
821: }
822:
1.22 www 823:
1.1 albertel 824: $readit='done';
1.12 www 825: &logthis('<font color=yellow>INFO: Read configuration</font>');
1.1 albertel 826: }
827: }
828: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>