From ea714cfdbd628df934279b6d55a0289fc1c9d73c Mon Sep 17 00:00:00 2001 From: skodak Date: Sun, 29 Apr 2007 13:57:46 +0000 Subject: [PATCH] =?UTF-8?q?MDL-8813=20Cas=20auth=20for=201.8x=20-=20credit?= =?UTF-8?q?=20goes=20to=20J=C3=A9r=C3=B4me=20Gutierrez;=20TODO:=20redirect?= =?UTF-8?q?ion=20after=20failed=20login?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auth/cas/CAS/languages/german.php | 27 + auth/cas/CAS/languages/japanese.php | 27 + auth/cas/README-CAS | 11 +- auth/cas/auth.php | 1573 ++++++++++--- auth/cas/cas_form.html | 12 + ...sync_users.php => cas_ldap_sync_users.php} | 0 auth/cas/config.html | 621 ++++-- auth/cas/forbidden.html | 8 - auth/cas/forbidden.php | 18 - auth/cas/index_form.html | 85 - auth/cas/languages.php | 19 +- auth/cas/login.php | 313 --- auth/cas/logout.php | 15 - lang/en_utf8/auth.php | 9 + lib/cas/CAS.php | 1182 ---------- lib/cas/PGTStorage/pgt-db.php | 190 -- lib/cas/PGTStorage/pgt-file.php | 237 -- lib/cas/PGTStorage/pgt-main.php | 188 -- lib/cas/client.php | 1950 ----------------- lib/cas/domxml-php4-php5.php | 277 --- lib/cas/languages/english.php | 27 - lib/cas/languages/french.php | 28 - lib/cas/languages/greek.php | 27 - lib/cas/languages/languages.php | 24 - 24 files changed, 1780 insertions(+), 5088 deletions(-) create mode 100644 auth/cas/CAS/languages/german.php create mode 100644 auth/cas/CAS/languages/japanese.php create mode 100644 auth/cas/cas_form.html rename auth/cas/{auth_ldap_sync_users.php => cas_ldap_sync_users.php} (100%) delete mode 100644 auth/cas/forbidden.html delete mode 100644 auth/cas/forbidden.php delete mode 100644 auth/cas/index_form.html delete mode 100644 auth/cas/login.php delete mode 100644 auth/cas/logout.php delete mode 100644 lib/cas/CAS.php delete mode 100644 lib/cas/PGTStorage/pgt-db.php delete mode 100644 lib/cas/PGTStorage/pgt-file.php delete mode 100644 lib/cas/PGTStorage/pgt-main.php delete mode 100644 lib/cas/client.php delete mode 100644 lib/cas/domxml-php4-php5.php delete mode 100644 lib/cas/languages/english.php delete mode 100644 lib/cas/languages/french.php delete mode 100644 lib/cas/languages/greek.php delete mode 100644 lib/cas/languages/languages.php diff --git a/auth/cas/CAS/languages/german.php b/auth/cas/CAS/languages/german.php new file mode 100644 index 00000000000..29daeb35dde --- /dev/null +++ b/auth/cas/CAS/languages/german.php @@ -0,0 +1,27 @@ + + * @sa @link internalLang Internationalization @endlink + * @ingroup internalLang + */ + +$this->_strings = array( + CAS_STR_USING_SERVER + => 'via Server', + CAS_STR_AUTHENTICATION_WANTED + => 'CAS Authentifizierung erforderlich!', + CAS_STR_LOGOUT + => 'CAS Abmeldung!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie hier um fortzufahren.', + CAS_STR_AUTHENTICATION_FAILED + => 'CAS Anmeldung fehlgeschlagen!', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

Sie wurden nicht angemeldet.

Um es erneut zu versuchen klicken Sie hier.

Wenn das Problem bestehen bleibt, kontkatieren Sie den Administrator dieser Seite.

', + CAS_STR_SERVICE_UNAVAILABLE + => 'Der Dienst `%s\' ist nicht verfügbar (%s).' +); + +?> \ No newline at end of file diff --git a/auth/cas/CAS/languages/japanese.php b/auth/cas/CAS/languages/japanese.php new file mode 100644 index 00000000000..333bb17b6a0 --- /dev/null +++ b/auth/cas/CAS/languages/japanese.php @@ -0,0 +1,27 @@ +_strings = array( + CAS_STR_USING_SERVER + => 'using server', + CAS_STR_AUTHENTICATION_WANTED + => 'CAS¤Ë¤è¤ëǧ¾Ú¤ò¹Ô¤¤¤Þ¤¹', + CAS_STR_LOGOUT + => 'CAS¤«¤é¥í¥°¥¢¥¦¥È¤·¤Þ¤¹!', + CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED + => 'CAS¥µ¡¼¥Ð¤Ë¹Ô¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡£¼«Æ°Åª¤ËžÁ÷¤µ¤ì¤Ê¤¤¾ì¹ç¤Ï ¤³¤Á¤é ¤ò¥¯¥ê¥Ã¥¯¤·¤ÆÂ³¹Ô¤·¤Þ¤¹¡£', + CAS_STR_AUTHENTICATION_FAILED + => 'CAS¤Ë¤è¤ëǧ¾Ú¤Ë¼ºÇÔ¤·¤Þ¤·¤¿', + CAS_STR_YOU_WERE_NOT_AUTHENTICATED + => '

ǧ¾Ú¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿.

¤â¤¦°ìÅ٥ꥯ¥¨¥¹¥È¤òÁ÷¿®¤¹¤ë¾ì¹ç¤Ï¤³¤Á¤é¤ò¥¯¥ê¥Ã¥¯.

ÌäÂ꤬²ò·è¤·¤Ê¤¤¾ì¹ç¤Ï ¤³¤Î¥µ¥¤¥È¤Î´ÉÍý¼Ô¤ËÌ䤤¹ç¤ï¤»¤Æ¤¯¤À¤µ¤¤.

', + CAS_STR_SERVICE_UNAVAILABLE + => '¥µ¡¼¥Ó¥¹ `%s\' ¤ÏÍøÍѤǤ­¤Þ¤»¤ó (%s).' +); + +?> \ No newline at end of file diff --git a/auth/cas/README-CAS b/auth/cas/README-CAS index 8b133052b15..2a63bccf403 100644 --- a/auth/cas/README-CAS +++ b/auth/cas/README-CAS @@ -1,7 +1,4 @@ -CAS-module README - -Please read comments from lib.php for auth/cas module -The auth/cas module is using part of the /auth/ldap module. The /auth/ldap directory should exist. -The auth/cas use the PHPCAS project from http://esup-phpcas.sourceforge.net - - +CAS-module README + + + diff --git a/auth/cas/auth.php b/auth/cas/auth.php index c49b83cc0f4..ad8262d0b52 100644 --- a/auth/cas/auth.php +++ b/auth/cas/auth.php @@ -1,315 +1,1258 @@ -libdir.'/authlib.php'); - -/** - * CAS authentication plugin. - */ -class auth_plugin_cas extends auth_plugin_base { - - /** - * Constructor. - */ - function auth_plugin_cas() { - $this->authtype = 'cas'; - $this->config = get_config('auth/cas'); - } - - /** - * Authenticates user againt CAS with LDAP. - * Returns true if the username and password work and false if they are - * wrong or don't exist. - * - * @param string $username The username - * @param string $password The password - * @return bool Authentication success or failure. - */ - function user_login ($username, $password) { - if (! function_exists('ldap_connect')) { - print_error('auth_casnotinstalled','mnet'); - return false; - } - - global $CFG; - - // don't allow blank usernames or passwords - if (!$username or !$password) { - return false; - } - - // CAS specific - if ($CFG->auth == "cas" and !empty($this->config->enabled)) { - if ($this->config->create_user == '0') { - if (record_exists('user', 'username', $username)) { - return true; - } - else { - return false; - } - } - else { - return true; - } - } - - $ldap_connection = ldap_connect(); - - if ($ldap_connection) { - $ldap_user_dn = auth_ldap_find_userdn($ldap_connection, $username); - - // if ldap_user_dn is empty, user does not exist - if (!$ldap_user_dn) { - ldap_close($ldap_connection); - return false; - } - - // Try to bind with current username and password - $ldap_login = ldap_bind($ldap_connection, $ldap_user_dn, $password); - ldap_close($ldap_connection); - if ($ldap_login) { - if ($this->config->create_user=='0') { //cas specific - if (record_exists('user', 'username', $username, 'mnethostid', $CFG->mnet_localhost_id)) { - return true; - }else{ - return false; - } - }else{ - return true; - } - } - } else { - ldap_close($ldap_connection); - print_error('auth_cas_cantconnect', 'auth', $CFG->ldap_host_url); - } - return false; - } - - /** - * Authenticates user against CAS from screen login - * the user doesn't have a CAS Ticket yet. - * - * Returns an object user if the username and password work - * and nothing if they don't - * - * @param string $username - * @param string $password - * - */ - function authenticate_user_login ($username, $password) { - - // TODO: fix SOMEOTHER:: - - global $CFG; - // FIX ME: $cas_validate is not global - $cas_validate = true; - phpCAS::client($this->config->casversion, $this->config->hostname, (int) $this->config->port, $this->config->baseuri); - phpCAS::setLang($this->config->language); - phpCAS::forceAuthentication(); - if ($this->config->create_user == '0') { - if (record_exists('user', 'username', phpCAS::getUser(), 'mnethostid', $CFG->mnet_localhost_id)) { - // TODO::SOMEOTHER:: - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - else { - // login as guest if CAS but not Moodle and not automatic creation - if ($CFG->guestloginbutton) { - // TODO::SOMEOTHER:: - $user = authenticate_user_login('guest', 'guest'); - } - else { - // TODO::SOMEOTHER:: - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - } - } - else { - // TODO::SOMEOTHER:: - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - return $user; - } - - /** - * Authenticates user against CAS when first call of Moodle - * if already in CAS (cookie with the CAS ticket), don't have to log again (SSO) - * - * Returns an object user if the username and password work - * and nothing if they don't - * - * @param object $user - * - */ - function automatic_authenticate ($user='') { - - // TODO: fix SOMEOTHER:: - - global $CFG; - // FIX ME: $cas_validate is not global, but it works anyway ;-) - if (!$cas_validate) { - $cas_validate = true; - phpCAS::client($this->config->casversion, $this->config->hostname, (int) $this->config->port, $this->config->baseuri); - phpCAS::setLang($this->config->language); - $cas_user_exist = phpCAS::checkAuthentication(); - if (!$cas_user_exist and !$CFG->guestloginbutton) { - $cas_user_exist=phpCAS::forceAuthentication(); - } - if ($cas_user_exist) { - if ($this->config->create_user == '0') { - if (record_exists('user', 'username', phpCAS::getUser(), 'mnethostid', $CFG->mnet_localhost_id)) { - // TODO::SOMEOTHER:: - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - else { - // login as guest if CAS but not Moodle and not automatic creation - if ($CFG->guestloginbutton) { - // TODO::SOMEOTHER:: - $user = authenticate_user_login('guest', 'guest'); - } - else { - // TODO::SOMEOTHER:: - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - } - } - else { - // TODO::SOMEOTHER:: - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - return $user; - } - else { - return; - } - } - else { - return $user; - } - } - - /** - * Returns true if this authentication plugin is 'internal'. - * - * @return bool - */ - function is_internal() { - return false; - } - - /** - * Returns true if this authentication plugin can change the user's - * password. - * - * @return bool - */ - function can_change_password() { - return !empty($this->config->changepasswordurl); - } - - function loginpage_hook() { - // Load alternative login screens if necessary - // TODO: fix the cas login screen - return; - - if(!empty($CFG->cas_enabled)) { - require($CFG->dirroot.'/auth/cas/login.php'); - } - } - - function prelogout_hook() { - global $CFG; - - require($CFG->dirroot.'/auth/cas/logout.php'); - } - - /** - * Prints a form for configuring this authentication plugin. - * - * This function is called from admin/auth.php, and outputs a full page with - * a form for configuring this plugin. - * - * @param array $page An object containing all the data for this page. - */ - function config_form($config, $err, $user_fields) { - include 'config.html'; - } - - /** - * Returns the URL for changing the user's pw, or empty if the default can - * be used. - * - * @return string - */ - function change_password_url() { - return $this->config->changepasswordurl; - } - - /** - * Processes and stores configuration data for this authentication plugin. - */ - function process_config($config) { - // set to defaults if undefined - if (!isset ($config->hostname)) { - $config->hostname = ''; - } - if (!isset ($config->port)) { - $config->port = ''; - } - if (!isset ($config->casversion)) { - $config->casversion = ''; - } - if (!isset ($config->baseuri)) { - $config->baseuri = ''; - } - if (!isset ($config->language)) { - $config->language = ''; - } - if (!isset ($config->use_cas)) { - $config->use_cas = ''; - } - if (!isset ($config->auth_user_create)) { - $config->auth_user_create = ''; - } - if (!isset ($config->create_user)) { - $config->create_user = '0'; - } - if (!isset($config->changepasswordurl)) { - $config->changepasswordurl = ''; - } - - // save CAS settings - set_config('hostname', $config->hostname, 'auth/cas'); - set_config('port', $config->port, 'auth/cas'); - set_config('casversion', $config->casversion, 'auth/cas'); - set_config('baseuri', $config->baseuri, 'auth/cas'); - set_config('language', $config->language, 'auth/cas'); - set_config('use_cas', $config->use_cas, 'auth/cas'); - set_config('auth_user_create', $config->auth_user_create, 'auth/cas'); - set_config('create_user', $config->create_user, 'auth/cas'); - set_config('changepasswordurl', $config->changepasswordurl, 'auth/cas'); - - // save LDAP settings - // TODO: settings must be separated now that we have multiauth! - $ldapauth = get_auth_plugin('ldap'); - $ldapauth->process_config($config); - - return true; - } - -} - -?> +libdir.'/authlib.php'); +require_once('CAS/CAS.php'); +/** + * CAS authentication plugin. + */ +class auth_plugin_cas extends auth_plugin_base { + + /** + * Constructor. + */ + function auth_plugin_cas() { + $this->authtype = 'cas'; + $this->config = get_config('auth/cas'); + if (empty($this->config->ldapencoding)) { + $this->config->ldapencoding = 'utf-8'; + } + if (empty($this->config->user_type)) { + $this->config->user_type = 'default'; + } + + $default = $this->ldap_getdefaults(); + + //use defaults if values not given + foreach ($default as $key => $value) { + // watch out - 0, false are correct values too + if (!isset($this->config->{$key}) or $this->config->{$key} == '') { + $this->config->{$key} = $value[$this->config->user_type]; + } + } + //hack prefix to objectclass + if (empty($this->config->objectclass)) { // Can't send empty filter + $this->config->objectclass='objectClass=*'; + } else if (strpos($this->config->objectclass, 'objectClass=') !== 0) { + $this->config->objectclass = 'objectClass='.$this->config->objectclass; + } + + } + + /** + * Authenticates user againt CAS + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @return bool Authentication success or failure. + */ + function user_login ($username, $password) { + return phpCAS::isAuthenticated(); + } + + + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @return bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @return bool + */ + function can_change_password() { + return false; + } + + /** + * authentication choice (CAS or other) + * redirection to the CAS form or to login/index.php + * for other authentication + */ + function loginpage_hook() { + global $frm; + global $test; + global $CFG; + + $site = get_site(); + $CASform = get_string("CASform","auth"); + $username = optional_param("username"); + + if (!empty($username)) { + + return; + } + +// Connection to CAS server + $this->connectCAS(); + + + if ($this->config->multiauth) { + $authCAS = optional_param("authCAS"); + if ($authCAS=="NOCAS") + return; + +// choice authentication form for multi-authentication +// test pgtIou parameter for proxy mode (https connection +// in background from CAS server to the php server) + if ($authCAS!="CAS" && !isset($_GET["pgtIou"])) + { + print_header("$site->fullname: $CASform", $site->fullname, $CASform); + include($CFG->dirroot."/auth/cas/cas_form.html"); + print_footer(); + exit(); + } + } + +// CAS authentication + if (!phpCAS::isAuthenticated()) + {phpCAS::forceAuthentication();} + + $frm->username=phpCAS::getUser(); + $frm->password="cas"; + + +} + + /** + * logout from the cas + * + * This function is called from admin/auth.php + * + */ + function prelogout_hook() { + global $CFG; + if ($this->config->logoutcas ) { + $backurl = $CFG->wwwroot; + $this->connectCAS(); + phpCAS::logout($backurl); + } + } + + + /** + * Connect to the cas (clientcas connection or proxycas connection + * + * This function is called from admin/auth.php + * + */ + function connectCAS() { +// mode proxy CAS + if ($this->config->proxycas) { + phpCAS::proxy($this->config->casversion, $this-> config->hostname, (int) $this->config->port, $this->config->baseuri); + } +// mode client CAS + else { + phpCAS::client($this->config->casversion, $this-> config->hostname, (int) $this->config->port, $this->config->baseuri); + } + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err, $user_fields) { + include 'config.html'; + } + + /** + * Returns the URL for changing the user's pw, or empty if the default can + * be used. + * + * @return string + */ + function change_password_url() { + return ""; + } + + /** + * returns predefined usertypes + * + * @return array of predefined usertypes + */ + function ldap_suppported_usertypes() { + $types = array(); + $types['edir']='Novell Edirectory'; + $types['rfc2307']='posixAccount (rfc2307)'; + $types['rfc2307bis']='posixAccount (rfc2307bis)'; + $types['samba']='sambaSamAccount (v.3.0.7)'; + $types['ad']='MS ActiveDirectory'; + $types['default']=get_string('default'); + return $types; + } + + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + // CAS settings + if (!isset ($config->hostname)) + $config->hostname = ''; + if (!isset ($config->port)) + $config->port = ''; + if (!isset ($config->casversion)) + $config->casversion = ''; + if (!isset ($config->baseuri)) + $config->baseuri = ''; + if (!isset ($config->language)) + $config->language = ''; + if (!isset ($config->use_cas)) + $config->use_cas = ''; + if (!isset ($config->proxycas)) + $config->proxycas = ''; + if (!isset ($config->logoutcas)) + $config->logoutcas = ''; + if (!isset ($config->multiauth)) + $config->multiauth = ''; + // LDAP settings + if (!isset($config->host_url)) + { $config->host_url = ''; } + if (empty($config->ldapencoding)) + { $config->ldapencoding = 'utf-8'; } + if (!isset($config->contexts)) + { $config->contexts = ''; } + if (!isset($config->user_type)) + { $config->user_type = 'default'; } + if (!isset($config->user_attribute)) + { $config->user_attribute = ''; } + if (!isset($config->search_sub)) + { $config->search_sub = ''; } + if (!isset($config->opt_deref)) + { $config->opt_deref = ''; } + if (!isset($config->bind_dn)) + {$config->bind_dn = ''; } + if (!isset($config->bind_pw)) + {$config->bind_pw = ''; } + if (!isset($config->version)) + {$config->version = '2'; } + if (!isset($config->objectclass)) + {$config->objectclass = ''; } + if (!isset($config->memberattribute)) + {$config->memberattribute = ''; } + if (!isset($config->memberattribute_isdn)) + {$config->memberattribute_isdn = ''; } + if (!isset($config->attrcreators)) + {$config->attrcreators = ''; } + if (!isset($config->groupecreators)) + {$config->groupecreators = ''; } + if (!isset($config->removeuser)) + {$config->removeuser = 0; } + + // save CAS settings + set_config('hostname', $config->hostname, 'auth/cas'); + set_config('port', $config->port, 'auth/cas'); + set_config('casversion', $config->casversion, 'auth/cas'); + set_config('baseuri', $config->baseuri, 'auth/cas'); + set_config('language', $config->language, 'auth/cas'); + set_config('use_cas', $config->use_cas, 'auth/cas'); + set_config('proxycas', $config->proxycas, 'auth/cas'); + set_config('logoutcas', $config->logoutcas, 'auth/cas'); + set_config('multiauth', $config->multiauth, 'auth/cas'); + // save LDAP settings + set_config('host_url', $config->host_url, 'auth/cas'); + set_config('ldapencoding', $config->ldapencoding, 'auth/cas'); + set_config('host_url', $config->host_url, 'auth/cas'); + set_config('contexts', $config->contexts, 'auth/cas'); + set_config('user_type', $config->user_type, 'auth/cas'); + set_config('user_attribute', $config->user_attribute, 'auth/cas'); + set_config('search_sub', $config->search_sub, 'auth/cas'); + set_config('opt_deref', $config->opt_deref, 'auth/cas'); + set_config('bind_dn', $config->bind_dn, 'auth/cas'); + set_config('bind_pw', $config->bind_pw, 'auth/cas'); + set_config('version', $config->version, 'auth/cas'); + set_config('objectclass', $config->objectclass, 'auth/cas'); + set_config('memberattribute', $config->memberattribute, 'auth/cas'); + set_config('memberattribute_isdn', $config->memberattribute_isdn, 'auth/cas'); + set_config('attrcreators', $config->attrcreators, 'auth/cas'); + set_config('groupecreators', $config->groupecreators, 'auth/cas'); + set_config('removeuser', $config->removeuser, 'auth/cas'); + + return true; + } + + /** + * Initializes needed ldap variables for cas-module + * + * Uses names defined in ldap_supported_usertypes. + * $default is first defined as: + * $default['pseudoname'] = array( + * 'typename1' => 'value', + * 'typename2' => 'value' + * .... + * ); + * + * @return array of default values + */ + function ldap_getdefaults() { + $default['objectclass'] = array( + 'edir' => 'User', + 'rfc2307' => 'posixAccount', + 'rfc2307bis' => 'posixAccount', + 'samba' => 'sambaSamAccount', + 'ad' => 'user', + 'default' => '*' + ); + $default['user_attribute'] = array( + 'edir' => 'cn', + 'rfc2307' => 'uid', + 'rfc2307bis' => 'uid', + 'samba' => 'uid', + 'ad' => 'cn', + 'default' => 'cn' + ); + $default['memberattribute'] = array( + 'edir' => 'member', + 'rfc2307' => 'member', + 'rfc2307bis' => 'member', + 'samba' => 'member', + 'ad' => 'member', + 'default' => 'member' + ); + $default['memberattribute_isdn'] = array( + 'edir' => '1', + 'rfc2307' => '0', + 'rfc2307bis' => '1', + 'samba' => '0', //is this right? + 'ad' => '1', + 'default' => '0' + ); + return $default; + } + + /** + * reads userinformation from ldap and return it in array() + * + * Read user information from external database and returns it as array(). + * Function should return all information available. If you are saving + * this information to moodle user-table you should honor syncronization flags + * + * @param string $username username (with system magic quotes) + * + * @return mixed array with no magic quotes or false on error + */ + function get_userinfo($username) { + + $textlib = textlib_get_instance(); + $extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding); + + $ldapconnection = $this->ldap_connect(); + $attrmap = $this->ldap_attributes(); + + $result = array(); + $search_attribs = array(); + + foreach ($attrmap as $key=>$values) { + if (!is_array($values)) { + $values = array($values); + } + foreach ($values as $value) { + if (!in_array($value, $search_attribs)) { + array_push($search_attribs, $value); + } + } + } + + $user_dn = $this->ldap_find_userdn($ldapconnection, $extusername); + + if (!$user_info_result = ldap_read($ldapconnection, $user_dn, $this->config->objectclass, $search_attribs)) { + return false; // error! + } + + $user_entry = $this->ldap_get_entries($ldapconnection, $user_info_result); + if (empty($user_entry)) { + return false; // entry not found + } + + foreach ($attrmap as $key=>$values) { + if (!is_array($values)) { + $values = array($values); + } + $ldapval = NULL; + foreach ($values as $value) { + if ($value == 'dn') { + $result[$key] = $user_dn; + } + if (!array_key_exists($value, $user_entry[0])) { + continue; // wrong data mapping! + } + if (is_array($user_entry[0][$value])) { + + $newval = $textlib->convert($user_entry[0][$value][0], $this->config->ldapencoding, 'utf-8'); + } else { + $newval = $textlib->convert($user_entry[0][$value], $this->config->ldapencoding, 'utf-8'); + } + if (!empty($newval)) { // favour ldap entries that are set + $ldapval = $newval; + } + } + if (!is_null($ldapval)) { + $result[$key] = $ldapval; + } + } + + @ldap_close($ldapconnection); + return $result; + } + + /** + * reads userinformation from ldap and return it in an object + * + * @param string $username username (with system magic quotes) + * @return mixed object or false on error + */ + function get_userinfo_asobj($username) { + $user_array = $this->get_userinfo($username); + if ($user_array == false) { + return false; //error or not found + } + $user_array = truncate_userinfo($user_array); + $user = new object(); + foreach ($user_array as $key=>$value) { + $user->{$key} = $value; + } + return $user; + } + + /** + * connects to ldap server + * + * Tries connect to specified ldap servers. + * Returns connection result or error. + * + * @return connection result + */ + function ldap_connect($binddn='',$bindpwd='') { + //Select bind password, With empty values use + //ldap_bind_* variables or anonymous bind if ldap_bind_* are empty + if ($binddn == '' and $bindpwd == '') { + if (!empty($this->config->bind_dn)) { + $binddn = $this->config->bind_dn; + } + if (!empty($this->config->bind_pw)) { + $bindpwd = $this->config->bind_pw; + } + } + + $urls = explode(";",$this->config->host_url); + + foreach ($urls as $server) { + $server = trim($server); + if (empty($server)) { + continue; + } + + $connresult = ldap_connect($server); + //ldap_connect returns ALWAYS true + + if (!empty($this->config->version)) { + ldap_set_option($connresult, LDAP_OPT_PROTOCOL_VERSION, $this->config->version); + } + + if (!empty($binddn)) { + //bind with search-user + //$debuginfo .= 'Using bind user'.$binddn.'and password:'.$bindpwd; + $bindresult=ldap_bind($connresult, $binddn,$bindpwd); + } + else { + //bind anonymously + $bindresult=@ldap_bind($connresult); + } + + if (!empty($this->config->opt_deref)) { + ldap_set_option($connresult, LDAP_OPT_DEREF, $this->config->opt_deref); + } + + if ($bindresult) { + return $connresult; + } + + $debuginfo .= "
Server: '$server'
Connection: '$connresult'
Bind result: '$bindresult'
"; + } + + //If any of servers are alive we have already returned connection + print_error('auth_ldap_noconnect_all','auth',$this->config->user_type); + return false; + } + + /** + * retuns user attribute mappings between moodle and ldap + * + * @return array + */ + + function ldap_attributes () { + $fields = array("firstname", "lastname", "email", "phone1", "phone2", + "department", "address", "city", "country", "description", + "idnumber", "lang" ); + $moodleattributes = array(); + foreach ($fields as $field) { + if (!empty($this->config->{"field_map_$field"})) { + $moodleattributes[$field] = $this->config->{"field_map_$field"}; + if (preg_match('/,/',$moodleattributes[$field])) { + $moodleattributes[$field] = explode(',', $moodleattributes[$field]); // split ? + } + } + } + $moodleattributes['username'] = $this->config->user_attribute; + return $moodleattributes; + } + + /** + * retuns dn of username + * + * Search specified contexts for username and return user dn + * like: cn=username,ou=suborg,o=org + * + * @param mixed $ldapconnection $ldapconnection result + * @param mixed $username username (external encoding no slashes) + * + */ + + function ldap_find_userdn ($ldapconnection, $extusername) { + + //default return value + $ldap_user_dn = FALSE; + + //get all contexts and look for first matching user + $ldap_contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context)) { + array_push($ldap_contexts, $this->config->create_context); + } + + foreach ($ldap_contexts as $context) { + + $context = trim($context); + if (empty($context)) { + continue; + } + + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context, "(".$this->config->user_attribute."=".$this->filter_addslashes($extusername).")",array($this->config->user_attribute)); + + } + else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, "(".$this->config->user_attribute."=".$this->filter_addslashes($extusername).")",array($this->config->user_attribute)); + } + + $entry = ldap_first_entry($ldapconnection,$ldap_result); + + if ($entry) { + $ldap_user_dn = ldap_get_dn($ldapconnection, $entry); + break ; + } + } + + return $ldap_user_dn; + } + + /** + * Quote control characters in quoted "texts" used in ldap + * + * @param string + */ + function ldap_addslashes($text) { + $text = str_replace('\\', '\\\\', $text); + $text = str_replace(array('"', "\0"), + array('\\"', '\\00'), $text); + return $text; + } + + /** + * returns all usernames from external database + * + * get_userlist returns all usernames from external database + * + * @return array + */ + function get_userlist() { + return $this->ldap_get_userlist("({$this->config->user_attribute}=*)"); + } + + /** + * checks if user exists on external db + * + * @param string $username (with system magic quotes) + */ + function user_exists($username) { + + $textlib = textlib_get_instance(); + $extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding); + + //returns true if given username exist on ldap + $users = $this->ldap_get_userlist("({$this->config->user_attribute}=".$this->filter_addslashes($extusername).")"); + return count($users); + } + + /** + * syncronizes user fron external db to moodle user table + * + * Sync is now using username attribute. + * + * Syncing users removes or suspends users that dont exists anymore in external db. + * Creates new users and updates coursecreator status of users. + * + * @param int $bulk_insert_records will insert $bulkinsert_records per insert statement + * valid only with $unsafe. increase to a couple thousand for + * blinding fast inserts -- but test it: you may hit mysqld's + * max_allowed_packet limit. + * @param bool $do_updates will do pull in data updates from ldap if relevant + */ + function sync_users ($bulk_insert_records = 1000, $do_updates = true) { + + global $CFG; + + $textlib = textlib_get_instance(); + + $droptablesql = array(); /// sql commands to drop the table (because session scope could be a problem for + /// some persistent drivers like ODBTP (mssql) or if this function is invoked + /// from within a PHP application using persistent connections + + // configure a temp table + print "Configuring temp table\n"; + switch (strtolower($CFG->dbfamily)) { + case 'mysql': + $temptable = $CFG->prefix . 'extuser'; + $droptablesql[] = 'DROP TEMPORARY TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem) + execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later + echo "Creating temp table $temptable\n"; + execute_sql('CREATE TEMPORARY TABLE ' . $temptable . ' (username VARCHAR(64), PRIMARY KEY (username)) TYPE=MyISAM', false); + break; + case 'postgres': + $temptable = $CFG->prefix . 'extuser'; + $droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem) + execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later + echo "Creating temp table $temptable\n"; + $bulk_insert_records = 1; // no support for multiple sets of values + execute_sql('CREATE TEMPORARY TABLE '. $temptable . ' (username VARCHAR(64), PRIMARY KEY (username))', false); + break; + case 'mssql': + $temptable = '#'.$CFG->prefix . 'extuser'; /// MSSQL temp tables begin with # + $droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem) + execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later + echo "Creating temp table $temptable\n"; + $bulk_insert_records = 1; // no support for multiple sets of values + execute_sql('CREATE TABLE ' . $temptable . ' (username VARCHAR(64), PRIMARY KEY (username))', false); + break; + case 'oracle': + $temptable = $CFG->prefix . 'extuser'; + $droptablesql[] = 'TRUNCATE TABLE ' . $temptable; // oracle requires truncate before being able to drop a temp table + $droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem) + execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later + echo "Creating temp table $temptable\n"; + $bulk_insert_records = 1; // no support for multiple sets of values + execute_sql('CREATE GLOBAL TEMPORARY TABLE '.$temptable.' (username VARCHAR(64), PRIMARY KEY (username)) ON COMMIT PRESERVE ROWS', false); + break; + } + + print "Connecting to ldap...\n"; + $ldapconnection = $this->ldap_connect(); + + if (!$ldapconnection) { + @ldap_close($ldapconnection); + print get_string('auth_ldap_noconnect','auth',$this->config->host_url); + exit; + } + + //// + //// get user's list from ldap to sql in a scalable fashion + //// + // prepare some data we'll need + $filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))"; + + $contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context)) { + array_push($contexts, $this->config->create_context); + } + + $fresult = array(); + foreach ($contexts as $context) { + $context = trim($context); + if (empty($context)) { + continue; + } + begin_sql(); + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context, + $filter, + array($this->config->user_attribute)); + } else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, + $filter, + array($this->config->user_attribute)); + } + + if ($entry = ldap_first_entry($ldapconnection, $ldap_result)) { + do { + $value = ldap_get_values_len($ldapconnection, $entry, $this->config->user_attribute); + $value = $textlib->convert($value[0], $this->config->ldapencoding, 'utf-8'); + array_push($fresult, $value); + if (count($fresult) >= $bulk_insert_records) { + $this->ldap_bulk_insert($fresult, $temptable); + $fresult = array(); + } + } while ($entry = ldap_next_entry($ldapconnection, $entry)); + } + unset($ldap_result); // free mem + + // insert any remaining users and release mem + if (count($fresult)) { + $this->ldap_bulk_insert($fresult, $temptable); + $fresult = array(); + } + commit_sql(); + } + + /// preserve our user database + /// if the temp table is empty, it probably means that something went wrong, exit + /// so as to avoid mass deletion of users; which is hard to undo + $count = get_record_sql('SELECT COUNT(username) AS count, 1 FROM ' . $temptable); + $count = $count->{'count'}; + if ($count < 1) { + print "Did not get any users from LDAP -- error? -- exiting\n"; + exit; + } else { + print "Got $count records from LDAP\n\n"; + } + + +/// User removal + // find users in DB that aren't in ldap -- to be removed! + // this is still not as scalable (but how often do we mass delete?) + if (!empty($this->config->removeuser)) { + $sql = "SELECT u.id, u.username, u.email + FROM {$CFG->prefix}user u + LEFT JOIN $temptable e ON u.username = e.username + WHERE u.auth='cas' + AND u.deleted=0 + AND e.username IS NULL"; + $remove_users = get_records_sql($sql); + + if (!empty($remove_users)) { + print "User entries to remove: ". count($remove_users) . "\n"; + + begin_sql(); + foreach ($remove_users as $user) { + if ($this->config->removeuser == 2) { + //following is copy pasted from admin/user.php + //maybe this should moved to function in lib/datalib.php + $updateuser = new object(); + $updateuser->id = $user->id; + $updateuser->deleted = 1; + $updateuser->username = addslashes("$user->email.".time()); // Remember it just in case + $updateuser->email = ''; // Clear this field to free it up + $updateuser->idnumber = ''; // Clear this field to free it up + $updateuser->timemodified = time(); + if (update_record('user', $updateuser)) { + delete_records('role_assignments', 'userid', $user->id); // unassign all roles + //copy pasted part ends + echo "\t"; print_string('auth_dbdeleteuser', 'auth', array($user->username, $user->id)); echo "\n"; + } else { + echo "\t"; print_string('auth_dbdeleteusererror', 'auth', $user->username); echo "\n"; + } + } else if ($this->config->removeuser == 1) { + $updateuser = new object(); + $updateuser->id = $user->id; + $updateuser->auth = 'nologin'; + if (update_record('user', $updateuser)) { + echo "\t"; print_string('auth_dbsuspenduser', 'auth', array($user->username, $user->id)); echo "\n"; + } else { + echo "\t"; print_string('auth_dbsuspendusererror', 'auth', $user->username); echo "\n"; + } + } + } + commit_sql(); + } else { + print "No user entries to be removed\n"; + } + unset($remove_users); // free mem! + } + +/// Revive suspended users + if (!empty($this->config->removeuser) and $this->config->removeuser == 1) { + $sql = "SELECT u.id, u.username + FROM $temptable e, {$CFG->prefix}user u + WHERE e.username=u.username + AND u.auth='nologin'"; + $revive_users = get_records_sql($sql); + + if (!empty($revive_users)) { + print "User entries to be revived: ". count($revive_users) . "\n"; + + begin_sql(); + foreach ($revive_users as $user) { + $updateuser = new object(); + $updateuser->id = $user->id; + $updateuser->auth = 'cas'; + if (update_record('user', $updateuser)) { + echo "\t"; print_string('auth_dbreviveser', 'auth', array($user->username, $user->id)); echo "\n"; + } else { + echo "\t"; print_string('auth_dbreviveusererror', 'auth', $user->username); echo "\n"; + } + } + commit_sql(); + } else { + print "No user entries to be revived\n"; + } + + unset($revive_users); + } + + +/// User Updates - time-consuming (optional) + if ($do_updates) { + // narrow down what fields we need to update + $all_keys = array_keys(get_object_vars($this->config)); + $updatekeys = array(); + foreach ($all_keys as $key) { + if (preg_match('/^field_updatelocal_(.+)$/',$key, $match)) { + // if we have a field to update it from + // and it must be updated 'onlogin' we + // update it on cron + if ( !empty($this->config->{'field_map_'.$match[1]}) + and $this->config->{$match[0]} === 'onlogin') { + array_push($updatekeys, $match[1]); // the actual key name + } + } + } + // print_r($all_keys); print_r($updatekeys); + unset($all_keys); unset($key); + + } else { + print "No updates to be done\n"; + } + if ( $do_updates and !empty($updatekeys) ) { // run updates only if relevant + $users = get_records_sql("SELECT u.username, u.id + FROM {$CFG->prefix}user u + WHERE u.deleted=0 AND u.auth='cas'"); + if (!empty($users)) { + print "User entries to update: ". count($users). "\n"; + + $sitecontext = get_context_instance(CONTEXT_SYSTEM); + if (!empty($this->config->creators) and !empty($this->config->memberattribute) + and $roles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { + $creatorrole = array_shift($roles); // We can only use one, let's use the first one + } else { + $creatorrole = false; + } + + begin_sql(); + $xcount = 0; + $maxxcount = 100; + + foreach ($users as $user) { + echo "\t"; print_string('auth_dbupdatinguser', 'auth', array($user->username, $user->id)); + if (!$this->update_user_record(addslashes($user->username), $updatekeys)) { + echo " - ".get_string('skipped'); + } + echo "\n"; + $xcount++; + + // update course creators if needed + if ($creatorrole !== false) { + if ($this->iscreator($user->username)) { + role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'cas'); + } else { + role_unassign($creatorrole->id, $user->id, 0, $sitecontext->id, 'cas'); + } + } + + if ($xcount++ > $maxxcount) { + commit_sql(); + begin_sql(); + $xcount = 0; + } + } + commit_sql(); + unset($users); // free mem + } + } else { // end do updates + print "No updates to be done\n"; + } + +/// User Additions + // find users missing in DB that are in LDAP + // note that get_records_sql wants at least 2 fields returned, + // and gives me a nifty object I don't want. + // note: we do not care about deleted accounts anymore, this feature was replaced by suspending to nologin auth plugin + $sql = "SELECT e.username, e.username + FROM $temptable e LEFT JOIN {$CFG->prefix}user u ON e.username = u.username + WHERE u.id IS NULL"; + $add_users = get_records_sql($sql); // get rid of the fat + + if (!empty($add_users)) { + print "User entries to add: ". count($add_users). "\n"; + + $sitecontext = get_context_instance(CONTEXT_SYSTEM); + if (!empty($this->config->creators) and !empty($this->config->memberattribute) + and $roles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { + $creatorrole = array_shift($roles); // We can only use one, let's use the first one + } else { + $creatorrole = false; + } + + begin_sql(); + foreach ($add_users as $user) { + $user = $this->get_userinfo_asobj(addslashes($user->username)); + + // prep a few params + $user->modified = time(); + $user->confirmed = 1; + $user->auth = 'cas'; + $user->mnethostid = $CFG->mnet_localhost_id; + if (empty($user->lang)) { + $user->lang = $CFG->lang; + } + + $user = addslashes_recursive($user); + + if ($id = insert_record('user',$user)) { + echo "\t"; print_string('auth_dbinsertuser', 'auth', array(stripslashes($user->username), $id)); echo "\n"; + $userobj = $this->update_user_record($user->username); + if (!empty($this->config->forcechangepassword)) { + set_user_preference('auth_forcepasswordchange', 1, $userobj->id); + } + } else { + echo "\t"; print_string('auth_dbinsertusererror', 'auth', $user->username); echo "\n"; + } + + // add course creators if needed + if ($creatorrole !== false and $this->iscreator(stripslashes($user->username))) { + role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'cas'); + } + } + commit_sql(); + unset($add_users); // free mem + } else { + print "No users to be added\n"; + } + return true; + } + + /** + * Update a local user record from an external source. + * This is a lighter version of the one in moodlelib -- won't do + * expensive ops such as enrolment. + * + * If you don't pass $updatekeys, there is a performance hit and + * values removed from LDAP won't be removed from moodle. + * + * @param string $username username (with system magic quotes) + */ + function update_user_record($username, $updatekeys = false) { + global $CFG; + + //just in case check text case + $username = trim(moodle_strtolower($username)); + + // get the current user record + $user = get_record('user', 'username', $username, 'mnethostid', $CFG->mnet_localhost_id); + if (empty($user)) { // trouble + error_log("Cannot update non-existent user: ".stripslashes($username)); + print_error('auth_dbusernotexist','auth',$username); + die; + } + + // Protect the userid from being overwritten + $userid = $user->id; + + if ($newinfo = $this->get_userinfo($username)) { + $newinfo = truncate_userinfo($newinfo); + + if (empty($updatekeys)) { // all keys? this does not support removing values + $updatekeys = array_keys($newinfo); + } + + foreach ($updatekeys as $key) { + if (isset($newinfo[$key])) { + $value = $newinfo[$key]; + } else { + $value = ''; + } + + if (!empty($this->config->{'field_updatelocal_' . $key})) { + if ($user->{$key} != $value) { // only update if it's changed + set_field('user', $key, addslashes($value), 'id', $userid); + } + } + } + } else { + return false; + } + return get_record_select('user', "id = $userid AND deleted = 0"); + } + + /** + * Bulk insert in SQL's temp table + * @param array $users is an array of usernames + */ + function ldap_bulk_insert($users, $temptable) { + + // bulk insert -- superfast with $bulk_insert_records + $sql = 'INSERT INTO ' . $temptable . ' (username) VALUES '; + // make those values safe + $users = addslashes_recursive($users); + // join and quote the whole lot + $sql = $sql . "('" . implode("'),('", $users) . "')"; + print "\t+ " . count($users) . " users\n"; + execute_sql($sql, false); + } + + + + /** + * Returns true if user should be coursecreator. + * + * @param mixed $username username (without system magic quotes) + * @return boolean result + */ + function iscreator($username) { + + if ((empty($this->config->attrcreators) && empty($this->config->groupecreators)) or empty($this->config->memberattribute)) { + return null; + } + + $textlib = textlib_get_instance(); + $extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding); + +//test for groupe creator + +if (!empty($this->config->groupecreators)) + if ((boolean)$this->ldap_isgroupmember($extusername, $this->config->groupecreators)) + return true; + +//build filter for attrcreator +if (!empty($this->config->attrcreators)) { + $attrs = explode(";",$this->config->attrcreators); + $filter = "(& (".$this->config->user_attribute."=$username)(|"; + foreach ($attrs as $attr){ + if(strpos($attr, "=")) + $filter .= "($attr)"; + else + $filter .= "(".$this->config->memberattribute."=$attr)"; + } + $filter .= "))"; + //search + $result = $this->ldap_get_userlist($filter); + + if (count($result)!=0) + return true; + } + + return false; + } + + /** + * checks if user belong to specific group(s) + * + * Returns true if user belongs group in grupdns string. + * + * @param mixed $username username + * @param mixed $groupdns string of group dn separated by ; + * + */ + function ldap_isgroupmember($extusername='', $groupdns='') { + // Takes username and groupdn(s) , separated by ; + // Returns true if user is member of any given groups + + $ldapconnection = $this->ldap_connect(); + + if (empty($extusername) or empty($groupdns)) { + return false; + } + + if ($this->config->memberattribute_isdn) { + $memberuser = $this->ldap_find_userdn($ldapconnection, $extusername); + } else { + $memberuser = $extusername; + } + + if (empty($memberuser)) { + return false; + } + + $groups = explode(";",$groupdns); + + $result = false; + foreach ($groups as $group) { + $group = trim($group); + if (empty($group)) { + continue; + } + //echo "Checking group $group for member $username\n"; + $search = ldap_read($ldapconnection, $group, '('.$this->config->memberattribute.'='.$this->filter_addslashes($memberuser).')', array($this->config->memberattribute)); + if (!empty($search) and ldap_count_entries($ldapconnection, $search)) { + $info = $this->ldap_get_entries($ldapconnection, $search); + + if (count($info) > 0 ) { + // user is member of group + $result = true; + break; + } + } + } + + return $result; + + } + + /** + * return all usernames from ldap + * + * @return array + */ + + function ldap_get_userlist($filter="*") { + /// returns all users from ldap servers + $fresult = array(); + + $ldapconnection = $this->ldap_connect(); + + if ($filter=="*") { + $filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))"; + } + + $contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context)) { + array_push($contexts, $this->config->create_context); + } + + foreach ($contexts as $context) { + + $context = trim($context); + if (empty($context)) { + continue; + } + + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context,$filter,array($this->config->user_attribute)); + } + else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, + $filter, + array($this->config->user_attribute)); + } + + $users = $this->ldap_get_entries($ldapconnection, $ldap_result); + + //add found users to list + for ($i=0;$iconfig->user_attribute][0]) ); + } + } + + return $fresult; + } + + /** + * return entries from ldap + * + * Returns values like ldap_get_entries but is + * binary compatible and return all attributes as array + * + * @return array ldap-entries + */ + + function ldap_get_entries($conn, $searchresult) { + //Returns values like ldap_get_entries but is + //binary compatible + $i=0; + $fresult=array(); + $entry = ldap_first_entry($conn, $searchresult); + + do { + $attributes = @ldap_get_attributes($conn, $entry); + for ($j=0; $j<$attributes['count']; $j++) { + $values = ldap_get_values_len($conn, $entry,$attributes[$j]); + if (is_array($values)) { + $fresult[$i][$attributes[$j]] = $values; + } + else { + $fresult[$i][$attributes[$j]] = array($values); + } + } + $i++; + } + while ($entry = @ldap_next_entry($conn, $entry)); + //were done + return ($fresult); + } + + /** + * Sync roles for this user + * + * @param $user object user object (without system magic quotes) + */ + function sync_roles($user) { + $iscreator = $this->iscreator($user->username); + if ($iscreator === null) { + return; //nothing to sync - creators not configured + } + + if ($roles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { + $creatorrole = array_shift($roles); // We can only use one, let's use the first one + $systemcontext = get_context_instance(CONTEXT_SYSTEM); + + if ($iscreator) { // Following calls will not create duplicates + role_assign($creatorrole->id, $user->id, 0, $systemcontext->id, 0, 0, 0, 'cas'); + } else { + //unassign only if previously assigned by this plugin! + role_unassign($creatorrole->id, $user->id, 0, $systemcontext->id, 'cas'); + } + } + } + + /** + * Quote control characters in texts used in ldap filters - see rfc2254.txt + * + * @param string + */ + function filter_addslashes($text) { + $text = str_replace('\\', '\\5c', $text); + $text = str_replace(array('*', '(', ')', "\0"), + array('\\2a', '\\28', '\\29', '\\00'), $text); + return $text; + } + +} + + +?> diff --git a/auth/cas/cas_form.html b/auth/cas/cas_form.html new file mode 100644 index 00000000000..43eb05faf55 --- /dev/null +++ b/auth/cas/cas_form.html @@ -0,0 +1,12 @@ + +
+
+
+ +
+
+
+ +
+
+
diff --git a/auth/cas/auth_ldap_sync_users.php b/auth/cas/cas_ldap_sync_users.php similarity index 100% rename from auth/cas/auth_ldap_sync_users.php rename to auth/cas/cas_ldap_sync_users.php diff --git a/auth/cas/config.html b/auth/cas/config.html index 8ce11b4b7a4..b7446fdb3c0 100644 --- a/auth/cas/config.html +++ b/auth/cas/config.html @@ -1,187 +1,434 @@ -hostname)) { - $config->hostname = ''; - } - if (!isset ($config->port)) { - $config->port = ''; - } - if (!isset ($config->casversion)) { - $config->casversion = ''; - } - if (!isset ($config->baseuri)) { - $config->baseuri = ''; - } - if (!isset ($config->language)) { - $config->language = ''; - } - if (!isset ($config->use_cas)) { - $config->use_cas = ''; - } - if (!isset ($config->auth_user_create)) { - $config->auth_user_create = '0'; - } - if (!isset ($config->create_user)) { - $config->create_user = '0'; - } - if (!isset($config->changepasswordurl)) { - $config->changepasswordurl = ''; - } - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

-
: - use_cas, get_string('no'), '', ''); - - ?> -
: - - -
: - - -
: - - -
: - - -
: - language, ''); - - ?> -
: - auth_user_create, ''); - if (isset($err['auth_user_create'])) { - formerr($err['auth_user_create']); - } - - ?> - - -
: - create_user, ''); - - ?> -
: - - -
- -config_form(get_config('auth/ldap'), $err); - -?> +hostname)) + $config->hostname = ''; + if (!isset ($config->port)) + $config->port = ''; + if (!isset ($config->casversion)) + $config->casversion = ''; + if (!isset ($config->baseuri)) + $config->baseuri = ''; + if (!isset ($config->language)) + $config->language = ''; + if (!isset ($config->use_cas)) + $config->use_cas = ''; + if (!isset ($config->proxycas)) + $config->proxycas = ''; + if (!isset ($config->logoutcas)) + $config->logoutcas = ''; + if (!isset ($config->multiauth)) + $config->multiauth = ''; + // set to defaults if undefined (LDAP) + if (!isset($config->host_url)) + { $config->host_url = ''; } + if (empty($config->ldapencoding)) + { $config->ldapencoding = 'utf-8'; } + if (!isset($config->contexts)) + { $config->contexts = ''; } + if (!isset($config->user_type)) + { $config->user_type = 'default'; } + if (!isset($config->user_attribute)) + { $config->user_attribute = ''; } + if (!isset($config->search_sub)) + { $config->search_sub = ''; } + if (!isset($config->opt_deref)) + { $config->opt_deref = LDAP_DEREF_NEVER; } + if (!isset($config->bind_dn)) + {$config->bind_dn = ''; } + if (!isset($config->bind_pw)) + {$config->bind_pw = ''; } + if (!isset($config->version)) + {$config->version = '2'; } + if (!isset($config->objectclass)) + {$config->objectclass = ''; } + if (!isset($config->memberattribute)) + {$config->memberattribute = ''; } + if (!isset($config->memberattribute_isdn)) + {$config->memberattribute_isdn = ''; } + if (!isset($config->groupecreators)) + {$config->groupecreators = ''; } + if (!isset($config->attrcreators)) + {$config->attrcreators = ''; } + if (!isset($config->removeuser)) + {$config->removeuser = 0; } + + $yesno = array( get_string('no'), get_string('yes') ); + +if (!function_exists('ldap_connect')) { // Is php4-ldap really there? + notify(get_string('auth_ldap_noextension','auth')); + } + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+
: + use_cas, get_string('no'), '', ''); + + ?> +
: + + +
: + + +
: + + +
: + + +
: + language, ''); + + ?> +
: + proxycas, get_string('no'), '', ''); + ?> +
: + logoutcas, get_string('no'), '', ''); + ?> +
: + multiauth, get_string('no'), '', ''); + ?> +
+

+
+ + + + +
+ version, ''); + if (isset($err['version'])) formerr($err['version']); + ?> + + +
+ + +
+

+
+ + + + +
+ + + + +
+

+
+ ldap_suppported_usertypes(), 'user_type', $config->user_type, ''); ?> + + + +
+ + + + +
+ search_sub, ''); ?> + + +
+ opt_deref, LDAP_DEREF_NEVER, ''); + if (isset($err['opt_deref'])) formerr($err['opt_deref']); + ?> + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+

+
+ + + + +
+ + + + +
+

+
+ removeuser, ''); + ?> + + +
+ +'; +$help .= get_string('auth_updateremote_ldap','auth'); + +print_auth_lock_options('cas', $user_fields, $help, true, true); + +?> diff --git a/auth/cas/forbidden.html b/auth/cas/forbidden.html deleted file mode 100644 index fb4674bef68..00000000000 --- a/auth/cas/forbidden.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - -
-

-
- diff --git a/auth/cas/forbidden.php b/auth/cas/forbidden.php deleted file mode 100644 index 918261ecf65..00000000000 --- a/auth/cas/forbidden.php +++ /dev/null @@ -1,18 +0,0 @@ -fullname: $loginsite", $site->fullname, $loginsite); - include("forbidden.html"); - print_footer(); - exit; -?> - diff --git a/auth/cas/index_form.html b/auth/cas/index_form.html deleted file mode 100644 index 5a1c85e2e39..00000000000 --- a/auth/cas/index_form.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - -
-

-
-

-
-

:
- () -
-

-
-
- - - - -
- - - " /> -
-
-
-guestloginbutton) { ?> -
-

:

-
-
- - - " /> -
-
- - - -
-

-
-
-
- - -
-auth) { - case "email": - print_string("loginsteps", "", "signup.php"); -?> -
-
" />
-
-auth); - echo format_text($CFG->auth_instructions); - if (!empty($authplugin->config->user_create) and method_exists($authplugin, 'user_create')) { -?> - -
-
" />
-
- - -
- diff --git a/auth/cas/languages.php b/auth/cas/languages.php index c021b004097..c3dc5310e15 100644 --- a/auth/cas/languages.php +++ b/auth/cas/languages.php @@ -1,10 +1,9 @@ - "Modern Greek", -"english" => "English", -"french" => "French"); -?> \ No newline at end of file + "English", +"french" => "French"); +?> diff --git a/auth/cas/login.php b/auth/cas/login.php deleted file mode 100644 index 7551bc88c40..00000000000 --- a/auth/cas/login.php +++ /dev/null @@ -1,313 +0,0 @@ -langmenu)) { - $langmenu = ""; - } else { - $currlang = current_language(); - $langs = get_list_of_languages(); - if (empty($CFG->loginhttps)) { - $wwwroot = $CFG->wwwroot; - } else { - $wwwroot = str_replace('http:','https:',$CFG->wwwroot); - } - $langmenu = popup_form ("$wwwroot/login/index.php?lang=", $langs, "chooselang", $currlang, "", "", "", true); - } - - $loginsite = get_string("loginsite"); - $casauth = get_auth_plugin('cas'); - $ldapauth = get_auth_plugin('ldap'); - - - $frm = false; - $user = false; - if ((!empty($SESSION->wantsurl) and strstr($SESSION->wantsurl,'username=guest')) or $loginguest) { - /// Log in as guest automatically (idea from Zbigniew Fiedorowicz) - $frm->username = 'guest'; - $frm->password = 'guest'; - } else if (!empty($SESSION->wantsurl) && file_exists($CFG->dirroot.'/login/weblinkauth.php')) { - // Handles the case of another Moodle site linking into a page on this site - include($CFG->dirroot.'/login/weblinkauth.php'); - if (function_exists(weblink_auth)) { - $user = weblink_auth($SESSION->wantsurl); - } - if ($user) { - $frm->username = $user->username; - } else { - $frm = data_submitted(); - } - } else { - $frm = data_submitted(); - } - - if ($frm and (get_moodle_cookie() == '')) { // Login without cookie - - $errormsg = get_string("cookiesnotenabled"); - - } else if ($frm) { // Login WITH cookies - - $frm->username = trim(moodle_strtolower($frm->username)); - - if (($frm->username == 'guest') and empty($CFG->guestloginbutton)) { - $user = false; /// Can't log in as guest if guest button is disabled - $frm = false; - } else if (!$user) { - if ($CFG->auth == "cas" && $frm->username != 'guest') { /// Cas SSO case - $user = $casauth->authenticate_user_login($frm->username, $frm->password); - }else{ - $user = authenticate_user_login($frm->username, $frm->password); - } - } - update_login_count(); - - if ($user) { - if (! $user->confirmed ) { // they never confirmed via email - print_header(get_string("mustconfirm"), get_string("mustconfirm") ); - print_heading(get_string("mustconfirm")); - print_simple_box(get_string("emailconfirmsent", "", $user->email), "center"); - print_footer(); - die; - } - - $USER = $user; - if (!empty($USER->description)) { - $USER->description = true; // No need to cart all of it around - } - $USER->loggedin = true; - $USER->site = $CFG->wwwroot; // for added security, store the site in the session - sesskey(); // for added security, used to check script parameters - - if ($USER->username == "guest") { - $USER->lang = $CFG->lang; // Guest language always same as site - $USER->firstname = get_string("guestuser"); // Name always in current language - $USER->lastname = " "; - } - - if (!update_user_login_times()) { - error("Wierd error: could not update login records"); - } - - set_moodle_cookie($USER->username); - - unset($SESSION->lang); - $SESSION->justloggedin = true; - - // Restore the calendar filters, if saved - if (intval(get_user_preferences('calendar_persistflt', 0))) { - include_once($CFG->dirroot.'/calendar/lib.php'); - calendar_set_filters_status(get_user_preferences('calendar_savedflt', 0xff)); - } - - //Select password change url - $userauth = get_auth_plugin($USER->auth); - if (method_exists($userauth, 'can_change_password') and $userauth->can_change_password()) { - $passwordchangeurl=$CFG->wwwroot.'/login/change_password.php'; - } - - // check whether the user should be changing password - if (get_user_preferences('auth_forcepasswordchange', false)) { - if (isset($passwordchangeurl)) { - redirect($passwordchangeurl); - } else { - print_error('auth_cas_broken_password','auth'); - } - } - - - add_to_log(SITEID, "user", "login", "view.php?id=$user->id&course=".SITEID, $user->id, 0, $user->id); - - if (user_not_fully_set_up($USER)) { - $urltogo = $CFG->wwwroot.'/user/edit.php?id='.$USER->id.'&course='.SITEID; - // We don't delete $SESSION->wantsurl yet, so we get there later - - } else if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0)) { - $urltogo = $SESSION->wantsurl; /// Because it's an address in this site - unset($SESSION->wantsurl); - - } else { - $urltogo = $CFG->wwwroot.'/'; /// Go to the standard home page - unset($SESSION->wantsurl); /// Just in case - } - - // check if user password has expired - // Currently supported only for ldap-authentication module - if ($ldapauth->config->expiration == 1) { - $days2expire = $ldapauth->password_expire($USER->username); - if (intval($days2expire) > 0 && intval($days2expire) < intval($CFG->{$USER->auth.'_expiration_warning'})) { - print_header("$site->fullname: $loginsite", $site->fullname, $loginsite, $focus, "", true, "
$langmenu
"); - notice_yesno(get_string('auth_passwordwillexpire', 'auth', $days2expire), $passwordchangeurl, $urltogo); - print_footer(); - exit; - } elseif (intval($days2expire) < 0 ) { - print_header("$site->fullname: $loginsite", $site->fullname, $loginsite, $focus, "", true, "
$langmenu
"); - notice_yesno(get_string('auth_passwordisexpired', 'auth'), $passwordchangeurl, $urltogo); - print_footer(); - exit; - } - } - - reset_login_count(); - - load_all_capabilities(); /// This is what lets the user do anything on the site :-) - - redirect($urltogo); - - exit; - - } else { - if ($CFG->auth == "cas" ) { /// CAS error login - $errormsg = get_string("invalidcaslogin"); - phpCAS::logout("$CFG->wwwroot/auth/cas/forbidden.php"); - }else{ - $errormsg = get_string("invalidlogin"); - } - } - } - $user = $casauth->automatic_authenticate($user); - if ($user) { - if (! $user->confirmed ) { // they never confirmed via email - print_header(get_string("mustconfirm"), get_string("mustconfirm") ); - print_heading(get_string("mustconfirm")); - print_simple_box(get_string("emailconfirmsent", "", $user->email), "center"); - print_footer(); - die; - } - - $USER = $user; - if (!empty($USER->description)) { - $USER->description = true; // No need to cart all of it around - } - $USER->loggedin = true; - $USER->site = $CFG->wwwroot; // for added security, store the site in the session - sesskey(); // for added security, used to check script parameters - - if ($USER->username == "guest") { - $USER->lang = $CFG->lang; // Guest language always same as site - $USER->firstname = get_string("guestuser"); // Name always in current language - $USER->lastname = " "; - } - - if (!update_user_login_times()) { - error("Wierd error: could not update login records"); - } - - set_moodle_cookie($USER->username); - - unset($SESSION->lang); - $SESSION->justloggedin = true; - - // Restore the calendar filters, if saved - if (intval(get_user_preferences('calendar_persistflt', 0))) { - include_once($CFG->dirroot.'/calendar/lib.php'); - calendar_set_filters_status(get_user_preferences('calendar_savedflt', 0xff)); - } - - //Select password change url - $userauth = get_auth_plugin($USER->auth); - if (method_exists($userauth, 'can_change_password') and $userauth->can_change_password()) { - $passwordchangeurl=$CFG->wwwroot.'/login/change_password.php'; - } - - // check whether the user should be changing password - if (get_user_preferences('auth_forcepasswordchange', false)) { - if (isset($passwordchangeurl)) { - redirect($passwordchangeurl); - } else { - print_error('auth_cas_broken_password','auth'); - } - } - - - add_to_log(SITEID, "user", "login", "view.php?id=$user->id&course=".SITEID, $user->id, 0, $user->id); - - if (user_not_fully_set_up($USER)) { - $urltogo = $CFG->wwwroot.'/user/edit.php?id='.$USER->id.'&course='.SITEID; - // We don't delete $SESSION->wantsurl yet, so we get there later - - } else if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0)) { - $urltogo = $SESSION->wantsurl; /// Because it's an address in this site - unset($SESSION->wantsurl); - - } else { - $urltogo = $CFG->wwwroot.'/'; /// Go to the standard home page - unset($SESSION->wantsurl); /// Just in case - } - - // check if user password has expired - // Currently supported only for ldap-authentication module - if ($ldapauth->config->expiration == 1) { - $days2expire = $ldapauth->password_expire($USER->username); - if (intval($days2expire) > 0 && intval($days2expire) < intval($CFG->{$USER->auth.'_expiration_warning'})) { - print_header("$site->fullname: $loginsite", $site->fullname, $loginsite, $focus, "", true, "
$langmenu
"); - notice_yesno(get_string('auth_passwordwillexpire', 'auth', $days2expire), $passwordchangeurl, $urltogo); - print_footer(); - exit; - } elseif (intval($days2expire) < 0 ) { - print_header("$site->fullname: $loginsite", $site->fullname, $loginsite, $focus, "", true, "
$langmenu
"); - notice_yesno(get_string('auth_passwordisexpired', 'auth'), $passwordchangeurl, $urltogo); - print_footer(); - exit; - } - } - - reset_login_count(); - - load_all_capabilities(); /// This is what lets the user do anything on the site :-) - - redirect($urltogo); - - exit; - } else { - if (!$CFG->guestloginbutton) { - $errormsg = get_string("invalidcaslogin"); - phpCAS::logout("$CFG->wwwroot/auth/cas/forbidden.php"); - } - } - - if (empty($errormsg)) { - $errormsg = ""; - } - - if (empty($SESSION->wantsurl)) { - $SESSION->wantsurl = array_key_exists('HTTP_REFERER',$_SERVER) ? $_SERVER["HTTP_REFERER"] : $CFG->wwwroot.'/'; - } - - if (get_moodle_cookie() == '') { - set_moodle_cookie('nobody'); // To help search for cookies - } - - if (empty($frm->username)) { - $frm->username = get_moodle_cookie() === 'nobody' ? '' : get_moodle_cookie(); - $frm->password = ""; - } - - if (!empty($frm->username)) { - $focus = "login.password"; - } else { - $focus = "login.username"; - } - - if ($CFG->auth == "email" or $CFG->auth == "none" or chop($CFG->auth_instructions) <> "" ) { - $show_instructions = true; - } else { - $show_instructions = false; - } - - print_header("$site->fullname: $loginsite", $site->fullname, $loginsite, $focus, "", true, "
$langmenu
"); - include($CFG->dirroot.'/auth/cas/index_form.html'); - print_footer(); - - exit; - - // No footer on this page - -?> diff --git a/auth/cas/logout.php b/auth/cas/logout.php deleted file mode 100644 index 5f0a5cc87ad..00000000000 --- a/auth/cas/logout.php +++ /dev/null @@ -1,15 +0,0 @@ -cas_logout) { - require_once($CFG->dirroot.'/config.php'); - include_once($CFG->dirroot.'/lib/cas/CAS.php'); - phpCAS::client($CFG->cas_version,$CFG->cas_hostname,(int)$CFG->cas_port,$CFG->cas_baseuri); - $backurl = $CFG->wwwroot; - phpCAS::logout($backurl); - } - -?> \ No newline at end of file diff --git a/lang/en_utf8/auth.php b/lang/en_utf8/auth.php index 21a555d8eb2..1a6b689fde3 100644 --- a/lang/en_utf8/auth.php +++ b/lang/en_utf8/auth.php @@ -30,6 +30,15 @@ $string['auth_nologindescription'] = 'Auxiliary plugin that prevents user to log $string['auth_nologintitle'] = 'No login'; // CAS plugin +$string['auth_cas_proxycas_key'] = "Proxy mode"; +$string['auth_cas_logoutcas_key'] = "Logout CAS"; +$string['auth_cas_multiauth_key'] = "Multi-authentication"; +$string['auth_cas_proxycas'] = "Turn this to 'yes'' if you use CASin proxy-mode"; +$string['auth_cas_logoutcas'] = "Turn this to 'yes'' if tou want to logout from CAS when you deconnect from Moodle"; +$string['auth_cas_multiauth'] = "Turn this to 'yes'' if you want to have multi-authentication (CAS + other authentication)"; +$string['accesCAS'] = "CAS users"; +$string['accesNOCAS'] = "other users"; +$string['CASform'] = "Authentication choice"; $string['auth_cas_logincas'] = 'Secure connection access'; $string['auth_cas_invalidcaslogin'] = 'Sorry, your login has failed - you could not be authorised'; $string['auth_cas_server_settings'] = 'CAS server configuration'; diff --git a/lib/cas/CAS.php b/lib/cas/CAS.php deleted file mode 100644 index 07774766072..00000000000 --- a/lib/cas/CAS.php +++ /dev/null @@ -1,1182 +0,0 @@ -=')) { - require_once(dirname(__FILE__).'/domxml-php4-php5.php'); -} - -/** - * @file CAS/CAS.php - * Interface class of the phpCAS library - * - * @ingroup public - */ - -// ######################################################################## -// CONSTANTS -// ######################################################################## - -// ------------------------------------------------------------------------ -// CAS VERSIONS -// ------------------------------------------------------------------------ - -/** - * phpCAS version. accessible for the user by phpCAS::getVersion(). - */ -define('PHPCAS_VERSION','0.4.20-1'); - -// ------------------------------------------------------------------------ -// CAS VERSIONS -// ------------------------------------------------------------------------ -/** - * @addtogroup public - * @{ - */ - -/** - * CAS version 1.0 - */ -define("CAS_VERSION_1_0",'1.0'); -/*! - * CAS version 2.0 - */ -define("CAS_VERSION_2_0",'2.0'); - -/** @} */ -/** - * @addtogroup publicPGTStorage - * @{ - */ -// ------------------------------------------------------------------------ -// FILE PGT STORAGE -// ------------------------------------------------------------------------ -/** - * Default path used when storing PGT's to file - */ -define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH",'/tmp'); -/** - * phpCAS::setPGTStorageFile()'s 2nd parameter to write plain text files - */ -define("CAS_PGT_STORAGE_FILE_FORMAT_PLAIN",'plain'); -/** - * phpCAS::setPGTStorageFile()'s 2nd parameter to write xml files - */ -define("CAS_PGT_STORAGE_FILE_FORMAT_XML",'xml'); -/** - * Default format used when storing PGT's to file - */ -define("CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT",CAS_PGT_STORAGE_FILE_FORMAT_PLAIN); -// ------------------------------------------------------------------------ -// DATABASE PGT STORAGE -// ------------------------------------------------------------------------ -/** - * default database type when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE",'mysql'); -/** - * default host when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME",'localhost'); -/** - * default port when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_PORT",''); -/** - * default database when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE",'phpCAS'); -/** - * default table when storing PGT's to database - */ -define("CAS_PGT_STORAGE_DB_DEFAULT_TABLE",'pgt'); - -/** @} */ -// ------------------------------------------------------------------------ -// SERVICE ACCESS ERRORS -// ------------------------------------------------------------------------ -/** - * @addtogroup publicServices - * @{ - */ - -/** - * phpCAS::service() error code on success - */ -define("PHPCAS_SERVICE_OK",0); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the CAS server did not respond. - */ -define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE",1); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the response of the CAS server was ill-formed. - */ -define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE",2); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the CAS server did not want to. - */ -define("PHPCAS_SERVICE_PT_FAILURE",3); -/** - * phpCAS::service() error code when the service was not available. - */ -define("PHPCAS_SERVICE_NOT AVAILABLE",4); - -/** @} */ -// ------------------------------------------------------------------------ -// LANGUAGES -// ------------------------------------------------------------------------ -/** - * @addtogroup publicLang - * @{ - */ - -define("PHPCAS_LANG_ENGLISH", 'english'); -define("PHPCAS_LANG_FRENCH", 'french'); -define("PHPCAS_LANG_GREEK", 'greek'); - -/** @} */ - -/** - * @addtogroup internalLang - * @{ - */ - -/** - * phpCAS default language (when phpCAS::setLang() is not used) - */ -define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH); - -/** @} */ -// ------------------------------------------------------------------------ -// MISC -// ------------------------------------------------------------------------ -/** - * @addtogroup internalMisc - * @{ - */ - -/** - * This global variable is used by the interface class phpCAS. - * - * @hideinitializer - */ -$PHPCAS_CLIENT = null; - -/** - * This global variable is used to store where the initializer is called from - * (to print a comprehensive error in case of multiple calls). - * - * @hideinitializer - */ -$PHPCAS_INIT_CALL = array('done' => FALSE, - 'file' => '?', - 'line' => -1, - 'method' => '?'); - -/** - * This global variable is used to store where the method checking - * the authentication is called from (to print comprehensive errors) - * - * @hideinitializer - */ -$PHPCAS_AUTH_CHECK_CALL = array('done' => FALSE, - 'file' => '?', - 'line' => -1, - 'method' => '?', - 'result' => FALSE); - -/** - * This global variable is used to store phpCAS debug mode. - * - * @hideinitializer - */ -$PHPCAS_DEBUG = array('filename' => FALSE, - 'indent' => 0, - 'unique_id' => ''); - -/** @} */ - -// ######################################################################## -// CLIENT CLASS -// ######################################################################## - -// include client class -include_once(dirname(__FILE__).'/client.php'); - -// ######################################################################## -// INTERFACE CLASS -// ######################################################################## - -/** - * @class phpCAS - * The phpCAS class is a simple container for the phpCAS library. It provides CAS - * authentication for web applications written in PHP. - * - * @ingroup public - * @author Pascal Aubry - * - * \internal All its methods access the same object ($PHPCAS_CLIENT, declared - * at the end of CAS/client.php). - */ - - - -class phpCAS -{ - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * @addtogroup publicInit - * @{ - */ - - /** - * phpCAS client initializer. - * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be - * called, only once, and before all other methods (except phpCAS::getVersion() - * and phpCAS::setDebug()). - * - * @param $server_version the version of the CAS server - * @param $server_hostname the hostname of the CAS server - * @param $server_port the port the CAS server is running on - * @param $server_uri the URI the CAS server is responding on - * @param $start_session Have phpCAS start PHP sessions (default true) - * - * @return a newly created CASClient object - */ - function client($server_version, - $server_hostname, - $server_port, - $server_uri, - $start_session = true) - { - global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL; - - phpCAS::traceBegin(); - if ( is_object($PHPCAS_CLIENT) ) { - phpCAS::error($PHPCAS_INIT_CALL['method'].'() has already been called (at '.$PHPCAS_INIT_CALL['file'].':'.$PHPCAS_INIT_CALL['line'].')'); - } - if ( gettype($server_version) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_version (should be `string\')'); - } - if ( gettype($server_hostname) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_hostname (should be `string\')'); - } - if ( gettype($server_port) != 'integer' ) { - phpCAS::error('type mismatched for parameter $server_port (should be `integer\')'); - } - if ( gettype($server_uri) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_uri (should be `string\')'); - } - - // store where the initialzer is called from - $dbg = phpCAS::backtrace(); - $PHPCAS_INIT_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__); - - // initialize the global object $PHPCAS_CLIENT - $PHPCAS_CLIENT = new CASClient($server_version,FALSE/*proxy*/,$server_hostname,$server_port,$server_uri,$start_session); - phpCAS::traceEnd(); - } - - /** - * phpCAS proxy initializer. - * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be - * called, only once, and before all other methods (except phpCAS::getVersion() - * and phpCAS::setDebug()). - * - * @param $server_version the version of the CAS server - * @param $server_hostname the hostname of the CAS server - * @param $server_port the port the CAS server is running on - * @param $server_uri the URI the CAS server is responding on - * @param $start_session Have phpCAS start PHP sessions (default true) - * - * @return a newly created CASClient object - */ - function proxy($server_version, - $server_hostname, - $server_port, - $server_uri, - $start_session = true) - { - global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL; - - phpCAS::traceBegin(); - if ( is_object($PHPCAS_CLIENT) ) { - phpCAS::error($PHPCAS_INIT_CALL['method'].'() has already been called (at '.$PHPCAS_INIT_CALL['file'].':'.$PHPCAS_INIT_CALL['line'].')'); - } - if ( gettype($server_version) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_version (should be `string\')'); - } - if ( gettype($server_hostname) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_hostname (should be `string\')'); - } - if ( gettype($server_port) != 'integer' ) { - phpCAS::error('type mismatched for parameter $server_port (should be `integer\')'); - } - if ( gettype($server_uri) != 'string' ) { - phpCAS::error('type mismatched for parameter $server_uri (should be `string\')'); - } - - // store where the initialzer is called from - $dbg = phpCAS::backtrace(); - $PHPCAS_INIT_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__); - - // initialize the global object $PHPCAS_CLIENT - $PHPCAS_CLIENT = new CASClient($server_version,TRUE/*proxy*/,$server_hostname,$server_port,$server_uri,$start_session); - phpCAS::traceEnd(); - } - - /** @} */ - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * @addtogroup publicDebug - * @{ - */ - - /** - * Set/unset debug mode - * - * @param $filename the name of the file used for logging, or FALSE to stop debugging. - */ - function setDebug($filename='') - { - global $PHPCAS_DEBUG; - - if ( $filename != FALSE && gettype($filename) != 'string' ) { - phpCAS::error('type mismatched for parameter $dbg (should be FALSE or the name of the log file)'); - } - - if ( empty($filename) ) { - if ( preg_match('/^Win.*/',getenv('OS')) ) { - if ( isset($_ENV['TMP']) ) { - $debugDir = $_ENV['TMP'].'/'; - } else if ( isset($_ENV['TEMP']) ) { - $debugDir = $_ENV['TEMP'].'/'; - } else { - $debugDir = ''; - } - } else { - $debugDir = '/tmp/'; - } - $filename = $debugDir . 'phpCAS.log'; - } - - if ( empty($PHPCAS_DEBUG['unique_id']) ) { - $PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))),0,4); - } - - $PHPCAS_DEBUG['filename'] = $filename; - - phpCAS::trace('START ******************'); - } - - /** @} */ - /** - * @addtogroup internalDebug - * @{ - */ - - /** - * This method is a wrapper for debug_backtrace() that is not available - * in all PHP versions (>= 4.3.0 only) - */ - function backtrace() - { - if ( function_exists('debug_backtrace') ) { - return debug_backtrace(); - } else { - // poor man's hack ... but it does work ... - return array(); - } - } - - /** - * Logs a string in debug mode. - * - * @param $str the string to write - * - * @private - */ - function log($str) - { - $indent_str = "."; - global $PHPCAS_DEBUG; - - if ( $PHPCAS_DEBUG['filename'] ) { - for ($i=0;$i<$PHPCAS_DEBUG['indent'];$i++) { - $indent_str .= '| '; - } - error_log($PHPCAS_DEBUG['unique_id'].' '.$indent_str.$str."\n",3,$PHPCAS_DEBUG['filename']); - } - - } - - /** - * This method is used by interface methods to print an error and where the function - * was originally called from. - * - * @param $msg the message to print - * - * @private - */ - function error($msg) - { - $dbg = phpCAS::backtrace(); - $function = '?'; - $file = '?'; - $line = '?'; - if ( is_array($dbg) ) { - for ( $i=1; $i\nphpCAS error: ".__CLASS__."::".$function.'(): '.htmlentities($msg)." in ".$file." on line ".$line."
\n"; - phpCAS::trace($msg); - phpCAS::traceExit(); - exit(); - } - - /** - * This method is used to log something in debug mode. - */ - function trace($str) - { - $dbg = phpCAS::backtrace(); - phpCAS::log($str.' ['.basename($dbg[1]['file']).':'.$dbg[1]['line'].']'); - } - - /** - * This method is used to indicate the start of the execution of a function in debug mode. - */ - function traceBegin() - { - global $PHPCAS_DEBUG; - - $dbg = phpCAS::backtrace(); - $str = '=> '; - if ( !empty($dbg[2]['class']) ) { - $str .= $dbg[2]['class'].'::'; - } - $str .= $dbg[2]['function'].'('; - if ( is_array($dbg[2]['args']) ) { - foreach ($dbg[2]['args'] as $index => $arg) { - if ( $index != 0 ) { - $str .= ', '; - } - $str .= str_replace("\n","",var_export($arg,TRUE)); - } - } - $str .= ') ['.basename($dbg[2]['file']).':'.$dbg[2]['line'].']'; - phpCAS::log($str); - $PHPCAS_DEBUG['indent'] ++; - } - - /** - * This method is used to indicate the end of the execution of a function in debug mode. - * - * @param $res the result of the function - */ - function traceEnd($res='') - { - global $PHPCAS_DEBUG; - - $PHPCAS_DEBUG['indent'] --; - $dbg = phpCAS::backtrace(); - $str = ''; - $str .= '<= '.str_replace("\n","",var_export($res,TRUE)); - phpCAS::log($str); - } - - /** - * This method is used to indicate the end of the execution of the program - */ - function traceExit() - { - global $PHPCAS_DEBUG; - - phpCAS::log('exit()'); - while ( $PHPCAS_DEBUG['indent'] > 0 ) { - phpCAS::log('-'); - $PHPCAS_DEBUG['indent'] --; - } - } - - /** @} */ - // ######################################################################## - // INTERNATIONALIZATION - // ######################################################################## - /** - * @addtogroup publicLang - * @{ - */ - - /** - * This method is used to set the language used by phpCAS. - * @note Can be called only once. - * - * @param $lang a string representing the language. - * - * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH - */ - function setLang($lang) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($lang) != 'string' ) { - phpCAS::error('type mismatched for parameter $lang (should be `string\')'); - } - $PHPCAS_CLIENT->setLang($lang); - } - - /** @} */ - // ######################################################################## - // VERSION - // ######################################################################## - /** - * @addtogroup public - * @{ - */ - - /** - * This method returns the phpCAS version. - * - * @return the phpCAS version. - */ - function getVersion() - { - return PHPCAS_VERSION; - } - - /** @} */ - // ######################################################################## - // HTML OUTPUT - // ######################################################################## - /** - * @addtogroup publicOutput - * @{ - */ - - /** - * This method sets the HTML header used for all outputs. - * - * @param $header the HTML header. - */ - function setHTMLHeader($header) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($header) != 'string' ) { - phpCAS::error('type mismatched for parameter $header (should be `string\')'); - } - $PHPCAS_CLIENT->setHTMLHeader($header); - } - - /** - * This method sets the HTML footer used for all outputs. - * - * @param $footer the HTML footer. - */ - function setHTMLFooter($footer) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( gettype($footer) != 'string' ) { - phpCAS::error('type mismatched for parameter $footer (should be `string\')'); - } - $PHPCAS_CLIENT->setHTMLHeader($header); - } - - /** @} */ - // ######################################################################## - // PGT STORAGE - // ######################################################################## - /** - * @addtogroup publicPGTStorage - * @{ - */ - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests onto the filesystem. - * - * @param $format the format used to store the PGT's (`plain' and `xml' allowed) - * @param $path the path where the PGT's should be stored - */ - function setPGTStorageFile($format='', - $path='') - { - global $PHPCAS_CLIENT,$PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( $PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called before '.$PHPCAS_AUTH_CHECK_CALL['method'].'() (called at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].')'); - } - if ( gettype($format) != 'string' ) { - phpCAS::error('type mismatched for parameter $format (should be `string\')'); - } - if ( gettype($path) != 'string' ) { - phpCAS::error('type mismatched for parameter $format (should be `string\')'); - } - $PHPCAS_CLIENT->setPGTStorageFile($format,$path); - phpCAS::traceEnd(); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests into a database. - * @note The connection to the database is done only when needed. - * As a consequence, bad parameters are detected only when - * initializing PGT storage, except in debug mode. - * - * @param $user the user to access the data with - * @param $password the user's password - * @param $database_type the type of the database hosting the data - * @param $hostname the server hosting the database - * @param $port the port the server is listening on - * @param $database the name of the database - * @param $table the name of the table storing the data - */ - function setPGTStorageDB($user, - $password, - $database_type='', - $hostname='', - $port=0, - $database='', - $table='') - { - global $PHPCAS_CLIENT,$PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( $PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called before '.$PHPCAS_AUTH_CHECK_CALL['method'].'() (called at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].')'); - } - if ( gettype($user) != 'string' ) { - phpCAS::error('type mismatched for parameter $user (should be `string\')'); - } - if ( gettype($password) != 'string' ) { - phpCAS::error('type mismatched for parameter $password (should be `string\')'); - } - if ( gettype($database_type) != 'string' ) { - phpCAS::error('type mismatched for parameter $database_type (should be `string\')'); - } - if ( gettype($hostname) != 'string' ) { - phpCAS::error('type mismatched for parameter $hostname (should be `string\')'); - } - if ( gettype($port) != 'integer' ) { - phpCAS::error('type mismatched for parameter $port (should be `integer\')'); - } - if ( gettype($database) != 'string' ) { - phpCAS::error('type mismatched for parameter $database (should be `string\')'); - } - if ( gettype($table) != 'string' ) { - phpCAS::error('type mismatched for parameter $table (should be `string\')'); - } - $PHPCAS_CLIENT->setPGTStorageDB($this,$user,$password,$hostname,$port,$database,$table); - phpCAS::traceEnd(); - } - - /** @} */ - // ######################################################################## - // ACCESS TO EXTERNAL SERVICES - // ######################################################################## - /** - * @addtogroup publicServices - * @{ - */ - - /** - * This method is used to access an HTTP[S] service. - * - * @param $url the service to access. - * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on - * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. - * @param $output the output of the service (also used to give an error - * message on failure). - * - * @return TRUE on success, FALSE otherwise (in this later case, $err_code - * gives the reason why it failed and $output contains an error message). - */ - function serviceWeb($url,&$err_code,&$output) - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called after the programmer is sure the user has been authenticated (by calling '.__CLASS__.'::checkAuthentication() or '.__CLASS__.'::forceAuthentication()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { - phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - - $res = $PHPCAS_CLIENT->serviceWeb($url,$err_code,$output); - - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method is used to access an IMAP/POP3/NNTP service. - * - * @param $url a string giving the URL of the service, including the mailing box - * for IMAP URLs, as accepted by imap_open(). - * @param $flags options given to imap_open(). - * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on - * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. - * @param $err_msg an error message on failure - * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL - * on success, FALSE on error). - * - * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code - * gives the reason why it failed and $err_msg contains an error message). - */ - function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt) - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called after the programmer is sure the user has been authenticated (by calling '.__CLASS__.'::checkAuthentication() or '.__CLASS__.'::forceAuthentication()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { - phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - - if ( gettype($flags) != 'integer' ) { - phpCAS::error('type mismatched for parameter $flags (should be `integer\')'); - } - - $res = $PHPCAS_CLIENT->serviceMail($url,$flags,$err_code,$err_msg,$pt); - - phpCAS::traceEnd($res); - return $res; - } - - /** @} */ - // ######################################################################## - // AUTHENTICATION - // ######################################################################## - /** - * @addtogroup publicAuth - * @{ - */ - - /** - * This method is called to check if the user is authenticated (use the gateway feature). - * @return TRUE when the user is authenticated; otherwise FALSE. - */ - function checkAuthentication() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - - $auth = $PHPCAS_CLIENT->checkAuthentication(); - - // store where the authentication has been checked and the result - $dbg = phpCAS::backtrace(); - $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__, - 'result' => $auth ); - phpCAS::traceEnd($auth); - return $auth; - } - - /** - * This method is called to force authentication if the user was not already - * authenticated. If the user is not authenticated, halt by redirecting to - * the CAS server. - */ - function forceAuthentication() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - - $auth = $PHPCAS_CLIENT->forceAuthentication(); - - // store where the authentication has been checked and the result - $dbg = phpCAS::backtrace(); - $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__.'::'.__FUNCTION__, - 'result' => $auth ); - - if ( !$auth ) { - phpCAS::trace('user is not authenticated, redirecting to the CAS server'); - $PHPCAS_CLIENT->forceAuthentication(); - } else { - phpCAS::trace('no need to authenticate (user `'.phpCAS::getUser().'\' is already authenticated)'); - } - - phpCAS::traceEnd(); - } - - /** - * This method has been left from version 0.4.1 for compatibility reasons. - */ - function authenticate() - { - phpCAS::error('this method is deprecated. You should use '.__CLASS__.'::forceAuthentication() instead'); - } - - /** - * This method has been left from version 0.4.19 for compatibility reasons. - */ - function isAuthenticated() - { - phpCAS::error('this method is deprecated. You should use '.__CLASS__.'::forceAuthentication() instead'); - } - - /** - * This method returns the CAS user's login name. - * @warning should not be called only after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - * - * @return the login name of the authenticated user - */ - function getUser() - { - global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['done'] ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'); - } - if ( !$PHPCAS_AUTH_CHECK_CALL['result'] ) { - phpCAS::error('authentication was checked (by '.$PHPCAS_AUTH_CHECK_CALL['method'].'() at '.$PHPCAS_AUTH_CHECK_CALL['file'].':'.$PHPCAS_AUTH_CHECK_CALL['line'].') but the method returned FALSE'); - } - return $PHPCAS_CLIENT->getUser(); - } - - /** - * This method returns the URL to be used to login. - * or phpCAS::isAuthenticated(). - * - * @return the login name of the authenticated user - */ - function getServerLoginURL() - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - return $PHPCAS_CLIENT->getServerLoginURL(); - } - - /** - * This method returns the URL to be used to login. - * or phpCAS::isAuthenticated(). - * - * @return the login name of the authenticated user - */ - function getServerLogoutURL() - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should not be called before '.__CLASS__.'::client() or '.__CLASS__.'::proxy()'); - } - return $PHPCAS_CLIENT->getServerLogoutURL(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS server. - * @param $url a URL that will be transmitted to the CAS server (to come back to when logged out) - */ - function logout($url = "") - { - global $PHPCAS_CLIENT; - - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::client() or'.__CLASS__.'::proxy()'); - } - $PHPCAS_CLIENT->logout($url); - // never reached - phpCAS::traceEnd(); - } - - /** - * Set the fixed URL that will be used by the CAS server to transmit the PGT. - * When this method is not called, a phpCAS script uses its own URL for the callback. - * - * @param $url the URL - */ - function setFixedCallbackURL($url='') - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( !$PHPCAS_CLIENT->isProxy() ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - $PHPCAS_CLIENT->setCallbackURL($url); - phpCAS::traceEnd(); - } - - /** - * Set the fixed URL that will be set as the CAS service parameter. When this - * method is not called, a phpCAS script uses its own URL. - * - * @param $url the URL - */ - function setFixedServiceURL($url) - { - global $PHPCAS_CLIENT; - phpCAS::traceBegin(); - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( gettype($url) != 'string' ) { - phpCAS::error('type mismatched for parameter $url (should be `string\')'); - } - $PHPCAS_CLIENT->setURL($url); - phpCAS::traceEnd(); - } - - /** - * Get the URL that is set as the CAS service parameter. - */ - function getServiceURL() - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - return($PHPCAS_CLIENT->getURL()); - } - - /** - * Retrieve a Proxy Ticket from the CAS server. - */ - function retrievePT($target_service,&$err_code,&$err_msg) - { - global $PHPCAS_CLIENT; - if ( !is_object($PHPCAS_CLIENT) ) { - phpCAS::error('this method should only be called after '.__CLASS__.'::proxy()'); - } - if ( gettype($target_service) != 'string' ) { - phpCAS::error('type mismatched for parameter $target_service(should be `string\')'); - } - return($PHPCAS_CLIENT->retrievePT($target_service,$err_code,$err_msg)); - } - /** @} */ - -} - -// ######################################################################## -// DOCUMENTATION -// ######################################################################## - -// ######################################################################## -// MAIN PAGE - -/** - * @mainpage - * - * The following pages only show the source documentation. - * - * For more information on phpCAS, please refer to http://esup-phpcas.sourceforge.net - * - */ - -// ######################################################################## -// MODULES DEFINITION - -/** @defgroup public User interface */ - -/** @defgroup publicInit Initialization - * @ingroup public */ - -/** @defgroup publicAuth Authentication - * @ingroup public */ - -/** @defgroup publicServices Access to external services - * @ingroup public */ - -/** @defgroup publicConfig Configuration - * @ingroup public */ - -/** @defgroup publicLang Internationalization - * @ingroup publicConfig */ - -/** @defgroup publicOutput HTML output - * @ingroup publicConfig */ - -/** @defgroup publicPGTStorage PGT storage - * @ingroup publicConfig */ - -/** @defgroup publicDebug Debugging - * @ingroup public */ - - -/** @defgroup internal Implementation */ - -/** @defgroup internalAuthentication Authentication - * @ingroup internal */ - -/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets) - * @ingroup internal */ - -/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets) - * @ingroup internal */ - -/** @defgroup internalPGTStorage PGT storage - * @ingroup internalProxy */ - -/** @defgroup internalPGTStorageDB PGT storage in a database - * @ingroup internalPGTStorage */ - -/** @defgroup internalPGTStorageFile PGT storage on the filesystem - * @ingroup internalPGTStorage */ - -/** @defgroup internalCallback Callback from the CAS server - * @ingroup internalProxy */ - -/** @defgroup internalProxied CAS proxied client features (CAS 2.0, Proxy Tickets) - * @ingroup internal */ - -/** @defgroup internalConfig Configuration - * @ingroup internal */ - -/** @defgroup internalOutput HTML output - * @ingroup internalConfig */ - -/** @defgroup internalLang Internationalization - * @ingroup internalConfig - * - * To add a new language: - * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php - * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php - * - 3. Make the translations - */ - -/** @defgroup internalDebug Debugging - * @ingroup internal */ - -/** @defgroup internalMisc Miscellaneous - * @ingroup internal */ - -// ######################################################################## -// EXAMPLES - -/** - * @example example_simple.php - */ -/** - * @example example_proxy.php - */ -/** - * @example example_proxy2.php - */ -/** - * @example example_lang.php - */ -/** - * @example example_html.php - */ -/** - * @example example_file.php - */ -/** - * @example example_db.php - */ -/** - * @example example_service.php - */ -/** - * @example example_session_proxy.php - */ -/** - * @example example_session_service.php - */ -/** - * @example example_gateway.php - */ - - - -?> diff --git a/lib/cas/PGTStorage/pgt-db.php b/lib/cas/PGTStorage/pgt-db.php deleted file mode 100644 index 1477570badb..00000000000 --- a/lib/cas/PGTStorage/pgt-db.php +++ /dev/null @@ -1,190 +0,0 @@ - - * - * @ingroup internalPGTStorageDB - */ - -class PGTStorageDB extends PGTStorage -{ - /** - * @addtogroup internalPGTStorageDB - * @{ - */ - - /** - * a string representing a PEAR DB URL to connect to the database. Written by - * PGTStorageDB::PGTStorageDB(), read by getURL(). - * - * @hideinitializer - * @private - */ - var $_url=''; - - /** - * This method returns the PEAR DB URL to use to connect to the database. - * - * @return a PEAR DB URL - * - * @private - */ - function getURL() - { - return $this->_url; - } - - /** - * The handle of the connection to the database where PGT's are stored. Written by - * PGTStorageDB::init(), read by getLink(). - * - * @hideinitializer - * @private - */ - var $_link = null; - - /** - * This method returns the handle of the connection to the database where PGT's are - * stored. - * - * @return a handle of connection. - * - * @private - */ - function getLink() - { - return $this->_link; - } - - /** - * The name of the table where PGT's are stored. Written by - * PGTStorageDB::PGTStorageDB(), read by getTable(). - * - * @hideinitializer - * @private - */ - var $_table = ''; - - /** - * This method returns the name of the table where PGT's are stored. - * - * @return the name of a table. - * - * @private - */ - function getTable() - { - return $this->_table; - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return an informational string. - * @public - */ - function getStorageType() - { - return "database"; - } - - /** - * This method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @public - */ - function getStorageInfo() - { - return 'url=`'.$this->getURL().'\', table=`'.$this->getTable().'\''; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The class constructor, called by CASClient::SetPGTStorageDB(). - * - * @param $cas_parent the CASClient instance that creates the object. - * @param $user the user to access the data with - * @param $password the user's password - * @param $database_type the type of the database hosting the data - * @param $hostname the server hosting the database - * @param $port the port the server is listening on - * @param $database the name of the database - * @param $table the name of the table storing the data - * - * @public - */ - function PGTStorageDB($cas_parent,$user,$password,$database_type,$hostname,$port,$database,$table) - { - phpCAS::traceBegin(); - - // call the ancestor's constructor - $this->PGTStorage($cas_parent); - - if ( empty($database_type) ) $database_type = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE; - if ( empty($hostname) ) $hostname = CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME; - if ( $port==0 ) $port = CAS_PGT_STORAGE_DB_DEFAULT_PORT; - if ( empty($database) ) $database = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE; - if ( empty($table) ) $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE; - - // build and store the PEAR DB URL - $this->_url = $database_type.':'.'//'.$user.':'.$password.'@'.$server.':'.$port.'/'.$database; - - // XXX should use setURL and setTable - phpCAS::traceEnd(); - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * This method is used to initialize the storage. Halts on error. - * - * @public - */ - function init() - { - phpCAS::traceBegin(); - // if the storage has already been initialized, return immediatly - if ( $this->isInitialized() ) - return; - // call the ancestor's method (mark as initialized) - parent::init(); - - // try to connect to the database - $this->_link = DB::connect($this->getURL()); - if ( DB::isError($this->_link) ) { - phpCAS::error('could not connect to database ('.DB::errorMessage($this->_link).')'); - } - var_dump($this->_link); - phpCAS::traceBEnd(); - } - - /** @} */ -} - -?> \ No newline at end of file diff --git a/lib/cas/PGTStorage/pgt-file.php b/lib/cas/PGTStorage/pgt-file.php deleted file mode 100644 index bd0637c33bb..00000000000 --- a/lib/cas/PGTStorage/pgt-file.php +++ /dev/null @@ -1,237 +0,0 @@ - - * - * @ingroup internalPGTStorageFile - */ - -class PGTStorageFile extends PGTStorage -{ - /** - * @addtogroup internalPGTStorageFile - * @{ - */ - - /** - * a string telling where PGT's should be stored on the filesystem. Written by - * PGTStorageFile::PGTStorageFile(), read by getPath(). - * - * @private - */ - var $_path; - - /** - * This method returns the name of the directory where PGT's should be stored - * on the filesystem. - * - * @return the name of a directory (with leading and trailing '/') - * - * @private - */ - function getPath() - { - return $this->_path; - } - - /** - * a string telling the format to use to store PGT's (plain or xml). Written by - * PGTStorageFile::PGTStorageFile(), read by getFormat(). - * - * @private - */ - var $_format; - - /** - * This method returns the format to use when storing PGT's on the filesystem. - * - * @return a string corresponding to the format used (plain or xml). - * - * @private - */ - function getFormat() - { - return $this->_format; - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return an informational string. - * @public - */ - function getStorageType() - { - return "file"; - } - - /** - * This method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @return an informational string. - * @public - */ - function getStorageInfo() - { - return 'path=`'.$this->getPath().'\', format=`'.$this->getFormat().'\''; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The class constructor, called by CASClient::SetPGTStorageFile(). - * - * @param $cas_parent the CASClient instance that creates the object. - * @param $format the format used to store the PGT's (`plain' and `xml' allowed). - * @param $path the path where the PGT's should be stored - * - * @public - */ - function PGTStorageFile($cas_parent,$format,$path) - { - phpCAS::traceBegin(); - // call the ancestor's constructor - $this->PGTStorage($cas_parent); - - if (empty($format) ) $format = CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT; - if (empty($path) ) $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH; - - // check that the path is an absolute path - if ( $path[0] != '/' ) { - phpCAS::error('an absolute path is needed for PGT storage to file'); - } - - // store the path (with a leading and trailing '/') - $path = preg_replace('|[/]*$|','/',$path); - $path = preg_replace('|^[/]*|','/',$path); - $this->_path = $path; - - // check the format and store it - switch ($format) { - case CAS_PGT_STORAGE_FILE_FORMAT_PLAIN: - case CAS_PGT_STORAGE_FILE_FORMAT_XML: - $this->_format = $format; - break; - default: - phpCAS::error('unknown PGT file storage format (`'.CAS_PGT_STORAGE_FILE_FORMAT_PLAIN.'\' and `'.CAS_PGT_STORAGE_FILE_FORMAT_XML.'\' allowed)'); - } - phpCAS::traceEnd(); - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * This method is used to initialize the storage. Halts on error. - * - * @public - */ - function init() - { - phpCAS::traceBegin(); - // if the storage has already been initialized, return immediatly - if ( $this->isInitialized() ) - return; - // call the ancestor's method (mark as initialized) - parent::init(); - phpCAS::traceEnd(); - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This method returns the filename corresponding to a PGT Iou. - * - * @param $pgt_iou the PGT iou. - * - * @return a filename - * @private - */ - function getPGTIouFilename($pgt_iou) - { - phpCAS::traceBegin(); - return $this->getPath().$pgt_iou.'.'.$this->getFormat(); - phpCAS::traceEnd(); - } - - /** - * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a - * warning on error. - * - * @param $pgt the PGT - * @param $pgt_iou the PGT iou - * - * @public - */ - function write($pgt,$pgt_iou) - { - phpCAS::traceBegin(); - $fname = $this->getPGTIouFilename($pgt_iou); - if ( $f=fopen($fname,"w") ) { - if ( fputs($f,$pgt) === FALSE ) { - phpCAS::error('could not write PGT to `'.$fname.'\''); - } - fclose($f); - } else { - phpCAS::error('could not open `'.$fname.'\''); - } - phpCAS::traceEnd(); - } - - /** - * This method reads a PGT corresponding to a PGT Iou and deletes the - * corresponding file. - * - * @param $pgt_iou the PGT iou - * - * @return the corresponding PGT, or FALSE on error - * - * @public - */ - function read($pgt_iou) - { - phpCAS::traceBegin(); - $pgt = FALSE; - $fname = $this->getPGTIouFilename($pgt_iou); - if ( !($f=fopen($fname,"r")) ) { - phpCAS::trace('could not open `'.$fname.'\''); - } else { - if ( ($pgt=fgets($f)) === FALSE ) { - phpCAS::trace('could not read PGT from `'.$fname.'\''); - } - fclose($f); - } - - // delete the PGT file - @unlink($fname); - - phpCAS::traceEnd($pgt); - return $pgt; - } - - /** @} */ - -} - - -?> \ No newline at end of file diff --git a/lib/cas/PGTStorage/pgt-main.php b/lib/cas/PGTStorage/pgt-main.php deleted file mode 100644 index 8fd3c9e12ba..00000000000 --- a/lib/cas/PGTStorage/pgt-main.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * @ingroup internalPGTStorage - */ - -class PGTStorage -{ - /** - * @addtogroup internalPGTStorage - * @{ - */ - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The constructor of the class, should be called only by inherited classes. - * - * @param $cas_parent the CASclient instance that creates the current object. - * - * @protected - */ - function PGTStorage($cas_parent) - { - phpCAS::traceBegin(); - if ( !$cas_parent->isProxy() ) { - phpCAS::error('defining PGT storage makes no sense when not using a CAS proxy'); - } - phpCAS::traceEnd(); - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This virtual method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @public - */ - function getStorageType() - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** - * This virtual method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @public - */ - function getStorageInfo() - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - // ######################################################################## - // ERROR HANDLING - // ######################################################################## - - /** - * string used to store an error message. Written by PGTStorage::setErrorMessage(), - * read by PGTStorage::getErrorMessage(). - * - * @hideinitializer - * @private - * @deprecated not used. - */ - var $_error_message=FALSE; - - /** - * This method sets en error message, which can be read later by - * PGTStorage::getErrorMessage(). - * - * @param $error_message an error message - * - * @protected - * @deprecated not used. - */ - function setErrorMessage($error_message) - { - $this->_error_message = $error_message; - } - - /** - * This method returns an error message set by PGTStorage::setErrorMessage(). - * - * @return an error message when set by PGTStorage::setErrorMessage(), FALSE - * otherwise. - * - * @public - * @deprecated not used. - */ - function getErrorMessage() - { - return $this->_error_message; - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * a boolean telling if the storage has already been initialized. Written by - * PGTStorage::init(), read by PGTStorage::isInitialized(). - * - * @hideinitializer - * @private - */ - var $_initialized = FALSE; - - /** - * This method tells if the storage has already been intialized. - * - * @return a boolean - * - * @protected - */ - function isInitialized() - { - return $this->_initialized; - } - - /** - * This virtual method initializes the object. - * - * @protected - */ - function init() - { - $this->_initialized = TRUE; - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This virtual method stores a PGT and its corresponding PGT Iuo. - * @note Should never be called. - * - * @param $pgt the PGT - * @param $pgt_iou the PGT iou - * - * @protected - */ - function write($pgt,$pgt_iou) - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** - * This virtual method reads a PGT corresponding to a PGT Iou and deletes - * the corresponding storage entry. - * @note Should never be called. - * - * @param $pgt_iou the PGT iou - * - * @protected - */ - function read($pgt_iou) - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** @} */ - -} - -// include specific PGT storage classes -include_once(dirname(__FILE__).'/pgt-file.php'); -include_once(dirname(__FILE__).'/pgt-db.php'); - -?> \ No newline at end of file diff --git a/lib/cas/client.php b/lib/cas/client.php deleted file mode 100644 index 7b878642418..00000000000 --- a/lib/cas/client.php +++ /dev/null @@ -1,1950 +0,0 @@ - - */ - -class CASClient -{ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX CONFIGURATION XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // HTML OUTPUT - // ######################################################################## - /** - * @addtogroup internalOutput - * @{ - */ - - /** - * This method filters a string by replacing special tokens by appropriate values - * and prints it. The corresponding tokens are taken into account: - * - __CAS_VERSION__ - * - __PHPCAS_VERSION__ - * - __SERVER_BASE_URL__ - * - * Used by CASClient::PrintHTMLHeader() and CASClient::printHTMLFooter(). - * - * @param $str the string to filter and output - * - * @private - */ - function HTMLFilterOutput($str) - { - $str = str_replace('__CAS_VERSION__',$this->getServerVersion(),$str); - $str = str_replace('__PHPCAS_VERSION__',phpCAS::getVersion(),$str); - $str = str_replace('__SERVER_BASE_URL__',$this->getServerBaseURL(),$str); - echo $str; - } - - /** - * A string used to print the header of HTML pages. Written by CASClient::setHTMLHeader(), - * read by CASClient::printHTMLHeader(). - * - * @hideinitializer - * @private - * @see CASClient::setHTMLHeader, CASClient::printHTMLHeader() - */ - var $_output_header = ''; - - /** - * This method prints the header of the HTML output (after filtering). If - * CASClient::setHTMLHeader() was not used, a default header is output. - * - * @param $title the title of the page - * - * @see HTMLFilterOutput() - * @private - */ - function printHTMLHeader($title) - { - $this->HTMLFilterOutput(str_replace('__TITLE__', - $title, - (empty($this->_output_header) - ? '__TITLE__

__TITLE__

' - : $this->output_header) - ) - ); - } - - /** - * A string used to print the footer of HTML pages. Written by CASClient::setHTMLFooter(), - * read by printHTMLFooter(). - * - * @hideinitializer - * @private - * @see CASClient::setHTMLFooter, CASClient::printHTMLFooter() - */ - var $_output_footer = ''; - - /** - * This method prints the footer of the HTML output (after filtering). If - * CASClient::setHTMLFooter() was not used, a default footer is output. - * - * @see HTMLFilterOutput() - * @private - */ - function printHTMLFooter() - { - $this->HTMLFilterOutput(empty($this->_output_footer) - ?('
phpCAS __PHPCAS_VERSION__ '.$this->getString(CAS_STR_USING_SERVER).' __SERVER_BASE_URL__ (CAS __CAS_VERSION__)
') - :$this->_output_footer); - } - - /** - * This method set the HTML header used for all outputs. - * - * @param $header the HTML header. - * - * @public - */ - function setHTMLHeader($header) - { - $this->_output_header = $header; - } - - /** - * This method set the HTML footer used for all outputs. - * - * @param $footer the HTML footer. - * - * @public - */ - function setHTMLFooter($footer) - { - $this->_output_footer = $footer; - } - - /** @} */ - // ######################################################################## - // INTERNATIONALIZATION - // ######################################################################## - /** - * @addtogroup internalLang - * @{ - */ - /** - * A string corresponding to the language used by phpCAS. Written by - * CASClient::setLang(), read by CASClient::getLang(). - - * @note debugging information is always in english (debug purposes only). - * - * @hideinitializer - * @private - * @sa CASClient::_strings, CASClient::getString() - */ - var $_lang = ''; - - /** - * This method returns the language used by phpCAS. - * - * @return a string representing the language - * - * @private - */ - function getLang() - { - if ( empty($this->_lang) ) - $this->setLang(PHPCAS_LANG_DEFAULT); - return $this->_lang; - } - - /** - * array containing the strings used by phpCAS. Written by CASClient::setLang(), read by - * CASClient::getString() and used by CASClient::setLang(). - * - * @note This array is filled by instructions in CAS/languages/<$this->_lang>.php - * - * @private - * @see CASClient::_lang, CASClient::getString(), CASClient::setLang(), CASClient::getLang() - */ - var $_strings; - - /** - * This method returns a string depending on the language. - * - * @param $str the index of the string in $_string. - * - * @return the string corresponding to $index in $string. - * - * @private - */ - function getString($str) - { - // call CASclient::getLang() to be sure the language is initialized - $this->getLang(); - - if ( !isset($this->_strings[$str]) ) { - trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR); - } - return $this->_strings[$str]; - } - - /** - * This method is used to set the language used by phpCAS. - * @note Can be called only once. - * - * @param $lang a string representing the language. - * - * @public - * @sa CAS_LANG_FRENCH, CAS_LANG_ENGLISH - */ - function setLang($lang) - { - // include the corresponding language file - include_once(dirname(__FILE__).'/languages/'.$lang.'.php'); - - if ( !is_array($this->_strings) ) { - trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR); - } - $this->_lang = $lang; - } - - /** @} */ - // ######################################################################## - // CAS SERVER CONFIG - // ######################################################################## - /** - * @addtogroup internalConfig - * @{ - */ - - /** - * a record to store information about the CAS server. - * - $_server["version"]: the version of the CAS server - * - $_server["hostname"]: the hostname of the CAS server - * - $_server["port"]: the port the CAS server is running on - * - $_server["uri"]: the base URI the CAS server is responding on - * - $_server["base_url"]: the base URL of the CAS server - * - $_server["login_url"]: the login URL of the CAS server - * - $_server["service_validate_url"]: the service validating URL of the CAS server - * - $_server["proxy_url"]: the proxy URL of the CAS server - * - $_server["proxy_validate_url"]: the proxy validating URL of the CAS server - * - $_server["logout_url"]: the logout URL of the CAS server - * - * $_server["version"], $_server["hostname"], $_server["port"] and $_server["uri"] - * are written by CASClient::CASClient(), read by CASClient::getServerVersion(), - * CASClient::getServerHostname(), CASClient::getServerPort() and CASClient::getServerURI(). - * - * The other fields are written and read by CASClient::getServerBaseURL(), - * CASClient::getServerLoginURL(), CASClient::getServerServiceValidateURL(), - * CASClient::getServerProxyValidateURL() and CASClient::getServerLogoutURL(). - * - * @hideinitializer - * @private - */ - var $_server = array( - 'version' => -1, - 'hostname' => 'none', - 'port' => -1, - 'uri' => 'none' - ); - - /** - * This method is used to retrieve the version of the CAS server. - * @return the version of the CAS server. - * @private - */ - function getServerVersion() - { - return $this->_server['version']; - } - - /** - * This method is used to retrieve the hostname of the CAS server. - * @return the hostname of the CAS server. - * @private - */ - function getServerHostname() - { return $this->_server['hostname']; } - - /** - * This method is used to retrieve the port of the CAS server. - * @return the port of the CAS server. - * @private - */ - function getServerPort() - { return $this->_server['port']; } - - /** - * This method is used to retrieve the URI of the CAS server. - * @return a URI. - * @private - */ - function getServerURI() - { return $this->_server['uri']; } - - /** - * This method is used to retrieve the base URL of the CAS server. - * @return a URL. - * @private - */ - function getServerBaseURL() - { - // the URL is build only when needed - if ( empty($this->_server['base_url']) ) { - $this->_server['base_url'] = 'https://' - .$this->getServerHostname() - .':' - .$this->getServerPort() - .$this->getServerURI(); - } - return $this->_server['base_url']; - } - - /** - * This method is used to retrieve the login URL of the CAS server. - * @param $gateway true to check authentication, false to force it - * @return a URL. - * @private - */ - function getServerLoginURL($gateway) - { - phpCAS::traceBegin(); - // the URL is build only when needed - if ( empty($this->_server['login_url']) ) { - $this->_server['login_url'] = $this->getServerBaseURL(); - $this->_server['login_url'] .= 'login?service='; - $this->_server['login_url'] .= preg_replace('/&/','%26',$this->getURL()); - if ($gateway) { - $this->_server['login_url'] .= '&gateway=true'; - } - } - phpCAS::traceEnd($this->_server['login_url']); - return $this->_server['login_url']; - } - - /** - * This method is used to retrieve the service validating URL of the CAS server. - * @return a URL. - * @private - */ - function getServerServiceValidateURL() - { - // the URL is build only when needed - if ( empty($this->_server['service_validate_url']) ) { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - $this->_server['service_validate_url'] = $this->getServerBaseURL().'validate'; - break; - case CAS_VERSION_2_0: - $this->_server['service_validate_url'] = $this->getServerBaseURL().'serviceValidate'; - break; - } - } - return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); - } - - /** - * This method is used to retrieve the proxy validating URL of the CAS server. - * @return a URL. - * @private - */ - function getServerProxyValidateURL() - { - // the URL is build only when needed - if ( empty($this->_server['proxy_validate_url']) ) { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - $this->_server['proxy_validate_url'] = ''; - break; - case CAS_VERSION_2_0: - $this->_server['proxy_validate_url'] = $this->getServerBaseURL().'proxyValidate'; - break; - } - } - return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); - } - - /** - * This method is used to retrieve the proxy URL of the CAS server. - * @return a URL. - * @private - */ - function getServerProxyURL() - { - // the URL is build only when needed - if ( empty($this->_server['proxy_url']) ) { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - $this->_server['proxy_url'] = ''; - break; - case CAS_VERSION_2_0: - $this->_server['proxy_url'] = $this->getServerBaseURL().'proxy'; - break; - } - } - return $this->_server['proxy_url']; - } - - /** - * This method is used to retrieve the logout URL of the CAS server. - * @return a URL. - * @private - */ - function getServerLogoutURL() - { - // the URL is build only when needed - if ( empty($this->_server['logout_url']) ) { - $this->_server['logout_url'] = $this->getServerBaseURL().'logout'; - } - return $this->_server['logout_url']; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - /** - * CASClient constructor. - * - * @param $server_version the version of the CAS server - * @param $proxy TRUE if the CAS client is a CAS proxy, FALSE otherwise - * @param $server_hostname the hostname of the CAS server - * @param $server_port the port the CAS server is running on - * @param $server_uri the URI the CAS server is responding on - * @param $start_session Have phpCAS start PHP sessions (default true) - * - * @return a newly created CASClient object - * - * @public - */ - function CASClient($server_version, - $proxy, - $server_hostname, - $server_port, - $server_uri, - $start_session = true) - { - phpCAS::traceBegin(); - - // activate session mechanism if desired - if ($start_session) { - session_start(); - } - - $this->_proxy = $proxy; - - // check version - switch ($server_version) { - case CAS_VERSION_1_0: - if ( $this->isProxy() ) - phpCAS::error('CAS proxies are not supported in CAS ' - .$server_version); - break; - case CAS_VERSION_2_0: - break; - default: - phpCAS::error('this version of CAS (`' - .$server_version - .'\') is not supported by phpCAS ' - .phpCAS::getVersion()); - } - $this->_server['version'] = $server_version; - - // check hostname - if ( empty($server_hostname) - || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) { - phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')'); - } - $this->_server['hostname'] = $server_hostname; - - // check port - if ( $server_port == 0 - || !is_int($server_port) ) { - phpCAS::error('bad CAS server port (`'.$server_hostname.'\')'); - } - $this->_server['port'] = $server_port; - - // check URI - if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) { - phpCAS::error('bad CAS server URI (`'.$server_uri.'\')'); - } - // add leading and trailing `/' and remove doubles - $server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/'); - $this->_server['uri'] = $server_uri; - - // set to callback mode if PgtIou and PgtId CGI GET parameters are provided - if ( $this->isProxy() ) { - $this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId'])); - } - - if ( $this->isCallbackMode() ) { - // callback mode: check that phpCAS is secured - if ( $_SERVER['HTTPS'] != 'on' ) { - phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server'); - } - } else { - // normal mode: get ticket and remove it from CGI parameters for developpers - $ticket = $_GET['ticket']; - // at first check for a Service Ticket - if( preg_match('/^ST-/',$ticket)) { - phpCAS::trace('ST \''.$ticket.'\' found'); - // ST present - $this->setST($ticket); - } - // in a second time check for a Proxy Ticket (CAS >= 2.0) - else if( ($this->getServerVersion()!=CAS_VERSION_1_0) && preg_match('/^PT-/',$ticket) ) { - phpCAS::trace('PT \''.$ticket.'\' found'); - $this->setPT($ticket); - } - // ill-formed ticket, halt - else if ( !empty($ticket) ) { - phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')'); - } - // ticket has been taken into account, unset it to hide it to applications - unset($_GET['ticket']); - } - phpCAS::traceEnd(); - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX AUTHENTICATION XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - /** - * @addtogroup internalAuthentication - * @{ - */ - - /** - * The Authenticated user. Written by CASClient::setUser(), read by CASClient::getUser(). - * @attention client applications should use phpCAS::getUser(). - * - * @hideinitializer - * @private - */ - var $_user = ''; - - /** - * This method sets the CAS user's login name. - * - * @param $user the login name of the authenticated user. - * - * @private - */ - function setUser($user) - { - $this->_user = $user; - } - - /** - * This method returns the CAS user's login name. - * @warning should be called only after CASClient::forceAuthentication() or - * CASClient::isAuthenticated(), otherwise halt with an error. - * - * @return the login name of the authenticated user - */ - function getUser() - { - if ( empty($this->_user) ) { - phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'); - } - return $this->_user; - } - - /** - * This method is called to be sure that the user is authenticated. When not - * authenticated, halt by redirecting to the CAS server; otherwise return TRUE. - * @return TRUE when the user is authenticated; otherwise halt. - * @public - */ - function forceAuthentication() - { - phpCAS::traceBegin(); - - if ( $this->isAuthenticated() ) { - // the user is authenticated, nothing to be done. - phpCAS::trace('no need to authenticate'); - $res = TRUE; - } else { - // the user is not authenticated, redirect to the CAS server - unset($_SESSION['phpCAS']['auth_checked']); - $this->redirectToCas(FALSE/* no gateway */); - // never reached - $res = FALSE; - } - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method is called to check whether the ser is authenticated or not. - * @return TRUE when the user is authenticated, FALSE otherwise. - * @public - */ - function checkAuthentication() - { - phpCAS::traceBegin(); - - if ( $this->isAuthenticated() ) { - phpCAS::trace('user is authenticated'); - $res = TRUE; - } else if (isset($_SESSION['phpCAS']['auth_checked'])) { - // the previous request has redirected the client to the CAS server with gateway=true - unset($_SESSION['phpCAS']['auth_checked']); - $res = FALSE; - } else { - $_SESSION['phpCAS']['auth_checked'] = true; - $this->redirectToCas(TRUE/* gateway */); - // never reached - $res = FALSE; - } - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method is called to check if the user is authenticated (previously or by - * tickets given in the URL - * - * @return TRUE when the user is authenticated; otherwise halt. - * - * @public - */ - function isAuthenticated() - { - phpCAS::traceBegin(); - $res = FALSE; - $validate_url = ''; - - if ( $this->wasPreviouslyAuthenticated() ) { - // the user has already (previously during the session) been - // authenticated, nothing to be done. - phpCAS::trace('user was already authenticated, no need to look for tickets'); - $res = TRUE; - } elseif ( $this->hasST() ) { - // if a Service Ticket was given, validate it - phpCAS::trace('ST `'.$this->getST().'\' is present'); - $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts - phpCAS::trace('ST `'.$this->getST().'\' was validated'); - if ( $this->isProxy() ) { - $this->validatePGT($validate_url,$text_response,$tree_response); // idem - phpCAS::trace('PGT `'.$this->getPGT().'\' was validated'); - $_SESSION['phpCAS']['pgt'] = $this->getPGT(); - } - $_SESSION['phpCAS']['user'] = $this->getUser(); - $res = TRUE; - } elseif ( $this->hasPT() ) { - // if a Proxy Ticket was given, validate it - phpCAS::trace('PT `'.$this->getPT().'\' is present'); - $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts - phpCAS::trace('PT `'.$this->getPT().'\' was validated'); - if ( $this->isProxy() ) { - $this->validatePGT($validate_url,$text_response,$tree_response); // idem - phpCAS::trace('PGT `'.$this->getPGT().'\' was validated'); - $_SESSION['phpCAS']['pgt'] = $this->getPGT(); - } - $_SESSION['phpCAS']['user'] = $this->getUser(); - $res = TRUE; - } else { - // no ticket given, not authenticated - phpCAS::trace('no ticket found'); - } - - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method tells if the user has already been (previously) authenticated - * by looking into the session variables. - * - * @note This function switches to callback mode when needed. - * - * @return TRUE when the user has already been authenticated; FALSE otherwise. - * - * @private - */ - function wasPreviouslyAuthenticated() - { - phpCAS::traceBegin(); - - if ( $this->isCallbackMode() ) { - $this->callback(); - } - - $auth = FALSE; - - if ( $this->isProxy() ) { - // CAS proxy: username and PGT must be present - if ( !empty($_SESSION['phpCAS']['user']) && !empty($_SESSION['phpCAS']['pgt']) ) { - // authentication already done - $this->setUser($_SESSION['phpCAS']['user']); - $this->setPGT($_SESSION['phpCAS']['pgt']); - phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\''); - $auth = TRUE; - } elseif ( !empty($_SESSION['phpCAS']['user']) && empty($_SESSION['phpCAS']['pgt']) ) { - // these two variables should be empty or not empty at the same time - phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty'); - // unset all tickets to enforce authentication - unset($_SESSION['phpCAS']); - $this->setST(''); - $this->setPT(''); - } elseif ( empty($_SESSION['phpCAS']['user']) && !empty($_SESSION['phpCAS']['pgt']) ) { - // these two variables should be empty or not empty at the same time - phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty'); - // unset all tickets to enforce authentication - unset($_SESSION['phpCAS']); - $this->setST(''); - $this->setPT(''); - } else { - phpCAS::trace('neither user not PGT found'); - } - } else { - // `simple' CAS client (not a proxy): username must be present - if ( !empty($_SESSION['phpCAS']['user']) ) { - // authentication already done - $this->setUser($_SESSION['phpCAS']['user']); - phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\''); - $auth = TRUE; - } else { - phpCAS::trace('no user found'); - } - } - - phpCAS::traceEnd($auth); - return $auth; - } - - /** - * This method is used to redirect the client to the CAS server. - * It is used by CASClient::forceAuthentication() and CASClient::checkAuthentication(). - * @param $gateway true to check authentication, false to force it - * @public - */ - function redirectToCas($gateway) - { - phpCAS::traceBegin(); - $cas_url = $this->getServerLoginURL($gateway); - header('Location: '.$cas_url); - $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED)); - printf('

'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'

',$cas_url); - $this->printHTMLFooter(); - phpCAS::traceExit(); - exit(); - } - - /** - * This method is used to logout from CAS. - * @param $url a URL that will be transmitted to the CAS server (to come back to when logged out) - * @public - */ - function logout($url = "") - { - phpCAS::traceBegin(); - $cas_url = $this->getServerLogoutURL(); - // v0.4.14 sebastien.gougeon at univ-rennes1.fr - // header('Location: '.$cas_url); - if ( $url != "" ) { - $url = '?service=' . $url; - } - header('Location: '.$cas_url . $url); - session_unset(); - session_destroy(); - $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT)); - printf('

'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'

',$cas_url); - $this->printHTMLFooter(); - phpCAS::traceExit(); - exit(); - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX BASIC CLIENT FEATURES (CAS 1.0) XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // ST - // ######################################################################## - /** - * @addtogroup internalBasic - * @{ - */ - - /** - * the Service Ticket provided in the URL of the request if present - * (empty otherwise). Written by CASClient::CASClient(), read by - * CASClient::getST() and CASClient::hasPGT(). - * - * @hideinitializer - * @private - */ - var $_st = ''; - - /** - * This method returns the Service Ticket provided in the URL of the request. - * @return The service ticket. - * @private - */ - function getST() - { return $this->_st; } - - /** - * This method stores the Service Ticket. - * @param $st The Service Ticket. - * @private - */ - function setST($st) - { $this->_st = $st; } - - /** - * This method tells if a Service Ticket was stored. - * @return TRUE if a Service Ticket has been stored. - * @private - */ - function hasST() - { return !empty($this->_st); } - - /** @} */ - - // ######################################################################## - // ST VALIDATION - // ######################################################################## - /** - * @addtogroup internalBasic - * @{ - */ - - /** - * This method is used to validate a ST; halt on failure, and sets $validate_url, - * $text_reponse and $tree_response on success. These parameters are used later - * by CASClient::validatePGT() for CAS proxies. - * - * @param $validate_url the URL of the request to the CAS server. - * @param $text_response the response of the CAS server, as is (XML text). - * @param $tree_response the response of the CAS server, as a DOM XML tree. - * - * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError(). - * - * @private - */ - function validateST($validate_url,&$text_response,&$tree_response) - { - phpCAS::traceBegin(); - // build the URL to validate the ticket - $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST(); - if ( $this->isProxy() ) { - // pass the callback url for CAS proxies - $validate_url .= '&pgtUrl='.$this->getCallbackURL(); - } - - // open and read the URL - if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) { - phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'); - $this->authError('ST not validated', - $validate_url, - TRUE/*$no_response*/); - } - - // analyze the result depending on the version - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - if (preg_match('/^no\n/',$text_response)) { - phpCAS::trace('ST has not been validated'); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - FALSE/*$bad_response*/, - $text_response); - } - if (!preg_match('/^yes\n/',$text_response)) { - phpCAS::trace('ill-formed response'); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - // ST has been validated, extract the user name - $arr = preg_split('/\n/',$text_response); - $this->setUser(trim($arr[1])); - break; - case CAS_VERSION_2_0: - // read the response of the CAS server into a DOM object - if ( !($dom = domxml_open_mem($text_response))) { - phpCAS::trace('domxml_open_mem() failed'); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - // read the root node of the XML tree - if ( !($tree_response = $dom->document_element()) ) { - phpCAS::trace('document_element() failed'); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - // insure that tag name is 'serviceResponse' - if ( $tree_response->node_name() != 'serviceResponse' ) { - phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\''); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) { - // authentication succeded, extract the user name - if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) { - phpCAS::trace(' found, but no '); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - $user = trim($user_elements[0]->get_content()); - phpCAS::trace('user = `'.$user); - $this->setUser($user); - - } else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) { - phpCAS::trace(' found'); - // authentication failed, extract the error code and message - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - FALSE/*$bad_response*/, - $text_response, - $failure_elements[0]->get_attribute('code')/*$err_code*/, - trim($failure_elements[0]->get_content())/*$err_msg*/); - } else { - phpCAS::trace('neither nor found'); - $this->authError('ST not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - break; - } - - // at this step, ST has been validated and $this->_user has been set, - phpCAS::traceEnd(TRUE); - return TRUE; - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX PROXY FEATURES (CAS 2.0) XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // PROXYING - // ######################################################################## - /** - * @addtogroup internalProxy - * @{ - */ - - /** - * A boolean telling if the client is a CAS proxy or not. Written by CASClient::CASClient(), - * read by CASClient::isProxy(). - * - * @private - */ - var $_proxy; - - /** - * Tells if a CAS client is a CAS proxy or not - * - * @return TRUE when the CAS client is a CAs proxy, FALSE otherwise - * - * @private - */ - function isProxy() - { - return $this->_proxy; - } - - /** @} */ - // ######################################################################## - // PGT - // ######################################################################## - /** - * @addtogroup internalProxy - * @{ - */ - - /** - * the Proxy Grnting Ticket given by the CAS server (empty otherwise). - * Written by CASClient::setPGT(), read by CASClient::getPGT() and CASClient::hasPGT(). - * - * @hideinitializer - * @private - */ - var $_pgt = ''; - - /** - * This method returns the Proxy Granting Ticket given by the CAS server. - * @return The Proxy Granting Ticket. - * @private - */ - function getPGT() - { return $this->_pgt; } - - /** - * This method stores the Proxy Granting Ticket. - * @param $pgt The Proxy Granting Ticket. - * @private - */ - function setPGT($pgt) - { $this->_pgt = $pgt; } - - /** - * This method tells if a Proxy Granting Ticket was stored. - * @return TRUE if a Proxy Granting Ticket has been stored. - * @private - */ - function hasPGT() - { return !empty($this->_pgt); } - - /** @} */ - - // ######################################################################## - // CALLBACK MODE - // ######################################################################## - /** - * @addtogroup internalCallback - * @{ - */ - /** - * each PHP script using phpCAS in proxy mode is its own callback to get the - * PGT back from the CAS server. callback_mode is detected by the constructor - * thanks to the GET parameters. - */ - - /** - * a boolean to know if the CAS client is running in callback mode. Written by - * CASClient::setCallBackMode(), read by CASClient::isCallbackMode(). - * - * @hideinitializer - * @private - */ - var $_callback_mode = FALSE; - - /** - * This method sets/unsets callback mode. - * - * @param $callback_mode TRUE to set callback mode, FALSE otherwise. - * - * @private - */ - function setCallbackMode($callback_mode) - { - $this->_callback_mode = $callback_mode; - } - - /** - * This method returns TRUE when the CAs client is running i callback mode, - * FALSE otherwise. - * - * @return A boolean. - * - * @private - */ - function isCallbackMode() - { - return $this->_callback_mode; - } - - /** - * the URL that should be used for the PGT callback (in fact the URL of the - * current request without any CGI parameter). Written and read by - * CASClient::getCallbackURL(). - * - * @hideinitializer - * @private - */ - var $_callback_url = ''; - - /** - * This method returns the URL that should be used for the PGT callback (in - * fact the URL of the current request without any CGI parameter, except if - * phpCAS::setFixedCallbackURL() was used). - * - * @return The callback URL - * - * @private - */ - function getCallbackURL() - { - // the URL is built when needed only - if ( empty($this->_callback_url) ) { - $final_uri = ''; - // remove the ticket if present in the URL - $final_uri = 'https://'; - /* replaced by Julien Marchal - v0.4.6 - * $this->uri .= $_SERVER['SERVER_NAME']; - */ - if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){ - /* replaced by teedog - v0.4.12 - * $final_uri .= $_SERVER['SERVER_NAME']; - */ - if (empty($_SERVER['SERVER_NAME'])) { - $final_uri .= $_SERVER['HTTP_HOST']; - } else { - $final_uri .= $_SERVER['SERVER_NAME']; - } - } else { - $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER']; - } - if ( ($_SERVER['HTTPS']=='on' && $_SERVER['SERVER_PORT']!=443) - || ($_SERVER['HTTPS']!='on' && $_SERVER['SERVER_PORT']!=80) ) { - $final_uri .= ':'; - $final_uri .= $_SERVER['SERVER_PORT']; - } - $request_uri = $_SERVER['REQUEST_URI']; - $request_uri = preg_replace('/\?.*$/','',$request_uri); - $final_uri .= $request_uri; - $this->setCallbackURL($final_uri); - } - return $this->_callback_url; - } - - /** - * This method sets the callback url. - * - * @param $callback_url url to set callback - * - * @private - */ - function setCallbackURL($url) - { - return $this->_callback_url = $url; - } - - /** - * This method is called by CASClient::CASClient() when running in callback - * mode. It stores the PGT and its PGT Iou, prints its output and halts. - * - * @private - */ - function callback() - { - phpCAS::traceBegin(); - $this->printHTMLHeader('phpCAS callback'); - $pgt_iou = $_GET['pgtIou']; - $pgt = $_GET['pgtId']; - phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')'); - echo '

Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').

'; - $this->storePGT($pgt,$pgt_iou); - $this->printHTMLFooter(); - phpCAS::traceExit(); - } - - /** @} */ - - // ######################################################################## - // PGT STORAGE - // ######################################################################## - /** - * @addtogroup internalPGTStorage - * @{ - */ - - /** - * an instance of a class inheriting of PGTStorage, used to deal with PGT - * storage. Created by CASClient::setPGTStorageFile() or CASClient::setPGTStorageDB(), used - * by CASClient::setPGTStorageFile(), CASClient::setPGTStorageDB() and CASClient::initPGTStorage(). - * - * @hideinitializer - * @private - */ - var $_pgt_storage = null; - - /** - * This method is used to initialize the storage of PGT's. - * Halts on error. - * - * @private - */ - function initPGTStorage() - { - // if no SetPGTStorageXxx() has been used, default to file - if ( !is_object($this->_pgt_storage) ) { - $this->setPGTStorageFile(); - } - - // initializes the storage - $this->_pgt_storage->init(); - } - - /** - * This method stores a PGT. Halts on error. - * - * @param $pgt the PGT to store - * @param $pgt_iou its corresponding Iou - * - * @private - */ - function storePGT($pgt,$pgt_iou) - { - // ensure that storage is initialized - $this->initPGTStorage(); - // writes the PGT - $this->_pgt_storage->write($pgt,$pgt_iou); - } - - /** - * This method reads a PGT from its Iou and deletes the corresponding storage entry. - * - * @param $pgt_iou the PGT Iou - * - * @return The PGT corresponding to the Iou, FALSE when not found. - * - * @private - */ - function loadPGT($pgt_iou) - { - // ensure that storage is initialized - $this->initPGTStorage(); - // read the PGT - return $this->_pgt_storage->read($pgt_iou); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests onto the filesystem. - * - * @param $format the format used to store the PGT's (`plain' and `xml' allowed) - * @param $path the path where the PGT's should be stored - * - * @public - */ - function setPGTStorageFile($format='', - $path='') - { - // check that the storage has not already been set - if ( is_object($this->_pgt_storage) ) { - phpCAS::error('PGT storage already defined'); - } - - // create the storage object - $this->_pgt_storage = &new PGTStorageFile($this,$format,$path); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests into a database. - * @note The connection to the database is done only when needed. - * As a consequence, bad parameters are detected only when - * initializing PGT storage. - * - * @param $user the user to access the data with - * @param $password the user's password - * @param $database_type the type of the database hosting the data - * @param $hostname the server hosting the database - * @param $port the port the server is listening on - * @param $database the name of the database - * @param $table the name of the table storing the data - * - * @public - */ - function setPGTStorageDB($user, - $password, - $database_type, - $hostname, - $port, - $database, - $table) - { - // check that the storage has not already been set - if ( is_object($this->_pgt_storage) ) { - phpCAS::error('PGT storage already defined'); - } - - // warn the user that he should use file storage... - trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING); - - // create the storage object - $this->_pgt_storage = & new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table); - } - - // ######################################################################## - // PGT VALIDATION - // ######################################################################## - /** - * This method is used to validate a PGT; halt on failure. - * - * @param $validate_url the URL of the request to the CAS server. - * @param $text_response the response of the CAS server, as is (XML text); result - * of CASClient::validateST() or CASClient::validatePT(). - * @param $tree_response the response of the CAS server, as a DOM XML tree; result - * of CASClient::validateST() or CASClient::validatePT(). - * - * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError(). - * - * @private - */ - function validatePGT(&$validate_url,$text_response,$tree_response) - { - phpCAS::traceBegin(); - if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) { - phpCAS::trace(' not found'); - // authentication succeded, but no PGT Iou was transmitted - $this->authError('Ticket validated but no PGT Iou transmitted', - $validate_url, - FALSE/*$no_response*/, - FALSE/*$bad_response*/, - $text_response); - } else { - // PGT Iou transmitted, extract it - $pgt_iou = trim($arr[0]->get_content()); - $pgt = $this->loadPGT($pgt_iou); - if ( $pgt == FALSE ) { - phpCAS::trace('could not load PGT'); - $this->authError('PGT Iou was transmitted but PGT could not be retrieved', - $validate_url, - FALSE/*$no_response*/, - FALSE/*$bad_response*/, - $text_response); - } - $this->setPGT($pgt); - } - phpCAS::traceEnd(TRUE); - return TRUE; - } - - // ######################################################################## - // PGT VALIDATION - // ######################################################################## - - /** - * This method is used to retrieve PT's from the CAS server thanks to a PGT. - * - * @param $target_service the service to ask for with the PT. - * @param $err_code an error code (PHPCAS_SERVICE_OK on success). - * @param $err_msg an error message (empty on success). - * - * @return a Proxy Ticket, or FALSE on error. - * - * @private - */ - function retrievePT($target_service,&$err_code,&$err_msg) - { - phpCAS::traceBegin(); - - // by default, $err_msg is set empty and $pt to TRUE. On error, $pt is - // set to false and $err_msg to an error message. At the end, if $pt is FALSE - // and $error_msg is still empty, it is set to 'invalid response' (the most - // commonly encountered error). - $err_msg = ''; - - // build the URL to retrieve the PT - $cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT(); - - // open and read the URL - if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) { - phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')'); - $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE; - $err_msg = 'could not retrieve PT (no response from the CAS server)'; - phpCAS::traceEnd(FALSE); - return FALSE; - } - - $bad_response = FALSE; - - if ( !$bad_response ) { - // read the response of the CAS server into a DOM object - if ( !($dom = @domxml_open_mem($cas_response))) { - phpCAS::trace('domxml_open_mem() failed'); - // read failed - $bad_response = TRUE; - } - } - - if ( !$bad_response ) { - // read the root node of the XML tree - if ( !($root = $dom->document_element()) ) { - phpCAS::trace('document_element() failed'); - // read failed - $bad_response = TRUE; - } - } - - if ( !$bad_response ) { - // insure that tag name is 'serviceResponse' - if ( $root->node_name() != 'serviceResponse' ) { - phpCAS::trace('node_name() failed'); - // bad root node - $bad_response = TRUE; - } - } - - if ( !$bad_response ) { - // look for a proxySuccess tag - if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) { - // authentication succeded, look for a proxyTicket tag - if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) { - $err_code = PHPCAS_SERVICE_OK; - $err_msg = ''; - $pt = trim($arr[0]->get_content()); - phpCAS::traceEnd($pt); - return $pt; - } else { - phpCAS::trace(' was found, but not '); - } - } - // look for a proxyFailure tag - else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) { - // authentication failed, extract the error - $err_code = PHPCAS_SERVICE_PT_FAILURE; - $err_msg = 'PT retrieving failed (code=`' - .$arr[0]->get_attribute('code') - .'\', message=`' - .trim($arr[0]->get_content()) - .'\')'; - phpCAS::traceEnd(FALSE); - return FALSE; - } else { - phpCAS::trace('neither nor found'); - } - } - - // at this step, we are sure that the response of the CAS server was ill-formed - $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE; - $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')'; - - phpCAS::traceEnd(FALSE); - return FALSE; - } - - // ######################################################################## - // ACCESS TO EXTERNAL SERVICES - // ######################################################################## - - /** - * This method is used to acces a remote URL. - * - * @param $url the URL to access. - * @param $cookies an array containing cookies strings such as 'name=val' - * @param $headers an array containing the HTTP header lines of the response - * (an empty array on failure). - * @param $body the body of the response, as a string (empty on failure). - * @param $err_msg an error message, filled on failure. - * - * @return TRUE on success, FALSE otherwise (in this later case, $err_msg - * contains an error message). - * - * @private - */ - function readURL($url,$cookies,&$headers,&$body,&$err_msg) - { - phpCAS::traceBegin(); - $headers = ''; - $body = ''; - $err_msg = ''; - - $res = TRUE; - - // initialize the CURL session - $ch = curl_init($url); - - // verify the the server's certificate corresponds to its name - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); - // but do not verify the certificate itself - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - - // return the CURL output into a variable - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - // include the HTTP header with the body - curl_setopt($ch, CURLOPT_HEADER, 1); - // add cookies headers - if ( is_array($cookies) ) { - curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies)); - } - // perform the query - $buf = curl_exec ($ch); - if ( $buf === FALSE ) { - phpCAS::trace('cur_exec() failed'); - $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch); - // close the CURL session - curl_close ($ch); - $res = FALSE; - } else { - // close the CURL session - curl_close ($ch); - - // find the end of the headers - // note: strpos($str,"\n\r\n\r") does not work (?) - $pos = FALSE; - for ($i=0; $iretrievePT($url,$err_code,$output); - - $res = TRUE; - - // test if PT was retrieved correctly - if ( !$pt ) { - // note: $err_code and $err_msg are filled by CASClient::retrievePT() - phpCAS::trace('PT was not retrieved correctly'); - $res = FALSE; - } else { - // add cookies if necessary - if ( is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) { - foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) { - $cookies[] = $name.'='.$val; - } - } - - // build the URL including the PT - if ( strstr($url,'?') === FALSE ) { - $service_url = $url.'?ticket='.$pt; - } else { - $service_url = $url.'&ticket='.$pt; - } - - phpCAS::trace('reading URL`'.$service_url.'\''); - if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) { - phpCAS::trace('could not read URL`'.$service_url.'\''); - $err_code = PHPCAS_SERVICE_NOT_AVAILABLE; - // give an error message - $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE), - $service_url, - $err_msg); - $res = FALSE; - } else { - // URL has been fetched, extract the cookies - phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:'); - foreach ( $headers as $header ) { - // test if the header is a cookie - if ( preg_match('/^Set-Cookie:/',$header) ) { - // the header is a cookie, remove the beginning - $header_val = preg_replace('/^Set-Cookie: */','',$header); - // extract interesting information - $name_val = strtok($header_val,'; '); - // extract the name and the value of the cookie - $cookie_name = strtok($name_val,'='); - $cookie_val = strtok('='); - // store the cookie - $_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val; - phpCAS::trace($cookie_name.' -> '.$cookie_val); - } - } - } - } - - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method is used to access an IMAP/POP3/NNTP service. - * - * @param $url a string giving the URL of the service, including the mailing box - * for IMAP URLs, as accepted by imap_open(). - * @param $flags options given to imap_open(). - * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on - * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE. - * @param $err_msg an error message on failure - * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL - * on success, FALSE on error). - * - * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code - * gives the reason why it failed and $err_msg contains an error message). - * - * @public - */ - function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt) - { - phpCAS::traceBegin(); - // at first retrieve a PT - $pt = $this->retrievePT($target_service,$err_code,$output); - - $stream = FALSE; - - // test if PT was retrieved correctly - if ( !$pt ) { - // note: $err_code and $err_msg are filled by CASClient::retrievePT() - phpCAS::trace('PT was not retrieved correctly'); - } else { - phpCAS::trace('opening IMAP URL `'.$url.'\'...'); - $stream = @imap_open($url,$this->getUser(),$pt,$flags); - if ( !$stream ) { - phpCAS::trace('could not open URL'); - $err_code = PHPCAS_SERVICE_NOT_AVAILABLE; - // give an error message - $err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE), - $service_url, - var_export(imap_errors(),TRUE)); - $pt = FALSE; - $stream = FALSE; - } else { - phpCAS::trace('ok'); - } - } - - phpCAS::traceEnd($stream); - return $stream; - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX PROXIED CLIENT FEATURES (CAS 2.0) XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // PT - // ######################################################################## - /** - * @addtogroup internalProxied - * @{ - */ - - /** - * the Proxy Ticket provided in the URL of the request if present - * (empty otherwise). Written by CASClient::CASClient(), read by - * CASClient::getPT() and CASClient::hasPGT(). - * - * @hideinitializer - * @private - */ - var $_pt = ''; - - /** - * This method returns the Proxy Ticket provided in the URL of the request. - * @return The proxy ticket. - * @private - */ - function getPT() - { return $this->_pt; } - - /** - * This method stores the Proxy Ticket. - * @param $pt The Proxy Ticket. - * @private - */ - function setPT($pt) - { $this->_pt = $pt; } - - /** - * This method tells if a Proxy Ticket was stored. - * @return TRUE if a Proxy Ticket has been stored. - * @private - */ - function hasPT() - { return !empty($this->_pt); } - - /** @} */ - // ######################################################################## - // PT VALIDATION - // ######################################################################## - /** - * @addtogroup internalProxied - * @{ - */ - - /** - * This method is used to validate a PT; halt on failure - * - * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError(). - * - * @private - */ - function validatePT(&$validate_url,&$text_response,&$tree_response) - { - phpCAS::traceBegin(); - // build the URL to validate the ticket - $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT(); - - if ( $this->isProxy() ) { - // pass the callback url for CAS proxies - $validate_url .= '&pgtUrl='.$this->getCallbackURL(); - } - - // open and read the URL - if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) { - phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'); - $this->authError('PT not validated', - $validate_url, - TRUE/*$no_response*/); - } - - // read the response of the CAS server into a DOM object - if ( !($dom = domxml_open_mem($text_response))) { - // read failed - $this->authError('PT not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - // read the root node of the XML tree - if ( !($tree_response = $dom->document_element()) ) { - // read failed - $this->authError('PT not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - // insure that tag name is 'serviceResponse' - if ( $tree_response->node_name() != 'serviceResponse' ) { - // bad root node - $this->authError('PT not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) { - // authentication succeded, extract the user name - if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) { - // no user specified => error - $this->authError('PT not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - $this->setUser(trim($arr[0]->get_content())); - - } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) { - // authentication succeded, extract the error code and message - $this->authError('PT not validated', - $validate_url, - FALSE/*$no_response*/, - FALSE/*$bad_response*/, - $text_response, - $arr[0]->get_attribute('code')/*$err_code*/, - trim($arr[0]->get_content())/*$err_msg*/); - } else { - $this->authError('PT not validated', - $validate_url, - FALSE/*$no_response*/, - TRUE/*$bad_response*/, - $text_response); - } - - // at this step, PT has been validated and $this->_user has been set, - - phpCAS::traceEnd(TRUE); - return TRUE; - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX MISC XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - /** - * @addtogroup internalMisc - * @{ - */ - - // ######################################################################## - // URL - // ######################################################################## - /** - * the URL of the current request (without any ticket CGI parameter). Written - * and read by CASClient::getURL(). - * - * @hideinitializer - * @private - */ - var $_url = ''; - - /** - * This method returns the URL of the current request (without any ticket - * CGI parameter). - * - * @return The URL - * - * @private - */ - function getURL() - { - phpCAS::traceBegin(); - // the URL is built when needed only - if ( empty($this->_url) ) { - $final_uri = ''; - // remove the ticket if present in the URL - $final_uri = ($_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; - $final_uri .= '://'; - /* replaced by Julien Marchal - v0.4.6 - * $this->_url .= $_SERVER['SERVER_NAME']; - */ - if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){ - /* replaced by teedog - v0.4.12 - * $this->_url .= $_SERVER['SERVER_NAME']; - */ - if (empty($_SERVER['SERVER_NAME'])) { - $final_uri .= $_SERVER['HTTP_HOST']; - } else { - $final_uri .= $_SERVER['SERVER_NAME']; - } - } else { - $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER']; - } - if ( ($_SERVER['HTTPS']=='on' && $_SERVER['SERVER_PORT']!=443) - || ($_SERVER['HTTPS']!='on' && $_SERVER['SERVER_PORT']!=80) ) { - $final_uri .= ':'; - $final_uri .= $_SERVER['SERVER_PORT']; - } - - $final_uri .= strtok($_SERVER['REQUEST_URI'],"?"); - $cgi_params = '?'.strtok("?"); - // remove the ticket if present in the CGI parameters - $cgi_params = preg_replace('/&ticket=[^&]*/','',$cgi_params); - $cgi_params = preg_replace('/\?ticket=[^&;]*/','?',$cgi_params); - $cgi_params = preg_replace('/\?$/','',$cgi_params); - $final_uri .= $cgi_params; - $this->setURL($final_uri); - } - phpCAS::traceEnd($this->_url); - return $this->_url; - } - - /** - * This method sets the URL of the current request - * - * @param $url url to set for service - * - * @private - */ - function setURL($url) - { - $this->_url = $url; - } - - // ######################################################################## - // AUTHENTICATION ERROR HANDLING - // ######################################################################## - /** - * This method is used to print the HTML output when the user was not authenticated. - * - * @param $failure the failure that occured - * @param $cas_url the URL the CAS server was asked for - * @param $no_response the response from the CAS server (other - * parameters are ignored if TRUE) - * @param $bad_response bad response from the CAS server ($err_code - * and $err_msg ignored if TRUE) - * @param $cas_response the response of the CAS server - * @param $err_code the error code given by the CAS server - * @param $err_msg the error message given by the CAS server - * - * @private - */ - function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='') - { - phpCAS::traceBegin(); - - $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED)); - printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),$this->getURL(),$_SERVER['SERVER_ADMIN']); - phpCAS::trace('CAS URL: '.$cas_url); - phpCAS::trace('Authentication failure: '.$failure); - if ( $no_response ) { - phpCAS::trace('Reason: no response from the CAS server'); - } else { - if ( $bad_response ) { - phpCAS::trace('Reason: bad response from the CAS server'); - } else { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - phpCAS::trace('Reason: CAS error'); - break; - case CAS_VERSION_2_0: - if ( empty($err_code) ) - phpCAS::trace('Reason: no CAS error'); - else - phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg); - break; - } - } - phpCAS::trace('CAS response: '.$cas_response); - } - $this->printHTMLFooter(); - phpCAS::traceExit(); - exit(); - } - - /** @} */ -} - -?> diff --git a/lib/cas/domxml-php4-php5.php b/lib/cas/domxml-php4-php5.php deleted file mode 100644 index a0dfb99c7ac..00000000000 --- a/lib/cas/domxml-php4-php5.php +++ /dev/null @@ -1,277 +0,0 @@ - - * { - * if (version_compare(PHP_VERSION,'5','>=')) - * require_once('domxml-php4-to-php5.php'); - * } - * - * - * Version 1.5.5, 2005-01-18, http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ - * - * ------------------------------------------------------------------
- * Written by Alexandre Alapetite, http://alexandre.alapetite.net/cv/ - * - * Copyright 2004, Licence: Creative Commons "Attribution-ShareAlike 2.0 France" BY-SA (FR), - * http://creativecommons.org/licenses/by-sa/2.0/fr/ - * http://alexandre.alapetite.net/divers/apropos/#by-sa - * - Attribution. You must give the original author credit - * - Share Alike. If you alter, transform, or build upon this work, - * you may distribute the resulting work only under a license identical to this one - * - The French law is authoritative - * - Any of these conditions can be waived if you get permission from Alexandre Alapetite - * - Please send to Alexandre Alapetite the modifications you make, - * in order to improve this file for the benefit of everybody - * - * If you want to distribute this code, please do it as a link to: - * http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ - */ - -function domxml_new_doc($version) {return new php4DOMDocument('');} -function domxml_open_file($filename) {return new php4DOMDocument($filename);} -function domxml_open_mem($str) -{ - $dom=new php4DOMDocument(''); - $dom->myDOMNode->loadXML($str); - return $dom; -} -function xpath_eval($xpath_context,$eval_str,$contextnode=null) {return $xpath_context->query($eval_str,$contextnode);} -function xpath_new_context($dom_document) {return new php4DOMXPath($dom_document);} - -class php4DOMAttr extends php4DOMNode -{ - function php4DOMAttr($aDOMAttr) {$this->myDOMNode=$aDOMAttr;} - function Name() {return $this->myDOMNode->name;} - function Specified() {return $this->myDOMNode->specified;} - function Value() {return $this->myDOMNode->value;} -} - -class php4DOMDocument extends php4DOMNode -{ - function php4DOMDocument($filename='') - { - $this->myDOMNode=new DOMDocument(); - if ($filename!='') $this->myDOMNode->load($filename); - } - function create_attribute($name,$value) - { - $myAttr=$this->myDOMNode->createAttribute($name); - $myAttr->value=$value; - return new php4DOMAttr($myAttr,$this); - } - function create_cdata_section($content) {return new php4DOMNode($this->myDOMNode->createCDATASection($content),$this);} - function create_comment($data) {return new php4DOMNode($this->myDOMNode->createComment($data),$this);} - function create_element($name) {return new php4DOMElement($this->myDOMNode->createElement($name),$this);} - function create_text_node($content) {return new php4DOMNode($this->myDOMNode->createTextNode($content),$this);} - function document_element() {return new php4DOMElement($this->myDOMNode->documentElement,$this);} - function dump_file($filename,$compressionmode=false,$format=false) {return $this->myDOMNode->save($filename);} - function dump_mem($format=false,$encoding=false) {return $this->myDOMNode->saveXML();} - function get_element_by_id($id) {return new php4DOMElement($this->myDOMNode->getElementById($id),$this);} - function get_elements_by_tagname($name) - { - $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name); - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMElement($node,$this); - $i++; - } - return $nodeSet; - } - function html_dump_mem() {return $this->myDOMNode->saveHTML();} - function root() {return new php4DOMElement($this->myDOMNode->documentElement,$this);} -} - -class php4DOMElement extends php4DOMNode -{ - function get_attribute($name) {return $this->myDOMNode->getAttribute($name);} - function get_elements_by_tagname($name) - { - $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name); - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument); - $i++; - } - return $nodeSet; - } - function has_attribute($name) {return $this->myDOMNode->hasAttribute($name);} - function remove_attribute($name) {return $this->myDOMNode->removeAttribute($name);} - function set_attribute($name,$value) {return $this->myDOMNode->setAttribute($name,$value);} - function tagname() {return $this->myDOMNode->tagName;} -} - -class php4DOMNode -{ - var $myDOMNode; - var $myOwnerDocument; - function php4DOMNode($aDomNode,$aOwnerDocument) - { - $this->myDOMNode=$aDomNode; - $this->myOwnerDocument=$aOwnerDocument; - } - function __get($name) - { - if ($name=='type') return $this->myDOMNode->nodeType; - elseif ($name=='tagname') return $this->myDOMNode->tagName; - elseif ($name=='content') return $this->myDOMNode->textContent; - else - { - $myErrors=debug_backtrace(); - trigger_error('Undefined property: '.get_class($this).'::$'.$name.' ['.$myErrors[0]['file'].':'.$myErrors[0]['line'].']',E_USER_NOTICE); - return false; - } - } - function append_child($newnode) {return new php4DOMElement($this->myDOMNode->appendChild($newnode->myDOMNode),$this->myOwnerDocument);} - function append_sibling($newnode) {return new php4DOMElement($this->myDOMNode->parentNode->appendChild($newnode->myDOMNode),$this->myOwnerDocument);} - function attributes() - { - $myDOMNodeList=$this->myDOMNode->attributes; - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMAttr($node,$this->myOwnerDocument); - $i++; - } - return $nodeSet; - } - function child_nodes() - { - $myDOMNodeList=$this->myDOMNode->childNodes; - $nodeSet=array(); - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument); - $i++; - } - return $nodeSet; - } - function children() {return $this->child_nodes();} - function clone_node($deep=false) {return new php4DOMElement($this->myDOMNode->cloneNode($deep),$this->myOwnerDocument);} - function first_child() {return new php4DOMElement($this->myDOMNode->firstChild,$this->myOwnerDocument);} - function get_content() {return $this->myDOMNode->textContent;} - function has_attributes() {return $this->myDOMNode->hasAttributes();} - function has_child_nodes() {return $this->myDOMNode->hasChildNodes();} - function insert_before($newnode,$refnode) {return new php4DOMElement($this->myDOMNode->insertBefore($newnode->myDOMNode,$refnode->myDOMNode),$this->myOwnerDocument);} - function is_blank_node() - { - $myDOMNodeList=$this->myDOMNode->childNodes; - $i=0; - if (isset($myDOMNodeList)) - while ($node=$myDOMNodeList->item($i)) - { - if (($node->nodeType==XML_ELEMENT_NODE)|| - (($node->nodeType==XML_TEXT_NODE)&&!ereg('^([[:cntrl:]]|[[:space:]])*$',$node->nodeValue))) - return false; - $i++; - } - return true; - } - function last_child() {return new php4DOMElement($this->myDOMNode->lastChild,$this->myOwnerDocument);} - function new_child($name,$content) - { - $mySubNode=$this->myDOMNode->ownerDocument->createElement($name); - $mySubNode->appendChild($this->myDOMNode->ownerDocument->createTextNode($content)); - $this->myDOMNode->appendChild($mySubNode); - return new php4DOMElement($mySubNode,$this->myOwnerDocument); - } - function next_sibling() {return new php4DOMElement($this->myDOMNode->nextSibling,$this->myOwnerDocument);} - function node_name() {return $this->myDOMNode->localName;} - function node_type() {return $this->myDOMNode->nodeType;} - function node_value() {return $this->myDOMNode->nodeValue;} - function owner_document() {return $this->myOwnerDocument;} - function parent_node() {return new php4DOMElement($this->myDOMNode->parentNode,$this->myOwnerDocument);} - function prefix() {return $this->myDOMNode->prefix;} - function previous_sibling() {return new php4DOMElement($this->myDOMNode->previousSibling,$this->myOwnerDocument);} - function remove_child($oldchild) {return new php4DOMElement($this->myDOMNode->removeChild($oldchild->myDOMNode),$this->myOwnerDocument);} - function replace_child($oldnode,$newnode) {return new php4DOMElement($this->myDOMNode->replaceChild($oldnode->myDOMNode,$newnode->myDOMNode),$this->myOwnerDocument);} - function set_content($text) - { - if (($this->myDOMNode->hasChildNodes())&&($this->myDOMNode->firstChild->nodeType==XML_TEXT_NODE)) - $this->myDOMNode->removeChild($this->myDOMNode->firstChild); - return $this->myDOMNode->appendChild($this->myDOMNode->ownerDocument->createTextNode($text)); - } -} - -class php4DOMNodelist -{ - var $myDOMNodelist; - var $nodeset; - function php4DOMNodelist($aDOMNodelist,$aOwnerDocument) - { - $this->myDOMNodelist=$aDOMNodelist; - $this->nodeset=array(); - $i=0; - if (isset($this->myDOMNodelist)) - while ($node=$this->myDOMNodelist->item($i)) - { - $this->nodeset[]=new php4DOMElement($node,$aOwnerDocument); - $i++; - } - } -} - -class php4DOMXPath -{ - var $myDOMXPath; - var $myOwnerDocument; - function php4DOMXPath($dom_document) - { - $this->myOwnerDocument=$dom_document; - $this->myDOMXPath=new DOMXPath($dom_document->myDOMNode); - } - function query($eval_str,$contextnode) - { - if (isset($contextnode)) return new php4DOMNodelist($this->myDOMXPath->query($eval_str,$contextnode->myDOMNode),$this->myOwnerDocument); - else return new php4DOMNodelist($this->myDOMXPath->query($eval_str),$this->myOwnerDocument); - } - function xpath_register_ns($prefix,$namespaceURI) {return $this->myDOMXPath->registerNamespace($prefix,$namespaceURI);} -} - -if (extension_loaded('xsl')) -{//See also: http://alexandre.alapetite.net/doc-alex/xslt-php4-php5/ - function domxml_xslt_stylesheet($xslstring) {return new php4DomXsltStylesheet(DOMDocument::loadXML($xslstring));} - function domxml_xslt_stylesheet_doc($dom_document) {return new php4DomXsltStylesheet($dom_document);} - function domxml_xslt_stylesheet_file($xslfile) {return new php4DomXsltStylesheet(DOMDocument::load($xslfile));} - class php4DomXsltStylesheet - { - var $myxsltProcessor; - function php4DomXsltStylesheet($dom_document) - { - $this->myxsltProcessor=new xsltProcessor(); - $this->myxsltProcessor->importStyleSheet($dom_document); - } - function process($dom_document,$xslt_parameters=array(),$param_is_xpath=false) - { - foreach ($xslt_parameters as $param=>$value) - $this->myxsltProcessor->setParameter('',$param,$value); - $myphp4DOMDocument=new php4DOMDocument(); - $myphp4DOMDocument->myDOMNode=$this->myxsltProcessor->transformToDoc($dom_document->myDOMNode); - return $myphp4DOMDocument; - } - function result_dump_file($dom_document,$filename) - { - $html=$dom_document->myDOMNode->saveHTML(); - file_put_contents($filename,$html); - return $html; - } - function result_dump_mem($dom_document) {return $dom_document->myDOMNode->saveHTML();} - } -} -?> \ No newline at end of file diff --git a/lib/cas/languages/english.php b/lib/cas/languages/english.php deleted file mode 100644 index d38d42c1f7c..00000000000 --- a/lib/cas/languages/english.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'using server', - CAS_STR_AUTHENTICATION_WANTED - => 'CAS Authentication wanted!', - CAS_STR_LOGOUT - => 'CAS logout wanted!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'You should already have been redirected to the CAS server. Click here to continue.', - CAS_STR_AUTHENTICATION_FAILED - => 'CAS Authentication failed!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

You were not authenticated.

You may submit your request again by clicking here.

If the problem persists, you may contact the administrator of this site.

', - CAS_STR_SERVICE_UNAVAILABLE - => 'The service `%s\' is not available (%s).' -); - -?> \ No newline at end of file diff --git a/lib/cas/languages/french.php b/lib/cas/languages/french.php deleted file mode 100644 index 32d14168506..00000000000 --- a/lib/cas/languages/french.php +++ /dev/null @@ -1,28 +0,0 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => 'utilisant le serveur', - CAS_STR_AUTHENTICATION_WANTED - => 'Authentication CAS nécessaire !', - CAS_STR_LOGOUT - => 'Déconnexion demandée !', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'Vous auriez du etre redirigé(e) vers le serveur CAS. Cliquez ici pour continuer.', - CAS_STR_AUTHENTICATION_FAILED - => 'Authentification CAS infructueuse !', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

Vous n\'avez pas été authentifié(e).

Vous pouvez soumettre votre requete à nouveau en cliquant ici.

Si le problème persiste, vous pouvez contacter l\'administrateur de ce site.

', - CAS_STR_SERVICE_UNAVAILABLE - => 'Le service `%s\' est indisponible (%s)' - -); - -?> \ No newline at end of file diff --git a/lib/cas/languages/greek.php b/lib/cas/languages/greek.php deleted file mode 100644 index c17b1d66377..00000000000 --- a/lib/cas/languages/greek.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -$this->_strings = array( - CAS_STR_USING_SERVER - => '÷ñçóéìïðïéåßôáé ï åîõðçñåôçôÞò', - CAS_STR_AUTHENTICATION_WANTED - => 'Áðáéôåßôáé ç ôáõôïðïßçóç CAS!', - CAS_STR_LOGOUT - => 'Áðáéôåßôáé ç áðïóýíäåóç áðü CAS!', - CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED - => 'Èá Ýðñåðå íá åß÷áôå áíáêáôåõèõíèåß óôïí åîõðçñåôçôÞ CAS. ÊÜíôå êëßê åäþ ãéá íá óõíå÷ßóåôå.', - CAS_STR_AUTHENTICATION_FAILED - => 'Ç ôáõôïðïßçóç CAS áðÝôõ÷å!', - CAS_STR_YOU_WERE_NOT_AUTHENTICATED - => '

Äåí ôáõôïðïéçèÞêáôå.

Ìðïñåßôå íá îáíáðñïóðáèÞóåôå, êÜíïíôáò êëßê åäþ.

Åáí ôï ðñüâëçìá åðéìåßíåé, åëÜôå óå åðáöÞ ìå ôïí äéá÷åéñéóôÞ.

', - CAS_STR_SERVICE_UNAVAILABLE - => 'Ç õðçñåóßá `%s\' äåí åßíáé äéáèÝóéìç (%s).' -); - -?> \ No newline at end of file diff --git a/lib/cas/languages/languages.php b/lib/cas/languages/languages.php deleted file mode 100644 index 001cfe445cd..00000000000 --- a/lib/cas/languages/languages.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -//@{ -/** - * a phpCAS string index - */ -define("CAS_STR_USING_SERVER", 1); -define("CAS_STR_AUTHENTICATION_WANTED", 2); -define("CAS_STR_LOGOUT", 3); -define("CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED", 4); -define("CAS_STR_AUTHENTICATION_FAILED", 5); -define("CAS_STR_YOU_WERE_NOT_AUTHENTICATED", 6); -define("CAS_STR_SERVICE_UNAVAILABLE", 7); -//@} - -?> \ No newline at end of file