Diff for /loncom/lond between versions 1.152 and 1.196

version 1.152, 2003/10/08 14:18:34 version 1.196, 2004/06/17 11:02:25
Line 10 Line 10
 #  #
 # LON-CAPA is free software; you can redistribute it and/or modify  # LON-CAPA is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by  # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or  # the Free Software Foundation; either version 2 of the License, or 
 # (at your option) any later version.  # (at your option) any later version.
 #  #
 # LON-CAPA is distributed in the hope that it will be useful,  # LON-CAPA is distributed in the hope that it will be useful,
Line 24 Line 24
 #  #
 # /home/httpd/html/adm/gpl.txt  # /home/httpd/html/adm/gpl.txt
 #  #
   
   
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 # 5/26/99,6/4,6/10,6/11,6/14,6/15,6/26,6/28,6/30,  
 # 7/8,7/9,7/10,7/12,7/17,7/19,9/21,  
 # 10/7,10/8,10/9,10/11,10/13,10/15,11/4,11/16,  
 # 12/7,12/15,01/06,01/11,01/12,01/14,2/8,  
 # 03/07,05/31 Gerd Kortemeyer  
 # 06/29,06/30,07/14,07/15,07/17,07/20,07/25,09/18 Gerd Kortemeyer  
 # 12/05,12/13,12/29 Gerd Kortemeyer  
 # YEAR=2001  
 # 02/12 Gerd Kortemeyer  
 # 03/24 Gerd Kortemeyer  
 # 05/11,05/28,08/30 Gerd Kortemeyer  
 # 11/26,11/27 Gerd Kortemeyer  
 # 12/22 Gerd Kortemeyer  
 # YEAR=2002  
 # 01/20/02,02/05 Gerd Kortemeyer  
 # 02/05 Guy Albertelli  
 # 02/12 Gerd Kortemeyer  
 # 02/19 Matthew Hall  
 # 02/25 Gerd Kortemeyer  
 # 01/xx/2003 Ron Fox.. Remove preforking.  This makes the general daemon  
 #      logic simpler (and there were problems maintaining the preforked  
 #      population).  Since the time averaged connection rate is close to zero  
 #      because lonc's purpose is to maintain near continuous connnections,  
 #      preforking is not really needed.  
 # 08/xx/2003 Ron Fox:  Add management requests.  Management requests  
 #      will be validated via a call to ValidateManager. At present, this  
 #      is done by simple host verification.  In the future we can modify  
 #      this function to do a certificate check.  
 #      Management functions supported include:  
 #       - pushing /home/httpd/lonTabs/hosts.tab  
 #       - pushing /home/httpd/lonTabs/domain.tab  
 # 09/08/2003 Ron Fox:  Told lond to take care of change logging so we  
 #      don't have to remember it:  
 # $Log$  
 # Revision 1.152  2003/10/08 14:18:34  www  
 # Not good: this should be backported into 1.0.2!  
 #  
 # Revision 1.151  2003/10/03 15:11:03  albertel  
 # - if we fail to fetch an update to the file, don't blow away the old one  
 #   (this was the BUG that blew away that one default.sequence that Matthew  
 #    ended up restoring from data.)  
 #  
 # Revision 1.150  2003/09/30 10:16:06  foxr  
 # Added invocation of apachereload in ReloadApache sub.  
 # This completes the addtion of the reinit functionality.  
 #  
 # Revision 1.149  2003/09/30 09:44:13  foxr  
 # Tested UpdateHosts ability to  
 # - Remove live children for hosts that are no longer in the hosts.tab  
 # - Remove live children for hosts whose IPs have changed in the hosts.tab  
 #  
 # Revision 1.148  2003/09/29 10:09:18  foxr  
 # Put in logic to reinit lond itself (except for apache reload).  I don't believe  
 # this logic works correctly yet, however lond still does everything it used to doso I'll do the commit anyway.  
 #  
 # Revision 1.147  2003/09/23 11:23:31  foxr  
 # Comlplete implementation of reinit functionality.  Must still implement  
 # the actual initialization functionality, but the process can now  
 # receive the request and either invoke the appropriate internal function or  
 # signal the correct lonc.  
 #  
 # Revision 1.146  2003/09/16 10:28:14  foxr  
 # ReinitProcess - decode the process selector and produce the associated pid  
 # filename.  Note: While it is possible to test that valid process selectors are  
 # handled properly I am not able to test that invalid process selectors produce  
 # the appropriate error as lonManage also blocks the use of invalid process selectors.  
 #  
 # Revision 1.145  2003/09/16 10:13:20  foxr  
 # Added ReinitProcess function to oversee the parsing and processing of the  
 # reinit:<process> client request.  
 #  
 # Revision 1.144  2003/09/16 09:47:01  foxr  
 # Added skeletal support for SIGUSR2 (update hosts.tab)  
 #  
 # Revision 1.143  2003/09/15 10:03:52  foxr  
 # Completed and tested code for pushfile.  
 #  
 # Revision 1.142  2003/09/09 20:47:46  www  
 # Permanently store chatroom entries in chatroom.log  
 #  
 # Revision 1.141  2003/09/08 10:32:07  foxr  
 # Added PushFile sub This sub oversees the push of a new configuration table file  
 # Currently supported files are:  
 # - hosts.tab   (transaction pushfile:hosts:contents)  
 # - domain.tab  (transaction pushfile:domain:contents)  
 #  
   
   
 use strict;  use strict;
 use lib '/home/httpd/lib/perl/';  use lib '/home/httpd/lib/perl/';
Line 130  use Authen::Krb4; Line 45  use Authen::Krb4;
 use Authen::Krb5;  use Authen::Krb5;
 use lib '/home/httpd/lib/perl/';  use lib '/home/httpd/lib/perl/';
 use localauth;  use localauth;
   use localenroll;
 use File::Copy;  use File::Copy;
   use LONCAPA::ConfigFileEdit;
   use LONCAPA::lonlocal;
   use LONCAPA::lonssl;
   
 my $DEBUG = 0;       # Non zero to enable debug log entries.  my $DEBUG = 11;       # Non zero to enable debug log entries.
   
 my $status='';  my $status='';
 my $lastlog='';  my $lastlog='';
Line 143  my $currenthostid; Line 62  my $currenthostid;
 my $currentdomainid;  my $currentdomainid;
   
 my $client;  my $client;
 my $clientip;  my $clientip; # IP address of client.
   my $clientdns; # DNS name of client.
   my $clientname; # LonCAPA name of client.
   
 my $server;  my $server;
 my $thisserver;  my $thisserver; # DNS of us.
   
   # 
   #   Connection type is:
   #      client                   - All client actions are allowed
   #      manager                  - only management functions allowed.
   #      both                     - Both management and client actions are allowed
   #
   
   my $ConnectionType;
   
   my %hostid; # ID's for hosts in cluster by ip.
   my %hostdom; # LonCAPA domain for hosts in cluster.
   my %hostip; # IPs for hosts in cluster.
   my %hostdns; # ID's of hosts looked up by DNS name.
   
   my %managers; # Ip -> manager names
   
 my %hostid;  
 my %hostdom;  
 my %hostip;  
 my %perlvar; # Will have the apache conf defined perl vars.  my %perlvar; # Will have the apache conf defined perl vars.
   
 #  #
Line 181  my @adderrors    = ("ok", Line 115  my @adderrors    = ("ok",
     "lcuseradd Incorrect number of stdinput lines, must be 3",      "lcuseradd Incorrect number of stdinput lines, must be 3",
     "lcuseradd Too many other simultaneous pwd changes in progress",      "lcuseradd Too many other simultaneous pwd changes in progress",
     "lcuseradd User does not exist",      "lcuseradd User does not exist",
     "lcuseradd Unabel to mak ewww member of users's group",      "lcuseradd Unable to make www member of users's group",
     "lcuseradd Unable to su to root",      "lcuseradd Unable to su to root",
     "lcuseradd Unable to set password",      "lcuseradd Unable to set password",
     "lcuseradd Usrname has invbalid charcters",      "lcuseradd Usrname has invalid characters",
     "lcuseradd Password has an invalid character",      "lcuseradd Password has an invalid character",
     "lcuseradd User already exists",      "lcuseradd User already exists",
     "lcuseradd Could not add user.",      "lcuseradd Could not add user.",
     "lcuseradd Password mismatch");      "lcuseradd Password mismatch");
   
   
   #------------------------------------------------------------------------
   #
   #   LocalConnection
   #     Completes the formation of a locally authenticated connection.
   #     This function will ensure that the 'remote' client is really the
   #     local host.  If not, the connection is closed, and the function fails.
   #     If so, initcmd is parsed for the name of a file containing the
   #     IDEA session key.  The fie is opened, read, deleted and the session
   #     key returned to the caller.
   #
   # Parameters:
   #   $Socket      - Socket open on client.
   #   $initcmd     - The full text of the init command.
   #
   # Implicit inputs:
   #    $clientdns  - The DNS name of the remote client.
   #    $thisserver - Our DNS name.
   #
   # Returns:
   #     IDEA session key on success.
   #     undef on failure.
   #
   sub LocalConnection {
       my ($Socket, $initcmd) = @_;
       Debug("Attempting local connection: $initcmd client: $clientdns me: $thisserver");
       if($clientdns ne $thisserver) {
    &logthis('<font color="red"> LocalConnection rejecting non local: '
    ."$clientdns ne $thisserver </font>");
    close $Socket;
    return undef;
       } 
       else {
    chomp($initcmd); # Get rid of \n in filename.
    my ($init, $type, $name) = split(/:/, $initcmd);
    Debug(" Init command: $init $type $name ");
   
    # Require that $init = init, and $type = local:  Otherwise
    # the caller is insane:
   
    if(($init ne "init") && ($type ne "local")) {
       &logthis('<font color = "red"> LocalConnection: caller is insane! '
        ."init = $init, and type = $type </font>");
       close($Socket);;
       return undef;
   
    }
    #  Now get the key filename:
   
    my $IDEAKey = lonlocal::ReadKeyFile($name);
    return $IDEAKey;
       }
   }
   #------------------------------------------------------------------------------
   #
   #  SSLConnection
   #   Completes the formation of an ssh authenticated connection. The
   #   socket is promoted to an ssl socket.  If this promotion and the associated
   #   certificate exchange are successful, the IDEA key is generated and sent
   #   to the remote peer via the SSL tunnel. The IDEA key is also returned to
   #   the caller after the SSL tunnel is torn down.
   #
   # Parameters:
   #   Name              Type             Purpose
   #   $Socket          IO::Socket::INET  Plaintext socket.
   #
   # Returns:
   #    IDEA key on success.
   #    undef on failure.
   #
   sub SSLConnection {
       my $Socket   = shift;
   
       Debug("SSLConnection: ");
       my $KeyFile         = lonssl::KeyFile();
       if(!$KeyFile) {
    my $err = lonssl::LastError();
    &logthis("<font color=\"red\"> CRITICAL"
    ."Can't get key file $err </font>");
    return undef;
       }
       my ($CACertificate,
    $Certificate) = lonssl::CertificateFile();
   
   
       # If any of the key, certificate or certificate authority 
       # certificate filenames are not defined, this can't work.
   
       if((!$Certificate) || (!$CACertificate)) {
    my $err = lonssl::LastError();
    &logthis("<font color=\"red\"> CRITICAL"
    ."Can't get certificates: $err </font>");
   
    return undef;
       }
       Debug("Key: $KeyFile CA: $CACertificate Cert: $Certificate");
   
       # Indicate to our peer that we can procede with
       # a transition to ssl authentication:
   
       print $Socket "ok:ssl\n";
   
       Debug("Approving promotion -> ssl");
       #  And do so:
   
       my $SSLSocket = lonssl::PromoteServerSocket($Socket,
    $CACertificate,
    $Certificate,
    $KeyFile);
       if(! ($SSLSocket) ) { # SSL socket promotion failed.
    my $err = lonssl::LastError();
    &logthis("<font color=\"red\"> CRITICAL "
    ."SSL Socket promotion failed: $err </font>");
    return undef;
       }
       Debug("SSL Promotion successful");
   
       # 
       #  The only thing we'll use the socket for is to send the IDEA key
       #  to the peer:
   
       my $Key = lonlocal::CreateCipherKey();
       print $SSLSocket "$Key\n";
   
       lonssl::Close($SSLSocket); 
   
       Debug("Key exchange complete: $Key");
   
       return $Key;
   }
   #
   #     InsecureConnection: 
   #        If insecure connections are allowd,
   #        exchange a challenge with the client to 'validate' the
   #        client (not really, but that's the protocol):
   #        We produce a challenge string that's sent to the client.
   #        The client must then echo the challenge verbatim to us.
   #
   #  Parameter:
   #      Socket      - Socket open on the client.
   #  Returns:
   #      1           - success.
   #      0           - failure (e.g.mismatch or insecure not allowed).
   #
   sub InsecureConnection {
       my $Socket  =  shift;
   
       #   Don't even start if insecure connections are not allowed.
   
       if(! $perlvar{londAllowInsecure}) { # Insecure connections not allowed.
    return 0;
       }
   
       #   Fabricate a challenge string and send it..
   
       my $challenge = "$$".time; # pid + time.
       print $Socket "$challenge\n";
       &status("Waiting for challenge reply");
   
       my $answer = <$Socket>;
       $answer    =~s/\W//g;
       if($challenge eq $answer) {
    return 1;
       } 
       else {
    logthis("<font color='blue'>WARNING client did not respond to challenge</font>");
    &status("No challenge reqply");
    return 0;
       }
       
   
   }
   
 #  #
 #   GetCertificate: Given a transaction that requires a certificate,  #   GetCertificate: Given a transaction that requires a certificate,
 #   this function will extract the certificate from the transaction  #   this function will extract the certificate from the transaction
Line 208  sub GetCertificate { Line 314  sub GetCertificate {
     return $clientip;      return $clientip;
 }  }
   
   #
   #   Return true if client is a manager.
   #
   sub isManager {
       return (($ConnectionType eq "manager") || ($ConnectionType eq "both"));
   }
   #
   #   Return tru if client can do client functions
   #
   sub isClient {
       return (($ConnectionType eq "client") || ($ConnectionType eq "both"));
   }
   
   
   #
   #   ReadManagerTable: Reads in the current manager table. For now this is
   #                     done on each manager authentication because:
   #                     - These authentications are not frequent
   #                     - This allows dynamic changes to the manager table
   #                       without the need to signal to the lond.
   #
   
   sub ReadManagerTable {
   
       #   Clean out the old table first..
   
      foreach my $key (keys %managers) {
         delete $managers{$key};
      }
   
      my $tablename = $perlvar{'lonTabDir'}."/managers.tab";
      if (!open (MANAGERS, $tablename)) {
         logthis('<font color="red">No manager table.  Nobody can manage!!</font>');
         return;
      }
      while(my $host = <MANAGERS>) {
         chomp($host);
         if ($host =~ "^#") {                  # Comment line.
            logthis('<font color="green"> Skipping line: '. "$host</font>\n");
            next;
         }
         if (!defined $hostip{$host}) { # This is a non cluster member
       #  The entry is of the form:
       #    cluname:hostname
       #  cluname - A 'cluster hostname' is needed in order to negotiate
       #            the host key.
       #  hostname- The dns name of the host.
       #
             my($cluname, $dnsname) = split(/:/, $host);
             
             my $ip = gethostbyname($dnsname);
             if(defined($ip)) {                 # bad names don't deserve entry.
               my $hostip = inet_ntoa($ip);
               $managers{$hostip} = $cluname;
               logthis('<font color="green"> registering manager '.
                       "$dnsname as $cluname with $hostip </font>\n");
            }
         } else {
            logthis('<font color="green"> existing host'." $host</font>\n");
            $managers{$hostip{$host}} = $host;  # Use info from cluster tab if clumemeber
         }
      }
   }
   
 #  #
 #  ValidManager: Determines if a given certificate represents a valid manager.  #  ValidManager: Determines if a given certificate represents a valid manager.
Line 219  sub GetCertificate { Line 388  sub GetCertificate {
 sub ValidManager {  sub ValidManager {
     my $certificate = shift;       my $certificate = shift; 
   
     my $hostentry   = $hostid{$certificate};      return isManager;
     if ($hostentry ne undef) {  
  &logthis('<font color="yellow">Authenticating manager'.  
  " $hostentry</font>");  
  return 1;  
     } else {  
  &logthis('<font color="red"> Failed manager authentication '.  
  "$certificate </font>");  
     }  
 }  }
 #  #
 #  CopyFile:  Called as part of the process of installing a   #  CopyFile:  Called as part of the process of installing a 
Line 241  sub ValidManager { Line 402  sub ValidManager {
 #     1   - Success.  #     1   - Success.
 #  #
 sub CopyFile {  sub CopyFile {
     my $oldfile = shift;  
     my $newfile = shift;      my ($oldfile, $newfile) = @_;
   
     #  The file must exist:      #  The file must exist:
   
Line 278  sub CopyFile { Line 439  sub CopyFile {
  return 0;   return 0;
     }      }
 }  }
   #
   #  Host files are passed out with externally visible host IPs.
   #  If, for example, we are behind a fire-wall or NAT host, our 
   #  internally visible IP may be different than the externally
   #  visible IP.  Therefore, we always adjust the contents of the
   #  host file so that the entry for ME is the IP that we believe
   #  we have.  At present, this is defined as the entry that
   #  DNS has for us.  If by some chance we are not able to get a
   #  DNS translation for us, then we assume that the host.tab file
   #  is correct.  
   #    BUGBUGBUG - in the future, we really should see if we can
   #       easily query the interface(s) instead.
   # Parameter(s):
   #     contents    - The contents of the host.tab to check.
   # Returns:
   #     newcontents - The adjusted contents.
   #
   #
   sub AdjustHostContents {
       my $contents  = shift;
       my $adjusted;
       my $me        = $perlvar{'lonHostID'};
   
    foreach my $line (split(/\n/,$contents)) {
    if(!(($line eq "") || ($line =~ /^ *\#/) || ($line =~ /^ *$/))) {
       chomp($line);
       my ($id,$domain,$role,$name,$ip,$maxcon,$idleto,$mincon)=split(/:/,$line);
       if ($id eq $me) {
             my $ip = gethostbyname($name);
             my $ipnew = inet_ntoa($ip);
            $ip = $ipnew;
    #  Reconstruct the host line and append to adjusted:
   
      my $newline = "$id:$domain:$role:$name:$ip";
      if($maxcon ne "") { # Not all hosts have loncnew tuning params
        $newline .= ":$maxcon:$idleto:$mincon";
      }
      $adjusted .= $newline."\n";
   
         } else { # Not me, pass unmodified.
      $adjusted .= $line."\n";
         }
    } else {                  # Blank or comment never re-written.
       $adjusted .= $line."\n"; # Pass blanks and comments as is.
    }
    }
    return $adjusted;
   }
 #  #
 #   InstallFile: Called to install an administrative file:  #   InstallFile: Called to install an administrative file:
 #       - The file is created with <name>.tmp  #       - The file is created with <name>.tmp
Line 295  sub CopyFile { Line 503  sub CopyFile {
 #      0       - failure and $! has an errno.  #      0       - failure and $! has an errno.
 #  #
 sub InstallFile {  sub InstallFile {
     my $Filename = shift;  
     my $Contents = shift;      my ($Filename, $Contents) = @_;
     my $TempFile = $Filename.".tmp";      my $TempFile = $Filename.".tmp";
   
     #  Open the file for write:      #  Open the file for write:
Line 320  sub InstallFile { Line 528  sub InstallFile {
     return 1;      return 1;
 }  }
   
   
   #
   #   ConfigFileFromSelector: converts a configuration file selector
   #                 (one of host or domain at this point) into a 
   #                 configuration file pathname.
   #
   #  Parameters:
   #      selector  - Configuration file selector.
   #  Returns:
   #      Full path to the file or undef if the selector is invalid.
   #
   sub ConfigFileFromSelector {
       my $selector   = shift;
       my $tablefile;
   
       my $tabledir = $perlvar{'lonTabDir'}.'/';
       if ($selector eq "hosts") {
    $tablefile = $tabledir."hosts.tab";
       } elsif ($selector eq "domain") {
    $tablefile = $tabledir."domain.tab";
       } else {
    return undef;
       }
       return $tablefile;
   
   }
 #  #
 #   PushFile:  Called to do an administrative push of a file.  #   PushFile:  Called to do an administrative push of a file.
 #              - Ensure the file being pushed is one we support.  #              - Ensure the file being pushed is one we support.
Line 349  sub PushFile { Line 583  sub PushFile {
     # part of some elaborate spoof that managed somehow to authenticate.      # part of some elaborate spoof that managed somehow to authenticate.
     #      #
   
     my $tablefile = $perlvar{'lonTabDir'}.'/'; # need to precede with dir.  
     if ($filename eq "host") {      my $tablefile = ConfigFileFromSelector($filename);
  $tablefile .= "hosts.tab";      if(! (defined $tablefile)) {
     } elsif ($filename eq "domain") {  
  $tablefile .= "domain.tab";  
     } else {  
  return "refused";   return "refused";
     }      }
     #      #
Line 371  sub PushFile { Line 602  sub PushFile {
     &logthis('<font color="green"> Pushfile: backed up '      &logthis('<font color="green"> Pushfile: backed up '
     .$tablefile." to $backupfile</font>");      .$tablefile." to $backupfile</font>");
           
       #  If the file being pushed is the host file, we adjust the entry for ourself so that the
       #  IP will be our current IP as looked up in dns.  Note this is only 99% good as it's possible
       #  to conceive of conditions where we don't have a DNS entry locally.  This is possible in a 
       #  network sense but it doesn't make much sense in a LonCAPA sense so we ignore (for now)
       #  that possibilty.
   
       if($filename eq "host") {
    $contents = AdjustHostContents($contents);
       }
   
     #  Install the new file:      #  Install the new file:
   
     if(!InstallFile($tablefile, $contents)) {      if(!InstallFile($tablefile, $contents)) {
Line 436  sub ReinitProcess { Line 677  sub ReinitProcess {
     }      }
     return 'ok';      return 'ok';
 }  }
   #   Validate a line in a configuration file edit script:
   #   Validation includes:
   #     - Ensuring the command is valid.
   #     - Ensuring the command has sufficient parameters
   #   Parameters:
   #     scriptline - A line to validate (\n has been stripped for what it's worth).
   #
   #   Return:
   #      0     - Invalid scriptline.
   #      1     - Valid scriptline
   #  NOTE:
   #     Only the command syntax is checked, not the executability of the
   #     command.
   #
   sub isValidEditCommand {
       my $scriptline = shift;
   
       #   Line elements are pipe separated:
   
       my ($command, $key, $newline)  = split(/\|/, $scriptline);
       &logthis('<font color="green"> isValideditCommand checking: '.
        "Command = '$command', Key = '$key', Newline = '$newline' </font>\n");
       
       if ($command eq "delete") {
    #
    #   key with no newline.
    #
    if( ($key eq "") || ($newline ne "")) {
       return 0; # Must have key but no newline.
    } else {
       return 1; # Valid syntax.
    }
       } elsif ($command eq "replace") {
    #
    #   key and newline:
    #
    if (($key eq "") || ($newline eq "")) {
       return 0;
    } else {
       return 1;
    }
       } elsif ($command eq "append") {
    if (($key ne "") && ($newline eq "")) {
       return 1;
    } else {
       return 0;
    }
       } else {
    return 0; # Invalid command.
       }
       return 0; # Should not get here!!!
   }
   #
   #   ApplyEdit - Applies an edit command to a line in a configuration 
   #               file.  It is the caller's responsiblity to validate the
   #               edit line.
   #   Parameters:
   #      $directive - A single edit directive to apply.  
   #                   Edit directives are of the form:
   #                  append|newline      - Appends a new line to the file.
   #                  replace|key|newline - Replaces the line with key value 'key'
   #                  delete|key          - Deletes the line with key value 'key'.
   #      $editor   - A config file editor object that contains the
   #                  file being edited.
   #
   sub ApplyEdit {
   
       my ($directive, $editor) = @_;
   
       # Break the directive down into its command and its parameters
       # (at most two at this point.  The meaning of the parameters, if in fact
       #  they exist depends on the command).
   
       my ($command, $p1, $p2) = split(/\|/, $directive);
   
       if($command eq "append") {
    $editor->Append($p1);          # p1 - key p2 null.
       } elsif ($command eq "replace") {
    $editor->ReplaceLine($p1, $p2);   # p1 - key p2 = newline.
       } elsif ($command eq "delete") {
    $editor->DeleteLine($p1);         # p1 - key p2 null.
       } else {          # Should not get here!!!
    die "Invalid command given to ApplyEdit $command"
       }
   }
   #
   # AdjustOurHost:
   #           Adjusts a host file stored in a configuration file editor object
   #           for the true IP address of this host. This is necessary for hosts
   #           that live behind a firewall.
   #           Those hosts have a publicly distributed IP of the firewall, but
   #           internally must use their actual IP.  We assume that a given
   #           host only has a single IP interface for now.
   # Formal Parameters:
   #     editor   - The configuration file editor to adjust.  This
   #                editor is assumed to contain a hosts.tab file.
   # Strategy:
   #    - Figure out our hostname.
   #    - Lookup the entry for this host.
   #    - Modify the line to contain our IP
   #    - Do a replace for this host.
   sub AdjustOurHost {
       my $editor        = shift;
   
       # figure out who I am.
   
       my $myHostName    = $perlvar{'lonHostID'}; # LonCAPA hostname.
   
       #  Get my host file entry.
   
       my $ConfigLine    = $editor->Find($myHostName);
       if(! (defined $ConfigLine)) {
    die "AdjustOurHost - no entry for me in hosts file $myHostName";
       }
       # figure out my IP:
       #   Use the config line to get my hostname.
       #   Use gethostbyname to translate that into an IP address.
       #
       my ($id,$domain,$role,$name,$ip,$maxcon,$idleto,$mincon) = split(/:/,$ConfigLine);
       my $BinaryIp = gethostbyname($name);
       my $ip       = inet_ntoa($ip);
       #
       #  Reassemble the config line from the elements in the list.
       #  Note that if the loncnew items were not present before, they will
       #  be now even if they would be empty
       #
       my $newConfigLine = $id;
       foreach my $item ($domain, $role, $name, $ip, $maxcon, $idleto, $mincon) {
    $newConfigLine .= ":".$item;
       }
       #  Replace the line:
   
       $editor->ReplaceLine($id, $newConfigLine);
       
   }
   #
   #   ReplaceConfigFile:
   #              Replaces a configuration file with the contents of a
   #              configuration file editor object.
   #              This is done by:
   #              - Copying the target file to <filename>.old
   #              - Writing the new file to <filename>.tmp
   #              - Moving <filename.tmp>  -> <filename>
   #              This laborious process ensures that the system is never without
   #              a configuration file that's at least valid (even if the contents
   #              may be dated).
   #   Parameters:
   #        filename   - Name of the file to modify... this is a full path.
   #        editor     - Editor containing the file.
   #
   sub ReplaceConfigFile {
       
       my ($filename, $editor) = @_;
   
       CopyFile ($filename, $filename.".old");
   
       my $contents  = $editor->Get(); # Get the contents of the file.
   
       InstallFile($filename, $contents);
   }
   #   
   #
   #   Called to edit a configuration table  file
   #   Parameters:
   #      request           - The entire command/request sent by lonc or lonManage
   #   Return:
   #      The reply to send to the client.
   #
   sub EditFile {
       my $request = shift;
   
       #  Split the command into it's pieces:  edit:filetype:script
   
       my ($request, $filetype, $script) = split(/:/, $request,3); # : in script
   
       #  Check the pre-coditions for success:
   
       if($request != "edit") { # Something is amiss afoot alack.
    return "error:edit request detected, but request != 'edit'\n";
       }
       if( ($filetype ne "hosts")  &&
    ($filetype ne "domain")) {
    return "error:edit requested with invalid file specifier: $filetype \n";
       }
   
       #   Split the edit script and check it's validity.
   
       my @scriptlines = split(/\n/, $script);  # one line per element.
       my $linecount   = scalar(@scriptlines);
       for(my $i = 0; $i < $linecount; $i++) {
    chomp($scriptlines[$i]);
    if(!isValidEditCommand($scriptlines[$i])) {
       return "error:edit with bad script line: '$scriptlines[$i]' \n";
    }
       }
   
       #   Execute the edit operation.
       #   - Create a config file editor for the appropriate file and 
       #   - execute each command in the script:
       #
       my $configfile = ConfigFileFromSelector($filetype);
       if (!(defined $configfile)) {
    return "refused\n";
       }
       my $editor = ConfigFileEdit->new($configfile);
   
       for (my $i = 0; $i < $linecount; $i++) {
    ApplyEdit($scriptlines[$i], $editor);
       }
       # If the file is the host file, ensure that our host is
       # adjusted to have our ip:
       #
       if($filetype eq "host") {
    AdjustOurHost($editor);
       }
       #  Finally replace the current file with our file.
       #
       ReplaceConfigFile($configfile, $editor);
   
       return "ok\n";
   }
 #  #
 #  Convert an error return code from lcpasswd to a string value.  #  Convert an error return code from lcpasswd to a string value.
 #  #
Line 466  sub catchexception { Line 927  sub catchexception {
     my ($error)=@_;      my ($error)=@_;
     $SIG{'QUIT'}='DEFAULT';      $SIG{'QUIT'}='DEFAULT';
     $SIG{__DIE__}='DEFAULT';      $SIG{__DIE__}='DEFAULT';
     &logthis("<font color=red>CRITICAL: "      &status("Catching exception");
       &logthis("<font color='red'>CRITICAL: "
      ."ABNORMAL EXIT. Child $$ for server $thisserver died through "       ."ABNORMAL EXIT. Child $$ for server $thisserver died through "
      ."a crash with this error msg->[$error]</font>");       ."a crash with this error msg->[$error]</font>");
     &logthis('Famous last words: '.$status.' - '.$lastlog);      &logthis('Famous last words: '.$status.' - '.$lastlog);
Line 476  sub catchexception { Line 938  sub catchexception {
 }  }
   
 sub timeout {  sub timeout {
     &logthis("<font color=ref>CRITICAL: TIME OUT ".$$."</font>");      &status("Handling Timeout");
       &logthis("<font color='red'>CRITICAL: TIME OUT ".$$."</font>");
     &catchexception('Timeout');      &catchexception('Timeout');
 }  }
 # -------------------------------- Set signal handlers to record abnormal exits  # -------------------------------- Set signal handlers to record abnormal exits
Line 528  $server = IO::Socket::INET->new(LocalPor Line 991  $server = IO::Socket::INET->new(LocalPor
 # global variables  # global variables
   
 my %children               = ();       # keys are current child process IDs  my %children               = ();       # keys are current child process IDs
 my $children               = 0;        # current number of children  
   
 sub REAPER {                        # takes care of dead children  sub REAPER {                        # takes care of dead children
     $SIG{CHLD} = \&REAPER;      $SIG{CHLD} = \&REAPER;
     my $pid = wait;      &status("Handling child death");
     if (defined($children{$pid})) {      my $pid;
  &logthis("Child $pid died");      do {
  $children --;   $pid = waitpid(-1,&WNOHANG());
  delete $children{$pid};   if (defined($children{$pid})) {
     } else {      &logthis("Child $pid died");
  &logthis("Unknown Child $pid died");      delete($children{$pid});
    } elsif ($pid > 0) {
       &logthis("Unknown Child $pid died");
    }
       } while ( $pid > 0 );
       foreach my $child (keys(%children)) {
    $pid = waitpid($child,&WNOHANG());
    if ($pid > 0) {
       &logthis("Child $child - $pid looks like we missed it's death");
       delete($children{$pid});
    }
     }      }
       &status("Finished Handling child death");
 }  }
   
 sub HUNTSMAN {                      # signal handler for SIGINT  sub HUNTSMAN {                      # signal handler for SIGINT
       &status("Killing children (INT)");
     local($SIG{CHLD}) = 'IGNORE';   # we're going to kill our children      local($SIG{CHLD}) = 'IGNORE';   # we're going to kill our children
     kill 'INT' => keys %children;      kill 'INT' => keys %children;
     &logthis("Free socket: ".shutdown($server,2)); # free up socket      &logthis("Free socket: ".shutdown($server,2)); # free up socket
     my $execdir=$perlvar{'lonDaemons'};      my $execdir=$perlvar{'lonDaemons'};
     unlink("$execdir/logs/lond.pid");      unlink("$execdir/logs/lond.pid");
     &logthis("<font color=red>CRITICAL: Shutting down</font>");      &logthis("<font color='red'>CRITICAL: Shutting down</font>");
       &status("Done killing children");
     exit;                           # clean up with dignity      exit;                           # clean up with dignity
 }  }
   
 sub HUPSMAN {                      # signal handler for SIGHUP  sub HUPSMAN {                      # signal handler for SIGHUP
     local($SIG{CHLD}) = 'IGNORE';  # we're going to kill our children      local($SIG{CHLD}) = 'IGNORE';  # we're going to kill our children
       &status("Killing children for restart (HUP)");
     kill 'INT' => keys %children;      kill 'INT' => keys %children;
     &logthis("Free socket: ".shutdown($server,2)); # free up socket      &logthis("Free socket: ".shutdown($server,2)); # free up socket
     &logthis("<font color=red>CRITICAL: Restarting</font>");      &logthis("<font color='red'>CRITICAL: Restarting</font>");
     my $execdir=$perlvar{'lonDaemons'};      my $execdir=$perlvar{'lonDaemons'};
     unlink("$execdir/logs/lond.pid");      unlink("$execdir/logs/lond.pid");
       &status("Restarting self (HUP)");
     exec("$execdir/lond");         # here we go again      exec("$execdir/lond");         # here we go again
 }  }
   
 #  #
 #    Kill off hashes that describe the host table prior to re-reading it.  #    Kill off hashes that describe the host table prior to re-reading it.
 #    Hashes affected are:  #    Hashes affected are:
 #       %hostid, %hostdom %hostip  #       %hostid, %hostdom %hostip %hostdns.
 #  #
 sub KillHostHashes {  sub KillHostHashes {
     foreach my $key (keys %hostid) {      foreach my $key (keys %hostid) {
Line 577  sub KillHostHashes { Line 1054  sub KillHostHashes {
     foreach my $key (keys %hostip) {      foreach my $key (keys %hostip) {
  delete $hostip{$key};   delete $hostip{$key};
     }      }
       foreach my $key (keys %hostdns) {
    delete $hostdns{$key};
       }
 }  }
 #  #
 #   Read in the host table from file and distribute it into the various hashes:  #   Read in the host table from file and distribute it into the various hashes:
Line 587  sub KillHostHashes { Line 1067  sub KillHostHashes {
 sub ReadHostTable {  sub ReadHostTable {
   
     open (CONFIG,"$perlvar{'lonTabDir'}/hosts.tab") || die "Can't read host file";      open (CONFIG,"$perlvar{'lonTabDir'}/hosts.tab") || die "Can't read host file";
           my $myloncapaname = $perlvar{'lonHostID'};
       Debug("My loncapa name is : $myloncapaname");
     while (my $configline=<CONFIG>) {      while (my $configline=<CONFIG>) {
  my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);   if (!($configline =~ /^\s*\#/)) {
  chomp($ip); $ip=~s/\D+$//;      my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
  $hostid{$ip}=$id;      chomp($ip); $ip=~s/\D+$//;
  $hostdom{$id}=$domain;      $hostid{$ip}=$id;         # LonCAPA name of host by IP.
  $hostip{$id}=$ip;      $hostdom{$id}=$domain;    # LonCAPA domain name of host. 
  if ($id eq $perlvar{'lonHostID'}) { $thisserver=$name; }      $hostip{$id}=$ip;      # IP address of host.
       $hostdns{$name} = $id;    # LonCAPA name of host by DNS.
   
       if ($id eq $perlvar{'lonHostID'}) { 
    Debug("Found me in the host table: $name");
    $thisserver=$name; 
       }
    }
     }      }
     close(CONFIG);      close(CONFIG);
 }  }
Line 620  sub ReloadApache { Line 1108  sub ReloadApache {
 #     now be honored.  #     now be honored.
 #  #
 sub UpdateHosts {  sub UpdateHosts {
       &status("Reload hosts.tab");
     logthis('<font color="blue"> Updating connections </font>');      logthis('<font color="blue"> Updating connections </font>');
     #      #
     #  The %children hash has the set of IP's we currently have children      #  The %children hash has the set of IP's we currently have children
Line 644  sub UpdateHosts { Line 1133  sub UpdateHosts {
  }   }
     }      }
     ReloadApache;      ReloadApache;
       &status("Finished reloading hosts.tab");
 }  }
   
   
 sub checkchildren {  sub checkchildren {
       &status("Checking on the children (sending signals)");
     &initnewstatus();      &initnewstatus();
     &logstatus();      &logstatus();
     &logthis('Going to check on the children');      &logthis('Going to check on the children');
Line 662  sub checkchildren { Line 1153  sub checkchildren {
     sleep 5;      sleep 5;
     $SIG{ALRM} = sub { die "timeout" };      $SIG{ALRM} = sub { die "timeout" };
     $SIG{__DIE__} = 'DEFAULT';      $SIG{__DIE__} = 'DEFAULT';
       &status("Checking on the children (waiting for reports)");
     foreach (sort keys %children) {      foreach (sort keys %children) {
         unless (-e "$docdir/lon-status/londchld/$_.txt") {          unless (-e "$docdir/lon-status/londchld/$_.txt") {
           eval {            eval {
Line 678  sub checkchildren { Line 1170  sub checkchildren {
         }          }
     }      }
     $SIG{ALRM} = 'DEFAULT';      $SIG{ALRM} = 'DEFAULT';
     $SIG{__DIE__} = \&catchcexception;      $SIG{__DIE__} = \&catchexception;
       &status("Finished checking children");
 }  }
   
 # --------------------------------------------------------------------- Logging  # --------------------------------------------------------------------- Logging
Line 700  sub Debug { Line 1193  sub Debug {
  &logthis($message);   &logthis($message);
     }      }
 }  }
   
   #
   #   Sub to do replies to client.. this gives a hook for some
   #   debug tracing too:
   #  Parameters:
   #     fd      - File open on client.
   #     reply   - Text to send to client.
   #     request - Original request from client.
   #
   sub Reply {
   
       my ($fd, $reply, $request) = @_;
   
       print $fd $reply;
       Debug("Request was $request  Reply was $reply");
   
   }
 # ------------------------------------------------------------------ Log status  # ------------------------------------------------------------------ Log status
   
 sub logstatus {  sub logstatus {
       &status("Doing logging");
     my $docdir=$perlvar{'lonDocRoot'};      my $docdir=$perlvar{'lonDocRoot'};
     {      {
     my $fh=IO::File->new(">>$docdir/lon-status/londstatus.txt");      my $fh=IO::File->new(">>$docdir/lon-status/londstatus.txt");
     print $fh $$."\t".$currenthostid."\t".$status."\t".$lastlog."\n";      print $fh $$."\t".$clientname."\t".$currenthostid."\t"
    .$status."\t".$lastlog."\n";
     $fh->close();      $fh->close();
     }      }
       &status("Finished londstatus.txt");
     {      {
  my $fh=IO::File->new(">$docdir/lon-status/londchld/$$.txt");   my $fh=IO::File->new(">$docdir/lon-status/londchld/$$.txt");
         print $fh $status."\n".$lastlog."\n".time;          print $fh $status."\n".$lastlog."\n".time;
         $fh->close();          $fh->close();
     }      }
       &status("Finished logging");
 }  }
   
 sub initnewstatus {  sub initnewstatus {
Line 769  sub reconlonc { Line 1283  sub reconlonc {
             kill USR1 => $loncpid;              kill USR1 => $loncpid;
         } else {          } else {
     &logthis(      &logthis(
               "<font color=red>CRITICAL: "                "<font color='red'>CRITICAL: "
              ."lonc at pid $loncpid not responding, giving up</font>");               ."lonc at pid $loncpid not responding, giving up</font>");
         }          }
     } else {      } else {
       &logthis('<font color=red>CRITICAL: lonc not running, giving up</font>');        &logthis('<font color="red">CRITICAL: lonc not running, giving up</font>');
     }      }
 }  }
   
Line 877  my $execdir=$perlvar{'lonDaemons'}; Line 1391  my $execdir=$perlvar{'lonDaemons'};
 open (PIDSAVE,">$execdir/logs/lond.pid");  open (PIDSAVE,">$execdir/logs/lond.pid");
 print PIDSAVE "$$\n";  print PIDSAVE "$$\n";
 close(PIDSAVE);  close(PIDSAVE);
 &logthis("<font color=red>CRITICAL: ---------- Starting ----------</font>");  &logthis("<font color='red'>CRITICAL: ---------- Starting ----------</font>");
 &status('Starting');  &status('Starting');
   
   
Line 901  ReadHostTable; Line 1415  ReadHostTable;
 #   along the connection.  #   along the connection.
   
 while (1) {  while (1) {
       &status('Starting accept');
     $client = $server->accept() or next;      $client = $server->accept() or next;
       &status('Accepted '.$client.' off to spawn');
     make_new_child($client);      make_new_child($client);
       &status('Finished spawning');
 }  }
   
 sub make_new_child {  sub make_new_child {
Line 911  sub make_new_child { Line 1428  sub make_new_child {
     my $sigset;      my $sigset;
   
     $client = shift;      $client = shift;
     &logthis("Attempting to start child");          &status('Starting new child '.$client);
       &logthis('<font color="green"> Attempting to start child ('.$client.
        ")</font>");    
     # block signal for fork      # block signal for fork
     $sigset = POSIX::SigSet->new(SIGINT);      $sigset = POSIX::SigSet->new(SIGINT);
     sigprocmask(SIG_BLOCK, $sigset)      sigprocmask(SIG_BLOCK, $sigset)
Line 927  sub make_new_child { Line 1446  sub make_new_child {
     #  the pid hash.      #  the pid hash.
     #      #
     my $caller = getpeername($client);      my $caller = getpeername($client);
     my ($port,$iaddr)=unpack_sockaddr_in($caller);      my ($port,$iaddr);
     $clientip=inet_ntoa($iaddr);      if (defined($caller) && length($caller) > 0) {
    ($port,$iaddr)=unpack_sockaddr_in($caller);
       } else {
    &logthis("Unable to determine who caller was, getpeername returned nothing");
       }
       if (defined($iaddr)) {
    $clientip  = inet_ntoa($iaddr);
    Debug("Connected with $clientip");
    $clientdns = gethostbyaddr($iaddr, AF_INET);
    Debug("Connected with $clientdns by name");
       } else {
    &logthis("Unable to determine clientip");
    $clientip='Unavailable';
       }
           
     if ($pid) {      if ($pid) {
         # Parent records the child's birth and returns.          # Parent records the child's birth and returns.
         sigprocmask(SIG_UNBLOCK, $sigset)          sigprocmask(SIG_UNBLOCK, $sigset)
             or die "Can't unblock SIGINT for fork: $!\n";              or die "Can't unblock SIGINT for fork: $!\n";
         $children{$pid} = $clientip;          $children{$pid} = $clientip;
         $children++;  
         &status('Started child '.$pid);          &status('Started child '.$pid);
         return;          return;
     } else {      } else {
Line 957  sub make_new_child { Line 1488  sub make_new_child {
         &Authen::Krb5::init_context();          &Authen::Krb5::init_context();
         &Authen::Krb5::init_ets();          &Authen::Krb5::init_ets();
   
             &status('Accepted connection');   &status('Accepted connection');
 # =============================================================================  # =============================================================================
             # do something with the connection              # do something with the connection
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
  # see if we know client and check for spoof IP by challenge   # see if we know client and 'check' for spoof IP by ineffective challenge
   
             my $clientrec=($hostid{$clientip} ne undef);   ReadManagerTable; # May also be a manager!!
             &logthis(  
 "<font color=yellow>INFO: Connection, $clientip ($hostid{$clientip})</font>"   my $clientrec=($hostid{$clientip}     ne undef);
             );   my $ismanager=($managers{$clientip}    ne undef);
             &status("Connecting $clientip ($hostid{$clientip})");    $clientname  = "[unknonwn]";
             my $clientok;   if($clientrec) { # Establish client type.
             if ($clientrec) {      $ConnectionType = "client";
       &status("Waiting for init from $clientip ($hostid{$clientip})");      $clientname = $hostid{$clientip};
       my $remotereq=<$client>;      if($ismanager) {
               $remotereq=~s/[^\w:]//g;   $ConnectionType = "both";
               if ($remotereq =~ /^init/) {      }
   &sethost("sethost:$perlvar{'lonHostID'}");   } else {
   my $challenge="$$".time;      $ConnectionType = "manager";
                   print $client "$challenge\n";      $clientname = $managers{$clientip};
                   &status(   }
            "Waiting for challenge reply from $clientip ($hostid{$clientip})");    my $clientok;
                   $remotereq=<$client>;  
                   $remotereq=~s/\W//g;   if ($clientrec || $ismanager) {
                   if ($challenge eq $remotereq) {      &status("Waiting for init from $clientip $clientname");
       $clientok=1;      &logthis('<font color="yellow">INFO: Connection, '.
                       print $client "ok\n";       $clientip.
                   } else {    " ($clientname) connection type = $ConnectionType </font>" );
       &logthis(      &status("Connecting $clientip  ($clientname))"); 
  "<font color=blue>WARNING: $clientip did not reply challenge</font>");      my $remotereq=<$client>;
                       &status('No challenge reply '.$clientip);      chomp($remotereq);
                   }      Debug("Got init: $remotereq");
               } else {      my $inikeyword = split(/:/, $remotereq);
   &logthis(      if ($remotereq =~ /^init/) {
                     "<font color=blue>WARNING: "   &sethost("sethost:$perlvar{'lonHostID'}");
                    ."$clientip failed to initialize: >$remotereq< </font>");   #
                   &status('No init '.$clientip);   #  If the remote is attempting a local init... give that a try:
               }   #
     } else {   my ($i, $inittype) = split(/:/, $remotereq);
               &logthis(  
  "<font color=blue>WARNING: Unknown client $clientip</font>");   # If the connection type is ssl, but I didn't get my
               &status('Hung up on '.$clientip);   # certificate files yet, then I'll drop  back to 
             }   # insecure (if allowed).
             if ($clientok) {  
 # ---------------- New known client connecting, could mean machine online again   if($inittype eq "ssl") {
       my ($ca, $cert) = lonssl::CertificateFile;
       my $kfile       = lonssl::KeyFile;
       if((!$ca)   || 
          (!$cert) || 
          (!$kfile)) {
    $inittype = ""; # This forces insecure attempt.
    &logthis("<font color=\"blue\"> Certificates not "
    ."installed -- trying insecure auth</font>");
       }
       else { # SSL certificates are in place so
       } # Leave the inittype alone.
    }
   
  foreach my $id (keys(%hostip)) {   if($inittype eq "local") {
     if ($hostip{$id} ne $clientip ||      my $key = LocalConnection($client, $remotereq);
        $hostip{$currenthostid} eq $clientip) {      if($key) {
  # no need to try to do recon's to myself   Debug("Got local key $key");
  next;   $clientok     = 1;
    my $cipherkey = pack("H32", $key);
    $cipher       = new IDEA($cipherkey);
    print $client "ok:local\n";
    &logthis('<font color="green"'
    . "Successful local authentication </font>");
       } else {
    Debug("Failed to get local key");
    $clientok = 0;
    shutdown($client, 3);
    close $client;
       }
    } elsif ($inittype eq "ssl") {
       my $key = SSLConnection($client);
       if ($key) {
    $clientok = 1;
    my $cipherkey = pack("H32", $key);
    $cipher       = new IDEA($cipherkey);
    &logthis('<font color="green">'
    ."Successfull ssl authentication with $clientname </font>");
        
       } else {
    $clientok = 0;
    close $client;
       }
      
    } else {
       my $ok = InsecureConnection($client);
       if($ok) {
    $clientok = 1;
    &logthis('<font color="green">'
    ."Successful insecure authentication with $clientname </font>");
    print $client "ok\n";
       } else {
    &logthis('<font color="yellow">'
     ."Attempted insecure connection disallowed </font>");
    close $client;
    $clientok = 0;
   
     }      }
     &reconlonc("$perlvar{'lonSockDir'}/$id");  
  }   }
  &logthis("<font color=green>Established connection: $hostid{$clientip}</font>");      } else {
               &status('Will listen to '.$hostid{$clientip});   &logthis(
    "<font color='blue'>WARNING: "
    ."$clientip failed to initialize: >$remotereq< </font>");
    &status('No init '.$clientip);
       }
       
    } else {
       &logthis(
        "<font color='blue'>WARNING: Unknown client $clientip</font>");
       &status('Hung up on '.$clientip);
    }
    
    if ($clientok) {
   # ---------------- New known client connecting, could mean machine online again
       
       foreach my $id (keys(%hostip)) {
    if ($hostip{$id} ne $clientip ||
       $hostip{$currenthostid} eq $clientip) {
       # no need to try to do recon's to myself
       next;
    }
    &reconlonc("$perlvar{'lonSockDir'}/$id");
       }
       &logthis("<font color='green'>Established connection: $clientname</font>");
       &status('Will listen to '.$clientname);
 # ------------------------------------------------------------ Process requests  # ------------------------------------------------------------ Process requests
               while (my $userinput=<$client>) {      while (my $userinput=<$client>) {
                 chomp($userinput);                  chomp($userinput);
  Debug("Request = $userinput\n");   Debug("Request = $userinput\n");
                 &status('Processing '.$hostid{$clientip}.': '.$userinput);                  &status('Processing '.$clientname.': '.$userinput);
                 my $wasenc=0;                  my $wasenc=0;
                 alarm(120);                  alarm(120);
 # ------------------------------------------------------------ See if encrypted  # ------------------------------------------------------------ See if encrypted
  if ($userinput =~ /^enc/) {   if ($userinput =~ /^enc/) {
   if ($cipher) {      if ($cipher) {
                     my ($cmd,$cmdlength,$encinput)=split(/:/,$userinput);   my ($cmd,$cmdlength,$encinput)=split(/:/,$userinput);
     $userinput='';   $userinput='';
                     for (my $encidx=0;$encidx<length($encinput);$encidx+=16) {   for (my $encidx=0;$encidx<length($encinput);$encidx+=16) {
                        $userinput.=      $userinput.=
    $cipher->decrypt(   $cipher->decrypt(
                             pack("H16",substr($encinput,$encidx,16))   pack("H16",substr($encinput,$encidx,16))
                            );   );
    }
    $userinput=substr($userinput,0,$cmdlength);
    $wasenc=1;
     }      }
     $userinput=substr($userinput,0,$cmdlength);  
                     $wasenc=1;  
  }   }
       }  
     
 # ------------------------------------------------------------- Normal commands  # ------------------------------------------------------------- Normal commands
 # ------------------------------------------------------------------------ ping  # ------------------------------------------------------------------------ ping
    if ($userinput =~ /^ping/) {   if ($userinput =~ /^ping/) { # client only
                        print $client "$currenthostid\n";      if(isClient) {
    print $client "$currenthostid\n";
       } else {
    Reply($client, "refused\n", $userinput);
       }
 # ------------------------------------------------------------------------ pong  # ------------------------------------------------------------------------ pong
    }elsif ($userinput =~ /^pong/) {   }elsif ($userinput =~ /^pong/) { # client only
                        my $reply=&reply("ping",$hostid{$clientip});      if(isClient) {
                        print $client "$currenthostid:$reply\n";    my $reply=&reply("ping",$clientname);
    print $client "$currenthostid:$reply\n"; 
       } else {
    Reply($client, "refused\n", $userinput);
       }
 # ------------------------------------------------------------------------ ekey  # ------------------------------------------------------------------------ ekey
    } elsif ($userinput =~ /^ekey/) {   } elsif ($userinput =~ /^ekey/) { # ok for both clients & mgrs
                        my $buildkey=time.$$.int(rand 100000);      my $buildkey=time.$$.int(rand 100000);
                        $buildkey=~tr/1-6/A-F/;      $buildkey=~tr/1-6/A-F/;
                        $buildkey=int(rand 100000).$buildkey.int(rand 100000);      $buildkey=int(rand 100000).$buildkey.int(rand 100000);
                        my $key=$currenthostid.$hostid{$clientip};      my $key=$currenthostid.$clientname;
                        $key=~tr/a-z/A-Z/;      $key=~tr/a-z/A-Z/;
                        $key=~tr/G-P/0-9/;      $key=~tr/G-P/0-9/;
                        $key=~tr/Q-Z/0-9/;      $key=~tr/Q-Z/0-9/;
                        $key=$key.$buildkey.$key.$buildkey.$key.$buildkey;      $key=$key.$buildkey.$key.$buildkey.$key.$buildkey;
                        $key=substr($key,0,32);      $key=substr($key,0,32);
                        my $cipherkey=pack("H32",$key);      my $cipherkey=pack("H32",$key);
                        $cipher=new IDEA $cipherkey;      $cipher=new IDEA $cipherkey;
                        print $client "$buildkey\n";       print $client "$buildkey\n"; 
 # ------------------------------------------------------------------------ load  # ------------------------------------------------------------------------ load
    } elsif ($userinput =~ /^load/) {   } elsif ($userinput =~ /^load/) { # client only
                        my $loadavg;      if (isClient) {
                        {   my $loadavg;
                           my $loadfile=IO::File->new('/proc/loadavg');   {
                           $loadavg=<$loadfile>;      my $loadfile=IO::File->new('/proc/loadavg');
                        }      $loadavg=<$loadfile>;
                        $loadavg =~ s/\s.*//g;   }
        my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'};   $loadavg =~ s/\s.*//g;
        print $client "$loadpercent\n";   my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'};
    print $client "$loadpercent\n";
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # -------------------------------------------------------------------- userload  # -------------------------------------------------------------------- userload
    } elsif ($userinput =~ /^userload/) {   } elsif ($userinput =~ /^userload/) { # client only
        my $userloadpercent=&userload();      if(isClient) {
        print $client "$userloadpercent\n";   my $userloadpercent=&userload();
    print $client "$userloadpercent\n";
       } else {
    Reply($client, "refused\n", $userinput);
        
       }
 #  #
 #        Transactions requiring encryption:  #        Transactions requiring encryption:
 #  #
 # ----------------------------------------------------------------- currentauth  # ----------------------------------------------------------------- currentauth
    } elsif ($userinput =~ /^currentauth/) {   } elsif ($userinput =~ /^currentauth/) {
      if ($wasenc==1) {      if (($wasenc==1)  && isClient) { # Encoded & client only.
                        my ($cmd,$udom,$uname)=split(/:/,$userinput);   my ($cmd,$udom,$uname)=split(/:/,$userinput);
        my $result = GetAuthType($udom, $uname);   my $result = GetAuthType($udom, $uname);
        if($result eq "nouser") {   if($result eq "nouser") {
    print $client "unknown_user\n";      print $client "unknown_user\n";
        }   }
        else {   else {
    print $client "$result\n"      print $client "$result\n"
        }      }
      } else {      } else {
        print $client "refused\n";   Reply($client, "refused\n", $userinput);
      }  
       }
 #--------------------------------------------------------------------- pushfile  #--------------------------------------------------------------------- pushfile
    } elsif($userinput =~ /^pushfile/) {    } elsif($userinput =~ /^pushfile/) { # encoded & manager.
        if($wasenc == 1) {      if(($wasenc == 1) && isManager) {
    my $cert = GetCertificate($userinput);   my $cert = GetCertificate($userinput);
    if(ValidManager($cert)) {   if(ValidManager($cert)) {
        my $reply = PushFile($userinput);      my $reply = PushFile($userinput);
        print $client "$reply\n";      print $client "$reply\n";
    } else {   } else {
        print $client "refused\n";      print $client "refused\n";
    }    } 
        } else {      } else {
    print $client "refused\n";   Reply($client, "refused\n", $userinput);
        }  
       }
 #--------------------------------------------------------------------- reinit  #--------------------------------------------------------------------- reinit
    } elsif($userinput =~ /^reinit/) {   } elsif($userinput =~ /^reinit/) { # Encoded and manager
        if ($wasenc == 1) {   if (($wasenc == 1) && isManager) {
    my $cert = GetCertificate($userinput);   my $cert = GetCertificate($userinput);
    if(ValidManager($cert)) {   if(ValidManager($cert)) {
        chomp($userinput);   chomp($userinput);
        my $reply = ReinitProcess($userinput);   my $reply = ReinitProcess($userinput);
        print $client  "$reply\n";   print $client  "$reply\n";
    } else {   } else {
        print $client "refused\n";   print $client "refused\n";
    }   }
        } else {   } else {
    print $client "refused\n";   Reply($client, "refused\n", $userinput);
        }   }
   #------------------------------------------------------------------------- edit
       } elsif ($userinput =~ /^edit/) {    # encoded and manager:
    if(($wasenc ==1) && (isManager)) {
       my $cert = GetCertificate($userinput);
       if(ValidManager($cert)) {
                  my($command, $filetype, $script) = split(/:/, $userinput);
                  if (($filetype eq "hosts") || ($filetype eq "domain")) {
                     if($script ne "") {
         Reply($client, EditFile($userinput));
                     } else {
                        Reply($client,"refused\n",$userinput);
                     }
                  } else {
                     Reply($client,"refused\n",$userinput);
                  }
               } else {
                  Reply($client,"refused\n",$userinput);
               }
            } else {
        Reply($client,"refused\n",$userinput);
    }
 # ------------------------------------------------------------------------ auth  # ------------------------------------------------------------------------ auth
                    } elsif ($userinput =~ /^auth/) {      } elsif ($userinput =~ /^auth/) { # Encoded and client only.
      if ($wasenc==1) {      if (($wasenc==1) && isClient) {
                        my ($cmd,$udom,$uname,$upass)=split(/:/,$userinput);   my ($cmd,$udom,$uname,$upass)=split(/:/,$userinput);
                        chomp($upass);   chomp($upass);
                        $upass=unescape($upass);   $upass=unescape($upass);
                        my $proname=propath($udom,$uname);   my $proname=propath($udom,$uname);
                        my $passfilename="$proname/passwd";   my $passfilename="$proname/passwd";
                        if (-e $passfilename) {   if (-e $passfilename) {
                           my $pf = IO::File->new($passfilename);      my $pf = IO::File->new($passfilename);
                           my $realpasswd=<$pf>;      my $realpasswd=<$pf>;
                           chomp($realpasswd);      chomp($realpasswd);
                           my ($howpwd,$contentpwd)=split(/:/,$realpasswd);      my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
                           my $pwdcorrect=0;      my $pwdcorrect=0;
                           if ($howpwd eq 'internal') {      if ($howpwd eq 'internal') {
       &Debug("Internal auth");   &Debug("Internal auth");
       $pwdcorrect=   $pwdcorrect=
   (crypt($upass,$contentpwd) eq $contentpwd);      (crypt($upass,$contentpwd) eq $contentpwd);
                           } elsif ($howpwd eq 'unix') {      } elsif ($howpwd eq 'unix') {
       &Debug("Unix auth");   &Debug("Unix auth");
                               if((getpwnam($uname))[1] eq "") { #no such user!   if((getpwnam($uname))[1] eq "") { #no such user!
   $pwdcorrect = 0;      $pwdcorrect = 0;
       } else {   } else {
   $contentpwd=(getpwnam($uname))[1];      $contentpwd=(getpwnam($uname))[1];
   my $pwauth_path="/usr/local/sbin/pwauth";      my $pwauth_path="/usr/local/sbin/pwauth";
   unless ($contentpwd eq 'x') {      unless ($contentpwd eq 'x') {
       $pwdcorrect=   $pwdcorrect=
   (crypt($upass,$contentpwd) eq       (crypt($upass,$contentpwd) eq 
    $contentpwd);       $contentpwd);
   }      }
         
       elsif (-e $pwauth_path) {      elsif (-e $pwauth_path) {
   open PWAUTH, "|$pwauth_path" or   open PWAUTH, "|$pwauth_path" or
       die "Cannot invoke authentication";      die "Cannot invoke authentication";
   print PWAUTH "$uname\n$upass\n";   print PWAUTH "$uname\n$upass\n";
   close PWAUTH;   close PWAUTH;
   $pwdcorrect=!$?;   $pwdcorrect=!$?;
       }      }
       }   }
                           } elsif ($howpwd eq 'krb4') {      } elsif ($howpwd eq 'krb4') {
                               my $null=pack("C",0);   my $null=pack("C",0);
                               unless ($upass=~/$null/) {   unless ($upass=~/$null/) {
                                   my $krb4_error = &Authen::Krb4::get_pw_in_tkt      my $krb4_error = &Authen::Krb4::get_pw_in_tkt
                                       ($uname,"",$contentpwd,'krbtgt',   ($uname,"",$contentpwd,'krbtgt',
                                        $contentpwd,1,$upass);   $contentpwd,1,$upass);
                                   if (!$krb4_error) {      if (!$krb4_error) {
                                       $pwdcorrect = 1;   $pwdcorrect = 1;
                                   } else {       } else { 
                                       $pwdcorrect=0;    $pwdcorrect=0; 
                                       # log error if it is not a bad password   # log error if it is not a bad password
                                       if ($krb4_error != 62) {   if ($krb4_error != 62) {
        &logthis('krb4:'.$uname.','.$contentpwd.','.      &logthis('krb4:'.$uname.','.
                 &Authen::Krb4::get_err_txt($Authen::Krb4::error));       &Authen::Krb4::get_err_txt($Authen::Krb4::error));
                                       }   }
                                   }      }
                               }   }
                           } elsif ($howpwd eq 'krb5') {      } elsif ($howpwd eq 'krb5') {
       my $null=pack("C",0);   my $null=pack("C",0);
       unless ($upass=~/$null/) {   unless ($upass=~/$null/) {
   my $krbclient=&Authen::Krb5::parse_name($uname.'@'.$contentpwd);      my $krbclient=&Authen::Krb5::parse_name($uname.'@'.$contentpwd);
   my $krbservice="krbtgt/".$contentpwd."\@".$contentpwd;      my $krbservice="krbtgt/".$contentpwd."\@".$contentpwd;
   my $krbserver=&Authen::Krb5::parse_name($krbservice);      my $krbserver=&Authen::Krb5::parse_name($krbservice);
   my $credentials=&Authen::Krb5::cc_default();      my $credentials=&Authen::Krb5::cc_default();
   $credentials->initialize($krbclient);      $credentials->initialize($krbclient);
   my $krbreturn =       my $krbreturn = 
     &Authen::Krb5::get_in_tkt_with_password(   &Authen::Krb5::get_in_tkt_with_password(
      $krbclient,$krbserver,$upass,$credentials);   $krbclient,$krbserver,$upass,$credentials);
 #  unless ($krbreturn) {  #  unless ($krbreturn) {
 #      &logthis("Krb5 Error: ".  #      &logthis("Krb5 Error: ".
 #       &Authen::Krb5::error());  #       &Authen::Krb5::error());
 #  }  #  }
   $pwdcorrect = ($krbreturn == 1);      $pwdcorrect = ($krbreturn == 1);
    } else { $pwdcorrect=0; }   } else { $pwdcorrect=0; }
                           } elsif ($howpwd eq 'localauth') {      } elsif ($howpwd eq 'localauth') {
     $pwdcorrect=&localauth::localauth($uname,$upass,   $pwdcorrect=&localauth::localauth($uname,$upass,
       $contentpwd);    $contentpwd);
   }      }
                           if ($pwdcorrect) {      if ($pwdcorrect) {
                              print $client "authorized\n";   print $client "authorized\n";
                           } else {      } else {
                              print $client "non_authorized\n";   print $client "non_authorized\n";
                           }        }  
        } else {   } else {
                           print $client "unknown_user\n";      print $client "unknown_user\n";
                        }   }
      } else {      } else {
        print $client "refused\n";   Reply($client, "refused\n", $userinput);
      }         
       }
 # ---------------------------------------------------------------------- passwd  # ---------------------------------------------------------------------- passwd
                    } elsif ($userinput =~ /^passwd/) {   } elsif ($userinput =~ /^passwd/) { # encoded and client
      if ($wasenc==1) {      if (($wasenc==1) && isClient) {
                        my    my 
                        ($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput);      ($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput);
                        chomp($npass);   chomp($npass);
                        $upass=&unescape($upass);   $upass=&unescape($upass);
                        $npass=&unescape($npass);   $npass=&unescape($npass);
        &Debug("Trying to change password for $uname");   &Debug("Trying to change password for $uname");
        my $proname=propath($udom,$uname);   my $proname=propath($udom,$uname);
                        my $passfilename="$proname/passwd";   my $passfilename="$proname/passwd";
                        if (-e $passfilename) {   if (-e $passfilename) {
    my $realpasswd;      my $realpasswd;
                           { my $pf = IO::File->new($passfilename);      { my $pf = IO::File->new($passfilename);
     $realpasswd=<$pf>; }        $realpasswd=<$pf>; }
                           chomp($realpasswd);      chomp($realpasswd);
                           my ($howpwd,$contentpwd)=split(/:/,$realpasswd);      my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
                           if ($howpwd eq 'internal') {      if ($howpwd eq 'internal') {
    &Debug("internal auth");   &Debug("internal auth");
    if (crypt($upass,$contentpwd) eq $contentpwd) {   if (crypt($upass,$contentpwd) eq $contentpwd) {
      my $salt=time;      my $salt=time;
                              $salt=substr($salt,6,2);      $salt=substr($salt,6,2);
      my $ncpass=crypt($npass,$salt);      my $ncpass=crypt($npass,$salt);
                              {      {
  my $pf;   my $pf;
  if ($pf = IO::File->new(">$passfilename")) {   if ($pf = IO::File->new(">$passfilename")) {
      print $pf "internal:$ncpass\n";      print $pf "internal:$ncpass\n";
      &logthis("Result of password change for $uname: pwchange_success");      &logthis("Result of password change for $uname: pwchange_success");
      print $client "ok\n";      print $client "ok\n";
  } else {   } else {
      &logthis("Unable to open $uname passwd to change password");      &logthis("Unable to open $uname passwd to change password");
      print $client "non_authorized\n";      print $client "non_authorized\n";
  }   }
      }                   }             
            
                            } else {   } else {
                              print $client "non_authorized\n";      print $client "non_authorized\n";
                            }   }
                           } elsif ($howpwd eq 'unix') {      } elsif ($howpwd eq 'unix') {
       # Unix means we have to access /etc/password   # Unix means we have to access /etc/password
       # one way or another.   # one way or another.
       # First: Make sure the current password is   # First: Make sure the current password is
       #        correct   #        correct
       &Debug("auth is unix");   &Debug("auth is unix");
       $contentpwd=(getpwnam($uname))[1];   $contentpwd=(getpwnam($uname))[1];
       my $pwdcorrect = "0";   my $pwdcorrect = "0";
       my $pwauth_path="/usr/local/sbin/pwauth";   my $pwauth_path="/usr/local/sbin/pwauth";
       unless ($contentpwd eq 'x') {   unless ($contentpwd eq 'x') {
   $pwdcorrect=      $pwdcorrect=
                                     (crypt($upass,$contentpwd) eq $contentpwd);   (crypt($upass,$contentpwd) eq $contentpwd);
       } elsif (-e $pwauth_path) {   } elsif (-e $pwauth_path) {
   open PWAUTH, "|$pwauth_path" or      open PWAUTH, "|$pwauth_path" or
       die "Cannot invoke authentication";   die "Cannot invoke authentication";
   print PWAUTH "$uname\n$upass\n";      print PWAUTH "$uname\n$upass\n";
   close PWAUTH;      close PWAUTH;
   &Debug("exited pwauth with $? ($uname,$upass) ");      &Debug("exited pwauth with $? ($uname,$upass) ");
   $pwdcorrect=($? == 0);      $pwdcorrect=($? == 0);
       }   }
      if ($pwdcorrect) {   if ($pwdcorrect) {
  my $execdir=$perlvar{'lonDaemons'};      my $execdir=$perlvar{'lonDaemons'};
  &Debug("Opening lcpasswd pipeline");      &Debug("Opening lcpasswd pipeline");
  my $pf = IO::File->new("|$execdir/lcpasswd > $perlvar{'lonDaemons'}/logs/lcpasswd.log");      my $pf = IO::File->new("|$execdir/lcpasswd > $perlvar{'lonDaemons'}/logs/lcpasswd.log");
  print $pf "$uname\n$npass\n$npass\n";      print $pf "$uname\n$npass\n$npass\n";
  close $pf;      close $pf;
  my $err = $?;      my $err = $?;
  my $result = ($err>0 ? 'pwchange_failure'       my $result = ($err>0 ? 'pwchange_failure' 
        : 'ok');    : 'ok');
  &logthis("Result of password change for $uname: ".      &logthis("Result of password change for $uname: ".
   &lcpasswdstrerror($?));       &lcpasswdstrerror($?));
  print $client "$result\n";      print $client "$result\n";
      } else {   } else {
  print $client "non_authorized\n";      print $client "non_authorized\n";
      }   }
   } else {      } else {
                             print $client "auth_mode_error\n";   print $client "auth_mode_error\n";
                           }        }  
        } else {   } else {
                           print $client "unknown_user\n";      print $client "unknown_user\n";
                        }   }
      } else {      } else {
        print $client "refused\n";   Reply($client, "refused\n", $userinput);
      }         
       }
 # -------------------------------------------------------------------- makeuser  # -------------------------------------------------------------------- makeuser
                    } elsif ($userinput =~ /^makeuser/) {   } elsif ($userinput =~ /^makeuser/) { # encoded and client.
      &Debug("Make user received");      &Debug("Make user received");
                 my $oldumask=umask(0077);      my $oldumask=umask(0077);
      if ($wasenc==1) {      if (($wasenc==1) && isClient) {
                        my    my 
                        ($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput);      ($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput);
        &Debug("cmd =".$cmd." $udom =".$udom.   &Debug("cmd =".$cmd." $udom =".$udom.
     " uname=".$uname);         " uname=".$uname);
                        chomp($npass);   chomp($npass);
                        $npass=&unescape($npass);   $npass=&unescape($npass);
                        my $proname=propath($udom,$uname);   my $proname=propath($udom,$uname);
                        my $passfilename="$proname/passwd";   my $passfilename="$proname/passwd";
        &Debug("Password file created will be:".   &Debug("Password file created will be:".
     $passfilename);         $passfilename);
                        if (-e $passfilename) {   if (-e $passfilename) {
    print $client "already_exists\n";      print $client "already_exists\n";
                        } elsif ($udom ne $currentdomainid) {   } elsif ($udom ne $currentdomainid) {
                            print $client "not_right_domain\n";      print $client "not_right_domain\n";
                        } else {   } else {
                            my @fpparts=split(/\//,$proname);      my @fpparts=split(/\//,$proname);
                            my $fpnow=$fpparts[0].'/'.$fpparts[1].'/'.$fpparts[2];      my $fpnow=$fpparts[0].'/'.$fpparts[1].'/'.$fpparts[2];
                            my $fperror='';      my $fperror='';
                            for (my $i=3;$i<=$#fpparts;$i++) {      for (my $i=3;$i<=$#fpparts;$i++) {
                                $fpnow.='/'.$fpparts[$i];    $fpnow.='/'.$fpparts[$i]; 
                                unless (-e $fpnow) {   unless (-e $fpnow) {
    unless (mkdir($fpnow,0777)) {      unless (mkdir($fpnow,0777)) {
                                       $fperror="error: ".($!+0)   $fperror="error: ".($!+0)
   ." mkdir failed while attempting "      ." mkdir failed while attempting "
                                               ."makeuser\n";      ."makeuser";
                                    }      }
                                }   }
                            }      }
                            unless ($fperror) {      unless ($fperror) {
        my $result=&make_passwd_file($uname, $umode,$npass,   my $result=&make_passwd_file($uname, $umode,$npass,
     $passfilename);       $passfilename);
        print $client $result;   print $client $result;
                            } else {      } else {
                                print $client "$fperror\n";   print $client "$fperror\n";
                            }      }
                        }   }
      } else {      } else {
        print $client "refused\n";   Reply($client, "refused\n", $userinput);
      }        
      umask($oldumask);      }
       umask($oldumask);
 # -------------------------------------------------------------- changeuserauth  # -------------------------------------------------------------- changeuserauth
                    } elsif ($userinput =~ /^changeuserauth/) {   } elsif ($userinput =~ /^changeuserauth/) { # encoded & client
        &Debug("Changing authorization");      &Debug("Changing authorization");
       if ($wasenc==1) {      if (($wasenc==1) && isClient) {
                        my    my 
        ($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput);      ($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput);
                        chomp($npass);   chomp($npass);
        &Debug("cmd = ".$cmd." domain= ".$udom.   &Debug("cmd = ".$cmd." domain= ".$udom.
       "uname =".$uname." umode= ".$umode);         "uname =".$uname." umode= ".$umode);
                        $npass=&unescape($npass);   $npass=&unescape($npass);
                        my $proname=&propath($udom,$uname);   my $proname=&propath($udom,$uname);
                        my $passfilename="$proname/passwd";   my $passfilename="$proname/passwd";
        if ($udom ne $currentdomainid) {   if ($udom ne $currentdomainid) {
                            print $client "not_right_domain\n";      print $client "not_right_domain\n";
                        } else {   } else {
    my $result=&make_passwd_file($uname, $umode,$npass,      my $result=&make_passwd_file($uname, $umode,$npass,
  $passfilename);   $passfilename);
    print $client $result;      print $client $result;
                        }   }
      } else {      } else {
        print $client "refused\n";   Reply($client, "refused\n", $userinput);
      }     
       }
 # ------------------------------------------------------------------------ home  # ------------------------------------------------------------------------ home
                    } elsif ($userinput =~ /^home/) {   } elsif ($userinput =~ /^home/) { # client clear or encoded
                        my ($cmd,$udom,$uname)=split(/:/,$userinput);      if(isClient) {
                        chomp($uname);   my ($cmd,$udom,$uname)=split(/:/,$userinput);
                        my $proname=propath($udom,$uname);   chomp($uname);
                        if (-e $proname) {   my $proname=propath($udom,$uname);
                           print $client "found\n";   if (-e $proname) {
                        } else {      print $client "found\n";
   print $client "not_found\n";   } else {
                        }      print $client "not_found\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ---------------------------------------------------------------------- update  # ---------------------------------------------------------------------- update
                    } elsif ($userinput =~ /^update/) {   } elsif ($userinput =~ /^update/) { # client clear or encoded.
                        my ($cmd,$fname)=split(/:/,$userinput);      if(isClient) {
                        my $ownership=ishome($fname);   my ($cmd,$fname)=split(/:/,$userinput);
                        if ($ownership eq 'not_owner') {   my $ownership=ishome($fname);
                         if (-e $fname) {   if ($ownership eq 'not_owner') {
                           my ($dev,$ino,$mode,$nlink,      if (-e $fname) {
                               $uid,$gid,$rdev,$size,   my ($dev,$ino,$mode,$nlink,
                               $atime,$mtime,$ctime,      $uid,$gid,$rdev,$size,
                               $blksize,$blocks)=stat($fname);      $atime,$mtime,$ctime,
                           my $now=time;      $blksize,$blocks)=stat($fname);
                           my $since=$now-$atime;   my $now=time;
                           if ($since>$perlvar{'lonExpire'}) {   my $since=$now-$atime;
                               my $reply=   if ($since>$perlvar{'lonExpire'}) {
                                     &reply("unsub:$fname","$hostid{$clientip}");      my $reply=
                               unlink("$fname");   &reply("unsub:$fname","$clientname");
                           } else {      unlink("$fname");
      my $transname="$fname.in.transfer";   } else {
                              my $remoteurl=      my $transname="$fname.in.transfer";
                                     reply("sub:$fname","$hostid{$clientip}");      my $remoteurl=
                              my $response;   &reply("sub:$fname","$clientname");
                               {      my $response;
                              my $ua=new LWP::UserAgent;      {
                              my $request=new HTTP::Request('GET',"$remoteurl");   my $ua=new LWP::UserAgent;
                              $response=$ua->request($request,$transname);   my $request=new HTTP::Request('GET',"$remoteurl");
       }   $response=$ua->request($request,$transname);
                              if ($response->is_error()) {      }
  unlink($transname);      if ($response->is_error()) {
                                  my $message=$response->status_line;   unlink($transname);
                                  &logthis(   my $message=$response->status_line;
                                   "LWP GET: $message for $fname ($remoteurl)");   &logthis(
                              } else {   "LWP GET: $message for $fname ($remoteurl)");
                          if ($remoteurl!~/\.meta$/) {      } else {
                                   my $ua=new LWP::UserAgent;   if ($remoteurl!~/\.meta$/) {
                                   my $mrequest=      my $ua=new LWP::UserAgent;
                                    new HTTP::Request('GET',$remoteurl.'.meta');      my $mrequest=
                                   my $mresponse=   new HTTP::Request('GET',$remoteurl.'.meta');
                                    $ua->request($mrequest,$fname.'.meta');      my $mresponse=
                                   if ($mresponse->is_error()) {   $ua->request($mrequest,$fname.'.meta');
                     unlink($fname.'.meta');      if ($mresponse->is_error()) {
                                   }   unlink($fname.'.meta');
                          }      }
                                  rename($transname,$fname);   }
      }   rename($transname,$fname);
                           }      }
                           print $client "ok\n";   }
                         } else {   print $client "ok\n";
                           print $client "not_found\n";      } else {
                         }   print $client "not_found\n";
        } else {      }
  print $client "rejected\n";   } else {
                        }      print $client "rejected\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # -------------------------------------- fetch a user file from a remote server  # -------------------------------------- fetch a user file from a remote server
                    } elsif ($userinput =~ /^fetchuserfile/) {   } elsif ($userinput =~ /^fetchuserfile/) { # Client clear or enc.
        my ($cmd,$fname)=split(/:/,$userinput);      if(isClient) {
        my ($udom,$uname,$ufile)=split(/\//,$fname);   my ($cmd,$fname)=split(/:/,$userinput);
        my $udir=propath($udom,$uname).'/userfiles';   my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|);
        unless (-e $udir) { mkdir($udir,0770); }   my $udir=propath($udom,$uname).'/userfiles';
                        if (-e $udir) {   unless (-e $udir) { mkdir($udir,0770); }
    $ufile=~s/^[\.\~]+//;   if (-e $udir) {
    $ufile=~s/\///g;                              $ufile=~s/^[\.\~]+//;
    my $destname=$udir.'/'.$ufile;                              my $path = $udir;
    my $transname=$udir.'/'.$ufile.'.in.transit';                              if ($ufile =~m|(.+)/([^/]+)$|) {
    my $remoteurl='http://'.$clientip.'/userfiles/'.$fname;                                  my @parts=split('/',$1);
    my $response;                                  foreach my $part (@parts) {
    {                                      $path .= '/'.$part;
        my $ua=new LWP::UserAgent;                                      if ((-e $path)!=1) {
        my $request=new HTTP::Request('GET',"$remoteurl");                                          mkdir($path,0770);
        $response=$ua->request($request,$transname);                                      }
    }                                  }
    if ($response->is_error()) {                              }
        unlink($transname);      my $destname=$udir.'/'.$ufile;
        my $message=$response->status_line;      my $transname=$udir.'/'.$ufile.'.in.transit';
        &logthis("LWP GET: $message for $fname ($remoteurl)");      my $remoteurl='http://'.$clientip.'/userfiles/'.$fname;
        print $client "failed\n";      my $response;
    } else {      {
        if (!rename($transname,$destname)) {   my $ua=new LWP::UserAgent;
    &logthis("Unable to move $transname to $destname");   my $request=new HTTP::Request('GET',"$remoteurl");
    unlink($transname);   $response=$ua->request($request,$transname);
    print $client "failed\n";      }
        } else {      if ($response->is_error()) {
    print $client "ok\n";   unlink($transname);
        }   my $message=$response->status_line;
    }   &logthis("LWP GET: $message for $fname ($remoteurl)");
        } else {   print $client "failed\n";
    print $client "not_home\n";      } else {
        }   if (!rename($transname,$destname)) {
       &logthis("Unable to move $transname to $destname");
       unlink($transname);
       print $client "failed\n";
    } else {
       print $client "ok\n";
    }
       }
    } else {
       print $client "not_home\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
       }
   # --------------------------------------------------------- remove a user file 
    } elsif ($userinput =~ /^removeuserfile/) { # Client clear or enc.
       if(isClient) {
    my ($cmd,$fname)=split(/:/,$userinput);
    my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|);
    &logthis("$udom - $uname - $ufile");
    if ($ufile =~m|/\.\./|) {
       # any files paths with /../ in them refuse 
                               # to deal with
       print $client "refused\n";
    } else {
       my $udir=propath($udom,$uname);
       if (-e $udir) {
    my $file=$udir.'/userfiles/'.$ufile;
    if (-e $file) {
       unlink($file);
       if (-e $file) {
    print $client "failed\n";
       } else {
    print $client "ok\n";
       }
    } else {
       print $client "not_found\n";
    }
       } else {
    print $client "not_home\n";
       }
    }
       } else {
    Reply($client, "refused\n", $userinput);
       }
 # ------------------------------------------ authenticate access to a user file  # ------------------------------------------ authenticate access to a user file
                    } elsif ($userinput =~ /^tokenauthuserfile/) {   } elsif ($userinput =~ /^tokenauthuserfile/) { # Client only
                        my ($cmd,$fname,$session)=split(/:/,$userinput);      if(isClient) {
                        chomp($session);   my ($cmd,$fname,$session)=split(/:/,$userinput);
                        my $reply='non_auth';   chomp($session);
                        if (open(ENVIN,$perlvar{'lonIDsDir'}.'/'.   my $reply='non_auth';
  $session.'.id')) {   if (open(ENVIN,$perlvar{'lonIDsDir'}.'/'.
    while (my $line=<ENVIN>) {   $session.'.id')) {
        if ($line=~/userfile\.$fname\=/) { $reply='ok'; }      while (my $line=<ENVIN>) {
    }   if ($line=~ m|userfile\.\Q$fname\E\=|) { $reply='ok'; }
    close(ENVIN);      }
    print $client $reply."\n";      close(ENVIN);
        } else {      print $client $reply."\n";
    print $client "invalid_token\n";   } else {
                        }      print $client "invalid_token\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ----------------------------------------------------------------- unsubscribe  # ----------------------------------------------------------------- unsubscribe
                    } elsif ($userinput =~ /^unsub/) {   } elsif ($userinput =~ /^unsub/) {
                        my ($cmd,$fname)=split(/:/,$userinput);      if(isClient) {
                        if (-e $fname) {   my ($cmd,$fname)=split(/:/,$userinput);
    print $client &unsub($client,$fname,$clientip);   if (-e $fname) {
                        } else {      print $client &unsub($fname,$clientip);
    print $client "not_found\n";   } else {
                        }      print $client "not_found\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ------------------------------------------------------------------- subscribe  # ------------------------------------------------------------------- subscribe
                    } elsif ($userinput =~ /^sub/) {   } elsif ($userinput =~ /^sub/) {
        print $client &subscribe($userinput,$clientip);      if(isClient) {
    print $client &subscribe($userinput,$clientip);
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ------------------------------------------------------------- current version  # ------------------------------------------------------------- current version
                    } elsif ($userinput =~ /^currentversion/) {   } elsif ($userinput =~ /^currentversion/) {
                        my ($cmd,$fname)=split(/:/,$userinput);      if(isClient) {
        print $client &currentversion($fname)."\n";   my ($cmd,$fname)=split(/:/,$userinput);
    print $client &currentversion($fname)."\n";
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ------------------------------------------------------------------------- log  # ------------------------------------------------------------------------- log
                    } elsif ($userinput =~ /^log/) {   } elsif ($userinput =~ /^log/) {
                        my ($cmd,$udom,$uname,$what)=split(/:/,$userinput);      if(isClient) {
                        chomp($what);   my ($cmd,$udom,$uname,$what)=split(/:/,$userinput);
                        my $proname=propath($udom,$uname);   chomp($what);
                        my $now=time;   my $proname=propath($udom,$uname);
                        {   my $now=time;
  my $hfh;   {
  if ($hfh=IO::File->new(">>$proname/activity.log")) {       my $hfh;
                             print $hfh "$now:$hostid{$clientip}:$what\n";      if ($hfh=IO::File->new(">>$proname/activity.log")) { 
                             print $client "ok\n";    print $hfh "$now:$clientname:$what\n";
  } else {   print $client "ok\n"; 
                             print $client "error: ".($!+0)      } else {
  ." IO::File->new Failed "   print $client "error: ".($!+0)
                                     ."while attempting log\n";      ." IO::File->new Failed "
         }      ."while attempting log\n";
        }      }
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ------------------------------------------------------------------------- put  # ------------------------------------------------------------------------- put
                    } elsif ($userinput =~ /^put/) {   } elsif ($userinput =~ /^put/) {
                       my ($cmd,$udom,$uname,$namespace,$what)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$what)
                       $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                       $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                       if ($namespace ne 'roles') {   $namespace=~s/\W//g;
                        chomp($what);   if ($namespace ne 'roles') {
                        my $proname=propath($udom,$uname);      chomp($what);
                        my $now=time;      my $proname=propath($udom,$uname);
                        unless ($namespace=~/^nohist\_/) {      my $now=time;
    my $hfh;      unless ($namespace=~/^nohist\_/) {
    if (   my $hfh;
                              $hfh=IO::File->new(">>$proname/$namespace.hist")   if (
        ) { print $hfh "P:$now:$what\n"; }      $hfh=IO::File->new(">>$proname/$namespace.hist")
        }      ) { print $hfh "P:$now:$what\n"; }
                        my @pairs=split(/\&/,$what);      }
        my %hash;      my @pairs=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {      my %hash;
                            foreach my $pair (@pairs) {      if (tie(%hash,'GDBM_File',
        my ($key,$value)=split(/=/,$pair);      "$proname/$namespace.db",
                                $hash{$key}=$value;      &GDBM_WRCREAT(),0640)) {
                            }   foreach my $pair (@pairs) {
    if (untie(%hash)) {      my ($key,$value)=split(/=/,$pair);
                               print $client "ok\n";      $hash{$key}=$value;
                            } else {   }
                               print $client "error: ".($!+0)   if (untie(%hash)) {
   ." untie(GDBM) failed ".      print $client "ok\n";
                                       "while attempting put\n";   } else {
                            }      print $client "error: ".($!+0)
                        } else {   ." untie(GDBM) failed ".
                            print $client "error: ".($!)   "while attempting put\n";
        ." tie(GDBM) Failed ".   }
                                    "while attempting put\n";      } else {
                        }   print $client "error: ".($!)
       } else {      ." tie(GDBM) Failed ".
                           print $client "refused\n";      "while attempting put\n";
                       }      }
    } else {
       print $client "refused\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
   # ------------------------------------------------------------------- inc
    } elsif ($userinput =~ /^inc:/) {
       if(isClient) {
    my ($cmd,$udom,$uname,$namespace,$what)
       =split(/:/,$userinput);
    $namespace=~s/\//\_/g;
    $namespace=~s/\W//g;
    if ($namespace ne 'roles') {
       chomp($what);
       my $proname=propath($udom,$uname);
       my $now=time;
       unless ($namespace=~/^nohist\_/) {
    my $hfh;
    if (
       $hfh=IO::File->new(">>$proname/$namespace.hist")
       ) { print $hfh "P:$now:$what\n"; }
       }
       my @pairs=split(/\&/,$what);
       my %hash;
       if (tie(%hash,'GDBM_File',
       "$proname/$namespace.db",
       &GDBM_WRCREAT(),0640)) {
    foreach my $pair (@pairs) {
       my ($key,$value)=split(/=/,$pair);
                                       # We could check that we have a number...
                                       if (! defined($value) || $value eq '') {
                                           $value = 1;
                                       }
       $hash{$key}+=$value;
    }
    if (untie(%hash)) {
       print $client "ok\n";
    } else {
       print $client "error: ".($!+0)
    ." untie(GDBM) failed ".
    "while attempting inc\n";
    }
       } else {
    print $client "error: ".($!)
       ." tie(GDBM) Failed ".
       "while attempting inc\n";
       }
    } else {
       print $client "refused\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # -------------------------------------------------------------------- rolesput  # -------------------------------------------------------------------- rolesput
                    } elsif ($userinput =~ /^rolesput/) {   } elsif ($userinput =~ /^rolesput/) {
        &Debug("rolesput");      if(isClient) {
     if ($wasenc==1) {   &Debug("rolesput");
                        my ($cmd,$exedom,$exeuser,$udom,$uname,$what)   if ($wasenc==1) {
                           =split(/:/,$userinput);      my ($cmd,$exedom,$exeuser,$udom,$uname,$what)
        &Debug("cmd = ".$cmd." exedom= ".$exedom.   =split(/:/,$userinput);
     "user = ".$exeuser." udom=".$udom.      &Debug("cmd = ".$cmd." exedom= ".$exedom.
     "what = ".$what);     "user = ".$exeuser." udom=".$udom.
                        my $namespace='roles';     "what = ".$what);
                        chomp($what);      my $namespace='roles';
                        my $proname=propath($udom,$uname);      chomp($what);
                        my $now=time;      my $proname=propath($udom,$uname);
                        {      my $now=time;
    my $hfh;      {
    if (   my $hfh;
                              $hfh=IO::File->new(">>$proname/$namespace.hist")   if (
        ) {       $hfh=IO::File->new(">>$proname/$namespace.hist")
                                   print $hfh "P:$now:$exedom:$exeuser:$what\n";      ) { 
                                  }      print $hfh "P:$now:$exedom:$exeuser:$what\n";
        }   }
                        my @pairs=split(/\&/,$what);      }
        my %hash;      my @pairs=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {      my %hash;
                            foreach my $pair (@pairs) {      if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {
        my ($key,$value)=split(/=/,$pair);   foreach my $pair (@pairs) {
        &ManagePermissions($key, $udom, $uname,      my ($key,$value)=split(/=/,$pair);
   &GetAuthType( $udom,       &ManagePermissions($key, $udom, $uname,
  $uname));         &GetAuthType( $udom, 
                                $hash{$key}=$value;       $uname));
                            }      $hash{$key}=$value;
    if (untie(%hash)) {   }
                               print $client "ok\n";   if (untie(%hash)) {
                            } else {      print $client "ok\n";
                               print $client "error: ".($!+0)   } else {
   ." untie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting rolesput\n";   ." untie(GDBM) Failed ".
                            }   "while attempting rolesput\n";
                        } else {   }
                            print $client "error: ".($!+0)      } else {
        ." tie(GDBM) Failed ".   print $client "error: ".($!+0)
                                    "while attempting rolesput\n";      ." tie(GDBM) Failed ".
                        }      "while attempting rolesput\n";
       } else {      }
                           print $client "refused\n";   } else {
                       }      print $client "refused\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
     
       }
 # -------------------------------------------------------------------- rolesdel  # -------------------------------------------------------------------- rolesdel
                    } elsif ($userinput =~ /^rolesdel/) {   } elsif ($userinput =~ /^rolesdel/) {
        &Debug("rolesdel");      if(isClient) {
     if ($wasenc==1) {   &Debug("rolesdel");
                        my ($cmd,$exedom,$exeuser,$udom,$uname,$what)   if ($wasenc==1) {
                           =split(/:/,$userinput);      my ($cmd,$exedom,$exeuser,$udom,$uname,$what)
        &Debug("cmd = ".$cmd." exedom= ".$exedom.   =split(/:/,$userinput);
     "user = ".$exeuser." udom=".$udom.      &Debug("cmd = ".$cmd." exedom= ".$exedom.
     "what = ".$what);     "user = ".$exeuser." udom=".$udom.
                        my $namespace='roles';     "what = ".$what);
                        chomp($what);      my $namespace='roles';
                        my $proname=propath($udom,$uname);      chomp($what);
                        my $now=time;      my $proname=propath($udom,$uname);
                        {      my $now=time;
    my $hfh;      {
    if (   my $hfh;
                              $hfh=IO::File->new(">>$proname/$namespace.hist")   if (
        ) {       $hfh=IO::File->new(">>$proname/$namespace.hist")
                                   print $hfh "D:$now:$exedom:$exeuser:$what\n";      ) { 
                                  }      print $hfh "D:$now:$exedom:$exeuser:$what\n";
        }   }
                        my @rolekeys=split(/\&/,$what);      }
        my %hash;      my @rolekeys=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {      my %hash;
                            foreach my $key (@rolekeys) {      if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {
                                delete $hash{$key};   foreach my $key (@rolekeys) {
                            }      delete $hash{$key};
    if (untie(%hash)) {   }
                               print $client "ok\n";   if (untie(%hash)) {
                            } else {      print $client "ok\n";
                               print $client "error: ".($!+0)   } else {
   ." untie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting rolesdel\n";   ." untie(GDBM) Failed ".
                            }   "while attempting rolesdel\n";
                        } else {   }
                            print $client "error: ".($!+0)      } else {
        ." tie(GDBM) Failed ".   print $client "error: ".($!+0)
                                    "while attempting rolesdel\n";      ." tie(GDBM) Failed ".
                        }      "while attempting rolesdel\n";
       } else {      }
                           print $client "refused\n";   } else {
                       }      print $client "refused\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
         
       }
 # ------------------------------------------------------------------------- get  # ------------------------------------------------------------------------- get
                    } elsif ($userinput =~ /^get/) {   } elsif ($userinput =~ /^get/) {
                        my ($cmd,$udom,$uname,$namespace,$what)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$what)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        chomp($what);   $namespace=~s/\W//g;
                        my @queries=split(/\&/,$what);   chomp($what);
                        my $proname=propath($udom,$uname);   my @queries=split(/\&/,$what);
                        my $qresult='';   my $proname=propath($udom,$uname);
        my %hash;   my $qresult='';
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {   my %hash;
                            for (my $i=0;$i<=$#queries;$i++) {   if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {
                                $qresult.="$hash{$queries[$i]}&";      for (my $i=0;$i<=$#queries;$i++) {
                            }   $qresult.="$hash{$queries[$i]}&";
    if (untie(%hash)) {      }
               $qresult=~s/\&$//;      if (untie(%hash)) {
                               print $client "$qresult\n";   $qresult=~s/\&$//;
                            } else {   print $client "$qresult\n";
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting get\n";      ." untie(GDBM) Failed ".
                            }      "while attempting get\n";
                        } else {      }
                            if ($!+0 == 2) {   } else {
                                print $client "error:No such file or ".      if ($!+0 == 2) {
                                    "GDBM reported bad block error\n";   print $client "error:No such file or ".
                            } else {      "GDBM reported bad block error\n";
                                print $client "error: ".($!+0)      } else {
                                    ." tie(GDBM) Failed ".   print $client "error: ".($!+0)
                                        "while attempting get\n";      ." tie(GDBM) Failed ".
                            }      "while attempting get\n";
                        }      }
    }
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ------------------------------------------------------------------------ eget  # ------------------------------------------------------------------------ eget
                    } elsif ($userinput =~ /^eget/) {   } elsif ($userinput =~ /^eget/) {
                        my ($cmd,$udom,$uname,$namespace,$what)      if (isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$what)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        chomp($what);   $namespace=~s/\W//g;
                        my @queries=split(/\&/,$what);   chomp($what);
                        my $proname=propath($udom,$uname);   my @queries=split(/\&/,$what);
                        my $qresult='';   my $proname=propath($udom,$uname);
        my %hash;   my $qresult='';
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {   my %hash;
                            for (my $i=0;$i<=$#queries;$i++) {   if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {
                                $qresult.="$hash{$queries[$i]}&";      for (my $i=0;$i<=$#queries;$i++) {
                            }   $qresult.="$hash{$queries[$i]}&";
    if (untie(%hash)) {      }
               $qresult=~s/\&$//;      if (untie(%hash)) {
                               if ($cipher) {   $qresult=~s/\&$//;
                                 my $cmdlength=length($qresult);   if ($cipher) {
                                 $qresult.="         ";      my $cmdlength=length($qresult);
                                 my $encqresult='';      $qresult.="         ";
                                 for       my $encqresult='';
  (my $encidx=0;$encidx<=$cmdlength;$encidx+=8) {      for 
                                  $encqresult.=   (my $encidx=0;$encidx<=$cmdlength;$encidx+=8) {
                                  unpack("H16",      $encqresult.=
                                  $cipher->encrypt(substr($qresult,$encidx,8)));   unpack("H16",
                                 }         $cipher->encrypt(substr($qresult,$encidx,8)));
                                 print $client "enc:$cmdlength:$encqresult\n";   }
       } else {      print $client "enc:$cmdlength:$encqresult\n";
         print $client "error:no_key\n";   } else {
                               }      print $client "error:no_key\n";
                            } else {   }
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting eget\n";      ." untie(GDBM) Failed ".
                            }      "while attempting eget\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                    "while attempting eget\n";   ." tie(GDBM) Failed ".
                        }   "while attempting eget\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
       
       }
 # ------------------------------------------------------------------------- del  # ------------------------------------------------------------------------- del
                    } elsif ($userinput =~ /^del/) {   } elsif ($userinput =~ /^del/) {
                        my ($cmd,$udom,$uname,$namespace,$what)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$what)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        chomp($what);   $namespace=~s/\W//g;
                        my $proname=propath($udom,$uname);   chomp($what);
                        my $now=time;   my $proname=propath($udom,$uname);
                        unless ($namespace=~/^nohist\_/) {   my $now=time;
    my $hfh;   unless ($namespace=~/^nohist\_/) {
    if (      my $hfh;
                              $hfh=IO::File->new(">>$proname/$namespace.hist")      if (
        ) { print $hfh "D:$now:$what\n"; }   $hfh=IO::File->new(">>$proname/$namespace.hist")
        }   ) { print $hfh "D:$now:$what\n"; }
                        my @keys=split(/\&/,$what);   }
        my %hash;   my @keys=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {   my %hash;
                            foreach my $key (@keys) {   if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {
                                delete($hash{$key});      foreach my $key (@keys) {
                            }   delete($hash{$key});
    if (untie(%hash)) {      }
                               print $client "ok\n";      if (untie(%hash)) {
                            } else {   print $client "ok\n";
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting del\n";      ." untie(GDBM) Failed ".
                            }      "while attempting del\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                    "while attempting del\n";   ." tie(GDBM) Failed ".
                        }   "while attempting del\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
   
       }
 # ------------------------------------------------------------------------ keys  # ------------------------------------------------------------------------ keys
                    } elsif ($userinput =~ /^keys/) {   } elsif ($userinput =~ /^keys/) {
                        my ($cmd,$udom,$uname,$namespace)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        my $proname=propath($udom,$uname);   $namespace=~s/\W//g;
                        my $qresult='';   my $proname=propath($udom,$uname);
        my %hash;   my $qresult='';
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {   my %hash;
                            foreach my $key (keys %hash) {   if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {
                                $qresult.="$key&";      foreach my $key (keys %hash) {
                            }   $qresult.="$key&";
    if (untie(%hash)) {      }
               $qresult=~s/\&$//;      if (untie(%hash)) {
                               print $client "$qresult\n";   $qresult=~s/\&$//;
                            } else {   print $client "$qresult\n";
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting keys\n";      ." untie(GDBM) Failed ".
                            }      "while attempting keys\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                    "while attempting keys\n";   ." tie(GDBM) Failed ".
                        }   "while attempting keys\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
      
       }
 # ----------------------------------------------------------------- dumpcurrent  # ----------------------------------------------------------------- dumpcurrent
                    } elsif ($userinput =~ /^currentdump/) {   } elsif ($userinput =~ /^currentdump/) {
                        my ($cmd,$udom,$uname,$namespace)      if (isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        my $qresult='';   $namespace=~s/\W//g;
                        my $proname=propath($udom,$uname);   my $qresult='';
        my %hash;   my $proname=propath($udom,$uname);
                        if (tie(%hash,'GDBM_File',   my %hash;
                                "$proname/$namespace.db",   if (tie(%hash,'GDBM_File',
                                &GDBM_READER(),0640)) {   "$proname/$namespace.db",
                            # Structure of %data:   &GDBM_READER(),0640)) {
                            # $data{$symb}->{$parameter}=$value;      # Structure of %data:
                            # $data{$symb}->{'v.'.$parameter}=$version;      # $data{$symb}->{$parameter}=$value;
                            # since $parameter will be unescaped, we do not      # $data{$symb}->{'v.'.$parameter}=$version;
                            # have to worry about silly parameter names...      # since $parameter will be unescaped, we do not
                            my %data = ();      # have to worry about silly parameter names...
                            while (my ($key,$value) = each(%hash)) {      my %data = ();
                               my ($v,$symb,$param) = split(/:/,$key);      while (my ($key,$value) = each(%hash)) {
                               next if ($v eq 'version' || $symb eq 'keys');   my ($v,$symb,$param) = split(/:/,$key);
                               next if (exists($data{$symb}) &&    next if ($v eq 'version' || $symb eq 'keys');
                                        exists($data{$symb}->{$param}) &&   next if (exists($data{$symb}) && 
                                        $data{$symb}->{'v.'.$param} > $v);   exists($data{$symb}->{$param}) &&
                               $data{$symb}->{$param}=$value;   $data{$symb}->{'v.'.$param} > $v);
                               $data{$symb}->{'v.'.$param}=$v;   $data{$symb}->{$param}=$value;
                            }   $data{$symb}->{'v.'.$param}=$v;
                            if (untie(%hash)) {      }
                              while (my ($symb,$param_hash) = each(%data)) {      if (untie(%hash)) {
                                while(my ($param,$value) = each (%$param_hash)){   while (my ($symb,$param_hash) = each(%data)) {
                                  next if ($param =~ /^v\./);      while(my ($param,$value) = each (%$param_hash)){
                                  $qresult.=$symb.':'.$param.'='.$value.'&';   next if ($param =~ /^v\./);
                                }   $qresult.=$symb.':'.$param.'='.$value.'&';
                              }      }
                              chop($qresult);   }
                              print $client "$qresult\n";   chop($qresult);
                            } else {   print $client "$qresult\n";
                              print $client "error: ".($!+0)      } else {
  ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                      "while attempting currentdump\n";      ." untie(GDBM) Failed ".
                            }      "while attempting currentdump\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting currentdump\n";   ." tie(GDBM) Failed ".
                        }   "while attempting currentdump\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
       }
 # ------------------------------------------------------------------------ dump  # ------------------------------------------------------------------------ dump
                    } elsif ($userinput =~ /^dump/) {   } elsif ($userinput =~ /^dump/) {
                        my ($cmd,$udom,$uname,$namespace,$regexp)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$regexp)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        if (defined($regexp)) {   $namespace=~s/\W//g;
                           $regexp=&unescape($regexp);   if (defined($regexp)) {
        } else {      $regexp=&unescape($regexp);
                           $regexp='.';   } else {
        }      $regexp='.';
                        my $qresult='';   }
                        my $proname=propath($udom,$uname);   my $qresult='';
        my %hash;   my $proname=propath($udom,$uname);
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {   my %hash;
                            study($regexp);   if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {
                            while (my ($key,$value) = each(%hash)) {         while (my ($key,$value) = each(%hash)) {
                                if ($regexp eq '.') {     if ($regexp eq '.') {
                                    $qresult.=$key.'='.$value.'&';         $qresult.=$key.'='.$value.'&';
                                } else {     } else {
                                    my $unescapeKey = &unescape($key);         my $unescapeKey = &unescape($key);
                                    if (eval('$unescapeKey=~/$regexp/')) {         if (eval('$unescapeKey=~/$regexp/')) {
                                        $qresult.="$key=$value&";     $qresult.="$key=$value&";
                                    }         }
                                }     }
                            }         }
                            if (untie(%hash)) {         if (untie(%hash)) {
                                chop($qresult);     chop($qresult);
                                print $client "$qresult\n";     print $client "$qresult\n";
                            } else {         } else {
                                print $client "error: ".($!+0)     print $client "error: ".($!+0)
    ." untie(GDBM) Failed ".         ." untie(GDBM) Failed ".
                                        "while attempting dump\n";                                         "while attempting dump\n";
                            }         }
                        } else {     } else {
                            print $client "error: ".($!+0)         print $client "error: ".($!+0)
        ." tie(GDBM) Failed ".     ." tie(GDBM) Failed ".
                                       "while attempting dump\n";     "while attempting dump\n";
                        }     }
       } else {
    Reply($client, "refused\n", $userinput);
     
       }
 # ----------------------------------------------------------------------- store  # ----------------------------------------------------------------------- store
                    } elsif ($userinput =~ /^store/) {   } elsif ($userinput =~ /^store/) {
                       my ($cmd,$udom,$uname,$namespace,$rid,$what)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$rid,$what)
                       $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                       $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                       if ($namespace ne 'roles') {   $namespace=~s/\W//g;
                        chomp($what);   if ($namespace ne 'roles') {
                        my $proname=propath($udom,$uname);      chomp($what);
                        my $now=time;      my $proname=propath($udom,$uname);
                        unless ($namespace=~/^nohist\_/) {      my $now=time;
    my $hfh;      unless ($namespace=~/^nohist\_/) {
    if (   my $hfh;
                              $hfh=IO::File->new(">>$proname/$namespace.hist")   if (
        ) { print $hfh "P:$now:$rid:$what\n"; }      $hfh=IO::File->new(">>$proname/$namespace.hist")
        }      ) { print $hfh "P:$now:$rid:$what\n"; }
                        my @pairs=split(/\&/,$what);      }
        my %hash;      my @pairs=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {      my %hash;
                            my @previouskeys=split(/&/,$hash{"keys:$rid"});      if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_WRCREAT(),0640)) {
                            my $key;   my @previouskeys=split(/&/,$hash{"keys:$rid"});
                            $hash{"version:$rid"}++;   my $key;
                            my $version=$hash{"version:$rid"};   $hash{"version:$rid"}++;
                            my $allkeys='';    my $version=$hash{"version:$rid"};
                            foreach my $pair (@pairs) {   my $allkeys=''; 
        my ($key,$value)=split(/=/,$pair);   foreach my $pair (@pairs) {
                                $allkeys.=$key.':';      my ($key,$value)=split(/=/,$pair);
                                $hash{"$version:$rid:$key"}=$value;      $allkeys.=$key.':';
                            }      $hash{"$version:$rid:$key"}=$value;
                            $hash{"$version:$rid:timestamp"}=$now;   }
                            $allkeys.='timestamp';   $hash{"$version:$rid:timestamp"}=$now;
                            $hash{"$version:keys:$rid"}=$allkeys;   $allkeys.='timestamp';
    if (untie(%hash)) {   $hash{"$version:keys:$rid"}=$allkeys;
                               print $client "ok\n";   if (untie(%hash)) {
                            } else {      print $client "ok\n";
                               print $client "error: ".($!+0)   } else {
   ." untie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting store\n";   ." untie(GDBM) Failed ".
                            }   "while attempting store\n";
                        } else {   }
                            print $client "error: ".($!+0)      } else {
        ." tie(GDBM) Failed ".   print $client "error: ".($!+0)
                                    "while attempting store\n";      ." tie(GDBM) Failed ".
                        }      "while attempting store\n";
       } else {      }
                           print $client "refused\n";   } else {
                       }      print $client "refused\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
        
       }
 # --------------------------------------------------------------------- restore  # --------------------------------------------------------------------- restore
                    } elsif ($userinput =~ /^restore/) {   } elsif ($userinput =~ /^restore/) {
                        my ($cmd,$udom,$uname,$namespace,$rid)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$uname,$namespace,$rid)
                        $namespace=~s/\//\_/g;      =split(/:/,$userinput);
                        $namespace=~s/\W//g;   $namespace=~s/\//\_/g;
                        chomp($rid);   $namespace=~s/\W//g;
                        my $proname=propath($udom,$uname);   chomp($rid);
                        my $qresult='';   my $proname=propath($udom,$uname);
        my %hash;   my $qresult='';
        if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {   my %hash;
                   my $version=$hash{"version:$rid"};   if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) {
                            $qresult.="version=$version&";      my $version=$hash{"version:$rid"};
                            my $scope;      $qresult.="version=$version&";
                            for ($scope=1;$scope<=$version;$scope++) {      my $scope;
       my $vkeys=$hash{"$scope:keys:$rid"};      for ($scope=1;$scope<=$version;$scope++) {
                               my @keys=split(/:/,$vkeys);   my $vkeys=$hash{"$scope:keys:$rid"};
                               my $key;   my @keys=split(/:/,$vkeys);
                               $qresult.="$scope:keys=$vkeys&";   my $key;
                               foreach $key (@keys) {   $qresult.="$scope:keys=$vkeys&";
      $qresult.="$scope:$key=".$hash{"$scope:$rid:$key"}."&";   foreach $key (@keys) {
                               }                                        $qresult.="$scope:$key=".$hash{"$scope:$rid:$key"}."&";
                            }   }                                  
    if (untie(%hash)) {      }
               $qresult=~s/\&$//;      if (untie(%hash)) {
                               print $client "$qresult\n";   $qresult=~s/\&$//;
                            } else {   print $client "$qresult\n";
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting restore\n";      ." untie(GDBM) Failed ".
                            }      "while attempting restore\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                    "while attempting restore\n";   ." tie(GDBM) Failed ".
                        }   "while attempting restore\n";
    }
       } else  {
    Reply($client, "refused\n", $userinput);
          
       }
 # -------------------------------------------------------------------- chatsend  # -------------------------------------------------------------------- chatsend
                    } elsif ($userinput =~ /^chatsend/) {   } elsif ($userinput =~ /^chatsend/) {
                        my ($cmd,$cdom,$cnum,$newpost)=split(/\:/,$userinput);      if(isClient) {
                        &chatadd($cdom,$cnum,$newpost);   my ($cmd,$cdom,$cnum,$newpost)=split(/\:/,$userinput);
                        print $client "ok\n";   &chatadd($cdom,$cnum,$newpost);
    print $client "ok\n";
       } else {
    Reply($client, "refused\n", $userinput);
         
       }
 # -------------------------------------------------------------------- chatretr  # -------------------------------------------------------------------- chatretr
                    } elsif ($userinput =~ /^chatretr/) {   } elsif ($userinput =~ /^chatretr/) {
                        my       if(isClient) {
                         ($cmd,$cdom,$cnum,$udom,$uname)=split(/\:/,$userinput);   my 
                        my $reply='';      ($cmd,$cdom,$cnum,$udom,$uname)=split(/\:/,$userinput);
                        foreach (&getchat($cdom,$cnum,$udom,$uname)) {   my $reply='';
    $reply.=&escape($_).':';   foreach (&getchat($cdom,$cnum,$udom,$uname)) {
                        }      $reply.=&escape($_).':';
                        $reply=~s/\:$//;   }
                        print $client $reply."\n";   $reply=~s/\:$//;
    print $client $reply."\n";
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ------------------------------------------------------------------- querysend  # ------------------------------------------------------------------- querysend
                    } elsif ($userinput =~ /^querysend/) {   } elsif ($userinput =~ /^querysend/) {
                        my ($cmd,$query,      if (isClient) {
    $arg1,$arg2,$arg3)=split(/\:/,$userinput);   my ($cmd,$query,
        $query=~s/\n*$//g;      $arg1,$arg2,$arg3)=split(/\:/,$userinput);
        print $client "".   $query=~s/\n*$//g;
        sqlreply("$hostid{$clientip}\&$query".   print $client "".
  "\&$arg1"."\&$arg2"."\&$arg3")."\n";      sqlreply("$clientname\&$query".
        "\&$arg1"."\&$arg2"."\&$arg3")."\n";
       } else {
    Reply($client, "refused\n", $userinput);
         
       }
 # ------------------------------------------------------------------ queryreply  # ------------------------------------------------------------------ queryreply
                    } elsif ($userinput =~ /^queryreply/) {   } elsif ($userinput =~ /^queryreply/) {
                        my ($cmd,$id,$reply)=split(/:/,$userinput);       if(isClient) {
        my $store;   my ($cmd,$id,$reply)=split(/:/,$userinput); 
                        my $execdir=$perlvar{'lonDaemons'};   my $store;
                        if ($store=IO::File->new(">$execdir/tmp/$id")) {   my $execdir=$perlvar{'lonDaemons'};
    $reply=~s/\&/\n/g;   if ($store=IO::File->new(">$execdir/tmp/$id")) {
    print $store $reply;      $reply=~s/\&/\n/g;
    close $store;      print $store $reply;
    my $store2=IO::File->new(">$execdir/tmp/$id.end");      close $store;
    print $store2 "done\n";      my $store2=IO::File->new(">$execdir/tmp/$id.end");
    close $store2;      print $store2 "done\n";
    print $client "ok\n";      close $store2;
        }      print $client "ok\n";
        else {   }
    print $client "error: ".($!+0)   else {
        ." IO::File->new Failed ".      print $client "error: ".($!+0)
                                    "while attempting queryreply\n";   ." IO::File->new Failed ".
        }   "while attempting queryreply\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
        
       }
 # ----------------------------------------------------------------- courseidput  # ----------------------------------------------------------------- courseidput
                    } elsif ($userinput =~ /^courseidput/) {   } elsif ($userinput =~ /^courseidput/) {
                        my ($cmd,$udom,$what)=split(/:/,$userinput);      if(isClient) {
                        chomp($what);   my ($cmd,$udom,$what)=split(/:/,$userinput);
                        $udom=~s/\W//g;   chomp($what);
                        my $proname=   $udom=~s/\W//g;
                               "$perlvar{'lonUsersDir'}/$udom/nohist_courseids";   my $proname=
                        my $now=time;      "$perlvar{'lonUsersDir'}/$udom/nohist_courseids";
                        my @pairs=split(/\&/,$what);   my $now=time;
        my %hash;   my @pairs=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_WRCREAT(),0640)) {   my %hash;
                            foreach my $pair (@pairs) {   if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_WRCREAT(),0640)) {
        my ($key,$value)=split(/=/,$pair);      foreach my $pair (@pairs) {
                                $hash{$key}=$value.':'.$now;   my ($key,$value)=split(/=/,$pair);
                            }   $hash{$key}=$value.':'.$now;
    if (untie(%hash)) {      }
                               print $client "ok\n";      if (untie(%hash)) {
                            } else {   print $client "ok\n";
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting courseidput\n";      ." untie(GDBM) Failed ".
                            }      "while attempting courseidput\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting courseidput\n";   ." tie(GDBM) Failed ".
                        }   "while attempting courseidput\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ---------------------------------------------------------------- courseiddump  # ---------------------------------------------------------------- courseiddump
                    } elsif ($userinput =~ /^courseiddump/) {   } elsif ($userinput =~ /^courseiddump/) {
                        my ($cmd,$udom,$since,$description)      if(isClient) {
                           =split(/:/,$userinput);   my ($cmd,$udom,$since,$description)
                        if (defined($description)) {      =split(/:/,$userinput);
                           $description=&unescape($description);   if (defined($description)) {
        } else {      $description=&unescape($description);
                           $description='.';   } else {
        }      $description='.';
                        unless (defined($since)) { $since=0; }   }
                        my $qresult='';   unless (defined($since)) { $since=0; }
                        my $proname=   my $qresult='';
                               "$perlvar{'lonUsersDir'}/$udom/nohist_courseids";   my $proname=
        my %hash;      "$perlvar{'lonUsersDir'}/$udom/nohist_courseids";
        if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_READER(),0640)) {   my %hash;
                            while (my ($key,$value) = each(%hash)) {   if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_READER(),0640)) {
                                my ($descr,$lasttime)=split(/\:/,$value);      while (my ($key,$value) = each(%hash)) {
                                if ($lasttime<$since) { next; }   my ($descr,$lasttime)=split(/\:/,$value);
                                if ($description eq '.') {   if ($lasttime<$since) { next; }
                                    $qresult.=$key.'='.$descr.'&';   if ($description eq '.') {
                                } else {      $qresult.=$key.'='.$descr.'&';
                                    my $unescapeVal = &unescape($descr);   } else {
                                    if (eval('$unescapeVal=~/$description/i')) {      my $unescapeVal = &unescape($descr);
                                        $qresult.="$key=$descr&";      if (eval('$unescapeVal=~/\Q$description\E/i')) {
                                    }   $qresult.="$key=$descr&";
                                }      }
                            }   }
                            if (untie(%hash)) {      }
                                chop($qresult);      if (untie(%hash)) {
                                print $client "$qresult\n";   chop($qresult);
                            } else {   print $client "$qresult\n";
                                print $client "error: ".($!+0)      } else {
    ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                        "while attempting courseiddump\n";      ." untie(GDBM) Failed ".
                            }      "while attempting courseiddump\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting courseiddump\n";   ." tie(GDBM) Failed ".
                        }   "while attempting courseiddump\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ----------------------------------------------------------------------- idput  # ----------------------------------------------------------------------- idput
                    } elsif ($userinput =~ /^idput/) {   } elsif ($userinput =~ /^idput/) {
                        my ($cmd,$udom,$what)=split(/:/,$userinput);      if(isClient) {
                        chomp($what);   my ($cmd,$udom,$what)=split(/:/,$userinput);
                        $udom=~s/\W//g;   chomp($what);
                        my $proname="$perlvar{'lonUsersDir'}/$udom/ids";   $udom=~s/\W//g;
                        my $now=time;   my $proname="$perlvar{'lonUsersDir'}/$udom/ids";
                        {   my $now=time;
    my $hfh;   {
    if (      my $hfh;
                              $hfh=IO::File->new(">>$proname.hist")      if (
        ) { print $hfh "P:$now:$what\n"; }   $hfh=IO::File->new(">>$proname.hist")
        }   ) { print $hfh "P:$now:$what\n"; }
                        my @pairs=split(/\&/,$what);   }
        my %hash;   my @pairs=split(/\&/,$what);
        if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_WRCREAT(),0640)) {   my %hash;
                            foreach my $pair (@pairs) {   if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_WRCREAT(),0640)) {
        my ($key,$value)=split(/=/,$pair);      foreach my $pair (@pairs) {
                                $hash{$key}=$value;   my ($key,$value)=split(/=/,$pair);
                            }   $hash{$key}=$value;
    if (untie(%hash)) {      }
                               print $client "ok\n";      if (untie(%hash)) {
                            } else {   print $client "ok\n";
                               print $client "error: ".($!+0)      } else {
   ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
                                       "while attempting idput\n";      ." untie(GDBM) Failed ".
                            }      "while attempting idput\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                       "while attempting idput\n";   ." tie(GDBM) Failed ".
                        }   "while attempting idput\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ----------------------------------------------------------------------- idget  # ----------------------------------------------------------------------- idget
                    } elsif ($userinput =~ /^idget/) {   } elsif ($userinput =~ /^idget/) {
                        my ($cmd,$udom,$what)=split(/:/,$userinput);      if(isClient) {
                        chomp($what);   my ($cmd,$udom,$what)=split(/:/,$userinput);
                        $udom=~s/\W//g;   chomp($what);
                        my $proname="$perlvar{'lonUsersDir'}/$udom/ids";   $udom=~s/\W//g;
                        my @queries=split(/\&/,$what);   my $proname="$perlvar{'lonUsersDir'}/$udom/ids";
                        my $qresult='';   my @queries=split(/\&/,$what);
        my %hash;   my $qresult='';
        if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_READER(),0640)) {   my %hash;
                            for (my $i=0;$i<=$#queries;$i++) {   if (tie(%hash,'GDBM_File',"$proname.db",&GDBM_READER(),0640)) {
                                $qresult.="$hash{$queries[$i]}&";      for (my $i=0;$i<=$#queries;$i++) {
                            }   $qresult.="$hash{$queries[$i]}&";
    if (untie(%hash)) {      }
        $qresult=~s/\&$//;      if (untie(%hash)) {
        print $client "$qresult\n";   $qresult=~s/\&$//;
                            } else {   print $client "$qresult\n";
        print $client "error: ".($!+0)      } else {
    ." untie(GDBM) Failed ".   print $client "error: ".($!+0)
        "while attempting idget\n";      ." untie(GDBM) Failed ".
                            }      "while attempting idget\n";
                        } else {      }
                            print $client "error: ".($!+0)   } else {
        ." tie(GDBM) Failed ".      print $client "error: ".($!+0)
                                    "while attempting idget\n";   ." tie(GDBM) Failed ".
                        }   "while attempting idget\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ---------------------------------------------------------------------- tmpput  # ---------------------------------------------------------------------- tmpput
                    } elsif ($userinput =~ /^tmpput/) {   } elsif ($userinput =~ /^tmpput/) {
                        my ($cmd,$what)=split(/:/,$userinput);      if(isClient) {
        my $store;   my ($cmd,$what)=split(/:/,$userinput);
                        $tmpsnum++;   my $store;
                        my $id=$$.'_'.$clientip.'_'.$tmpsnum;   $tmpsnum++;
                        $id=~s/\W/\_/g;   my $id=$$.'_'.$clientip.'_'.$tmpsnum;
                        $what=~s/\n//g;   $id=~s/\W/\_/g;
                        my $execdir=$perlvar{'lonDaemons'};   $what=~s/\n//g;
                        if ($store=IO::File->new(">$execdir/tmp/$id.tmp")) {   my $execdir=$perlvar{'lonDaemons'};
    print $store $what;   if ($store=IO::File->new(">$execdir/tmp/$id.tmp")) {
    close $store;      print $store $what;
    print $client "$id\n";      close $store;
        }      print $client "$id\n";
        else {   }
    print $client "error: ".($!+0)   else {
        ."IO::File->new Failed ".      print $client "error: ".($!+0)
                                    "while attempting tmpput\n";   ."IO::File->new Failed ".
        }   "while attempting tmpput\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
       
       }
       
 # ---------------------------------------------------------------------- tmpget  # ---------------------------------------------------------------------- tmpget
                    } elsif ($userinput =~ /^tmpget/) {   } elsif ($userinput =~ /^tmpget/) {
                        my ($cmd,$id)=split(/:/,$userinput);      if(isClient) {
                        chomp($id);   my ($cmd,$id)=split(/:/,$userinput);
                        $id=~s/\W/\_/g;   chomp($id);
                        my $store;   $id=~s/\W/\_/g;
                        my $execdir=$perlvar{'lonDaemons'};   my $store;
                        if ($store=IO::File->new("$execdir/tmp/$id.tmp")) {   my $execdir=$perlvar{'lonDaemons'};
                            my $reply=<$store>;   if ($store=IO::File->new("$execdir/tmp/$id.tmp")) {
    print $client "$reply\n";      my $reply=<$store>;
                            close $store;      print $client "$reply\n";
        }      close $store;
        else {   }
    print $client "error: ".($!+0)   else {
        ."IO::File->new Failed ".      print $client "error: ".($!+0)
                                    "while attempting tmpget\n";   ."IO::File->new Failed ".
        }   "while attempting tmpget\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
         
       }
 # ---------------------------------------------------------------------- tmpdel  # ---------------------------------------------------------------------- tmpdel
                    } elsif ($userinput =~ /^tmpdel/) {   } elsif ($userinput =~ /^tmpdel/) {
                        my ($cmd,$id)=split(/:/,$userinput);      if(isClient) {
                        chomp($id);   my ($cmd,$id)=split(/:/,$userinput);
                        $id=~s/\W/\_/g;   chomp($id);
                        my $execdir=$perlvar{'lonDaemons'};   $id=~s/\W/\_/g;
                        if (unlink("$execdir/tmp/$id.tmp")) {   my $execdir=$perlvar{'lonDaemons'};
    print $client "ok\n";   if (unlink("$execdir/tmp/$id.tmp")) {
        } else {      print $client "ok\n";
    print $client "error: ".($!+0)   } else {
        ."Unlink tmp Failed ".      print $client "error: ".($!+0)
                                    "while attempting tmpdel\n";   ."Unlink tmp Failed ".
        }   "while attempting tmpdel\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
        
       }
 # -------------------------------------------------------------------------- ls  # -------------------------------------------------------------------------- ls
                    } elsif ($userinput =~ /^ls/) {   } elsif ($userinput =~ /^ls/) {
                        my ($cmd,$ulsdir)=split(/:/,$userinput);      if(isClient) {
                        my $ulsout='';   my $obs;
                        my $ulsfn;   my $rights;
                        if (-e $ulsdir) {   my ($cmd,$ulsdir)=split(/:/,$userinput);
                            if(-d $ulsdir) {   my $ulsout='';
                                if (opendir(LSDIR,$ulsdir)) {   my $ulsfn;
                                    while ($ulsfn=readdir(LSDIR)) {   if (-e $ulsdir) {
                                        my @ulsstats=stat($ulsdir.'/'.$ulsfn);      if(-d $ulsdir) {
                                        $ulsout.=$ulsfn.'&'.   if (opendir(LSDIR,$ulsdir)) {
                                                 join('&',@ulsstats).':';      while ($ulsfn=readdir(LSDIR)) {
                                    }   undef $obs, $rights; 
                                    closedir(LSDIR);   my @ulsstats=stat($ulsdir.'/'.$ulsfn);
                                }   #We do some obsolete checking here
                            } else {   if(-e $ulsdir.'/'.$ulsfn.".meta") { 
                                my @ulsstats=stat($ulsdir);      open(FILE, $ulsdir.'/'.$ulsfn.".meta");
                                $ulsout.=$ulsfn.'&'.join('&',@ulsstats).':';      my @obsolete=<FILE>;
                            }      foreach my $obsolete (@obsolete) {
                        } else {          if($obsolete =~ m|(<obsolete>)(on)|) { $obs = 1; } 
                           $ulsout='no_such_dir';   if($obsolete =~ m|(<copyright>)(default)|) { $rights = 1; }
                        }      }
                        if ($ulsout eq '') { $ulsout='empty'; }   }
                        print $client "$ulsout\n";   $ulsout.=$ulsfn.'&'.join('&',@ulsstats);
    if($obs eq '1') { $ulsout.="&1"; }
    else { $ulsout.="&0"; }
    if($rights eq '1') { $ulsout.="&1:"; }
    else { $ulsout.="&0:"; }
       }
       closedir(LSDIR);
    }
       } else {
    my @ulsstats=stat($ulsdir);
    $ulsout.=$ulsfn.'&'.join('&',@ulsstats).':';
       }
    } else {
       $ulsout='no_such_dir';
    }
    if ($ulsout eq '') { $ulsout='empty'; }
    print $client "$ulsout\n";
       } else {
    Reply($client, "refused\n", $userinput);
        
       }
 # ----------------------------------------------------------------- setannounce  # ----------------------------------------------------------------- setannounce
                    } elsif ($userinput =~ /^setannounce/) {   } elsif ($userinput =~ /^setannounce/) {
        my ($cmd,$announcement)=split(/:/,$userinput);      if (isClient) {
        chomp($announcement);   my ($cmd,$announcement)=split(/:/,$userinput);
        $announcement=&unescape($announcement);   chomp($announcement);
                        if (my $store=IO::File->new('>'.$perlvar{'lonDocRoot'}.   $announcement=&unescape($announcement);
  '/announcement.txt')) {   if (my $store=IO::File->new('>'.$perlvar{'lonDocRoot'}.
    print $store $announcement;      '/announcement.txt')) {
                            close $store;      print $store $announcement;
    print $client "ok\n";      close $store;
        } else {      print $client "ok\n";
    print $client "error: ".($!+0)."\n";   } else {
        }      print $client "error: ".($!+0)."\n";
    }
       } else {
    Reply($client, "refused\n", $userinput);
          
       }
 # ------------------------------------------------------------------ Hanging up  # ------------------------------------------------------------------ Hanging up
                    } elsif (($userinput =~ /^exit/) ||   } elsif (($userinput =~ /^exit/) ||
                             ($userinput =~ /^init/)) {   ($userinput =~ /^init/)) { # no restrictions.
                        &logthis(      &logthis(
       "Client $clientip ($hostid{$clientip}) hanging up: $userinput");       "Client $clientip ($clientname) hanging up: $userinput");
                        print $client "bye\n";      print $client "bye\n";
                        $client->close();      $client->shutdown(2);        # shutdown the socket forcibly.
        last;      $client->close();
       last;
   
   # ---------------------------------- set current host/domain
    } elsif ($userinput =~ /^sethost:/) {
       if (isClient) {
    print $client &sethost($userinput)."\n";
       } else {
    print $client "refused\n";
       }
   #---------------------------------- request file (?) version.
    } elsif ($userinput =~/^version:/) {
       if (isClient) {
    print $client &version($userinput)."\n";
       } else {
    print $client "refused\n";
       }
   #------------------------------- is auto-enrollment enabled?
                   } elsif ($userinput =~/^autorun/) {
                       if (isClient) {
                           my $outcome = &localenroll::run();
                           print $client "$outcome\n";
                       } else {
                           print $client "0\n";
                       }
   #------------------------------- get official sections (for auto-enrollment).
                   } elsif ($userinput =~/^autogetsections/) {
                       if (isClient) {
                           my ($cmd,$coursecode)=split(/:/,$userinput);
                           my @secs = &localenroll::get_sections($coursecode);
                           my $seclist = &escape(join(':',@secs));
                           print $client "$seclist\n";
                       } else {
                           print $client "refused\n";
                       }
   #----------------------- validate owner of new course section (for auto-enrollment).
                   } elsif ($userinput =~/^autonewcourse/) {
                       if (isClient) {
                           my ($cmd,$course_id,$owner)=split(/:/,$userinput);
                           my $outcome = &localenroll::new_course($course_id,$owner);
                           print $client "$outcome\n";
                       } else {
                           print $client "refused\n";
                       }
   #-------------- validate course section in schedule of classes (for auto-enrollment).
                   } elsif ($userinput =~/^autovalidatecourse/) {
                       if (isClient) {
                           my ($cmd,$course_id)=split(/:/,$userinput);
                           my $outcome=&localenroll::validate_courseID($course_id);
                           print $client "$outcome\n";
                       } else {
                           print $client "refused\n";
                       }
   #--------------------------- create password for new user (for auto-enrollment).
                   } elsif ($userinput =~/^autocreatepassword/) {
                       if (isClient) {
                           my ($cmd,$authparam)=split(/:/,$userinput);
                           my ($create_passwd,$authchk) = @_;
                           ($authparam,$create_passwd,$authchk) = &localenroll::create_password($authparam);
                           print $client &escape($authparam.':'.$create_passwd.':'.$authchk)."\n";
                       } else {
                           print $client "refused\n";
                       }
   #---------------------------  read and remove temporary files (for auto-enrollment).
                   } elsif ($userinput =~/^autoretrieve/) {
                       if (isClient) {
                           my ($cmd,$filename) = split(/:/,$userinput);
                           my $source = $perlvar{'lonDaemons'}.'/tmp/'.$filename;
                           if ( (-e $source) && ($filename ne '') ) {
                               my $reply = '';
                               if (open(my $fh,$source)) {
                                   while (<$fh>) {
                                       chomp($_);
                                       $_ =~ s/^\s+//g;
                                       $_ =~ s/\s+$//g;
                                       $reply .= $_;
                                   }
                                   close($fh);
                                   print $client &escape($reply)."\n";
   #                                unlink($source);
                               } else {
                                   print $client "error\n";
                               }
                           } else {
                               print $client "error\n";
                           }
                       } else {
                           print $client "refused\n";
                       }
 # ------------------------------------------------------------- unknown command  # ------------------------------------------------------------- unknown command
    } elsif ($userinput =~ /^sethost:/) {  
        print $client &sethost($userinput)."\n";   } else {
    } elsif ($userinput =~/^version:/) {      # unknown command
        print $client &version($userinput)."\n";      print $client "unknown_cmd\n";
                    } else {   }
                        # unknown command  
                        print $client "unknown_cmd\n";  
                    }  
 # -------------------------------------------------------------------- complete  # -------------------------------------------------------------------- complete
    alarm(0);   alarm(0);
                    &status('Listening to '.$hostid{$clientip});   &status('Listening to '.$clientname);
        }      }
 # --------------------------------------------- client unknown or fishy, refuse  # --------------------------------------------- client unknown or fishy, refuse
             } else {   } else {
         print $client "refused\n";      print $client "refused\n";
                 $client->close();      $client->close();
                 &logthis("<font color=blue>WARNING: "      &logthis("<font color='blue'>WARNING: "
                 ."Rejected client $clientip, closing connection</font>");       ."Rejected client $clientip, closing connection</font>");
             }   }
  }                   }             
       
 # =============================================================================  # =============================================================================
              
  &logthis("<font color=red>CRITICAL: "      &logthis("<font color='red'>CRITICAL: "
  ."Disconnect from $clientip ($hostid{$clientip})</font>");           ."Disconnect from $clientip ($clientname)</font>");    
       
       
         # this exit is VERY important, otherwise the child will become      # this exit is VERY important, otherwise the child will become
         # a producer of more and more children, forking yourself into      # a producer of more and more children, forking yourself into
         # process death.      # process death.
         exit;      exit;
           
 }  }
   
Line 2237  sub make_new_child { Line 3232  sub make_new_child {
 #  #
 sub ManagePermissions  sub ManagePermissions
 {  {
     my $request = shift;  
     my $domain  = shift;      my ($request, $domain, $user, $authtype) = @_;
     my $user    = shift;  
     my $authtype= shift;  
   
     # See if the request is of the form /$domain/_au      # See if the request is of the form /$domain/_au
     &logthis("ruequest is $request");  
     if($request =~ /^(\/$domain\/_au)$/) { # It's an author rolesput...      if($request =~ /^(\/$domain\/_au)$/) { # It's an author rolesput...
  my $execdir = $perlvar{'lonDaemons'};   my $execdir = $perlvar{'lonDaemons'};
  my $userhome= "/home/$user" ;   my $userhome= "/home/$user" ;
Line 2258  sub ManagePermissions Line 3250  sub ManagePermissions
 #  #
 sub GetAuthType   sub GetAuthType 
 {  {
     my $domain = shift;  
     my $user   = shift;      my ($domain, $user)  = @_;
   
     Debug("GetAuthType( $domain, $user ) \n");      Debug("GetAuthType( $domain, $user ) \n");
     my $proname    = &propath($domain, $user);       my $proname    = &propath($domain, $user); 
Line 2368  sub chatadd { Line 3360  sub chatadd {
 sub unsub {  sub unsub {
     my ($fname,$clientip)=@_;      my ($fname,$clientip)=@_;
     my $result;      my $result;
     if (unlink("$fname.$hostid{$clientip}")) {      my $unsubs = 0; # Number of successful unsubscribes:
  $result="ok\n";  
     } else {  
  $result="not_subscribed\n";      # An old way subscriptions were handled was to have a 
     }      # subscription marker file:
   
       Debug("Attempting unlink of $fname.$clientname");
       if (unlink("$fname.$clientname")) {
    $unsubs++; # Successful unsub via marker file.
       } 
   
       # The more modern way to do it is to have a subscription list
       # file:
   
     if (-e "$fname.subscription") {      if (-e "$fname.subscription") {
  my $found=&addline($fname,$hostid{$clientip},$clientip,'');   my $found=&addline($fname,$clientname,$clientip,'');
  if ($found) { $result="ok\n"; }   if ($found) { 
       $unsubs++;
    }
       } 
   
       #  If either or both of these mechanisms succeeded in unsubscribing a 
       #  resource we can return ok:
   
       if($unsubs) {
    $result = "ok\n";
     } else {      } else {
  if ($result != "ok\n") { $result="not_subscribed\n"; }   $result = "not_subscribed\n";
     }      }
   
     return $result;      return $result;
 }  }
   
Line 2406  sub currentversion { Line 3417  sub currentversion {
 # see if this is a regular file (ignore links produced earlier)  # see if this is a regular file (ignore links produced earlier)
     my $thisfile=$ulsdir.'/'.$ulsfn;      my $thisfile=$ulsdir.'/'.$ulsfn;
     unless (-l $thisfile) {      unless (-l $thisfile) {
  if ($thisfile=~/\Q$fnamere1\E(\d+)\Q$fnamere2\E/) {   if ($thisfile=~/\Q$fnamere1\E(\d+)\Q$fnamere2\E$/) {
     if ($1>$version) { $version=$1; }      if ($1>$version) { $version=$1; }
  }   }
     }      }
Line 2454  sub subscribe { Line 3465  sub subscribe {
     if (-d $fname) {      if (-d $fname) {
  $result="directory\n";   $result="directory\n";
     } else {      } else {
  if (-e "$fname.$hostid{$clientip}") {&unsub($fname,$clientip);}   if (-e "$fname.$clientname") {&unsub($fname,$clientip);}
  my $now=time;   my $now=time;
  my $found=&addline($fname,$hostid{$clientip},$clientip,   my $found=&addline($fname,$clientname,$clientip,
    "$hostid{$clientip}:$clientip:$now\n");     "$clientname:$clientip:$now\n");
  if ($found) { $result="$fname\n"; }   if ($found) { $result="$fname\n"; }
  # if they were subscribed to only meta data, delete that   # if they were subscribed to only meta data, delete that
                 # subscription, when you subscribe to a file you also get                  # subscription, when you subscribe to a file you also get
Line 2500  sub make_passwd_file { Line 3511  sub make_passwd_file {
  }   }
     } elsif ($umode eq 'unix') {      } elsif ($umode eq 'unix') {
  {   {
       #
       #  Don't allow the creation of privileged accounts!!! that would
       #  be real bad!!!
       #
       my $uid = getpwnam($uname);
       if((defined $uid) && ($uid == 0)) {
    &logthis(">>>Attempted to create privilged account blocked");
    return "no_priv_account_error\n";
       }
   
     my $execpath="$perlvar{'lonDaemons'}/"."lcuseradd";      my $execpath="$perlvar{'lonDaemons'}/"."lcuseradd";
     {      {
  &Debug("Executing external: ".$execpath);   &Debug("Executing external: ".$execpath);
Line 2532  sub sethost { Line 3553  sub sethost {
     my (undef,$hostid)=split(/:/,$remotereq);      my (undef,$hostid)=split(/:/,$remotereq);
     if (!defined($hostid)) { $hostid=$perlvar{'lonHostID'}; }      if (!defined($hostid)) { $hostid=$perlvar{'lonHostID'}; }
     if ($hostip{$perlvar{'lonHostID'}} eq $hostip{$hostid}) {      if ($hostip{$perlvar{'lonHostID'}} eq $hostip{$hostid}) {
  $currenthostid=$hostid;   $currenthostid  =$hostid;
  $currentdomainid=$hostdom{$hostid};   $currentdomainid=$hostdom{$hostid};
  &logthis("Setting hostid to $hostid, and domain to $currentdomainid");   &logthis("Setting hostid to $hostid, and domain to $currentdomainid");
     } else {      } else {
Line 2559  sub userload { Line 3580  sub userload {
  while ($filename=readdir(LONIDS)) {   while ($filename=readdir(LONIDS)) {
     if ($filename eq '.' || $filename eq '..') {next;}      if ($filename eq '.' || $filename eq '..') {next;}
     my ($mtime)=(stat($perlvar{'lonIDsDir'}.'/'.$filename))[9];      my ($mtime)=(stat($perlvar{'lonIDsDir'}.'/'.$filename))[9];
     if ($curtime-$mtime < 3600) { $numusers++; }      if ($curtime-$mtime < 1800) { $numusers++; }
  }   }
  closedir(LONIDS);   closedir(LONIDS);
     }      }
Line 2572  sub userload { Line 3593  sub userload {
     return $userloadpercent;      return $userloadpercent;
 }  }
   
   
 # ----------------------------------- POD (plain old documentation, CPAN style)  # ----------------------------------- POD (plain old documentation, CPAN style)
   
 =head1 NAME  =head1 NAME

Removed from v.1.152  
changed lines
  Added in v.1.196


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>