skala
Julio Montoya 14 years ago
commit 22c9680350
  1. 4
      .hgignore
  2. 6
      custompages/index-unlogged.php
  3. 2
      custompages/style.css
  4. 7
      documentation/credits.html
  5. 5
      index.php
  6. 12
      main/auth/shibboleth/_readme.txt
  7. 153
      main/auth/shibboleth/app/controller/shibboleth_controller.class.php
  8. 18
      main/auth/shibboleth/app/lib/model.class.php
  9. 63
      main/auth/shibboleth/app/lib/scaffolder/scaffolder.class.php
  10. 145
      main/auth/shibboleth/app/lib/scaffolder/template/default.php
  11. 145
      main/auth/shibboleth/app/lib/scaffolder/template/model.php
  12. 38
      main/auth/shibboleth/app/lib/scaffolder/template/public.php
  13. 60
      main/auth/shibboleth/app/lib/shibboleth_config.class.php
  14. 82
      main/auth/shibboleth/app/lib/shibboleth_session.class.php
  15. 351
      main/auth/shibboleth/app/lib/store.class.php
  16. 186
      main/auth/shibboleth/app/model/scaffold/user.class.php
  17. 196
      main/auth/shibboleth/app/model/shibboleth_store.class.php
  18. 32
      main/auth/shibboleth/app/model/shibboleth_user.class.php
  19. 85
      main/auth/shibboleth/app/model/user.class.php
  20. 286
      main/auth/shibboleth/app/shibboleth.class.php
  21. 19
      main/auth/shibboleth/app/view/admin_login.php
  22. 19
      main/auth/shibboleth/app/view/request.php
  23. 64
      main/auth/shibboleth/app/view/shibboleth_display.class.php
  24. 50
      main/auth/shibboleth/app/view/shibboleth_email_form.class.php
  25. 94
      main/auth/shibboleth/app/view/shibboleth_status_request_form.class.php
  26. 15
      main/auth/shibboleth/config-dist.php
  27. 12
      main/auth/shibboleth/config.php
  28. 68
      main/auth/shibboleth/config/aai.class.php
  29. 82
      main/auth/shibboleth/db/shibboleth_upgrade.class.php
  30. 9
      main/auth/shibboleth/index.php
  31. 36
      main/auth/shibboleth/init.php
  32. 33
      main/auth/shibboleth/login.php
  33. 0
      main/auth/shibboleth/script/output/user.class.php
  34. 35
      main/auth/shibboleth/script/scaffold.php
  35. 216
      main/auth/shibboleth/test/shibboleth_test.class.php
  36. 113
      main/auth/shibboleth/test/shibboleth_test_helper.class.php
  37. 31
      main/auth/shibboleth/test/test.php
  38. 19
      main/auth/shibboleth/test/test_no_email.php
  39. 2
      main/calendar/agenda_js.php
  40. BIN
      main/document/Wami.swf
  41. 14
      main/document/document.php
  42. 9
      main/document/record_audio.php
  43. 199
      main/document/record_audio_wami.php
  44. 72
      main/document/save_pixlr.php
  45. 33
      main/inc/lib/nanogong/receiver.php
  46. 176
      main/inc/lib/plugin.class.php
  47. 2
      main/inc/lib/svg-edit/extensions/filesave.php
  48. 14
      main/inc/lib/userportal.lib.php
  49. BIN
      main/inc/lib/wami-recorder/Wami.swf
  50. BIN
      main/inc/lib/wami-recorder/buttons.png
  51. 349
      main/inc/lib/wami-recorder/gui.js
  52. 6
      main/inc/lib/wami-recorder/index.html
  53. 64
      main/inc/lib/wami-recorder/record_document.php
  54. 273
      main/inc/lib/wami-recorder/recorder.js
  55. 7
      main/install/db_main.sql
  56. 5
      main/install/migrate-db-1.8.8-1.9.0-pre.sql
  57. 25
      main/lang/english/shibboleth.inc.php
  58. 24
      main/lang/french/shibboleth.inc.php
  59. 4
      main/template/default/layout/hot_courses.tpl
  60. 59
      plugin/rss/index.php
  61. 16
      plugin/rss/lang/english.php
  62. 13
      plugin/rss/lang/french.php
  63. 38
      plugin/rss/lib/rss_plugin.class.php
  64. 16
      plugin/rss/plugin.php
  65. 4
      plugin/rss/readme.txt
  66. BIN
      plugin/rss/resources/arrow-bullet.png
  67. 41
      plugin/rss/resources/color.css
  68. 103
      plugin/rss/resources/rss.css
  69. 5
      plugin/search_course/index.php
  70. 10
      plugin/search_course/lang/english.php
  71. 10
      plugin/search_course/lang/french.php
  72. 163
      plugin/search_course/lib/register_course_widget.class.php
  73. 33
      plugin/search_course/lib/search_course_plugin.class.php
  74. 435
      plugin/search_course/lib/search_course_widget.class.php
  75. 11
      plugin/search_course/plugin.php
  76. 1
      plugin/search_course/readme.txt
  77. 28
      plugin/static/index.php
  78. 15
      plugin/static/lang/english.php
  79. 13
      plugin/static/lang/french.php
  80. 38
      plugin/static/lib/static_plugin.class.php
  81. 12
      plugin/static/plugin.php
  82. 1
      plugin/static/readme.txt
  83. 4
      plugin/static/resources/static.css

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

@ -29,13 +29,14 @@ if (isset($_GET['loginFailed'])){
<title>Custompage - login</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--[if !IE 6]><!-->
<link rel="stylesheet" type="text/css" href="/custompages/style.css" />
<link rel="stylesheet" type="text/css" href="custompages/style.css" />
<!--<![endif]-->
<!--[if IE 6]>
<link rel="stylesheet" type="text/css" href="/custompages/style-ie6.css" />
<![endif]-->
<script type="text/javascript" src="/custompages/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="custompages/jquery-1.5.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
if (top.location != location)
@ -87,5 +88,6 @@ if (isset($_GET['loginFailed'])){
<img src="<?php echo api_get_path(WEB_PATH)?>/custompages/images/footer.png" />
</div> <!-- #footer -->
</div> <!-- #wrapper -->
</body>
</html>

@ -87,7 +87,7 @@ body {
*/
}
#backgroundimage {
#backgroundimage {
background-attachment:fixed;
width: 100%;
height: 100%;

@ -579,6 +579,13 @@ These institutions and companies have either contributed to the Chamilo project
<li>Formascience, Strasbourg, France</li>
<li>IPYS, Lima, Peru</li>
<li>Imag'in, Nouméa, New Caledony</li>
<li>Vall d'Hebron Hospital, Barcelona, Spain</li>
<li>Université de Genève, Geneva, Switzerland</li>
<li>Université de Grenoble, Grenoble, France</li>
<li>ESIAJ, Namur, Belgique</li>
<li>Unidad Editorial, Spain</li>
<li>Académie d'Aix-Marseilles, France</li>
<li>Commission Scolaire des Hautes-Rivières, project TIC-FP, Canada</li>
</ul>

@ -122,11 +122,8 @@ if (!empty($_POST['submitAuth'])) {
event_open();
}
//@todo add this in the template
if (api_get_setting('display_categories_on_homepage') == 'true') {
echo '<div class="home_cats">';
$controller->display_anonymous_course_list();
echo '</div>';
$controller->tpl->assign('content', $controller->display_anonymous_course_list());
}
$controller->set_login_form();

@ -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($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';

@ -19,6 +19,8 @@ require_once 'agenda.inc.php';
$current_course_tool = TOOL_CALENDAR_EVENT;
$this_section = SECTION_MYAGENDA;
$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui','jquery-ui-i18n'));
$htmlHeadXtra[] = api_get_js('qtip2/jquery.qtip.min.js');
$htmlHeadXtra[] = api_get_js('fullcalendar/fullcalendar.min.js');

Binary file not shown.

@ -505,7 +505,7 @@ foreach ($docs_and_folders as $file) {
//errorAlerts: true,
//warningAlerts: true,
swfPath: "'.$js_path.'jquery-jplayer",
//supplied: "m4a, oga, mp3, ogg, wav",
supplied: "m4a, oga, mp3, ogg, wav",
wmode: "window",
//solution: "flash, html", // Do not change this setting otherwise
cssSelectorAncestor: "#jp_container_'.$count.'",
@ -1073,7 +1073,7 @@ if ($is_allowed_to_edit || $group_member_with_upload_rights || is_my_shared_fold
<?php
}
// Record new audio
// Record new audio nanogong
if (api_get_setting('enable_nanogong') == 'true') {
?>
<a href="record_audio.php?<?php echo api_get_cidreq(); ?>&id=<?php echo $document_id.$req_gid; ?>">
@ -1081,7 +1081,15 @@ if ($is_allowed_to_edit || $group_member_with_upload_rights || is_my_shared_fold
<?php
}
// Create new audio
// Record new audio wami record
if (api_get_setting('enable_wami_record') == 'true') {
?>
<a href="record_audio_wami.php?<?php echo api_get_cidreq(); ?>&id=<?php echo $document_id.$req_gid; ?>">
<?php Display::display_icon('new_recording.png', get_lang('RecordMyVoice'),'',ICON_SIZE_MEDIUM); ?></a>
<?php
}
// Create new audio from text
if (api_get_setting('enabled_text2audio') == 'true'){
?>
<a href="create_audio.php?<?php echo api_get_cidreq(); ?>&id=<?php echo $document_id.$req_gid; ?>">

@ -135,15 +135,18 @@ function submitVoice() {
var lang_give_a_title="<?php echo get_lang('NanogongGiveTitle'); ?>";
var lang_failled_to_submit="<?php echo get_lang('NanogongFailledToSubmit'); ?>";
var lang_submitted="<?php echo get_lang('NanogongSubmitted'); ?>";
// user and group id
var nano_user_id="<?php echo api_get_user_id(); ?>";
var nano_group_id="<?php echo api_get_group_id(); ?>";
var nano_session_id="<?php echo api_get_session_id(); ?>";
//path, url and filename
var filename = document.getElementById("audio_title").value+".wav";
var filename = document.getElementById("audio_title").value+"_chnano_.wav";//adding name file, tag and extension
var filename = filename.replace(/\s/g, "_");//replace spaces by _
var filename = encodeURIComponent(filename);
var filepath="<?php echo urlencode($filepath); ?>";
var dir="<?php echo urlencode($dir); ?>";
var course_code="<?php echo urlencode($course_code); ?>";
var urlnanogong="../inc/lib/nanogong/receiver.php?filename="+filename+"&filepath="+filepath+"&dir="+dir+"&course_code="+course_code;
var urlnanogong="../inc/lib/nanogong/receiver.php?filename="+filename+"&filepath="+filepath+"&dir="+dir+"&course_code="+course_code+"&nano_group_id="+nano_group_id+"&nano_session_id="+nano_session_id+"&nano_user_id="+nano_user_id;
//check
var recorder

@ -0,0 +1,199 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This file allows record wav files.
*
* @package chamilo.document
*
* @author Juan Carlos Raña Trabado herodoto@telefonica.net
* @since 5/april/2012
*/
/**
* Code
*/
/* INIT SECTION */
// Name of the language file that needs to be included
$language_file = array('document');
require_once '../inc/global.inc.php';
$_SESSION['whereami'] = 'document/voicerecord';
$this_section = SECTION_COURSES;
require_once api_get_path(SYS_CODE_PATH).'document/document.inc.php';
require_once api_get_path(LIBRARY_PATH).'groupmanager.lib.php';
$nameTools = get_lang('VoiceRecord');
api_protect_course_script();
api_block_anonymous_users();
$document_data = DocumentManager::get_document_data_by_id($_GET['id'], api_get_course_id(), true);
if (empty($document_data)) {
if (api_is_in_group()) {
$group_properties = GroupManager::get_group_properties(api_get_group_id());
$document_id = DocumentManager::get_document_id(api_get_course_info(), $group_properties['directory']);
$document_data = DocumentManager::get_document_data_by_id($document_id, api_get_course_id());
}
}
$document_id = $document_data['id'];
$dir = $document_data['path'];
//make some vars
$wamidir=$dir;
if($wamidir=="/"){
$wamidir="";
}
$wamiurlplay=api_get_path(WEB_COURSE_PATH).api_get_course_path().'/document'.$wamidir."/";
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
// Please, do not modify this dirname formatting
if (strstr($dir, '..')) {
$dir = '/';
}
if ($dir[0] == '.') {
$dir = substr($dir, 1);
}
if ($dir[0] != '/') {
$dir = '/'.$dir;
}
if ($dir[strlen($dir) - 1] != '/') {
$dir .= '/';
}
$filepath = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document'.$dir;
if (!is_dir($filepath)) {
$filepath = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document/';
$dir = '/';
}
//make some vars
//$waminame="audiorecord.wav";
$wamiuserid=api_get_user_id();
$userinfo=Database::get_user_info_from_id($wamiuserid);
$waminame = api_get_person_name($userinfo['firstname'], $userinfo['lastname']).'.wav';
$waminame = replace_dangerous_char($waminame, 'strict');
$waminame_noex=basename($waminame, ".wav");
$dirBaseDocuments = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
$saveDir=$dirBaseDocuments.$wamidir;
if (file_exists($saveDir.'/'.$waminame)){
$i = 1;
while (file_exists($saveDir.'/'.$waminame_noex.'_'.$i.'.wav')) $i++;
$waminame = $waminame_noex . '_' . $i . '.wav';
}
//groups //TODO: clean
if (isset ($_SESSION['_gid']) && $_SESSION['_gid'] != 0) {
$req_gid = '&amp;gidReq='.$_SESSION['_gid'];
$interbreadcrumb[] = array ("url" => "../group/group_space.php?gidReq=".$_SESSION['_gid'], "name" => get_lang('GroupSpace'));
$noPHP_SELF = true;
$to_group_id = $_SESSION['_gid'];
$group = GroupManager :: get_group_properties($to_group_id);
$path = explode('/', $dir);
if ('/'.$path[1] != $group['directory']) {
api_not_allowed(true);
}
}
$interbreadcrumb[] = array ("url" => "./document.php?id=".$document_id.$req_gid, "name" => get_lang('Documents'));
if (!$is_allowed_in_course) {
api_not_allowed(true);
}
if (!($is_allowed_to_edit || $_SESSION['group_member_with_upload_rights'] || is_my_shared_folder(api_get_user_id(), Security::remove_XSS($dir),api_get_session_id()))) {
api_not_allowed(true);
}
/* Header */
event_access_tool(TOOL_DOCUMENT);
$display_dir = $dir;
if (isset ($group)) {
$display_dir = explode('/', $dir);
unset ($display_dir[0]);
unset ($display_dir[1]);
$display_dir = implode('/', $display_dir);
}
// Interbreadcrumb for the current directory root path
$counter = 0;
if (isset($document_data['parents'])) {
foreach($document_data['parents'] as $document_sub_data) {
//fixing double group folder in breadcrumb
if (api_get_group_id()) {
if ($counter == 0) {
$counter++;
continue;
}
}
$interbreadcrumb[] = array('url' => $document_sub_data['document_url'], 'name' => $document_sub_data['title']);
$counter++;
}
}
Display :: display_header($nameTools, 'Doc');
echo '<div class="actions">';
echo '<a href="document.php?id='.$document_id.'">'.Display::return_icon('back.png',get_lang('BackTo').' '.get_lang('DocumentsOverview'),'',ICON_SIZE_MEDIUM).'</a>';
echo '</div>';
?>
<!-- swfobject is a commonly used library to embed Flash content https://ajax.googleapis.com/ajax/libs/swfobject/2.2/ -->
<script type="text/javascript" src="<?php echo api_get_path(WEB_LIBRARY_PATH) ?>swfobject/swfobject.js"></script>
<!-- Setup the recorder interface -->
<script type="text/javascript" src="<?php echo api_get_path(WEB_LIBRARY_PATH) ?>wami-recorder/recorder.js"></script>
<!-- GUI code... take it or leave it -->
<script type="text/javascript" src="<?php echo api_get_path(WEB_LIBRARY_PATH) ?>wami-recorder/gui.js"></script>
<script>
function setupRecorder() {
Wami.setup({
id : "wami",
onReady : setupGUI
});
}
function setupGUI() {
var gui = new Wami.GUI({
id : "wami",
recordUrl : "<?php echo api_get_path(WEB_LIBRARY_PATH) ?>wami-recorder/record_document.php?waminame=<?php echo $waminame; ?>&wamidir=<?php echo $wamidir; ?>&wamiuserid=<?php echo $wamiuserid; ?>",
playUrl : "<?php echo $wamiurlplay.$waminame; ?>",
buttonUrl : "<?php echo api_get_path(WEB_LIBRARY_PATH) ?>wami-recorder/buttons.png",
swfUrl : "<?php echo api_get_path(WEB_LIBRARY_PATH) ?>wami-recorder/Wami.swf",
});
gui.setPlayEnabled(false);
}
</script>
<div id="wami" style="margin-left: 460px; margin-top:50px;"></div>
<div align="center" style="margin-top:200px;">
<?php
Display::display_normal_message(get_lang('VoiceRecord'), false);
?>
</div>
<body onLoad="setupRecorder()">
<?php
Display :: display_footer();

@ -15,20 +15,28 @@ require_once '../inc/global.inc.php';
require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
require_once api_get_path(LIBRARY_PATH).'document.lib.php';
api_protect_course_script();
api_block_anonymous_users();
if(!isset($_GET['title']) && !isset($_GET['type']) && !isset($_GET['image'])) {
if ($_user['user_id']!= api_get_user_id() || api_get_user_id()==0 || $_user['user_id']==0) {
api_not_allowed();
die();
}
if(!isset($_GET['title']) || !isset($_GET['type']) || !isset($_GET['image'])) {
api_not_allowed();
die();
}
if(!isset($_SESSION['paint_dir']) || !isset($_SESSION['whereami']) ){
api_not_allowed();//
api_not_allowed();
die();
}
//pixlr return
$filename=Security::remove_XSS($_GET['title']);//The user preferred file name of the image.
$extension=Security::remove_XSS($_GET['type']);//The image type, "pdx", "jpg", "bmp" or "png".
$urlcontents=Security::remove_XSS($_GET['image']);//A URL to the image on Pixlr.com server or the raw file post of the saved image.
@ -42,9 +50,18 @@ $relativeUrlPath=$_SESSION['paint_dir'];
$currentTool=$_SESSION['whereami'];
$dirBaseDocuments = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
$saveDir=$dirBaseDocuments.$_SESSION['paint_dir'];
$contents = file_get_contents($urlcontents);
//Verify that the URL is pointing to a file @ pixlr.com domain or an ip @ pixlr.com
//Security. Verify that the URL is pointing to a file @ pixlr.com domain or an ip @ pixlr.com. Comment because sometimes return a ip number
/*
if (strpos($urlcontents, "pixlr.com") === 0){
echo "Invalid referrer";
exit;
}
*/
//Security. Allway get from pixlr.com. Comment because for now this does not run
/*
$urlcontents1='http://pixlr.com/';
$urlcontents2 = strstr($urlcontents, '_temp');
@ -52,26 +69,50 @@ $urlcontents_to_save=$urlcontents1.$urlcontents2;
$contents = file_get_contents($urlcontents_to_save);//replace line 45.
*/
//Verify that the file is an image
$headers = get_headers($urlcontents, 1);
$content_type = explode("/", $headers['Content-Type']);
if ($content_type[0] != "image"){
echo "Invalid file type";
exit;
}
//a bit title security
$filename = addslashes(trim($filename));
$filename = Security::remove_XSS($filename);
$filename = replace_dangerous_char($filename, 'strict');
$filename = disable_dangerous_file($filename);
// a bit extension security
if($extension!= 'jpg' && $extension!= 'png' && $extension!= 'bmp' && $extension!= 'pxd'){
if (strlen(trim($filename))==0) {
echo "The title is empty";//if title is empty, headers Content-Type = application/octet-stream, then not create a new title here please
exit;
}
//check file_get_contents
if ($contents === false) {
echo "I cannot read: ".$urlcontents;
exit;
}
// Extension security
if($extension!= 'jpg' && $extension!= 'png' && $extension!= 'pxd'){
die();
}
if($extension=='pxd') {
echo "pxd file type does not supported";// not secure because check security headers and finfo() return Content-Type = application/octet-stream
exit;
}
//TODO: a bit mime security
//Verify that the file is an image. Headers method
$headers = get_headers($urlcontents, 1);
$content_type = explode("/", $headers['Content-Type']);
if ($content_type[0] != "image") {
echo "Invalid file type";
exit;
}
//Verify that the file is an image. Fileinfo method
if (phpversion() >= '5.3' && extension_loaded('fileinfo')) {
$finfo = new finfo(FILEINFO_MIME);
$current_mime=$finfo->buffer($contents);
finfo_close($finfo);
if(strpos($current_mime, 'image')===false) {
echo "Invalid mime type file";
exit;
}
}
//path, file and title
$paintFileName = $filename.'.'.$extension;
@ -127,7 +168,8 @@ if($currentTool=='document/createpaint'){
//delete temporal file
unlink($_SESSION['temp_realpath_image']);
$temp_file_2delete=$_SESSION['temp_realpath_image'];
unlink($temp_file_2delete);
//Clean sessions and return to Chamilo file list
unset($_SESSION['paint_dir']);

@ -6,7 +6,7 @@
*
* @package chamilo.document
*
* @author Juan Carlos Ra<EFBFBD>a Trabado
* @author Juan Carlos Raña Trabado
* @since 5/mar/2011
*/
/**
@ -15,18 +15,23 @@
require_once '../../../inc/global.inc.php';
require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
//security. Nanogong need less security because under Firefox, Chrome..., not save user_id...
//security. Nanogong need less security because under Firefox, Chrome..., not stay SESSION
if (api_get_setting('enable_nanogong') == 'false'){
api_protect_course_script();
api_block_anonymous_users();
}
if (!isset($_GET['filename']) || !isset($_GET['filepath']) || !isset($_GET['dir']) || !isset($_GET['course_code'])){
api_not_allowed(true);
if (!isset($_GET['filename']) || !isset($_GET['filepath']) || !isset($_GET['dir']) || !isset($_GET['course_code'])|| !isset($_GET['nano_group_id']) || !isset($_GET['nano_session_id']) || !isset($_GET['nano_user_id'])){
echo 'Error. Not allowed';
exit;
}
if (!is_uploaded_file($_FILES['voicefile']['tmp_name'])) exit;
//clean
$nano_user_id=Security::remove_XSS($_GET['nano_user_id']);
$nano_group_id=Security::remove_XSS($_GET['nano_group_id']);
$nano_session_id=Security::remove_XSS($_GET['nano_session_id']);
$filename=Security::remove_XSS($_GET['filename']);
$filename=urldecode($filename);
$filepath=Security::remove_XSS(urldecode($_GET['filepath']));
@ -41,21 +46,33 @@ $filename = Database::escape_string($filename);
$filename = replace_dangerous_char($filename, $strict = 'loose');// or strict
$filename = disable_dangerous_file($filename);
$title= str_replace('_',' ',$filename);
$title= trim(str_replace('_chnano_.','.',$filename));//hide nanogong wav tag at title
$title= str_replace('_',' ',$title);
//
$documentPath = $filepath.$filename;
/*
//comment because here api_get_user_id() return alway 0
if ($nano_user_id!= api_get_user_id() || api_get_user_id()==0 || $nano_user_id==0) {
echo 'Not allowed';
exit;
}
*/
//Do not use here check Fileinfo method because return: text/plain
if (!file_exists($documentPath)){
//add document to disk
move_uploaded_file($_FILES['voicefile']['tmp_name'], $documentPath);
//add document to database
$current_session_id = api_get_session_id();
$groupId=$_SESSION['_gid'];
$current_session_id = $nano_session_id; // $nano_session_id instead api_get_session_id() because here $_SESSION is lost
$groupId=$nano_group_id; // $nano_group_id instead $_SESSION['_gid'], because here $_SESSION is lost.
$file_size = filesize($documentPath);
$relativeUrlPath=$dir;
$doc_id = add_document($_course, $relativeUrlPath.$filename, 'file', filesize($documentPath), $title);
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $_user['user_id'], $groupId, null, null, null, $current_session_id);
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $nano_user_id, $groupId, null, null, null, $current_session_id);// $nano_user_id instead $_user['user_id'], because here $_user['user_id'] is lost.
} else {
return get_lang('FileExistRename');
}

@ -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);
}
}

@ -83,7 +83,7 @@ if ($suffix!= 'svg' && $suffix!= 'png'){
//a bit mime security
//comment because finfo seems stopping the save process files in some php vers.
/*
if (phpversion() >= '5.3') {
if (phpversion() >= '5.3' && extension_loaded('fileinfo')) {
$finfo = new finfo(FILEINFO_MIME);
$current_mime=$finfo->buffer($contents);
finfo_close($finfo);

@ -423,6 +423,7 @@ class IndexManager {
* @author Patrick Cool <patrick.cool@UGent.be>, Ghent University - refactoring and code cleaning
*/
function display_anonymous_course_list() {
$result = '';
$ctok = $_SESSION['sec_token'];
$stok = Security::get_token();
@ -553,12 +554,12 @@ class IndexManager {
}
$htmlListCat .= "</ul>";
}
echo $htmlTitre;
$result .= $htmlTitre;
if ($thereIsSubCat) {
echo $htmlListCat;
$result .= $htmlListCat;
}
while ($categoryName = Database::fetch_array($resCats)) {
echo '<h3>', $categoryName['name'], "</h3>\n";
$result .= '<h3>' . $categoryName['name'] . "</h3>\n";
}
$numrows = Database::num_rows($sql_result_courses);
$courses_list_string = '';
@ -657,16 +658,17 @@ class IndexManager {
}
$courses_list_string .= "</ul>";
} else {
//echo '<blockquote>', get_lang('_No_course_publicly_available'), "</blockquote>\n";
//$result .= '<blockquote>', get_lang('_No_course_publicly_available'), "</blockquote>\n";
}
if ($courses_shown > 0) {
// Only display the list of courses and categories if there was more than
// 0 courses visible to the world (we're in the anonymous list here).
echo $courses_list_string;
$result .= $courses_list_string;
}
if ($category != '') {
echo '<p><a href="'.api_get_self().'"> ', Display :: return_icon('back.png', get_lang('BackToHomePage')), get_lang('BackToHomePage'), '</a></p>';
$result .= '<p><a href="'.api_get_self().'"> ' . Display :: return_icon('back.png', get_lang('BackToHomePage')) . get_lang('BackToHomePage') . '</a></p>';
}
return '<div class="home_cats">' . $result . '</div>';
}
/**

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -0,0 +1,349 @@
var Wami = window.Wami || {};
// Upon a creation of a new Wami.GUI(options), we assume that a WAMI recorder
// has been initialized.
Wami.GUI = function(options) {
var RECORD_BUTTON = 1;
var PLAY_BUTTON = 2;
setOptions(options);
setupDOM();
var recordButton, playButton;
var recordInterval, playInterval;
function createDiv(id, style) {
var div = document.createElement("div");
if (id) {
div.setAttribute('id', id);
}
if (style) {
div.style.cssText = style;
}
return div;
}
function setOptions(options) {
if (!options.buttonUrl) {
options.buttonUrl = "buttons.png";
}
if (typeof options.listen == 'undefined' || options.listen) {
listen();
}
}
function setupDOM() {
var guidiv = createDiv(null,
"position: absolute; width: 214px; height: 137px;");
document.getElementById(options.id).appendChild(guidiv);
var rid = Wami.createID();
var recordDiv = createDiv(rid,
"position: absolute; left: 40px; top: 25px");
guidiv.appendChild(recordDiv);
recordButton = new Button(rid, RECORD_BUTTON, options.buttonUrl);
recordButton.onstart = startRecording;
recordButton.onstop = stopRecording;
recordButton.setEnabled(true);
if (!options.singleButton) {
var pid = Wami.createID();
var playDiv = createDiv(pid,
"position: absolute; right: 40px; top: 25px");
guidiv.appendChild(playDiv);
playButton = new Button(pid, PLAY_BUTTON, options.buttonUrl);
playButton.onstart = startPlaying;
playButton.onstop = stopPlaying;
}
}
/**
* These methods are called on clicks from the GUI.
*/
function startRecording() {
if (!options.recordUrl) {
alert("No record Url specified!");
}
recordButton.setActivity(0);
playButton.setEnabled(false);
Wami.startRecording(options.recordUrl,
Wami.nameCallback(onRecordStart), Wami
.nameCallback(onRecordFinish), Wami
.nameCallback(onError));
}
function stopRecording() {
Wami.stopRecording();
clearInterval(recordInterval);
recordButton.setEnabled(true);
}
function startPlaying() {
if (!options.playUrl) {
alert('No play URL specified!');
}
playButton.setActivity(0);
recordButton.setEnabled(false);
Wami.startPlaying(options.playUrl, Wami.nameCallback(onPlayStart), Wami
.nameCallback(onPlayFinish), Wami.nameCallback(onError));
}
function stopPlaying() {
Wami.stopPlaying();
}
this.setPlayUrl = function(url) {
options.playUrl = url;
}
this.setRecordUrl = function(url) {
options.recordUrl = url;
}
this.setPlayEnabled = function(val) {
playButton.setEnabled(val);
}
this.setRecordEnabled = function(val) {
recordButton.setEnabled(val);
}
/**
* Callbacks from the flash indicating certain events
*/
function onError(e) {
alert(e);
}
function onRecordStart() {
recordInterval = setInterval(function() {
if (recordButton.isActive()) {
var level = Wami.getRecordingLevel();
recordButton.setActivity(level);
}
}, 200);
if (options.onRecordStart) {
options.onRecordStart();
}
}
function onRecordFinish() {
playButton.setEnabled(true);
if (options.onRecordFinish) {
options.onRecordFinish();
}
}
function onPlayStart() {
playInterval = setInterval(function() {
if (playButton.isActive()) {
var level = Wami.getPlayingLevel();
playButton.setActivity(level);
}
}, 200);
if (options.onPlayStart) {
options.onPlayStart();
}
}
function onPlayFinish() {
clearInterval(playInterval);
recordButton.setEnabled(true);
playButton.setEnabled(true);
if (options.onPlayFinish) {
options.onPlayFinish();
}
}
function listen() {
Wami.startListening();
// Continually listening when the window is in focus allows us to
// buffer a little audio before the users clicks, since sometimes
// people talk too soon. Without "listening", the audio would record
// exactly when startRecording() is called.
window.onfocus = function() {
Wami.startListening();
};
// Note that the use of onfocus and onblur should probably be replaced
// with a more robust solution (e.g. jQuery's $(window).focus(...)
window.onblur = function() {
Wami.stopListening();
};
}
function Button(buttonid, type, url) {
var self = this;
self.active = false;
self.type = type;
init();
// Get the background button image position
// Index: 1) normal 2) pressed 3) mouse-over
function background(index) {
if (index == 1)
return "-56px 0px";
if (index == 2)
return "0px 0px";
if (index == 3)
return "-112px 0";
alert("Background not found: " + index);
}
// Get the type of meter and its state
// Index: 1) enabled 2) meter 3) disabled
function meter(index, offset) {
var top = 5;
if (offset)
top += offset;
if (self.type == RECORD_BUTTON) {
if (index == 1)
return "-169px " + top + "px";
if (index == 2)
return "-189px " + top + "px";
if (index == 3)
return "-249px " + top + "px";
} else {
if (index == 1)
return "-269px " + top + "px";
if (index == 2)
return "-298px " + top + "px";
if (index == 3)
return "-327px " + top + "px";
}
alert("Meter not found: " + self.type + " " + index);
}
function silhouetteWidth() {
if (self.type == RECORD_BUTTON) {
return "20px";
} else {
return "29px";
}
}
function mouseHandler(e) {
var rightclick;
if (!e)
var e = window.event;
if (e.which)
rightclick = (e.which == 3);
else if (e.button)
rightclick = (e.button == 2);
if (!rightclick) {
if (self.active && self.onstop) {
self.active = false;
self.onstop();
} else if (!self.active && self.onstart) {
self.active = true;
self.onstart();
}
}
}
function init() {
var div = document.createElement("div");
var elem = document.getElementById(buttonid);
if (elem) {
elem.appendChild(div);
} else {
alert('Could not find element on page named ' + buttonid);
}
self.guidiv = document.createElement("div");
self.guidiv.style.width = '56px';
self.guidiv.style.height = '63px';
self.guidiv.style.cursor = 'pointer';
self.guidiv.style.background = "url(" + url + ") no-repeat";
self.guidiv.style.backgroundPosition = background(1);
div.appendChild(self.guidiv);
// margin auto doesn't work in IE quirks mode
// http://stackoverflow.com/questions/816343/why-will-this-div-img-not-center-in-ie8
// text-align is a hack to force it to work even if you forget the
// doctype.
self.guidiv.style.textAlign = 'center';
self.meterDiv = document.createElement("div");
self.meterDiv.style.width = silhouetteWidth();
self.meterDiv.style.height = '63px';
self.meterDiv.style.margin = 'auto';
self.meterDiv.style.cursor = 'pointer';
self.meterDiv.style.position = 'relative';
self.meterDiv.style.background = "url(" + url + ") no-repeat";
self.meterDiv.style.backgroundPosition = meter(2);
self.guidiv.appendChild(self.meterDiv);
self.coverDiv = document.createElement("div");
self.coverDiv.style.width = silhouetteWidth();
self.coverDiv.style.height = '63px';
self.coverDiv.style.margin = 'auto';
self.coverDiv.style.cursor = 'pointer';
self.coverDiv.style.position = 'relative';
self.coverDiv.style.background = "url(" + url + ") no-repeat";
self.coverDiv.style.backgroundPosition = meter(1);
self.meterDiv.appendChild(self.coverDiv);
self.active = false;
self.guidiv.onmousedown = mouseHandler;
}
self.isActive = function() {
return self.active;
}
self.setActivity = function(level) {
self.guidiv.onmouseout = function() {
};
self.guidiv.onmouseover = function() {
};
self.guidiv.style.backgroundPosition = background(2);
self.coverDiv.style.backgroundPosition = meter(1, 5);
self.meterDiv.style.backgroundPosition = meter(2, 5);
var totalHeight = 31;
var maxHeight = 9;
// When volume goes up, the black image loses height,
// creating the perception of the colored one increasing.
var height = (maxHeight + totalHeight - Math.floor(level / 100
* totalHeight));
self.coverDiv.style.height = height + "px";
}
self.setEnabled = function(enable) {
var guidiv = self.guidiv;
self.active = false;
if (enable) {
self.coverDiv.style.backgroundPosition = meter(1);
self.meterDiv.style.backgroundPosition = meter(1);
guidiv.style.backgroundPosition = background(1);
guidiv.onmousedown = mouseHandler;
guidiv.onmouseover = function() {
guidiv.style.backgroundPosition = background(3);
};
guidiv.onmouseout = function() {
guidiv.style.backgroundPosition = background(1);
};
} else {
self.coverDiv.style.backgroundPosition = meter(3);
self.meterDiv.style.backgroundPosition = meter(3);
guidiv.style.backgroundPosition = background(1);
guidiv.onmousedown = null;
guidiv.onmouseout = function() {
};
guidiv.onmouseover = function() {
};
}
}
}
}

@ -0,0 +1,6 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -0,0 +1,64 @@
<?php
require_once '../../../inc/global.inc.php';
require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
require_once api_get_path(LIBRARY_PATH).'document.lib.php';
////Add security from Chamilo
api_protect_course_script();
api_block_anonymous_users();
//
# Save the audio to a URL-accessible directory for playback.
parse_str($_SERVER['QUERY_STRING'], $params);
if(isset($params['waminame']) && isset($params['wamidir']) && isset($params['wamiuserid'])) {
$waminame = $params['waminame'];
$wamidir = $params['wamidir'];
$wamiuserid = $params['wamiuserid'];
}
else {
api_not_allowed();
die();
}
if ($wamiuserid!= api_get_user_id() || api_get_user_id()==0 || $wamiuserid==0) {
api_not_allowed();
die();
}
//clean
$waminame = Security::remove_XSS($waminame);
$waminame = addslashes(trim($waminame));
$waminame = replace_dangerous_char($waminame, 'strict');
$waminame = disable_dangerous_file($waminame);
$wamidir = Security::remove_XSS($wamidir);
$content = file_get_contents('php://input');
//security extension
$ext = explode('.', $waminame);
$ext = strtolower($ext[sizeof($ext) - 1]);
if($ext!= 'wav'){
die();
}
//Do not use here check Fileinfo method because return: text/plain
$dirBaseDocuments = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
$saveDir=$dirBaseDocuments.$wamidir;
$current_session_id = api_get_session_id();
$groupId=$_SESSION['_gid'];
$documentPath = $saveDir.'/'.$waminame;
$title=str_replace('_',' ',$waminame);
//$title=basename($waminame, ".wav");//save title whitout extension
//add to disk
$fh = fopen($documentPath, 'w') or die("can't open file");
fwrite($fh, $content);
fclose($fh);
//add document to database
$doc_id = add_document($_course, $wamidir.'/'.$waminame, 'file', filesize($documentPath), $title);
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $_user['user_id'], $groupId, null, null, null, $current_session_id);
?>

@ -0,0 +1,273 @@
var Wami = window.Wami || {};
// Returns a (very likely) unique string with of random letters and numbers
Wami.createID = function() {
return "wid" + ("" + 1e10).replace(/[018]/g, function(a) {
return (a ^ Math.random() * 16 >> a / 4).toString(16)
});
}
// Creates a named callback in WAMI and returns the name as a string.
Wami.nameCallback = function(cb, cleanup) {
Wami._callbacks = Wami._callbacks || {};
var id = Wami.createID();
Wami._callbacks[id] = function() {
if (cleanup) {
Wami._callbacks[id] = null;
}
cb.apply(null, arguments);
};
var named = "Wami._callbacks['" + id + "']";
return named;
}
// This method ensures that a WAMI recorder is operational, and that
// the following API is available in the Wami namespace. All functions
// must be named (i.e. cannot be anonymous).
//
// Wami.startPlaying(url, startfn = null, finishedfn = null, failedfn = null);
// Wami.stopPlaying()
//
// Wami.startRecording(url, startfn = null, finishedfn = null, failedfn = null);
// Wami.stopRecording()
//
// Wami.getRecordingLevel() // Returns a number between 0 and 100
// Wami.getPlayingLevel() // Returns a number between 0 and 100
//
// Wami.hide()
// Wami.show()
//
// Manipulate the WAMI recorder's settings. In Flash
// we need to check if the microphone permission has been granted.
// We might also set/return sample rate here, etc.
//
// Wami.getSettings();
// Wami.setSettings(options);
//
// Optional way to set up browser so that it's constantly listening
// This is to prepend audio in case the user starts talking before
// they click-to-talk.
//
// Wami.startListening()
//
Wami.setup = function(options) {
if (Wami.startRecording) {
// Wami's already defined.
if (options.onReady) {
options.onReady();
}
return;
}
// Assumes that swfobject.js is included if Wami.swfobject isn't
// already defined.
Wami.swfobject = Wami.swfobject || swfobject;
if (!Wami.swfobject) {
alert("Unable to find swfobject to help embed the SWF.");
}
var _options;
setOptions(options);
embedWamiSWF(_options.id, Wami.nameCallback(delegateWamiAPI));
function supportsTransparency() {
// Detecting the OS is a big no-no in Javascript programming, but
// I can't think of a better way to know if wmode is supported or
// not... since NOT supporting it (like Flash on Ubuntu) is a bug.
return (navigator.platform.indexOf("Linux") == -1);
}
function setOptions(options) {
// Start with default options
_options = {
swfUrl : "Wami.swf",
onReady : function() {
Wami.hide();
},
onSecurity : checkSecurity,
onError : function(error) {
alert(error);
}
};
if (typeof options == 'undefined') {
alert('Need at least an element ID to place the Flash object.');
}
if (typeof options == 'string') {
_options.id = options;
} else {
_options.id = options.id;
}
if (options.swfUrl) {
_options.swfUrl = options.swfUrl;
}
if (options.onReady) {
_options.onReady = options.onReady;
}
if (options.onLoaded) {
_options.onLoaded = options.onLoaded;
}
if (options.onSecurity) {
_options.onSecurity = options.onSecurity;
}
if (options.onError) {
_options.onError = options.onError;
}
// Create a DIV for the SWF under _options.id
var container = document.createElement('div');
container.style.position = 'absolute';
_options.cid = Wami.createID();
container.setAttribute('id', _options.cid);
var swfdiv = document.createElement('div');
var id = Wami.createID();
swfdiv.setAttribute('id', id);
container.appendChild(swfdiv);
document.getElementById(_options.id).appendChild(container);
_options.id = id;
}
function checkSecurity() {
var settings = Wami.getSettings();
if (settings.microphone.granted) {
_options.onReady();
} else {
// Show any Flash settings panel you want:
// http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/SecurityPanel.html
Wami.showSecurity("privacy", "Wami.show", Wami
.nameCallback(_options.onSecurity), Wami
.nameCallback(_options.onError));
}
}
// Embed the WAMI SWF and call the named callback function when loaded.
function embedWamiSWF(id, initfn) {
var flashVars = {
visible : false,
loadedCallback : initfn
}
var params = {
allowScriptAccess : "always"
}
if (supportsTransparency()) {
params.wmode = "transparent";
}
if (typeof console !== 'undefined') {
flashVars.console = true;
}
var version = '10.0.0';
document.getElementById(id).innerHTML = "WAMI requires Flash "
+ version
+ " or greater<br />https://get.adobe.com/flashplayer/";
// This is the minimum size due to the microphone security panel
Wami.swfobject.embedSWF(_options.swfUrl, id, 214, 137, version, null,
flashVars, params);
// Without this line, Firefox has a dotted outline of the flash
Wami.swfobject.createCSS("#" + id, "outline:none");
}
// To check if the microphone settings were 'remembered', we
// must actually embed an entirely new Wami client and check
// whether its microphone is granted. If it is, it was remembered.
function checkRemembered(finishedfn) {
var id = Wami.createID();
var div = document.createElement('div');
div.style.top = '-999px';
div.style.left = '-999px';
div.setAttribute('id', id);
var body = document.getElementsByTagName('body').item(0);
body.appendChild(div);
var fn = Wami.nameCallback(function() {
var swf = document.getElementById(id);
Wami._remembered = swf.getSettings().microphone.granted;
Wami.swfobject.removeSWF(id);
eval(finishedfn + "()");
});
embedWamiSWF(id, fn);
}
// Attach all the audio methods to the Wami namespace in the callback.
function delegateWamiAPI() {
var recorder = document.getElementById(_options.id);
function delegate(name) {
Wami[name] = function() {
return recorder[name].apply(recorder, arguments);
}
}
delegate('startPlaying');
delegate('stopPlaying');
delegate('startRecording');
delegate('stopRecording');
delegate('startListening');
delegate('stopListening');
delegate('getRecordingLevel');
delegate('getPlayingLevel');
delegate('setSettings');
// Append extra information about whether mic settings are sticky
Wami.getSettings = function() {
var settings = recorder.getSettings();
settings.microphone.remembered = Wami._remembered;
return settings;
}
Wami.showSecurity = function(panel, startfn, finishedfn, failfn) {
// Flash must be on top for this.
var container = document.getElementById(_options.cid);
var augmentedfn = Wami.nameCallback(function() {
checkRemembered(finishedfn);
container.style.cssText = "position: absolute;";
});
container.style.cssText = "position: absolute; z-index: 99999";
recorder.showSecurity(panel, startfn, augmentedfn, failfn);
}
Wami.show = function() {
if (!supportsTransparency()) {
recorder.style.visibility = "visible";
}
}
Wami.hide = function() {
// Hiding flash in all the browsers is tricky. Please read:
// https://code.google.com/p/wami-recorder/wiki/HidingFlash
if (!supportsTransparency()) {
recorder.style.visibility = "hidden";
}
}
// If we already have permissions, they were previously 'remembered'
Wami._remembered = recorder.getSettings().microphone.granted;
if (_options.onLoaded) {
_options.onLoaded();
}
if (!_options.noSecurityCheck) {
checkSecurity();
}
}
}

@ -864,7 +864,8 @@ VALUES
('login_is_email', NULL, 'radio', 'Platform', 'false', 'LoginIsEmailTitle', 'LoginIsEmailComment', NULL, NULL, 0),
('courses_default_creation_visibility', NULL, 'radio', 'Course', '2', 'CoursesDefaultCreationVisibilityTitle', 'CoursesDefaultCreationVisibilityComment', NULL, NULL, 1),
('allow_browser_sniffer', NULL, 'radio', 'Tuning', 'false', 'AllowBrowserSnifferTitle', 'AllowBrowserSnifferComment', NULL, NULL, 0),
('chamilo_database_version',NULL,'textfield',NULL, '1.9.0.17053','DokeosDatabaseVersion','', NULL, NULL, 0);
('enable_wami_record',NULL,'radio','Tools','false','EnableWamiRecordTitle','EnableWamiRecordComment',NULL,NULL, 0),
('chamilo_database_version',NULL,'textfield',NULL, '1.9.0.17054','DokeosDatabaseVersion','', NULL, NULL, 0);
/*
('show_tabs', 'custom_tab_1', 'checkbox', 'Platform', 'true', 'ShowTabsTitle', 'ShowTabsComment', NULL, 'TabsCustom1', 1),
@ -1201,7 +1202,9 @@ VALUES
('courses_default_creation_visibility', '1', 'Private'),
('courses_default_creation_visibility', '0', 'CourseVisibilityClosed'),
('allow_browser_sniffer', 'true', 'Yes'),
('allow_browser_sniffer', 'false', 'No');
('allow_browser_sniffer', 'false', 'No'),
('enable_wami_record', 'true', 'Yes'),
('enable_wami_record', 'false', 'No');
UNLOCK TABLES;
/*

@ -148,6 +148,11 @@ INSERT INTO settings_current (variable, subkey, type, category, selected_value,
INSERT INTO settings_options (variable, value, display_text) VALUES ('allow_browser_sniffer', 'true', 'Yes');
INSERT INTO settings_options (variable, value, display_text) VALUES ('allow_browser_sniffer', 'false', 'No');
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('enable_wami_record', NULL, 'radio', 'Tools', 'false', 'EnableWamiRecordTitle', 'EnableWamiRecordComment', NULL, NULL, 0);
INSERT INTO settings_options (variable, value, display_text) VALUES ('enable_wami_record', 'true', 'Yes');
INSERT INTO settings_options (variable, value, display_text) VALUES ('enable_wami_record', 'false', 'No');
-- Course ranking
CREATE TABLE track_course_ranking (id int unsigned not null PRIMARY KEY AUTO_INCREMENT,c_id int unsigned not null, session_id int unsigned not null default 0, url_id int unsigned not null default 0, accesses int unsigned not null default 0, total_score int unsigned not null default 0, users int unsigned not null default 0, creation_date datetime not null);

@ -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';

@ -1,4 +1,4 @@
{% if hot_courses is not null %}
{% if hot_courses is not null and hot_courses is not empty %}
<script type="text/javascript">
$(document).ready( function() {
@ -67,4 +67,4 @@ $(document).ready( function() {
{% endfor %}
</div>
</section>
{% endif %}
{% endif %}

@ -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