diff --git a/admin/external_forms.php b/admin/external_forms.php
new file mode 100644
index 00000000000..3e24b667aec
--- /dev/null
+++ b/admin/external_forms.php
@@ -0,0 +1,89 @@
+.
+
+/**
+ * Web services admin UI forms
+ *
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once $CFG->libdir.'/formslib.php';
+
+class external_service_form extends moodleform {
+ function definition() {
+ global $CFG, $USER;
+
+ $mform = $this->_form;
+ $service = $this->_customdata;
+
+ $mform->addElement('header', 'extservice', get_string('externalservice', 'webservice'));
+
+ $mform->addElement('text', 'name', get_string('name'));
+ $mform->addElement('advcheckbox', 'enabled', get_string('enabled', 'webservice'));
+ $mform->addElement('text', 'requiredcapability', get_string('requiredcapability', 'webservice'));
+ $mform->addElement('advcheckbox', 'restrictedusers', get_string('restrictedusers', 'webservice'));
+
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+
+ $this->add_action_buttons(true);
+
+ $this->set_data($service);
+ }
+
+ function definition_after_data() {
+ $mform = $this->_form;
+ $service = $this->_customdata;
+
+ if (!empty($service->component)) {
+ // custom component
+ $mform->hardFreeze('name,requiredcapability,restrictedusers');
+ }
+ }
+}
+
+class external_service_functions_form extends moodleform {
+ function definition() {
+ global $CFG, $USER, $DB;
+
+ $mform = $this->_form;
+ $data = $this->_customdata;
+
+ $mform->addElement('header', 'addfunction', get_string('addfunction', 'webservice'));
+
+ $select = "name NOT IN (SELECT s.functionname
+ FROM {external_services_functions} s
+ WHERE s.externalserviceid = :sid
+ )";
+
+ $functions = $DB->get_records_select_menu('external_functions', $select, array('sid'=>$data['id']), 'name', 'id, name');
+
+ $mform->addElement('select', 'fid', get_string('name'), $functions);
+
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+
+ $mform->addElement('hidden', 'action');
+ $mform->setType('action', PARAM_ACTION);
+
+ $this->add_action_buttons(true);
+
+ $this->set_data($data);
+ }
+}
diff --git a/admin/external_service.php b/admin/external_service.php
new file mode 100644
index 00000000000..089ef3fada9
--- /dev/null
+++ b/admin/external_service.php
@@ -0,0 +1,84 @@
+.
+
+/**
+ * Web services admin UI
+ *
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once('external_forms.php');
+
+$id = required_param('id', PARAM_INT);
+$action = optional_param('action', '', PARAM_ACTION);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+$PAGE->set_url('admin/external_service.php', array('id'=>$id));
+
+admin_externalpage_setup('externalservice');
+
+$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=externalservices";
+
+if ($id) {
+ $service = $DB->get_record('external_services', array('id'=>$id), '*', MUST_EXIST);
+} else {
+ $service = null;
+}
+
+if ($action == 'delete' and confirm_sesskey() and $service and empty($service->component)) {
+ if (!$confirm) {
+ admin_externalpage_print_header();
+ $optionsyes = array('id'=>$id, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey());
+ $optionsno = array('section'=>'externalservices');
+ $formcontinue = html_form::make_button('external_service.php', $optionsyes, get_string('delete'), 'post');
+ $formcancel = html_form::make_button('settings.php', $optionsno, get_string('cancel'), 'get');
+ echo $OUTPUT->confirm(get_string('deleteserviceconfirm', 'webservice', $service->name), $formcontinue, $formcancel);
+ echo $OUTPUT->footer();
+ die;
+ }
+ $DB->delete_records('external_services_users', array('externalserviceid'=>$service->id));
+ $DB->delete_records('external_services_functions', array('externalserviceid'=>$service->id));
+ $DB->delete_records('external_services', array('id'=>$service->id));
+ redirect($returnurl);
+}
+
+$mform = new external_service_form(null, $service);
+
+if ($mform->is_cancelled()) {
+ redirect($returnurl);
+
+} else if ($data = $mform->get_data()) {
+ $data = (object)$data;
+
+ //TODO: add timecreated+modified and maybe logging too
+ if (empty($data->id)) {
+ $DB->insert_record('external_services', $data);
+ } else {
+ $DB->update_record('external_services', $data);
+ }
+
+ redirect($returnurl);
+}
+
+admin_externalpage_print_header();
+$mform->display();
+echo $OUTPUT->footer();
+
diff --git a/admin/external_service_functions.php b/admin/external_service_functions.php
new file mode 100644
index 00000000000..298fb30672f
--- /dev/null
+++ b/admin/external_service_functions.php
@@ -0,0 +1,142 @@
+.
+
+/**
+ * Web services function UI
+ *
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once('external_forms.php');
+
+$id = required_param('id', PARAM_INT);
+$fid = optional_param('fid', 0, PARAM_INT);
+$action = optional_param('action', '', PARAM_ACTION);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+$PAGE->set_url('admin/external_service_functions.php', array('id'=>$id));
+
+admin_externalpage_setup('externalservicefunctions');
+
+$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=externalservices";
+$thisurl = "external_service_functions.php?id=$id";
+
+$service = $DB->get_record('external_services', array('id'=>$id), '*', MUST_EXIST);
+
+if ($action === 'delete' and confirm_sesskey() and $service and empty($service->component)) {
+ $function = $DB->get_record('external_functions', array('id'=>$fid), '*', MUST_EXIST);
+ if (!$confirm) {
+ admin_externalpage_print_header();
+ $optionsyes = array('id'=>$id, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey(), 'fid'=>$function->id);
+ $optionsno = array('id'=>$id);
+ $formcontinue = html_form::make_button('external_service_functions.php', $optionsyes, get_string('delete'), 'post');
+ $formcancel = html_form::make_button('external_service_functions.php', $optionsno, get_string('cancel'), 'get');
+ echo $OUTPUT->confirm(get_string('removefunctionconfirm', 'webservice', (object)array('service'=>$service->name, 'function'=>$function->name)), $formcontinue, $formcancel);
+ echo $OUTPUT->footer();
+ die;
+ }
+ $DB->delete_records('external_services_functions', array('externalserviceid'=>$service->id, 'functionname'=>$function->name));
+ redirect($thisurl);
+
+} else if ($action === 'add') {
+ $mform = new external_service_functions_form(null, array('action'=>'add', 'id'=>$service->id));
+
+ if ($mform->is_cancelled()) {
+ redirect($thisurl);
+ } else if ($data = $mform->get_data()) {
+ ignore_user_abort(true); // no interruption here!
+ $function = $DB->get_record('external_functions', array('id'=>$data->fid), '*', MUST_EXIST);
+ // make sure the function is not there yet
+ if ($DB->record_exists('external_services_functions', array('externalserviceid'=>$service->id, 'functionname'=>$function->name))) {
+ redirect($thisurl);
+ }
+ $new = new object();
+ $new->externalserviceid = $service->id;
+ $new->functionname = $function->name;
+ $DB->insert_record('external_services_functions', $new);
+ redirect($thisurl);
+ }
+
+ //ask for function id
+ admin_externalpage_print_header();
+ echo $OUTPUT->heading($service->name);
+ $mform->display();
+ echo $OUTPUT->footer();
+ die;
+}
+
+admin_externalpage_print_header();
+
+echo $OUTPUT->heading($service->name);
+
+$select = "name IN (SELECT s.functionname
+ FROM {external_services_functions} s
+ WHERE s.externalserviceid = :sid
+ )";
+
+$functions = $DB->get_records_select('external_functions', $select, array('sid'=>$service->id), 'name');
+
+$strfunction = get_string('function', 'webservice');
+$strdelete = get_string('removefunction', 'webservice');
+$stredit = get_string('edit');
+
+$table = new html_table();
+$table->head = array($strfunction);
+$table->align = array('left');
+$table->width = '100%';
+$table->data = array();
+if (empty($service->component)) {
+ $table->head[] = $stredit;
+ $table->align[] = 'center';
+}
+
+$durl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php?sesskey=".sesskey();
+
+foreach ($functions as $function) {
+ if (empty($service->component)) {
+ $delete = "id&id=$service->id\">$strdelete";
+ $table->data[] = array($function->name, $delete);
+ } else {
+ $table->data[] = array($function->name);
+ }
+}
+
+echo $OUTPUT->table($table);
+
+
+// we can edit only custom functions, the build-in would be overridden after each upgrade
+if (empty($service->component)) {
+ $form = new html_form();
+ $form->url = new moodle_url('external_service_functions.php', array('sesskey'=>sesskey(), 'id'=>$service->id, 'action'=>'add'));
+ $form->button->text = get_string('add');
+ $form->method = 'get';
+ echo $OUTPUT->button($form);
+}
+
+// simple back button
+$form = new html_form();
+$form->url = new moodle_url('settings.php', array('section'=>'externalservices'));
+$form->button->text = get_string('back');
+$form->method = 'get';
+echo $OUTPUT->button($form);
+
+echo $OUTPUT->footer();
+
diff --git a/admin/external_service_users.php b/admin/external_service_users.php
new file mode 100644
index 00000000000..e3b7584c8f0
--- /dev/null
+++ b/admin/external_service_users.php
@@ -0,0 +1,38 @@
+.
+
+/**
+ * Web services function UI
+ *
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once('external_forms.php');
+
+$id = required_param('id', PARAM_INT);
+
+$PAGE->set_url('admin/external_service_users.php', array('id'=>$id));
+
+admin_externalpage_setup('externalserviceusers');
+
+echo('TODO: we need something like the role assign UI');
+
+echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php
index 1161a4b74b4..8c981594d85 100644
--- a/admin/settings/plugins.php
+++ b/admin/settings/plugins.php
@@ -237,6 +237,33 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
}
}
+ // Web services
+ $ADMIN->add('modules', new admin_category('webservicesettings', get_string('webservices', 'webservice')));
+ $temp = new admin_settingpage('externalservices', get_string('externalservices', 'webservice'));
+ $temp->add(new admin_setting_manageexternalservices());
+ $ADMIN->add('webservicesettings', $temp);
+ $ADMIN->add('webservicesettings', new admin_externalpage('externalservice', get_string('externalservice', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service.php"), 'moodle/site:config', true);
+ $ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions', get_string('externalservicefunctions', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_functions.php"), 'moodle/site:config', true);
+ $ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers', get_string('externalserviceusers', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_users.php"), 'moodle/site:config', true);
+ $temp = new admin_settingpage('webserviceprotocols', get_string('manageprotocols', 'webservice'));
+ $temp->add(new admin_setting_managewebserviceprotokols());
+ if (empty($CFG->enablewebservices)) {
+ $temp->add(new admin_setting_heading('webservicesaredisabled', '', get_string('disabledwarning', 'webservice')));
+ }
+ $ADMIN->add('webservicesettings', $temp);
+ $webservices_available = get_plugin_list('webservice');
+ $active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+ foreach ($webservices_available as $webservice => $location) {
+ if (file_exists("$location/settings.php")) {
+ $name = get_string('pluginname', 'webservice_'.$webservice);
+ $settings = new admin_settingpage('webservicesetting'.$webservice, $name, 'moodle/site:config', !in_array($webservice, $active_webservices) or empty($CFG->enablewebservices));
+ if ($ADMIN->fulltree) {
+ include("$location/settings.php");
+ }
+ $ADMIN->add('webservicesettings', $settings);
+ }
+ }
+
// Question type settings.
$ADMIN->add('modules', new admin_category('qtypesettings', get_string('questiontypes', 'admin')));
$ADMIN->add('qtypesettings', new admin_page_manageqtypes());
diff --git a/admin/settings/security.php b/admin/settings/security.php
index e5601f80d09..71145d2ee5a 100644
--- a/admin/settings/security.php
+++ b/admin/settings/security.php
@@ -11,26 +11,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
'', ''));
$ADMIN->add('security', $temp);
- // "web service" settingpage
- $temp = new admin_settingpage('webservices', get_string('webservices', 'admin'));
- $temp->add(new admin_setting_heading('webserviceprotocols', get_string('protocols', 'webservice'), ''));
- $temp->add(new admin_setting_managewsprotocols());
- $url = $CFG->wwwroot.'/'.$CFG->admin.'/wsprotocols.php';
- $ADMIN->add('security', new admin_externalpage('managews',
- get_string('managews', 'admin'), $url, 'moodle/site:config', true),
- '', $url);
- $temp->add(new admin_setting_heading('webservicesystemsettings', get_string('systemsettings', 'webservice'), ''));
- $temp->add(new admin_setting_configiplist('ipwhitelist', get_string('ipwhitelist', 'admin'),'', ''));
- $temp->add(new admin_setting_heading('webserviceusersettings', get_string('usersettings', 'webservice'), ''));
- $temp->add(new admin_setting_managewsusersettings());
- $temp->add(new admin_setting_heading('webserviceservicelist', get_string('servicelist', 'webservice'), ''));
- $temp->add(new admin_setting_managewsservicelist());
- $url = $CFG->wwwroot.'/'.$CFG->admin.'/webservices.php';
- $ADMIN->add('security', new admin_externalpage('webservicessettings',
- get_string('webservicessettings', 'admin'), $url, 'moodle/site:config', true),
- '', $url);
- $ADMIN->add('security', $temp);
-
// "sitepolicies" settingpage
$temp = new admin_settingpage('sitepolicies', get_string('sitepolicies', 'admin'));
$temp->add(new admin_setting_configcheckbox('protectusernames', get_string('protectusernames', 'admin'), get_string('configprotectusernames', 'admin'), 1));
@@ -137,4 +117,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
} // end of speedup
-?>
+
diff --git a/admin/webservice_protocols.php b/admin/webservice_protocols.php
new file mode 100644
index 00000000000..e1b7abab81c
--- /dev/null
+++ b/admin/webservice_protocols.php
@@ -0,0 +1,87 @@
+.
+
+/**
+ * Web services protocols admin UI
+ *
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once($CFG->libdir.'/tablelib.php');
+
+$PAGE->set_url('admin/webservice_protocols.php', array());
+//TODO: disable the blocks here or better make the page layout default to no blocks!
+
+require_login();
+require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
+
+$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webserviceprotocols";
+
+$action = optional_param('action', '', PARAM_ACTION);
+$webservice = optional_param('webservice', '', PARAM_SAFEDIR);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+// get currently installed and enabled auth plugins
+$available_webservices = get_plugin_list('webservice');
+if (!empty($webservice) and empty($available_webservices[$webservice])) {
+ redirect($returnurl);
+}
+
+$active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+foreach ($active_webservices as $key=>$active) {
+ if (empty($available_webservices[$active])) {
+ unset($active_webservices[$key]);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// process actions
+
+if (!confirm_sesskey()) {
+ redirect($returnurl);
+}
+
+switch ($action) {
+ case 'uninstall':
+ die('TODO: not implemented yet');
+ break;
+
+ case 'disable':
+ // remove from enabled list
+ $key = array_search($webservice, $active_webservices);
+ unset($active_webservices[$key]);
+ break;
+
+ case 'enable':
+ // add to enabled list
+ if (!in_array($webservice, $active_webservices)) {
+ $active_webservices[] = $webservice;
+ $active_webservices = array_unique($active_webservices);
+ }
+ break;
+
+ default:
+ break;
+}
+
+set_config('webserviceprotocols', implode(',', $active_webservices));
+
+redirect($returnurl);
diff --git a/admin/webservices.php b/admin/webservices.php
deleted file mode 100644
index 8628a53b66a..00000000000
--- a/admin/webservices.php
+++ /dev/null
@@ -1,117 +0,0 @@
-.
-
-require_once(dirname(dirname(__FILE__)) . '/config.php');
-require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/webservice/lib.php');
-
-
-$serviceid = optional_param('serviceid', '', PARAM_FORMAT);
-$remove = optional_param('remove', '', PARAM_FORMAT);
-
-$pagename = 'webservicessettings';
-
-
-admin_externalpage_setup($pagename);
-require_login(SITEID, false);
-require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
-
-$sesskeyurl = "$CFG->wwwroot/$CFG->admin/webservices.php?sesskey=" . sesskey();
-$baseurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webservices";
-
-if (!confirm_sesskey()) {
- print_error('confirmsesskeybad', '', $baseurl);
-}
-
-if (!empty($remove)) {
- $functionserviceid = optional_param('functionserviceid', '', PARAM_FORMAT);
- if (!empty($functionserviceid)) {
- $DB->delete_records('external_services_functions',array('id' => $functionserviceid));
- }
-}
-
-if (!empty($serviceid)) {
- admin_externalpage_print_header();
-
- //cannot use moodle form in order to display complex list of functions
- $form = new html_form();
- $service = $DB->get_record('external_services',array('id' => $serviceid));
- $formhtml = get_string('servicename', 'webservice').': '.get_string($service->name, 'webservice') ;
- $formhtml .= "
";
- //display function selector
- if (empty($serviceid)) {
-
- }
-
- //display service functions
- $servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, f.component as component, s.name as servicename, s.id as serviceid, f.name as functionname, f.id as functionid
- FROM {external_services} s, {external_functions} f, {external_services_functions} fs
- WHERE fs.externalserviceid = s.id AND fs.functionname = f.name AND s.id = ?", array($serviceid));
-
- //save the administrator changes
- $saved = optional_param('saved', 0, PARAM_NUMBER);
-
- if ($saved) {
- foreach($servicesfunctions as &$servicefunction) { //need to be a refence cause we're going to update the form value too
- $enabled = optional_param($servicefunction->functionname, '', PARAM_ALPHANUMEXT);
- if ($enabled) {
- $servicefunction->enabled = 1; //update the form "enabled" value
- } else {
- $servicefunction->enabled = 0; //update the form "enabled" value
- }
- $wsservicefunction = new object();
- $wsservicefunction->id = $servicefunction->id;
- $wsservicefunction->enabled = $servicefunction->enabled;
- $DB->update_record('external_services_functions',$wsservicefunction);
- }
- }
-
-
- $data = array();
- reset($servicesfunctions);
- foreach($servicesfunctions as $servicefunction) {
- $checkbox = html_select_option::make_checkbox($servicefunction->functionid, $servicefunction->enabled, 'functionenabled');
- $checkbox->label->add_class('accesshide');
- $checkbox->disabled;
- $checkboxhtml = $OUTPUT->checkbox($checkbox, $servicefunction->functionname);
- $data[] = array($servicefunction->functionname, $servicefunction->component, "id.">".get_string("removefunctionfromservice","webservice")."");
- }
- $table = new html_table();
- $table->head = array(get_string('functionname', 'webservice'), get_string('component', 'webservice'), get_string('actions', 'webservice'));
- $table->size = array('40%', '40%', '20%');
- $table->align = array('left', 'left', 'left');
- //$table->width = '30%';
- $table->data = $data;
- $table->tablealign = 'center';
- $formhtml .= $OUTPUT->table($table);
-
- $form->button->text = get_string('save', 'webservice');
- $form->button->title = get_string('save', 'webservice');
- $form->button->id = 'save';
- $form->url = new moodle_url('webservices.php', array('serviceid' => $serviceid, 'saved' => 1));
- //$form->add_class($class);
- $formhtml .= "
";
-
- echo $OUTPUT->box_start('generalbox boxaligncenter centerpara');
- echo $OUTPUT->form($form, $formhtml);
- echo $OUTPUT->box_end();
-
- echo $OUTPUT->footer();
-
-}
-
-?>
diff --git a/admin/wsprotocols.php b/admin/wsprotocols.php
deleted file mode 100644
index ad0bf593f78..00000000000
--- a/admin/wsprotocols.php
+++ /dev/null
@@ -1,88 +0,0 @@
-dirroot . '/webservice/lib.php');
-require_once($CFG->libdir . '/adminlib.php');
-
-$hide = optional_param('hide', '', PARAM_ALPHANUM);
-$username = optional_param('username', '', PARAM_ALPHANUM);
-$settings = optional_param('settings', '', PARAM_ALPHANUM);
-
-$pagename = 'managews';
-
-admin_externalpage_setup($pagename);
-require_login(SITEID, false);
-require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
-
-$baseurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webservices";
-
-if (!confirm_sesskey()) {
- print_error('confirmsesskeybad', '', $baseurl);
- }
-
-if (!empty($hide)) {
-
- set_config("enable", !get_config($hide, "enable"), $hide);
- $return = true;
-} else if (!empty($username)) {
- admin_externalpage_print_header();
- $mform = new wsuser_form('', array('username' => $username));
- if ($mform->is_cancelled()){
- redirect($baseurl);
- exit;
- }
- $fromform = $mform->get_data();
-
-
-
- if (!empty($fromform)) {
- $wsuser = $DB->get_record("user", array("username" => $fromform->username));
- set_user_preference("ipwhitelist", $fromform->ipwhitelist, $wsuser->id);
- redirect($baseurl,get_string("changessaved"));
- }
-
- echo $OUTPUT->box_start();
- $mform->display();
- echo $OUTPUT->box_end();
-
-} else if (!empty($settings)) {
-/// Server settings page
- admin_externalpage_print_header();
-
- $mform = new wssettings_form('', array('settings' => $settings)); // load the server settings form
-
- if ($mform->is_cancelled()){
- /// user pressed cancel button and return to the security web service page
- redirect($baseurl);
- exit;
- }
-
- $fromform = $mform->get_data();
-
- if (!empty($fromform)) {
- /// save the new setting
- require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
- $settingnames = call_user_func(array($settings.'_server', 'get_setting_names'));
- foreach($settingnames as $settingname) {
- if (empty($fromform->$settingname)) {
- set_config($settingname, null, $settings);
- } else {
- set_config($settingname, $fromform->$settingname, $settings);
- }
- }
-
- redirect($baseurl,get_string("changessaved")); // return to the security web service page
- }
-/// display the server settings form
- echo $OUTPUT->box_start();
- $mform->display();
- echo $OUTPUT->box_end();
-} else {
- $return = true;
-}
-
-if (!empty($return)) {
- redirect($baseurl);
-}
-
-echo $OUTPUT->footer();
diff --git a/lang/en_utf8/admin.php b/lang/en_utf8/admin.php
index 09c1fefa95a..dbc4c5c9ff9 100644
--- a/lang/en_utf8/admin.php
+++ b/lang/en_utf8/admin.php
@@ -527,8 +527,6 @@ It is recommended to install local copy of free GeoLite City database from MaxMi
IP address location is displayed on simple map or using Google Maps. Please note that you need to have a Google account and apply for free Google Maps API key to enable interactive maps.';
$string['iplookupmaxmindnote'] = 'This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/.';
$string['iplookupnetgeonote'] = 'The NetGeo server is currently being used to look up geographical information. For more accurate results we recommend installing a local copy of the MaxMind GeoLite database.';
-$string['ipwhitelist'] = 'IP whitelist';
-$string['ipwhitelistdesc'] = 'When not empty, only IP set here are allowed to use web service with the username: $a->username';
$string['keeptagnamecase'] = 'Keep tag name casing';
$string['lang'] = 'Default language';
$string['lang16notify'] = 'Moodle 1.6 and above allows you to install and update language packs directly from download.moodle.org by following the link below';
@@ -571,7 +569,6 @@ $string['maintfileopenerror'] = 'Error opening maintenance files!';
$string['maintinprogress'] = 'Maintenance is in progress...';
$string['managelang'] = 'Manage';
$string['manageqtypes'] = 'Manage question types';
-$string['managews'] = 'Manage web services';
$string['maintenancemode'] = 'In Maintenance Mode';
$string['maxbytes'] = 'Maximum uploaded file size';
$string['maxeditingtime'] = 'Maximum time to edit posts';
@@ -670,6 +667,7 @@ $string['php50restricted'] = 'PHP 5.0.x has a number of known problems, please u
$string['phpfloatproblem'] = 'Detected unexpected problem in handling of PHP float numbers - $a';
$string['pleaseregister'] = 'Please register your site to remove this button';
$string['pleaserefreshregistration'] = 'Your site has been registered with moodle.org, please consider updating the registration if significant changes happened since your last update, on $a';
+$string['plugin'] = 'Plugin';
$string['plugins'] = 'Plugins';
$string['profilecategory'] = 'Category';
$string['profilecategoryname'] = 'Category name (must be unique)';
@@ -832,6 +830,8 @@ $string['supportname'] = 'Support name';
$string['supportpage'] = 'Support page';
$string['switchlang'] = 'Switch lang directory';
$string['systempaths'] = 'System Paths';
+$string['tablenosave'] = 'Changes in table above are saved automatically.';
+$string['tablesnosave'] = 'Changes in tables above are saved automatically.';
$string['tabselectedtofront'] = 'On tables with tabs, should the row with the currently selected tab be placed at the front';
$string['tabselectedtofronttext'] = 'Bring selected tab row to front';
$string['themelist'] = 'Theme list';
@@ -849,6 +849,7 @@ $string['unicodeupgradenotice'] = 'In Moodle 1.6 we have migrated all languages
$string['unicoderecommended'] = 'Storing all your data in Unicode (UTF-8) is recommended. New installations should be performed into databases that have their default character set as Unicode. If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
$string['unicoderequired'] = 'It is required that you store all your data in Unicode format (UTF-8). New installations must be performed into databases that have their default character set as Unicode. If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
$string['uninstall'] = 'Uninstall selected language pack';
+$string['uninstallplugin'] = 'Uninstall';
$string['uninstallconfirm'] = 'You are about to completely uninstall language pack $a, are you sure?';
$string['uninstallqtype'] = 'Uninstall this question type.';
$string['unsupported'] = 'Unsupported';
@@ -931,7 +932,6 @@ $string['verifychangedemail'] = 'Restrict domains when changing email';
$string['warningcurrentsetting'] = 'Invalid current value: $a';
$string['webproxy'] = 'Web proxy';
$string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc. PHP cURL extension is highly recommended.';
-$string['webservices'] = 'Web services';
$string['xmlrpcrecommended'] = 'Installing the optional xmlrpc extension is useful for Moodle Networking functionality.';
$string['xmlstrictheaders'] = 'XML strict headers';
$string['useblogassociations'] = 'Enable associations';
diff --git a/lang/en_utf8/webservice.php b/lang/en_utf8/webservice.php
index 0847061da05..a3114fa5099 100644
--- a/lang/en_utf8/webservice.php
+++ b/lang/en_utf8/webservice.php
@@ -1,61 +1,25 @@
-Alert the Moodle administrator to set it Off.';
+SOAP Manual
- 1. Call the method get_token on \"http://remotemoodle/webservice/soap/server.php?wsdl\"
- The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")
- Return value is a token (integer)
-
- 2. Then call a moodle web service method on \"http://remotemoodle/webservice/soap/server.php?token=the_received_token&classpath=the_moodle_path&wsdl\"
- Every method has only one parameter which is an array.
-
- For example in PHP for this specific function:
- Moodle path: user
- tmp_delete_user( string username , integer mnethostid )
- You will call something like:
- your_client->tmp_delete_user(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1))
-';
-$string['systemsettings'] = 'Common settings';
-$string['usersettings'] = 'Users with web service permissions';
-$string['webservicesenable'] = 'Web services enable';
-$string['wsdeletefunction'] = '$a->functionname function has been deleted from the $a->servicename service.';
-$string['wsinsertfunction'] = '$a->functionname function has been inserted into the $a->servicename service.';
-$string['wspagetitle'] = 'Web services documentation';
-$string['wsuserreminder'] = 'Reminder: the Moodle administrator of this site needs to give you moodle/site:usewebservices capability.';
-$string['xmlrpcdocumentation'] = '
XMLRPC Manual
- 1. Call the method authentication.get_token on \"http://remotemoodle/webservice/xmlrpc/server.php\"
- The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")
- Return value is a token (integer)
-
- 2. Then call a moodle web service method on \"http://remotemoodle/webservice/xmlrpc/server.php?classpath=the_moodle_path&token=the_received_token\"
- Every method has only one parameter which is an array.
-
- For example in PHP for this specific function:
- Moodle path: user
- tmp_delete_user( string username , integer mnethostid )
- You will call something like:
- your_client->call(\"user.tmp_delete_user\", array(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1)))
-
-';
-
-//service names
-$string['user'] = "User";
-
+$string['externalservices'] = 'External services';
+$string['externalservice'] = 'External service';
+$string['externalservicefunctions'] = 'External service functions';
+$string['externalserviceusers'] = 'External service users';
+$string['function'] = 'Function';
+$string['functions'] = 'Functions';
+$string['manageprotocols'] = 'Manage protocols';
+$string['protocol'] = 'Protocol';
+$string['removefunction'] = 'Remove';
+$string['removefunctionconfirm'] = 'Do you really want to remove function \"$a->function\" from service \"$a->service\"?';
+$string['requiredcapability'] = 'Required capability';
+$string['restrictedusers'] = 'Restricted users';
+$string['servicesbuiltin'] = 'Built-in services';
+$string['servicescustom'] = 'Custom services';
+$string['test'] = 'Test';
+$string['testclient'] = 'Test client';
+$string['webservices'] = 'Web services';
diff --git a/lang/en_utf8/webservice_amf.php b/lang/en_utf8/webservice_amf.php
new file mode 100644
index 00000000000..f51fe76cb83
--- /dev/null
+++ b/lang/en_utf8/webservice_amf.php
@@ -0,0 +1,4 @@
+data[] =array($displayname, $hideshow, $updown, $settings);
}
$return .= $OUTPUT->table($table);
- $return .= get_string('configeditorplugins', 'editor').' '.get_string('tablenosave', 'filters');
+ $return .= get_string('configeditorplugins', 'editor').' '.get_string('tablenosave', 'admin');
$return .= $OUTPUT->box_end();
return highlight($query, $return);
}
@@ -6077,26 +6077,23 @@ class admin_setting_managerepository extends admin_setting {
}
}
-/**
- *
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class admin_setting_managewsprotocols extends admin_setting {
-/** @var string */
- private $baseurl;
+/**
+ * Special class for management of external services
+ *
+ * @author Petr Skoda (skodak)
+ */
+class admin_setting_manageexternalservices extends admin_setting {
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
- global $CFG;
- parent::__construct('managewsprotocols', get_string('managewsprotocols', 'admin'), '', '');
- $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey();
+ parent::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
}
/**
* Always returns true, does nothing
+ *
* @return true
*/
public function get_setting() {
@@ -6104,233 +6101,304 @@ class admin_setting_managewsprotocols extends admin_setting {
}
/**
- * Doesnt nothing, always returns ''
+ * Always returns true, does nothing
+ *
+ * @return true
+ */
+ public function get_defaultsetting() {
+ return true;
+ }
+
+ /**
+ * Always returns '', does not write anything
*
* @return string Always returns ''
*/
public function write_setting($data) {
- $url = $this->baseurl . '&new=' . $data;
+ // do not write any setting
return '';
}
/**
- * Builds XHTML to display the control
+ * Checks if $query is one of the available external services
*
- * @param string $data
- * @param string $query
- * @return string XHTML
+ * @param string $query The string to search for
+ * @return bool Returns true if found, false if not
*/
- public function output_html($data, $query='') {
- global $CFG, $OUTPUT;
+ public function is_related($query) {
+ global $DB;
- $namestr = get_string('name');
- $settingsstr = get_string('settings');
- $hiddenstr = get_string('activated', 'webservice');
- require_once("../webservice/lib.php");
- $protocols = webservice_lib::get_list_protocols();
- $table = new html_table();
- $table->head = array($namestr, $hiddenstr, $settingsstr);
- $table->align = array('left', 'center', 'center');
- $table->data = array();
- $table->tablealign = 'center';
+ if (parent::is_related($query)) {
+ return true;
+ }
- foreach ($protocols as $i) {
- $hidetitle = $i->get_protocolid() ? get_string('clicktodeactivate', 'webservice') : get_string('clicktoactivate', 'webservice');
- $hiddenshow = ' '
- .''
- .'' . "\n";
-
- $settingnames = $i->get_setting_names();
- if (!empty($settingnames)) {
- $settingsshow = ' '
- .$settingsstr
- .'' . "\n";
- } else {
- $settingsshow = "";
- }
- $table->data[] = array($i->get_protocolname(), $hiddenshow, $settingsshow);
-
- //display a grey row if the type is defined as not visible
- if (!$i->get_enable()) {
- $table->rowclasses[] = 'dimmed_text';
- } else {
- $table->rowclasses[] = '';
+ $textlib = textlib_get_instance();
+ $services = $DB->get_records('external_services', array(), 'id, name');
+ foreach ($services as $service) {
+ if (strpos($textlib->strtolower($service->name), $query) !== false) {
+ return true;
}
}
- $output = $OUTPUT->table($table);
- $output .= "
";
- return highlight($query, $output);
- }
-}
-
-/**
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class admin_setting_managewsusersettings extends admin_setting {
-/** @var string */
- private $baseurl;
-
- /**
- * Calls parent::__construct with specific arguments
- */
- public function __construct() {
- global $CFG;
- parent::__construct('managewsusersettings', get_string('managewsusersettings', 'admin'), '', '');
- $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey();
+ return false;
}
/**
- * Always returns true does nothing
- *
- * @return true
- */
- public function get_setting() {
- return true;
- }
-
- /**
- * Does nothing always returns ''
- *
- * @return string Always returns ''
- */
- public function write_setting($data) {
- $url = $this->baseurl . '&new=' . $data;
- return '';
- }
-
- /**
- * Build XHTML to display the control
+ * Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
- * @return string XHTML
- */
- public function output_html($data, $query='') {
- global $CFG, $OUTPUT;
- $output = "";
-
- //search all web service users
- $users = get_users(true, '', false, null, 'firstname ASC','', '', '', 1000);
-
- $table = new html_table();
- $table->head = array('username', 'whitelist');
- $table->align = array('left', 'center');
- $table->data = array();
- $table->tablealign = 'center';
-
- foreach ($users as $user) {
- if (has_capability("moodle/site:usewebservices",get_system_context(), $user->id)) { //test if the users has has_capability('use_webservice')
- $wsusersetting = ' '
- . get_string("settings")
- .'' . "\n";
- $table->data[] = array($user->username, $wsusersetting);
- }
- }
-
- $output .= $OUTPUT->table($table);
- $output .= "
";
- return highlight($query, $output);
- }
-}
-
-/**
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class admin_setting_managewsservicelist extends admin_setting {
-/** @var string */
- private $baseurl;
-
- /**
- * Calls parent::__construct with specific arguments
- */
- public function __construct() {
- global $CFG;
- parent::__construct('managewsservicelist', get_string('managewsservicelist', 'admin'), '', '');
- $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/webservices.php?sesskey=' . sesskey();
- }
-
- /**
- * Always returns true does nothing
- *
- * @return true
- */
- public function get_setting() {
- return true;
- }
-
- /**
- * Does nothing always returns ''
- *
- * @return string Always returns ''
- */
- public function write_setting($data) {
- $url = $this->baseurl . '&new=' . $data;
- return '';
- }
-
- /**
- * Build XHTML to display the control
- *
- * @param string $data Unused
- * @param string $query
- * @return string XHTML
+ * @return string
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT, $DB;
- $output = "
";
+ // display strings
+ $stradministration = get_string('administration');
+ $stredit = get_string('edit');
+ $strservice = get_string('externalservice', 'webservice');
+ $strdelete = get_string('delete');
+ $strplugin = get_string('plugin', 'admin');
+ $stradd = get_string('add');
+ $strfunctions = get_string('functions', 'webservice');
+ $strusers = get_string('restrictedusers', 'webservice');
+
+ $esurl = "$CFG->wwwroot/$CFG->admin/external_service.php";
+ $efurl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php";
+ $euurl = "$CFG->wwwroot/$CFG->admin/external_service_users.php";
+
+ // built in services
+ $return = $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main', true);
+
+ $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
+
$table = new html_table();
- $table->head = array(get_string('servicename','webservice'), get_string('custom','webservice'), get_string('activated','webservice'),get_string('activatedfunctions','webservice'),get_string('settings'));
- $table->align = array('left', 'center', 'center','center','center');
- $table->data = array();
- $table->tablealign = 'center';
+ $table->head = array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
+ $table->align = array('left', 'left', 'center', 'center', 'center');
+ $table->size = array('30%', '20%', '20%', '20%', '10%');
+ $table->width = '100%';
+ $table->data = array();
- //retrieve all services
- // $services = $DB->get_records('external_services',null,'custom DESC');
- $servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, s.id as serviceid, s.component as component, s.name as servicename, s.enabled as serviceenabled, f.name as functionname
- FROM {external_services} s, {external_functions} f, {external_services_functions} fs
- WHERE fs.externalserviceid = s.id AND fs.functionname = f.name ORDER BY s.name ASC");
+ // iterate through auth plugins and add to the display table
+ foreach ($services as $service) {
+ $name = $service->name;
- //create a services array
- $services = array();
- foreach($servicesfunctions as $servicefunction) {
- if (!array_key_exists($servicefunction->servicename, $services)) {
- $services[$servicefunction->servicename] = new object();
- $services[$servicefunction->servicename]->name = $servicefunction->servicename;
- $services[$servicefunction->servicename]->id = $servicefunction->serviceid;
- $services[$servicefunction->servicename]->enabled = $servicefunction->serviceenabled;
- $services[$servicefunction->servicename]->custom = $servicefunction->custom;
- $services[$servicefunction->servicename]->funcnb = 0;
- $services[$servicefunction->servicename]->enabledfuncnb = 0;
- }
- $services[$servicefunction->servicename]->funcnb = $services[$servicefunction->servicename]->funcnb +1;
- if ($servicefunction->functionenabled) {
- $services[$servicefunction->servicename]->enabledfuncnb = $services[$servicefunction->servicename]->enabledfuncnb +1;
+ // hide/show link
+ if ($service->enabled) {
+ $displayname = "$name";
+ } else {
+ $displayname = "$name";
}
+ $plugin = $service->component;
+
+ $functions = "id\">$strfunctions";
+
+ if ($service->restrictedusers) {
+ $users = "id\">$strusers";
+ } else {
+ $users = '-';
+ }
+
+ $edit = "id\">$stredit";
+
+ // add a row to the table
+ $table->data[] = array($displayname, $plugin, $functions, $users, $edit);
}
+ $return .= $OUTPUT->table($table);
- foreach($services as $service) {
- //$numberoffunc = $DB->count_records('external_services_functions',array('externalserviceid' => $service->id));
- $activated = ' '
- .''.'' ;
- $custom = ($service->custom ? get_string('yes') : '');
- $settings = $OUTPUT->link('/admin/webservices.php?serviceid='.$service->id.'&sesskey='.sesskey().'&settings=true',get_string('settings'));
- $table->data[] = array(get_string($service->name,'webservice'), $custom, $activated, $service->enabledfuncnb."/".$service->funcnb, $settings);
+ // Custom services
+ $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main', true);
+ $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
+
+ $table = new html_table();
+ $table->head = array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
+ $table->align = array('left', 'center', 'center', 'center', 'center');
+ $table->size = array('30%', '20%', '20%', '20%', '10%');
+ $table->width = '100%';
+ $table->data = array();
+
+ // iterate through auth plugins and add to the display table
+ foreach ($services as $service) {
+ $name = $service->name;
+
+ // hide/show link
+ if ($service->enabled) {
+ $displayname = "$name";
+ } else {
+ $displayname = "$name";
+ }
+
+ // delete link
+ $delete = "id\">$strdelete";
+
+ $functions = "id\">$strfunctions";
+
+ if ($service->restrictedusers) {
+ $users = "id\">$strusers";
+ } else {
+ $users = '-';
+ }
+
+ $edit = "id\">$stredit";
+
+ // add a row to the table
+ $table->data[] = array($displayname, $delete, $functions, $users, $edit);
}
+ // add new custom service option
+ $table->data[] = array('', '', '', '', "$stradd");
+ $return .= $OUTPUT->table($table);
- $output .= $OUTPUT->table($table);
+ $return .= ' '.get_string('tablesnosave', 'admin');
- $output .= ' ';
+ return highlight($query, $return);
+ }
+}
- return highlight($query, $output);
+/**
+ * Special class for web service protocol administration.
+ *
+ * @author Petr Skoda (skodak)
+ */
+class admin_setting_managewebserviceprotokols extends admin_setting {
+
+ /**
+ * Calls parent::__construct with specific arguments
+ */
+ public function __construct() {
+ parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
+ }
+
+ /**
+ * Always returns true, does nothing
+ *
+ * @return true
+ */
+ public function get_setting() {
+ return true;
+ }
+
+ /**
+ * Always returns true, does nothing
+ *
+ * @return true
+ */
+ public function get_defaultsetting() {
+ return true;
+ }
+
+ /**
+ * Always returns '', does not write anything
+ *
+ * @return string Always returns ''
+ */
+ public function write_setting($data) {
+ // do not write any setting
+ return '';
+ }
+
+ /**
+ * Checks if $query is one of the available webservices
+ *
+ * @param string $query The string to search for
+ * @return bool Returns true if found, false if not
+ */
+ public function is_related($query) {
+ if (parent::is_related($query)) {
+ return true;
+ }
+
+ $textlib = textlib_get_instance();
+ $protocols = get_plugin_list('webservice');
+ foreach ($protocols as $protocol=>$location) {
+ if (strpos($protocol, $query) !== false) {
+ return true;
+ }
+ $protocolstr = get_string('pluginname', 'webservice_'.$protocol);
+ if (strpos($textlib->strtolower($protocolstr), $query) !== false) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Builds the XHTML to display the control
+ *
+ * @param string $data Unused
+ * @param string $query
+ * @return string
+ */
+ public function output_html($data, $query='') {
+ global $CFG, $OUTPUT;
+
+ // display strings
+ $stradministration = get_string('administration');
+ $strsettings = get_string('settings');
+ $stredit = get_string('edit');
+ $strprotocol = get_string('protocol', 'webservice');
+ $strenable = get_string('enable');
+ $strdisable = get_string('disable');
+ $strversion = get_string('version');
+ $struninstall = get_string('uninstallplugin', 'admin');
+
+ $protocols_available = get_plugin_list('webservice');
+ $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+ ksort($protocols_available);
+
+ foreach ($active_protocols as $key=>$protocol) {
+ if (empty($protocols_available[$protocol])) {
+ unset($active_protocols[$key]);
+ }
+ }
+
+ $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main', true);
+ $return .= $OUTPUT->box_start('generalbox webservicesui');
+
+ $table = new html_table();
+ $table->head = array($strprotocol, $strversion, $strenable, $struninstall, $strsettings);
+ $table->align = array('left', 'center', 'center', 'center', 'center');
+ $table->width = '100%';
+ $table->data = array();
+
+ // iterate through auth plugins and add to the display table
+ $url = "$CFG->wwwroot/$CFG->admin/webservice_protocols.php?sesskey=" . sesskey();
+ foreach ($protocols_available as $protocol => $location) {
+ $name = get_string('pluginname', 'webservice_'.$protocol);
+
+ $plugin = new object();
+ if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/version.php')) {
+ include($CFG->dirroot.'/webservice/'.$protocol.'/version.php');
+ }
+ $version = isset($plugin->version) ? $plugin->version : '';
+
+ // hide/show link
+ if (in_array($protocol, $active_protocols)) {
+ $hideshow = "";
+ $hideshow .= "old_icon_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" />";
+ $displayname = "$name";
+ } else {
+ $hideshow = "";
+ $hideshow .= "old_icon_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" />";
+ $displayname = "$name";
+ }
+
+ // delete link
+ $uninstall = "$struninstall";
+
+ // settings link
+ if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) {
+ $settings = "$strsettings";
+ } else {
+ $settings = '';
+ }
+
+ // add a row to the table
+ $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
+ }
+ $return .= $OUTPUT->table($table);
+ $return .= get_string('configwebserviceplugins', 'webservice').' '.get_string('tablenosave', 'admin');
+ $return .= $OUTPUT->box_end();
+
+ return highlight($query, $return);
}
}
diff --git a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php
index ba91a2c3f82..d3381690495 100644
--- a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php
+++ b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php
@@ -941,14 +941,6 @@ get_string('allowbeforeblock', 'admin', NULL);
get_string('allowbeforeblockdesc', 'admin', NULL);
get_string('allowediplist', 'admin', NULL);
get_string('blockediplist', 'admin', NULL);
-get_string('webservices', 'admin', NULL);
-get_string('webserviceprotocols', 'admin', NULL);
-get_string('managewsprotocols', 'admin', NULL);
-get_string('managews', 'admin', NULL);
-get_string('webservicesystemsettings', 'admin', NULL);
-get_string('ipwhitelist', 'admin', NULL);
-get_string('webserviceusersettings', 'admin', NULL);
-get_string('managewsusersettings', 'admin', NULL);
get_string('sitepolicies', 'admin', NULL);
get_string('protectusernames', 'admin', NULL);
get_string('configprotectusernames', 'admin', NULL);
diff --git a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php
index 76261bda034..543029fee56 100644
--- a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php
+++ b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php
@@ -941,14 +941,6 @@ old_get_string('allowbeforeblock', 'admin', NULL);
old_get_string('allowbeforeblockdesc', 'admin', NULL);
old_get_string('allowediplist', 'admin', NULL);
old_get_string('blockediplist', 'admin', NULL);
-old_get_string('webservices', 'admin', NULL);
-old_get_string('webserviceprotocols', 'admin', NULL);
-old_get_string('managewsprotocols', 'admin', NULL);
-old_get_string('managews', 'admin', NULL);
-old_get_string('webservicesystemsettings', 'admin', NULL);
-old_get_string('ipwhitelist', 'admin', NULL);
-old_get_string('webserviceusersettings', 'admin', NULL);
-old_get_string('managewsusersettings', 'admin', NULL);
old_get_string('sitepolicies', 'admin', NULL);
old_get_string('protectusernames', 'admin', NULL);
old_get_string('configprotectusernames', 'admin', NULL);
diff --git a/webservice/lib.php b/webservice/lib.php
index 4e1c22359f0..b37a48c4816 100644
--- a/webservice/lib.php
+++ b/webservice/lib.php
@@ -1,394 +1,393 @@
.
+
/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
+ * Web services utility functions and classes
*
- * LICENSE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details:
- *
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @category Moodle
* @package webservice
* @copyright 2009 Moodle Pty Ltd (http://moodle.com)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-require_once(dirname(dirname(__FILE__)) . '/lib/formslib.php');
+require_once($CFG->libdir.'/externallib.php');
-/**
- * Returns detailed information about external function
- * @param string $functionname name of external function
- * @return aray
- */
-function ws_get_function_info($functionname) {
- global $CFG, $DB;
+function webservice_protocol_is_enabled($protocol) {
+ global $CFG;
- $function = $DB->get_record('external_functions', array('name'=>$functionname), '*', MUST_EXIST);
-
- $defpath = get_component_directory($function->component);
- if (!file_exists("$defpath/db/services.php")) {
- //TODO: maybe better throw invalid parameter exception
- return null;
+ if (empty($CFG->enablewebservices)) {
+ return false;
}
- $functions = array();
- include("$defpath/db/services.php");
+ $active = explode(',', $CFG->webserviceprotocols);
- if (empty($functions[$functionname])) {
- return null;
- }
-
- $desc = $functions[$functionname];
- if (empty($desc['classpath'])) {
- $desc['classpath'] = "$defpath/externallib.php";
- } else {
- $desc['classpath'] = "$CFG->dirroot/".$desc['classpath'];
- }
- $desc['component'] = $function->component;
-
- return $desc;
+ return(in_array($protocol, $active));
}
/**
- * web service library
+ * Mandatory web service server interface
+ * @author Petr Skoda (skodak)
*/
-final class webservice_lib {
-
-/**
- * Return list of all web service protocol into the webservice folder
- * @global $CFG
- * @return
- */
- public static function get_list_protocols() {
- global $CFG;
- $protocols = array();
- $directorypath = $CFG->dirroot . "/webservice";
- if( $dh = opendir($directorypath)) {
- while( false !== ($file = readdir($dh))) {
- if( $file == '.' || $file == '..' || $file == 'CVS') { // Skip '.' and '..'
- continue;
- }
- $path = $directorypath . '/' . $file;
- ///browse the subfolder
- if( is_dir($path) ) {
- if ($file != 'db') { //we don't want to browse the 'db' subfolder of webservice folder
- require_once($path."/lib.php");
- $classname = $file."_server";
- $protocols[] = new $classname;
- }
- }
- ///retrieve api.php file
- else {
- continue;
- }
- }
- closedir($dh);
- }
- return $protocols;
- }
-
+interface webservice_server {
/**
- * Temporary Authentication method to be modified/removed
- * @global $DB
- * @param $token
- * @return
+ * Process request from client.
+ * @param bool $simple use simple authentication
+ * @return void
*/
- public static function mock_check_token($token) {
- //fake test
- if ($token == 456) {
- ///retrieve the user
- global $DB;
- $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
-
- if (empty($user)) {
- return false;
- }
-
- return $user;
- } else {
- return false;
- }
- }
-
- /**
- * Retrieve all external.php from Moodle (except the one of the exception list)
- * @param $
- * @param $directorypath
- * @return boolean true if n
- */
- public static function setListApiFiles( &$files, $directorypath ) {
- global $CFG;
-
- if(is_dir($directorypath)) { //check that we are browsing a folder not a file
-
- if( $dh = opendir($directorypath)) {
- while( false !== ($file = readdir($dh))) {
-
- if( $file == '.' || $file == '..') { // Skip '.' and '..'
- continue;
- }
- $path = $directorypath . '/' . $file;
- ///browse the subfolder
- if( is_dir($path) ) {
- webservice_lib::setListApiFiles($files, $path);
- }
- ///retrieve api.php file
- else if ($file == "external.php") {
- $files[] = $path;
- }
- }
- closedir($dh);
-
- }
- }
-
- }
-
- /**
- * Check if the Moodle site has the web service protocol enable
- * @global object $CFG
- * @param string $protocol
- */
- function display_webservices_availability($protocol) {
- global $CFG;
-
- $available = true;
-
- echo get_string('webservicesenable','webservice').": ";
- if (empty($CFG->enablewebservices)) {
- echo "".get_string('fail','webservice')."";
- $available = false;
- } else {
- echo "".get_string('ok','webservice')."";
- }
- echo " ";
-
- foreach(webservice_lib::get_list_protocols() as $wsprotocol) {
- if (strtolower($wsprotocol->get_protocolid()) == strtolower($protocol)) {
- echo get_string('protocolenable','webservice',array($wsprotocol->get_protocolid())).": ";
- if ( get_config($wsprotocol-> get_protocolid(), "enable")) {
- echo "".get_string('ok','webservice')."";
- } else {
- echo "".get_string('fail','webservice')."";
- $available = false;
- }
- echo " ";
- continue;
- }
- }
-
- //check debugging
- if ($CFG->debugdisplay) {
- echo "".get_string('debugdisplayon','webservice')."";
- $available = false;
- }
-
- return $available;
- }
-
+ public function run($simple);
}
/**
- * Web Service server base class
+ * Special abstraction of our srvices that allows
+ * interaction with stock Zend ws servers.
+ * @author skodak
*/
-abstract class webservice_server {
+abstract class webservice_zend_server implements webservice_server {
+ //TODO: implement base class for all ws servers in zend framework
+ // the idea is to create one huge class on the fly, this class contains all
+ // methods user is allowed to access and contains all needed PHPDoc metadata.
+}
+
/**
- * Web Service Protocol name (eg. SOAP, REST, XML-RPC,...)
- * @var String
+ * Web Service server base class, this class handles both
+ * simple and token authentication.
+ * @author Petr Skoda (skodak)
*/
- private $protocolname;
+abstract class webservice_base_server implements webservice_server {
+
+ /** @property string $wsname name of the web server plugin */
+ protected $wsname = null;
+
+ /** @property bool $simple true if simple auth used */
+ protected $simple;
+
+ /** @property string $username name of local user */
+ protected $username = null;
+
+ /** @property string $password password of the local user */
+ protected $password = null;
+
+ /** @property string $token authentication token*/
+ protected $token = null;
+
+ /** @property array $parameters the function parameters - the real values submitted in the request */
+ protected $parameters = null;
+
+ /** @property string $functionname the name of the function that is executed */
+ protected $functionname = null;
+
+ /** @property object $function full function description */
+ protected $function = null;
+
+ /** @property mixed $returns function return value */
+ protected $returns = null;
/**
- * Web Service Protocol id (eg. soap, rest, xmlrpc...)
- * @var String
+ * Contructor
*/
- private $protocolid;
-
public function __construct() {
}
- abstract public function run();
+ /**
+ * This method parses the request input, it needs to get:
+ * 1/ user authentication - username+password or token
+ * 2/ function name
+ * 3/ function parameters
+ *
+ * @return void
+ */
+ abstract protected function parse_request();
- public function get_protocolname() {
- return $this->protocolname;
- }
+ /**
+ * Send the result of function call to the WS client.
+ * @return void
+ */
+ abstract protected function send_response();
- public function get_protocolid() {
- return $this->protocolid;
- }
+ /**
+ * Send the error information to the WS client.
+ * @param exception $ex
+ * @return void
+ */
+ abstract protected function send_error($ex=null);
- public function set_protocolname($protocolname) {
- $this->protocolname = $protocolname;
- }
- public function set_protocolid($protocolid) {
- $this->protocolid = $protocolid;
- }
+ /**
+ * Process request from client.
+ * @param bool $simple use simple authentication
+ * @return void
+ */
+ public function run($simple) {
+ $this->simple = $simple;
- public function get_enable() {
- return get_config($this->get_protocolid(), "enable");
- }
+ // we will probably need a lot of memory in some functions
+ @raise_memory_limit('128M');
- public function set_enable($enable) {
- set_config("enable", $enable, $this->get_protocolid());
+ // set some longer timeout, this script is not sending any output,
+ // this means we need to manually extend the timeout operations
+ // that need longer time to finish
+ external_api::set_timeout();
+
+ // set up exception handler first, we want to sent them back in correct format that
+ // the other system understands
+ // we do not need to call the original default handler because this ws handler does everything
+ set_exception_handler(array($this, 'exception_handler'));
+
+ // init all properties from the request data
+ $this->parse_request();
+
+ // authenticate user, this has to be done after the request parsing
+ // this also sets up $USER and $SESSION
+ $this->authenticate_user();
+
+ // find all needed function info and make sure user may actually execute the function
+ $this->load_function_info();
+
+ // finally, execute the function - any errors are catched by the default exception handler
+ $this->execute();
+
+ // send the results back in correct format
+ $this->send_response();
+
+ // session cleanup
+ $this->session_cleanup();
+
+ die;
}
/**
- * Names of the server settings
- * @return array
+ * Specialised exception handler, we can not use the standard one because
+ * it can not just print html to output.
+ *
+ * @param exception $ex
+ * @return void does not return
*/
- public static function get_setting_names() {
- return array();
+ public function exception_handler($ex) {
+ global $CFG, $DB, $SCRIPT;
+
+ // detect active db transactions, rollback and log as error
+ if ($DB->is_transaction_started()) {
+ error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT);
+ try {
+ // note: transaction blocks should never change current $_SESSION
+ $DB->rollback_sql();
+ } catch (Exception $ignored) {
+ }
+ }
+
+ // now let the plugin send the exception to client
+ $this->send_error($ex);
+
+ // some hacks might need a cleanup hook
+ $this->session_cleanup($ex);
+
+ // not much else we can do now, add some logging later
+ exit(1);
}
- public function settings_form(&$mform) {
- }
-
-}
-
-/**
- * Temporary authentication class to be removed/modified
- */
-class ws_authentication {
-/**
- *
- * @param object|struct $params
- * @return integer
- */
- function get_token($params) {
- $params->username = clean_param($params->username, PARAM_ALPHANUM);
- $params->password = clean_param($params->password, PARAM_ALPHANUM);
- if ($params->username == 'wsuser' && $params->password == 'wspassword') {
- return '456';
+ /**
+ * Future hook needed for emulated sessions.
+ * @param exception $exception null means normal termination, $exception received when WS call failed
+ * @return void
+ */
+ protected function session_cleanup($exception=null) {
+ if ($this->simple) {
+ // nothing needs to be done, there is no persistent session
} else {
- throw new moodle_exception('wrongusernamepassword');
+ // close emulated session if used
}
}
-}
-
-/**
- * Form for web service user settings (administration)
- */
-final class wsuser_form extends moodleform {
- protected $username;
/**
- * Definition of the moodleform
+ * Authenticate user using username+password or token.
+ * This function sets up $USER global.
+ * It is safe to use has_capability() after this.
+ * This method also verifies user is allowed to use this
+ * server.
+ * @return void
*/
- public function definition() {
- global $DB;
- $this->username = $this->_customdata['username'];
- $mform =& $this->_form;
+ protected function authenticate_user() {
+ global $CFG, $DB;
- $mform->addElement('hidden', 'username', $this->username);
- $mform->setType('username', PARAM_RAW);
- $param = new stdClass();
- $param->username = $this->username;
- $wsuser = $DB->get_record("user", array("username" => $this->username));
+ if (!NO_MOODLE_COOKIES) {
+ throw new coding_exception('Cookies must be disabled in WS servers!');
+ }
- $mform->addElement('text', 'ipwhitelist', get_string('ipwhitelist', 'admin'), array('value'=>get_user_preferences("ipwhitelist", "", $wsuser->id),'size' => '40'));
- $mform->addElement('static', null, '', get_string('ipwhitelistdesc','admin', $param));
+ if ($this->simple) {
+ if (!is_enabled_auth('webservice')) {
+ die('WS auth not enabled');
+ }
- $this->add_action_buttons(true, get_string('savechanges','admin'));
+ if (!$auth = get_auth_plugin('webservice')) {
+ die('WS auth missing');
+ }
+
+ if (!$this->username) {
+ throw new invalid_parameter_exception('Missing username');
+ }
+
+ if (!$this->password) {
+ throw new invalid_parameter_exception('Missing password');
+ }
+
+ if (!$auth->user_login_webservice($this->username, $this->password)) {
+ throw new invalid_parameter_exception('Wrong username or password');
+ }
+
+ $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
+
+ // now fake user login, the session is completely empty too
+ session_set_user($user);
+
+ if (!has_capability("webservice/$this->wsname:use", get_context_instance(CONTEXT_SYSTEM))) {
+ throw new invalid_parameter_exception('Access to web service not allowed');
+ }
+
+ } else {
+ //TODO: not implemented yet
+ die('token login not implemented yet');
+
+ // note we had to wait until here because we did not know the security context earlier
+ if (!has_capability("webservice/$this->wsname:use", $context)) {
+ throw new invalid_parameter_exception('Access to web service not allowed');
+ }
+ }
}
-}
-
-/**
- * Form for web service server settings (administration)
- */
-final class wssettings_form extends moodleform {
- protected $settings;
/**
- * Definition of the moodleform
+ * Fetches the function description from database,
+ * verifies user is allowed to use this function and
+ * loads all paremeters and return descriptions.
+ * @return void
*/
- public function definition() {
- global $DB,$CFG;
- $settings = $this->_customdata['settings'];
- $mform =& $this->_form;
+ protected function load_function_info() {
+ global $DB, $USER, $CFG;
- $mform->addElement('hidden', 'settings', $settings);
- $mform->setType('settings', PARAM_RAW);
- $param = new stdClass();
-
- require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
- $servername = $settings.'_server';
- $server = new $servername();
- $server->settings_form($mform);
-
- // set the data if we have some.
- $data = array();
- $option_names = $server->get_setting_names();
- foreach ($option_names as $config) {
- $data[$config] = get_config($settings, $config);
+ if (empty($this->functionname)) {
+ throw new invalid_parameter_exception('Missing function name');
}
- $this->set_data($data);
+
+ // function must exist
+ $function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST);
- $this->add_action_buttons(true, get_string('savechanges','admin'));
+ // now let's verify access control
+ if ($this->simple) {
+ // now make sure the function is listed in at least one service user is allowed to use
+ // allow access only if:
+ // 1/ entry in the external_services_users table if required
+ // 2/ validuntil not reached
+ // 3/ has capability if specified in service desc
+ // 4/ iprestriction
+
+ $sql = "SELECT s.*, NULL AS iprestriction
+ FROM {external_services} s
+ JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0 AND sf.functionname = :name1)
+ WHERE s.enabled = 1
+
+ UNION
+
+ SELECT s.*, su.iprestriction
+ FROM {external_services} s
+ JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1 AND sf.functionname = :name2)
+ JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
+ WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now";
+
+ $rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name1'=>$function->name, 'name2'=>$function->name, 'now'=>time()));
+ // now make sure user may access at least one service
+ $syscontext = get_context_instance(CONTEXT_SYSTEM);
+ $remoteaddr = getremoteaddr();
+ $allowed = false;
+ foreach ($rs as $service) {
+ if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) {
+ continue; // cap required, sorry
+ }
+ if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
+ continue; // wrong request source ip, sorry
+ }
+ $allowed = true;
+ break; // one service is enough, no need to continue
+ }
+ $rs->close();
+ if (!$allowed) {
+ throw new invalid_parameter_exception('Access to external function not allowed');
+ }
+ // now we finally know the user may execute this function,
+ // the last step is to set context restriction - in this simple case
+ // we use system context because each external system has different user account
+ // and we can manage everything through normal permissions.
+ external_api::set_context_restriction($syscontext);
+
+ } else {
+ //TODO: implement token security checks
+ die('not implemented yet');
+ }
+
+ // get the params and return descriptions of the function
+ unset($function->id); // we want to prevent any accidental db updates ;-)
+
+ $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath;
+ if (!file_exists($function->classpath)) {
+ throw new coding_exception('Can not find file with external function implementation');
+ }
+ require_once($function->classpath);
+
+ $function->parameters_method = $function->methodname.'_parameters';
+ $function->returns_method = $function->methodname.'_returns';
+
+ // make sure the implementaion class is ok
+ if (!method_exists($function->classname, $function->methodname)) {
+ throw new coding_exception('Missing implementation method');
+ }
+ if (!method_exists($function->classname, $function->parameters_method)) {
+ throw new coding_exception('Missing parameters description');
+ }
+ if (!method_exists($function->classname, $function->returns_method)) {
+ throw new coding_exception('Missing returned values description');
+ }
+
+ // fetch the parameters description
+ $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));
+ if (!($function->parameters_desc instanceof external_function_parameters)) {
+ throw new coding_exception('Invalid parameters description');
+ }
+
+ // fetch the return values description
+ $function->returns_desc = call_user_func(array($function->classname, $function->returns_method));
+ // null means void result or result is ignored
+ if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) {
+ throw new coding_exception('Invalid return description');
+ }
+
+ // we have all we need now
+ $this->function = $function;
}
-}
-
-/**
- * Form for web service server settings (administration)
- */
-final class wsservicesettings_form extends moodleform {
- protected $settings;
/**
- * Definition of the moodleform
+ * Execute previously loaded function using parameters parsed from the request data.
+ * @return void
*/
- public function definition() {
- global $DB,$CFG;
- $serviceid = $this->_customdata['serviceid'];
- $mform =& $this->_form;
+ protected function execute() {
+ // validate params, this also sorts the params properly, we need the correct order in the next part
+ $params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters);
- $mform->addElement('hidden', 'serviceid', $serviceid);
- $mform->setType('serviceid', PARAM_INT);
- $param = new stdClass();
-
- // require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
- // $servername = $settings.'_server';
- // $server = new $servername();
- // $server->settings_form($mform);
-
- // set the data if we have some.
- // $data = array();
- // $option_names = $server->get_setting_names();
- // foreach ($option_names as $config) {
- // $data[$config] = get_config($settings, $config);
- // }
- // $this->set_data($data);
- $service = $DB->get_record('external_services',array('id' => $serviceid));
-
- $mform->addElement('text', 'servicename', get_string('servicename', 'webservice'));
- $mform->setDefault('servicename',get_string($service->name, 'webservice'));
- if (!empty($serviceid)) {
- $mform->disabledIf('servicename', 'serviceid', 'eq', $serviceid);
- }
-
- if (empty($serviceid)) {
- //display list of functions to select
- }
-
- //display list of functions associated to the service
-
-
-
- $this->add_action_buttons(true, get_string('savechanges','admin'));
+ // execute - yay!
+ $this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params));
}
}
-?>
diff --git a/webservice/rest/db/access.php b/webservice/rest/db/access.php
new file mode 100644
index 00000000000..e5de8842a47
--- /dev/null
+++ b/webservice/rest/db/access.php
@@ -0,0 +1,12 @@
+ array(
+ 'captype' => 'read', // in fact this may be considered read and write at the same time
+ 'contextlevel' => CONTEXT_COURSE, // the context level should be probably CONTEXT_MODULE
+ 'legacy' => array(
+ ),
+ ),
+
+);
diff --git a/webservice/rest/lib.php b/webservice/rest/lib.php
deleted file mode 100644
index 324ce2f457a..00000000000
--- a/webservice/rest/lib.php
+++ /dev/null
@@ -1,59 +0,0 @@
-dirroot.'/webservice/lib.php');
-
-/*
- * Rest server class
- */
-final class rest_server extends webservice_server {
-
- public function __construct() {
-
- $this->set_protocolname("Rest");
- $this->set_protocolid("rest");
- }
-
- /**
- * Run REST server
- */
- public function run() {
- $enable = $this->get_enable();
- if (empty($enable)) {
- die;
- }
-
- require_once('locallib.php');
- //retrieve path and function name from the URL
- $rest_arguments = get_file_argument('server.php');
- header ("Content-type: text/xml");
- echo call_moodle_function($rest_arguments);
- }
-
-}
-
-
-
-?>
diff --git a/webservice/rest/locallib.php b/webservice/rest/locallib.php
index 1ed14f7b0bc..b1af6b7f5fb 100644
--- a/webservice/rest/locallib.php
+++ b/webservice/rest/locallib.php
@@ -1,233 +1,155 @@
.
+
/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
+ * REST web service implementation classes and methods.
*
- * LICENSE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details:
- *
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @category Moodle
* @package webservice
- * @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+require_once("$CFG->dirroot/webservice/lib.php");
/**
- * Rest library
- * @author Jerome Mouneyrac, Ferran Recio, David Castro Garcia
+ * REST service server implementation.
+ * @author Petr Skoda (skodak)
*/
-
-/**
- *
- * @author Jerome Mouneyrac
- * @global object $CFG
- * @param string $rest_arguments example: /mod/forum/get_discussion
- * @return string xml object
- */
-function call_moodle_function ($rest_arguments) {
- global $CFG, $USER;
-
- ///REST params conversion
- $functionname = substr($rest_arguments,strrpos($rest_arguments,"/")+1); //retrieve the function name (it's located after the last '/') in $rest_arguments
- //$rest_argument
- $apipath = substr($rest_arguments,0, strlen($rest_arguments) - strlen($functionname)); //api path is the other part of $rest_arguments
-
- $classname = str_replace('/', '_', $apipath); // convert '/' into '_' (e.g. /mod/forum/ => _mod_forum_)
- $classname = substr($classname,1, strlen($classname) - 1); //remove first _ (e.g. _mod_forum => mod_forum)
- $classname .= 'external';
-
- /// Authentication process
- /// TODO: this use a fake token => need to implement token generation
- $token = optional_param('token',null,PARAM_ALPHANUM);
- if (empty($token)) {
- if ($functionname != 'get_token') {
- throw new moodle_exception('identifyfirst');
- } else {
- /// TODO: authentication + token generation need to be implemented
- if (optional_param('username',null,PARAM_ALPHANUM) == 'wsuser' && optional_param('password',null,PARAM_ALPHANUM) == 'wspassword') {
- return '456';
- } else {
- throw new moodle_exception('wrongusernamepassword');
- }
- }
- } else {
- /// TODO: following function will need to be modified
- $user = mock_check_token($token);
- if (empty($user)) {
- throw new moodle_exception('wrongidentification');
- }
- else {
- /// TODO: probably change this
- $USER = $user;
- }
- }
-
- /// load the external class
- $file = $CFG->dirroot.$apipath.'external.php';
- $description = webservice_lib::generate_webservice_description($file, $classname);
-
- /// This following line is only REST protocol
- $params = retrieve_params ($description[$functionname]); //retrieve the REST params
-
- /// Generic part to any protocols
- if ($params === false) {
- //return an error message, the REST params doesn't match with the web service description
- }
-
- try {
- $res = call_user_func_array ( $classname.'::'.$functionname, array($params));
- } catch (moodle_exception $e) {
- return "".$e->getMessage()."";
- }
-
- ///Transform result into xml in order to send the REST response
- $key = key($description[$functionname]['return']);
-
- if (strpos($key,":")!==false) {
- $key = substr($key, strpos($key,":")+1);
- } else {
- $key = 'return';
- }
- $return = mdl_conn_rest_object_to_xml ($res,$key);
-
- return "$return";
-}
-
-/**
- * TODO: remove/rewrite this function
- * Mock function waiting for token system implementation
- * @param int $token
- * @return object|boolean
- */
-function mock_check_token($token) {
- //fake test
- if ($token == 456) {
- ///retrieve the user
- global $DB;
- $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
-
- if (empty($user)) {
- return false;
- }
-
- return $user;
- } else {
- return false;
- }
-}
-
- /**
- * Convert into a Moodle type
- * @param integer $param
- * @return string
+class webservice_rest_server extends webservice_base_server {
+ /**
+ * Contructor
*/
-function convert_paramtype($param) {
- switch ($param) {
- case "integer":
- return PARAM_NUMBER;
- break;
- case "integer":
- return PARAM_INT;
- break;
- case "boolean":
- return PARAM_BOOL;
- break;
- case "string":
- return PARAM_ALPHANUM;
- break;
- case "object":
- return PARAM_RAW;
- break;
- default:
- return PARAM_RAW;
- break;
+ public function __construct() {
+ parent::__construct();
+ $this->wsname = 'rest';
}
-}
-/**
- *
- * @author Jerome Mouneyrac
- * @param array $description
- * @return array
- */
-function retrieve_params ($description) {
- $params = array();
- //retrieve REST param matching the description (warning: PHP assign the first instanciation as the first position in the table)
- foreach ($description['params'] as $paramname => $paramtype) {
- $paramtype = convert_paramtype($paramtype);
- $value = optional_param($paramname,null,$paramtype);
- if (!empty($value)) {
- $params[$paramname] = $value;
+ /**
+ * This method parses the $_REQUEST superglobal and looks for
+ * the following information:
+ * 1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters)
+ * 2/ function name (wsfunction parameter)
+ * 3/ function parameters (all other parameters except those above)
+ *
+ * @return void
+ */
+ protected function parse_request() {
+ if ($this->simple) {
+ $this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null;
+ unset($_REQUEST['wsusername']);
+
+ $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
+ unset($_REQUEST['wspassword']);
+
+ $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
+ unset($_REQUEST['wsfunction']);
+
+ $this->parameters = $_REQUEST;
+
+ } else {
+ //TODO
+ die('not implemented yet');
}
}
- //retrieve REST optional params
- if (!empty($description['optional'])) {
- foreach ($description['optional'] as $paramname => $paramtype) {
- $paramtype = convert_paramtype($paramtype);
- $value = optional_param($paramname,null,$paramtype);
- if (!empty($value)) {
- $params[$paramname] = $value;
+
+ /**
+ * Send the result of function call to the WS client
+ * formatted as XML document.
+ * @return void
+ */
+ protected function send_response() {
+ $this->send_headers();
+ $xml = ''."\n";
+ $xml .= ''."\n";
+ $xml .= self::xmlize_result($this->returns, $this->function->returns_desc);
+ $xml .= ''."\n";
+ echo $xml;
+ }
+
+ /**
+ * Send the error information to the WS client
+ * formatted as XML document.
+ * @param exception $ex
+ * @return void
+ */
+ protected function send_error($ex=null) {
+ $this->send_headers();
+ $xml = ''."\n";
+ $xml .= ''."\n";
+ $xml .= ''.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').''."\n";
+ if (debugging() and isset($ex->debuginfo)) {
+ $xml .= ''.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').''."\n";
+ }
+ $xml .= ''."\n";
+ echo $xml;
+ }
+
+ /**
+ * Internal implementation - sending of page headers.
+ * @return void
+ */
+ protected function send_headers() {
+ header('Content-Type: application/xml');
+ header('Content-Disposition: inline; filename="response.xml"');
+ header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
+ header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
+ header('Pragma: no-cache');
+ header('Accept-Ranges: none');
+ }
+
+ /**
+ * Internal implementation - recursive function producing XML markup.
+ * @param mixed $returns
+ * @param $desc
+ * @return unknown_type
+ */
+ protected static function xmlize_result($returns, $desc) {
+ if ($desc === null) {
+ return '';
+
+ } else if ($desc instanceof external_value) {
+ //TODO: there should be some way to indicate the real NULL value
+ return ''.htmlentities($returns, ENT_COMPAT, 'UTF-8').''."\n";
+
+ } else if ($desc instanceof external_multiple_structure) {
+ $mult = ''."\n";
+ foreach ($returns as $val) {
+ $mult .= self::xmlize_result($val, $desc->content);
}
+ $mult .= ''."\n";
+ return $mult;
+
+ } else if ($desc instanceof external_single_structure) {
+ $single = ''."\n";
+ foreach ($desc->keys as $key=>$subdesc) {
+ if (!array_key_exists($key, $returns)) {
+ if ($subdesc->rewquired) {
+ $single .= 'Missing required key';
+ continue;
+ } else {
+ //optional field
+ continue;
+ }
+ }
+ $single .= ''.self::xmlize_result($returns[$key], $subdesc).''."\n";
+ }
+ $single .= ''."\n";
+ return $single;
}
}
- return $params;
}
-/**
- * auxiliar function for simplexml_object_to_xml
- * @author Ferran Recio, David Castro Garcia
- * @param $obj
- * @param $tag
- * @param $atts assoc array (key => value)
- * @return string
- */
-function mdl_conn_rest_object_to_xml ($obj, $tag,$atts=false) {
- $res = '';
- $tag_atts = '';
- if ($atts) {
- $main_atts = array();
- foreach ($atts as $att=>$val) {
- $main_atts[] = "$att=\"".urlencode($val)."\"";
- }
- if (count($main_atts)) $tag_atts = ' '.implode(' ',$main_atts);
- }
-
- //if is an object
- if (is_object($obj)) {
- $parts = get_object_vars($obj);
- foreach ($parts as $tag2 => $val) {
- $res.= mdl_conn_rest_object_to_xml ($val, $tag2);
- }
- return "<$tag$tag_atts>\n$res$tag>\n";
- }
- //if it's an array all elements will be inside te same tag but with a new atribute key
- if (is_array($obj)){
- if (!$atts) $atts = array();
- //we came from another array
- if (isset($atts['keys'])) $atts = array();
- foreach ($obj as $key=>$val) {
- $array_atts = $atts;
- $array_atts['key'] = $key;
- $res.= mdl_conn_rest_object_to_xml ($val, $tag,$array_atts);
- }
- return $res;
- }
- //any other type, just encapsule it
- $obj = htmlentities($obj);
- return "<$tag$tag_atts>$obj$tag>\n";
-
-}
-
-?>
\ No newline at end of file
diff --git a/webservice/rest/server.php b/webservice/rest/server.php
index 585159662df..0e9def198db 100644
--- a/webservice/rest/server.php
+++ b/webservice/rest/server.php
@@ -1,47 +1,38 @@
.
+
/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
+ * REST web service entry point. The authentication is done via tokens.
*
- * LICENSE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details:
- *
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @category Moodle
* @package webservice
- * @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-/**
- * REST Moodle server.
- *
- * NOTE: for this first implementation, REST requires implicit url encoded params.
- * It uses function get_file_argument to get them.
- *
- * @author Jerome Mouneyrac
- * @author Ferran Recio
- * @author David Castro Garcia
- */
+define('NO_MOODLE_COOKIES', true);
-require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
-require_once('lib.php');
+require('../../config.php');
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
-if (empty($CFG->enablewebservices)) {
+if (!webservice_protocol_is_enabled('rest')) {
die;
}
-$server = new rest_server();
-$server->run();
+$server = new webservice_rest_server();
+$server->run(false);
+die;
-?>
\ No newline at end of file
diff --git a/webservice/rest/simpleserver.php b/webservice/rest/simpleserver.php
index cb435233a56..73a5e08e0f1 100644
--- a/webservice/rest/simpleserver.php
+++ b/webservice/rest/simpleserver.php
@@ -16,575 +16,24 @@
// along with Moodle. If not, see .
/**
- * Sample simple REST web service server.
+ * REST web service entry point. The authentication is done via tokens.
*
- * This WS entry point accepts only users from the 'auth/webservice'
- * plugin. Enabling of webservice for each user is explicitly allowed
- * via records in the external_services_users table.
- *
- * @package moodlecore
- * @subpackage file
- * @copyright 2009 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-
-/*
- * NOTE: this is a proposal for a new WS server OOP framework
- *
- * I did not understand much how the WS protocols are supposed
- * to work, I just tried to create some clean abstraction that
- * should allow easy implementation of any protocol server.
- * The REST was chosen only because it seems to be the easiest
- * one with no real standardisation ;-)
- *
- * == How to test this ==
- * 1/ create new service that includes function 'moodle_group_get_groups' by adding new local plugin,
- * this adds new record into external_services table
- * 2/ create new user and select 'webservice' as auth plugin and enable webservice auth plugin
- * 3/ add $CFG->enablesimplewebservices=true; to your config.php
- * 4/ manually enable the rest service: set_config('enable', 1, 'rest');
- * 5/ manually insert record into external_services_users - your new service + your new user
- * 6/ create course with some groups
- * 7/ execute the REST query: http://nahore.skodak.local/moodle20/webservice/rest/simpleserver.php?wsusername=a&wspassword=p&wsfunction=moodle_group_get_groups&groupids[0]=1&groupids[1]=3
- * 8/ sit tight and watch in awe the super hyper mega cool xml response of fully working REST WS server :-)
- *
- * skodak
- */
-
-
define('NO_MOODLE_COOKIES', true);
require('../../config.php');
-require_once("$CFG->libdir/externallib.php");
-//require_once("$CFG->dirroot/webservice/rest/lib.php"); TODO: uncomment when rewrite finished
-//require_once("$CFG->dirroot/webservice/rest/locallib.php"); TODO: uncomment when rewrite finished
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
-
-
-//======== NOTE: this should be defined in /webservice/rest/locallib.php =============================
-
-/**
- * REST service server class.
- *
- * @author Petr Skoda (skodak)
- */
-class webservice_rest_server extends webservice_base_server {
- /**
- * Contructor
- * @param bool $simple use simple authentication
- */
- public function __construct($simple) {
- parent::__construct($simple);
- $this->wsname = 'rest';
- }
-
- /**
- * This method parses the $_REQUEST superglobal and looks for
- * the following information:
- * 1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters)
- * 2/ function name (wsfunction parameter)
- * 3/ function parameters (all other parameters except those above)
- *
- * @return void
- */
- protected function parse_request() {
- if ($this->simple) {
- $this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null;
- unset($_REQUEST['wsusername']);
-
- $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
- unset($_REQUEST['wspassword']);
-
- $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
- unset($_REQUEST['wsfunction']);
-
- $this->parameters = $_REQUEST;
-
- } else {
- //TODO
- die('not implemented yet');
- }
- }
-
- /**
- * Send the result of function call to the WS client
- * formatted as XML document.
- * @return void
- */
- protected function send_response() {
- $this->send_headers();
- $xml = ''."\n";
- $xml .= ''."\n";
- $xml .= self::xmlize_result($this->returns, $this->function->returns_desc);
- $xml .= ''."\n";
- echo $xml;
- }
-
- /**
- * Send the error information to the WS client
- * formatted as XML document.
- * @param exception $ex
- * @return void
- */
- protected function send_error($ex=null) {
- $this->send_headers();
- $xml = ''."\n";
- $xml .= ''."\n";
- $xml .= ''.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').''."\n";
- if (debugging() and isset($ex->debuginfo)) {
- $xml .= ''.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').''."\n";
- }
- $xml .= ''."\n";
- echo $xml;
- }
-
- /**
- * Internal implementation - sending of page headers.
- * @return void
- */
- protected function send_headers() {
- header('Content-Type: application/xml');
- header('Content-Disposition: inline; filename="response.xml"');
- header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
- header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
- header('Pragma: no-cache');
- header('Accept-Ranges: none');
- }
-
- /**
- * Internal implementation - recursive function producing XML markup.
- * @param mixed $returns
- * @param $desc
- * @return unknown_type
- */
- protected static function xmlize_result($returns, $desc) {
- if ($desc === null) {
- return '';
-
- } else if ($desc instanceof external_value) {
- //TODO: there should be some way to indicate the real NULL value
- return ''.htmlentities($returns, ENT_COMPAT, 'UTF-8').''."\n";
-
- } else if ($desc instanceof external_multiple_structure) {
- $mult = ''."\n";
- foreach ($returns as $val) {
- $mult .= self::xmlize_result($val, $desc->content);
- }
- $mult .= ''."\n";
- return $mult;
-
- } else if ($desc instanceof external_single_structure) {
- $single = ''."\n";
- foreach ($desc->keys as $key=>$subdesc) {
- if (!array_key_exists($key, $returns)) {
- if ($subdesc->rewquired) {
- $single .= 'Missing key';
- continue;
- } else {
- //optional field
- continue;
- }
- }
- $single .= ''.self::xmlize_result($returns[$key], $subdesc).''."\n";
- }
- $single .= ''."\n";
- return $single;
- }
- }
-}
-
-
-
-
-//======== NOTE: this should be defined in /webservice/lib.php =============================
-
-/**
- * Web Service server base class, this class handles both
- * simple and token authentication.
- */
-abstract class webservice_base_server {
-
- /** @property string $wsname name of the web server plugin */
- protected $wsname = null;
-
- /** @property bool $simple true if simple auth used */
- protected $simple;
-
- /** @property string $username name of local user */
- protected $username = null;
-
- /** @property string $password password of the local user */
- protected $password = null;
-
- /** @property string $token authentication token*/
- protected $token = null;
-
- /** @property array $parameters the function parameters - the real values submitted in the request */
- protected $parameters = null;
-
- /** @property string $functionname the name of the function that is executed */
- protected $functionname = null;
-
- /** @property object $function full function description */
- protected $function = null;
-
- /** @property mixed $returns function return value */
- protected $returns = null;
-
- /**
- * Contructor
- * @param bool $simple use simple authentication
- */
- public function __construct($simple) {
- $this->simple = $simple;
- }
-
- /**
- * This method parses the request input, it needs to get:
- * 1/ user authentication - username+password or token
- * 2/ function name
- * 3/ function parameters
- *
- * @return void
- */
- abstract protected function parse_request();
-
- /**
- * Send the result of function call to the WS client.
- * @return void
- */
- abstract protected function send_response();
-
- /**
- * Send the error information to the WS client.
- * @param exception $ex
- * @return void
- */
- abstract protected function send_error($ex=null);
-
-
- public function run() {
- // first make sure this service is enabled
- if (!$this->is_enabled()) {
- die();
- }
-
- // we will probably need a lot of memory in some functions
- @raise_memory_limit('128M');
-
- // set some longer timeout, this script is not sending any output,
- // this means we need to manually extend the timeout operations
- // that need longer time to finish
- external_api::set_timeout();
-
- // set up exception handler first, we want to sent them back in correct format that
- // the other system understands
- // we do not need to call the original default handler because this ws handler does everything
- set_exception_handler(array($this, 'exception_handler'));
-
- // init all properties from the request data
- $this->parse_request();
-
- // authenticate user, this has to be done after the request parsing
- // this also sets up $USER and $SESSION
- $this->authenticate_user();
-
- // find all needed function info and make sure user may actually execute the function
- $this->load_function_info();
-
- // finally, execute the function - any errors are catched by the default exception handler
- $this->execute();
-
- // send the results back in correct format
- $this->send_response();
-
- // session cleanup
- $this->session_cleanup();
-
- die;
- }
-
- /**
- * Specialised exception handler, we can not use the standard one because
- * it can not just print html to output.
- *
- * @param exception $ex
- * @return void does not return
- */
- public function exception_handler($ex) {
- global $CFG, $DB, $SCRIPT;
-
- // detect active db transactions, rollback and log as error
- if ($DB->is_transaction_started()) {
- error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT);
- try {
- // note: transaction blocks should never change current $_SESSION
- $DB->rollback_sql();
- } catch (Exception $ignored) {
- }
- }
-
- // now let the plugin send the exception to client
- $this->send_error($ex);
-
- // some hacks might need a cleanup hook
- $this->session_cleanup($ex);
-
- // not much else we can do now, add some logging later
- exit(1);
- }
-
- /**
- * Future hook needed for emulated sessions.
- * @param exception $exception null means normal termination, $exception received when WS call failed
- * @return void
- */
- protected function session_cleanup($exception=null) {
- if ($this->simple) {
- // nothing needs to be done, there is no persistent session
- } else {
- // close emulated session if used
- }
- }
-
- /**
- * Authenticate user using username+password or token.
- * This function sets up $USER global.
- * It is safe to use has_capability() after this.
- * This method also verifies user is allowed to use this
- * server.
- * @return void
- */
- protected function authenticate_user() {
- global $CFG, $DB;
-
- if (!NO_MOODLE_COOKIES) {
- throw new coding_exception('Cookies must be disabled in WS servers!');
- }
-
- if ($this->simple) {
- if (!is_enabled_auth('webservice')) {
- die('WS auth not enabled');
- }
-
- if (!$auth = get_auth_plugin('webservice')) {
- die('WS auth missing');
- }
-
- if (!$this->username) {
- throw new invalid_parameter_exception('Missing username');
- }
-
- if (!$this->password) {
- throw new invalid_parameter_exception('Missing password');
- }
-
- if (!$auth->user_login_webservice($this->username, $this->password)) {
- throw new invalid_parameter_exception('Wrong username or password');
- }
-
- $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
-
- // now fake user login, the session is completely empty too
- session_set_user($user);
-
- /* //TODO: add web service usage capabilities
- if (!has_capability("webservice/$this->wsname:usesimple", get_context_instance(CONTEXT_SYSTEM))) {
- throw new invalid_parameter_exception('Access to web service not allowed');
- }
- */
-
- } else {
- //TODO: not implemented yet
- die('token login not implemented yet');
-
- /* //TODO: add web service usage capabilities
- // note we had to wait until here because we did not know the security context earlier
- if (!has_capability("webservice/$this->wsname:use", $context)) {
- throw new invalid_parameter_exception('Access to web service not allowed');
- }
- */
- }
- }
-
- /**
- * Fetches the function description from database,
- * verifies user is allowed to use this function and
- * loads all paremeters and return descriptions.
- * @return void
- */
- protected function load_function_info() {
- global $DB, $USER, $CFG;
-
- if (empty($this->functionname)) {
- throw new invalid_parameter_exception('Missing function name');
- }
-
- // function must exist
- $function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST);
-
-
- // now let's verify access control
- if ($this->simple) {
- // now make sure the function is listed in at least one service user is allowed to use
- // allow access only if:
- // 1/ entry in the external_services_users table - the restricted users flag is ignored in service desc
- // 2/ validuntil not reached
- // 3/ has capability if specified in service desc
- // 4/ iprestriction
-
- $sql = "SELECT s.*, su.iprestriction
- FROM {external_services} s
- JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND sf.functionname = :name)
- JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
- WHERE su.validuntil IS NULL OR su.validuntil < :now";
- $rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name'=>$function->name, 'now'=>time()));
- // now make sure user may access at least one service
- $syscontext = get_context_instance(CONTEXT_SYSTEM);
- $remoteaddr = getremoteaddr();
- $allowed = false;
- foreach ($rs as $service) {
- if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) {
- continue; // cap required, sorry
- }
- if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
- continue; // wrong request source ip, sorry
- }
- $allowed = true;
- break; // one service is enough, no need to continue
- }
- $rs->close();
- if (!$allowed) {
- throw new invalid_parameter_exception('Access to external function not allowed');
- }
- // now we finally know the user may execute this function,
- // the last step is to set context restriction - in this simple case
- // we use system context because each external system has different user account
- // and we can manage everything through normal permissions.
- external_api::set_context_restriction($syscontext);
-
- } else {
- //TODO: implement token security checks
- die('not implemented yet');
- }
-
- // get the params and return descriptions of the function
- unset($function->id); // we want to prevent any accidental db updates ;-)
-
- $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath;
- if (!file_exists($function->classpath)) {
- throw new coding_exception('Can not find file with external function implementation');
- }
- require_once($function->classpath);
-
- $function->parameters_method = $function->methodname.'_parameters';
- $function->returns_method = $function->methodname.'_returns';
-
- // make sure the implementaion class is ok
- if (!method_exists($function->classname, $function->methodname)) {
- throw new coding_exception('Missing implementation method');
- }
- if (!method_exists($function->classname, $function->parameters_method)) {
- throw new coding_exception('Missing parameters description');
- }
- if (!method_exists($function->classname, $function->returns_method)) {
- throw new coding_exception('Missing returned values description');
- }
-
- // fetch the parameters description
- $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));
- if (!($function->parameters_desc instanceof external_function_parameters)) {
- throw new coding_exception('Invalid parameters description');
- }
-
- // fetch the return values description
- $function->returns_desc = call_user_func(array($function->classname, $function->returns_method));
- // null means void result or result is ignored
- if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) {
- throw new coding_exception('Invalid return description');
- }
-
- // we have all we need now
- $this->function = $function;
- }
-
- /**
- * Execute previously loaded function using parameters parsed from the request data.
- * @return void
- */
- protected function execute() {
- // validate params, this also sorts the params properly, we need the correct order in the next part
- $params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters);
-
- // execute - yay!
- $this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params));
- }
-
- /**
- * Returns human readable protocol name.
- * @return string
- */
- public function get_protocolname() {
- return get_string('protocolname', 'webservice_'.$this->wsname); //TODO: add to lang pack
- }
-
- /**
- * Returns WS plugin name (not localized)
- * @return string
- */
- public function get_name() {
- return $this->wsname;
- }
-
- /**
- * Is this WS server plugin enabled?
- * @return bool
- */
- public function is_enabled() {
- return get_config($this->wsname, 'enable');
- }
-
- /**
- * Change enabled flag
- * @param bool $enable
- * @return void
- */
- public function set_enable($enable) {
- set_config('enable', $enable, $this->wsname);
- }
-
- /**
- * Returns the settings form,
- * the current data and defaults are already loaded.
- * @return moodleform or null if settings not used
- */
- public function settings_form() {
- //NOTE: store the form definition in separate file, not directly in lib.php!!
- return null;
- }
-
- /**
- * Saves settings form data to db.
- * @param array $data
- * @return void
- */
- public function settings_save($data) {
- return;
- }
-}
-
-
-
-//======== NOTE: this is finally the code that would be in this file =============================
-
-
-if (empty($CFG->enablesimplewebservices)) {
+if (!webservice_protocol_is_enabled('rest')) {
die;
}
-$server = new webservice_rest_server(true);
-$server->run();
+$server = new webservice_rest_server();
+$server->run(true);
die;
diff --git a/webservice/rest/testclient/addgroupmember.php b/webservice/rest/testclient/addgroupmember.php
deleted file mode 100644
index 61a7b9e8e6f..00000000000
--- a/webservice/rest/testclient/addgroupmember.php
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-serverurl.'/group/add_groupmember');
-
-
- //we are asking for a token
- $connectiondata['username'] = 'wsuser';
- $connectiondata['password'] = 'wspassword';
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
- $token = curl_exec($ch);
-
- $data['token'] = $token;
- $data['groupid'] = $groupid;
- $data['userid'] = $userid;
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/add_groupmember');
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
- $out = curl_exec($ch);
-
- $res = basicxml_xml_to_object($out);
-
- show_object($res->result);
-
- show_xml ($out);
-} else {
- echo "