--- loncom/lond	2002/04/27 13:10:47	1.77
+++ loncom/lond	2002/09/03 02:02:50	1.90.2.1
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # lond "LON Daemon" Server (port "LOND" 5663)
 #
-# $Id: lond,v 1.77 2002/04/27 13:10:47 foxr Exp $
+# $Id: lond,v 1.90.2.1 2002/09/03 02:02:50 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -53,6 +53,7 @@
 # 02/12 Gerd Kortemeyer
 # 02/19 Matthew Hall
 # 02/25 Gerd Kortemeyer
+# 05/11 Scott Harrison
 ###
 
 # based on "Perl Cookbook" ISBN 1-56592-243-3
@@ -61,6 +62,9 @@
 # HUPs
 # uses IDEA encryption
 
+use lib '/home/httpd/lib/perl/';
+use LONCAPA::Configuration;
+
 use IO::Socket;
 use IO::File;
 use Apache::File;
@@ -101,18 +105,12 @@ sub timeout {
 $SIG{'QUIT'}=\&catchexception;
 $SIG{__DIE__}=\&catchexception;
 
-# ------------------------------------ Read httpd access.conf and get variables
-
-open (CONFIG,"/etc/httpd/conf/access.conf") || die "Can't read access.conf";
-
-while ($configline=<CONFIG>) {
-    if ($configline =~ /PerlSetVar/) {
-	my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);
-        chomp($varvalue);
-        $perlvar{$varname}=$varvalue;
-    }
-}
-close(CONFIG);
+# ---------------------------------- Read loncapa_apache.conf and loncapa.conf
+&status("Read loncapa_apache.conf and loncapa.conf");
+my $perlvarref=LONCAPA::Configuration::read_conf('loncapa_apache.conf',
+                                                 'loncapa.conf');
+my %perlvar=%{$perlvarref};
+undef $perlvarref;
 
 # ----------------------------- Make sure this process is running from user=www
 my $wwwid=getpwnam('www');
@@ -499,6 +497,8 @@ sub make_new_child {
 # =============================================================================
             # do something with the connection
 # -----------------------------------------------------------------------------
+	    $client->sockopt(SO_KEEPALIVE, 1);# Enable monitoring of
+	                                      # connection liveness.
             # see if we know client and check for spoof IP by challenge
             my $caller=getpeername($client);
             my ($port,$iaddr)=unpack_sockaddr_in($caller);
@@ -549,6 +549,7 @@ sub make_new_child {
 # ------------------------------------------------------------ Process requests
               while (my $userinput=<$client>) {
                 chomp($userinput);
+		Debug("Request = $userinput\n");
                 &status('Processing '.$hostid{$clientip}.': '.$userinput);
                 my $wasenc=0;
                 alarm(120);
@@ -604,21 +605,13 @@ sub make_new_child {
 		   } elsif ($userinput =~ /^currentauth/) {
 		     if ($wasenc==1) {
                        my ($cmd,$udom,$uname)=split(/:/,$userinput);
-                       my $proname=propath($udom,$uname);
-                       my $passfilename="$proname/passwd";
-                       if (-e $passfilename) {
-			   my $pf = IO::File->new($passfilename);
-			   my $realpasswd=<$pf>;
-			   chomp($realpasswd);
-			   my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
-			   my $availablecontent='';
-			   if ($howpwd eq 'krb4') {
-			       $availablecontent=$contentpwd;
-			   }
-			   print $client "$howpwd:$availablecontent\n";
-		       } else {
-                          print $client "unknown_user\n";
-                       }
+		       my $result = GetAuthType($udom, $uname);
+		       if($result eq "nouser") {
+			   print $client "unknown_user\n";
+		       }
+		       else {
+			   print $client "$result\n"
+		       }
 		     } else {
 		       print $client "refused\n";
 		     }
@@ -956,48 +949,61 @@ sub make_new_child {
 		       } else {
 			print $client "rejected\n";
                        }
+# -------------------------------------- fetch a user file from a remote server
+                   } elsif ($userinput =~ /^fetchuserfile/) {
+                      my ($cmd,$fname)=split(/:/,$userinput);
+		      my ($udom,$uname,$ufile)=split(/\//,$fname);
+                      my $udir=propath($udom,$uname).'/userfiles';
+                      unless (-e $udir) { mkdir($udir,0770); }
+                       if (-e $udir) {
+                       $ufile=~s/^[\.\~]+//;
+                       $ufile=~s/\///g;
+                       my $transname=$udir.'/'.$ufile;
+                       my $remoteurl='http://'.$clientip.'/userfiles/'.$fname;
+                             my $response;
+                              {
+                             my $ua=new LWP::UserAgent;
+                             my $request=new HTTP::Request('GET',"$remoteurl");
+                             $response=$ua->request($request,$transname);
+			      }
+                             if ($response->is_error()) {
+				 unlink($transname);
+                                 my $message=$response->status_line;
+                                 &logthis(
+                                  "LWP GET: $message for $fname ($remoteurl)");
+				 print $client "failed\n";
+                             } else {
+                                 print $client "ok\n";
+                             }
+                     } else {
+                       print $client "not_home\n";
+                     } 
+# ------------------------------------------ authenticate access to a user file
+                   } elsif ($userinput =~ /^tokenauthuserfile/) {
+                       my ($cmd,$fname,$session)=split(/:/,$userinput);
+                       chomp($session);
+                       $reply='non_auth';
+                       if (open(ENVIN,$perlvar{'lonIDsDir'}.'/'.
+                                      $session.'.id')) {
+                        while ($line=<ENVIN>) {
+			   if ($line=~/userfile\.$fname\=/) { $reply='ok'; }
+                        }
+                        close(ENVIN);
+                        print $client $reply."\n";
+		       } else {
+			print $client "invalid_token\n";
+                       }
 # ----------------------------------------------------------------- unsubscribe
                    } elsif ($userinput =~ /^unsub/) {
                        my ($cmd,$fname)=split(/:/,$userinput);
                        if (-e $fname) {
-                           if (unlink("$fname.$hostid{$clientip}")) {
-                              print $client "ok\n";
-			   } else {
-                              print $client "not_subscribed\n";
-			   }
+			   print $client &unsub($client,$fname,$clientip);
                        } else {
 			   print $client "not_found\n";
                        }
 # ------------------------------------------------------------------- subscribe
                    } elsif ($userinput =~ /^sub/) {
-                       my ($cmd,$fname)=split(/:/,$userinput);
-                       my $ownership=ishome($fname);
-                       if ($ownership eq 'owner') {
-                        if (-e $fname) {
-			 if (-d $fname) {
-			   print $client "directory\n";
-                         } else {
-                           $now=time;
-                           { 
-			    my $sh;
-                            if ($sh=
-                             IO::File->new(">$fname.$hostid{$clientip}")) {
-                               print $sh "$clientip:$now\n";
-			    }
-			   }
-                           unless ($fname=~/\.meta$/) {
-			       unlink("$fname.meta.$hostid{$clientip}");
-                           }
-                           $fname=~s/\/home\/httpd\/html\/res/raw/;
-                           $fname="http://$thisserver/".$fname;
-                           print $client "$fname\n";
-		         }
-                        } else {
-		      	   print $client "not_found\n";
-                        }
-		       } else {
-                        print $client "rejected\n";
-		       }
+		       print $client &subscribe($userinput,$clientip);
 # ------------------------------------------------------------------------- log
                    } elsif ($userinput =~ /^log/) {
                        my ($cmd,$udom,$uname,$what)=split(/:/,$userinput);
@@ -1071,7 +1077,11 @@ sub make_new_child {
       if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT,0640)) {
                            foreach $pair (@pairs) {
 			       ($key,$value)=split(/=/,$pair);
+			       &ManagePermissions($key, $udom, $uname,
+						  &GetAuthType( $udom, 
+								$uname));
                                $hash{$key}=$value;
+			       
                            }
 			   if (untie(%hash)) {
                               print $client "ok\n";
@@ -1206,10 +1216,12 @@ sub make_new_child {
                        my $proname=propath($udom,$uname);
                        my $qresult='';
       if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER,0640)) {
+                           study($regexp);
                            foreach $key (keys %hash) {
-                               if (eval('$key=~/$regexp/')) {
+                               my $unescapeKey = &unescape($key);
+                               if (eval('$unescapeKey=~/$regexp/')) {
                                   $qresult.="$key=$hash{$key}&";
-			       }
+                              }
                            }
 			   if (untie(%hash)) {
 		              $qresult=~s/\&$//;
@@ -1294,20 +1306,28 @@ sub make_new_child {
                        } else {
                            print $client "error:$!\n";
                        }
+# -------------------------------------------------------------------- chatsend
+                   } elsif ($userinput =~ /^chatsend/) {
+                       my ($cmd,$cdom,$cnum,$newpost)=split(/\:/,$userinput);
+                       &chatadd($cdom,$cnum,$newpost);
+                       print $client "ok\n";
+# -------------------------------------------------------------------- chatretr
+                   } elsif ($userinput =~ /^chatretr/) {
+                       my ($cmd,$cdom,$cnum)=split(/\:/,$userinput);
+                       my $reply='';
+                       foreach (&getchat($cdom,$cnum)) {
+			   $reply.=&escape($_).':';
+                       }
+                       $reply=~s/\:$//;
+                       print $client $reply."\n";
 # ------------------------------------------------------------------- querysend
                    } elsif ($userinput =~ /^querysend/) {
                        my ($cmd,$query,
-			   $custom,$customshow)=split(/:/,$userinput);
+			   $arg1,$arg2,$arg3)=split(/\:/,$userinput);
 		       $query=~s/\n*$//g;
-		       unless ($custom or $customshow) {
-			   print $client "".
-			       sqlreply("$hostid{$clientip}\&$query")."\n";
-		       }
-		       else {
-			   print $client "".
+		       print $client "".
 			       sqlreply("$hostid{$clientip}\&$query".
-					"\&$custom"."\&$customshow")."\n";
-		       }
+					"\&$arg1"."\&$arg2"."\&$arg3")."\n";
 # ------------------------------------------------------------------ queryreply
                    } elsif ($userinput =~ /^queryreply/) {
                        my ($cmd,$id,$reply)=split(/:/,$userinput); 
@@ -1413,14 +1433,20 @@ sub make_new_child {
                        my $ulsout='';
                        my $ulsfn;
                        if (-e $ulsdir) {
-			if (opendir(LSDIR,$ulsdir)) {
-                          while ($ulsfn=readdir(LSDIR)) {
-			     my @ulsstats=stat($ulsdir.'/'.$ulsfn);
-                             $ulsout.=$ulsfn.'&'.join('&',@ulsstats).':';
-                          }
-                          closedir(LSDIR);
-		        }
-		       } else {
+                           if(-d $ulsdir) {
+                               if (opendir(LSDIR,$ulsdir)) {
+                                   while ($ulsfn=readdir(LSDIR)) {
+                                       my @ulsstats=stat($ulsdir.'/'.$ulsfn);
+                                       $ulsout.=$ulsfn.'&'.
+                                                join('&',@ulsstats).':';
+                                   }
+                                   closedir(LSDIR);
+                               }
+                           } else {
+                               my @ulsstats=stat($ulsdir);
+                               $ulsout.=$ulsfn.'&'.join('&',@ulsstats).':';
+                           }
+                       } else {
                           $ulsout='no_such_dir';
                        }
                        if ($ulsout eq '') { $ulsout='empty'; }
@@ -1466,6 +1492,177 @@ sub make_new_child {
     }
 }
 
+
+#
+#   Checks to see if the input roleput request was to set
+# an author role.  If so, invokes the lchtmldir script to set
+# up a correct public_html 
+# Parameters:
+#    request   - The request sent to the rolesput subchunk.
+#                We're looking for  /domain/_au
+#    domain    - The domain in which the user is having roles doctored.
+#    user      - Name of the user for which the role is being put.
+#    authtype  - The authentication type associated with the user.
+#
+sub ManagePermissions
+{
+    my $request = shift;
+    my $domain  = shift;
+    my $user    = shift;
+    my $authtype= shift;
+
+    # See if the request is of the form /$domain/_au
+
+    if($request =~ /^(\/$domain\/_au)$/) { # It's an author rolesput...
+	my $execdir = $perlvar{'lonDaemons'};
+	my $userhome= "/home/$user" ;
+	Debug("system $execdir/lchtmldir $userhome $system $authtype");
+	system("$execdir/lchtmldir $userhome $user $authtype");
+    }
+}
+#
+#   GetAuthType - Determines the authorization type of a user in a domain.
+
+#     Returns the authorization type or nouser if there is no such user.
+#
+sub GetAuthType 
+{
+    my $domain = shift;
+    my $user   = shift;
+
+    Debug("GetAuthType( $domain, $user ) \n");
+    my $proname    = &propath($domain, $user); 
+    my $passwdfile = "$proname/passwd";
+    if( -e $passwdfile ) {
+	my $pf = IO::File->new($passwdfile);
+	my $realpassword = <$pf>;
+	chomp($realpassword);
+	Debug("Password info = $realpassword\n");
+	my ($authtype, $contentpwd) = split(/:/, $realpassword);
+	Debug("Authtype = $authtype, content = $contentpwd\n");
+	my $availinfo = '';
+	if($authtype eq 'krb4') {
+	    $availinfo = $contentpwd;
+	}
+
+	return "$authtype:$availinfo";
+    }
+    else {
+	Debug("Returning nouser");
+	return "nouser";
+    }
+}
+
+sub addline {
+    my ($fname,$hostid,$ip,$newline)=@_;
+    my $contents;
+    my $found=0;
+    my $expr='^'.$hostid.':'.$ip.':';
+    $expr =~ s/\./\\\./g;
+    if ($sh=IO::File->new("$fname.subscription")) {
+	while (my $subline=<$sh>) {
+	    if ($subline !~ /$expr/) {$contents.= $subline;} else {$found=1;}
+	}
+	$sh->close();
+    }
+    $sh=IO::File->new(">$fname.subscription");
+    if ($contents) { print $sh $contents; }
+    if ($newline) { print $sh $newline; }
+    $sh->close();
+    return $found;
+}
+
+sub getchat {
+    my ($cdom,$cname)=@_;
+    my %hash;
+    my $proname=&propath($cdom,$cname);
+    my @entries=();
+    if (tie(%hash,'GDBM_File',"$proname/nohist_chatroom.db",
+	    &GDBM_READER(),0640)) {
+	@entries=map { $_.':'.$hash{$_} } sort keys %hash;
+	untie %hash;
+    }
+    return @entries;
+}
+
+sub chatadd {
+    my ($cdom,$cname,$newchat)=@_;
+    my %hash;
+    my $proname=&propath($cdom,$cname);
+    my @entries=();
+    if (tie(%hash,'GDBM_File',"$proname/nohist_chatroom.db",
+	    &GDBM_WRCREAT(),0640)) {
+	@entries=map { $_.':'.$hash{$_} } sort keys %hash;
+	my $time=time;
+	my ($lastid)=($entries[$#entries]=~/^(\w+)\:/);
+	my ($thentime,$idnum)=split(/\_/,$lastid);
+	my $newid=$time.'_000000';
+	if ($thentime==$time) {
+	    $idnum=~s/^0+//;
+	    $idnum++;
+	    $idnum=substr('000000'.$idnum,-6,6);
+	    $newid=$time.'_'.$idnum;
+	}
+	$hash{$newid}=$newchat;
+	my $expired=$time-3600;
+	foreach (keys %hash) {
+	    my ($thistime)=($_=~/(\d+)\_/);
+	    if ($thistime<$expired) {
+		delete $hash{$_};
+	    }
+	}
+	untie %hash;
+    }
+}
+
+sub unsub {
+    my ($fname,$clientip)=@_;
+    my $result;
+    if (unlink("$fname.$hostid{$clientip}")) {
+	$result="ok\n";
+    } else {
+	$result="not_subscribed\n";
+    }
+    if (-e "$fname.subscription") {
+	my $found=&addline($fname,$hostid{$clientip},$clientip,'');
+	if ($found) { $result="ok\n"; }
+    } else {
+	if ($result != "ok\n") { $result="not_subscribed\n"; }
+    }
+    return $result;
+}
+
+sub subscribe {
+    my ($userinput,$clientip)=@_;
+    my $result;
+    my ($cmd,$fname)=split(/:/,$userinput);
+    my $ownership=&ishome($fname);
+    if ($ownership eq 'owner') {
+	if (-e $fname) {
+	    if (-d $fname) {
+		$result="directory\n";
+	    } else {
+		if (-e "$fname.$hostid{$clientip}") {&unsub($fname,$clientip);}
+		$now=time;
+		my $found=&addline($fname,$hostid{$clientip},$clientip,
+				   "$hostid{$clientip}:$clientip:$now\n");
+		if ($found) { $result="$fname\n"; }
+		# if they were subscribed to only meta data, delete that
+                # subscription, when you subscribe to a file you also get
+                # the metadata
+		unless ($fname=~/\.meta$/) { &unsub("$fname.meta",$clientip); }
+		$fname=~s/\/home\/httpd\/html\/res/raw/;
+		$fname="http://$thisserver/".$fname;
+		$result="$fname\n";
+	    }
+	} else {
+	    $result="not_found\n";
+	}
+    } else {
+	$result="rejected\n";
+    }
+    return $result;
+}
 # ----------------------------------- POD (plain old documentation, CPAN style)
 
 =head1 NAME