MDL-12886 minor web service code refactoring which includes new base server class, slightly changed admin UI, sample REST test client, cleaned up lang packs; more changes ahead and lots of TODOs to elliminate; expect more commints in the next few days

This commit is contained in:
skodak
2009-10-12 21:46:16 +00:00
parent 3e322a88fc
commit cc93c7da15
42 changed files with 1426 additions and 2624 deletions
+89
View File
@@ -0,0 +1,89 @@
<?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);
}
}
+84
View File
@@ -0,0 +1,84 @@
<?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();
+142
View File
@@ -0,0 +1,142 @@
<?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&amp;action=delete&amp;fid=$function->id&amp;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();
+38
View File
@@ -0,0 +1,38 @@
<?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();
+27
View File
@@ -237,6 +237,33 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
}
}
// Web services
$ADMIN->add('modules', new admin_category('webservicesettings', get_string('webservices', 'webservice')));
$temp = new admin_settingpage('externalservices', get_string('externalservices', 'webservice'));
$temp->add(new admin_setting_manageexternalservices());
$ADMIN->add('webservicesettings', $temp);
$ADMIN->add('webservicesettings', new admin_externalpage('externalservice', get_string('externalservice', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service.php"), 'moodle/site:config', true);
$ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions', get_string('externalservicefunctions', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_functions.php"), 'moodle/site:config', true);
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers', get_string('externalserviceusers', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_users.php"), 'moodle/site:config', true);
$temp = new admin_settingpage('webserviceprotocols', get_string('manageprotocols', 'webservice'));
$temp->add(new admin_setting_managewebserviceprotokols());
if (empty($CFG->enablewebservices)) {
$temp->add(new admin_setting_heading('webservicesaredisabled', '', get_string('disabledwarning', 'webservice')));
}
$ADMIN->add('webservicesettings', $temp);
$webservices_available = get_plugin_list('webservice');
$active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
foreach ($webservices_available as $webservice => $location) {
if (file_exists("$location/settings.php")) {
$name = get_string('pluginname', 'webservice_'.$webservice);
$settings = new admin_settingpage('webservicesetting'.$webservice, $name, 'moodle/site:config', !in_array($webservice, $active_webservices) or empty($CFG->enablewebservices));
if ($ADMIN->fulltree) {
include("$location/settings.php");
}
$ADMIN->add('webservicesettings', $settings);
}
}
// Question type settings.
$ADMIN->add('modules', new admin_category('qtypesettings', get_string('questiontypes', 'admin')));
$ADMIN->add('qtypesettings', new admin_page_manageqtypes());
+1 -21
View File
@@ -11,26 +11,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
'', ''));
$ADMIN->add('security', $temp);
// "web service" settingpage
$temp = new admin_settingpage('webservices', get_string('webservices', 'admin'));
$temp->add(new admin_setting_heading('webserviceprotocols', get_string('protocols', 'webservice'), ''));
$temp->add(new admin_setting_managewsprotocols());
$url = $CFG->wwwroot.'/'.$CFG->admin.'/wsprotocols.php';
$ADMIN->add('security', new admin_externalpage('managews',
get_string('managews', 'admin'), $url, 'moodle/site:config', true),
'', $url);
$temp->add(new admin_setting_heading('webservicesystemsettings', get_string('systemsettings', 'webservice'), ''));
$temp->add(new admin_setting_configiplist('ipwhitelist', get_string('ipwhitelist', 'admin'),'', ''));
$temp->add(new admin_setting_heading('webserviceusersettings', get_string('usersettings', 'webservice'), ''));
$temp->add(new admin_setting_managewsusersettings());
$temp->add(new admin_setting_heading('webserviceservicelist', get_string('servicelist', 'webservice'), ''));
$temp->add(new admin_setting_managewsservicelist());
$url = $CFG->wwwroot.'/'.$CFG->admin.'/webservices.php';
$ADMIN->add('security', new admin_externalpage('webservicessettings',
get_string('webservicessettings', 'admin'), $url, 'moodle/site:config', true),
'', $url);
$ADMIN->add('security', $temp);
// "sitepolicies" settingpage
$temp = new admin_settingpage('sitepolicies', get_string('sitepolicies', 'admin'));
$temp->add(new admin_setting_configcheckbox('protectusernames', get_string('protectusernames', 'admin'), get_string('configprotectusernames', 'admin'), 1));
@@ -137,4 +117,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
} // end of speedup
?>
+87
View File
@@ -0,0 +1,87 @@
<?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);
-117
View File
@@ -1,117 +0,0 @@
<?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()."&amp;serviceid=".$serviceid."&amp;remove=1&amp;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();
}
?>
-88
View File
@@ -1,88 +0,0 @@
<?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();
+4 -4
View File
@@ -527,8 +527,6 @@ It is recommended to install local copy of free GeoLite City database from MaxMi
IP address location is displayed on simple map or using Google Maps. Please note that you need to have a Google account and apply for free Google Maps API key to enable interactive maps.';
$string['iplookupmaxmindnote'] = 'This product includes GeoLite data created by MaxMind, available from <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';
@@ -571,7 +569,6 @@ $string['maintfileopenerror'] = 'Error opening maintenance files!';
$string['maintinprogress'] = 'Maintenance is in progress...';
$string['managelang'] = 'Manage';
$string['manageqtypes'] = 'Manage question types';
$string['managews'] = 'Manage web services';
$string['maintenancemode'] = 'In Maintenance Mode';
$string['maxbytes'] = 'Maximum uploaded file size';
$string['maxeditingtime'] = 'Maximum time to edit posts';
@@ -670,6 +667,7 @@ $string['php50restricted'] = 'PHP 5.0.x has a number of known problems, please u
$string['phpfloatproblem'] = 'Detected unexpected problem in handling of PHP float numbers - $a';
$string['pleaseregister'] = 'Please register your site to remove this button';
$string['pleaserefreshregistration'] = 'Your site has been registered with moodle.org, please consider updating the registration if significant changes happened since your last update, on $a';
$string['plugin'] = 'Plugin';
$string['plugins'] = 'Plugins';
$string['profilecategory'] = 'Category';
$string['profilecategoryname'] = 'Category name (must be unique)';
@@ -832,6 +830,8 @@ $string['supportname'] = 'Support name';
$string['supportpage'] = 'Support page';
$string['switchlang'] = 'Switch lang directory';
$string['systempaths'] = 'System Paths';
$string['tablenosave'] = 'Changes in table above are saved automatically.';
$string['tablesnosave'] = 'Changes in tables above are saved automatically.';
$string['tabselectedtofront'] = 'On tables with tabs, should the row with the currently selected tab be placed at the front';
$string['tabselectedtofronttext'] = 'Bring selected tab row to front';
$string['themelist'] = 'Theme list';
@@ -849,6 +849,7 @@ $string['unicodeupgradenotice'] = 'In Moodle 1.6 we have migrated all languages
$string['unicoderecommended'] = 'Storing all your data in Unicode (UTF-8) is recommended. New installations should be performed into databases that have their default character set as Unicode. If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
$string['unicoderequired'] = 'It is required that you store all your data in Unicode format (UTF-8). New installations must be performed into databases that have their default character set as Unicode. If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
$string['uninstall'] = 'Uninstall selected language pack';
$string['uninstallplugin'] = 'Uninstall';
$string['uninstallconfirm'] = 'You are about to completely uninstall language pack $a, are you sure?';
$string['uninstallqtype'] = 'Uninstall this question type.';
$string['unsupported'] = 'Unsupported';
@@ -931,7 +932,6 @@ $string['verifychangedemail'] = 'Restrict domains when changing email';
$string['warningcurrentsetting'] = 'Invalid current value: $a';
$string['webproxy'] = 'Web proxy';
$string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.<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';
+24 -60
View File
@@ -1,61 +1,25 @@
<?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.';
<?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['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";
$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';
+4
View File
@@ -0,0 +1,4 @@
<?php
$string['amfdebug'] = 'AMF server debug mode';
$string['pluginname'] = 'AMF protocok';
+3
View File
@@ -0,0 +1,3 @@
<?php
$string['pluginname'] = 'REST protocol';
+3
View File
@@ -0,0 +1,3 @@
<?php
$string['pluginname'] = 'SOAP protocol';
+3
View File
@@ -0,0 +1,3 @@
<?php
$string['pluginname'] = 'XMLRPC protocol';
+273 -205
View File
@@ -4964,7 +4964,7 @@ class admin_setting_manageeditors extends admin_setting {
$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);
}
@@ -6077,26 +6077,23 @@ class admin_setting_managerepository extends admin_setting {
}
}
/**
*
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_managewsprotocols extends admin_setting {
/** @var string */
private $baseurl;
/**
* Special class for management of external services
*
* @author Petr Skoda (skodak)
*/
class admin_setting_manageexternalservices extends admin_setting {
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
global $CFG;
parent::__construct('managewsprotocols', get_string('managewsprotocols', 'admin'), '', '');
$this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey();
parent::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_setting() {
@@ -6104,233 +6101,304 @@ class admin_setting_managewsprotocols extends admin_setting {
}
/**
* Doesnt nothing, always returns ''
* Always returns true, does nothing
*
* @return true
*/
public function get_defaultsetting() {
return true;
}
/**
* Always returns '', does not write anything
*
* @return string Always returns ''
*/
public function write_setting($data) {
$url = $this->baseurl . '&amp;new=' . $data;
// do not write any setting
return '';
}
/**
* Builds XHTML to display the control
* Checks if $query is one of the available external services
*
* @param string $data
* @param string $query
* @return string XHTML
* @param string $query The string to search for
* @return bool Returns true if found, false if not
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT;
public function is_related($query) {
global $DB;
$namestr = get_string('name');
$settingsstr = get_string('settings');
$hiddenstr = get_string('activated', 'webservice');
require_once("../webservice/lib.php");
$protocols = webservice_lib::get_list_protocols();
$table = new html_table();
$table->head = array($namestr, $hiddenstr, $settingsstr);
$table->align = array('left', 'center', 'center');
$table->data = array();
$table->tablealign = 'center';
if (parent::is_related($query)) {
return true;
}
foreach ($protocols as $i) {
$hidetitle = $i->get_protocolid() ? get_string('clicktodeactivate', 'webservice') : get_string('clicktoactivate', 'webservice');
$hiddenshow = ' <a href="' . $this->baseurl . '&amp;hide=' . $i->get_protocolid() . '">'
.'<img src="' . $OUTPUT->old_icon_url('i/' . ($i->get_enable() ? 'hide' : 'show')) . '"'
.' alt="' . $hidetitle . '" '
.' title="' . $hidetitle . '" />'
.'</a>' . "\n";
$settingnames = $i->get_setting_names();
if (!empty($settingnames)) {
$settingsshow = ' <a href="' . $this->baseurl . '&amp;settings=' . $i->get_protocolid() . '">'
.$settingsstr
.'</a>' . "\n";
} else {
$settingsshow = "";
}
$table->data[] = array($i->get_protocolname(), $hiddenshow, $settingsshow);
//display a grey row if the type is defined as not visible
if (!$i->get_enable()) {
$table->rowclasses[] = 'dimmed_text';
} else {
$table->rowclasses[] = '';
$textlib = textlib_get_instance();
$services = $DB->get_records('external_services', array(), 'id, name');
foreach ($services as $service) {
if (strpos($textlib->strtolower($service->name), $query) !== false) {
return true;
}
}
$output = $OUTPUT->table($table);
$output .= "<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;
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
global $CFG;
parent::__construct('managewsusersettings', get_string('managewsusersettings', 'admin'), '', '');
$this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey();
return false;
}
/**
* Always returns true does nothing
*
* @return true
*/
public function get_setting() {
return true;
}
/**
* Does nothing always returns ''
*
* @return string Always returns ''
*/
public function write_setting($data) {
$url = $this->baseurl . '&amp;new=' . $data;
return '';
}
/**
* Build XHTML to display the control
* Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string XHTML
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT;
$output = "";
//search all web service users
$users = get_users(true, '', false, null, 'firstname ASC','', '', '', 1000);
$table = new html_table();
$table->head = array('username', 'whitelist');
$table->align = array('left', 'center');
$table->data = array();
$table->tablealign = 'center';
foreach ($users as $user) {
if (has_capability("moodle/site:usewebservices",get_system_context(), $user->id)) { //test if the users has has_capability('use_webservice')
$wsusersetting = ' <a href="' . $this->baseurl . '&amp;username=' . $user->username . '">'
. get_string("settings")
.'</a>' . "\n";
$table->data[] = array($user->username, $wsusersetting);
}
}
$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_managewsservicelist extends admin_setting {
/** @var string */
private $baseurl;
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
global $CFG;
parent::__construct('managewsservicelist', get_string('managewsservicelist', 'admin'), '', '');
$this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/webservices.php?sesskey=' . sesskey();
}
/**
* Always returns true does nothing
*
* @return true
*/
public function get_setting() {
return true;
}
/**
* Does nothing always returns ''
*
* @return string Always returns ''
*/
public function write_setting($data) {
$url = $this->baseurl . '&amp;new=' . $data;
return '';
}
/**
* Build XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string XHTML
* @return string
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT, $DB;
$output = "<div style=\"text-align:center;\">";
$output .= $OUTPUT->link('/admin/webservices.php?sesskey='.sesskey().'&create=true',get_string('createservicelabel', 'webservice'));
$output .= "</div>";
// display strings
$stradministration = get_string('administration');
$stredit = get_string('edit');
$strservice = get_string('externalservice', 'webservice');
$strdelete = get_string('delete');
$strplugin = get_string('plugin', 'admin');
$stradd = get_string('add');
$strfunctions = get_string('functions', 'webservice');
$strusers = get_string('restrictedusers', 'webservice');
$esurl = "$CFG->wwwroot/$CFG->admin/external_service.php";
$efurl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php";
$euurl = "$CFG->wwwroot/$CFG->admin/external_service_users.php";
// built in services
$return = $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main', true);
$services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
$table = new html_table();
$table->head = array(get_string('servicename','webservice'), get_string('custom','webservice'), get_string('activated','webservice'),get_string('activatedfunctions','webservice'),get_string('settings'));
$table->align = array('left', 'center', 'center','center','center');
$table->data = array();
$table->tablealign = 'center';
$table->head = array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
$table->align = array('left', 'left', 'center', 'center', 'center');
$table->size = array('30%', '20%', '20%', '20%', '10%');
$table->width = '100%';
$table->data = array();
//retrieve all services
// $services = $DB->get_records('external_services',null,'custom DESC');
$servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, s.id as serviceid, s.component as component, s.name as servicename, s.enabled as serviceenabled, f.name as functionname
FROM {external_services} s, {external_functions} f, {external_services_functions} fs
WHERE fs.externalserviceid = s.id AND fs.functionname = f.name ORDER BY s.name ASC");
// iterate through auth plugins and add to the display table
foreach ($services as $service) {
$name = $service->name;
//create a services array
$services = array();
foreach($servicesfunctions as $servicefunction) {
if (!array_key_exists($servicefunction->servicename, $services)) {
$services[$servicefunction->servicename] = new object();
$services[$servicefunction->servicename]->name = $servicefunction->servicename;
$services[$servicefunction->servicename]->id = $servicefunction->serviceid;
$services[$servicefunction->servicename]->enabled = $servicefunction->serviceenabled;
$services[$servicefunction->servicename]->custom = $servicefunction->custom;
$services[$servicefunction->servicename]->funcnb = 0;
$services[$servicefunction->servicename]->enabledfuncnb = 0;
}
$services[$servicefunction->servicename]->funcnb = $services[$servicefunction->servicename]->funcnb +1;
if ($servicefunction->functionenabled) {
$services[$servicefunction->servicename]->enabledfuncnb = $services[$servicefunction->servicename]->enabledfuncnb +1;
// hide/show link
if ($service->enabled) {
$displayname = "<span>$name</span>";
} else {
$displayname = "<span class=\"dimmed_text\">$name</span>";
}
$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 {
$users = '-';
}
$edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
// add a row to the table
$table->data[] = array($displayname, $plugin, $functions, $users, $edit);
}
$return .= $OUTPUT->table($table);
foreach($services as $service) {
//$numberoffunc = $DB->count_records('external_services_functions',array('externalserviceid' => $service->id));
$activated = ' <!--a href="' . $this->baseurl . '&amp;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);
// Custom services
$return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main', true);
$services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
$table = new html_table();
$table->head = array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
$table->align = array('left', 'center', 'center', 'center', 'center');
$table->size = array('30%', '20%', '20%', '20%', '10%');
$table->width = '100%';
$table->data = array();
// iterate through auth plugins and add to the display table
foreach ($services as $service) {
$name = $service->name;
// hide/show link
if ($service->enabled) {
$displayname = "<span>$name</span>";
} else {
$displayname = "<span class=\"dimmed_text\">$name</span>";
}
// delete link
$delete = "<a href=\"$esurl?action=delete&amp;sesskey=".sesskey()."&amp;id=$service->id\">$strdelete</a>";
$functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
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);
$return .= '<br />'.get_string('tablesnosave', 'admin');
$output .= '<br/>';
return highlight($query, $return);
}
}
return highlight($query, $output);
/**
* Special class for web service protocol administration.
*
* @author Petr Skoda (skodak)
*/
class admin_setting_managewebserviceprotokols extends admin_setting {
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_setting() {
return true;
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_defaultsetting() {
return true;
}
/**
* Always returns '', does not write anything
*
* @return string Always returns ''
*/
public function write_setting($data) {
// do not write any setting
return '';
}
/**
* Checks if $query is one of the available webservices
*
* @param string $query The string to search for
* @return bool Returns true if found, false if not
*/
public function is_related($query) {
if (parent::is_related($query)) {
return true;
}
$textlib = textlib_get_instance();
$protocols = get_plugin_list('webservice');
foreach ($protocols as $protocol=>$location) {
if (strpos($protocol, $query) !== false) {
return true;
}
$protocolstr = get_string('pluginname', 'webservice_'.$protocol);
if (strpos($textlib->strtolower($protocolstr), $query) !== false) {
return true;
}
}
return false;
}
/**
* Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT;
// display strings
$stradministration = get_string('administration');
$strsettings = get_string('settings');
$stredit = get_string('edit');
$strprotocol = get_string('protocol', 'webservice');
$strenable = get_string('enable');
$strdisable = get_string('disable');
$strversion = get_string('version');
$struninstall = get_string('uninstallplugin', 'admin');
$protocols_available = get_plugin_list('webservice');
$active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
ksort($protocols_available);
foreach ($active_protocols as $key=>$protocol) {
if (empty($protocols_available[$protocol])) {
unset($active_protocols[$key]);
}
}
$return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main', true);
$return .= $OUTPUT->box_start('generalbox webservicesui');
$table = new html_table();
$table->head = array($strprotocol, $strversion, $strenable, $struninstall, $strsettings);
$table->align = array('left', 'center', 'center', 'center', 'center');
$table->width = '100%';
$table->data = array();
// iterate through auth plugins and add to the display table
$url = "$CFG->wwwroot/$CFG->admin/webservice_protocols.php?sesskey=" . sesskey();
foreach ($protocols_available as $protocol => $location) {
$name = get_string('pluginname', 'webservice_'.$protocol);
$plugin = new object();
if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/version.php')) {
include($CFG->dirroot.'/webservice/'.$protocol.'/version.php');
}
$version = isset($plugin->version) ? $plugin->version : '';
// hide/show link
if (in_array($protocol, $active_protocols)) {
$hideshow = "<a href=\"$url&amp;action=disable&amp;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&amp;action=enable&amp;webservice=$protocol\">";
$hideshow .= "<img src=\"" . $OUTPUT->old_icon_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
$displayname = "<span class=\"dimmed_text\">$name</span>";
}
// delete link
$uninstall = "<a href=\"$url&amp;action=uninstall&amp;webservice=$protocol\">$struninstall</a>";
// settings link
if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) {
$settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
} else {
$settings = '';
}
// add a row to the table
$table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
}
$return .= $OUTPUT->table($table);
$return .= get_string('configwebserviceplugins', 'webservice').'<br />'.get_string('tablenosave', 'admin');
$return .= $OUTPUT->box_end();
return highlight($query, $return);
}
}
@@ -941,14 +941,6 @@ get_string('allowbeforeblock', 'admin', NULL);
get_string('allowbeforeblockdesc', 'admin', NULL);
get_string('allowediplist', 'admin', NULL);
get_string('blockediplist', 'admin', NULL);
get_string('webservices', 'admin', NULL);
get_string('webserviceprotocols', 'admin', NULL);
get_string('managewsprotocols', 'admin', NULL);
get_string('managews', 'admin', NULL);
get_string('webservicesystemsettings', 'admin', NULL);
get_string('ipwhitelist', 'admin', NULL);
get_string('webserviceusersettings', 'admin', NULL);
get_string('managewsusersettings', 'admin', NULL);
get_string('sitepolicies', 'admin', NULL);
get_string('protectusernames', 'admin', NULL);
get_string('configprotectusernames', 'admin', NULL);
@@ -941,14 +941,6 @@ old_get_string('allowbeforeblock', 'admin', NULL);
old_get_string('allowbeforeblockdesc', 'admin', NULL);
old_get_string('allowediplist', 'admin', NULL);
old_get_string('blockediplist', 'admin', NULL);
old_get_string('webservices', 'admin', NULL);
old_get_string('webserviceprotocols', 'admin', NULL);
old_get_string('managewsprotocols', 'admin', NULL);
old_get_string('managews', 'admin', NULL);
old_get_string('webservicesystemsettings', 'admin', NULL);
old_get_string('ipwhitelist', 'admin', NULL);
old_get_string('webserviceusersettings', 'admin', NULL);
old_get_string('managewsusersettings', 'admin', NULL);
old_get_string('sitepolicies', 'admin', NULL);
old_get_string('protectusernames', 'admin', NULL);
old_get_string('configprotectusernames', 'admin', NULL);
+324 -325
View File
@@ -1,394 +1,393 @@
<?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
* Web services utility functions and classes
*
* LICENSE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* http://www.gnu.org/copyleft/gpl.html
*
* @category Moodle
* @package webservice
* @copyright 2009 Moodle Pty Ltd (http://moodle.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(dirname(__FILE__)) . '/lib/formslib.php');
require_once($CFG->libdir.'/externallib.php');
/**
* Returns detailed information about external function
* @param string $functionname name of external function
* @return aray
*/
function ws_get_function_info($functionname) {
global $CFG, $DB;
function webservice_protocol_is_enabled($protocol) {
global $CFG;
$function = $DB->get_record('external_functions', array('name'=>$functionname), '*', MUST_EXIST);
$defpath = get_component_directory($function->component);
if (!file_exists("$defpath/db/services.php")) {
//TODO: maybe better throw invalid parameter exception
return null;
if (empty($CFG->enablewebservices)) {
return false;
}
$functions = array();
include("$defpath/db/services.php");
$active = explode(',', $CFG->webserviceprotocols);
if (empty($functions[$functionname])) {
return null;
}
$desc = $functions[$functionname];
if (empty($desc['classpath'])) {
$desc['classpath'] = "$defpath/externallib.php";
} else {
$desc['classpath'] = "$CFG->dirroot/".$desc['classpath'];
}
$desc['component'] = $function->component;
return $desc;
return(in_array($protocol, $active));
}
/**
* web service library
* Mandatory web service server interface
* @author Petr Skoda (skodak)
*/
final class webservice_lib {
/**
* Return list of all web service protocol into the webservice folder
* @global <type> $CFG
* @return <type>
*/
public static function get_list_protocols() {
global $CFG;
$protocols = array();
$directorypath = $CFG->dirroot . "/webservice";
if( $dh = opendir($directorypath)) {
while( false !== ($file = readdir($dh))) {
if( $file == '.' || $file == '..' || $file == 'CVS') { // Skip '.' and '..'
continue;
}
$path = $directorypath . '/' . $file;
///browse the subfolder
if( is_dir($path) ) {
if ($file != 'db') { //we don't want to browse the 'db' subfolder of webservice folder
require_once($path."/lib.php");
$classname = $file."_server";
$protocols[] = new $classname;
}
}
///retrieve api.php file
else {
continue;
}
}
closedir($dh);
}
return $protocols;
}
interface webservice_server {
/**
* Temporary Authentication method to be modified/removed
* @global <type> $DB
* @param <type> $token
* @return <type>
* Process request from client.
* @param bool $simple use simple authentication
* @return void
*/
public static function mock_check_token($token) {
//fake test
if ($token == 456) {
///retrieve the user
global $DB;
$user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
if (empty($user)) {
return false;
}
return $user;
} else {
return false;
}
}
/**
* Retrieve all external.php from Moodle (except the one of the exception list)
* @param <type> $
* @param <type> $directorypath
* @return boolean true if n
*/
public static function setListApiFiles( &$files, $directorypath ) {
global $CFG;
if(is_dir($directorypath)) { //check that we are browsing a folder not a file
if( $dh = opendir($directorypath)) {
while( false !== ($file = readdir($dh))) {
if( $file == '.' || $file == '..') { // Skip '.' and '..'
continue;
}
$path = $directorypath . '/' . $file;
///browse the subfolder
if( is_dir($path) ) {
webservice_lib::setListApiFiles($files, $path);
}
///retrieve api.php file
else if ($file == "external.php") {
$files[] = $path;
}
}
closedir($dh);
}
}
}
/**
* Check if the Moodle site has the web service protocol enable
* @global object $CFG
* @param string $protocol
*/
function display_webservices_availability($protocol) {
global $CFG;
$available = true;
echo get_string('webservicesenable','webservice').": ";
if (empty($CFG->enablewebservices)) {
echo "<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;
}
}
//check debugging
if ($CFG->debugdisplay) {
echo "<strong style=\"color:red\">".get_string('debugdisplayon','webservice')."</strong>";
$available = false;
}
return $available;
}
public function run($simple);
}
/**
* Web Service server base class
* Special abstraction of our srvices that allows
* interaction with stock Zend ws servers.
* @author skodak
*/
abstract class webservice_server {
abstract class webservice_zend_server implements webservice_server {
//TODO: implement base class for all ws servers in zend framework
// the idea is to create one huge class on the fly, this class contains all
// methods user is allowed to access and contains all needed PHPDoc metadata.
}
/**
* Web Service Protocol name (eg. SOAP, REST, XML-RPC,...)
* @var String
* Web Service server base class, this class handles both
* simple and token authentication.
* @author Petr Skoda (skodak)
*/
private $protocolname;
abstract class webservice_base_server implements webservice_server {
/** @property string $wsname name of the web server plugin */
protected $wsname = null;
/** @property bool $simple true if simple auth used */
protected $simple;
/** @property string $username name of local user */
protected $username = null;
/** @property string $password password of the local user */
protected $password = null;
/** @property string $token authentication token*/
protected $token = null;
/** @property array $parameters the function parameters - the real values submitted in the request */
protected $parameters = null;
/** @property string $functionname the name of the function that is executed */
protected $functionname = null;
/** @property object $function full function description */
protected $function = null;
/** @property mixed $returns function return value */
protected $returns = null;
/**
* Web Service Protocol id (eg. soap, rest, xmlrpc...)
* @var String
* Contructor
*/
private $protocolid;
public function __construct() {
}
abstract public function run();
/**
* This method parses the request input, it needs to get:
* 1/ user authentication - username+password or token
* 2/ function name
* 3/ function parameters
*
* @return void
*/
abstract protected function parse_request();
public function get_protocolname() {
return $this->protocolname;
}
/**
* Send the result of function call to the WS client.
* @return void
*/
abstract protected function send_response();
public function get_protocolid() {
return $this->protocolid;
}
/**
* Send the error information to the WS client.
* @param exception $ex
* @return void
*/
abstract protected function send_error($ex=null);
public function set_protocolname($protocolname) {
$this->protocolname = $protocolname;
}
public function set_protocolid($protocolid) {
$this->protocolid = $protocolid;
}
/**
* Process request from client.
* @param bool $simple use simple authentication
* @return void
*/
public function run($simple) {
$this->simple = $simple;
public function get_enable() {
return get_config($this->get_protocolid(), "enable");
}
// we will probably need a lot of memory in some functions
@raise_memory_limit('128M');
public function set_enable($enable) {
set_config("enable", $enable, $this->get_protocolid());
// set some longer timeout, this script is not sending any output,
// this means we need to manually extend the timeout operations
// that need longer time to finish
external_api::set_timeout();
// set up exception handler first, we want to sent them back in correct format that
// the other system understands
// we do not need to call the original default handler because this ws handler does everything
set_exception_handler(array($this, 'exception_handler'));
// init all properties from the request data
$this->parse_request();
// authenticate user, this has to be done after the request parsing
// this also sets up $USER and $SESSION
$this->authenticate_user();
// find all needed function info and make sure user may actually execute the function
$this->load_function_info();
// finally, execute the function - any errors are catched by the default exception handler
$this->execute();
// send the results back in correct format
$this->send_response();
// session cleanup
$this->session_cleanup();
die;
}
/**
* Names of the server settings
* @return array
* Specialised exception handler, we can not use the standard one because
* it can not just print html to output.
*
* @param exception $ex
* @return void does not return
*/
public static function get_setting_names() {
return array();
public function exception_handler($ex) {
global $CFG, $DB, $SCRIPT;
// detect active db transactions, rollback and log as error
if ($DB->is_transaction_started()) {
error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT);
try {
// note: transaction blocks should never change current $_SESSION
$DB->rollback_sql();
} catch (Exception $ignored) {
}
}
// now let the plugin send the exception to client
$this->send_error($ex);
// some hacks might need a cleanup hook
$this->session_cleanup($ex);
// not much else we can do now, add some logging later
exit(1);
}
public function settings_form(&$mform) {
}
}
/**
* Temporary authentication class to be removed/modified
*/
class ws_authentication {
/**
*
* @param object|struct $params
* @return integer
*/
function get_token($params) {
$params->username = clean_param($params->username, PARAM_ALPHANUM);
$params->password = clean_param($params->password, PARAM_ALPHANUM);
if ($params->username == 'wsuser' && $params->password == 'wspassword') {
return '456';
/**
* Future hook needed for emulated sessions.
* @param exception $exception null means normal termination, $exception received when WS call failed
* @return void
*/
protected function session_cleanup($exception=null) {
if ($this->simple) {
// nothing needs to be done, there is no persistent session
} else {
throw new moodle_exception('wrongusernamepassword');
// close emulated session if used
}
}
}
/**
* Form for web service user settings (administration)
*/
final class wsuser_form extends moodleform {
protected $username;
/**
* Definition of the moodleform
* Authenticate user using username+password or token.
* This function sets up $USER global.
* It is safe to use has_capability() after this.
* This method also verifies user is allowed to use this
* server.
* @return void
*/
public function definition() {
global $DB;
$this->username = $this->_customdata['username'];
$mform =& $this->_form;
protected function authenticate_user() {
global $CFG, $DB;
$mform->addElement('hidden', 'username', $this->username);
$mform->setType('username', PARAM_RAW);
$param = new stdClass();
$param->username = $this->username;
$wsuser = $DB->get_record("user", array("username" => $this->username));
if (!NO_MOODLE_COOKIES) {
throw new coding_exception('Cookies must be disabled in WS servers!');
}
$mform->addElement('text', 'ipwhitelist', get_string('ipwhitelist', 'admin'), array('value'=>get_user_preferences("ipwhitelist", "", $wsuser->id),'size' => '40'));
$mform->addElement('static', null, '', get_string('ipwhitelistdesc','admin', $param));
if ($this->simple) {
if (!is_enabled_auth('webservice')) {
die('WS auth not enabled');
}
$this->add_action_buttons(true, get_string('savechanges','admin'));
if (!$auth = get_auth_plugin('webservice')) {
die('WS auth missing');
}
if (!$this->username) {
throw new invalid_parameter_exception('Missing username');
}
if (!$this->password) {
throw new invalid_parameter_exception('Missing password');
}
if (!$auth->user_login_webservice($this->username, $this->password)) {
throw new invalid_parameter_exception('Wrong username or password');
}
$user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
// now fake user login, the session is completely empty too
session_set_user($user);
if (!has_capability("webservice/$this->wsname:use", get_context_instance(CONTEXT_SYSTEM))) {
throw new invalid_parameter_exception('Access to web service not allowed');
}
} else {
//TODO: not implemented yet
die('token login not implemented yet');
// note we had to wait until here because we did not know the security context earlier
if (!has_capability("webservice/$this->wsname:use", $context)) {
throw new invalid_parameter_exception('Access to web service not allowed');
}
}
}
}
/**
* Form for web service server settings (administration)
*/
final class wssettings_form extends moodleform {
protected $settings;
/**
* Definition of the moodleform
* Fetches the function description from database,
* verifies user is allowed to use this function and
* loads all paremeters and return descriptions.
* @return void
*/
public function definition() {
global $DB,$CFG;
$settings = $this->_customdata['settings'];
$mform =& $this->_form;
protected function load_function_info() {
global $DB, $USER, $CFG;
$mform->addElement('hidden', 'settings', $settings);
$mform->setType('settings', PARAM_RAW);
$param = new stdClass();
require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
$servername = $settings.'_server';
$server = new $servername();
$server->settings_form($mform);
// set the data if we have some.
$data = array();
$option_names = $server->get_setting_names();
foreach ($option_names as $config) {
$data[$config] = get_config($settings, $config);
if (empty($this->functionname)) {
throw new invalid_parameter_exception('Missing function name');
}
$this->set_data($data);
// function must exist
$function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST);
$this->add_action_buttons(true, get_string('savechanges','admin'));
// now let's verify access control
if ($this->simple) {
// now make sure the function is listed in at least one service user is allowed to use
// allow access only if:
// 1/ entry in the external_services_users table if required
// 2/ validuntil not reached
// 3/ has capability if specified in service desc
// 4/ iprestriction
$sql = "SELECT s.*, NULL AS iprestriction
FROM {external_services} s
JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0 AND sf.functionname = :name1)
WHERE s.enabled = 1
UNION
SELECT s.*, su.iprestriction
FROM {external_services} s
JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1 AND sf.functionname = :name2)
JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now";
$rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name1'=>$function->name, 'name2'=>$function->name, 'now'=>time()));
// now make sure user may access at least one service
$syscontext = get_context_instance(CONTEXT_SYSTEM);
$remoteaddr = getremoteaddr();
$allowed = false;
foreach ($rs as $service) {
if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) {
continue; // cap required, sorry
}
if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
continue; // wrong request source ip, sorry
}
$allowed = true;
break; // one service is enough, no need to continue
}
$rs->close();
if (!$allowed) {
throw new invalid_parameter_exception('Access to external function not allowed');
}
// now we finally know the user may execute this function,
// the last step is to set context restriction - in this simple case
// we use system context because each external system has different user account
// and we can manage everything through normal permissions.
external_api::set_context_restriction($syscontext);
} else {
//TODO: implement token security checks
die('not implemented yet');
}
// get the params and return descriptions of the function
unset($function->id); // we want to prevent any accidental db updates ;-)
$function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath;
if (!file_exists($function->classpath)) {
throw new coding_exception('Can not find file with external function implementation');
}
require_once($function->classpath);
$function->parameters_method = $function->methodname.'_parameters';
$function->returns_method = $function->methodname.'_returns';
// make sure the implementaion class is ok
if (!method_exists($function->classname, $function->methodname)) {
throw new coding_exception('Missing implementation method');
}
if (!method_exists($function->classname, $function->parameters_method)) {
throw new coding_exception('Missing parameters description');
}
if (!method_exists($function->classname, $function->returns_method)) {
throw new coding_exception('Missing returned values description');
}
// fetch the parameters description
$function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));
if (!($function->parameters_desc instanceof external_function_parameters)) {
throw new coding_exception('Invalid parameters description');
}
// fetch the return values description
$function->returns_desc = call_user_func(array($function->classname, $function->returns_method));
// null means void result or result is ignored
if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) {
throw new coding_exception('Invalid return description');
}
// we have all we need now
$this->function = $function;
}
}
/**
* Form for web service server settings (administration)
*/
final class wsservicesettings_form extends moodleform {
protected $settings;
/**
* Definition of the moodleform
* Execute previously loaded function using parameters parsed from the request data.
* @return void
*/
public function definition() {
global $DB,$CFG;
$serviceid = $this->_customdata['serviceid'];
$mform =& $this->_form;
protected function execute() {
// validate params, this also sorts the params properly, we need the correct order in the next part
$params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters);
$mform->addElement('hidden', 'serviceid', $serviceid);
$mform->setType('serviceid', PARAM_INT);
$param = new stdClass();
// require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
// $servername = $settings.'_server';
// $server = new $servername();
// $server->settings_form($mform);
// set the data if we have some.
// $data = array();
// $option_names = $server->get_setting_names();
// foreach ($option_names as $config) {
// $data[$config] = get_config($settings, $config);
// }
// $this->set_data($data);
$service = $DB->get_record('external_services',array('id' => $serviceid));
$mform->addElement('text', 'servicename', get_string('servicename', 'webservice'));
$mform->setDefault('servicename',get_string($service->name, 'webservice'));
if (!empty($serviceid)) {
$mform->disabledIf('servicename', 'serviceid', 'eq', $serviceid);
}
if (empty($serviceid)) {
//display list of functions to select
}
//display list of functions associated to the service
$this->add_action_buttons(true, get_string('savechanges','admin'));
// execute - yay!
$this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params));
}
}
?>
+12
View File
@@ -0,0 +1,12 @@
<?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(
),
),
);
-59
View File
@@ -1,59 +0,0 @@
<?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);
}
}
?>
+136 -214
View File
@@ -1,233 +1,155 @@
<?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
* REST web service implementation classes and methods.
*
* LICENSE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* http://www.gnu.org/copyleft/gpl.html
*
* @category Moodle
* @package webservice
* @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
* @copyright 2009 Moodle Pty Ltd (http://moodle.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once("$CFG->dirroot/webservice/lib.php");
/**
* Rest library
* @author Jerome Mouneyrac, Ferran Recio, David Castro Garcia
* REST service server implementation.
* @author Petr Skoda (skodak)
*/
/**
*
* @author Jerome Mouneyrac
* @global object $CFG
* @param string $rest_arguments example: /mod/forum/get_discussion
* @return string xml object
*/
function call_moodle_function ($rest_arguments) {
global $CFG, $USER;
///REST params conversion
$functionname = substr($rest_arguments,strrpos($rest_arguments,"/")+1); //retrieve the function name (it's located after the last '/') in $rest_arguments
//$rest_argument
$apipath = substr($rest_arguments,0, strlen($rest_arguments) - strlen($functionname)); //api path is the other part of $rest_arguments
$classname = str_replace('/', '_', $apipath); // convert '/' into '_' (e.g. /mod/forum/ => _mod_forum_)
$classname = substr($classname,1, strlen($classname) - 1); //remove first _ (e.g. _mod_forum => mod_forum)
$classname .= 'external';
/// Authentication process
/// TODO: this use a fake token => need to implement token generation
$token = optional_param('token',null,PARAM_ALPHANUM);
if (empty($token)) {
if ($functionname != 'get_token') {
throw new moodle_exception('identifyfirst');
} else {
/// TODO: authentication + token generation need to be implemented
if (optional_param('username',null,PARAM_ALPHANUM) == 'wsuser' && optional_param('password',null,PARAM_ALPHANUM) == 'wspassword') {
return '456';
} else {
throw new moodle_exception('wrongusernamepassword');
}
}
} else {
/// TODO: following function will need to be modified
$user = mock_check_token($token);
if (empty($user)) {
throw new moodle_exception('wrongidentification');
}
else {
/// TODO: probably change this
$USER = $user;
}
}
/// load the external class
$file = $CFG->dirroot.$apipath.'external.php';
$description = webservice_lib::generate_webservice_description($file, $classname);
/// This following line is only REST protocol
$params = retrieve_params ($description[$functionname]); //retrieve the REST params
/// Generic part to any protocols
if ($params === false) {
//return an error message, the REST params doesn't match with the web service description
}
try {
$res = call_user_func_array ( $classname.'::'.$functionname, array($params));
} catch (moodle_exception $e) {
return "<Result>".$e->getMessage()."</Result>";
}
///Transform result into xml in order to send the REST response
$key = key($description[$functionname]['return']);
if (strpos($key,":")!==false) {
$key = substr($key, strpos($key,":")+1);
} else {
$key = 'return';
}
$return = mdl_conn_rest_object_to_xml ($res,$key);
return "<Result>$return</Result>";
}
/**
* TODO: remove/rewrite this function
* Mock function waiting for token system implementation
* @param int $token
* @return object|boolean
*/
function mock_check_token($token) {
//fake test
if ($token == 456) {
///retrieve the user
global $DB;
$user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
if (empty($user)) {
return false;
}
return $user;
} else {
return false;
}
}
/**
* Convert into a Moodle type
* @param integer $param
* @return string
class webservice_rest_server extends webservice_base_server {
/**
* Contructor
*/
function convert_paramtype($param) {
switch ($param) {
case "integer":
return PARAM_NUMBER;
break;
case "integer":
return PARAM_INT;
break;
case "boolean":
return PARAM_BOOL;
break;
case "string":
return PARAM_ALPHANUM;
break;
case "object":
return PARAM_RAW;
break;
default:
return PARAM_RAW;
break;
public function __construct() {
parent::__construct();
$this->wsname = 'rest';
}
}
/**
*
* @author Jerome Mouneyrac
* @param array $description
* @return array
*/
function retrieve_params ($description) {
$params = array();
//retrieve REST param matching the description (warning: PHP assign the first instanciation as the first position in the table)
foreach ($description['params'] as $paramname => $paramtype) {
$paramtype = convert_paramtype($paramtype);
$value = optional_param($paramname,null,$paramtype);
if (!empty($value)) {
$params[$paramname] = $value;
/**
* This method parses the $_REQUEST superglobal and looks for
* the following information:
* 1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters)
* 2/ function name (wsfunction parameter)
* 3/ function parameters (all other parameters except those above)
*
* @return void
*/
protected function parse_request() {
if ($this->simple) {
$this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null;
unset($_REQUEST['wsusername']);
$this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
unset($_REQUEST['wspassword']);
$this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
unset($_REQUEST['wsfunction']);
$this->parameters = $_REQUEST;
} else {
//TODO
die('not implemented yet');
}
}
//retrieve REST optional params
if (!empty($description['optional'])) {
foreach ($description['optional'] as $paramname => $paramtype) {
$paramtype = convert_paramtype($paramtype);
$value = optional_param($paramname,null,$paramtype);
if (!empty($value)) {
$params[$paramname] = $value;
/**
* Send the result of function call to the WS client
* formatted as XML document.
* @return void
*/
protected function send_response() {
$this->send_headers();
$xml = '<?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 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 $params;
}
/**
* auxiliar function for simplexml_object_to_xml
* @author Ferran Recio, David Castro Garcia
* @param $obj
* @param $tag
* @param $atts assoc array (key => value)
* @return string
*/
function mdl_conn_rest_object_to_xml ($obj, $tag,$atts=false) {
$res = '';
$tag_atts = '';
if ($atts) {
$main_atts = array();
foreach ($atts as $att=>$val) {
$main_atts[] = "$att=\"".urlencode($val)."\"";
}
if (count($main_atts)) $tag_atts = ' '.implode(' ',$main_atts);
}
//if is an object
if (is_object($obj)) {
$parts = get_object_vars($obj);
foreach ($parts as $tag2 => $val) {
$res.= mdl_conn_rest_object_to_xml ($val, $tag2);
}
return "<$tag$tag_atts>\n$res</$tag>\n";
}
//if it's an array all elements will be inside te same tag but with a new atribute key
if (is_array($obj)){
if (!$atts) $atts = array();
//we came from another array
if (isset($atts['keys'])) $atts = array();
foreach ($obj as $key=>$val) {
$array_atts = $atts;
$array_atts['key'] = $key;
$res.= mdl_conn_rest_object_to_xml ($val, $tag,$array_atts);
}
return $res;
}
//any other type, just encapsule it
$obj = htmlentities($obj);
return "<$tag$tag_atts>$obj</$tag>\n";
}
?>
+26 -35
View File
@@ -1,47 +1,38 @@
<?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
* REST web service entry point. The authentication is done via tokens.
*
* LICENSE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* http://www.gnu.org/copyleft/gpl.html
*
* @category Moodle
* @package webservice
* @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
* @copyright 2009 Moodle Pty Ltd (http://moodle.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* REST Moodle server.
*
* NOTE: for this first implementation, REST requires implicit url encoded params.
* It uses function get_file_argument to get them.
*
* @author Jerome Mouneyrac
* @author Ferran Recio
* @author David Castro Garcia
*/
define('NO_MOODLE_COOKIES', true);
require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
require_once('lib.php');
require('../../config.php');
require_once("$CFG->dirroot/webservice/rest/locallib.php");
if (empty($CFG->enablewebservices)) {
if (!webservice_protocol_is_enabled('rest')) {
die;
}
$server = new rest_server();
$server->run();
$server = new webservice_rest_server();
$server->run(false);
die;
?>
+8 -559
View File
@@ -16,575 +16,24 @@
// 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
* @package webservice
* @copyright 2009 Moodle Pty Ltd (http://moodle.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/*
* NOTE: this is a proposal for a new WS server OOP framework
*
* I did not understand much how the WS protocols are supposed
* to work, I just tried to create some clean abstraction that
* should allow easy implementation of any protocol server.
* The REST was chosen only because it seems to be the easiest
* one with no real standardisation ;-)
*
* == How to test this ==
* 1/ create new service that includes function 'moodle_group_get_groups' by adding new local plugin,
* this adds new record into external_services table
* 2/ create new user and select 'webservice' as auth plugin and enable webservice auth plugin
* 3/ add $CFG->enablesimplewebservices=true; to your config.php
* 4/ manually enable the rest service: set_config('enable', 1, 'rest');
* 5/ manually insert record into external_services_users - your new service + your new user
* 6/ create course with some groups
* 7/ execute the REST query: http://nahore.skodak.local/moodle20/webservice/rest/simpleserver.php?wsusername=a&wspassword=p&wsfunction=moodle_group_get_groups&groupids[0]=1&groupids[1]=3
* 8/ sit tight and watch in awe the super hyper mega cool xml response of fully working REST WS server :-)
*
* skodak
*/
define('NO_MOODLE_COOKIES', true);
require('../../config.php');
require_once("$CFG->libdir/externallib.php");
//require_once("$CFG->dirroot/webservice/rest/lib.php"); TODO: uncomment when rewrite finished
//require_once("$CFG->dirroot/webservice/rest/locallib.php"); TODO: uncomment when rewrite finished
require_once("$CFG->dirroot/webservice/rest/locallib.php");
//======== NOTE: this should be defined in /webservice/rest/locallib.php =============================
/**
* REST service server class.
*
* @author Petr Skoda (skodak)
*/
class webservice_rest_server extends webservice_base_server {
/**
* Contructor
* @param bool $simple use simple authentication
*/
public function __construct($simple) {
parent::__construct($simple);
$this->wsname = 'rest';
}
/**
* This method parses the $_REQUEST superglobal and looks for
* the following information:
* 1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters)
* 2/ function name (wsfunction parameter)
* 3/ function parameters (all other parameters except those above)
*
* @return void
*/
protected function parse_request() {
if ($this->simple) {
$this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null;
unset($_REQUEST['wsusername']);
$this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
unset($_REQUEST['wspassword']);
$this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
unset($_REQUEST['wsfunction']);
$this->parameters = $_REQUEST;
} else {
//TODO
die('not implemented yet');
}
}
/**
* Send the result of function call to the WS client
* formatted as XML document.
* @return void
*/
protected function send_response() {
$this->send_headers();
$xml = '<?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 =============================
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;
@@ -1,69 +0,0 @@
<?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();
?>
@@ -1,23 +0,0 @@
<?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!');
?>
@@ -1,70 +0,0 @@
<?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();
?>
-49
View File
@@ -1,49 +0,0 @@
<?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'] = "[email protected]";
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();
?>
@@ -1,66 +0,0 @@
<?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();
?>
@@ -1,69 +0,0 @@
<?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();
?>
-66
View File
@@ -1,66 +0,0 @@
<?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();
?>
-65
View File
@@ -1,65 +0,0 @@
<?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();
?>
-63
View File
@@ -1,63 +0,0 @@
<?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();
?>
+83 -28
View File
@@ -1,38 +1,93 @@
<?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');
require('../../../config.php');
require_once("$CFG->dirroot/webservice/webservice_test_client_form.php");
require_once("$CFG->dirroot/webservice/rest/locallib.php");
start_interface (false);
$function = optional_param('function', '', PARAM_SAFEDIR);
$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()'));
$PAGE->set_url('webservice/rest/testclient/index.php');
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_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);
?>
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;
}
-226
View File
@@ -1,226 +0,0 @@
<?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="&nbsp;") {
$title2 = ($title)?$title:"&nbsp;";
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;
}
?>
@@ -0,0 +1,28 @@
<?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'));
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

-57
View File
@@ -1,57 +0,0 @@
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;
}
-70
View File
@@ -1,70 +0,0 @@
<?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();
?>
+3
View File
@@ -0,0 +1,3 @@
<?php
$plugin->version = 2009100800;
@@ -0,0 +1,19 @@
<?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'));
}
}
+5
View File
@@ -19,6 +19,11 @@
// //
///////////////////////////////////////////////////////////////////////////
// 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