--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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);
+ }
+}
--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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();
+
--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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 = "<a href=\"$durl&action=delete&fid=$function->id&id=$service->id\">$strdelete</a>";
+ $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();
+
--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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
}
}
+ // 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());
'', ''));
$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));
} // end of speedup
-?>
+
--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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);
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-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 .= "<br/><br/>";
- //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, "<a href=?sesskey=".sesskey()."&serviceid=".$serviceid."&remove=1&functionserviceid=".$servicefunction->id.">".get_string("removefunctionfromservice","webservice")."</a>");
- }
- $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 .= "<br/><br/>";
-
- echo $OUTPUT->box_start('generalbox boxaligncenter centerpara');
- echo $OUTPUT->form($form, $formhtml);
- echo $OUTPUT->box_end();
-
- echo $OUTPUT->footer();
-
-}
-
-?>
+++ /dev/null
-<?php
-// $Id$
-require_once(dirname(dirname(__FILE__)) . '/config.php');
-require_once($CFG->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();
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 <a href=\"http://www.maxmind.com/\">http://www.maxmind.com/</a>.';
$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: <strong>$a->username</strong>';
$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';
$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';
$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)';
$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';
$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';
$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.<br /><em>PHP cURL extension is highly recommended.</em>';
-$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';
-<?php // $Id$
-$string['activated'] = 'Activated';
-$string['activatedfunctions'] = 'Activated functions';
-$string['amfdebug'] = 'AMF server debug mode';
-$string['clicktoactivate'] = 'Click to activate';
-$string['clicktodeactivate'] = 'Click to deactivate';
-$string['component'] = 'Component';
-$string['createservicelabel'] = 'Create a custom service';
-$string['custom'] = 'Custom';
-$string['debugdisplayon'] = '\"Display debug messages\" is set On. The XMLRPC server will not work. The other web service servers could also return some problems. <br/>Alert the Moodle administrator to set it Off.';
-$string['enabled'] = 'Enabled';
-$string['fail'] = 'FAIL';
-$string['functionlist'] = 'list of web service functions';
-$string['functionname'] = 'Function name';
-$string['moodlepath'] = 'Moodle path';
-$string['ok'] = 'OK';
-$string['protocolenable'] = '$a[0] protocol enable';
-$string['protocols'] = 'Protocols';
-$string['save'] = 'Save';
-$string['servicelist'] = 'Services';
-$string['servicename'] = 'Service name';
-$string['soapdocumentation'] = '<H2>SOAP Manual</H2>
- <b>1.</b> Call the method <b>get_token</b> on \"<i>http://remotemoodle/webservice/soap/server.php?wsdl</i>\"<br>
- The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")<br>
- Return value is a token (integer)<br>
- <br>
- <b>2.</b> Then call a moodle web service method on \"<i>http://remotemoodle/webservice/soap/server.php?token=the_received_token&classpath=the_moodle_path&wsdl</i>\"<br>
- Every method has only one parameter which is an array.<br>
- <br>
- For example in PHP for this specific function:<br>
- Moodle path: <b>user</b><br>
- <b>tmp_delete_user</b>( string username , integer mnethostid )<br>
- You will call something like:<br>
- your_client->tmp_delete_user(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1))<br><br>
-';
-$string['systemsettings'] = 'Common settings';
-$string['usersettings'] = 'Users with web service permissions';
-$string['webservicesenable'] = 'Web services enable';
-$string['wsdeletefunction'] = '<b>$a->functionname</b> function has been deleted from the <b>$a->servicename</b> service.';
-$string['wsinsertfunction'] = '<b>$a->functionname</b> function has been inserted into the <b>$a->servicename</b> 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'] = '<H2>XMLRPC Manual</H2>
- <b>1.</b> Call the method <b>authentication.get_token</b> on \"<i>http://remotemoodle/webservice/xmlrpc/server.php</i>\"<br>
- The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")<br>
- Return value is a token (integer)<br>
- <br>
- <b>2.</b> Then call a moodle web service method on \"<i>http://remotemoodle/webservice/xmlrpc/server.php?classpath=the_moodle_path&token=the_received_token</i>\"<br>
- Every method has only one parameter which is an array.<br>
- <br>
- For example in PHP for this specific function:<br>
- Moodle path: <b>user</b><br>
- <b>tmp_delete_user</b>( string username , integer mnethostid )<br>
- You will call something like:<br>
- your_client->call(\"user.tmp_delete_user\", array(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1)))<br>
-
-';
-
-//service names
-$string['user'] = "User";
+<?php
+$string['addfunction'] = 'Add function';
+$string['actwebserviceshhdr'] = 'Active web service protocols';
+$string['configwebserviceplugins'] = 'For security reasons enable only protocols that are used.';
+$string['deleteserviceconfirm'] = 'Do you really want to delete external service \"$a\"?';
+$string['disabledwarning'] = 'All webs service protocols are disabled, the \Enable web services\" setting can be found in the \"Advanced features\" section.';
+$string['enabled'] = 'Enabled';
+$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';
--- /dev/null
+<?php
+
+$string['amfdebug'] = 'AMF server debug mode';
+$string['pluginname'] = 'AMF protocok';
--- /dev/null
+<?php
+
+$string['pluginname'] = 'REST protocol';
--- /dev/null
+<?php
+
+$string['pluginname'] = 'SOAP protocol';
--- /dev/null
+<?php
+
+$string['pluginname'] = 'XMLRPC protocol';
$table->data[] =array($displayname, $hideshow, $updown, $settings);
}
$return .= $OUTPUT->table($table);
- $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'filters');
+ $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
$return .= $OUTPUT->box_end();
return highlight($query, $return);
}
}
}
+
/**
+ * Special class for management of external services
*
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @author Petr Skoda (skodak)
*/
-class admin_setting_managewsprotocols extends admin_setting {
-/** @var string */
- private $baseurl;
-
+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() {
}
/**
- * 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 The string to search for
+ * @return bool Returns true if found, false if not
+ */
+ public function is_related($query) {
+ global $DB;
+
+ if (parent::is_related($query)) {
+ return true;
+ }
+
+ $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;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Builds the 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;
+ global $CFG, $OUTPUT, $DB;
+
+ // 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');
- $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';
+ $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();
- foreach ($protocols as $i) {
- $hidetitle = $i->get_protocolid() ? get_string('clicktodeactivate', 'webservice') : get_string('clicktoactivate', 'webservice');
- $hiddenshow = ' <a href="' . $this->baseurl . '&hide=' . $i->get_protocolid() . '">'
- .'<img src="' . $OUTPUT->old_icon_url('i/' . ($i->get_enable() ? 'hide' : 'show')) . '"'
- .' alt="' . $hidetitle . '" '
- .' title="' . $hidetitle . '" />'
- .'</a>' . "\n";
+ // iterate through auth plugins and add to the display table
+ foreach ($services as $service) {
+ $name = $service->name;
- $settingnames = $i->get_setting_names();
- if (!empty($settingnames)) {
- $settingsshow = ' <a href="' . $this->baseurl . '&settings=' . $i->get_protocolid() . '">'
- .$settingsstr
- .'</a>' . "\n";
+ // hide/show link
+ if ($service->enabled) {
+ $displayname = "<span>$name</span>";
} else {
- $settingsshow = "";
+ $displayname = "<span class=\"dimmed_text\">$name</span>";
}
- $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';
+ $plugin = $service->component;
+
+ $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
+
+ if ($service->restrictedusers) {
+ $users = "<a href=\"$euurl?id=$service->id\">$strusers</a>";
} else {
- $table->rowclasses[] = '';
+ $users = '-';
}
- }
- $output = $OUTPUT->table($table);
- $output .= "<br/><br/>";
- 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;
+ $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
- /**
- * 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();
- }
+ // add a row to the table
+ $table->data[] = array($displayname, $plugin, $functions, $users, $edit);
+ }
+ $return .= $OUTPUT->table($table);
- /**
- * Always returns true does nothing
- *
- * @return true
- */
- public function get_setting() {
- return true;
- }
+ // Custom services
+ $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main', true);
+ $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
- /**
- * Does nothing always returns ''
- *
- * @return string Always returns ''
- */
- public function write_setting($data) {
- $url = $this->baseurl . '&new=' . $data;
- return '';
- }
+ $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();
- /**
- * Build 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 = "";
+ // iterate through auth plugins and add to the display table
+ foreach ($services as $service) {
+ $name = $service->name;
+
+ // hide/show link
+ if ($service->enabled) {
+ $displayname = "<span>$name</span>";
+ } else {
+ $displayname = "<span class=\"dimmed_text\">$name</span>";
+ }
- //search all web service users
- $users = get_users(true, '', false, null, 'firstname ASC','', '', '', 1000);
+ // delete link
+ $delete = "<a href=\"$esurl?action=delete&sesskey=".sesskey()."&id=$service->id\">$strdelete</a>";
- $table = new html_table();
- $table->head = array('username', 'whitelist');
- $table->align = array('left', 'center');
- $table->data = array();
- $table->tablealign = 'center';
+ $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
- 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 = ' <a href="' . $this->baseurl . '&username=' . $user->username . '">'
- . get_string("settings")
- .'</a>' . "\n";
- $table->data[] = array($user->username, $wsusersetting);
+ if ($service->restrictedusers) {
+ $users = "<a href=\"$euurl?id=$service->id\">$strusers</a>";
+ } else {
+ $users = '-';
}
+
+ $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
+
+ // add a row to the table
+ $table->data[] = array($displayname, $delete, $functions, $users, $edit);
}
+ // add new custom service option
+ $table->data[] = array('', '', '', '', "<a href=\"$esurl?id=0\">$stradd</a>");
+ $return .= $OUTPUT->table($table);
- $output .= $OUTPUT->table($table);
- $output .= "<br/><br/>";
- return highlight($query, $output);
+ $return .= '<br />'.get_string('tablesnosave', 'admin');
+
+ return highlight($query, $return);
}
}
/**
+ * Special class for web service protocol administration.
*
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @author Petr Skoda (skodak)
*/
-class admin_setting_managewsservicelist extends admin_setting {
-/** @var string */
- private $baseurl;
+class admin_setting_managewebserviceprotokols extends admin_setting {
/**
* 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();
+ parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
}
/**
- * Always returns true does nothing
+ * Always returns true, does nothing
*
* @return true
*/
}
/**
- * Does 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 '';
}
/**
- * Build XHTML to display the control
+ * 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 XHTML
+ * @return string
*/
public function output_html($data, $query='') {
- global $CFG, $OUTPUT, $DB;
- $output = "<div style=\"text-align:center;\">";
+ global $CFG, $OUTPUT;
- $output .= $OUTPUT->link('/admin/webservices.php?sesskey='.sesskey().'&create=true',get_string('createservicelabel', 'webservice'));
- $output .= "</div>";
- $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';
+ // 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');
- //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");
+ $protocols_available = get_plugin_list('webservice');
+ $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+ ksort($protocols_available);
- //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;
+ foreach ($active_protocols as $key=>$protocol) {
+ if (empty($protocols_available[$protocol])) {
+ unset($active_protocols[$key]);
}
- $services[$servicefunction->servicename]->funcnb = $services[$servicefunction->servicename]->funcnb +1;
- if ($servicefunction->functionenabled) {
- $services[$servicefunction->servicename]->enabledfuncnb = $services[$servicefunction->servicename]->enabledfuncnb +1;
+ }
+
+ $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 = "<a href=\"$url&action=disable&webservice=$protocol\">";
+ $hideshow .= "<img src=\"" . $OUTPUT->old_icon_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" /></a>";
+ $displayname = "<span>$name</span>";
+ } else {
+ $hideshow = "<a href=\"$url&action=enable&webservice=$protocol\">";
+ $hideshow .= "<img src=\"" . $OUTPUT->old_icon_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
+ $displayname = "<span class=\"dimmed_text\">$name</span>";
+ }
- foreach($services as $service) {
- //$numberoffunc = $DB->count_records('external_services_functions',array('externalserviceid' => $service->id));
- $activated = ' <!--a href="' . $this->baseurl . '&deactivate=' . $service->id . '"-->'
- .'<img src="' . $OUTPUT->old_icon_url('i/' . ($service->enabled ? 'deactivate' : 'activate')) . '"'
- .' alt="' . ($service->enabled ? 'activated' : 'not activated') . '" '
- .' title="' . ($service->enabled ? 'activated' : 'not activated') . '" />'.'<!--/a-->' ;
- $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);
- }
+ // delete link
+ $uninstall = "<a href=\"$url&action=uninstall&webservice=$protocol\">$struninstall</a>";
- $output .= $OUTPUT->table($table);
+ // settings link
+ if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) {
+ $settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
+ } else {
+ $settings = '';
+ }
- $output .= '<br/>';
+ // add a row to the table
+ $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
+ }
+ $return .= $OUTPUT->table($table);
+ $return .= get_string('configwebserviceplugins', 'webservice').'<br />'.get_string('tablenosave', 'admin');
+ $return .= $OUTPUT->box_end();
- return highlight($query, $output);
+ return highlight($query, $return);
}
}
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);
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);
<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
- *
- * 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:
+ * Web services utility functions and classes
*
- * 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');
-
-/**
- * Returns detailed information about external function
- * @param string $functionname name of external function
- * @return aray
- */
-function ws_get_function_info($functionname) {
- global $CFG, $DB;
+require_once($CFG->libdir.'/externallib.php');
- $function = $DB->get_record('external_functions', array('name'=>$functionname), '*', MUST_EXIST);
+function webservice_protocol_is_enabled($protocol) {
+ global $CFG;
- $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(in_array($protocol, $active));
+}
- return $desc;
+/**
+ * Mandatory web service server interface
+ * @author Petr Skoda (skodak)
+ */
+interface webservice_server {
+ /**
+ * Process request from client.
+ * @param bool $simple use simple authentication
+ * @return void
+ */
+ public function run($simple);
}
/**
- * web service library
+ * Special abstraction of our srvices that allows
+ * interaction with stock Zend ws servers.
+ * @author skodak
*/
-final class webservice_lib {
+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.
+}
+
/**
- * Return list of all web service protocol into the webservice folder
- * @global <type> $CFG
- * @return <type>
+ * Web Service server base class, this class handles both
+ * simple and token authentication.
+ * @author Petr Skoda (skodak)
*/
- 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;
- }
+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;
/**
- * Temporary Authentication method to be modified/removed
- * @global <type> $DB
- * @param <type> $token
- * @return <type>
+ * Contructor
*/
- 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;
- }
+ public function __construct() {
}
/**
- * Retrieve all external.php from Moodle (except the one of the exception list)
- * @param <type> $
- * @param <type> $directorypath
- * @return boolean true if n
+ * 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
*/
- 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);
+ abstract protected function parse_request();
- }
- }
-
- }
+ /**
+ * Send the result of function call to the WS client.
+ * @return void
+ */
+ abstract protected function send_response();
/**
- * Check if the Moodle site has the web service protocol enable
- * @global object $CFG
- * @param string $protocol
+ * Send the error information to the WS client.
+ * @param exception $ex
+ * @return void
*/
- function display_webservices_availability($protocol) {
- global $CFG;
+ abstract protected function send_error($ex=null);
- $available = true;
- echo get_string('webservicesenable','webservice').": ";
- if (empty($CFG->enablewebservices)) {
- echo "<strong style=\"color:red\">".get_string('fail','webservice')."</strong>";
- $available = false;
- } else {
- echo "<strong style=\"color:green\">".get_string('ok','webservice')."</strong>";
- }
- echo "<br/>";
-
- 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 "<strong style=\"color:green\">".get_string('ok','webservice')."</strong>";
- } else {
- echo "<strong style=\"color:red\">".get_string('fail','webservice')."</strong>";
- $available = false;
- }
- echo "<br/>";
- continue;
- }
- }
+ /**
+ * Process request from client.
+ * @param bool $simple use simple authentication
+ * @return void
+ */
+ public function run($simple) {
+ $this->simple = $simple;
- //check debugging
- if ($CFG->debugdisplay) {
- echo "<strong style=\"color:red\">".get_string('debugdisplayon','webservice')."</strong>";
- $available = false;
- }
+ // we will probably need a lot of memory in some functions
+ @raise_memory_limit('128M');
- return $available;
- }
+ // 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'));
-/**
- * Web Service server base class
- */
-abstract class webservice_server {
+ // init all properties from the request data
+ $this->parse_request();
-/**
- * Web Service Protocol name (eg. SOAP, REST, XML-RPC,...)
- * @var String
- */
- private $protocolname;
+ // authenticate user, this has to be done after the request parsing
+ // this also sets up $USER and $SESSION
+ $this->authenticate_user();
- /**
- * Web Service Protocol id (eg. soap, rest, xmlrpc...)
- * @var String
- */
- private $protocolid;
+ // find all needed function info and make sure user may actually execute the function
+ $this->load_function_info();
- public function __construct() {
- }
+ // finally, execute the function - any errors are catched by the default exception handler
+ $this->execute();
- abstract public function run();
+ // send the results back in correct format
+ $this->send_response();
- public function get_protocolname() {
- return $this->protocolname;
- }
+ // session cleanup
+ $this->session_cleanup();
- public function get_protocolid() {
- return $this->protocolid;
+ die;
}
- public function set_protocolname($protocolname) {
- $this->protocolname = $protocolname;
- }
+ /**
+ * 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) {
+ }
+ }
- public function set_protocolid($protocolid) {
- $this->protocolid = $protocolid;
- }
+ // now let the plugin send the exception to client
+ $this->send_error($ex);
- public function get_enable() {
- return get_config($this->get_protocolid(), "enable");
- }
+ // some hacks might need a cleanup hook
+ $this->session_cleanup($ex);
- public function set_enable($enable) {
- set_config("enable", $enable, $this->get_protocolid());
+ // not much else we can do now, add some logging later
+ exit(1);
}
/**
- * Names of the server settings
- * @return array
+ * Future hook needed for emulated sessions.
+ * @param exception $exception null means normal termination, $exception received when WS call failed
+ * @return void
*/
- public static function get_setting_names() {
- return array();
+ 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
+ }
}
- public function settings_form(&$mform) {
- }
+ /**
+ * 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);
+
+ if (!has_capability("webservice/$this->wsname:use", get_context_instance(CONTEXT_SYSTEM))) {
+ throw new invalid_parameter_exception('Access to web service not allowed');
+ }
-/**
- * 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';
} else {
- throw new moodle_exception('wrongusernamepassword');
+ //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 user settings (administration)
- */
-final class wsuser_form extends moodleform {
- protected $username;
/**
- * 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;
- $this->username = $this->_customdata['username'];
- $mform =& $this->_form;
+ protected function load_function_info() {
+ global $DB, $USER, $CFG;
- $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 (empty($this->functionname)) {
+ throw new invalid_parameter_exception('Missing function name');
+ }
- $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));
+ // 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 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);
- $this->add_action_buttons(true, get_string('savechanges','admin'));
- }
-}
+ } else {
+ //TODO: implement token security checks
+ die('not implemented yet');
+ }
-/**
- * Form for web service server settings (administration)
- */
-final class wssettings_form extends moodleform {
- protected $settings;
+ // get the params and return descriptions of the function
+ unset($function->id); // we want to prevent any accidental db updates ;-)
- /**
- * Definition of the moodleform
- */
- public function definition() {
- global $DB,$CFG;
- $settings = $this->_customdata['settings'];
- $mform =& $this->_form;
-
- $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);
+ $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');
}
- $this->set_data($data);
+ require_once($function->classpath);
+ $function->parameters_method = $function->methodname.'_parameters';
+ $function->returns_method = $function->methodname.'_returns';
- $this->add_action_buttons(true, get_string('savechanges','admin'));
- }
-}
-
-/**
- * Form for web service server settings (administration)
- */
-final class wsservicesettings_form extends moodleform {
- protected $settings;
+ // 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');
+ }
- /**
- * Definition of the moodleform
- */
- public function definition() {
- global $DB,$CFG;
- $serviceid = $this->_customdata['serviceid'];
- $mform =& $this->_form;
-
- $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);
+ // 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');
}
- if (empty($serviceid)) {
- //display list of functions to select
+ // 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');
}
- //display list of functions associated to the service
-
-
+ // 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);
- $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));
}
}
-?>
--- /dev/null
+<?php
+
+$webservice_rest_capabilities = array(
+
+ 'webservice/rest:use' => 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(
+ ),
+ ),
+
+);
+++ /dev/null
-<?php
-/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
- *
- * 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
- */
-
-require_once($CFG->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);
- }
-
-}
-
-
-
-?>
<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
- *
- * 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
+ * REST web service implementation classes and methods.
*
- * @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
+class webservice_rest_server extends webservice_base_server {
+ /**
+ * Contructor
+ */
+ public function __construct() {
+ parent::__construct();
+ $this->wsname = 'rest';
}
- try {
- $res = call_user_func_array ( $classname.'::'.$functionname, array($params));
- } catch (moodle_exception $e) {
- return "<Result>".$e->getMessage()."</Result>";
- }
+ /**
+ * 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']);
- ///Transform result into xml in order to send the REST response
- $key = key($description[$functionname]['return']);
+ $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
+ unset($_REQUEST['wspassword']);
- if (strpos($key,":")!==false) {
- $key = substr($key, strpos($key,":")+1);
- } else {
- $key = 'return';
- }
- $return = mdl_conn_rest_object_to_xml ($res,$key);
+ $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
+ unset($_REQUEST['wsfunction']);
- return "<Result>$return</Result>";
-}
+ $this->parameters = $_REQUEST;
-/**
- * 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;
+ } else {
+ //TODO
+ die('not implemented yet');
}
-
- return $user;
- } else {
- return false;
}
-}
- /**
- * Convert into a Moodle type
- * @param integer $param
- * @return string
+ /**
+ * Send the result of function call to the WS client
+ * formatted as XML document.
+ * @return void
*/
-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;
+ protected function send_response() {
+ $this->send_headers();
+ $xml = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
+ $xml .= '<RESPONSE>'."\n";
+ $xml .= self::xmlize_result($this->returns, $this->function->returns_desc);
+ $xml .= '</RESPONSE>'."\n";
+ echo $xml;
}
-}
-/**
- *
- * @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;
- }
- }
- //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 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 = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
+ $xml .= '<EXCEPTION class="'.get_class($ex).'">'."\n";
+ $xml .= '<MESSAGE>'.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').'</MESSAGE>'."\n";
+ if (debugging() and isset($ex->debuginfo)) {
+ $xml .= '<DEBUGINFO>'.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').'</DEBUGINFO>'."\n";
}
+ $xml .= '</EXCEPTION>'."\n";
+ echo $xml;
}
- 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);
+ /**
+ * 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');
}
- //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);
+ /**
+ * 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 '<VALUE>'.htmlentities($returns, ENT_COMPAT, 'UTF-8').'</VALUE>'."\n";
+
+ } else if ($desc instanceof external_multiple_structure) {
+ $mult = '<MULTIPLE>'."\n";
+ foreach ($returns as $val) {
+ $mult .= self::xmlize_result($val, $desc->content);
+ }
+ $mult .= '</MULTIPLE>'."\n";
+ return $mult;
+
+ } else if ($desc instanceof external_single_structure) {
+ $single = '<SINGLE>'."\n";
+ foreach ($desc->keys as $key=>$subdesc) {
+ if (!array_key_exists($key, $returns)) {
+ if ($subdesc->rewquired) {
+ $single .= '<ERROR>Missing required key</ERROR>';
+ continue;
+ } else {
+ //optional field
+ continue;
+ }
+ }
+ $single .= '<KEY name="'.$key.'">'.self::xmlize_result($returns[$key], $subdesc).'</KEY>'."\n";
+ }
+ $single .= '</SINGLE>'."\n";
+ return $single;
}
- return $res;
}
- //any other type, just encapsule it
- $obj = htmlentities($obj);
- return "<$tag$tag_atts>$obj</$tag>\n";
-
}
-?>
\ No newline at end of file
<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- * http://moodle.com
- *
- * 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:
+ * REST web service entry point. The authentication is done via tokens.
*
- * 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
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * 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
- */
-
-
-/*
- * 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
+ * @package webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-
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
-
-
-
-//======== 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 = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
- $xml .= '<RESPONSE>'."\n";
- $xml .= self::xmlize_result($this->returns, $this->function->returns_desc);
- $xml .= '</RESPONSE>'."\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 = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
- $xml .= '<EXCEPTION class="'.get_class($ex).'">'."\n";
- $xml .= '<MESSAGE>'.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').'</MESSAGE>'."\n";
- if (debugging() and isset($ex->debuginfo)) {
- $xml .= '<DEBUGINFO>'.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').'</DEBUGINFO>'."\n";
- }
- $xml .= '</EXCEPTION>'."\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 '<VALUE>'.htmlentities($returns, ENT_COMPAT, 'UTF-8').'</VALUE>'."\n";
-
- } else if ($desc instanceof external_multiple_structure) {
- $mult = '<MULTIPLE>'."\n";
- foreach ($returns as $val) {
- $mult .= self::xmlize_result($val, $desc->content);
- }
- $mult .= '</MULTIPLE>'."\n";
- return $mult;
-
- } else if ($desc instanceof external_single_structure) {
- $single = '<SINGLE>'."\n";
- foreach ($desc->keys as $key=>$subdesc) {
- if (!array_key_exists($key, $returns)) {
- if ($subdesc->rewquired) {
- $single .= '<ERROR>Missing key</ERROR>';
- continue;
- } else {
- //optional field
- continue;
- }
- }
- $single .= '<KEY name="'.$key.'">'.self::xmlize_result($returns[$key], $subdesc).'</KEY>'."\n";
- }
- $single .= '</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 =============================
-
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
-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;
+++ /dev/null
-<?php
-/**
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid', 'userid');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Add group member to group");
-?>
-
-<form action="addgroupmember.php" method="post">
-<table border="0">
- <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
- <tr><td>User id: </td><td><input type="text" name="userid" value="<?php echo $userid; ?>"/></td></tr>
- <tr><td></td><td><input type="submit" value="Add member"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid && $userid) {
-
- var_dump($CFG->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 "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client configuration file
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- *
- */
-
-require_once("../../../config.php");
-require_once ('lib.php');
-
-if (empty($CFG->enablewebservices)) {
- die;
-}
-
-$CFG->serverurl = $CFG->wwwroot.'/webservice/rest/server.php';
-if (!function_exists('curl_init')) die ('CURL library was not found!');
-
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupname', 'courseid');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Create Group");
-?>
-
-<form action="creategroup.php" method="post">
-<table border="0">
- <tr><td>Group name: </td><td><input type="text" name="groupname" value="<?php echo $groupname; ?>"/></td></tr>
- <tr><td>Course id: </td><td><input type="text" name="courseid" value="<?php echo $groupid; ?>"/></td></tr>
- <tr><td></td><td><input type="submit" value="Create Group"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupname && $courseid) {
-
- var_dump($CFG->serverurl.'/group/create_group');
-
-
- //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['groupname'] = $groupname;
- $data['courseid'] = $courseid;
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/create_group');
- 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->groupid);
-
- show_xml ($out);
-} else {
- echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-start_interface("Create A User");
-
-$ch = curl_init();
-
-$data['username'] = "mockuser5";
-$data['firstname'] = "mockuser5";
-$data['lastname'] = "mockuser5";
-$data['email'] = "mockuser5@lastname.com";
-
-var_dump($data);
-
-//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;
-
-curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/create_user');
-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->userid);
-
-show_xml ($out);
-
-end_interface();
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Delete group");
-?>
-
-<form action="deletegroup.php" method="post">
-<table border="0">
- <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
- <tr><td></td><td><input type="submit" value="Delete Group"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid) {
-
- //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;
-
- $ch = curl_init();
-
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/delete_group');
- 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);
-
- show_xml ($out);
-} else {
- echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
+++ /dev/null
-<?php
-/**
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid', 'userid');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Delete group member from a group");
-?>
-
-<form action="deletegroupmember.php" method="post">
-<table border="0">
- <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
- <tr><td>User id: </td><td><input type="text" name="userid" value="<?php echo $userid; ?>"/></td></tr>
- <tr><td></td><td><input type="submit" value="Delete"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid && $userid) {
-
- var_dump($CFG->serverurl.'/group/delete_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/delete_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 "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-
-$params = array('username','mnethostid');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Delete a user");
-?>
-
-<form action="deleteuser.php" method="post">
-<table border="0">
- <tr><td>Search: </td><td><input type="text" name="username" value="<?php echo $username; ?>"/></td></tr>
- <tr><td></td><td><input type="hidden" name="mnethostid" value="1"><input type="submit" value="Find Users"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($username) {
-
- //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['username'] = $username;
- $data['mnethostid'] = $mnethostid;
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/delete_user');
- 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->user,2,'auth');
- var_dump($res);
- show_xml ($out);
-} else {
- echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Get Group");
-?>
-
-<form action="getgroup.php" method="post">
-<table border="0">
- <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
- <tr><td></td><td><input type="submit" value="Find Group"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid) {
-
- //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;
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/get_group');
- 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->return);
-
- show_xml ($out);
-} else {
- echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-
-$params = array('search');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("List of Users");
-?>
-
-<form action="getusers.php" method="post">
- <table border="0">
- <tr><td>Search: </td><td><input type="text" name="search" value="<?php echo $search; ?>"/></td></tr>
- <tr><td></td><td><input type="submit" value="Find Users"></td></tr>
- </table>
-</form>
-
-<?php
-
-if ($search) {
- $data['search'] = $search;
-
- //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;
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_users');
- 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->user,2,'auth');
-
- show_xml ($out);
-} else {
- echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
/**
- * Created on 10/17/2008
+ * REST web service test client.
*
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- * @author Jordi Piguillem
+ * @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_rest.php');
-
-start_interface (false);
-
-$links = array( array('USERS'),
- array('getusers.php','get_users()'),
- array('createuser.php','create_user()'),
- array('deleteuser.php','delete_user()'),
- array('updateuser.php','update_user()'),
- array('GROUPS'),
- array('creategroup.php','create_group()'),
- array('addgroupmember.php', 'add_groupmember()'),
- array('getgroup.php', 'get_group()'));
-
-echo '<ul>';
-foreach ($links as $link) {
- if (sizeof($link)==2){
- echo '<li><a href="'.$link[0].'">'.$link[1].'</a></li>';
- } else {
- echo '</ul><h2>'.$link[0].'</h2><ul>';
- }
+require('../../../config.php');
+require_once("$CFG->dirroot/webservice/webservice_test_client_form.php");
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
+
+$function = optional_param('function', '', PARAM_SAFEDIR);
+
+$PAGE->set_url('webservice/rest/testclient/index.php');
+
+require_login();
+require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); // TODO: do we need some new capability?
+
+$functions = array('moodle_group_get_groups');
+$functions = array_combine($functions, $functions);
+
+if (!isset($functions[$function])) {
+ $function = '';
}
-echo '</ul>';
-end_interface(false);
-?>
\ No newline at end of file
+if (!$function) {
+ $mform = new webservice_test_client_form(null, $functions);
+ echo $OUTPUT->header();
+ echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest'));
+ $mform->display();
+ echo $OUTPUT->footer();
+ die;
+}
+
+$class = $function.'_form';
+require_once("$CFG->dirroot/webservice/rest/testclient/$class.php");
+
+$mform = new $class();
+
+if ($mform->is_cancelled()) {
+ redirect('index.php');
+
+} else if ($data = $mform->get_data()) {
+ $serverurl = "$CFG->wwwroot/webservice/rest/simpleserver.php";
+ $serverurl .= '?wsusername='.urlencode($data->wsusername);
+ $serverurl .= '&wspassword='.urlencode($data->wspassword);
+ $serverurl .= '&wsfunction='.urlencode($data->function);
+ for ($i=0; $i<10; $i++) {
+ if (empty($data->groupids[$i])) {
+ continue;
+ }
+ $serverurl .= "&groupids[$i]=".urlencode($data->groupids[$i]);
+ }
+
+ echo $OUTPUT->header();
+ echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest').': '.$function);
+
+ echo 'URL: '.s($serverurl);
+ echo $OUTPUT->box_start();
+ echo '<code>';
+ $response = download_file_content($serverurl);
+ echo str_replace("\n", '<br />', s($response));
+ echo '</code>';
+ echo $OUTPUT->box_end();
+ $mform->display();
+ echo $OUTPUT->footer();
+ die;
+
+} else {
+ echo $OUTPUT->header();
+ echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest').': '.$function);
+ $mform->display();
+ echo $OUTPUT->footer();
+ die;
+}
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client Suport Library
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- */
-
-//--- interface helpers ---
-
-/**
- * starts the interface
- */
-function start_interface ($title=" ") {
- $title2 = ($title)?$title:" ";
- echo '<html><head>';
- echo "<title>Moodle Webservice Rest Test Client</title>";
- echo '<link rel="stylesheet" href="style.css" type="text/css">';
- echo '</head><body>';
- echo '<div class="head"><h1>Moodle Webservice Rest Test Client</h1>';
- echo "<h3>$title2</h3>";
- echo '</div>';
- echo '<div class="content">';
- if ($title) echo '<p class="return"><a href="index.php"><img src="return.gif" border="0"/></a></p>';
-}
-
-/**
- * end interface
- *
- * @param bool $ret=true: show return button
- */
-function end_interface ($ret = true) {
- if ($ret) echo '<p class="return"><a href="index.php"><img src="return.gif" border="0"/></a></p>';
- echo '</div>';
- echo '<div class="footer">Created by David Castro i Ferran Recio for Moodle Webservices</div>';
- echo '</body></html>';
-}
-
-/**
- * print XML div area
- *
- * @param string $xml
- *
- */
-function show_xml ($xml) {
- echo '<div class="xmlshow">';
- echo '<a onClick="document.getElementById(\'toggleme\').style.display = ' .
- '(document.getElementById(\'toggleme\').style.display!=\'none\')?\'none\':\'\';">Hide/Show XML</a>';
- echo "<div style=\"display:none;\" id=\"toggleme\">";
- echo '<pre>';echo htmlentities($xml);echo '</pre>';
- echo "</div>";
- echo "</div>";
-}
-
-/**
- * format post data
- */
-function format_postdata ($data) {
- $o="";
- foreach ($data as $k=>$v) {
- $o.= "$k=".rawurlencode($v)."&";
- }
- $post_data=substr($o,0,-1);
- return $post_data;
-}
-
-/**
- * shows an object in list format
- *
- * @param mixed $obj
- * @param integer $cols: number of colums
- * @ string string $check=false: if this attribute is not present, the $obj is ans error
- *
- */
-function show_object ($obj,$cols=1,$check=false) {
- if (!is_array($obj)) $obj = array($obj);
- echo '<ul class="results">';
- foreach ($obj as $r) {
-
- if ($check && (!isset($r->$check) || $r->$check==-1)) {
- echo '<li class="error">';
- echo "EMPTY ROW!";
- } else {
- if (is_object($r)) {
- echo '<li class="element">';
- $text = array();
- $parts = get_object_vars($r);
- $num = 1;
- $currline = '';
- foreach ($parts as $key => $val) {
- $currline.= "<span class=\"resultval\"><b>$key:</b> <i>$val</i></span>, ";
- if ($num >= $cols) {
- $currline=substr($currline,0,-2);
- $text[] = $currline;
- $currline = '';
- $num = 0;
- }
- $num++;
- }
- echo implode('<br/>',$text);
- } else {
- if ($r==-1 || !$r) {
- echo '<li class="error">';
- echo "EMPTY ROW!";
- } else {
- echo '<li class="element">';
- echo "<span class=\"resultval\"><b>Returned Value:</b> <i>$r</i></span>";
- }
- }
- }
- echo '</li>';
- }
- echo '</ul>';
-}
-
-
-//---- XML simple parser ----
-//this code was donated by Ferran Recio
-
-/**
- * convert a simple xml into php object
- *
- * @author ferran recio
- *
- * @param String $xml
- *
- * @return mixed
- */
-function basicxml_xml_to_object ($xml) {
- $xml=utf8_encode($xml);
-
- //create the parser
- $parser = xml_parser_create ();
- xml_set_default_handler ($parser,'basicxml_xml_to_object_aux');
-
- $values = array();
- $index = array();
- xml_parse_into_struct($parser,$xml,$values,$index);
-
- //print_object($values);
- //print_object($index);
-
- //just simplexml tag (disabled)
- //if (strtolower($values[0]['tag']) != 'basicxml') return false;
- //if (strtolower($values[count($values)-1]['tag']) != 'basicxml') return false;
-
- $res = basicxml_xml_to_object_aux ($values);
- //omit the first tag
- $parts = array_keys(get_object_vars($res));
- $key = $parts[0];
- return $res->$key;
-}
-
-/**
- * auxiliar function to basicxml_xml_to_object
- *
- * @author ferran recio
- *
- * @param mixed $values
- *
- * @return mixed
- */
-function basicxml_xml_to_object_aux ($values) {
-
- if (!is_array($values)) return false;
- //print_object ($values);
- $currset = array();
- $search = false;
-
- foreach ($values as $value) {
- $tag = strtolower($value['tag']);
- //if we are acomulating, just acomulate it
- if ($search) {
- //if it closes a tag, we just stop searching
- if ($tag == $search && $value['type']=='close') {
- //recursivity
- $obj2 = basicxml_xml_to_object_aux ($currset);
- //search cleaning
- $search = false;
- //add to result
- if (isset($res->{$tag})){
- if (is_array($res->{$tag})){
- $res->{$tag}[] = $obj2;
- } else {
- $res->{$tag} = array($res->{$tag},$obj2);
- }
- } else {
- $res->{$tag} = $obj2;
- }
- } else {
- //we are searching. If it's cdada, pass it throw
- if ($value['type']=='cdata') continue;
- //if isn't cdata, put it in the set and continue searching
- //(because isn't the close we're searching)
- $currset[] = $value;
- }
- } else {
- //walking the xml
- if ($value['type']=='open'){
- //on open, let's search on it
- $currset = array();
- $search = $tag;
- } else {
- //if it's complete just save it
- if ($value['type']=='complete') {
- if (!empty($value['value'] )) {
- $val = html_entity_decode($value['value']);
- if (isset($res->{$tag})){
- if (is_array($res->{$tag})){
- $res->{$tag}[] = $val;
- } else {
- $res->{$tag} = array($res->{$tag},$val);
- }
- } else {
- $res->{$tag} = $val;
- }
- }
- }
- }
- }
- }
- return $res;
-}
-?>
--- /dev/null
+<?php
+
+require_once($CFG->dirroot.'/lib/formslib.php');
+
+
+class moodle_group_get_groups_form extends moodleform {
+ public function definition() {
+ global $CFG;
+
+ $mform = $this->_form;
+
+ $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
+
+ //note: these values are intentionally PARAM_RAW - we want users to test any rubbish as parameters
+ $mform->addElement('text', 'wsusername', 'wsusername');
+ $mform->addElement('text', 'wspassword', 'wspassword');
+ $mform->addElement('text', 'groupids[0]', 'groupids[0]');
+ $mform->addElement('text', 'groupids[1]', 'groupids[1]');
+ $mform->addElement('text', 'groupids[2]', 'groupids[2]');
+ $mform->addElement('text', 'groupids[3]', 'groupids[3]');
+
+ $mform->addElement('hidden', 'function');
+ $mform->setType('function', PARAM_SAFEDIR);
+ $mform->setDefault('function', 'moodle_group_get_groups');
+
+ $this->add_action_buttons(true, get_string('test', 'webservice'));
+ }
+}
\ No newline at end of file
+++ /dev/null
-body {
- background-color: #FAFFFF;;
-}
-
-.xmlshow {
- background-color: #DDDDFF;
- padding:20px;
-}
-
-.xmlshow div {
- height: 200px;
- overflow: auto;
- padding: 20px;
- background-color: #EEEEFF;
-}
-
-.head, .footer {
- background-color: #AAAAFF;
- text-align: center;
-}
-
-.footer {
- font-size: small;
- padding: 10px;
-}
-
-.content {
- padding-left: 20px;
- padding-right: 20px;
-}
-
-.results li{
- margin-bottom:20px;
- padding: 10px;
- list-style-type: square;
-}
-
-.element {
- background-color: #CCCCFF;
-}
-
-.element span:hover{
- background-color:#DDDDFF;
-}
-
-.error {
- background-color: #FFCCCC;
-}
-
-.return a, .return a:hover, .return a:visited{
- color:#0000DD;
-}
-
-h1, h2 {
- margin:0px;
- padding:5px;
-}
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-
-$params = array('username','mnethostid','newusername','firstname');
-
-foreach ($params as $param) {
- $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Update a user");
-?>
-
-<form action="updateuser.php" method="post">
-<table border="0">
- <tr><td>Old username: </td><td><input type="text" name="username" value="<?php echo $username; ?>"/></td></tr>
- <tr><td>New username: </td><td><input type="text" name="newusername" value="<?php echo $newusername; ?>"/></td></tr>
- <tr><td>New firstname: </td><td><input type="text" name="firstname" value="<?php echo $firstname; ?>"/></td></tr>
- <tr><td></td><td><input type="hidden" name="mnethostid" value="1"><input type="submit" value="Find Users"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($username) {
-
- //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['username'] = $username;
- $data['mnethostid'] = $mnethostid;
- $data['newusername'] = $newusername;
- $data['firstname'] = $firstname;
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/update_user');
- 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->user,2,'auth');
- var_dump($res);
- show_xml ($out);
-} else {
- echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
--- /dev/null
+<?php
+
+$plugin->version = 2009100800;
--- /dev/null
+<?php
+
+require_once($CFG->dirroot.'/lib/formslib.php');
+
+
+class webservice_test_client_form extends moodleform {
+ public function definition() {
+ global $CFG;
+
+ $mform = $this->_form;
+ $functions = $this->_customdata;
+
+ $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
+
+ $mform->addElement('select', 'function', get_string('function', 'webservice'), $functions);
+
+ $this->add_action_buttons(false, get_string('select'));
+ }
+}
\ No newline at end of file
// //
///////////////////////////////////////////////////////////////////////////
+// TODO: this needs to be rewritten to use the new description format
+// the problem here is that the list of functions is different for each use or even token
+// I guess this should ne moved to server itself and it should require user auth
+die('TODO');
+
/**
* This file generate a web service documentation in HTML
* This documentation describe how to call a Moodle Web Service