skala
Laurent Opprecht 13 years ago
commit 4ecd909b8c
  1. 4
      .hgignore
  2. 12
      main/auth/shibboleth/_readme.txt
  3. 153
      main/auth/shibboleth/app/controller/shibboleth_controller.class.php
  4. 18
      main/auth/shibboleth/app/lib/model.class.php
  5. 63
      main/auth/shibboleth/app/lib/scaffolder/scaffolder.class.php
  6. 145
      main/auth/shibboleth/app/lib/scaffolder/template/default.php
  7. 145
      main/auth/shibboleth/app/lib/scaffolder/template/model.php
  8. 38
      main/auth/shibboleth/app/lib/scaffolder/template/public.php
  9. 60
      main/auth/shibboleth/app/lib/shibboleth_config.class.php
  10. 82
      main/auth/shibboleth/app/lib/shibboleth_session.class.php
  11. 351
      main/auth/shibboleth/app/lib/store.class.php
  12. 186
      main/auth/shibboleth/app/model/scaffold/user.class.php
  13. 196
      main/auth/shibboleth/app/model/shibboleth_store.class.php
  14. 32
      main/auth/shibboleth/app/model/shibboleth_user.class.php
  15. 85
      main/auth/shibboleth/app/model/user.class.php
  16. 286
      main/auth/shibboleth/app/shibboleth.class.php
  17. 19
      main/auth/shibboleth/app/view/admin_login.php
  18. 19
      main/auth/shibboleth/app/view/request.php
  19. 64
      main/auth/shibboleth/app/view/shibboleth_display.class.php
  20. 50
      main/auth/shibboleth/app/view/shibboleth_email_form.class.php
  21. 94
      main/auth/shibboleth/app/view/shibboleth_status_request_form.class.php
  22. 15
      main/auth/shibboleth/config-dist.php
  23. 12
      main/auth/shibboleth/config.php
  24. 68
      main/auth/shibboleth/config/aai.class.php
  25. 82
      main/auth/shibboleth/db/shibboleth_upgrade.class.php
  26. 9
      main/auth/shibboleth/index.php
  27. 36
      main/auth/shibboleth/init.php
  28. 33
      main/auth/shibboleth/login.php
  29. 0
      main/auth/shibboleth/script/output/user.class.php
  30. 35
      main/auth/shibboleth/script/scaffold.php
  31. 216
      main/auth/shibboleth/test/shibboleth_test.class.php
  32. 113
      main/auth/shibboleth/test/shibboleth_test_helper.class.php
  33. 31
      main/auth/shibboleth/test/test.php
  34. 19
      main/auth/shibboleth/test/test_no_email.php
  35. 176
      main/inc/lib/plugin.class.php
  36. 25
      main/lang/english/shibboleth.inc.php
  37. 24
      main/lang/french/shibboleth.inc.php
  38. 59
      plugin/rss/index.php
  39. 16
      plugin/rss/lang/english.php
  40. 13
      plugin/rss/lang/french.php
  41. 38
      plugin/rss/lib/rss_plugin.class.php
  42. 16
      plugin/rss/plugin.php
  43. 4
      plugin/rss/readme.txt
  44. BIN
      plugin/rss/resources/arrow-bullet.png
  45. 41
      plugin/rss/resources/color.css
  46. 103
      plugin/rss/resources/rss.css
  47. 5
      plugin/search_course/index.php
  48. 10
      plugin/search_course/lang/english.php
  49. 10
      plugin/search_course/lang/french.php
  50. 163
      plugin/search_course/lib/register_course_widget.class.php
  51. 33
      plugin/search_course/lib/search_course_plugin.class.php
  52. 435
      plugin/search_course/lib/search_course_widget.class.php
  53. 11
      plugin/search_course/plugin.php
  54. 1
      plugin/search_course/readme.txt
  55. 28
      plugin/static/index.php
  56. 15
      plugin/static/lang/english.php
  57. 13
      plugin/static/lang/french.php
  58. 38
      plugin/static/lib/static_plugin.class.php
  59. 12
      plugin/static/plugin.php
  60. 1
      plugin/static/readme.txt
  61. 4
      plugin/static/resources/static.css

@ -116,4 +116,6 @@ syntax: regexp
^main/upload/users$
syntax: regexp
^\.settings$
^\.settings$
nbproject/*

@ -0,0 +1,12 @@
Shibboleth authentication module.
@copyright (c) 2012 University of Geneva
@license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
@author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
To use install Shibboleth on your web server and secure the application url
with a web server security directive.
Modify configuration to your federation's needs.
Add a login url/redirection to chamilo/main/auth/login.php.

@ -0,0 +1,153 @@
<?php
/**
* Controller for the Shibboleth authentication system.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ShibbolethController
{
/**
*
* @return ShibbolethController
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
/**
* Log user in with Shibboleth authentication
*/
function login()
{
if (Shibboleth::session()->is_logged_in())
{
Shibboleth::redirect();
}
$user = Shibboleth::store()->get_user();
if ($user->is_empty())
{
$message = get_lang('no_login');
Shibboleth::display()->error_page($message);
}
$is_new_user = !User::store()->shibboleth_id_exists($user->unique_id);
if ($is_new_user && empty($user->email) && Shibboleth::config()->is_email_mandatory)
{
$form = ShibbolethEmailForm::instance();
if ($email = $form->get_email())
{
$user->email = $email;
}
else
{
$content = $form->display();
Shibboleth::display()->page($content);
}
}
Shibboleth::save($user);
$chamilo_user = User::store()->get_by_shibboleth_id($user->unique_id);
Shibboleth::session()->login($chamilo_user->user_id);
if ($is_new_user && $user->status_request)
{
Shibboleth::redirect('main/auth/shibboleth/app/view/request.php');
}
else
{
Shibboleth::redirect();
}
}
/**
* Log user in using the standard Chamilo way of logging in.
* Useful when the normal login screen is removed from the user interface
* - replaced by Shibboleth login - and user want to login using a standard
* account
*/
public function admin_login()
{
$title = get_lang('internal_login');
if (Shibboleth::session()->is_logged_in())
{
$message = get_lang('already_logged_in');
Shibboleth::display()->message_page($message, $title);
}
$index_manager = new IndexManager('');
$html = $index_manager->display_login_form();
Shibboleth::display()->page($html, $title);
}
/**
* Display the request new status page to administrator for new users.
*/
public function request_status()
{
/*
* That may happen if a user visit that url again.
*/
if (!Shibboleth::session()->is_logged_in())
{
Shibboleth::redirect();
}
$user = Shibboleth::session()->user();
if ($user['status'] == Shibboleth::TEACHER_STATUS)
{
//Maximum user right is reached.
Shibboleth::redirect();
}
$form = ShibbolethStatusRequestForm::instance();
if ($form->cancelled())
{
Shibboleth::redirect();
}
if ($reason = $form->get_reason())
{
$subject = get_lang('request_status');
$status = $form->get_status();
$status = Shibboleth::format_status($status);
$message = <<<EOT
New status: $status
Reason:
$reason
EOT;
$success = Shibboleth::email_admin($subject, $message);
if ($success)
{
$request_submitted = get_lang('request_submitted');
Shibboleth::display()->message_page($request_submitted);
}
else
{
$request_failed = get_lang('request_failed');
Shibboleth::display()->error_page($request_failed);
}
}
$title = get_lang('request_status');
Display :: display_header($title);
echo $form->display();
Display :: display_footer();
}
}

@ -0,0 +1,18 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of model
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class Model
{
}

@ -0,0 +1,63 @@
<?php
/**
* Scaffolder. Genereate code templates from the database layout.
* See /template/ for the code being generated
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class Scaffolder
{
/**
*
* @staticvar boolean $result
* @return Scaffolder
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
public function scaffold($table_name, $class_name = '', $prefix = '_')
{
$db_name = Database :: get_main_database();
$sql = "SELECT * FROM `$db_name`.`$table_name` LIMIT 1";
$fields = array();
$unique_fields = array();
$rs = Database::query($sql, null, __FILE__);
while ($field = mysql_fetch_field($rs))
{
$fields[] = $field;
if ($field->primary_key)
{
/**
* Could move that to an array to support multiple keys
*/
$id_name = $field->name;
}
if ($field->unique_key | $field->primary_key)
{
$keys[] = $field->name;
}
}
$name = $table_name;
$class_name = ucfirst($table_name);
ob_start();
include dirname(__FILE__) . '/template/model.php';
$result = ob_get_clean();
return $result;
}
}

@ -0,0 +1,145 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
echo '<?php';
?>
/**
* This file is autogenerated. Do not modifiy it.
*/
/**
*
* Model for table <?php echo $table_name ?>
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class <?php echo $prefix . $class_name ?>
{
/**
* Store for <?php echo $class_name ?> objects. Interact with the database.
*
* @return <?php echo $class_name ?>Store
*/
public static function store()
{
static $result = false;
if (empty($result))
{
$result = new <?php echo $class_name ?>Store();
}
return $result;
}
/**
*
* @return <?php echo $class_name ?>
*/
public static function create($data = null)
{
return self::store()->create_object($data);
}
<?php foreach($fields as $field){?>
public $<?php echo $field->name; ?> = <?php echo $field->def ? $field->def : 'null'; ?>;
<?php }?>
/**
*
* @return bool
*/
public function save()
{
return self::store()->save($this);
}
}
/**
* Store for <?php echo $class_name ?> objects. Interact with the database.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class <?php echo $prefix . $class_name ?>Store extends Store
{
/**
*
* @return <?php echo $class_name ?>Store
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
public function __construct()
{
parent::__construct('<?php echo $table_name;?>', '<?php echo $class_name;?>', '<?php echo $id_name;?>');
}
/**
*
* @return <?php echo $class_name ?>
*/
public function get($w)
{
$args = func_get_args();
$f = array('parent', 'get');
return call_user_func_array($f, $args);
}
/**
*
* @return <?php echo $class_name ?>
*/
public function create_object($data)
{
return parent::create_object($data);
}
<?php foreach($keys as $key){?>
/**
*
* @return <?php echo $class_name ?>
*/
public function get_by_<?php echo $key ?>($value)
{
return $this->get(array('<?php echo $key; ?>' => $value));
}
/**
*
* @return bool
*/
public function <?php echo $key ?>_exists($value)
{
return $this->exist(array('<?php echo $key; ?>' => $value));
}
/**
*
* @return bool
*/
public function delete_by_<?php echo $key ?>($value)
{
return $this->delete(array('<?php echo $key; ?>' => $value));
}
<?php }?>
}

@ -0,0 +1,145 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
echo '<?php';
?>
/**
* This file is autogenerated. Do not modifiy it.
*/
/**
*
* Model for table <?php echo $table_name ?>
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class <?php echo $prefix . $class_name ?>
{
/**
* Store for <?php echo $class_name ?> objects. Interact with the database.
*
* @return <?php echo $class_name ?>Store
*/
public static function store()
{
static $result = false;
if (empty($result))
{
$result = new <?php echo $class_name ?>Store();
}
return $result;
}
/**
*
* @return <?php echo $class_name ?>
*/
public static function create($data = null)
{
return self::store()->create_object($data);
}
<?php foreach($fields as $field){?>
public $<?php echo $field->name; ?> = <?php echo $field->def ? $field->def : 'null'; ?>;
<?php }?>
/**
*
* @return bool
*/
public function save()
{
return self::store()->save($this);
}
}
/**
* Store for <?php echo $class_name ?> objects. Interact with the database.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class <?php echo $prefix . $class_name ?>Store extends Store
{
/**
*
* @return <?php echo $class_name ?>Store
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
public function __construct()
{
parent::__construct('<?php echo $table_name;?>', '<?php echo $class_name;?>', '<?php echo $id_name;?>');
}
/**
*
* @return <?php echo $class_name ?>
*/
public function get($w)
{
$args = func_get_args();
$f = array('parent', 'get');
return call_user_func_array($f, $args);
}
/**
*
* @return <?php echo $class_name ?>
*/
public function create_object($data)
{
return parent::create_object($data);
}
<?php foreach($keys as $key){?>
/**
*
* @return <?php echo $class_name ?>
*/
public function get_by_<?php echo $key ?>($value)
{
return $this->get(array('<?php echo $key; ?>' => $value));
}
/**
*
* @return bool
*/
public function <?php echo $key ?>_exists($value)
{
return $this->exist(array('<?php echo $key; ?>' => $value));
}
/**
*
* @return bool
*/
public function delete_by_<?php echo $key ?>($value)
{
return $this->delete(array('<?php echo $key; ?>' => $value));
}
<?php }?>
}

@ -0,0 +1,38 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
echo '<?php';
?>
/**
*
* Model for table <?php echo $table_name ?>
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class <?php echo $class_name ?>
{
}
/**
* Store for <?php echo $class_name ?> objects. Interact with the database.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class <?php echo $class_name ?>Store extends Store
{
}

@ -0,0 +1,60 @@
<?php
/**
* Shibboleth configuration. All configuration for the Shibboleth authentication
* plugin: field names mapping, etc.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
class ShibbolethConfig
{
public $unique_id = '';
public $firstname = '';
public $lastname = '';
public $email = '';
public $language = '';
public $gender = '';
public $address = '';
public $staff_category = '';
public $home_organization_type = '';
public $home_organization = '';
public $affiliation = '';
public $persistent_id = '';
public $default_status = Shibboleth::UNKNOWN_STATUS;
/**
* Mapping of affiliation => right
* @var array
*/
public $affiliation_status = array();
/**
* Mapping of affiliation => bool. Display the request status form.
* @var array
*/
public $affiliation_status_request = array();
/**
* List of fields to update when the user already exists field_name => boolean.
* @var array
*/
public $update_fields = array();
/*
* True if email is mandatory. False otherwise.
*/
public $is_email_mandatory = true;
/**
* The email of the shibboleth administrator.
*
* @var string
*/
public $admnistrator_email = '';
}

@ -0,0 +1,82 @@
<?php
/**
* A Chamilo user session. Used as there is no session object so far provided by the core API.
* Should be moved to the core library.Prefixed by Shibboleth to avoid name clashes.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
class ShibbolethSession
{
/**
* @return ShibbolethSession
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
function is_logged_in()
{
return isset($_SESSION['_user']['user_id']);
}
function user()
{
return $_SESSION['_user'];
}
function logout()
{
$_SESSION['_user'] = array();
}
/**
* Create a Shibboleth session for the user ID
*
* @param string $_uid - The user ID
* @return $_user (array) - The user infos array created when the user logs in
*/
function login($_uid)
{
$user = User::store()->get_by_user_id($_uid);
if (empty($user))
{
return;
}
api_session_register('_uid');
global $_user;
$_user = (array)$user;
$_SESSION['_user'] = $_user;
$_SESSION['_user']['user_id'] = $_uid;
$_SESSION['noredirection'] = true;
//used in 'init_local.inc.php'
$loginFailed = false;
$uidReset = true;
$gidReset = true;
$cidReset = true;
$mainDbName = Database :: get_main_database();
$includePath = api_get_path(INCLUDE_PATH);
require("$includePath/local.inc.php");
event_login();
return $_user;
}
}

@ -0,0 +1,351 @@
<?php
/**
* A database store. Used interact with the database - save objects, run queries.
*
* One store = one table.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class Store
{
/**
*
* @return Store
*/
public static function create($table_name, $class_name = '', $id_name = 'id', $db_name = '')
{
return new self($table_name, $class_name, $id_name, $db_name);
}
protected $db_name = '';
protected $table_name = '';
protected $id_name = '';
protected $class_name = '';
function __construct($table_name, $class_name = '', $id_name = 'id', $db_name = '')
{
$this->db_name = $db_name ? $db_name : Database::get_main_database();
$this->table_name = $table_name;
$this->class_name = $class_name;
$this->id_name = $id_name;
}
function get_db_name($object = '')
{
if ($this->db_name)
{
return $this->db_name;
}
if ($object)
{
$result = isset($object->{db_name}) ? $object->{db_name} : '';
$result = $result ? $result : Database :: get_main_database();
return $result;
}
return Database::get_main_database();
}
function get($w)
{
$args = func_get_args();
$f = array($this, 'get_where');
$db_name = $this->get_db_name();
$where = call_user_func_array($f, $args);
$sql = "SELECT *
FROM `{$db_name}`.`{$this->table_name}`
WHERE $where";
$items = $this->query($sql);
return (count($items) == 1) ? reset($items) : null;
}
function select($w)
{
$args = func_get_args();
$f = array($this, 'get_where');
$db_name = $this->get_db_name();
$where = call_user_func_array($f, $args);
$sql = "SELECT *
FROM `{$db_name}`.`{$this->table_name}`
WHERE $where";
$result = $this->query($sql);
return $result;
}
function exist($w)
{
$args = func_get_args();
$f = array($this, 'get');
$object = call_user_func_array($f, $args);
return !empty($object);
}
function is_new($object)
{
$id_name = $this->id_name;
$id = isset($object->{$id_name}) ? $object->{$id_name} : false;
return empty($id);
}
function save($object)
{
if (empty($object))
{
return false;
}
$object = is_array($object) ? $this->create_object($object) : $object;
$this->before_save($object);
if ($this->is_new($object))
{
$result = $this->insert($object);
}
else
{
$result = $this->update($object);
}
return $result;
}
function delete($object)
{
$args = func_get_args();
$f = array($this, 'get_where');
$db_name = $this->get_db_name();
$where = call_user_func_array($f, $args);
$sql = "DELETE
FROM `{$db_name
}
`.`{$this->table_name
}
`
WHERE $where";
$result = $this->query($sql);
return $result;
}
/**
*
* @param array|object $data
* @return object
*/
public function create_object($data = array())
{
$data = $data ? $data : array();
$data = (object) $data;
$class = $this->class_name;
if (empty($class))
{
return clone $data;
}
$result = new $class();
foreach ($result as $key => $value)
{
$result->{$key} = property_exists($data, $key) ? $data->{$key} : null;
}
return $result;
}
public function fields($object)
{
static $result = array();
if (!empty($result))
{
return $result;
}
$db_name = $this->get_db_name($object);
$sql = "SELECT *
FROM `{$db_name}`.`{$this->table_name}`
LIMIT 1";
$rs = Database::query($sql, null, __FILE__);
while ($field = mysql_fetch_field($rs))
{
$result[] = $field;
}
return $result;
}
protected function before_save($object)
{
//hook
}
protected function update($object)
{
$id = isset($object->{$this->id_name}) ? $object->{$this->id_name} : false;
if (empty($id))
{
return false;
}
$items = array();
$fields = $this->fields($object);
foreach ($fields as $field)
{
$name = $field->name;
if ($name != $this->id_name)
{
if (property_exists($object, $name))
{
$value = $object->{$name};
$value = $this->format_value($value);
$items[] = "$name=$value";
}
}
}
$db_name = $this->get_db_name($object);
$sql = "UPDATE `{$db_name}`.`{$this->table_name}` SET ";
$sql .= join(', ', $items);
$sql .= " WHERE {$this->id_name}=$id";
$result = $this->execute($sql);
if ($result)
{
$object->{db_name} = $db_name;
}
return (bool) $result;
}
protected function insert($object)
{
$id = isset($object->{$this->id_name}) ? $object->{$this->id_name} : false;
if (empty($object))
{
return false;
}
$values = array();
$keys = array();
$fields = $this->fields($object);
foreach ($fields as $field)
{
$name = $field->name;
if ($name != $this->id_name)
{
if (property_exists($object, $name))
{
$value = $object->{$name};
$value = is_null($value) ? 'DEFAULT' : $this->format_value($value);
$values[] = $value;
$keys[] = $name;
}
}
}
$db_name = $this->get_db_name($object);
$sql = "INSERT INTO `{$db_name}`.`{$this->table_name}` ";
$sql .= ' (' . join(', ', $keys) . ') ';
$sql .= 'VALUES';
$sql .= ' (' . join(', ', $values) . ') ';
$result = $this->execute($sql);
if ($result)
{
$id = mysql_insert_id();
$object->{$this->id_name} = $id;
$object->{db_name} = $db_name;
return $id;
}
else
{
return false;
}
}
protected function get_where($_)
{
$args = func_get_args();
if (count($args) == 1)
{
$arg = reset($args);
if (is_numeric($arg))
{
$id = (int) $arg;
if (empty($id))
{
return '';
}
$args = array($this->pk_name, $arg);
}
else if (is_string($arg))
{
return $arg;
}
else if (is_array($arg))
{
$args = $arg;
}
else
{
return $arg;
}
}
$items = array();
foreach ($args as $key => $val)
{
$items[] = $key . ' = ' . $this->format_value($val);
}
return implode(' AND ', $items);
}
protected function format_value($value)
{
if (is_null($value))
{
return 'NULL';
}
if (is_bool($var))
{
return $value ? '1' : '0';
}
else if (is_numeric($value))
{
return empty($value) ? '0' : $value;
}
else if (is_string($value))
{
$value = mysql_escape_string($value);
return "'$value'";
}
else
{
return $value;
}
}
/**
*
* @param string $sql
* @return array
*/
protected function query($sql)
{
$resource = Database::query($sql, null, __FILE__);
if ($resource == false)
{
return array();
}
$result = array();
while ($data = mysql_fetch_assoc($resource))
{
$result[] = $this->create_object($data);
}
return $result;
}
protected function execute($sql)
{
return Database::query($sql, null, __FILE__);
}
}

@ -0,0 +1,186 @@
<?php
/**
* This file is autogenerated. Do not modifiy it.
*/
/**
*
* Model for table user
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class _User
{
/**
* Store for User objects. Interact with the database.
*
* @return UserStore
*/
public static function store()
{
static $result = false;
if (empty($result))
{
$result = new UserStore();
}
return $result;
}
/**
*
* @return User
*/
public static function create($data = null)
{
return self::store()->create_object($data);
}
public $user_id = null;
public $lastname = null;
public $firstname = null;
public $username = null;
public $password = null;
public $auth_source = null;
public $shibb_unique_id = null;
public $email = null;
public $status = null;
public $official_code = null;
public $phone = null;
public $picture_uri = null;
public $creator_id = null;
public $competences = null;
public $diplomas = null;
public $openarea = null;
public $teach = null;
public $productions = null;
public $chatcall_user_id = null;
public $chatcall_date = null;
public $chatcall_text = null;
public $language = null;
public $registration_date = null;
public $expiration_date = null;
public $active = null;
public $openid = null;
public $theme = null;
public $hr_dept_id = null;
public $shibb_persistent_id = null;
/**
*
* @return bool
*/
public function save()
{
return self::store()->save($this);
}
}
/**
* Store for User objects. Interact with the database.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class _UserStore extends Store
{
/**
*
* @return UserStore
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
public function __construct()
{
parent::__construct('user', 'User', 'user_id');
}
/**
*
* @return User
*/
public function get($w)
{
$args = func_get_args();
$f = array('parent', 'get');
return call_user_func_array($f, $args);
}
/**
*
* @return User
*/
public function create_object($data)
{
return parent::create_object($data);
}
/**
*
* @return User
*/
public function get_by_user_id($value)
{
return $this->get(array('user_id' => $value));
}
/**
*
* @return bool
*/
public function user_id_exists($value)
{
return $this->exist(array('user_id' => $value));
}
/**
*
* @return bool
*/
public function delete_by_user_id($value)
{
return $this->delete(array('user_id' => $value));
}
/**
*
* @return User
*/
public function get_by_username($value)
{
return $this->get(array('username' => $value));
}
/**
*
* @return bool
*/
public function username_exists($value)
{
return $this->exist(array('username' => $value));
}
/**
*
* @return bool
*/
public function delete_by_username($value)
{
return $this->delete(array('username' => $value));
}
}

@ -0,0 +1,196 @@
<?php
/**
* Returns Shibboleth user's values based on Shibboleth's configuration.
* Shibboleth returns not only whether a user is authenticated but returns as
* well several paralemeter fields.
*
* If a user is not authenticated nothing is returned.
*
* @copyright 2010, University of Geneva
* @author laurent.opprecht@unige.ch, Nicolas Rod
* @license GNU, http://www.gnu.org/licenses/gpl.html
*/
class ShibbolethStore
{
/**
*
* @return ShibbolethData
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
/**
*
* @return ShibbolethConfig
*/
public static function config()
{
return Shibboleth::config();
}
public function get_unique_id()
{
return $this->get(__FUNCTION__);
}
/**
* If the user has more than one surname, it is possible depending of the user
* home organization that they are all given to the resource.
* In the case of the University of Geneva, with two surnames, three different values
* for the surname are sent. They are:
* 1) "givenname1"
* 2) "givenname2"
* 3) "givenname1 givenname2"
* meaning the string is as follow: "givenname1;givenname2;givenname1 givenname2"
*
* In such a case, the correct surname is the one which is followed by a space.
* This function tests if such a situation is encountered, and returns the first given name.
*
* @author Nicolas Rod
*/
public function get_firstname()
{
$result = $this->get(__FUNCTION__);
if (!is_array($result))
{
$result = ucfirst($result);
return $result;
}
foreach ($result as $name)
{
$parts = explode(' ', $name);
if (count($parts) > 1)
{
$result = reset($parts);
$result = ucfirst($result);
return $result;
}
}
$result = reset($result);
$result = ucfirst($result);
return $result;
}
public function get_lastname()
{
$result = $this->get(__FUNCTION__);
$result = ucfirst($result);
return $result;
}
public function get_email()
{
return $this->get(__FUNCTION__);
}
public function get_language()
{
return $this->get(__FUNCTION__);
}
public function get_gender()
{
return $this->get(__FUNCTION__);
}
public function get_address()
{
return $this->get(__FUNCTION__);
}
public function get_staff_category()
{
return $this->get(__FUNCTION__);
}
public function get_home_organization_type()
{
return $this->get(__FUNCTION__);
}
public function get_home_organization()
{
return $this->get(__FUNCTION__);
}
public function get_affiliation()
{
return $this->get(__FUNCTION__);
}
/**
* @return ShibbolethUser
*/
public function get_user()
{
$result = new ShibbolethUser();
foreach ($result as $key => $val)
{
$f = array($this, "get_$key");
if (is_callable($f))
{
$result->{$key} = call_user_func($f);
}
}
return $result;
}
/**
* Returns the shibboleth value stored in $_SERVER if it exists or $default if it is not the case.
*
* @param string $name the generic name. I.e. one of the class const.
* @param string $default default value if it is not provided by Shibboleth
* @return string
*/
public function get($name = '', $default = '')
{
$config = (array) Shibboleth::config();
if ($name)
{
$name = str_replace('get_', '', $name);
$shib_name = isset($config[$name]) ? $config[$name] : '';
if ($shib_name)
{
$result = isset($_SERVER[$shib_name]) ? $_SERVER[$shib_name] : $default;
$result = explode(';', $result);
if (empty($result))
{
$result = $default;
}
else if (count($result) == 1)
{
$result = reset($result);
}
else
{
$result = $result;
}
return $result;
}
}
$result = array();
foreach ($config as $key => $val)
{
$f = array($this, "get_$key");
if (is_callable($f))
{
$result[$key] = call_user_func($f);
}
}
return $result;
}
}

@ -0,0 +1,32 @@
<?php
/**
* Represent a Shibboleth user. Not to be missunderstand with a Chamilo user
* since they don't have the same attributes.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
class ShibbolethUser
{
public $unique_id = '';
public $firstname = '';
public $lastname = '';
public $email = '';
public $language = '';
public $gender = '';
public $address = '';
public $staff_category = '';
public $home_organization_type = '';
public $home_organization = '';
public $affiliation = '';
public $persistent_id = '';
public function is_empty()
{
return empty($this->unique_id);
}
}

@ -0,0 +1,85 @@
<?php
require_once dirname(__FILE__) . '/scaffold/user.class.php';
/**
* A Chamilo user. Model for the User table.
*
* Should be moved to the core. It only exists because it is not available through
* the API.
*
* The _User objet is generated by the scaffolder. User inherits from it to allow
* modifications without touching the generated file. Don't modify _User as
* it may change in the future. Instead add modifications to this class.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class User extends _User
{
}
/**
* Store for User objects. Interact with the database. Allows to save and retrieve
* user objects.
*
* Should be moved to the core. It only exists because it is not available through
* the API.
*
* The _UserStore objet is generated by the scaffolder. This class inherits from it to allow
* modifications without touching the generated file. Don't modify the _ object as
* it may change in the future. Instead add modifications to this class.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class UserStore extends _UserStore
{
function __construct()
{
parent::__construct();
ShibbolethUpgrade::update();
}
/**
*
* @param string $id
* @return User
*/
public function get_by_shibboleth_id($id)
{
return $this->get(array('shibb_unique_id' => $id));
}
public function shibboleth_id_exists($id)
{
return $this->exist(array('shibb_unique_id' => $id));
}
/**
*
* @param User $object
*/
protected function before_save($object)
{
$object->username = $object->username ? $object->username : $this->generate_username();
$object->password = $object->password ? $object->password : api_generate_password();
}
function generate_username()
{
$result = uniqid('s', true);
$result = str_replace('.', '', $result);
while ($this->username_exists($result))
{
$result = uniqid('s', true);
$result = str_replace('.', '', $result);
}
return $result;
}
}

@ -0,0 +1,286 @@
<?php
/**
* Shibboleth main class. Provides access to various Shibboleth sub components and
* provides the high level functionalities.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
class Shibboleth
{
const UNKNOWN_STATUS = -1;
const TEACHER_STATUS = 1;
const STUDENT_STATUS = 5;
static $config = null;
public static function format_status($status)
{
if ($status == Shibboleth::TEACHER_STATUS)
{
return 'Teacher';
}
else if ($status == Shibboleth::STUDENT_STATUS)
{
return 'Student';
}
else if ($status == Shibboleth::UNKNOWN_STATUS)
{
return 'Unknown';
}
else
{
return '???';
}
}
/**
*
* @return ShibbolethConfig
*/
public static function config()
{
self::$config = self::$config ? self::$config : new ShibbolethConfig();
return self::$config;
}
public static function set_config($config)
{
self::$config = $config;
}
/**
*
* @return ShibbolethSession
*/
public static function session()
{
return ShibbolethSession::instance();
}
/**
*
* @return ShibbolethStore
*/
public static function store()
{
return ShibbolethStore::instance();
}
/**
*
* @return ShibbolethDisplay
*/
public static function display()
{
return ShibbolethDisplay::instance();
}
public static function sys_path()
{
$path = dirname(__FILE__) . '/../';
return $path;
}
public static function url($path = '')
{
$result = api_get_path('WEB_PATH');
$result .= '/main/auth/shibboleth/' . $path;
return $result;
}
public static function redirect($url = '')
{
if (empty($url))
{
$url = isset($_SESSION['shibb_direct_url']) ? $_SESSION['shibb_direct_url'] : '';
unset($_SESSION['shibb_direct_url']);
/*
* Tests if the user tried to login directly in a protected course before to come here
* (this variable could be set in the modified code of /chamilo/inc/lib/main_api.lib.php)
*
* Note:
* this part was added to give the possibility to access Chamilo directly on a course URL from a link diplayed in a portal.
* This is not a direct Shibboleth related functionnality, but this could be used in a shibbolethized
* Dokeos installation, mainly if you have a SSO system in your network.
* Please note that the file /claroline/inc/lib/main_api.lib.php must be adapted to your Shibboleth settings
* If any interest or question, please contact Nicolas.Rod_at_adm.unige.ch
*
*/
if ($url)
{
//needed to log the user in his courses. Normally it is done by visiting /chamilo/index.php
$include_path = api_get_path(INCLUDE_PATH);
require("$include_path/local.inc.php");
if (strpos($url, '?') === false)
{
$url = "$url?";
}
$rootWeb = api_get_path('WEB_PATH');
$first_slash_pos = strpos($rootWeb, '/', 8);
$rootWeb_wo_uri = substr($rootWeb, 0, $first_slash_pos);
$url = $rootWeb_wo_uri . $course_url . '_stop';
header("Location: $url");
}
}
else
{
$_SESSION['request_uri'];
}
$url = api_get_path('WEB_PATH') . $url;
header("Location: $url");
die;
}
/**
*
* @param ShibbolethUser $user
*/
public static function save($shibb_user)
{
$shibb_user->status = self::infer_user_status($shibb_user);
$shibb_user->status_request = self::infer_status_request($shibb_user);
$shibb_user->shibb_unique_id = $shibb_user->unique_id;
$shibb_user->shibb_persistent_id = $shibb_user->persistent_id;
$user = User::store()->get_by_shibboleth_id($shibb_user->unique_id);
if (empty($user))
{
return User::create($shibb_user)->save();
}
$shibb_user->status_request = false;
$fields = self::config()->update_fields;
foreach ($fields as $key => $updatable)
{
if ($updatable)
{
$user->{$key} = $shibb_user->{$key};
}
}
$user->save();
return $result;
}
/**
* Infer the rights/status the user can have in Chamilo based on his affiliation attribute
*
* @param ShibbolethUser $user
* @return The Chamilo user status, one of TEACHER, STUDENT or UNKNOWN
*/
public static function infer_user_status($user)
{
$affiliations = $user->affiliation;
$affiliations = is_array($affiliations) ? $affiliations : array($affiliations);
$map = self::config()->affiliation_status;
$rights = array();
foreach ($affiliations as $affiliation)
{
$affiliation = strtolower($affiliation);
if (isset($map[$affiliation]))
{
$right = $map[$affiliation];
$rights[$right] = $right;
}
}
$teacher_status = isset($rights[self::TEACHER_STATUS]);
$student_status = isset($rights[self::STUDENT_STATUS]);
//if the user has got teacher rights, we doesn't check anything else
if ($teacher_status)
{
return self::TEACHER_STATUS;
}
if ($student_status)
{
return self::STUDENT_STATUS;
}
$result = self::config()->default_status;
$result = (int) $result;
$result = ($result == Shibboleth::TEACHER_STATUS || $result == Shibboleth::STUDENT_STATUS) ? $result : Shibboleth::UNKNOWN_STATUS;
return $result;
}
/**
* Return true if the user can ask for a greater status than student.
* This happens for staff members.
*
* @param ShibbolethUser $user
* @return boolean
*/
public static function infer_status_request($user)
{
if ($user->status == self::TEACHER_STATUS)
{
return false;
}
if ($user->status == self::UNKNOWN_STATUS)
{
return true;
}
$config = Shibboleth::config();
$affiliations = $user->affiliation;
$affiliations = is_array($affiliations) ? $affiliations : array($affiliations);
foreach ($affiliations as $affiliation)
{
$result = isset($config->affiliation_status_request[$affiliation]) ? $config->affiliation_status_request[$affiliation] : false;
if ($result)
{
return true;
}
}
return false;
}
/**
* Sends an email to the Chamilo and Shibboleth administrators in the name
* of the logged-in user.
*
*/
public static function email_admin($subject, $message)
{
$user = Shibboleth::session()->user();
$firstname = $user['firstname'];
$lastname = $user['lastname'];
$email = $user['email'];
$status = $user['status'];
$status = self::format_status($status);
$signagure = <<<EOT
_________________________
$firstname $lastname
$email
$status
EOT;
$message .= $signagure;
$header = "From: $email \n";
$shibb_admin_email = Shibboleth::config()->admnistrator_email;
if ($shibb_admin_email)
{
$header .= "Cc: $shibb_admin_email";
}
$administrator_email = get_setting('emailAdministrator');
$result = mail($administrator_email, $subject, $message);
return (bool) $result;
}
}

@ -0,0 +1,19 @@
<?php
/**
* Administratrive login. Useful when the standard login is not available anymore
* which is usually the case.
*
* This page allow administrators to log into the application using the standard
* Chamilo method when Shibboleth is not available.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
$dir = dirname(__FILE__);
include_once("$dir/../../init.php");
require_once api_get_path(LIBRARY_PATH).'userportal.lib.php';
ShibbolethController::instance()->admin_login();

@ -0,0 +1,19 @@
<?php
/**
* Display the Request another status/additional rights. The request is emailed
* to the shibboleth and platform administrators for processing.
*
* Users such as staff that can be either student or teachers are presented with
* this page upon first login.
*
* Other users - teachers, students - are directly logged-in.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
$dir = dirname(__FILE__);
include_once("$dir/../../init.php");
ShibbolethController::instance()->request_status();

@ -0,0 +1,64 @@
<?php
/**
* Utility display functions tailored for the Shibboleth pluging.
*
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ShibbolethDisplay
{
/**
*
* @return ShibbolethDisplay
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
public function error_page($message)
{
$include_path = api_get_path(INCLUDE_PATH);
require("$include_path/local.inc.php");
$page_title = get_lang('page_title');
Display :: display_header($page_title);
Display :: display_error_message($message);
Display :: display_footer();
die;
}
public function message_page($message, $title = '')
{
$include_path = api_get_path(INCLUDE_PATH);
require("$include_path/local.inc.php");
$title = $title ? $title : get_lang('page_title');
Display :: display_header($page_title);
Display :: display_confirmation_message($message);
Display :: display_footer();
die;
}
public function page($content, $title = '')
{
$include_path = api_get_path(INCLUDE_PATH);
require("$include_path/local.inc.php");
$title = $title ? $title : get_lang('page_title');
Display :: display_header($title);
echo $content;
Display :: display_footer();
die;
}
}

@ -0,0 +1,50 @@
<?php
/**
* Enter email form. When the email is mandatory and the Shibboleth email user field
* is empty the system display this form and ask the user to provide an email.
*
* @todo: add email validation
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
class ShibbolethEmailForm
{
/**
*
* @return ShibbolethEmailForm
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
function display()
{
$email = get_lang('email');
$submit = get_lang('submit');
return <<<EOT
<form id="email_form" action="" method="post">
<label for="">$email</label>
<input type="text" value="" tabindex="1" name="email" id="email_email" class=""><br/>
<input type="submit" value="$submit" tabindex="2" name="submit" id="email_submit" class="submit">
</form>
EOT;
}
function get_email()
{
return isset($_POST['email']) ? $_POST['email'] : '';
}
}

@ -0,0 +1,94 @@
<?php
/**
* Status request form. Display a form allowing the user to request additional
* rights/ another status.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
class ShibbolethStatusRequestForm
{
/**
*
* @return ShibbolethStatusRequestForm
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
function display()
{
if ($this->is_submitted() && $this->get_reason() == '')
{
$reason_is_mandatory = get_lang('reason_is_mandatory');
Display::display_error_message($reason_is_mandatory);
}
$status_request_message = get_lang('status_request_message');
$label_new_status = get_lang('new_status');
$label_reason = get_lang('reason');
$label_ok = get_lang('Ok');
$label_cancel = get_lang('Cancel');
$user = Shibboleth::session()->user();
$items = array();
if ($user['status'] == Shibboleth::UNKNOWN_STATUS)
{
$items[Shibboleth::STUDENT_STATUS] = get_lang('Student');
}
$items[Shibboleth::TEACHER_STATUS] = get_lang('Teacher');
$status_options = '';
foreach ($items as $key => $value)
{
$status_options.= "<option value=\"$key\">$value</option>";
}
return <<<EOT
<div id="askAccountText">
<p>$status_request_message</p>
</div>
<form method="post" action="request.php" id="status_request_form">
<input type="hidden" name="formPosted" value="true"/>
<label for="status">$label_new_status:</label>
<select name="status">
$status_options
</select>
<label for="reason">$label_reason:</label>
<textarea name="reason" style="min-width:400px; min-height:100px;"></textarea>
<p><input name="submit" type="submit" value="$label_ok" style="margin-right:10px;"/><input name="cancel" type="submit" value="$label_cancel" /></p>
</form>
EOT;
}
public function is_submitted()
{
return isset($_POST['submit']) ? $_POST['submit'] : false;
}
public function cancelled()
{
return isset($_POST['cancel']) ? $_POST['cancel'] : false;
}
function get_reason()
{
return isset($_POST['reason']) ? $_POST['reason'] : '';
}
function get_status()
{
return isset($_POST['status']) ? $_POST['status'] : '';
}
}

@ -0,0 +1,15 @@
<?php
/**
* Example of a config.php file. Not used. Configuration must appear in
* config.php.
*
* By default set up the aai configuration.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
require_once dirname(__FILE__) . '/config/aai.class.php';
Shibboleth::set_config(aai::config());

@ -0,0 +1,12 @@
<?php
/**
* Shibboleth configuration. See /config/aai.php for an example.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
require_once dirname(__FILE__) . '/config/aai.class.php';
Shibboleth::set_config(aai::config());

@ -0,0 +1,68 @@
<?php
/**
* Shibboleth configuration for the AAI federation.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class aai
{
/**
*
* @return ShibbolethConfig
*/
public static function config()
{
$result = new ShibbolethConfig();
$result->unique_id = 'Shib-SwissEP-UniqueID';
$result->firstname = 'Shib-InetOrgPerson-givenName';
$result->lastname = 'Shib-Person-surname';
$result->email = 'Shib-InetOrgPerson-mail';
$result->language = 'Shib-InetOrgPerson-preferredLanguage';
$result->gender = 'Shib-SwissEP-Gender';
$result->address = 'Shib-OrgPerson-postalAddress';
$result->staff_category = 'Shib-SwissEP-StaffCategory';
$result->home_organization_type = 'Shib-SwissEP-HomeOrganizationType';
$result->home_organization = 'Shib-SwissEP-HomeOrganization';
$result->affiliation = 'Shib-EP-Affiliation';
$result->persistent_id = 'persistent-id';
$result->default_status = Shibboleth::STUDENT_STATUS;
$result->affiliation_status = array(
'faculty' => Shibboleth::TEACHER_STATUS,
'member' => Shibboleth::STUDENT_STATUS,
'staff' => Shibboleth::STUDENT_STATUS,
'student' => Shibboleth::STUDENT_STATUS,
);
$result->update_fields = array(
'firstname' => false,
'lastname' => false,
'email' => true,
'status' => false,
'persistent_id' => true,
);
/*
* Persistent id should never change but it was introduced after unique id.
* So we update persistent id on login for those users who are still missing it.
*/
$result->is_email_mandatory = true;
$result->affiliation_status_request = array(
'faculty' => false,
'member' => false,
'staff' => true,
'student' => false,
);
$result->admnistrator_email = '';
return $result;
}
}

@ -0,0 +1,82 @@
<?php
/**
* Migrate the datatabase. Adds needed fields by Shibboleth to the User table.
* Upgrade is checked at each user login so there is no need to manually run
* an upgrade.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ShibbolethUpgrade
{
/**
* Create additional fields required by the shibboleth plugin if those
* are missing.
*/
public static function update()
{
static $done = false;
if ($done)
{
return false;
}
$done = true;
self::create_shibb_unique_id_field_if_missing();
self::create_shibb_persistent_id_field_if_missing();
}
/**
* Creates the 'shibb_unique_id' field in the table 'user' of the main Chamilo database if it doesn't exist yet
*
* @author Nicolas Rod
* @return void
*/
public static function create_shibb_unique_id_field_if_missing()
{
$db_name = Database :: get_main_database();
$sql = "SELECT * FROM `$db_name`.`user` LIMIT 1";
$result = Database::query($sql);
$row = mysql_fetch_assoc($result);
$exists = array_key_exists('shibb_unique_id', $row);
if ($exists)
{
return false;
}
//create the 'shibb_unique_id' field
$sql = "ALTER TABLE `$db_name`.`user` ADD `shibb_unique_id` VARCHAR( 60 ) AFTER `auth_source`";
$result_alter = Database::query($sql);
/*
* Index cannot be a UNIQUE index as it may exist users which don't log in through Shibboleth
* and therefore don't have any value for 'shibb_unique_id'
*/
$sql = "ALTER TABLE `$db_name`.`user` ADD INDEX ( `shibb_unique_id` )";
$result_alter = Database::query($sql);
}
public static function create_shibb_persistent_id_field_if_missing()
{
$db_name = Database :: get_main_database();
$sql = "SELECT * FROM $db_name.user LIMIT 1";
$result = Database::query($sql);
$row = mysql_fetch_assoc($result);
$exists = array_key_exists('shibb_persistent_id', $row);
if ($exists)
{
return false;
}
$sql = "ALTER table $db_name.user ADD COLUMN shibb_persistent_id varchar(255) NULL DEFAULT NULL;";
$result = api_sql_query($sql);
return (bool) $result;
}
}

@ -0,0 +1,9 @@
<?php
/**
* Display nothing. This ensure Apache doesn't display the list of files and folders
* when it is not propertly configured.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/

@ -0,0 +1,36 @@
<?php
/**
* Initialize the Shibboleth authentication system. All scripts that can be directly
* called must include this file
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
$__dir = dirname(__FILE__) . '/';
include_once($__dir . '/../../inc/global.inc.php');
require_once $__dir . 'app/lib/shibboleth_config.class.php';
require_once $__dir . 'app/lib/shibboleth_session.class.php';
require_once $__dir . 'app/lib/store.class.php';
require_once $__dir . 'app/controller/shibboleth_controller.class.php';
require_once $__dir . 'app/model/shibboleth_store.class.php';
require_once $__dir . 'app/model/shibboleth_user.class.php';
require_once $__dir . 'app/model/user.class.php';
require_once $__dir . 'app/view/shibboleth_email_form.class.php';
require_once $__dir . 'app/view/shibboleth_status_request_form.class.php';
require_once $__dir . 'app/view/shibboleth_display.class.php';
require_once $__dir . 'app/shibboleth.class.php';
require_once $__dir . 'db/shibboleth_upgrade.class.php';
require_once $__dir . 'config.php';
if (api_get_setting('server_type') == 'test')
{
include_once $__dir . '/test/shibboleth_test_helper.class.php';
include_once $__dir . '/test/shibboleth_test.class.php';
}
$language_files[] = 'shibboleth';

@ -0,0 +1,33 @@
<?php
/**
* Shibboleth login page.
*
* Actual authentication is provided by the Shibboleth Apache security module.
* Shibboleth must be properly installed and configured. Then this page must
* be secured through an Apache security directive.
*
* When Shibboleth is properly set up this page will only be available for
* authenticated users. The plugin ensure those people are created and logged in.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod
*/
include_once(dirname(__FILE__) . '/init.php');
/*
==============================================================================
TEST SECTION
==============================================================================
*
* @todo: Only for testing. Comment that out for production
*
*/
//Shibboleth::session()->logout();
//ShibbolethTest::helper()->setup_new_student_no_email();
//ShibbolethTest::helper()->setup_new_staff();
//ShibbolethTest::helper()->setup_new_teacher();
//ShibbolethTest::helper()->setup_new_student();
ShibbolethController::instance()->login();

@ -0,0 +1,35 @@
<?php
/**
* Scaffold script. Generates the required database models for the Shibboleth
* plugin.
*
* Will only run when the server is a test server.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$dir = dirname(__FILE__);
include_once($dir . '/../init.php');
include_once($dir . '/../app/lib/scaffolder/scaffolder.class.php');
if (!ShibbolethTest::is_enabled())
{
echo 'This is not a test server';
die;
}
if (!Shibboleth::session()->is_logged_in())
{
echo 'Not authorized';
die;
}
$name = 'user';
$result = Scaffolder::instance()->scaffold($name);
file_put_contents("$dir/output/$name.class.php", $result);
header('content-type: text/plain');
echo $result;

@ -0,0 +1,216 @@
<?php
/**
* Various Unit Tests. Note that those tests create users in the database but
* don't delete them.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ShibbolethTest
{
static function is_enabled()
{
return api_get_setting('server_type') == 'test';
}
/**
* @return ShibbolethTestHelper
*/
static function helper()
{
return ShibbolethTestHelper::instance();
}
static function init()
{
if (!self::is_enabled())
{
die;
}
}
static function test_new_teacher()
{
self::init();
self::helper()->setup_new_teacher();
$shib_user = Shibboleth::store()->get_user();
self::assert(!User::store()->shibboleth_id_exists($shib_user->unique_id));
Shibboleth::save($shib_user);
$user = User::store()->get_by_shibboleth_id($shib_user->unique_id);
self::assert($user->email == $shib_user->email);
self::assert($user->firstname == $shib_user->firstname);
self::assert($user->lastname == $shib_user->lastname);
self::assert($user->persistent_id == $shib_user->persistent_id);
self::assert($user->status == Shibboleth::TEACHER_STATUS);
self::assert(!empty($user->password));
self::assert(!empty($user->username));
}
static function test_new_student()
{
self::init();
self::helper()->setup_new_student();
$shib_user = Shibboleth::store()->get_user();
self::assert(!User::store()->shibboleth_id_exists($shib_user->unique_id));
Shibboleth::save($shib_user);
$user = User::store()->get_by_shibboleth_id($shib_user->unique_id);
self::assert($user->email == $shib_user->email);
self::assert($user->firstname == $shib_user->firstname);
self::assert($user->lastname == $shib_user->lastname);
self::assert($user->persistent_id == $shib_user->persistent_id);
self::assert($user->status == Shibboleth::STUDENT_STATUS);
self::assert(!empty($user->password));
self::assert(!empty($user->username));
}
static function test_new_staff()
{
self::init();
self::helper()->setup_new_staff();
$shib_user = Shibboleth::store()->get_user();
self::assert(!User::store()->shibboleth_id_exists($shib_user->unique_id));
Shibboleth::save($shib_user);
$user = User::store()->get_by_shibboleth_id($shib_user->unique_id);
self::assert($user->email == $shib_user->email);
self::assert($user->firstname == $shib_user->firstname);
self::assert($user->lastname == $shib_user->lastname);
self::assert($user->persistent_id == $shib_user->persistent_id);
self::assert($user->status == Shibboleth::STUDENT_STATUS);
self::assert(!empty($user->password));
self::assert(!empty($user->username));
}
static function test_new_infer_status_request()
{
self::init();
self::helper()->setup_new_staff();
$shib_user = Shibboleth::store()->get_user();
Shibboleth::save($shib_user);
self::assert($shib_user->status_request);
self::helper()->setup_new_teacher();
$shib_user = Shibboleth::store()->get_user();
Shibboleth::save($shib_user);
self::assert(!$shib_user->status_request);
self::helper()->setup_new_student();
$shib_user = Shibboleth::store()->get_user();
Shibboleth::save($shib_user);
self::assert(!$shib_user->status_request);
}
static function test_update_teacher()
{
self::init();
$fields = Shibboleth::config()->update_fields;
self::assert($fields['email']);
self::assert($fields['persistent_id']);
self::assert(!$fields['firstname']);
self::assert(!$fields['lastname']);
self::assert(!$fields['status']);
self::helper()->setup_teacher();
$shib_user = Shibboleth::store()->get_user();
Shibboleth::save($shib_user);
$new_shib_user = clone($shib_user);
$new_shib_user->firstname = 'frs';
$new_shib_user->lastname = 'ls';
$new_shib_user->email = 'em';
$new_shib_user->status = 10;
$new_shib_user->persistent_id = 'per';
Shibboleth::save($new_shib_user);
$user = User::store()->get_by_shibboleth_id($shib_user->unique_id);
self::assert($user->email == $new_shib_user->email);
self::assert($user->shibb_persistent_id == $new_shib_user->persistent_id);
self::assert($user->firstname == $shib_user->firstname);
self::assert($user->lastname == $shib_user->lastname);
self::assert($user->status == $shib_user->status);
self::assert(!empty($user->password));
self::assert(!empty($user->username));
}
static function test_new_student_multiple_givenname()
{
self::init();
self::helper()->setup_new_student_multiple_givenname();
$shib_user = Shibboleth::store()->get_user();
self::assert(!User::store()->shibboleth_id_exists($shib_user->unique_id));
Shibboleth::save($shib_user);
$user = User::store()->get_by_shibboleth_id($shib_user->unique_id);
self::assert($user->email == $shib_user->email);
self::assert($user->firstname == 'John');
self::assert($user->lastname == $shib_user->lastname);
self::assert($user->persistent_id == $shib_user->persistent_id);
self::assert($user->status == Shibboleth::STUDENT_STATUS);
self::assert(!empty($user->password));
self::assert(!empty($user->username));
}
static function test_new_no_affiliation_default()
{
self::init();
self::helper()->setup_new_no_affiliation();
$shib_user = Shibboleth::store()->get_user();
self::assert($config = Shibboleth::config()->default_status == Shibboleth::STUDENT_STATUS);
self::assert(!User::store()->shibboleth_id_exists($shib_user->unique_id));
self::assert($shib_user->affiliation == '');
Shibboleth::save($shib_user);
$user = User::store()->get_by_shibboleth_id($shib_user->unique_id);
self::assert($user->email == $shib_user->email);
self::assert($user->firstname == 'John');
self::assert($user->lastname == $shib_user->lastname);
self::assert($user->persistent_id == $shib_user->persistent_id);
self::assert($user->status == Shibboleth::STUDENT_STATUS);
self::assert(!empty($user->password));
self::assert(!empty($user->username));
}
static function assert($assertion, $message = '')
{
if (!$assertion)
{
$message = "Assert failed $message <br/>";
echo $message;
var_dump(debug_backtrace());
die;
}
else
{
$message = "Assert successful $message <br/>";
echo $message;
}
}
}

@ -0,0 +1,113 @@
<?php
/**
* Helper functions for the tests. Set up various dummy user types: teacher, student, etc.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class ShibbolethTestHelper
{
/**
*
* @return ShibbolethTestHelper
*/
public static function instance()
{
static $result = false;
if (empty($result))
{
$result = new self();
}
return $result;
}
public function setup_teacher()
{
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_1';
$_SERVER['Shib-EP-Affiliation'] = 'member;staff;faculty';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe';
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!drea34çcv3d';
}
public function setup_student()
{
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_1';
$_SERVER['Shib-EP-Affiliation'] = 'member';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe';
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!drea34çcv3d';
}
public function setup_new_student()
{
$id = uniqid();
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_' . $id;
$_SERVER['Shib-EP-Affiliation'] = 'member';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe' . $id;
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.' . $id . 'Doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!' . md5($id);
}
public function setup_new_student_no_email()
{
$id = uniqid();
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_' . $id;
$_SERVER['Shib-EP-Affiliation'] = 'member';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe' . $id;
$_SERVER['Shib-InetOrgPerson-mail'] = '';
$_SERVER['persistent-id'] = 'idp!viewer!' . md5($id);
}
public function setup_new_student_multiple_givenname()
{
$id = uniqid();
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_' . $id;
$_SERVER['Shib-EP-Affiliation'] = 'member';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John;Alex;John Alex';
$_SERVER['Shib-Person-surname'] = 'Doe' . $id;
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.' . $id . 'Doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!' . md5($id);
}
public function setup_new_teacher()
{
$id = uniqid();
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_' . $id;
$_SERVER['Shib-EP-Affiliation'] = 'member;staff;faculty';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe' . $id;
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.' . $id . 'Doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!' . md5($id);
}
public function setup_new_staff()
{
$id = uniqid();
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_' . $id;
$_SERVER['Shib-EP-Affiliation'] = 'member;staff';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe' . $id;
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.' . $id . 'Doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!' . md5($id);
}
public function setup_new_no_affiliation()
{
$id = uniqid();
$_SERVER['Shib-SwissEP-UniqueID'] = 'usr_' . $id;
$_SERVER['Shib-EP-Affiliation'] = '';
$_SERVER['Shib-InetOrgPerson-givenName'] = 'John';
$_SERVER['Shib-Person-surname'] = 'Doe' . $id;
$_SERVER['Shib-InetOrgPerson-mail'] = 'john.' . $id . 'Doe@localhost.org';
$_SERVER['persistent-id'] = 'idp!viewer!' . md5($id);
}
}

@ -0,0 +1,31 @@
<?php
/**
* Run unit tests. Server needs to be a test server to run those.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
include_once(dirname(__FILE__) . '/../init.php');
if (!ShibbolethTest::is_enabled())
{
echo 'This is not a test server';
die;
}
echo 'Test started<br/>-------------------<br/>';
ShibbolethTest::test_new_teacher();
ShibbolethTest::test_new_student();
ShibbolethTest::test_update_teacher();
ShibbolethTest::test_new_student_multiple_givenname();
ShibbolethTest::test_new_no_affiliation_default();
ShibbolethTest::test_new_staff();
ShibbolethTest::test_new_infer_status_request();
echo '-------------------<br/>Done!';

@ -0,0 +1,19 @@
<?php
/**
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
include_once(dirname(__FILE__) . '/../init.php');
if (!ShibbolethTest::is_enabled())
{
echo 'This is not a test server';
die;
}
Shibboleth::session()->logout();
ShibbolethTest::helper()->setup_new_student_no_email();
require_once dirname(__FILE__) . '/../login.php';

@ -0,0 +1,176 @@
<?php
/**
* Base class for plugins
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class Plugin
{
protected $version = '';
protected $author = '';
protected $fields = array();
protected function __construct($version, $author, $settings = array())
{
$this->version = $version;
$this->author = $author;
$this->fields = $settings;
global $language_files;
$language_files[] = 'plugin_' . $this->get_name();
}
function get_info()
{
$result = array();
$result['title'] = $this->get_title();
$result['comment'] = $this->get_comment();
$result['version'] = $this->get_version();
$result['author'] = $this->get_author();
if ($form = $this->get_settings_form())
{
$result['settings_form'] = $form;
foreach ($this->fields as $name => $type)
{
$value = $this->get($name);
$result[$name] = $value;
}
}
return $result;
}
function get_name()
{
$result = get_class($this);
$result = str_replace('Plugin', '', $result);
$result = strtolower($result);
return $result;
}
function get_title()
{
return $this->get_lang('plugin_title');
}
function get_comment()
{
return $this->get_lang('plugin_comment');
}
function get_version()
{
return $this->version;
}
function get_author()
{
return $this->author;
}
function get_css()
{
$name = $this->get_name();
$root = api_get_path(SYS_PLUGIN_PATH);
$path = "$root/$name/resources/$name.css";
if (!is_readable($path))
{
return '';
}
$css = array();
$css[] = file_get_contents($path);
$result = implode($css);
return $result;
}
/**
*
* @return FormValidator
*/
function get_settings_form()
{
$result = new FormValidator($this->get_name());
$defaults = array();
foreach ($this->fields as $name => $type)
{
$value = $this->get($name);
$defaults[$name] = $value;
$type = $type ? $type : 'text';
if ($type == 'wysiwyg')
{
$result->add_html_editor($name, $this->get_lang($name));
}
else
{
$result->addElement($type, $name, $this->get_lang($name));
}
}
$result->setDefaults($defaults);
$result->addElement('style_submit_button', 'submit_button', $this->get_lang('Save'));
return $result;
}
function get($name)
{
$content = '';
$title = 'Static';
$settings = $this->get_settings();
foreach ($settings as $setting)
{
if ($setting['variable'] == ($this->get_name() . '_' . $name))
{
return $setting['selected_value'];
}
}
return false;
}
private $settings = null;
public function get_settings()
{
if (is_null($this->settings))
{
$settings = api_get_settings_params(array("subkey = ? AND category = ? AND type = ? " => array($this->get_name(), 'Plugins', 'setting')));
$this->settings = $settings;
}
return $this->settings;
}
private $strings = null;
public function get_lang($name)
{
if (is_null($this->strings))
{
global $language_interface;
$root = api_get_path(SYS_PLUGIN_PATH);
$plugin_name = $this->get_name();
$language = $language_interface;
$path = "$root/$plugin_name/lang/$language.php";
if (is_readable($path))
{
include $path;
$this->strings = $strings;
}
else
{
$this->strings = array();
}
}
if (isset($this->strings[$name]))
{
return $this->strings[$name];
}
return get_lang($name);
}
}

@ -0,0 +1,25 @@
<?php
/**
* for more information: see languages.txt in the lang folder.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$no_login = 'The system was unable to log you in. Please contact your administrator.';
$page_title = 'Shibboleth Login';
$email = 'email';
$submit = 'submit';
$status = 'status';
$new_status = 'New status';
$reason = 'reason';
$request_status = 'Request new status';
$status_request_message = 'You have been logged-in with default rights. If you can request more rights by submitting the following request.';
$reason_is_mandatory = 'You reason field is mandatory. Please fill it in before submitting.';
$request_submitted = 'Your request has been submitted.';
$request_failed = 'We appologize but we are not ableto fulfill your request at this time. Please contact your administrator.';
$internal_login = 'Internal login';
$already_logged_in = 'You are already logged in';
$Pass = 'Password';

@ -0,0 +1,24 @@
<?php
/**
* for more information: see languages.txt in the lang folder.
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$no_login = "Le systéme n'a pas réussi à vous idenditfier. Veuiller contacter votre adminstrateur.";
$page_title = 'Login Shibboleth';
$email = 'Email';
$submit = 'Envoyer';
$new_status = 'Nouveau status';
$reason = 'Raison';
$request_status = 'Demande de nouveau status';
$status_request_message = 'Vous avez été enregistré avec les droits par défaut. Si vous le souhaitez vous pouvez remplir le formulaire ci-dessous pour demander plus de droits à votre administrateur.';
$reason_is_mandatory = 'Le champs "raison" est obligatoire. Veuillez remplir ce champs avant de soumettre votre formulaire.';
$request_submitted = 'Votre requête à été soumise. Elle sera traitée prochainement.';
$request_failed = "Nous ne sommes malheureusement pas en mesure de traiter votre demande pour le moment. Veuillez s'il vous plait prendre contacte avec votre administrateur ou réessayer à une date ultérieur.";
$internal_login = 'Login Interne';
$already_logged_in = 'Vous êtes déjà connecté';
$Pass = 'Mot de passe';

@ -0,0 +1,59 @@
<?php
$plugin = RssPlugin::create();
$rss = $plugin->get_rss();
$title = $plugin->get_block_title();
$title = $title ? "<h4>$title</h4>" : '';
$css = $plugin->get_css();
$css = $css ? "<style type=\"text/css\" scoped=\"scoped\">$css</style>" : '';
$bullet = api_get_path(WEB_PLUGIN_PATH) . '/rss/resources/arrow-bullet.png';
if (empty($rss))
{
echo get_lang('no_rss');
return;
}
echo<<<EOT
<div class="well sidebar-nav rss">
$css
<style type="text/css" scoped="scoped">
.gfg-listentry-highlight{
background-image: url('$bullet');
}
</style>
<div class="menusection">
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script src="http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js" type="text/javascript"></script>
<script type="text/javascript">
google.load('feeds', '1');
function OnLoad() {
var feeds = [
{
url: '$rss'
}
];
var options = {
stacked : true,
numResults : 5,
horizontal : false,
title : 'Nouvelles!'
};
new GFdynamicFeedControl(feeds, 'news', options);
}
google.setOnLoadCallback(OnLoad);
</script>
$title
<div id="news" class="" style="min-height:300px;"></div>
</div>
</div>
EOT;

@ -0,0 +1,16 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$strings['plugin_title'] = "Rss";
$strings['plugin_comment'] = "Display rss content.";
$strings['rss'] = "Rss";
$strings['block_title'] = "Block title";
$strings['title'] = "Title";
$strings['no_rss'] = "There is no RSS configured. Please add a RSS";

@ -0,0 +1,13 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$strings['plugin_title'] = "Rss";
$strings['plugin_comment'] = "Affiche le contenu de flux rss.";
$strings['title'] = "Titre";
$strings['no_rss'] = "Veuillez configurer";

@ -0,0 +1,38 @@
<?php
/**
* Description of
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class RssPlugin extends Plugin
{
/**
*
* @return RssPlugin
*/
static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
function get_block_title()
{
return $this->get('block_title');
}
function get_rss()
{
return $this->get('rss');
}
protected function __construct()
{
parent::__construct('1.1', 'Laurent Opprecht', array('block_title' => 'text', 'rss' => 'text'));
}
}

@ -0,0 +1,16 @@
<?php
/**
*
* @see http://www.google.com/uds/solutions/dynamicfeed/index.html
*
* @copyright (c) 2011 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht
*/
require_once api_get_path(LIBRARY_PATH) . '/plugin.class.php';
require_once dirname(__FILE__) . '/lib/rss_plugin.class.php';
$plugin_info = RssPlugin::create()->get_info();

@ -0,0 +1,4 @@
Display RSS feeds using the Google Dynamic Feed control.
<p>
See http://www.google.com/uds/solutions/dynamicfeed/index.html for further information.
</p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,41 @@
.gfg-root a:link,
.gfg-root a:visited,
.gfg-root a:focus,
.gfg-root a:active
{
color: #CC0066;
}
.gfg-subtitle, .gfg-title{
background-color: #CC0066 !important;
color: #FFFFFF !important;
}
.gfg-subtitle > a{
color: #FFFFFF !important;
}
.gfg-subtitle > a:hover{
color: black !important;
}
.gfg-root a:hover, .gfg-subtitle:hover {
color: black;
}
.gfg-listentry-odd:hover{
background-color: #E9E9F0 !important;
}
.gfg-listentry-even:hover{
background-color: #E9E9F0 !important;
}
.gfg-horizontal-root .gfg-entry .gf-result, .gfg-horizontal-root .gfg-entry, .gfg-horizontal-root .gf-snippet{
background-color: white !important;
}
.gfg-horizontal-root .gfg-entry {
background-color: white !important;
}

@ -0,0 +1,103 @@
@import url(http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css);
.well.sidebar-nav.rss
{
}
/*google feeds*/
.gfg-listentry-highlight,
.gfg-listentry
{
background-position: left center;
background-repeat: no-repeat;
padding-left: 20px;
}
.gfg-root a:link,
.gfg-root a:visited,
.gfg-root a:focus,
.gfg-root a:active
{
font-weight: normal;
text-decoration: none;
}
.gfg-root {
font-family: Verdana,Geneva,Arial,Helvetica,sans-serif !important;
border-left:0px;
border-right:0px;
border-top:0px ;
}
.gfg-listentry {
line-height: 14px !important;
}
.gfg-listentry{
white-space: normal;
}
.gfg-subtitle, .gfg-title{
font-weight: bold ;
}
.gfg-title{
display: none;
}
.gfg-subtitle a:link, .gfg-title a:link{
font-weight: bold;
}
.gfg-root .gfg-entry .gf-result .gf-title{
white-space: normal !important;
}
.gfg-entry{
height:9.5em !important;
/* border: 1px solid grey;
border-radius: 8px 8px 8px 8px;
margin:2px;*/
}
.gfg-root, .gfg-entry, .gf-result, .gf-snippet{
background-color: transparent !important;
}
.gfg-root a:hover, .gfg-subtitle:hover {
text-decoration: none;
}
.gfg-listentry{
height: auto;
padding-top:4px;
padding-bottom: 4px;
border-bottom-style: dotted;
border-bottom-width: 1px;
}
.gfg-listentry-odd {
background-color: transparent !important;
}
.gf-author, .gf-relativePublishedDate, .gf-spacer{
display:none !important;
}
.gfg-horizontal-root .gfg-entry .gf-result .gf-snippet {
display: block;
clear:both;
}
.gfg-branding{
display:none;
}
.gfg-horizontal-root{
height: auto;
border:none;
}
.gfg-horizontal-container{
display:inline;
}

@ -0,0 +1,5 @@
<?php
require_once dirname(__FILE__) . '/lib/search_course_widget.class.php';
$widget = new SearchCourseWidget();
$widget->run();

@ -0,0 +1,10 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$strings['plugin_title'] = "Search Course";
$strings['plugin_comment'] = "Allow to search the course catalog and register to courses.";

@ -0,0 +1,10 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$strings['plugin_title'] = "Rechercher un cours";
$strings['plugin_comment'] = "Permets de rechercher un cours dans le catalogue et de s'inscrire.";

@ -0,0 +1,163 @@
<?php
/**
* Register course widget.
* Handles user's registration action.
* Display a register to course form if required.
*
* @copyright (c) 2011 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht
*/
class RegisterCourseWidget
{
const ACTION_SUBSCRIBE = 'subscribe';
const PARAM_SUBSCRIBE = 'subscribe';
const PARAM_PASSCODE = 'course_registration_code';
/**
* Returns $_POST data for $key is it exists or $default otherwise.
*
* @param string $key
* @param object $default
* @return string
*/
public static function post($key, $default = '')
{
return isset($_POST[$key]) ? $_POST[$key] : $default;
}
/**
* Returns $_GET data for $key is it exists or $default otherwise.
*
* @param string $key
* @param object $default
* @return string
*/
public static function get($key, $default = '')
{
return isset($_GET[$key]) ? $_GET[$key] : $default;
}
/**
*
* @return RegisterCourseWidget
*/
public static function factory()
{
return new self();
}
function run()
{
return $this->action_subscribe_user();
}
/**
* Handle the subscribe action.
*
* @return bool
*/
function action_subscribe_user()
{
$action = self::get('action');
if ($action != self::ACTION_SUBSCRIBE)
{
return false;
}
$course_code = self::post(self::PARAM_SUBSCRIBE);
if (empty($course_code))
{
return false;
}
$registration_code = self::post(self::PARAM_PASSCODE);
if ($this->subscribe_user($course_code, $registration_code))
{
Display::display_confirmation_message(get_lang('EnrollToCourseSuccessful'));
return;
}
if (!empty($registration_code))
{
Display::display_error_message(get_lang('CourseRegistrationCodeIncorrect'));
}
$this->display_form($course_code);
return true;
}
/**
* Regiser a user to a course.
* Returns true on success, false otherwise.
*
* @param string $course_code
* @param string $registration_code
* @param int $user_id
* @return bool
*/
function subscribe_user($course_code, $registration_code = '', $user_id = null)
{
$course = $this->retrieve_course($course_code);
$course_regisration_code = $course['registration_code'];
if (!empty($course_regisration_code) && $registration_code != $course_regisration_code)
{
return false;
}
if (empty($user_id))
{
global $_user;
$user_id = $_user['user_id'];
}
return (bool) CourseManager::add_user_to_course($user_id, $course_code);
}
/**
* Display the course registration form.
* Asks for registration code/password.
*
* @param string $course_code
*/
function display_form($course_code)
{
global $stok;
$course = $this->retrieve_course($course_code);
$self = $_SERVER['REQUEST_URI'];
$course_code = $course['code'];
$course_visual_code = $course['visual_code'];
$course_title = $course['title'];
$submit_registration_code_label = get_lang("SubmitRegistrationCode");
$course_requires_password_label = get_lang('CourseRequiresPassword');
$result = <<<EOT
$course_requires_password_label<br/>
$course_visual_code - $course_title
<form action="$self" method="post">
<input type="hidden" name="sec_token" value="$stok" />
<input type="hidden" name="subscribe" value="$course_code" />
<input type="text" name="course_registration_code" value="$registration_code" />
<input type="Submit" name="submit_course_registration_code" value="OK" alt="$submit_registration_code_label" /></form>
EOT;
echo $result;
}
/**
* DB functions - DB functions - DB functions
*/
/**
*
* @param type $course_code
* @return type
*/
function retrieve_course($course_code)
{
require_once api_get_path(SYS_PATH) . '/main/inc/lib/course.lib.php';
return CourseManager::get_course_information($course_code);
}
}

@ -0,0 +1,33 @@
<?php
/**
* Description of SearchCoursePlugin
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class SearchCoursePlugin extends Plugin
{
/**
*
* @return SearchCoursePlugin
*/
static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
function get_name()
{
return 'search_course';
}
protected function __construct()
{
parent::__construct('1.1', 'Laurent Opprecht');
}
}

@ -0,0 +1,435 @@
<?php
require_once dirname(__FILE__) . '/register_course_widget.class.php';
/**
* Search course widget.
* Display a search form and a list of courses that matches the search.
*
* @copyright (c) 2011 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht
*/
class SearchCourseWidget
{
const PARAM_ACTION = 'action';
const ACTION_SUBSCRIBE = 'subscribe';
/**
* Returns $_POST data for $key is it exists or $default otherwise.
*
* @param string $key
* @param object $default
* @return string
*/
public static function post($key, $default = '')
{
return isset($_POST[$key]) ? $_POST[$key] : $default;
}
/**
* Returns $_GET data for $key is it exists or $default otherwise.
*
* @param string $key
* @param object $default
* @return string
*/
public static function get($key, $default = '')
{
return isset($_GET[$key]) ? $_GET[$key] : $default;
}
public static function server($key, $default = '')
{
return isset($_SERVER[$key]) ? $_SERVER[$key] : $default;
}
public static function get_lang($name)
{
return SearchCoursePlugin::create()->get_lang($name);
}
/**
*
* @return bool
*/
function is_homepage()
{
$url = self::server('REQUEST_URI');
$url = explode('?', $url);
$url = reset($url);
$url = self::server('SERVER_NAME') . $url;
$root = api_get_path('WEB_PATH');
$root = str_replace('https://', '', $root);
$root = str_replace('http://', '', $root);
$index_url = $root . 'index.php';
return $url == $index_url || $url == $root;
}
/**
*
* @return bool
*/
function is_user_portal()
{
$url = self::server('REQUEST_URI');
$url = explode('?', $url);
$url = reset($url);
$url = self::server('SERVER_NAME') . $url;
$root = api_get_path('WEB_PATH');
$root = str_replace('https://', '', $root);
$root = str_replace('http://', '', $root);
$index_url = $root . 'user_portal.php';
return $url == $index_url || $url == $root;
}
/**
*
*/
function accept()
{
return $this->is_homepage() || $this->is_user_portal();
}
/**
* Display the search course widget:
*
* Title
* Search form
*
* Search results
*/
function run()
{
if (!$this->accept())
{
return;
}
$this->display_header();
$this->display_form();
$search_term = self::post('search_term');
$action = self::get('action');
$has_content = !empty($search_term) || !empty($action);
if ($has_content)
{
echo '<div class="list">';
}
else
{
echo '<div>';
}
if (RegisterCourseWidget::factory()->run())
{
$result = true;
}
else
{
$result = $this->action_display();
}
echo '</div>';
$this->display_footer();
return $result;
}
function get_url($action = '')
{
$self = $_SERVER['PHP_SELF'];
$parameters = array();
if ($action)
{
$parameters[self::PARAM_ACTION] = $action;
}
$parameters = implode('&', $parameters);
$parameters = $parameters ? '?' . $parameters : '';
return $self . $parameters;
}
/**
* Handle the display action
*/
function action_display()
{
global $charset;
$search_term = self::post('search_term');
if ($search_term)
{
$search_result_for_label = self::get_lang('SearchResultsFor');
$search_term_html = htmlentities($search_term, ENT_QUOTES, $charset);
echo "<h5>$search_result_for_label $search_term_html</h5>";
$courses = $this->retrieve_courses($search_term);
$this->display_list($courses);
}
return true;
}
function display_header()
{
$search_course_label = self::get_lang('SearchCourse');
echo <<<EOT
<div class="well course_search">
<div class="menusection">
<h4>$search_course_label</h4>
EOT;
}
function display_footer()
{
echo '</div></div>';
}
/**
* Display the search course form.
*/
function display_form()
{
global $stok;
$search_label = self::get_lang('_search');
$self = api_get_self();
$search_term = self::post('search_term');
$form = <<<EOT
<form class="course_list" method="post" action="$self">
<input type="hidden" name="sec_token" value="$stok" />
<input type="hidden" name="search_course" value="1" />
<input type="text" name="search_term" size="55" value="$search_term" />
&nbsp;<input type="submit" value="$search_label" />
</form>
EOT;
echo $form;
}
/**
*
* @param array $courses
* @return bool
*/
function display_list($courses)
{
if (empty($courses))
{
return false;
}
$user_courses = $this->retrieve_user_courses();
$display_coursecode = (get_setting('display_coursecode_in_courselist') == 'true');
$display_teacher = (get_setting('display_teacher_in_courselist') == 'true');
echo '<table cellpadding="4">';
foreach ($courses as $key => $course)
{
$details = array();
if ($display_coursecode)
{
$details[] = $course['visual_code'];
}
if ($display_teacher)
{
$details[] = $course['tutor'];
}
$details = implode(' - ', $details);
$title = $course['title'];
$href = api_get_path(WEB_PATH) . 'courses/' . $course['code'];
echo '<tr><td><b><a href="' . $href . '">' . "$title</a></b><br/>$details</td><td>";
if ($course['registration_code'])
{
Display::display_icon('passwordprotected.png', '', array('style' => 'float:left;'));
}
$this->display_subscribe_icon($course, $user_courses);
echo '</td></tr>';
}
echo '</table>';
return true;
}
/**
* Displays the subscribe icon if subscribing is allowed and
* if the user is not yet subscribed to this course
*
* @global type $stok
* @param array $current_course
* @param array $user_courses
* @return bool
*/
function display_subscribe_icon($current_course, $user_courses)
{
global $stok;
//Already subscribed
$code = $current_course['code'];
if (isset($user_courses[$code]))
{
echo self::get_lang('AlreadySubscribed');
return false;
}
//Not authorized to subscribe
if ($current_course['subscribe'] != SUBSCRIBE_ALLOWED)
{
echo self::get_lang('SubscribingNotAllowed');
return false;
}
//Subscribe form
$self = $_SERVER['PHP_SELF'];
echo <<<EOT
<form action="$self?action=subscribe" method="post">
<input type="hidden" name="sec_token" value="$stok" />
<input type="hidden" name="subscribe" value="$code" />
EOT;
$search_term = $this->post('search_term');
if ($search_term)
{
$search_term = Security::remove_XSS($search_term);
echo <<<EOT
<input type="hidden" name="search_course" value="1" />
<input type="hidden" name="search_term" value="$search_term" />
EOT;
}
$web_path = api_get_path(WEB_PATH);
$subscribe_label = get_lang('Subscribe');
echo <<<EOT
<input type="image" name="unsub" src="$web_path/main/img/enroll.gif" alt="$subscribe_label" />$subscribe_label
</form>
EOT;
return true;
}
/**
* DB functions - DB functions - DB functions
*/
/**
* Search courses that match the search term.
* Search is done on the code, title and tutor fields.
*
* @param string $search_term
* @return array
*/
function retrieve_courses($search_term)
{
if (empty($search_term))
{
return array();
}
$search_term = Database::escape_string($search_term);
$course_table = Database::get_main_table(TABLE_MAIN_COURSE);
$sql = <<<EOT
SELECT * FROM $course_table
WHERE code LIKE '%$search_term%' OR visual_code LIKE '%$search_term%' OR title LIKE '%$search_term%' OR tutor_name LIKE '%$search_term%'
ORDER BY title, visual_code ASC
EOT;
$result = array();
$resultset = api_sql_query($sql, __FILE__, __LINE__);
while ($row = Database::fetch_array($resultset))
{
$code = $row['code'];
$result[$code] = array(
'code' => $code,
'directory' => $row['directory'],
'db' => $row['db_name'],
'visual_code' => $row['visual_code'],
'title' => $row['title'],
'tutor' => $row['tutor_name'],
'subscribe' => $row['subscribe'],
'unsubscribe' => $row['unsubscribe']
);
}
return $result;
}
/**
* Retrieves courses that the user is subscribed to
*
* @param int $user_id
* @return array
*/
function retrieve_user_courses($user_id = null)
{
if (is_null($user_id))
{
global $_user;
$user_id = $_user['user_id'];
}
$course_table = Database::get_main_table(TABLE_MAIN_COURSE);
$user_course_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$user_id = intval($user_id);
$sql_select_courses = "SELECT course.code k, course.visual_code vc, course.subscribe subscr, course.unsubscribe unsubscr,
course.title i, course.tutor_name t, course.db_name db, course.directory dir, course_rel_user.status status,
course_rel_user.sort sort, course_rel_user.user_course_cat user_course_cat
FROM $course_table course, $user_course_table course_rel_user
WHERE course.code = course_rel_user.course_code
AND course_rel_user.user_id = $user_id
ORDER BY course_rel_user.sort ASC";
$result = array();
$resultset = api_sql_query($sql_select_courses, __FILE__, __LINE__);
while ($row = Database::fetch_array($resultset))
{
$code = $row['k'];
$result[$code] = array(
'db' => $row['db'],
'code' => $code,
'visual_code' => $row['vc'],
'title' => $row['i'],
'directory' => $row['dir'],
'status' => $row['status'],
'tutor' => $row['t'],
'subscribe' => $row['subscr'],
'unsubscribe' => $row['unsubscr'],
'sort' => $row['sort'],
'user_course_category' => $row['user_course_cat']);
}
return $result;
}
/*
* Utility functions - Utility functions - Utility functions
*/
/**
* Removes from $courses all courses the user is subscribed to.
*
* @global array $_user
* @param array $courses
* @return array
*/
function filter_out_user_courses($courses)
{
if (empty($courses))
{
return $courses;
}
global $_user;
$user_id = $_user['user_id'];
$user_courses = $this->retrieve_user_courses($user_id);
foreach ($user_courses as $key => $value)
{
unset($courses[$key]);
}
return $courses;
}
}

@ -0,0 +1,11 @@
<?php
/**
* @copyright (c) 2011 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht
*/
require_once api_get_path(LIBRARY_PATH) . '/plugin.class.php';
require_once dirname(__FILE__) . '/lib/search_course_plugin.class.php';
$plugin_info = SearchCoursePlugin::create()->get_info();

@ -0,0 +1 @@
Search courses in the main catalogue and register.

@ -0,0 +1,28 @@
<?php
$plugin = StaticPlugin::create();
$content = $plugin->get_content();
$title = $plugin->get_block_title();
$title = $title ? "<h4>$title</h4>" : '';
$css = $plugin->get_css();
$css = $css ? "<style type=\"text/css\" scoped=\"scoped\">$css</style>" : '';
if (empty($content))
{
echo '';
}
echo <<<EOT
<div class="well sidebar-nav static">
$css
<div class="menusection">
$title
<div class="content">
$content
</div>
</div>
</div>
EOT;

@ -0,0 +1,15 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$strings['plugin_title'] = "Static";
$strings['plugin_comment'] = "Display static html content.";
$strings['content'] = "Content";
$strings['block_title'] = "Block title";
//$strings['title'] = "Title";

@ -0,0 +1,13 @@
<?php
/**
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
$strings['plugin_title'] = "Statique";
$strings['plugin_comment'] = "Affiche du contenu html.";
$strings['content'] = "Contenu";
$strings['block_title'] = "Titre du bloc";

@ -0,0 +1,38 @@
<?php
/**
* Description of static_plugin
*
* @copyright (c) 2012 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht <laurent@opprecht.info>
*/
class StaticPlugin extends Plugin
{
/**
*
* @return StaticPlugin
*/
static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
function get_block_title()
{
return $this->get('block_title');
}
function get_content()
{
return $this->get('content');
}
protected function __construct()
{
parent::__construct('1.1', 'Laurent Opprecht', array('block_title' => 'text', 'content' => 'wysiwyg'));
}
}

@ -0,0 +1,12 @@
<?php
/**
* @copyright (c) 2011 University of Geneva
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
* @author Laurent Opprecht
*/
require_once api_get_path(LIBRARY_PATH) . '/plugin.class.php';
require_once dirname(__FILE__) . '/lib/static_plugin.class.php';
$plugin_info = StaticPlugin::create()->get_info();

@ -0,0 +1 @@
Display static content.

@ -0,0 +1,4 @@
.well.sidebar-nav.rss
{
}
Loading…
Cancel
Save