[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/auth/mnet/ -> auth.php (source)

   1  <?php // $Id: auth.php,v 1.27.2.7 2008/08/13 23:31:01 peterbulmer Exp $
   2  
   3  /**
   4   * @author Martin Dougiamas
   5   * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
   6   * @package moodle multiauth
   7   *
   8   * Authentication Plugin: Moodle Network Authentication
   9   *
  10   * Multiple host authentication support for Moodle Network.
  11   *
  12   * 2006-11-01  File created.
  13   */
  14  
  15  if (!defined('MOODLE_INTERNAL')) {
  16      die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
  17  }
  18  
  19  require_once($CFG->libdir.'/authlib.php');
  20  
  21  /**
  22   * Moodle Network authentication plugin.
  23   */
  24  class auth_plugin_mnet extends auth_plugin_base {
  25  
  26      /**
  27       * Constructor.
  28       */
  29      function auth_plugin_mnet() {
  30          $this->authtype = 'mnet';
  31          $this->config = get_config('auth/mnet');
  32      }
  33  
  34      /**
  35       * Provides the allowed RPC services from this class as an array.
  36       * @return array  Allowed RPC services.
  37       */
  38      function mnet_publishes() {
  39  
  40          $sso_idp = array();
  41          $sso_idp['name']        = 'sso_idp'; // Name & Description go in lang file
  42          $sso_idp['apiversion']  = 1;
  43          $sso_idp['methods']     = array('user_authorise','keepalive_server', 'kill_children',
  44                                          'refresh_log', 'fetch_user_image', 'fetch_theme_info',
  45                                          'update_enrolments');
  46  
  47          $sso_sp = array();
  48          $sso_sp['name']         = 'sso_sp'; // Name & Description go in lang file
  49          $sso_sp['apiversion']   = 1;
  50          $sso_sp['methods']      = array('keepalive_client','kill_child');
  51  
  52          return array($sso_idp, $sso_sp);
  53      }
  54  
  55      /**
  56       * This function is normally used to determine if the username and password
  57       * are correct for local logins. Always returns false, as local users do not
  58       * need to login over mnet xmlrpc.
  59       *
  60       * @param string $username The username
  61       * @param string $password The password
  62       * @return bool Authentication success or failure.
  63       */
  64      function user_login($username, $password) {
  65          return false; // error("Remote MNET users cannot login locally.");
  66      }
  67  
  68      /**
  69       * Return user data for the provided token, compare with user_agent string.
  70       *
  71       * @param  string $token    The unique ID provided by remotehost.
  72       * @param  string $UA       User Agent string.
  73       * @return array  $userdata Array of user info for remote host
  74       */
  75      function user_authorise($token, $useragent) {
  76          global $CFG, $MNET, $SITE, $MNET_REMOTE_CLIENT;
  77          require_once $CFG->dirroot . '/mnet/xmlrpc/server.php';
  78  
  79          $mnet_session = get_record('mnet_session', 'token', $token, 'useragent', $useragent);
  80          if (empty($mnet_session)) {
  81              echo mnet_server_fault(1, get_string('authfail_nosessionexists', 'mnet'));
  82              exit;
  83          }
  84  
  85          // check session confirm timeout
  86          if ($mnet_session->confirm_timeout < time()) {
  87              echo mnet_server_fault(2, get_string('authfail_sessiontimedout', 'mnet'));
  88              exit;
  89          }
  90  
  91          // session okay, try getting the user
  92          if (!$user = get_record('user', 'id', $mnet_session->userid)) {
  93              echo mnet_server_fault(3, get_string('authfail_usermismatch', 'mnet'));
  94              exit;
  95          }
  96  
  97          $userdata = array();
  98          $userdata['username']                = $user->username;
  99          $userdata['email']                   = $user->email;
 100          $userdata['auth']                    = 'mnet';
 101          $userdata['confirmed']               = $user->confirmed;
 102          $userdata['deleted']                 = $user->deleted;
 103          $userdata['firstname']               = $user->firstname;
 104          $userdata['lastname']                = $user->lastname;
 105          $userdata['city']                    = $user->city;
 106          $userdata['country']                 = $user->country;
 107          $userdata['lang']                    = $user->lang;
 108          $userdata['timezone']                = $user->timezone;
 109          $userdata['description']             = $user->description;
 110          $userdata['mailformat']              = $user->mailformat;
 111          $userdata['maildigest']              = $user->maildigest;
 112          $userdata['maildisplay']             = $user->maildisplay;
 113          $userdata['htmleditor']              = $user->htmleditor;
 114          $userdata['wwwroot']                 = $MNET->wwwroot;
 115          $userdata['session.gc_maxlifetime']  = ini_get('session.gc_maxlifetime');
 116          $userdata['picture']                 = $user->picture;
 117          if (!empty($user->picture)) {
 118              $imagefile = make_user_directory($user->id, true) . "/f1.jpg";
 119              if (file_exists($imagefile)) {
 120                  $userdata['imagehash'] = sha1(file_get_contents($imagefile));
 121              }
 122          }
 123  
 124          $userdata['myhosts'] = array();
 125          if($courses = get_my_courses($user->id, 'id', 'id, visible')) {
 126              $userdata['myhosts'][] = array('name'=> $SITE->shortname, 'url' => $CFG->wwwroot, 'count' => count($courses));
 127          }
 128  
 129          $sql = "
 130                  SELECT
 131                      h.name as hostname,
 132                      h.wwwroot,
 133                      h.id as hostid,
 134                      count(c.id) as count
 135                  FROM
 136                      {$CFG->prefix}mnet_enrol_course c,
 137                      {$CFG->prefix}mnet_enrol_assignments a,
 138                      {$CFG->prefix}mnet_host h
 139                  WHERE
 140                      c.id      =  a.courseid   AND
 141                      c.hostid  =  h.id         AND
 142                      a.userid  = '{$user->id}' AND
 143                      c.hostid != '{$MNET_REMOTE_CLIENT->id}'
 144                  GROUP BY
 145                      h.name,
 146                      h.id,
 147                      h.wwwroot";
 148          if ($courses = get_records_sql($sql)) {
 149              foreach($courses as $course) {
 150                  $userdata['myhosts'][] = array('name'=> $course->hostname, 'url' => $CFG->wwwroot.'/auth/mnet/jump.php?hostid='.$course->hostid, 'count' => $course->count);
 151              }
 152          }
 153  
 154          return $userdata;
 155      }
 156  
 157      /**
 158       * Generate a random string for use as an RPC session token.
 159       */
 160      function generate_token() {
 161          return sha1(str_shuffle('' . mt_rand() . time()));
 162      }
 163  
 164      /**
 165       * Starts an RPC jump session and returns the jump redirect URL.
 166       */
 167      function start_jump_session($mnethostid, $wantsurl) {
 168          global $CFG;
 169          global $USER;
 170          global $MNET;
 171          require_once $CFG->dirroot . '/mnet/xmlrpc/client.php';
 172  
 173          // check remote login permissions
 174          if (! has_capability('moodle/site:mnetlogintoremote', get_context_instance(CONTEXT_SYSTEM))
 175                  or is_mnet_remote_user($USER)
 176                  or $USER->username == 'guest'
 177                  or empty($USER->id)) {
 178              print_error('notpermittedtojump', 'mnet');
 179          }
 180  
 181          // check for SSO publish permission first
 182          if ($this->has_service($mnethostid, 'sso_sp') == false) {
 183              print_error('hostnotconfiguredforsso', 'mnet');
 184          }
 185  
 186          // set RPC timeout to 30 seconds if not configured
 187          // TODO: Is this needed/useful/problematic?
 188          if (empty($this->config->rpc_negotiation_timeout)) {
 189              set_config('rpc_negotiation_timeout', '30', 'auth/mnet');
 190          }
 191  
 192          // get the host info
 193          $mnet_peer = new mnet_peer();
 194          $mnet_peer->set_id($mnethostid);
 195  
 196          // set up the session
 197          $mnet_session = get_record('mnet_session',
 198                                     'userid',     $USER->id,
 199                                     'mnethostid', $mnethostid,
 200                                     'useragent',  sha1($_SERVER['HTTP_USER_AGENT']));
 201          if ($mnet_session == false) {
 202              $mnet_session = new object();
 203              $mnet_session->mnethostid = $mnethostid;
 204              $mnet_session->userid = $USER->id;
 205              $mnet_session->username = $USER->username;
 206              $mnet_session->useragent = sha1($_SERVER['HTTP_USER_AGENT']);
 207              $mnet_session->token = $this->generate_token();
 208              $mnet_session->confirm_timeout = time() + $this->config->rpc_negotiation_timeout;
 209              $mnet_session->expires = time() + (integer)ini_get('session.gc_maxlifetime');
 210              $mnet_session->session_id = session_id();
 211              if (! $mnet_session->id = insert_record('mnet_session', addslashes_object($mnet_session))) {
 212                  print_error('databaseerror', 'mnet');
 213              }
 214          } else {
 215              $mnet_session->useragent = sha1($_SERVER['HTTP_USER_AGENT']);
 216              $mnet_session->token = $this->generate_token();
 217              $mnet_session->confirm_timeout = time() + $this->config->rpc_negotiation_timeout;
 218              $mnet_session->expires = time() + (integer)ini_get('session.gc_maxlifetime');
 219              $mnet_session->session_id = session_id();
 220              if (false == update_record('mnet_session', addslashes_object($mnet_session))) {
 221                  print_error('databaseerror', 'mnet');
 222              }
 223          }
 224  
 225          // construct the redirection URL
 226          //$transport = mnet_get_protocol($mnet_peer->transport);
 227          $wantsurl = urlencode($wantsurl);
 228          $url = "{$mnet_peer->wwwroot}{$mnet_peer->application->sso_land_url}?token={$mnet_session->token}&idp={$MNET->wwwroot}&wantsurl={$wantsurl}";
 229  
 230          return $url;
 231      }
 232  
 233      /**
 234       * This function confirms the remote (ID provider) host's mnet session
 235       * by communicating the token and UA over the XMLRPC transport layer, and
 236       * returns the local user record on success.
 237       *
 238       *   @param string $token           The random session token.
 239       *   @param string $remotewwwroot   The ID provider wwwroot.
 240       *   @return array The local user record.
 241       */
 242      function confirm_mnet_session($token, $remotewwwroot) {
 243          global $CFG, $MNET, $SESSION;
 244          require_once $CFG->dirroot . '/mnet/xmlrpc/client.php';
 245  
 246          // verify the remote host is configured locally before attempting RPC call
 247          if (! $remotehost = get_record('mnet_host', 'wwwroot', $remotewwwroot, 'deleted', 0)) {
 248              print_error('notpermittedtoland', 'mnet');
 249          }
 250  
 251          // get the originating (ID provider) host info
 252          $remotepeer = new mnet_peer();
 253          $remotepeer->set_wwwroot($remotewwwroot);
 254  
 255          // set up the RPC request
 256          $mnetrequest = new mnet_xmlrpc_client();
 257          $mnetrequest->set_method('auth/mnet/auth.php/user_authorise');
 258  
 259          // set $token and $useragent parameters
 260          $mnetrequest->add_param($token);
 261          $mnetrequest->add_param(sha1($_SERVER['HTTP_USER_AGENT']));
 262  
 263          // Thunderbirds are go! Do RPC call and store response
 264          if ($mnetrequest->send($remotepeer) === true) {
 265              $remoteuser = (object) $mnetrequest->response;
 266          } else {
 267              foreach ($mnetrequest->error as $errormessage) {
 268                  list($code, $message) = array_map('trim',explode(':', $errormessage, 2));
 269                  if($code == 702) {
 270                      $site = get_site();
 271                      print_error('mnet_session_prohibited', 'mnet', $remotewwwroot, format_string($site->fullname));
 272                      exit;
 273                  }
 274                  $message .= "ERROR $code:<br/>$errormessage<br/>";
 275              }
 276              error("RPC auth/mnet/user_authorise:<br/>$message");
 277          }
 278          unset($mnetrequest);
 279  
 280          if (empty($remoteuser) or empty($remoteuser->username)) {
 281              print_error('unknownerror', 'mnet');
 282              exit;
 283          }
 284  
 285          $firsttime = false;
 286  
 287          // get the local record for the remote user
 288          $localuser = get_record('user', 'username', addslashes($remoteuser->username), 'mnethostid', $remotehost->id);
 289  
 290          // add the remote user to the database if necessary, and if allowed
 291          // TODO: refactor into a separate function
 292          if (empty($localuser) || ! $localuser->id) {
 293              if (empty($this->config->auto_add_remote_users)) {
 294                  print_error('nolocaluser', 'mnet');
 295              }
 296              $remoteuser->mnethostid = $remotehost->id;
 297              if (! insert_record('user', addslashes_object($remoteuser))) {
 298                  print_error('databaseerror', 'mnet');
 299              }
 300              $firsttime = true;
 301              if (! $localuser = get_record('user', 'username', addslashes($remoteuser->username), 'mnethostid', $remotehost->id)) {
 302                  print_error('nolocaluser', 'mnet');
 303              }
 304          }
 305  
 306          // check sso access control list for permission first
 307          if (!$this->can_login_remotely($localuser->username, $remotehost->id)) {
 308              print_error('sso_mnet_login_refused', 'mnet', '', array($localuser->username, $remotehost->name));
 309          }
 310  
 311          $session_gc_maxlifetime = 1440;
 312  
 313          // update the local user record with remote user data
 314          foreach ((array) $remoteuser as $key => $val) {
 315              if ($key == 'session.gc_maxlifetime') {
 316                  $session_gc_maxlifetime = $val;
 317                  continue;
 318              }
 319  
 320              // TODO: fetch image if it has changed
 321              if ($key == 'imagehash') {
 322                  $dirname = make_user_directory($localuser->id, true);
 323                  $filename = "$dirname/f1.jpg";
 324  
 325                  $localhash = '';
 326                  if (file_exists($filename)) {
 327                      $localhash = sha1(file_get_contents($filename));
 328                  } elseif (!file_exists($dirname)) {
 329                      mkdir($dirname);
 330                  }
 331  
 332                  if ($localhash != $val) {
 333                      // fetch image from remote host
 334                      $fetchrequest = new mnet_xmlrpc_client();
 335                      $fetchrequest->set_method('auth/mnet/auth.php/fetch_user_image');
 336                      $fetchrequest->add_param($localuser->username);
 337                      if ($fetchrequest->send($remotepeer) === true) {
 338                          if (strlen($fetchrequest->response['f1']) > 0) {
 339                              $imagecontents = base64_decode($fetchrequest->response['f1']);
 340                              file_put_contents($filename, $imagecontents);
 341                              $localuser->picture = 1;
 342                          }
 343                          if (strlen($fetchrequest->response['f2']) > 0) {
 344                              $imagecontents = base64_decode($fetchrequest->response['f2']);
 345                              file_put_contents($dirname.'/f2.jpg', $imagecontents);
 346                          }
 347                      }
 348                  }
 349              }
 350  
 351              if($key == 'myhosts') {
 352                  $localuser->mnet_foreign_host_array = array();
 353                  foreach($val as $rhost) {
 354                      $name  = clean_param($rhost['name'], PARAM_ALPHANUM);
 355                      $url   = clean_param($rhost['url'], PARAM_URL);
 356                      $count = clean_param($rhost['count'], PARAM_INT);
 357                      $url_is_local = stristr($url , $CFG->wwwroot);
 358                      if (!empty($name) && !empty($count) && empty($url_is_local)) {
 359                          $localuser->mnet_foreign_host_array[] = array('name'  => $name,
 360                                                                        'url'   => $url,
 361                                                                        'count' => $count);
 362                      }
 363                  }
 364              }
 365  
 366              $localuser->{$key} = $val;
 367          }
 368  
 369          $localuser->mnethostid = $remotepeer->id;
 370  
 371          $bool = update_record('user', addslashes_object($localuser));
 372          if (!$bool) {
 373              // TODO: Jonathan to clean up mess
 374              // Actually, this should never happen (modulo race conditions) - ML
 375              error("updating user failed in mnet/auth/confirm_mnet_session ");
 376          }
 377  
 378          // set up the session
 379          $mnet_session = get_record('mnet_session',
 380                                     'userid',     $localuser->id,
 381                                     'mnethostid', $remotepeer->id,
 382                                     'useragent',  sha1($_SERVER['HTTP_USER_AGENT']));
 383          if ($mnet_session == false) {
 384              $mnet_session = new object();
 385              $mnet_session->mnethostid = $remotepeer->id;
 386              $mnet_session->userid = $localuser->id;
 387              $mnet_session->username = $localuser->username;
 388              $mnet_session->useragent = sha1($_SERVER['HTTP_USER_AGENT']);
 389              $mnet_session->token = $token; // Needed to support simultaneous sessions
 390                                             // and preserving DB rec uniqueness
 391              $mnet_session->confirm_timeout = time();
 392              $mnet_session->expires = time() + (integer)$session_gc_maxlifetime;
 393              $mnet_session->session_id = session_id();
 394              if (! $mnet_session->id = insert_record('mnet_session', addslashes_object($mnet_session))) {
 395                  print_error('databaseerror', 'mnet');
 396              }
 397          } else {
 398              $mnet_session->expires = time() + (integer)$session_gc_maxlifetime;
 399              update_record('mnet_session', addslashes_object($mnet_session));
 400          }
 401  
 402          if (!$firsttime) {
 403              // repeat customer! let the IDP know about enrolments
 404              // we have for this user.
 405              // set up the RPC request
 406              $mnetrequest = new mnet_xmlrpc_client();
 407              $mnetrequest->set_method('auth/mnet/auth.php/update_enrolments');
 408  
 409              // pass username and an assoc array of "my courses"
 410              // with info so that the IDP can maintain mnet_enrol_assignments
 411              $mnetrequest->add_param($remoteuser->username);
 412              $fields = 'id, category, sortorder, fullname, shortname, idnumber, summary,
 413                         startdate, cost, currency, defaultrole, visible';
 414              $courses = get_my_courses($localuser->id, 'visible DESC,sortorder ASC', $fields);
 415              if (is_array($courses) && !empty($courses)) {
 416                  // Second request to do the JOINs that we'd have done
 417                  // inside get_my_courses() if we had been allowed
 418                  $sql = "SELECT c.id,
 419                                 cc.name AS cat_name, cc.description AS cat_description,
 420                                 r.shortname as defaultrolename
 421                          FROM {$CFG->prefix}course c
 422                            JOIN {$CFG->prefix}course_categories cc ON c.category = cc.id
 423                            LEFT OUTER JOIN {$CFG->prefix}role r  ON c.defaultrole = r.id
 424                          WHERE c.id IN (" . join(',',array_keys($courses)) . ')';
 425                  $extra = get_records_sql($sql);
 426  
 427                  $keys = array_keys($courses);
 428                  $defaultrolename = get_field('role', 'shortname', 'id', $CFG->defaultcourseroleid);
 429                  foreach ($keys AS $id) {
 430                      if ($courses[$id]->visible == 0) {
 431                          unset($courses[$id]);
 432                          continue;
 433                      }
 434                      $courses[$id]->cat_id          = $courses[$id]->category;
 435                      $courses[$id]->defaultroleid   = $courses[$id]->defaultrole;
 436                      unset($courses[$id]->category);
 437                      unset($courses[$id]->defaultrole);
 438                      unset($courses[$id]->visible);
 439  
 440                      $courses[$id]->cat_name        = $extra[$id]->cat_name;
 441                      $courses[$id]->cat_description = $extra[$id]->cat_description;
 442                      if (!empty($extra[$id]->defaultrolename)) {
 443                          $courses[$id]->defaultrolename = $extra[$id]->defaultrolename;
 444                      } else {
 445                          $courses[$id]->defaultrolename = $defaultrolename;
 446                      }
 447                      // coerce to array
 448                      $courses[$id] = (array)$courses[$id];
 449                  }
 450              } else {
 451                  // if the array is empty, send it anyway
 452                  // we may be clearing out stale entries
 453                  $courses = array();
 454              }
 455              $mnetrequest->add_param($courses);
 456  
 457              // Call 0800-RPC Now! -- we don't care too much if it fails
 458              // as it's just informational.
 459              if ($mnetrequest->send($remotepeer) === false) {
 460                  // error_log(print_r($mnetrequest->error,1));
 461              }
 462          }
 463  
 464          return $localuser;
 465      }
 466  
 467      /**
 468       * Invoke this function _on_ the IDP to update it with enrolment info local to
 469       * the SP right after calling user_authorise()
 470       *
 471       * Normally called by the SP after calling
 472       *
 473       *   @param string $username        The username
 474       *   @param string $courses         Assoc array of courses following the structure of mnet_enrol_course
 475       *   @return bool
 476       */
 477      function update_enrolments($username, $courses) {
 478          global $MNET_REMOTE_CLIENT, $CFG;
 479  
 480          if (empty($username) || !is_array($courses)) {
 481              return false;
 482          }
 483          // make sure it is a user we have an in active session
 484          // with that host...
 485          $userid = get_field('mnet_session', 'userid',
 486                              'username', addslashes($username),
 487                              'mnethostid', (int)$MNET_REMOTE_CLIENT->id);
 488          if (!$userid) {
 489              return false;
 490          }
 491  
 492          if (empty($courses)) { // no courses? clear out quickly
 493              delete_records('mnet_enrol_assignments',
 494                             'hostid', (int)$MNET_REMOTE_CLIENT->id,
 495                             'userid', $userid);
 496              return true;
 497          }
 498  
 499          // IMPORTANT: Ask for remoteid as the first element in the query, so
 500          // that the array that comes back is indexed on the same field as the
 501          // array that we have received from the remote client
 502          $sql = '
 503                  SELECT
 504                      c.remoteid,
 505                      c.id,
 506                      c.cat_id,
 507                      c.cat_name,
 508                      c.cat_description,
 509                      c.sortorder,
 510                      c.fullname,
 511                      c.shortname,
 512                      c.idnumber,
 513                      c.summary,
 514                      c.startdate,
 515                      c.cost,
 516                      c.currency,
 517                      c.defaultroleid,
 518                      c.defaultrolename,
 519                      a.id as assignmentid
 520                  FROM
 521                      '.$CFG->prefix.'mnet_enrol_course c
 522                  LEFT JOIN
 523                      '.$CFG->prefix.'mnet_enrol_assignments a
 524                  ON
 525                     (a.courseid = c.id AND
 526                      a.hostid   = c.hostid AND
 527                      a.userid = \''.$userid.'\')
 528                  WHERE
 529                      c.hostid = \''.(int)$MNET_REMOTE_CLIENT->id.'\'';
 530  
 531          $currentcourses = get_records_sql($sql);
 532  
 533          $local_courseid_array = array();
 534          foreach($courses as $course) {
 535  
 536              $course['remoteid'] = $course['id'];
 537              $course['hostid']   =  (int)$MNET_REMOTE_CLIENT->id;
 538              $userisregd         = false;
 539  
 540              // First up - do we have a record for this course?
 541              if (!array_key_exists($course['remoteid'], $currentcourses)) {
 542                  // No record - we must create it
 543                  $course['id']  =  insert_record('mnet_enrol_course', addslashes_object((object)$course));
 544                  $currentcourse = (object)$course;
 545              } else {
 546                  // Pointer to current course:
 547                  $currentcourse =& $currentcourses[$course['remoteid']];
 548                  // We have a record - is it up-to-date?
 549                  $course['id'] = $currentcourse->id;
 550  
 551                  $saveflag = false;
 552  
 553                  foreach($course as $key => $value) {
 554                      if ($currentcourse->$key != $value) {
 555                          $saveflag = true;
 556                          $currentcourse->$key = $value;
 557                      }
 558                  }
 559  
 560                  if ($saveflag) {
 561                      update_record('mnet_enrol_course', addslashes_object($currentcourse));
 562                  }
 563  
 564                  if (isset($currentcourse->assignmentid) && is_numeric($currentcourse->assignmentid)) {
 565                      $userisregd = true;
 566                  }
 567              }
 568  
 569              // By this point, we should always have a $dataObj->id
 570              $local_courseid_array[] = $course['id'];
 571  
 572              // Do we have a record for this assignment?
 573              if ($userisregd) {
 574                  // Yes - we know about this one already
 575                  // We don't want to do updates because the new data is probably
 576                  // 'less complete' than the data we have.
 577              } else {
 578                  // No - create a record
 579                  $assignObj = new stdClass();
 580                  $assignObj->userid    = $userid;
 581                  $assignObj->hostid    = (int)$MNET_REMOTE_CLIENT->id;
 582                  $assignObj->courseid  = $course['id'];
 583                  $assignObj->rolename  = $course['defaultrolename'];
 584                  $assignObj->id = insert_record('mnet_enrol_assignments', addslashes_object($assignObj));
 585              }
 586          }
 587  
 588          // Clean up courses that the user is no longer enrolled in.
 589          $local_courseid_string = implode(', ', $local_courseid_array);
 590          $whereclause = " userid = '$userid' AND hostid = '{$MNET_REMOTE_CLIENT->id}' AND courseid NOT IN ($local_courseid_string)";
 591          delete_records_select('mnet_enrol_assignments', $whereclause);
 592      }
 593  
 594      /**
 595       * Returns true if this authentication plugin is 'internal'.
 596       *
 597       * @return bool
 598       */
 599      function is_internal() {
 600          return false;
 601      }
 602  
 603      /**
 604       * Returns true if this authentication plugin can change the user's
 605       * password.
 606       *
 607       * @return bool
 608       */
 609      function can_change_password() {
 610          //TODO: it should be able to redirect, right?
 611          return false;
 612      }
 613  
 614      /**
 615       * Returns the URL for changing the user's pw, or false if the default can
 616       * be used.
 617       *
 618       * @return string
 619       */
 620      function change_password_url() {
 621          return '';
 622      }
 623  
 624      /**
 625       * Prints a form for configuring this authentication plugin.
 626       *
 627       * This function is called from admin/auth.php, and outputs a full page with
 628       * a form for configuring this plugin.
 629       *
 630       * @param array $page An object containing all the data for this page.
 631       */
 632      function config_form($config, $err, $user_fields) {
 633          global $CFG;
 634  
 635           $query = "
 636              SELECT
 637                  h.id,
 638                  h.name as hostname,
 639                  h.wwwroot,
 640                  h2idp.publish as idppublish,
 641                  h2idp.subscribe as idpsubscribe,
 642                  idp.name as idpname,
 643                  h2sp.publish as sppublish,
 644                  h2sp.subscribe as spsubscribe,
 645                  sp.name as spname
 646              FROM
 647                  {$CFG->prefix}mnet_host h
 648              LEFT JOIN
 649                  {$CFG->prefix}mnet_host2service h2idp
 650              ON
 651                 (h.id = h2idp.hostid AND
 652                 (h2idp.publish = 1 OR
 653                  h2idp.subscribe = 1))
 654              INNER JOIN
 655                  {$CFG->prefix}mnet_service idp
 656              ON
 657                 (h2idp.serviceid = idp.id AND
 658                  idp.name = 'sso_idp')
 659              LEFT JOIN
 660                  {$CFG->prefix}mnet_host2service h2sp
 661              ON
 662                 (h.id = h2sp.hostid AND
 663                 (h2sp.publish = 1 OR
 664                  h2sp.subscribe = 1))
 665              INNER JOIN
 666                  {$CFG->prefix}mnet_service sp
 667              ON
 668                 (h2sp.serviceid = sp.id AND
 669                  sp.name = 'sso_sp')
 670              WHERE
 671                 ((h2idp.publish = 1 AND h2sp.subscribe = 1) OR
 672                 (h2sp.publish = 1 AND h2idp.subscribe = 1)) AND
 673                  h.id != {$CFG->mnet_localhost_id}
 674              ORDER BY
 675                  h.name ASC";
 676  
 677          $id_providers       = array();
 678          $service_providers  = array();
 679          if ($resultset = get_records_sql($query)) {
 680              foreach($resultset as $hostservice) {
 681                  if(!empty($hostservice->idppublish) && !empty($hostservice->spsubscribe)) {
 682                      $service_providers[]= array('id' => $hostservice->id, 'name' => $hostservice->hostname, 'wwwroot' => $hostservice->wwwroot);
 683                  }
 684                  if(!empty($hostservice->idpsubscribe) && !empty($hostservice->sppublish)) {
 685                      $id_providers[]= array('id' => $hostservice->id, 'name' => $hostservice->hostname, 'wwwroot' => $hostservice->wwwroot);
 686                  }
 687              }
 688          }
 689  
 690          include  "config.html";
 691      }
 692  
 693      /**
 694       * Processes and stores configuration data for this authentication plugin.
 695       */
 696      function process_config($config) {
 697          // set to defaults if undefined
 698          if (!isset ($config->rpc_negotiation_timeout)) {
 699              $config->rpc_negotiation_timeout = '30';
 700          }
 701          if (!isset ($config->auto_add_remote_users)) {
 702              $config->auto_add_remote_users = '0';
 703          }
 704  
 705          // save settings
 706          set_config('rpc_negotiation_timeout', $config->rpc_negotiation_timeout, 'auth/mnet');
 707          set_config('auto_add_remote_users',   $config->auto_add_remote_users,   'auth/mnet');
 708  
 709          return true;
 710      }
 711  
 712      /**
 713       * Poll the IdP server to let it know that a user it has authenticated is still
 714       * online
 715       *
 716       * @return  void
 717       */
 718      function keepalive_client() {
 719          global $CFG, $MNET;
 720          $cutoff = time() - 300; // TODO - find out what the remote server's session
 721                                  // cutoff is, and preempt that
 722  
 723          $sql = "
 724              select
 725                  id,
 726                  username,
 727                  mnethostid
 728              from
 729                  {$CFG->prefix}user
 730              where
 731                  lastaccess > '$cutoff' AND
 732                  mnethostid != '{$CFG->mnet_localhost_id}'
 733              order by
 734                  mnethostid";
 735  
 736          $immigrants = get_records_sql($sql);
 737  
 738          if ($immigrants == false) {
 739              return true;
 740          }
 741  
 742          $usersArray = array();
 743          foreach($immigrants as $immigrant) {
 744              $usersArray[$immigrant->mnethostid][] = $immigrant->username;
 745          }
 746  
 747          require_once $CFG->dirroot . '/mnet/xmlrpc/client.php';
 748          foreach($usersArray as $mnethostid => $users) {
 749              $mnet_peer = new mnet_peer();
 750              $mnet_peer->set_id($mnethostid);
 751  
 752              $mnet_request = new mnet_xmlrpc_client();
 753              $mnet_request->set_method('auth/mnet/auth.php/keepalive_server');
 754  
 755              // set $token and $useragent parameters
 756              $mnet_request->add_param($users);
 757  
 758              if ($mnet_request->send($mnet_peer) === true) {
 759                  if (!isset($mnet_request->response['code'])) {
 760                      debugging("Server side error has occured on host $mnethostid");
 761                      continue;
 762                  } elseif ($mnet_request->response['code'] > 0) {
 763                      debugging($mnet_request->response['message']);
 764                  }
 765  
 766                  if (!isset($mnet_request->response['last log id'])) {
 767                      debugging("Server side error has occured on host $mnethostid\nNo log ID was received.");
 768                      continue;
 769                  }
 770              } else {
 771                  debugging("Server side error has occured on host $mnethostid: " .
 772                            join("\n", $mnet_request->error));
 773                  break;
 774              }
 775  
 776              $query = "SELECT
 777                            l.id as remoteid,
 778                            l.time,
 779                            l.userid,
 780                            l.ip,
 781                            l.course,
 782                            l.module,
 783                            l.cmid,
 784                            l.action,
 785                            l.url,
 786                            l.info,
 787                            c.fullname as coursename,
 788                            c.modinfo as modinfo,
 789                            u.username
 790                        FROM
 791                            {$CFG->prefix}user u,
 792                            {$CFG->prefix}log l,
 793                            {$CFG->prefix}course c
 794                        WHERE
 795                            l.userid = u.id AND
 796                            u.mnethostid = '$mnethostid' AND
 797                            l.id > '".$mnet_request->response['last log id']."' AND
 798                            c.id = l.course
 799                        ORDER BY
 800                            remoteid ASC";
 801  
 802              $results = get_records_sql($query);
 803  
 804              if (false == $results) continue;
 805  
 806              $param = array();
 807  
 808              foreach($results as $result) {
 809                  if (!empty($result->modinfo) && !empty($result->cmid)) {
 810                      $modinfo = unserialize($result->modinfo);
 811                      unset($result->modinfo);
 812                      $modulearray = array();
 813                      foreach($modinfo as $module) {
 814                          $modulearray[$module->cm] = urldecode($module->name);
 815                      }
 816                      $result->resource_name = $modulearray[$result->cmid];
 817                  } else {
 818                      $result->resource_name = '';
 819                  }
 820  
 821                  $param[] = array (
 822                                      'remoteid'      => $result->remoteid,
 823                                      'time'          => $result->time,
 824                                      'userid'        => $result->userid,
 825                                      'ip'            => $result->ip,
 826                                      'course'        => $result->course,
 827                                      'coursename'    => $result->coursename,
 828                                      'module'        => $result->module,
 829                                      'cmid'          => $result->cmid,
 830                                      'action'        => $result->action,
 831                                      'url'           => $result->url,
 832                                      'info'          => $result->info,
 833                                      'resource_name' => $result->resource_name,
 834                                      'username'      => $result->username
 835                                   );
 836              }
 837  
 838              unset($result);
 839  
 840              $mnet_request = new mnet_xmlrpc_client();
 841              $mnet_request->set_method('auth/mnet/auth.php/refresh_log');
 842  
 843              // set $token and $useragent parameters
 844              $mnet_request->add_param($param);
 845  
 846              if ($mnet_request->send($mnet_peer) === true) {
 847                  if ($mnet_request->response['code'] > 0) {
 848                      debugging($mnet_request->response['message']);
 849                  }
 850              } else {
 851                  debugging("Server side error has occured on host $mnet_peer->ip: " .join("\n", $mnet_request->error));
 852              }
 853          }
 854      }
 855  
 856      /**
 857       * Receives an array of log entries from an SP and adds them to the mnet_log
 858       * table
 859       *
 860       * @param   array   $array      An array of usernames
 861       * @return  string              "All ok" or an error message
 862       */
 863      function refresh_log($array) {
 864          global $CFG, $MNET_REMOTE_CLIENT;
 865  
 866          // We don't want to output anything to the client machine
 867          $start = ob_start();
 868  
 869          $returnString = '';
 870          begin_sql();
 871          $useridarray = array();
 872  
 873          foreach($array as $logEntry) {
 874              $logEntryObj = (object)$logEntry;
 875              $logEntryObj->hostid = $MNET_REMOTE_CLIENT->id;
 876  
 877              if (isset($useridarray[$logEntryObj->username])) {
 878                  $logEntryObj->userid = $useridarray[$logEntryObj->username];
 879              } else {
 880                  $logEntryObj->userid = get_field('user','id','username',$logEntryObj->username);
 881                  if ($logEntryObj->userid == false) {
 882                      $logEntryObj->userid = 0;
 883                  }
 884                  $useridarray[$logEntryObj->username] = $logEntryObj->userid;
 885              }
 886  
 887              unset($logEntryObj->username);
 888  
 889              $insertok = insert_record('mnet_log', addslashes_object($logEntryObj), false);
 890  
 891              if ($insertok) {
 892                  $MNET_REMOTE_CLIENT->last_log_id = $logEntryObj->remoteid;
 893              } else {
 894                  $returnString .= 'Record with id '.$logEntryObj->remoteid." failed to insert.\n";
 895              }
 896          }
 897          $MNET_REMOTE_CLIENT->commit();
 898          commit_sql();
 899  
 900          $end = ob_end_clean();
 901  
 902          if (empty($returnString)) return array('code' => 0, 'message' => 'All ok');
 903          return array('code' => 1, 'message' => $returnString);
 904      }
 905  
 906      /**
 907       * Receives an array of usernames from a remote machine and prods their
 908       * sessions to keep them alive
 909       *
 910       * @param   array   $array      An array of usernames
 911       * @return  string              "All ok" or an error message
 912       */
 913      function keepalive_server($array) {
 914          global $MNET_REMOTE_CLIENT, $CFG;
 915  
 916          $CFG->usesid = true;
 917          // Addslashes to all usernames, so we can build the query string real
 918          // simply with 'implode'
 919          $array = array_map('addslashes', $array);
 920  
 921          // We don't want to output anything to the client machine
 922          $start = ob_start();
 923  
 924          // We'll get session records in batches of 30
 925          $superArray = array_chunk($array, 30);
 926  
 927          $returnString = '';
 928  
 929          foreach($superArray as $subArray) {
 930              $subArray = array_values($subArray);
 931              $instring = "('".implode("', '",$subArray)."')";
 932              $query = "select id, session_id, username from {$CFG->prefix}mnet_session where username in $instring";
 933              $results = get_records_sql($query);
 934  
 935              if ($results == false) {
 936                  // We seem to have a username that breaks our query:
 937                  // TODO: Handle this error appropriately
 938                  $returnString .= "We failed to refresh the session for the following usernames: \n".implode("\n", $subArray)."\n\n";
 939              } else {
 940                  // TODO: This process of killing and re-starting the session
 941                  // will cause PHP to forget any custom session_set_save_handler
 942                  // stuff. Subsequent attempts to prod existing sessions will
 943                  // fail, because PHP will look in wherever the default place
 944                  // may be (files?) and probably create a new session with the
 945                  // right session ID in that location. If it doesn't have write-
 946                  // access to that location, then it will fail... not sure how
 947                  // apparent that will be.
 948                  // There is no way to capture what the custom session handler
 949                  // is and then reset it on each pass - I checked that out
 950                  // already.
 951                  $sesscache = clone($_SESSION);
 952                  $sessidcache = session_id();
 953                  session_write_close();
 954                  unset($_SESSION);
 955  
 956                  $uc = ini_get('session.use_cookies');
 957                  ini_set('session.use_cookies', false);
 958                  foreach($results as $emigrant) {
 959  
 960                      unset($_SESSION);
 961                      session_name('MoodleSession'.$CFG->sessioncookie);
 962                      session_id($emigrant->session_id);
 963                      session_start();
 964                      session_write_close();
 965                  }
 966  
 967                  ini_set('session.use_cookies', $uc);
 968                  session_name('MoodleSession'.$CFG->sessioncookie);
 969                  session_id($sessidcache);
 970                  session_start();
 971                  $_SESSION = clone($sesscache);
 972                  session_write_close();
 973              }
 974          }
 975  
 976          $end = ob_end_clean();
 977  
 978          if (empty($returnString)) return array('code' => 0, 'message' => 'All ok', 'last log id' => $MNET_REMOTE_CLIENT->last_log_id);
 979          return array('code' => 1, 'message' => $returnString, 'last log id' => $MNET_REMOTE_CLIENT->last_log_id);
 980      }
 981  
 982      /**
 983       * Cron function will be called automatically by cron.php every 5 minutes
 984       *
 985       * @return void
 986       */
 987      function cron() {
 988  
 989          // run the keepalive client
 990          $this->keepalive_client();
 991  
 992          // admin/cron.php should have run srand for us
 993          $random100 = rand(0,100);
 994          if ($random100 < 10) {     // Approximately 10% of the time.
 995              // nuke olden sessions
 996              $longtime = time() - (1 * 3600 * 24);
 997              delete_records_select('mnet_session', "expires < $longtime");
 998          }
 999      }
1000  
1001      /**
1002       * Cleanup any remote mnet_sessions, kill the local mnet_session data
1003       *
1004       * This is called by require_logout in moodlelib
1005       *
1006       * @return   void
1007       */
1008      function prelogout_hook() {
1009          global $MNET, $CFG, $USER;
1010          if (!is_enabled_auth('mnet')) {
1011              return;
1012          }
1013  
1014          require_once $CFG->dirroot.'/mnet/xmlrpc/client.php';
1015  
1016          // If the user is local to this Moodle:
1017          if ($USER->mnethostid == $MNET->id) {
1018              $this->kill_children($USER->username, sha1($_SERVER['HTTP_USER_AGENT']));
1019  
1020          // Else the user has hit 'logout' at a Service Provider Moodle:
1021          } else {
1022              $this->kill_parent($USER->username, sha1($_SERVER['HTTP_USER_AGENT']));
1023  
1024          }
1025      }
1026  
1027      /**
1028       * The SP uses this function to kill the session on the parent IdP
1029       *
1030       * @param   string  $username       Username for session to kill
1031       * @param   string  $useragent      SHA1 hash of user agent to look for
1032       * @return  string                  A plaintext report of what has happened
1033       */
1034      function kill_parent($username, $useragent) {
1035          global $CFG, $USER;
1036          require_once $CFG->dirroot.'/mnet/xmlrpc/client.php';
1037          $sql = "
1038              select
1039                  *
1040              from
1041                  {$CFG->prefix}mnet_session s
1042              where
1043                  s.username   = '".addslashes($username)."' AND
1044                  s.useragent  = '$useragent' AND
1045                  s.mnethostid = '{$USER->mnethostid}'";
1046  
1047          $mnetsessions = get_records_sql($sql);
1048  
1049          $ignore = delete_records('mnet_session',
1050                                   'username', addslashes($username),
1051                                   'useragent', $useragent,
1052                                   'mnethostid', $USER->mnethostid);
1053  
1054          if (false != $mnetsessions) {
1055              $mnet_peer = new mnet_peer();
1056              $mnet_peer->set_id($USER->mnethostid);
1057  
1058              $mnet_request = new mnet_xmlrpc_client();
1059              $mnet_request->set_method('auth/mnet/auth.php/kill_children');
1060  
1061              // set $token and $useragent parameters
1062              $mnet_request->add_param($username);
1063              $mnet_request->add_param($useragent);
1064              if ($mnet_request->send($mnet_peer) === false) {
1065                  debugging(join("\n", $mnet_request->error));
1066                  return false;
1067              }
1068          }
1069  
1070          $_SESSION = array();
1071          return true;
1072      }
1073  
1074      /**
1075       * The IdP uses this function to kill child sessions on other hosts
1076       *
1077       * @param   string  $username       Username for session to kill
1078       * @param   string  $useragent      SHA1 hash of user agent to look for
1079       * @return  string                  A plaintext report of what has happened
1080       */
1081      function kill_children($username, $useragent) {
1082          global $CFG, $USER, $MNET_REMOTE_CLIENT;
1083          require_once $CFG->dirroot.'/mnet/xmlrpc/client.php';
1084  
1085          $userid = get_field('user', 'id', 'mnethostid', $CFG->mnet_localhost_id, 'username', addslashes($username));
1086  
1087          $returnstring = '';
1088          $sql = "
1089              select
1090                  *
1091              from
1092                  {$CFG->prefix}mnet_session s
1093              where
1094                  s.userid     = '{$userid}' AND
1095                  s.useragent  = '{$useragent}'";
1096  
1097          // If we are being executed from a remote machine (client) we don't have
1098          // to kill the moodle session on that machine.
1099          if (isset($MNET_REMOTE_CLIENT) && isset($MNET_REMOTE_CLIENT->id)) {
1100              $excludeid = $MNET_REMOTE_CLIENT->id;
1101          } else {
1102              $excludeid = -1;
1103          }
1104  
1105          $mnetsessions = get_records_sql($sql);
1106  
1107          if (false == $mnetsessions) {
1108              $returnstring .= "Could find no remote sessions\n$sql\n";
1109              $mnetsessions = array();
1110          }
1111  
1112          foreach($mnetsessions as $mnetsession) {
1113              $returnstring .=  "Deleting session\n";
1114  
1115              if ($mnetsession->mnethostid == $excludeid) continue;
1116  
1117              $mnet_peer = new mnet_peer();
1118              $mnet_peer->set_id($mnetsession->mnethostid);
1119  
1120              $mnet_request = new mnet_xmlrpc_client();
1121              $mnet_request->set_method('auth/mnet/auth.php/kill_child');
1122  
1123              // set $token and $useragent parameters
1124              $mnet_request->add_param($username);
1125              $mnet_request->add_param($useragent);
1126              if ($mnet_request->send($mnet_peer) === false) {
1127                  debugging("Server side error has occured on host $mnetsession->mnethostid: " .
1128                            join("\n", $mnet_request->error));
1129              }
1130          }
1131  
1132          $ignore = delete_records('mnet_session',
1133                                   'useragent', $useragent,
1134                                   'userid',    $userid);
1135  
1136          if (isset($MNET_REMOTE_CLIENT) && isset($MNET_REMOTE_CLIENT->id)) {
1137              $start = ob_start();
1138  
1139              $uc = ini_get('session.use_cookies');
1140              ini_set('session.use_cookies', false);
1141              $sesscache = clone($_SESSION);
1142              $sessidcache = session_id();
1143              session_write_close();
1144              unset($_SESSION);
1145  
1146  
1147              session_id($mnetsession->session_id);
1148              session_start();
1149              session_unregister("USER");
1150              session_unregister("SESSION");
1151              unset($_SESSION);
1152              $_SESSION = array();
1153              session_write_close();
1154  
1155  
1156              ini_set('session.use_cookies', $uc);
1157              session_name('MoodleSession'.$CFG->sessioncookie);
1158              session_id($sessidcache);
1159              session_start();
1160              $_SESSION = clone($sesscache);
1161              session_write_close();
1162  
1163              $end = ob_end_clean();
1164          } else {
1165              $_SESSION = array();
1166          }
1167          return $returnstring;
1168      }
1169  
1170      /**
1171       * TODO:Untested When the IdP requests that child sessions are terminated,
1172       * this function will be called on each of the child hosts. The machine that
1173       * calls the function (over xmlrpc) provides us with the mnethostid we need.
1174       *
1175       * @param   string  $username       Username for session to kill
1176       * @param   string  $useragent      SHA1 hash of user agent to look for
1177       * @return  bool                    True on success
1178       */
1179      function kill_child($username, $useragent) {
1180          global $CFG, $MNET_REMOTE_CLIENT;
1181          $session = get_record('mnet_session', 'username', addslashes($username), 'mnethostid', $MNET_REMOTE_CLIENT->id, 'useragent', $useragent);
1182          if (false != $session) {
1183              $start = ob_start();
1184  
1185              $uc = ini_get('session.use_cookies');
1186              ini_set('session.use_cookies', false);
1187              $sesscache = clone($_SESSION);
1188              $sessidcache = session_id();
1189              session_write_close();
1190              unset($_SESSION);
1191  
1192  
1193              session_id($session->session_id);
1194              session_start();
1195              session_unregister("USER");
1196              session_unregister("SESSION");
1197              unset($_SESSION);
1198              $_SESSION = array();
1199              session_write_close();
1200  
1201  
1202              ini_set('session.use_cookies', $uc);
1203              session_name('MoodleSession'.$CFG->sessioncookie);
1204              session_id($sessidcache);
1205              session_start();
1206              $_SESSION = clone($sesscache);
1207              session_write_close();
1208  
1209              $end = ob_end_clean();
1210              return true;
1211          }
1212          return false;
1213      }
1214  
1215      /**
1216       * To delete a host, we must delete all current sessions that users from
1217       * that host are currently engaged in.
1218       *
1219       * @param   string  $sessionidarray   An array of session hashes
1220       * @return  bool                      True on success
1221       */
1222      function end_local_sessions(&$sessionArray) {
1223          global $CFG;
1224          if (is_array($sessionArray)) {
1225              $start = ob_start();
1226  
1227              $uc = ini_get('session.use_cookies');
1228              ini_set('session.use_cookies', false);
1229              $sesscache = clone($_SESSION);
1230              $sessidcache = session_id();
1231              session_write_close();
1232              unset($_SESSION);
1233  
1234              while($session = array_pop($sessionArray)) {
1235                  session_id($session->session_id);
1236                  session_start();
1237                  session_unregister("USER");
1238                  session_unregister("SESSION");
1239                  unset($_SESSION);
1240                  $_SESSION = array();
1241                  session_write_close();
1242              }
1243  
1244              ini_set('session.use_cookies', $uc);
1245              session_name('MoodleSession'.$CFG->sessioncookie);
1246              session_id($sessidcache);
1247              session_start();
1248              $_SESSION = clone($sesscache);
1249  
1250              $end = ob_end_clean();
1251              return true;
1252          }
1253          return false;
1254      }
1255  
1256      /**
1257       * Returns the user's image as a base64 encoded string.
1258       *
1259       * @param int $userid The id of the user
1260       * @return string     The encoded image
1261       */
1262      function fetch_user_image($username) {
1263          global $CFG;
1264  
1265          if ($user = get_record('user', 'username', addslashes($username), 'mnethostid', $CFG->mnet_localhost_id)) {
1266              $filename1 = make_user_directory($user->id, true) . "/f1.jpg";
1267              $filename2 = make_user_directory($user->id, true) . "/f2.jpg";
1268              $return = array();
1269              if (file_exists($filename1)) {
1270                  $return['f1'] = base64_encode(file_get_contents($filename1));
1271              }
1272              if (file_exists($filename2)) {
1273                  $return['f2'] = base64_encode(file_get_contents($filename2));
1274              }
1275              return $return;
1276          }
1277          return false;
1278      }
1279  
1280      /**
1281       * Returns the theme information and logo url as strings.
1282       *
1283       * @return string     The theme info
1284       */
1285      function fetch_theme_info() {
1286          global $CFG;
1287  
1288          $themename = "$CFG->theme";
1289          $logourl   = "$CFG->wwwroot/theme/$CFG->theme/images/logo.jpg";
1290  
1291          $return['themename'] = $themename;
1292          $return['logourl'] = $logourl;
1293          return $return;
1294      }
1295  
1296      /**
1297       * Determines if an MNET host is providing the nominated service.
1298       *
1299       * @param int    $mnethostid   The id of the remote host
1300       * @param string $servicename  The name of the service
1301       * @return bool                Whether the service is available on the remote host
1302       */
1303      function has_service($mnethostid, $servicename) {
1304          global $CFG;
1305  
1306          $sql = "
1307              SELECT
1308                  svc.id as serviceid,
1309                  svc.name,
1310                  svc.description,
1311                  svc.offer,
1312                  svc.apiversion,
1313                  h2s.id as h2s_id
1314              FROM
1315                  {$CFG->prefix}mnet_host h,
1316                  {$CFG->prefix}mnet_service svc,
1317                  {$CFG->prefix}mnet_host2service h2s
1318              WHERE
1319                  h.deleted = '0' AND
1320                  h.id = h2s.hostid AND
1321                  h2s.hostid = '$mnethostid' AND
1322                  h2s.serviceid = svc.id AND
1323                  svc.name = '$servicename' AND
1324                  h2s.subscribe = '1'";
1325  
1326          return get_records_sql($sql);
1327      }
1328  
1329      /**
1330       * Checks the MNET access control table to see if the username/mnethost
1331       * is permitted to login to this moodle.
1332       *
1333       * @param string $username   The username
1334       * @param int    $mnethostid The id of the remote mnethost
1335       * @return bool              Whether the user can login from the remote host
1336       */
1337      function can_login_remotely($username, $mnethostid) {
1338          $accessctrl = 'allow';
1339          $aclrecord = get_record('mnet_sso_access_control', 'username', addslashes($username), 'mnet_host_id', $mnethostid);
1340          if (!empty($aclrecord)) {
1341              $accessctrl = $aclrecord->accessctrl;
1342          }
1343          return $accessctrl == 'allow';
1344      }
1345  
1346      function logoutpage_hook() {
1347          global $USER, $CFG, $redirect;
1348  
1349          if (!empty($USER->mnethostid) and $USER->mnethostid != $CFG->mnet_localhost_id) {
1350              $host = get_record('mnet_host', 'id', $USER->mnethostid);
1351              $redirect = $host->wwwroot.'/';
1352          }
1353      }
1354  
1355  }
1356  
1357  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7