From cc93c7da15bcd669959c7e554faab7c0b5c364ed Mon Sep 17 00:00:00 2001 From: skodak Date: Mon, 12 Oct 2009 21:46:16 +0000 Subject: [PATCH] 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 --- admin/external_forms.php | 89 +++ admin/external_service.php | 84 +++ admin/external_service_functions.php | 142 ++++ admin/external_service_users.php | 38 ++ admin/settings/plugins.php | 27 + admin/settings/security.php | 22 +- admin/webservice_protocols.php | 87 +++ admin/webservices.php | 117 ---- admin/wsprotocols.php | 88 --- lang/en_utf8/admin.php | 8 +- lang/en_utf8/webservice.php | 84 +-- lang/en_utf8/webservice_amf.php | 4 + lang/en_utf8/webservice_rest.php | 3 + lang/en_utf8/webservice_soap.php | 3 + lang/en_utf8/webservice_xmlrpc.php | 3 + lib/adminlib.php | 390 ++++++----- .../admin_index.php_get_string.log.php | 8 - .../admin_index.php_old_get_string.log.php | 8 - webservice/lib.php | 627 +++++++++--------- webservice/rest/db/access.php | 12 + webservice/rest/lib.php | 59 -- webservice/rest/locallib.php | 328 ++++----- webservice/rest/server.php | 61 +- webservice/rest/simpleserver.php | 567 +--------------- webservice/rest/testclient/addgroupmember.php | 69 -- webservice/rest/testclient/config_rest.php | 23 - webservice/rest/testclient/creategroup.php | 70 -- webservice/rest/testclient/createuser.php | 49 -- webservice/rest/testclient/deletegroup.php | 66 -- .../rest/testclient/deletegroupmember.php | 69 -- webservice/rest/testclient/deleteuser.php | 66 -- webservice/rest/testclient/getgroup.php | 65 -- webservice/rest/testclient/getusers.php | 63 -- webservice/rest/testclient/index.php | 117 +++- webservice/rest/testclient/lib.php | 226 ------- .../moodle_group_get_groups_form.php | 28 + webservice/rest/testclient/return.gif | Bin 132 -> 0 bytes webservice/rest/testclient/style.css | 57 -- webservice/rest/testclient/updateuser.php | 70 -- webservice/rest/version.php | 3 + webservice/webservice_test_client_form.php | 19 + webservice/wsdoc.php | 5 + 42 files changed, 1363 insertions(+), 2561 deletions(-) create mode 100644 admin/external_forms.php create mode 100644 admin/external_service.php create mode 100644 admin/external_service_functions.php create mode 100644 admin/external_service_users.php create mode 100644 admin/webservice_protocols.php delete mode 100644 admin/webservices.php delete mode 100644 admin/wsprotocols.php create mode 100644 lang/en_utf8/webservice_amf.php create mode 100644 lang/en_utf8/webservice_rest.php create mode 100644 lang/en_utf8/webservice_soap.php create mode 100644 lang/en_utf8/webservice_xmlrpc.php create mode 100644 webservice/rest/db/access.php delete mode 100644 webservice/rest/lib.php delete mode 100644 webservice/rest/testclient/addgroupmember.php delete mode 100644 webservice/rest/testclient/config_rest.php delete mode 100644 webservice/rest/testclient/creategroup.php delete mode 100644 webservice/rest/testclient/createuser.php delete mode 100644 webservice/rest/testclient/deletegroup.php delete mode 100644 webservice/rest/testclient/deletegroupmember.php delete mode 100644 webservice/rest/testclient/deleteuser.php delete mode 100644 webservice/rest/testclient/getgroup.php delete mode 100644 webservice/rest/testclient/getusers.php delete mode 100644 webservice/rest/testclient/lib.php create mode 100644 webservice/rest/testclient/moodle_group_get_groups_form.php delete mode 100644 webservice/rest/testclient/return.gif delete mode 100644 webservice/rest/testclient/style.css delete mode 100644 webservice/rest/testclient/updateuser.php create mode 100644 webservice/rest/version.php create mode 100644 webservice/webservice_test_client_form.php diff --git a/admin/external_forms.php b/admin/external_forms.php new file mode 100644 index 0000000000..3e24b667ae --- /dev/null +++ b/admin/external_forms.php @@ -0,0 +1,89 @@ +. + +/** + * Web services admin UI forms + * + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once $CFG->libdir.'/formslib.php'; + +class external_service_form extends moodleform { + function definition() { + global $CFG, $USER; + + $mform = $this->_form; + $service = $this->_customdata; + + $mform->addElement('header', 'extservice', get_string('externalservice', 'webservice')); + + $mform->addElement('text', 'name', get_string('name')); + $mform->addElement('advcheckbox', 'enabled', get_string('enabled', 'webservice')); + $mform->addElement('text', 'requiredcapability', get_string('requiredcapability', 'webservice')); + $mform->addElement('advcheckbox', 'restrictedusers', get_string('restrictedusers', 'webservice')); + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $this->add_action_buttons(true); + + $this->set_data($service); + } + + function definition_after_data() { + $mform = $this->_form; + $service = $this->_customdata; + + if (!empty($service->component)) { + // custom component + $mform->hardFreeze('name,requiredcapability,restrictedusers'); + } + } +} + +class external_service_functions_form extends moodleform { + function definition() { + global $CFG, $USER, $DB; + + $mform = $this->_form; + $data = $this->_customdata; + + $mform->addElement('header', 'addfunction', get_string('addfunction', 'webservice')); + + $select = "name NOT IN (SELECT s.functionname + FROM {external_services_functions} s + WHERE s.externalserviceid = :sid + )"; + + $functions = $DB->get_records_select_menu('external_functions', $select, array('sid'=>$data['id']), 'name', 'id, name'); + + $mform->addElement('select', 'fid', get_string('name'), $functions); + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'action'); + $mform->setType('action', PARAM_ACTION); + + $this->add_action_buttons(true); + + $this->set_data($data); + } +} diff --git a/admin/external_service.php b/admin/external_service.php new file mode 100644 index 0000000000..089ef3fada --- /dev/null +++ b/admin/external_service.php @@ -0,0 +1,84 @@ +. + +/** + * Web services admin UI + * + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once('external_forms.php'); + +$id = required_param('id', PARAM_INT); +$action = optional_param('action', '', PARAM_ACTION); +$confirm = optional_param('confirm', 0, PARAM_BOOL); + +$PAGE->set_url('admin/external_service.php', array('id'=>$id)); + +admin_externalpage_setup('externalservice'); + +$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=externalservices"; + +if ($id) { + $service = $DB->get_record('external_services', array('id'=>$id), '*', MUST_EXIST); +} else { + $service = null; +} + +if ($action == 'delete' and confirm_sesskey() and $service and empty($service->component)) { + if (!$confirm) { + admin_externalpage_print_header(); + $optionsyes = array('id'=>$id, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey()); + $optionsno = array('section'=>'externalservices'); + $formcontinue = html_form::make_button('external_service.php', $optionsyes, get_string('delete'), 'post'); + $formcancel = html_form::make_button('settings.php', $optionsno, get_string('cancel'), 'get'); + echo $OUTPUT->confirm(get_string('deleteserviceconfirm', 'webservice', $service->name), $formcontinue, $formcancel); + echo $OUTPUT->footer(); + die; + } + $DB->delete_records('external_services_users', array('externalserviceid'=>$service->id)); + $DB->delete_records('external_services_functions', array('externalserviceid'=>$service->id)); + $DB->delete_records('external_services', array('id'=>$service->id)); + redirect($returnurl); +} + +$mform = new external_service_form(null, $service); + +if ($mform->is_cancelled()) { + redirect($returnurl); + +} else if ($data = $mform->get_data()) { + $data = (object)$data; + + //TODO: add timecreated+modified and maybe logging too + if (empty($data->id)) { + $DB->insert_record('external_services', $data); + } else { + $DB->update_record('external_services', $data); + } + + redirect($returnurl); +} + +admin_externalpage_print_header(); +$mform->display(); +echo $OUTPUT->footer(); + diff --git a/admin/external_service_functions.php b/admin/external_service_functions.php new file mode 100644 index 0000000000..298fb30672 --- /dev/null +++ b/admin/external_service_functions.php @@ -0,0 +1,142 @@ +. + +/** + * Web services function UI + * + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once('external_forms.php'); + +$id = required_param('id', PARAM_INT); +$fid = optional_param('fid', 0, PARAM_INT); +$action = optional_param('action', '', PARAM_ACTION); +$confirm = optional_param('confirm', 0, PARAM_BOOL); + +$PAGE->set_url('admin/external_service_functions.php', array('id'=>$id)); + +admin_externalpage_setup('externalservicefunctions'); + +$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=externalservices"; +$thisurl = "external_service_functions.php?id=$id"; + +$service = $DB->get_record('external_services', array('id'=>$id), '*', MUST_EXIST); + +if ($action === 'delete' and confirm_sesskey() and $service and empty($service->component)) { + $function = $DB->get_record('external_functions', array('id'=>$fid), '*', MUST_EXIST); + if (!$confirm) { + admin_externalpage_print_header(); + $optionsyes = array('id'=>$id, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey(), 'fid'=>$function->id); + $optionsno = array('id'=>$id); + $formcontinue = html_form::make_button('external_service_functions.php', $optionsyes, get_string('delete'), 'post'); + $formcancel = html_form::make_button('external_service_functions.php', $optionsno, get_string('cancel'), 'get'); + echo $OUTPUT->confirm(get_string('removefunctionconfirm', 'webservice', (object)array('service'=>$service->name, 'function'=>$function->name)), $formcontinue, $formcancel); + echo $OUTPUT->footer(); + die; + } + $DB->delete_records('external_services_functions', array('externalserviceid'=>$service->id, 'functionname'=>$function->name)); + redirect($thisurl); + +} else if ($action === 'add') { + $mform = new external_service_functions_form(null, array('action'=>'add', 'id'=>$service->id)); + + if ($mform->is_cancelled()) { + redirect($thisurl); + } else if ($data = $mform->get_data()) { + ignore_user_abort(true); // no interruption here! + $function = $DB->get_record('external_functions', array('id'=>$data->fid), '*', MUST_EXIST); + // make sure the function is not there yet + if ($DB->record_exists('external_services_functions', array('externalserviceid'=>$service->id, 'functionname'=>$function->name))) { + redirect($thisurl); + } + $new = new object(); + $new->externalserviceid = $service->id; + $new->functionname = $function->name; + $DB->insert_record('external_services_functions', $new); + redirect($thisurl); + } + + //ask for function id + admin_externalpage_print_header(); + echo $OUTPUT->heading($service->name); + $mform->display(); + echo $OUTPUT->footer(); + die; +} + +admin_externalpage_print_header(); + +echo $OUTPUT->heading($service->name); + +$select = "name IN (SELECT s.functionname + FROM {external_services_functions} s + WHERE s.externalserviceid = :sid + )"; + +$functions = $DB->get_records_select('external_functions', $select, array('sid'=>$service->id), 'name'); + +$strfunction = get_string('function', 'webservice'); +$strdelete = get_string('removefunction', 'webservice'); +$stredit = get_string('edit'); + +$table = new html_table(); +$table->head = array($strfunction); +$table->align = array('left'); +$table->width = '100%'; +$table->data = array(); +if (empty($service->component)) { + $table->head[] = $stredit; + $table->align[] = 'center'; +} + +$durl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php?sesskey=".sesskey(); + +foreach ($functions as $function) { + if (empty($service->component)) { + $delete = "id&id=$service->id\">$strdelete"; + $table->data[] = array($function->name, $delete); + } else { + $table->data[] = array($function->name); + } +} + +echo $OUTPUT->table($table); + + +// we can edit only custom functions, the build-in would be overridden after each upgrade +if (empty($service->component)) { + $form = new html_form(); + $form->url = new moodle_url('external_service_functions.php', array('sesskey'=>sesskey(), 'id'=>$service->id, 'action'=>'add')); + $form->button->text = get_string('add'); + $form->method = 'get'; + echo $OUTPUT->button($form); +} + +// simple back button +$form = new html_form(); +$form->url = new moodle_url('settings.php', array('section'=>'externalservices')); +$form->button->text = get_string('back'); +$form->method = 'get'; +echo $OUTPUT->button($form); + +echo $OUTPUT->footer(); + diff --git a/admin/external_service_users.php b/admin/external_service_users.php new file mode 100644 index 0000000000..e3b7584c8f --- /dev/null +++ b/admin/external_service_users.php @@ -0,0 +1,38 @@ +. + +/** + * Web services function UI + * + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once('external_forms.php'); + +$id = required_param('id', PARAM_INT); + +$PAGE->set_url('admin/external_service_users.php', array('id'=>$id)); + +admin_externalpage_setup('externalserviceusers'); + +echo('TODO: we need something like the role assign UI'); + +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index 1161a4b74b..8c981594d8 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -237,6 +237,33 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext)) } } + // Web services + $ADMIN->add('modules', new admin_category('webservicesettings', get_string('webservices', 'webservice'))); + $temp = new admin_settingpage('externalservices', get_string('externalservices', 'webservice')); + $temp->add(new admin_setting_manageexternalservices()); + $ADMIN->add('webservicesettings', $temp); + $ADMIN->add('webservicesettings', new admin_externalpage('externalservice', get_string('externalservice', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service.php"), 'moodle/site:config', true); + $ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions', get_string('externalservicefunctions', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_functions.php"), 'moodle/site:config', true); + $ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers', get_string('externalserviceusers', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_users.php"), 'moodle/site:config', true); + $temp = new admin_settingpage('webserviceprotocols', get_string('manageprotocols', 'webservice')); + $temp->add(new admin_setting_managewebserviceprotokols()); + if (empty($CFG->enablewebservices)) { + $temp->add(new admin_setting_heading('webservicesaredisabled', '', get_string('disabledwarning', 'webservice'))); + } + $ADMIN->add('webservicesettings', $temp); + $webservices_available = get_plugin_list('webservice'); + $active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols); + foreach ($webservices_available as $webservice => $location) { + if (file_exists("$location/settings.php")) { + $name = get_string('pluginname', 'webservice_'.$webservice); + $settings = new admin_settingpage('webservicesetting'.$webservice, $name, 'moodle/site:config', !in_array($webservice, $active_webservices) or empty($CFG->enablewebservices)); + if ($ADMIN->fulltree) { + include("$location/settings.php"); + } + $ADMIN->add('webservicesettings', $settings); + } + } + // Question type settings. $ADMIN->add('modules', new admin_category('qtypesettings', get_string('questiontypes', 'admin'))); $ADMIN->add('qtypesettings', new admin_page_manageqtypes()); diff --git a/admin/settings/security.php b/admin/settings/security.php index e5601f80d0..71145d2ee5 100644 --- a/admin/settings/security.php +++ b/admin/settings/security.php @@ -11,26 +11,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page '', '')); $ADMIN->add('security', $temp); - // "web service" settingpage - $temp = new admin_settingpage('webservices', get_string('webservices', 'admin')); - $temp->add(new admin_setting_heading('webserviceprotocols', get_string('protocols', 'webservice'), '')); - $temp->add(new admin_setting_managewsprotocols()); - $url = $CFG->wwwroot.'/'.$CFG->admin.'/wsprotocols.php'; - $ADMIN->add('security', new admin_externalpage('managews', - get_string('managews', 'admin'), $url, 'moodle/site:config', true), - '', $url); - $temp->add(new admin_setting_heading('webservicesystemsettings', get_string('systemsettings', 'webservice'), '')); - $temp->add(new admin_setting_configiplist('ipwhitelist', get_string('ipwhitelist', 'admin'),'', '')); - $temp->add(new admin_setting_heading('webserviceusersettings', get_string('usersettings', 'webservice'), '')); - $temp->add(new admin_setting_managewsusersettings()); - $temp->add(new admin_setting_heading('webserviceservicelist', get_string('servicelist', 'webservice'), '')); - $temp->add(new admin_setting_managewsservicelist()); - $url = $CFG->wwwroot.'/'.$CFG->admin.'/webservices.php'; - $ADMIN->add('security', new admin_externalpage('webservicessettings', - get_string('webservicessettings', 'admin'), $url, 'moodle/site:config', true), - '', $url); - $ADMIN->add('security', $temp); - // "sitepolicies" settingpage $temp = new admin_settingpage('sitepolicies', get_string('sitepolicies', 'admin')); $temp->add(new admin_setting_configcheckbox('protectusernames', get_string('protectusernames', 'admin'), get_string('configprotectusernames', 'admin'), 1)); @@ -137,4 +117,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page } // end of speedup -?> + diff --git a/admin/webservice_protocols.php b/admin/webservice_protocols.php new file mode 100644 index 0000000000..e1b7abab81 --- /dev/null +++ b/admin/webservice_protocols.php @@ -0,0 +1,87 @@ +. + +/** + * Web services protocols admin UI + * + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once($CFG->libdir.'/tablelib.php'); + +$PAGE->set_url('admin/webservice_protocols.php', array()); +//TODO: disable the blocks here or better make the page layout default to no blocks! + +require_login(); +require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); + +$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webserviceprotocols"; + +$action = optional_param('action', '', PARAM_ACTION); +$webservice = optional_param('webservice', '', PARAM_SAFEDIR); +$confirm = optional_param('confirm', 0, PARAM_BOOL); + +// get currently installed and enabled auth plugins +$available_webservices = get_plugin_list('webservice'); +if (!empty($webservice) and empty($available_webservices[$webservice])) { + redirect($returnurl); +} + +$active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols); +foreach ($active_webservices as $key=>$active) { + if (empty($available_webservices[$active])) { + unset($active_webservices[$key]); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// process actions + +if (!confirm_sesskey()) { + redirect($returnurl); +} + +switch ($action) { + case 'uninstall': + die('TODO: not implemented yet'); + break; + + case 'disable': + // remove from enabled list + $key = array_search($webservice, $active_webservices); + unset($active_webservices[$key]); + break; + + case 'enable': + // add to enabled list + if (!in_array($webservice, $active_webservices)) { + $active_webservices[] = $webservice; + $active_webservices = array_unique($active_webservices); + } + break; + + default: + break; +} + +set_config('webserviceprotocols', implode(',', $active_webservices)); + +redirect($returnurl); diff --git a/admin/webservices.php b/admin/webservices.php deleted file mode 100644 index 8628a53b66..0000000000 --- a/admin/webservices.php +++ /dev/null @@ -1,117 +0,0 @@ -. - -require_once(dirname(dirname(__FILE__)) . '/config.php'); -require_once($CFG->libdir . '/adminlib.php'); -require_once($CFG->dirroot . '/webservice/lib.php'); - - -$serviceid = optional_param('serviceid', '', PARAM_FORMAT); -$remove = optional_param('remove', '', PARAM_FORMAT); - -$pagename = 'webservicessettings'; - - -admin_externalpage_setup($pagename); -require_login(SITEID, false); -require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); - -$sesskeyurl = "$CFG->wwwroot/$CFG->admin/webservices.php?sesskey=" . sesskey(); -$baseurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webservices"; - -if (!confirm_sesskey()) { - print_error('confirmsesskeybad', '', $baseurl); -} - -if (!empty($remove)) { - $functionserviceid = optional_param('functionserviceid', '', PARAM_FORMAT); - if (!empty($functionserviceid)) { - $DB->delete_records('external_services_functions',array('id' => $functionserviceid)); - } -} - -if (!empty($serviceid)) { - admin_externalpage_print_header(); - - //cannot use moodle form in order to display complex list of functions - $form = new html_form(); - $service = $DB->get_record('external_services',array('id' => $serviceid)); - $formhtml = get_string('servicename', 'webservice').': '.get_string($service->name, 'webservice') ; - $formhtml .= "

"; - //display function selector - if (empty($serviceid)) { - - } - - //display service functions - $servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, f.component as component, s.name as servicename, s.id as serviceid, f.name as functionname, f.id as functionid - FROM {external_services} s, {external_functions} f, {external_services_functions} fs - WHERE fs.externalserviceid = s.id AND fs.functionname = f.name AND s.id = ?", array($serviceid)); - - //save the administrator changes - $saved = optional_param('saved', 0, PARAM_NUMBER); - - if ($saved) { - foreach($servicesfunctions as &$servicefunction) { //need to be a refence cause we're going to update the form value too - $enabled = optional_param($servicefunction->functionname, '', PARAM_ALPHANUMEXT); - if ($enabled) { - $servicefunction->enabled = 1; //update the form "enabled" value - } else { - $servicefunction->enabled = 0; //update the form "enabled" value - } - $wsservicefunction = new object(); - $wsservicefunction->id = $servicefunction->id; - $wsservicefunction->enabled = $servicefunction->enabled; - $DB->update_record('external_services_functions',$wsservicefunction); - } - } - - - $data = array(); - reset($servicesfunctions); - foreach($servicesfunctions as $servicefunction) { - $checkbox = html_select_option::make_checkbox($servicefunction->functionid, $servicefunction->enabled, 'functionenabled'); - $checkbox->label->add_class('accesshide'); - $checkbox->disabled; - $checkboxhtml = $OUTPUT->checkbox($checkbox, $servicefunction->functionname); - $data[] = array($servicefunction->functionname, $servicefunction->component, "id.">".get_string("removefunctionfromservice","webservice").""); - } - $table = new html_table(); - $table->head = array(get_string('functionname', 'webservice'), get_string('component', 'webservice'), get_string('actions', 'webservice')); - $table->size = array('40%', '40%', '20%'); - $table->align = array('left', 'left', 'left'); - //$table->width = '30%'; - $table->data = $data; - $table->tablealign = 'center'; - $formhtml .= $OUTPUT->table($table); - - $form->button->text = get_string('save', 'webservice'); - $form->button->title = get_string('save', 'webservice'); - $form->button->id = 'save'; - $form->url = new moodle_url('webservices.php', array('serviceid' => $serviceid, 'saved' => 1)); - //$form->add_class($class); - $formhtml .= "

"; - - echo $OUTPUT->box_start('generalbox boxaligncenter centerpara'); - echo $OUTPUT->form($form, $formhtml); - echo $OUTPUT->box_end(); - - echo $OUTPUT->footer(); - -} - -?> diff --git a/admin/wsprotocols.php b/admin/wsprotocols.php deleted file mode 100644 index ad0bf593f7..0000000000 --- a/admin/wsprotocols.php +++ /dev/null @@ -1,88 +0,0 @@ -dirroot . '/webservice/lib.php'); -require_once($CFG->libdir . '/adminlib.php'); - -$hide = optional_param('hide', '', PARAM_ALPHANUM); -$username = optional_param('username', '', PARAM_ALPHANUM); -$settings = optional_param('settings', '', PARAM_ALPHANUM); - -$pagename = 'managews'; - -admin_externalpage_setup($pagename); -require_login(SITEID, false); -require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); - -$baseurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webservices"; - -if (!confirm_sesskey()) { - print_error('confirmsesskeybad', '', $baseurl); - } - -if (!empty($hide)) { - - set_config("enable", !get_config($hide, "enable"), $hide); - $return = true; -} else if (!empty($username)) { - admin_externalpage_print_header(); - $mform = new wsuser_form('', array('username' => $username)); - if ($mform->is_cancelled()){ - redirect($baseurl); - exit; - } - $fromform = $mform->get_data(); - - - - if (!empty($fromform)) { - $wsuser = $DB->get_record("user", array("username" => $fromform->username)); - set_user_preference("ipwhitelist", $fromform->ipwhitelist, $wsuser->id); - redirect($baseurl,get_string("changessaved")); - } - - echo $OUTPUT->box_start(); - $mform->display(); - echo $OUTPUT->box_end(); - -} else if (!empty($settings)) { -/// Server settings page - admin_externalpage_print_header(); - - $mform = new wssettings_form('', array('settings' => $settings)); // load the server settings form - - if ($mform->is_cancelled()){ - /// user pressed cancel button and return to the security web service page - redirect($baseurl); - exit; - } - - $fromform = $mform->get_data(); - - if (!empty($fromform)) { - /// save the new setting - require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php'); - $settingnames = call_user_func(array($settings.'_server', 'get_setting_names')); - foreach($settingnames as $settingname) { - if (empty($fromform->$settingname)) { - set_config($settingname, null, $settings); - } else { - set_config($settingname, $fromform->$settingname, $settings); - } - } - - redirect($baseurl,get_string("changessaved")); // return to the security web service page - } -/// display the server settings form - echo $OUTPUT->box_start(); - $mform->display(); - echo $OUTPUT->box_end(); -} else { - $return = true; -} - -if (!empty($return)) { - redirect($baseurl); -} - -echo $OUTPUT->footer(); diff --git a/lang/en_utf8/admin.php b/lang/en_utf8/admin.php index 09c1fefa95..dbc4c5c9ff 100644 --- a/lang/en_utf8/admin.php +++ b/lang/en_utf8/admin.php @@ -527,8 +527,6 @@ It is recommended to install local copy of free GeoLite City database from MaxMi IP address location is displayed on simple map or using Google Maps. Please note that you need to have a Google account and apply for free Google Maps API key to enable interactive maps.'; $string['iplookupmaxmindnote'] = 'This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/.'; $string['iplookupnetgeonote'] = 'The NetGeo server is currently being used to look up geographical information. For more accurate results we recommend installing a local copy of the MaxMind GeoLite database.'; -$string['ipwhitelist'] = 'IP whitelist'; -$string['ipwhitelistdesc'] = 'When not empty, only IP set here are allowed to use web service with the username: $a->username'; $string['keeptagnamecase'] = 'Keep tag name casing'; $string['lang'] = 'Default language'; $string['lang16notify'] = 'Moodle 1.6 and above allows you to install and update language packs directly from download.moodle.org by following the link below'; @@ -571,7 +569,6 @@ $string['maintfileopenerror'] = 'Error opening maintenance files!'; $string['maintinprogress'] = 'Maintenance is in progress...'; $string['managelang'] = 'Manage'; $string['manageqtypes'] = 'Manage question types'; -$string['managews'] = 'Manage web services'; $string['maintenancemode'] = 'In Maintenance Mode'; $string['maxbytes'] = 'Maximum uploaded file size'; $string['maxeditingtime'] = 'Maximum time to edit posts'; @@ -670,6 +667,7 @@ $string['php50restricted'] = 'PHP 5.0.x has a number of known problems, please u $string['phpfloatproblem'] = 'Detected unexpected problem in handling of PHP float numbers - $a'; $string['pleaseregister'] = 'Please register your site to remove this button'; $string['pleaserefreshregistration'] = 'Your site has been registered with moodle.org, please consider updating the registration if significant changes happened since your last update, on $a'; +$string['plugin'] = 'Plugin'; $string['plugins'] = 'Plugins'; $string['profilecategory'] = 'Category'; $string['profilecategoryname'] = 'Category name (must be unique)'; @@ -832,6 +830,8 @@ $string['supportname'] = 'Support name'; $string['supportpage'] = 'Support page'; $string['switchlang'] = 'Switch lang directory'; $string['systempaths'] = 'System Paths'; +$string['tablenosave'] = 'Changes in table above are saved automatically.'; +$string['tablesnosave'] = 'Changes in tables above are saved automatically.'; $string['tabselectedtofront'] = 'On tables with tabs, should the row with the currently selected tab be placed at the front'; $string['tabselectedtofronttext'] = 'Bring selected tab row to front'; $string['themelist'] = 'Theme list'; @@ -849,6 +849,7 @@ $string['unicodeupgradenotice'] = 'In Moodle 1.6 we have migrated all languages $string['unicoderecommended'] = 'Storing all your data in Unicode (UTF-8) is recommended. New installations should be performed into databases that have their default character set as Unicode. If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).'; $string['unicoderequired'] = 'It is required that you store all your data in Unicode format (UTF-8). New installations must be performed into databases that have their default character set as Unicode. If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).'; $string['uninstall'] = 'Uninstall selected language pack'; +$string['uninstallplugin'] = 'Uninstall'; $string['uninstallconfirm'] = 'You are about to completely uninstall language pack $a, are you sure?'; $string['uninstallqtype'] = 'Uninstall this question type.'; $string['unsupported'] = 'Unsupported'; @@ -931,7 +932,6 @@ $string['verifychangedemail'] = 'Restrict domains when changing email'; $string['warningcurrentsetting'] = 'Invalid current value: $a'; $string['webproxy'] = 'Web proxy'; $string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.
PHP cURL extension is highly recommended.'; -$string['webservices'] = 'Web services'; $string['xmlrpcrecommended'] = 'Installing the optional xmlrpc extension is useful for Moodle Networking functionality.'; $string['xmlstrictheaders'] = 'XML strict headers'; $string['useblogassociations'] = 'Enable associations'; diff --git a/lang/en_utf8/webservice.php b/lang/en_utf8/webservice.php index 0847061da0..a3114fa509 100644 --- a/lang/en_utf8/webservice.php +++ b/lang/en_utf8/webservice.php @@ -1,61 +1,25 @@ -Alert the Moodle administrator to set it Off.'; -$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'] = '

SOAP Manual

- 1. Call the method get_token on \"http://remotemoodle/webservice/soap/server.php?wsdl\"
- The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")
- Return value is a token (integer)
-
- 2. Then call a moodle web service method on \"http://remotemoodle/webservice/soap/server.php?token=the_received_token&classpath=the_moodle_path&wsdl\"
- Every method has only one parameter which is an array.
-
- For example in PHP for this specific function:
- Moodle path: user
- tmp_delete_user( string username , integer mnethostid )
- You will call something like:
- your_client->tmp_delete_user(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1))

-'; -$string['systemsettings'] = 'Common settings'; -$string['usersettings'] = 'Users with web service permissions'; -$string['webservicesenable'] = 'Web services enable'; -$string['wsdeletefunction'] = '$a->functionname function has been deleted from the $a->servicename service.'; -$string['wsinsertfunction'] = '$a->functionname function has been inserted into the $a->servicename service.'; -$string['wspagetitle'] = 'Web services documentation'; -$string['wsuserreminder'] = 'Reminder: the Moodle administrator of this site needs to give you moodle/site:usewebservices capability.'; -$string['xmlrpcdocumentation'] = '

XMLRPC Manual

- 1. Call the method authentication.get_token on \"http://remotemoodle/webservice/xmlrpc/server.php\"
- The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")
- Return value is a token (integer)
-
- 2. Then call a moodle web service method on \"http://remotemoodle/webservice/xmlrpc/server.php?classpath=the_moodle_path&token=the_received_token\"
- Every method has only one parameter which is an array.
-
- For example in PHP for this specific function:
- Moodle path: user
- tmp_delete_user( string username , integer mnethostid )
- You will call something like:
- your_client->call(\"user.tmp_delete_user\", array(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1)))
- -'; - -//service names -$string['user'] = "User"; +function\" from service \"$a->service\"?'; +$string['requiredcapability'] = 'Required capability'; +$string['restrictedusers'] = 'Restricted users'; +$string['servicesbuiltin'] = 'Built-in services'; +$string['servicescustom'] = 'Custom services'; +$string['test'] = 'Test'; +$string['testclient'] = 'Test client'; +$string['webservices'] = 'Web services'; diff --git a/lang/en_utf8/webservice_amf.php b/lang/en_utf8/webservice_amf.php new file mode 100644 index 0000000000..f51fe76cb8 --- /dev/null +++ b/lang/en_utf8/webservice_amf.php @@ -0,0 +1,4 @@ +data[] =array($displayname, $hideshow, $updown, $settings); } $return .= $OUTPUT->table($table); - $return .= get_string('configeditorplugins', 'editor').'
'.get_string('tablenosave', 'filters'); + $return .= get_string('configeditorplugins', 'editor').'
'.get_string('tablenosave', 'admin'); $return .= $OUTPUT->box_end(); return highlight($query, $return); } @@ -6077,26 +6077,23 @@ class admin_setting_managerepository extends admin_setting { } } + /** + * Special class for management of external services * - * - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda (skodak) */ -class admin_setting_managewsprotocols extends admin_setting { -/** @var string */ - private $baseurl; - +class admin_setting_manageexternalservices extends admin_setting { /** * Calls parent::__construct with specific arguments */ public function __construct() { - global $CFG; - parent::__construct('managewsprotocols', get_string('managewsprotocols', 'admin'), '', ''); - $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey(); + parent::__construct('webservicesui', get_string('externalservices', 'webservice'), '', ''); } /** * Always returns true, does nothing + * * @return true */ public function get_setting() { @@ -6104,157 +6101,175 @@ class admin_setting_managewsprotocols extends admin_setting { } /** - * Doesnt nothing, always returns '' + * Always returns true, does nothing + * + * @return true + */ + public function get_defaultsetting() { + return true; + } + + /** + * Always returns '', does not write anything * * @return string Always returns '' */ public function write_setting($data) { - $url = $this->baseurl . '&new=' . $data; + // do not write any setting return ''; } /** - * Builds XHTML to display the control + * Checks if $query is one of the available external services * - * @param string $data + * @param string $query The string to search for + * @return bool Returns true if found, false if not + */ + public function is_related($query) { + global $DB; + + if (parent::is_related($query)) { + return true; + } + + $textlib = textlib_get_instance(); + $services = $DB->get_records('external_services', array(), 'id, name'); + foreach ($services as $service) { + if (strpos($textlib->strtolower($service->name), $query) !== false) { + return true; + } + } + return false; + } + + /** + * Builds the XHTML to display the control + * + * @param string $data Unused * @param string $query - * @return string XHTML + * @return string */ public function output_html($data, $query='') { - global $CFG, $OUTPUT; + global $CFG, $OUTPUT, $DB; + + // display strings + $stradministration = get_string('administration'); + $stredit = get_string('edit'); + $strservice = get_string('externalservice', 'webservice'); + $strdelete = get_string('delete'); + $strplugin = get_string('plugin', 'admin'); + $stradd = get_string('add'); + $strfunctions = get_string('functions', 'webservice'); + $strusers = get_string('restrictedusers', 'webservice'); + + $esurl = "$CFG->wwwroot/$CFG->admin/external_service.php"; + $efurl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php"; + $euurl = "$CFG->wwwroot/$CFG->admin/external_service_users.php"; + + // built in services + $return = $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main', true); + + $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name'); - $namestr = get_string('name'); - $settingsstr = get_string('settings'); - $hiddenstr = get_string('activated', 'webservice'); - require_once("../webservice/lib.php"); - $protocols = webservice_lib::get_list_protocols(); $table = new html_table(); - $table->head = array($namestr, $hiddenstr, $settingsstr); - $table->align = array('left', 'center', 'center'); - $table->data = array(); - $table->tablealign = 'center'; + $table->head = array($strservice, $strplugin, $strfunctions, $strusers, $stredit); + $table->align = array('left', 'left', 'center', 'center', 'center'); + $table->size = array('30%', '20%', '20%', '20%', '10%'); + $table->width = '100%'; + $table->data = array(); - foreach ($protocols as $i) { - $hidetitle = $i->get_protocolid() ? get_string('clicktodeactivate', 'webservice') : get_string('clicktoactivate', 'webservice'); - $hiddenshow = ' ' - .'' . $hidetitle . '' - .'' . "\n"; + // iterate through auth plugins and add to the display table + foreach ($services as $service) { + $name = $service->name; - $settingnames = $i->get_setting_names(); - if (!empty($settingnames)) { - $settingsshow = ' ' - .$settingsstr - .'' . "\n"; + // hide/show link + if ($service->enabled) { + $displayname = "$name"; } else { - $settingsshow = ""; + $displayname = "$name"; } - $table->data[] = array($i->get_protocolname(), $hiddenshow, $settingsshow); - //display a grey row if the type is defined as not visible - if (!$i->get_enable()) { - $table->rowclasses[] = 'dimmed_text'; + $plugin = $service->component; + + $functions = "id\">$strfunctions"; + + if ($service->restrictedusers) { + $users = "id\">$strusers"; } else { - $table->rowclasses[] = ''; + $users = '-'; } - } - $output = $OUTPUT->table($table); - $output .= "

"; - return highlight($query, $output); - } -} -/** - * - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class admin_setting_managewsusersettings extends admin_setting { -/** @var string */ - private $baseurl; + $edit = "id\">$stredit"; - /** - * Calls parent::__construct with specific arguments - */ - public function __construct() { - global $CFG; - parent::__construct('managewsusersettings', get_string('managewsusersettings', 'admin'), '', ''); - $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey(); - } + // add a row to the table + $table->data[] = array($displayname, $plugin, $functions, $users, $edit); + } + $return .= $OUTPUT->table($table); - /** - * Always returns true does nothing - * - * @return true - */ - public function get_setting() { - return true; - } + // Custom services + $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main', true); + $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name'); - /** - * Does nothing always returns '' - * - * @return string Always returns '' - */ - public function write_setting($data) { - $url = $this->baseurl . '&new=' . $data; - return ''; - } + $table = new html_table(); + $table->head = array($strservice, $strdelete, $strfunctions, $strusers, $stredit); + $table->align = array('left', 'center', 'center', 'center', 'center'); + $table->size = array('30%', '20%', '20%', '20%', '10%'); + $table->width = '100%'; + $table->data = array(); - /** - * Build XHTML to display the control - * - * @param string $data Unused - * @param string $query - * @return string XHTML - */ - public function output_html($data, $query='') { - global $CFG, $OUTPUT; - $output = ""; + // iterate through auth plugins and add to the display table + foreach ($services as $service) { + $name = $service->name; + + // hide/show link + if ($service->enabled) { + $displayname = "$name"; + } else { + $displayname = "$name"; + } - //search all web service users - $users = get_users(true, '', false, null, 'firstname ASC','', '', '', 1000); + // delete link + $delete = "id\">$strdelete"; - $table = new html_table(); - $table->head = array('username', 'whitelist'); - $table->align = array('left', 'center'); - $table->data = array(); - $table->tablealign = 'center'; + $functions = "id\">$strfunctions"; - foreach ($users as $user) { - if (has_capability("moodle/site:usewebservices",get_system_context(), $user->id)) { //test if the users has has_capability('use_webservice') - $wsusersetting = ' ' - . get_string("settings") - .'' . "\n"; - $table->data[] = array($user->username, $wsusersetting); + if ($service->restrictedusers) { + $users = "id\">$strusers"; + } else { + $users = '-'; } + + $edit = "id\">$stredit"; + + // add a row to the table + $table->data[] = array($displayname, $delete, $functions, $users, $edit); } + // add new custom service option + $table->data[] = array('', '', '', '', "$stradd"); + $return .= $OUTPUT->table($table); - $output .= $OUTPUT->table($table); - $output .= "

"; - return highlight($query, $output); + $return .= '
'.get_string('tablesnosave', 'admin'); + + return highlight($query, $return); } } /** + * Special class for web service protocol administration. * - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda (skodak) */ -class admin_setting_managewsservicelist extends admin_setting { -/** @var string */ - private $baseurl; +class admin_setting_managewebserviceprotokols extends admin_setting { /** * Calls parent::__construct with specific arguments */ public function __construct() { - global $CFG; - parent::__construct('managewsservicelist', get_string('managewsservicelist', 'admin'), '', ''); - $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/webservices.php?sesskey=' . sesskey(); + parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', ''); } /** - * Always returns true does nothing + * Always returns true, does nothing * * @return true */ @@ -6263,74 +6278,127 @@ class admin_setting_managewsservicelist extends admin_setting { } /** - * Does nothing always returns '' + * Always returns true, does nothing + * + * @return true + */ + public function get_defaultsetting() { + return true; + } + + /** + * Always returns '', does not write anything * * @return string Always returns '' */ public function write_setting($data) { - $url = $this->baseurl . '&new=' . $data; + // do not write any setting return ''; } /** - * Build XHTML to display the control + * Checks if $query is one of the available webservices + * + * @param string $query The string to search for + * @return bool Returns true if found, false if not + */ + public function is_related($query) { + if (parent::is_related($query)) { + return true; + } + + $textlib = textlib_get_instance(); + $protocols = get_plugin_list('webservice'); + foreach ($protocols as $protocol=>$location) { + if (strpos($protocol, $query) !== false) { + return true; + } + $protocolstr = get_string('pluginname', 'webservice_'.$protocol); + if (strpos($textlib->strtolower($protocolstr), $query) !== false) { + return true; + } + } + return false; + } + + /** + * Builds the XHTML to display the control * * @param string $data Unused * @param string $query - * @return string XHTML + * @return string */ public function output_html($data, $query='') { - global $CFG, $OUTPUT, $DB; - $output = "
"; + global $CFG, $OUTPUT; - $output .= $OUTPUT->link('/admin/webservices.php?sesskey='.sesskey().'&create=true',get_string('createservicelabel', 'webservice')); - $output .= "
"; - $table = new html_table(); - $table->head = array(get_string('servicename','webservice'), get_string('custom','webservice'), get_string('activated','webservice'),get_string('activatedfunctions','webservice'),get_string('settings')); - $table->align = array('left', 'center', 'center','center','center'); - $table->data = array(); - $table->tablealign = 'center'; + // display strings + $stradministration = get_string('administration'); + $strsettings = get_string('settings'); + $stredit = get_string('edit'); + $strprotocol = get_string('protocol', 'webservice'); + $strenable = get_string('enable'); + $strdisable = get_string('disable'); + $strversion = get_string('version'); + $struninstall = get_string('uninstallplugin', 'admin'); - //retrieve all services - // $services = $DB->get_records('external_services',null,'custom DESC'); - $servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, s.id as serviceid, s.component as component, s.name as servicename, s.enabled as serviceenabled, f.name as functionname - FROM {external_services} s, {external_functions} f, {external_services_functions} fs - WHERE fs.externalserviceid = s.id AND fs.functionname = f.name ORDER BY s.name ASC"); + $protocols_available = get_plugin_list('webservice'); + $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols); + ksort($protocols_available); - //create a services array - $services = array(); - foreach($servicesfunctions as $servicefunction) { - if (!array_key_exists($servicefunction->servicename, $services)) { - $services[$servicefunction->servicename] = new object(); - $services[$servicefunction->servicename]->name = $servicefunction->servicename; - $services[$servicefunction->servicename]->id = $servicefunction->serviceid; - $services[$servicefunction->servicename]->enabled = $servicefunction->serviceenabled; - $services[$servicefunction->servicename]->custom = $servicefunction->custom; - $services[$servicefunction->servicename]->funcnb = 0; - $services[$servicefunction->servicename]->enabledfuncnb = 0; + foreach ($active_protocols as $key=>$protocol) { + if (empty($protocols_available[$protocol])) { + unset($active_protocols[$key]); } - $services[$servicefunction->servicename]->funcnb = $services[$servicefunction->servicename]->funcnb +1; - if ($servicefunction->functionenabled) { - $services[$servicefunction->servicename]->enabledfuncnb = $services[$servicefunction->servicename]->enabledfuncnb +1; + } + + $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main', true); + $return .= $OUTPUT->box_start('generalbox webservicesui'); + + $table = new html_table(); + $table->head = array($strprotocol, $strversion, $strenable, $struninstall, $strsettings); + $table->align = array('left', 'center', 'center', 'center', 'center'); + $table->width = '100%'; + $table->data = array(); + + // iterate through auth plugins and add to the display table + $url = "$CFG->wwwroot/$CFG->admin/webservice_protocols.php?sesskey=" . sesskey(); + foreach ($protocols_available as $protocol => $location) { + $name = get_string('pluginname', 'webservice_'.$protocol); + + $plugin = new object(); + if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/version.php')) { + include($CFG->dirroot.'/webservice/'.$protocol.'/version.php'); } + $version = isset($plugin->version) ? $plugin->version : ''; - } + // hide/show link + if (in_array($protocol, $active_protocols)) { + $hideshow = ""; + $hideshow .= "old_icon_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" />"; + $displayname = "$name"; + } else { + $hideshow = ""; + $hideshow .= "old_icon_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" />"; + $displayname = "$name"; + } - foreach($services as $service) { - //$numberoffunc = $DB->count_records('external_services_functions',array('externalserviceid' => $service->id)); - $activated = ' ' - .'' . ($service->enabled ? 'activated' : 'not activated') . ''.'' ; - $custom = ($service->custom ? get_string('yes') : ''); - $settings = $OUTPUT->link('/admin/webservices.php?serviceid='.$service->id.'&sesskey='.sesskey().'&settings=true',get_string('settings')); - $table->data[] = array(get_string($service->name,'webservice'), $custom, $activated, $service->enabledfuncnb."/".$service->funcnb, $settings); - } + // delete link + $uninstall = "$struninstall"; - $output .= $OUTPUT->table($table); + // settings link + if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) { + $settings = "$strsettings"; + } else { + $settings = ''; + } - $output .= '
'; + // add a row to the table + $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings); + } + $return .= $OUTPUT->table($table); + $return .= get_string('configwebserviceplugins', 'webservice').'
'.get_string('tablenosave', 'admin'); + $return .= $OUTPUT->box_end(); - return highlight($query, $output); + return highlight($query, $return); } } diff --git a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php index ba91a2c3f8..d338169049 100644 --- a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php +++ b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php @@ -941,14 +941,6 @@ get_string('allowbeforeblock', 'admin', NULL); get_string('allowbeforeblockdesc', 'admin', NULL); get_string('allowediplist', 'admin', NULL); get_string('blockediplist', 'admin', NULL); -get_string('webservices', 'admin', NULL); -get_string('webserviceprotocols', 'admin', NULL); -get_string('managewsprotocols', 'admin', NULL); -get_string('managews', 'admin', NULL); -get_string('webservicesystemsettings', 'admin', NULL); -get_string('ipwhitelist', 'admin', NULL); -get_string('webserviceusersettings', 'admin', NULL); -get_string('managewsusersettings', 'admin', NULL); get_string('sitepolicies', 'admin', NULL); get_string('protectusernames', 'admin', NULL); get_string('configprotectusernames', 'admin', NULL); diff --git a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php index 76261bda03..543029fee5 100644 --- a/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php +++ b/lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php @@ -941,14 +941,6 @@ old_get_string('allowbeforeblock', 'admin', NULL); old_get_string('allowbeforeblockdesc', 'admin', NULL); old_get_string('allowediplist', 'admin', NULL); old_get_string('blockediplist', 'admin', NULL); -old_get_string('webservices', 'admin', NULL); -old_get_string('webserviceprotocols', 'admin', NULL); -old_get_string('managewsprotocols', 'admin', NULL); -old_get_string('managews', 'admin', NULL); -old_get_string('webservicesystemsettings', 'admin', NULL); -old_get_string('ipwhitelist', 'admin', NULL); -old_get_string('webserviceusersettings', 'admin', NULL); -old_get_string('managewsusersettings', 'admin', NULL); old_get_string('sitepolicies', 'admin', NULL); old_get_string('protectusernames', 'admin', NULL); old_get_string('configprotectusernames', 'admin', NULL); diff --git a/webservice/lib.php b/webservice/lib.php index 4e1c22359f..b37a48c481 100644 --- a/webservice/lib.php +++ b/webservice/lib.php @@ -1,394 +1,393 @@ . + /** - * Moodle - Modular Object-Oriented Dynamic Learning Environment - * http://moodle.com - * - * LICENSE - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: + * Web services utility functions and classes * - * http://www.gnu.org/copyleft/gpl.html - * - * @category Moodle * @package webservice * @copyright 2009 Moodle Pty Ltd (http://moodle.com) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once(dirname(dirname(__FILE__)) . '/lib/formslib.php'); - -/** - * Returns detailed information about external function - * @param string $functionname name of external function - * @return aray - */ -function ws_get_function_info($functionname) { - global $CFG, $DB; +require_once($CFG->libdir.'/externallib.php'); - $function = $DB->get_record('external_functions', array('name'=>$functionname), '*', MUST_EXIST); +function webservice_protocol_is_enabled($protocol) { + global $CFG; - $defpath = get_component_directory($function->component); - if (!file_exists("$defpath/db/services.php")) { - //TODO: maybe better throw invalid parameter exception - return null; + if (empty($CFG->enablewebservices)) { + return false; } - $functions = array(); - include("$defpath/db/services.php"); + $active = explode(',', $CFG->webserviceprotocols); - if (empty($functions[$functionname])) { - return null; - } - - $desc = $functions[$functionname]; - if (empty($desc['classpath'])) { - $desc['classpath'] = "$defpath/externallib.php"; - } else { - $desc['classpath'] = "$CFG->dirroot/".$desc['classpath']; - } - $desc['component'] = $function->component; + return(in_array($protocol, $active)); +} - return $desc; +/** + * Mandatory web service server interface + * @author Petr Skoda (skodak) + */ +interface webservice_server { + /** + * Process request from client. + * @param bool $simple use simple authentication + * @return void + */ + public function run($simple); } /** - * web service library + * Special abstraction of our srvices that allows + * interaction with stock Zend ws servers. + * @author skodak */ -final class webservice_lib { +abstract class webservice_zend_server implements webservice_server { + //TODO: implement base class for all ws servers in zend framework + // the idea is to create one huge class on the fly, this class contains all + // methods user is allowed to access and contains all needed PHPDoc metadata. +} + /** - * Return list of all web service protocol into the webservice folder - * @global $CFG - * @return + * Web Service server base class, this class handles both + * simple and token authentication. + * @author Petr Skoda (skodak) */ - public static function get_list_protocols() { - global $CFG; - $protocols = array(); - $directorypath = $CFG->dirroot . "/webservice"; - if( $dh = opendir($directorypath)) { - while( false !== ($file = readdir($dh))) { - if( $file == '.' || $file == '..' || $file == 'CVS') { // Skip '.' and '..' - continue; - } - $path = $directorypath . '/' . $file; - ///browse the subfolder - if( is_dir($path) ) { - if ($file != 'db') { //we don't want to browse the 'db' subfolder of webservice folder - require_once($path."/lib.php"); - $classname = $file."_server"; - $protocols[] = new $classname; - } - } - ///retrieve api.php file - else { - continue; - } - } - closedir($dh); - } - return $protocols; - } +abstract class webservice_base_server implements webservice_server { + + /** @property string $wsname name of the web server plugin */ + protected $wsname = null; + + /** @property bool $simple true if simple auth used */ + protected $simple; + + /** @property string $username name of local user */ + protected $username = null; + + /** @property string $password password of the local user */ + protected $password = null; + + /** @property string $token authentication token*/ + protected $token = null; + + /** @property array $parameters the function parameters - the real values submitted in the request */ + protected $parameters = null; + + /** @property string $functionname the name of the function that is executed */ + protected $functionname = null; + + /** @property object $function full function description */ + protected $function = null; + + /** @property mixed $returns function return value */ + protected $returns = null; /** - * Temporary Authentication method to be modified/removed - * @global $DB - * @param $token - * @return + * Contructor */ - public static function mock_check_token($token) { - //fake test - if ($token == 456) { - ///retrieve the user - global $DB; - $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1)); - - if (empty($user)) { - return false; - } - - return $user; - } else { - return false; - } + public function __construct() { } /** - * Retrieve all external.php from Moodle (except the one of the exception list) - * @param $ - * @param $directorypath - * @return boolean true if n + * This method parses the request input, it needs to get: + * 1/ user authentication - username+password or token + * 2/ function name + * 3/ function parameters + * + * @return void */ - public static function setListApiFiles( &$files, $directorypath ) { - global $CFG; - - if(is_dir($directorypath)) { //check that we are browsing a folder not a file - - if( $dh = opendir($directorypath)) { - while( false !== ($file = readdir($dh))) { - - if( $file == '.' || $file == '..') { // Skip '.' and '..' - continue; - } - $path = $directorypath . '/' . $file; - ///browse the subfolder - if( is_dir($path) ) { - webservice_lib::setListApiFiles($files, $path); - } - ///retrieve api.php file - else if ($file == "external.php") { - $files[] = $path; - } - } - closedir($dh); + abstract protected function parse_request(); - } - } - - } + /** + * Send the result of function call to the WS client. + * @return void + */ + abstract protected function send_response(); /** - * Check if the Moodle site has the web service protocol enable - * @global object $CFG - * @param string $protocol + * Send the error information to the WS client. + * @param exception $ex + * @return void */ - function display_webservices_availability($protocol) { - global $CFG; + abstract protected function send_error($ex=null); - $available = true; - echo get_string('webservicesenable','webservice').": "; - if (empty($CFG->enablewebservices)) { - echo "".get_string('fail','webservice').""; - $available = false; - } else { - echo "".get_string('ok','webservice').""; - } - echo "
"; - - foreach(webservice_lib::get_list_protocols() as $wsprotocol) { - if (strtolower($wsprotocol->get_protocolid()) == strtolower($protocol)) { - echo get_string('protocolenable','webservice',array($wsprotocol->get_protocolid())).": "; - if ( get_config($wsprotocol-> get_protocolid(), "enable")) { - echo "".get_string('ok','webservice').""; - } else { - echo "".get_string('fail','webservice').""; - $available = false; - } - echo "
"; - continue; - } - } + /** + * Process request from client. + * @param bool $simple use simple authentication + * @return void + */ + public function run($simple) { + $this->simple = $simple; - //check debugging - if ($CFG->debugdisplay) { - echo "".get_string('debugdisplayon','webservice').""; - $available = false; - } + // we will probably need a lot of memory in some functions + @raise_memory_limit('128M'); - return $available; - } + // set some longer timeout, this script is not sending any output, + // this means we need to manually extend the timeout operations + // that need longer time to finish + external_api::set_timeout(); -} + // set up exception handler first, we want to sent them back in correct format that + // the other system understands + // we do not need to call the original default handler because this ws handler does everything + set_exception_handler(array($this, 'exception_handler')); -/** - * Web Service server base class - */ -abstract class webservice_server { + // init all properties from the request data + $this->parse_request(); -/** - * Web Service Protocol name (eg. SOAP, REST, XML-RPC,...) - * @var String - */ - private $protocolname; + // authenticate user, this has to be done after the request parsing + // this also sets up $USER and $SESSION + $this->authenticate_user(); - /** - * Web Service Protocol id (eg. soap, rest, xmlrpc...) - * @var String - */ - private $protocolid; + // find all needed function info and make sure user may actually execute the function + $this->load_function_info(); - public function __construct() { - } + // finally, execute the function - any errors are catched by the default exception handler + $this->execute(); - abstract public function run(); + // send the results back in correct format + $this->send_response(); - public function get_protocolname() { - return $this->protocolname; - } + // session cleanup + $this->session_cleanup(); - public function get_protocolid() { - return $this->protocolid; + die; } - public function set_protocolname($protocolname) { - $this->protocolname = $protocolname; - } + /** + * Specialised exception handler, we can not use the standard one because + * it can not just print html to output. + * + * @param exception $ex + * @return void does not return + */ + public function exception_handler($ex) { + global $CFG, $DB, $SCRIPT; + + // detect active db transactions, rollback and log as error + if ($DB->is_transaction_started()) { + error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT); + try { + // note: transaction blocks should never change current $_SESSION + $DB->rollback_sql(); + } catch (Exception $ignored) { + } + } - public function set_protocolid($protocolid) { - $this->protocolid = $protocolid; - } + // now let the plugin send the exception to client + $this->send_error($ex); - public function get_enable() { - return get_config($this->get_protocolid(), "enable"); - } + // some hacks might need a cleanup hook + $this->session_cleanup($ex); - public function set_enable($enable) { - set_config("enable", $enable, $this->get_protocolid()); + // not much else we can do now, add some logging later + exit(1); } /** - * Names of the server settings - * @return array + * Future hook needed for emulated sessions. + * @param exception $exception null means normal termination, $exception received when WS call failed + * @return void */ - public static function get_setting_names() { - return array(); + protected function session_cleanup($exception=null) { + if ($this->simple) { + // nothing needs to be done, there is no persistent session + } else { + // close emulated session if used + } } - public function settings_form(&$mform) { - } + /** + * Authenticate user using username+password or token. + * This function sets up $USER global. + * It is safe to use has_capability() after this. + * This method also verifies user is allowed to use this + * server. + * @return void + */ + protected function authenticate_user() { + global $CFG, $DB; -} + if (!NO_MOODLE_COOKIES) { + throw new coding_exception('Cookies must be disabled in WS servers!'); + } + + if ($this->simple) { + if (!is_enabled_auth('webservice')) { + die('WS auth not enabled'); + } + + if (!$auth = get_auth_plugin('webservice')) { + die('WS auth missing'); + } + + if (!$this->username) { + throw new invalid_parameter_exception('Missing username'); + } + + if (!$this->password) { + throw new invalid_parameter_exception('Missing password'); + } + + if (!$auth->user_login_webservice($this->username, $this->password)) { + throw new invalid_parameter_exception('Wrong username or password'); + } + + $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST); + + // now fake user login, the session is completely empty too + session_set_user($user); + + if (!has_capability("webservice/$this->wsname:use", get_context_instance(CONTEXT_SYSTEM))) { + throw new invalid_parameter_exception('Access to web service not allowed'); + } -/** - * Temporary authentication class to be removed/modified - */ -class ws_authentication { -/** - * - * @param object|struct $params - * @return integer - */ - function get_token($params) { - $params->username = clean_param($params->username, PARAM_ALPHANUM); - $params->password = clean_param($params->password, PARAM_ALPHANUM); - if ($params->username == 'wsuser' && $params->password == 'wspassword') { - return '456'; } else { - throw new moodle_exception('wrongusernamepassword'); + //TODO: not implemented yet + die('token login not implemented yet'); + + // note we had to wait until here because we did not know the security context earlier + if (!has_capability("webservice/$this->wsname:use", $context)) { + throw new invalid_parameter_exception('Access to web service not allowed'); + } } } -} - -/** - * Form for web service user settings (administration) - */ -final class wsuser_form extends moodleform { - protected $username; /** - * Definition of the moodleform + * Fetches the function description from database, + * verifies user is allowed to use this function and + * loads all paremeters and return descriptions. + * @return void */ - public function definition() { - global $DB; - $this->username = $this->_customdata['username']; - $mform =& $this->_form; + protected function load_function_info() { + global $DB, $USER, $CFG; - $mform->addElement('hidden', 'username', $this->username); - $mform->setType('username', PARAM_RAW); - $param = new stdClass(); - $param->username = $this->username; - $wsuser = $DB->get_record("user", array("username" => $this->username)); + if (empty($this->functionname)) { + throw new invalid_parameter_exception('Missing function name'); + } - $mform->addElement('text', 'ipwhitelist', get_string('ipwhitelist', 'admin'), array('value'=>get_user_preferences("ipwhitelist", "", $wsuser->id),'size' => '40')); - $mform->addElement('static', null, '', get_string('ipwhitelistdesc','admin', $param)); + // function must exist + $function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST); + + + // now let's verify access control + if ($this->simple) { + // now make sure the function is listed in at least one service user is allowed to use + // allow access only if: + // 1/ entry in the external_services_users table if required + // 2/ validuntil not reached + // 3/ has capability if specified in service desc + // 4/ iprestriction + + $sql = "SELECT s.*, NULL AS iprestriction + FROM {external_services} s + JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0 AND sf.functionname = :name1) + WHERE s.enabled = 1 + + UNION + + SELECT s.*, su.iprestriction + FROM {external_services} s + JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1 AND sf.functionname = :name2) + JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid) + WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now"; + + $rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name1'=>$function->name, 'name2'=>$function->name, 'now'=>time())); + // now make sure user may access at least one service + $syscontext = get_context_instance(CONTEXT_SYSTEM); + $remoteaddr = getremoteaddr(); + $allowed = false; + foreach ($rs as $service) { + if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) { + continue; // cap required, sorry + } + if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) { + continue; // wrong request source ip, sorry + } + $allowed = true; + break; // one service is enough, no need to continue + } + $rs->close(); + if (!$allowed) { + throw new invalid_parameter_exception('Access to external function not allowed'); + } + // now we finally know the user may execute this function, + // the last step is to set context restriction - in this simple case + // we use system context because each external system has different user account + // and we can manage everything through normal permissions. + external_api::set_context_restriction($syscontext); - $this->add_action_buttons(true, get_string('savechanges','admin')); - } -} + } else { + //TODO: implement token security checks + die('not implemented yet'); + } -/** - * Form for web service server settings (administration) - */ -final class wssettings_form extends moodleform { - protected $settings; + // get the params and return descriptions of the function + unset($function->id); // we want to prevent any accidental db updates ;-) - /** - * Definition of the moodleform - */ - public function definition() { - global $DB,$CFG; - $settings = $this->_customdata['settings']; - $mform =& $this->_form; - - $mform->addElement('hidden', 'settings', $settings); - $mform->setType('settings', PARAM_RAW); - $param = new stdClass(); - - require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php'); - $servername = $settings.'_server'; - $server = new $servername(); - $server->settings_form($mform); - - // set the data if we have some. - $data = array(); - $option_names = $server->get_setting_names(); - foreach ($option_names as $config) { - $data[$config] = get_config($settings, $config); + $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath; + if (!file_exists($function->classpath)) { + throw new coding_exception('Can not find file with external function implementation'); } - $this->set_data($data); + require_once($function->classpath); + $function->parameters_method = $function->methodname.'_parameters'; + $function->returns_method = $function->methodname.'_returns'; - $this->add_action_buttons(true, get_string('savechanges','admin')); - } -} - -/** - * Form for web service server settings (administration) - */ -final class wsservicesettings_form extends moodleform { - protected $settings; + // make sure the implementaion class is ok + if (!method_exists($function->classname, $function->methodname)) { + throw new coding_exception('Missing implementation method'); + } + if (!method_exists($function->classname, $function->parameters_method)) { + throw new coding_exception('Missing parameters description'); + } + if (!method_exists($function->classname, $function->returns_method)) { + throw new coding_exception('Missing returned values description'); + } - /** - * Definition of the moodleform - */ - public function definition() { - global $DB,$CFG; - $serviceid = $this->_customdata['serviceid']; - $mform =& $this->_form; - - $mform->addElement('hidden', 'serviceid', $serviceid); - $mform->setType('serviceid', PARAM_INT); - $param = new stdClass(); - - // require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php'); - // $servername = $settings.'_server'; - // $server = new $servername(); - // $server->settings_form($mform); - - // set the data if we have some. - // $data = array(); - // $option_names = $server->get_setting_names(); - // foreach ($option_names as $config) { - // $data[$config] = get_config($settings, $config); - // } - // $this->set_data($data); - $service = $DB->get_record('external_services',array('id' => $serviceid)); - - $mform->addElement('text', 'servicename', get_string('servicename', 'webservice')); - $mform->setDefault('servicename',get_string($service->name, 'webservice')); - if (!empty($serviceid)) { - $mform->disabledIf('servicename', 'serviceid', 'eq', $serviceid); + // fetch the parameters description + $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method)); + if (!($function->parameters_desc instanceof external_function_parameters)) { + throw new coding_exception('Invalid parameters description'); } - if (empty($serviceid)) { - //display list of functions to select + // fetch the return values description + $function->returns_desc = call_user_func(array($function->classname, $function->returns_method)); + // null means void result or result is ignored + if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) { + throw new coding_exception('Invalid return description'); } - //display list of functions associated to the service - - + // we have all we need now + $this->function = $function; + } + + /** + * Execute previously loaded function using parameters parsed from the request data. + * @return void + */ + protected function execute() { + // validate params, this also sorts the params properly, we need the correct order in the next part + $params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters); - $this->add_action_buttons(true, get_string('savechanges','admin')); + // execute - yay! + $this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params)); } } -?> diff --git a/webservice/rest/db/access.php b/webservice/rest/db/access.php new file mode 100644 index 0000000000..e5de8842a4 --- /dev/null +++ b/webservice/rest/db/access.php @@ -0,0 +1,12 @@ + array( + 'captype' => 'read', // in fact this may be considered read and write at the same time + 'contextlevel' => CONTEXT_COURSE, // the context level should be probably CONTEXT_MODULE + 'legacy' => array( + ), + ), + +); diff --git a/webservice/rest/lib.php b/webservice/rest/lib.php deleted file mode 100644 index 324ce2f457..0000000000 --- a/webservice/rest/lib.php +++ /dev/null @@ -1,59 +0,0 @@ -dirroot.'/webservice/lib.php'); - -/* - * Rest server class - */ -final class rest_server extends webservice_server { - - public function __construct() { - - $this->set_protocolname("Rest"); - $this->set_protocolid("rest"); - } - - /** - * Run REST server - */ - public function run() { - $enable = $this->get_enable(); - if (empty($enable)) { - die; - } - - require_once('locallib.php'); - //retrieve path and function name from the URL - $rest_arguments = get_file_argument('server.php'); - header ("Content-type: text/xml"); - echo call_moodle_function($rest_arguments); - } - -} - - - -?> diff --git a/webservice/rest/locallib.php b/webservice/rest/locallib.php index 1ed14f7b0b..b1af6b7f5f 100644 --- a/webservice/rest/locallib.php +++ b/webservice/rest/locallib.php @@ -1,233 +1,155 @@ . + /** - * Moodle - Modular Object-Oriented Dynamic Learning Environment - * http://moodle.com - * - * LICENSE - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * http://www.gnu.org/copyleft/gpl.html + * REST web service implementation classes and methods. * - * @category Moodle * @package webservice - * @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +require_once("$CFG->dirroot/webservice/lib.php"); /** - * Rest library - * @author Jerome Mouneyrac, Ferran Recio, David Castro Garcia + * REST service server implementation. + * @author Petr Skoda (skodak) */ - -/** - * - * @author Jerome Mouneyrac - * @global object $CFG - * @param string $rest_arguments example: /mod/forum/get_discussion - * @return string xml object - */ -function call_moodle_function ($rest_arguments) { - global $CFG, $USER; - - ///REST params conversion - $functionname = substr($rest_arguments,strrpos($rest_arguments,"/")+1); //retrieve the function name (it's located after the last '/') in $rest_arguments - //$rest_argument - $apipath = substr($rest_arguments,0, strlen($rest_arguments) - strlen($functionname)); //api path is the other part of $rest_arguments - - $classname = str_replace('/', '_', $apipath); // convert '/' into '_' (e.g. /mod/forum/ => _mod_forum_) - $classname = substr($classname,1, strlen($classname) - 1); //remove first _ (e.g. _mod_forum => mod_forum) - $classname .= 'external'; - - /// Authentication process - /// TODO: this use a fake token => need to implement token generation - $token = optional_param('token',null,PARAM_ALPHANUM); - if (empty($token)) { - if ($functionname != 'get_token') { - throw new moodle_exception('identifyfirst'); - } else { - /// TODO: authentication + token generation need to be implemented - if (optional_param('username',null,PARAM_ALPHANUM) == 'wsuser' && optional_param('password',null,PARAM_ALPHANUM) == 'wspassword') { - return '456'; - } else { - throw new moodle_exception('wrongusernamepassword'); - } - } - } else { - /// TODO: following function will need to be modified - $user = mock_check_token($token); - if (empty($user)) { - throw new moodle_exception('wrongidentification'); - } - else { - /// TODO: probably change this - $USER = $user; - } - } - - /// load the external class - $file = $CFG->dirroot.$apipath.'external.php'; - $description = webservice_lib::generate_webservice_description($file, $classname); - - /// This following line is only REST protocol - $params = retrieve_params ($description[$functionname]); //retrieve the REST params - - /// Generic part to any protocols - if ($params === false) { - //return an error message, the REST params doesn't match with the web service description +class webservice_rest_server extends webservice_base_server { + /** + * Contructor + */ + public function __construct() { + parent::__construct(); + $this->wsname = 'rest'; } - try { - $res = call_user_func_array ( $classname.'::'.$functionname, array($params)); - } catch (moodle_exception $e) { - return "".$e->getMessage().""; - } + /** + * This method parses the $_REQUEST superglobal and looks for + * the following information: + * 1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters) + * 2/ function name (wsfunction parameter) + * 3/ function parameters (all other parameters except those above) + * + * @return void + */ + protected function parse_request() { + if ($this->simple) { + $this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null; + unset($_REQUEST['wsusername']); - ///Transform result into xml in order to send the REST response - $key = key($description[$functionname]['return']); + $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null; + unset($_REQUEST['wspassword']); - if (strpos($key,":")!==false) { - $key = substr($key, strpos($key,":")+1); - } else { - $key = 'return'; - } - $return = mdl_conn_rest_object_to_xml ($res,$key); + $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null; + unset($_REQUEST['wsfunction']); - return "$return"; -} + $this->parameters = $_REQUEST; -/** - * TODO: remove/rewrite this function - * Mock function waiting for token system implementation - * @param int $token - * @return object|boolean - */ -function mock_check_token($token) { - //fake test - if ($token == 456) { - ///retrieve the user - global $DB; - $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1)); - - if (empty($user)) { - return false; + } else { + //TODO + die('not implemented yet'); } - - return $user; - } else { - return false; } -} - /** - * Convert into a Moodle type - * @param integer $param - * @return string + /** + * Send the result of function call to the WS client + * formatted as XML document. + * @return void */ -function convert_paramtype($param) { - switch ($param) { - case "integer": - return PARAM_NUMBER; - break; - case "integer": - return PARAM_INT; - break; - case "boolean": - return PARAM_BOOL; - break; - case "string": - return PARAM_ALPHANUM; - break; - case "object": - return PARAM_RAW; - break; - default: - return PARAM_RAW; - break; + protected function send_response() { + $this->send_headers(); + $xml = ''."\n"; + $xml .= ''."\n"; + $xml .= self::xmlize_result($this->returns, $this->function->returns_desc); + $xml .= ''."\n"; + echo $xml; } -} -/** - * - * @author Jerome Mouneyrac - * @param array $description - * @return array - */ -function retrieve_params ($description) { - $params = array(); - //retrieve REST param matching the description (warning: PHP assign the first instanciation as the first position in the table) - foreach ($description['params'] as $paramname => $paramtype) { - $paramtype = convert_paramtype($paramtype); - $value = optional_param($paramname,null,$paramtype); - if (!empty($value)) { - $params[$paramname] = $value; - } - } - //retrieve REST optional params - if (!empty($description['optional'])) { - foreach ($description['optional'] as $paramname => $paramtype) { - $paramtype = convert_paramtype($paramtype); - $value = optional_param($paramname,null,$paramtype); - if (!empty($value)) { - $params[$paramname] = $value; - } + /** + * Send the error information to the WS client + * formatted as XML document. + * @param exception $ex + * @return void + */ + protected function send_error($ex=null) { + $this->send_headers(); + $xml = ''."\n"; + $xml .= ''."\n"; + $xml .= ''.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').''."\n"; + if (debugging() and isset($ex->debuginfo)) { + $xml .= ''.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').''."\n"; } + $xml .= ''."\n"; + echo $xml; } - return $params; -} -/** - * auxiliar function for simplexml_object_to_xml - * @author Ferran Recio, David Castro Garcia - * @param $obj - * @param $tag - * @param $atts assoc array (key => value) - * @return string - */ -function mdl_conn_rest_object_to_xml ($obj, $tag,$atts=false) { - $res = ''; - $tag_atts = ''; - if ($atts) { - $main_atts = array(); - foreach ($atts as $att=>$val) { - $main_atts[] = "$att=\"".urlencode($val)."\""; - } - if (count($main_atts)) $tag_atts = ' '.implode(' ',$main_atts); + /** + * Internal implementation - sending of page headers. + * @return void + */ + protected function send_headers() { + header('Content-Type: application/xml'); + header('Content-Disposition: inline; filename="response.xml"'); + header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: no-cache'); + header('Accept-Ranges: none'); } - //if is an object - if (is_object($obj)) { - $parts = get_object_vars($obj); - foreach ($parts as $tag2 => $val) { - $res.= mdl_conn_rest_object_to_xml ($val, $tag2); - } - return "<$tag$tag_atts>\n$res\n"; - } - //if it's an array all elements will be inside te same tag but with a new atribute key - if (is_array($obj)){ - if (!$atts) $atts = array(); - //we came from another array - if (isset($atts['keys'])) $atts = array(); - foreach ($obj as $key=>$val) { - $array_atts = $atts; - $array_atts['key'] = $key; - $res.= mdl_conn_rest_object_to_xml ($val, $tag,$array_atts); + /** + * Internal implementation - recursive function producing XML markup. + * @param mixed $returns + * @param $desc + * @return unknown_type + */ + protected static function xmlize_result($returns, $desc) { + if ($desc === null) { + return ''; + + } else if ($desc instanceof external_value) { + //TODO: there should be some way to indicate the real NULL value + return ''.htmlentities($returns, ENT_COMPAT, 'UTF-8').''."\n"; + + } else if ($desc instanceof external_multiple_structure) { + $mult = ''."\n"; + foreach ($returns as $val) { + $mult .= self::xmlize_result($val, $desc->content); + } + $mult .= ''."\n"; + return $mult; + + } else if ($desc instanceof external_single_structure) { + $single = ''."\n"; + foreach ($desc->keys as $key=>$subdesc) { + if (!array_key_exists($key, $returns)) { + if ($subdesc->rewquired) { + $single .= 'Missing required key'; + continue; + } else { + //optional field + continue; + } + } + $single .= ''.self::xmlize_result($returns[$key], $subdesc).''."\n"; + } + $single .= ''."\n"; + return $single; } - return $res; } - //any other type, just encapsule it - $obj = htmlentities($obj); - return "<$tag$tag_atts>$obj\n"; - } -?> \ No newline at end of file diff --git a/webservice/rest/server.php b/webservice/rest/server.php index 585159662d..0e9def198d 100644 --- a/webservice/rest/server.php +++ b/webservice/rest/server.php @@ -1,47 +1,38 @@ . + /** - * Moodle - Modular Object-Oriented Dynamic Learning Environment - * http://moodle.com - * - * LICENSE - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: + * REST web service entry point. The authentication is done via tokens. * - * http://www.gnu.org/copyleft/gpl.html - * - * @category Moodle * @package webservice - * @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -/** - * REST Moodle server. - * - * NOTE: for this first implementation, REST requires implicit url encoded params. - * It uses function get_file_argument to get them. - * - * @author Jerome Mouneyrac - * @author Ferran Recio - * @author David Castro Garcia - */ +define('NO_MOODLE_COOKIES', true); -require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); -require_once('lib.php'); +require('../../config.php'); +require_once("$CFG->dirroot/webservice/rest/locallib.php"); -if (empty($CFG->enablewebservices)) { +if (!webservice_protocol_is_enabled('rest')) { die; } -$server = new rest_server(); -$server->run(); +$server = new webservice_rest_server(); +$server->run(false); +die; -?> \ No newline at end of file diff --git a/webservice/rest/simpleserver.php b/webservice/rest/simpleserver.php index cb435233a5..73a5e08e0f 100644 --- a/webservice/rest/simpleserver.php +++ b/webservice/rest/simpleserver.php @@ -16,575 +16,24 @@ // along with Moodle. If not, see . /** - * Sample simple REST web service server. + * REST web service entry point. The authentication is done via tokens. * - * This WS entry point accepts only users from the 'auth/webservice' - * plugin. Enabling of webservice for each user is explicitly allowed - * via records in the external_services_users table. - * - * @package moodlecore - * @subpackage file - * @copyright 2009 Petr Skoda (http://skodak.org) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - -/* - * NOTE: this is a proposal for a new WS server OOP framework - * - * I did not understand much how the WS protocols are supposed - * to work, I just tried to create some clean abstraction that - * should allow easy implementation of any protocol server. - * The REST was chosen only because it seems to be the easiest - * one with no real standardisation ;-) - * - * == How to test this == - * 1/ create new service that includes function 'moodle_group_get_groups' by adding new local plugin, - * this adds new record into external_services table - * 2/ create new user and select 'webservice' as auth plugin and enable webservice auth plugin - * 3/ add $CFG->enablesimplewebservices=true; to your config.php - * 4/ manually enable the rest service: set_config('enable', 1, 'rest'); - * 5/ manually insert record into external_services_users - your new service + your new user - * 6/ create course with some groups - * 7/ execute the REST query: http://nahore.skodak.local/moodle20/webservice/rest/simpleserver.php?wsusername=a&wspassword=p&wsfunction=moodle_group_get_groups&groupids[0]=1&groupids[1]=3 - * 8/ sit tight and watch in awe the super hyper mega cool xml response of fully working REST WS server :-) - * - * skodak + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - define('NO_MOODLE_COOKIES', true); require('../../config.php'); -require_once("$CFG->libdir/externallib.php"); -//require_once("$CFG->dirroot/webservice/rest/lib.php"); TODO: uncomment when rewrite finished -//require_once("$CFG->dirroot/webservice/rest/locallib.php"); TODO: uncomment when rewrite finished - - - -//======== NOTE: this should be defined in /webservice/rest/locallib.php ============================= - -/** - * REST service server class. - * - * @author Petr Skoda (skodak) - */ -class webservice_rest_server extends webservice_base_server { - /** - * Contructor - * @param bool $simple use simple authentication - */ - public function __construct($simple) { - parent::__construct($simple); - $this->wsname = 'rest'; - } - - /** - * This method parses the $_REQUEST superglobal and looks for - * the following information: - * 1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters) - * 2/ function name (wsfunction parameter) - * 3/ function parameters (all other parameters except those above) - * - * @return void - */ - protected function parse_request() { - if ($this->simple) { - $this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null; - unset($_REQUEST['wsusername']); - - $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null; - unset($_REQUEST['wspassword']); - - $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null; - unset($_REQUEST['wsfunction']); - - $this->parameters = $_REQUEST; - - } else { - //TODO - die('not implemented yet'); - } - } - - /** - * Send the result of function call to the WS client - * formatted as XML document. - * @return void - */ - protected function send_response() { - $this->send_headers(); - $xml = ''."\n"; - $xml .= ''."\n"; - $xml .= self::xmlize_result($this->returns, $this->function->returns_desc); - $xml .= ''."\n"; - echo $xml; - } - - /** - * Send the error information to the WS client - * formatted as XML document. - * @param exception $ex - * @return void - */ - protected function send_error($ex=null) { - $this->send_headers(); - $xml = ''."\n"; - $xml .= ''."\n"; - $xml .= ''.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').''."\n"; - if (debugging() and isset($ex->debuginfo)) { - $xml .= ''.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').''."\n"; - } - $xml .= ''."\n"; - echo $xml; - } - - /** - * Internal implementation - sending of page headers. - * @return void - */ - protected function send_headers() { - header('Content-Type: application/xml'); - header('Content-Disposition: inline; filename="response.xml"'); - header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); - header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - header('Pragma: no-cache'); - header('Accept-Ranges: none'); - } - - /** - * Internal implementation - recursive function producing XML markup. - * @param mixed $returns - * @param $desc - * @return unknown_type - */ - protected static function xmlize_result($returns, $desc) { - if ($desc === null) { - return ''; - - } else if ($desc instanceof external_value) { - //TODO: there should be some way to indicate the real NULL value - return ''.htmlentities($returns, ENT_COMPAT, 'UTF-8').''."\n"; - - } else if ($desc instanceof external_multiple_structure) { - $mult = ''."\n"; - foreach ($returns as $val) { - $mult .= self::xmlize_result($val, $desc->content); - } - $mult .= ''."\n"; - return $mult; - - } else if ($desc instanceof external_single_structure) { - $single = ''."\n"; - foreach ($desc->keys as $key=>$subdesc) { - if (!array_key_exists($key, $returns)) { - if ($subdesc->rewquired) { - $single .= 'Missing key'; - continue; - } else { - //optional field - continue; - } - } - $single .= ''.self::xmlize_result($returns[$key], $subdesc).''."\n"; - } - $single .= ''."\n"; - return $single; - } - } -} - - - - -//======== NOTE: this should be defined in /webservice/lib.php ============================= - -/** - * Web Service server base class, this class handles both - * simple and token authentication. - */ -abstract class webservice_base_server { - - /** @property string $wsname name of the web server plugin */ - protected $wsname = null; - - /** @property bool $simple true if simple auth used */ - protected $simple; - - /** @property string $username name of local user */ - protected $username = null; - - /** @property string $password password of the local user */ - protected $password = null; - - /** @property string $token authentication token*/ - protected $token = null; - - /** @property array $parameters the function parameters - the real values submitted in the request */ - protected $parameters = null; - - /** @property string $functionname the name of the function that is executed */ - protected $functionname = null; - - /** @property object $function full function description */ - protected $function = null; - - /** @property mixed $returns function return value */ - protected $returns = null; - - /** - * Contructor - * @param bool $simple use simple authentication - */ - public function __construct($simple) { - $this->simple = $simple; - } - - /** - * This method parses the request input, it needs to get: - * 1/ user authentication - username+password or token - * 2/ function name - * 3/ function parameters - * - * @return void - */ - abstract protected function parse_request(); - - /** - * Send the result of function call to the WS client. - * @return void - */ - abstract protected function send_response(); - - /** - * Send the error information to the WS client. - * @param exception $ex - * @return void - */ - abstract protected function send_error($ex=null); - - - public function run() { - // first make sure this service is enabled - if (!$this->is_enabled()) { - die(); - } - - // we will probably need a lot of memory in some functions - @raise_memory_limit('128M'); - - // set some longer timeout, this script is not sending any output, - // this means we need to manually extend the timeout operations - // that need longer time to finish - external_api::set_timeout(); - - // set up exception handler first, we want to sent them back in correct format that - // the other system understands - // we do not need to call the original default handler because this ws handler does everything - set_exception_handler(array($this, 'exception_handler')); - - // init all properties from the request data - $this->parse_request(); - - // authenticate user, this has to be done after the request parsing - // this also sets up $USER and $SESSION - $this->authenticate_user(); - - // find all needed function info and make sure user may actually execute the function - $this->load_function_info(); - - // finally, execute the function - any errors are catched by the default exception handler - $this->execute(); - - // send the results back in correct format - $this->send_response(); - - // session cleanup - $this->session_cleanup(); - - die; - } - - /** - * Specialised exception handler, we can not use the standard one because - * it can not just print html to output. - * - * @param exception $ex - * @return void does not return - */ - public function exception_handler($ex) { - global $CFG, $DB, $SCRIPT; - - // detect active db transactions, rollback and log as error - if ($DB->is_transaction_started()) { - error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT); - try { - // note: transaction blocks should never change current $_SESSION - $DB->rollback_sql(); - } catch (Exception $ignored) { - } - } - - // now let the plugin send the exception to client - $this->send_error($ex); - - // some hacks might need a cleanup hook - $this->session_cleanup($ex); - - // not much else we can do now, add some logging later - exit(1); - } - - /** - * Future hook needed for emulated sessions. - * @param exception $exception null means normal termination, $exception received when WS call failed - * @return void - */ - protected function session_cleanup($exception=null) { - if ($this->simple) { - // nothing needs to be done, there is no persistent session - } else { - // close emulated session if used - } - } - - /** - * Authenticate user using username+password or token. - * This function sets up $USER global. - * It is safe to use has_capability() after this. - * This method also verifies user is allowed to use this - * server. - * @return void - */ - protected function authenticate_user() { - global $CFG, $DB; - - if (!NO_MOODLE_COOKIES) { - throw new coding_exception('Cookies must be disabled in WS servers!'); - } - - if ($this->simple) { - if (!is_enabled_auth('webservice')) { - die('WS auth not enabled'); - } - - if (!$auth = get_auth_plugin('webservice')) { - die('WS auth missing'); - } - - if (!$this->username) { - throw new invalid_parameter_exception('Missing username'); - } - - if (!$this->password) { - throw new invalid_parameter_exception('Missing password'); - } - - if (!$auth->user_login_webservice($this->username, $this->password)) { - throw new invalid_parameter_exception('Wrong username or password'); - } - - $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST); - - // now fake user login, the session is completely empty too - session_set_user($user); - - /* //TODO: add web service usage capabilities - if (!has_capability("webservice/$this->wsname:usesimple", get_context_instance(CONTEXT_SYSTEM))) { - throw new invalid_parameter_exception('Access to web service not allowed'); - } - */ - - } else { - //TODO: not implemented yet - die('token login not implemented yet'); - - /* //TODO: add web service usage capabilities - // note we had to wait until here because we did not know the security context earlier - if (!has_capability("webservice/$this->wsname:use", $context)) { - throw new invalid_parameter_exception('Access to web service not allowed'); - } - */ - } - } - - /** - * Fetches the function description from database, - * verifies user is allowed to use this function and - * loads all paremeters and return descriptions. - * @return void - */ - protected function load_function_info() { - global $DB, $USER, $CFG; - - if (empty($this->functionname)) { - throw new invalid_parameter_exception('Missing function name'); - } - - // function must exist - $function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST); - - - // now let's verify access control - if ($this->simple) { - // now make sure the function is listed in at least one service user is allowed to use - // allow access only if: - // 1/ entry in the external_services_users table - the restricted users flag is ignored in service desc - // 2/ validuntil not reached - // 3/ has capability if specified in service desc - // 4/ iprestriction - - $sql = "SELECT s.*, su.iprestriction - FROM {external_services} s - JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND sf.functionname = :name) - JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid) - WHERE su.validuntil IS NULL OR su.validuntil < :now"; - $rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name'=>$function->name, 'now'=>time())); - // now make sure user may access at least one service - $syscontext = get_context_instance(CONTEXT_SYSTEM); - $remoteaddr = getremoteaddr(); - $allowed = false; - foreach ($rs as $service) { - if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) { - continue; // cap required, sorry - } - if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) { - continue; // wrong request source ip, sorry - } - $allowed = true; - break; // one service is enough, no need to continue - } - $rs->close(); - if (!$allowed) { - throw new invalid_parameter_exception('Access to external function not allowed'); - } - // now we finally know the user may execute this function, - // the last step is to set context restriction - in this simple case - // we use system context because each external system has different user account - // and we can manage everything through normal permissions. - external_api::set_context_restriction($syscontext); - - } else { - //TODO: implement token security checks - die('not implemented yet'); - } - - // get the params and return descriptions of the function - unset($function->id); // we want to prevent any accidental db updates ;-) - - $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath; - if (!file_exists($function->classpath)) { - throw new coding_exception('Can not find file with external function implementation'); - } - require_once($function->classpath); - - $function->parameters_method = $function->methodname.'_parameters'; - $function->returns_method = $function->methodname.'_returns'; - - // make sure the implementaion class is ok - if (!method_exists($function->classname, $function->methodname)) { - throw new coding_exception('Missing implementation method'); - } - if (!method_exists($function->classname, $function->parameters_method)) { - throw new coding_exception('Missing parameters description'); - } - if (!method_exists($function->classname, $function->returns_method)) { - throw new coding_exception('Missing returned values description'); - } - - // fetch the parameters description - $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method)); - if (!($function->parameters_desc instanceof external_function_parameters)) { - throw new coding_exception('Invalid parameters description'); - } - - // fetch the return values description - $function->returns_desc = call_user_func(array($function->classname, $function->returns_method)); - // null means void result or result is ignored - if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) { - throw new coding_exception('Invalid return description'); - } - - // we have all we need now - $this->function = $function; - } - - /** - * Execute previously loaded function using parameters parsed from the request data. - * @return void - */ - protected function execute() { - // validate params, this also sorts the params properly, we need the correct order in the next part - $params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters); - - // execute - yay! - $this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params)); - } - - /** - * Returns human readable protocol name. - * @return string - */ - public function get_protocolname() { - return get_string('protocolname', 'webservice_'.$this->wsname); //TODO: add to lang pack - } - - /** - * Returns WS plugin name (not localized) - * @return string - */ - public function get_name() { - return $this->wsname; - } - - /** - * Is this WS server plugin enabled? - * @return bool - */ - public function is_enabled() { - return get_config($this->wsname, 'enable'); - } - - /** - * Change enabled flag - * @param bool $enable - * @return void - */ - public function set_enable($enable) { - set_config('enable', $enable, $this->wsname); - } - - /** - * Returns the settings form, - * the current data and defaults are already loaded. - * @return moodleform or null if settings not used - */ - public function settings_form() { - //NOTE: store the form definition in separate file, not directly in lib.php!! - return null; - } - - /** - * Saves settings form data to db. - * @param array $data - * @return void - */ - public function settings_save($data) { - return; - } -} - - - -//======== NOTE: this is finally the code that would be in this file ============================= - +require_once("$CFG->dirroot/webservice/rest/locallib.php"); -if (empty($CFG->enablesimplewebservices)) { +if (!webservice_protocol_is_enabled('rest')) { die; } -$server = new webservice_rest_server(true); -$server->run(); +$server = new webservice_rest_server(); +$server->run(true); die; diff --git a/webservice/rest/testclient/addgroupmember.php b/webservice/rest/testclient/addgroupmember.php deleted file mode 100644 index 61a7b9e8e6..0000000000 --- a/webservice/rest/testclient/addgroupmember.php +++ /dev/null @@ -1,69 +0,0 @@ - - -
- - - - -
Group id:
User id:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/config_rest.php b/webservice/rest/testclient/config_rest.php deleted file mode 100644 index 8f9e94415b..0000000000 --- a/webservice/rest/testclient/config_rest.php +++ /dev/null @@ -1,23 +0,0 @@ -enablewebservices)) { - die; -} - -$CFG->serverurl = $CFG->wwwroot.'/webservice/rest/server.php'; -if (!function_exists('curl_init')) die ('CURL library was not found!'); - -?> \ No newline at end of file diff --git a/webservice/rest/testclient/creategroup.php b/webservice/rest/testclient/creategroup.php deleted file mode 100644 index c7b78fa958..0000000000 --- a/webservice/rest/testclient/creategroup.php +++ /dev/null @@ -1,70 +0,0 @@ - - -
- - - - -
Group name:
Course id:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/createuser.php b/webservice/rest/testclient/createuser.php deleted file mode 100644 index 6a8b983a39..0000000000 --- a/webservice/rest/testclient/createuser.php +++ /dev/null @@ -1,49 +0,0 @@ -serverurl.'/user/get_token'); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); -curl_setopt($ch, CURLOPT_POST, 1); -curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata)); -$token = curl_exec($ch); -$data['token'] = $token; - -curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/create_user'); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); -curl_setopt($ch, CURLOPT_POST, 1); -curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data)); - -$out = curl_exec($ch); - -$res = basicxml_xml_to_object($out); - -show_object($res->userid); - -show_xml ($out); - -end_interface(); -?> \ No newline at end of file diff --git a/webservice/rest/testclient/deletegroup.php b/webservice/rest/testclient/deletegroup.php deleted file mode 100644 index 889aee63db..0000000000 --- a/webservice/rest/testclient/deletegroup.php +++ /dev/null @@ -1,66 +0,0 @@ - - -
- - - -
Group id:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/deletegroupmember.php b/webservice/rest/testclient/deletegroupmember.php deleted file mode 100644 index 5d493aac1e..0000000000 --- a/webservice/rest/testclient/deletegroupmember.php +++ /dev/null @@ -1,69 +0,0 @@ - - -
- - - - -
Group id:
User id:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/deleteuser.php b/webservice/rest/testclient/deleteuser.php deleted file mode 100644 index 5aa15ab465..0000000000 --- a/webservice/rest/testclient/deleteuser.php +++ /dev/null @@ -1,66 +0,0 @@ - - -
- - - -
Search:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/getgroup.php b/webservice/rest/testclient/getgroup.php deleted file mode 100644 index cdc8d90702..0000000000 --- a/webservice/rest/testclient/getgroup.php +++ /dev/null @@ -1,65 +0,0 @@ - - -
- - - -
Group id:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/getusers.php b/webservice/rest/testclient/getusers.php deleted file mode 100644 index f8117f6e3d..0000000000 --- a/webservice/rest/testclient/getusers.php +++ /dev/null @@ -1,63 +0,0 @@ - - -
- - - -
Search:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/testclient/index.php b/webservice/rest/testclient/index.php index be0dca44d2..944a32eab5 100644 --- a/webservice/rest/testclient/index.php +++ b/webservice/rest/testclient/index.php @@ -1,38 +1,93 @@ . + /** - * Created on 10/17/2008 + * REST web service test client. * - * Rest Test Client - * - * @author David Castro Garcia - * @author Ferran Recio Calderó - * @author Jerome Mouneyrac - * @author Jordi Piguillem + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once ('config_rest.php'); - -start_interface (false); - -$links = array( array('USERS'), - array('getusers.php','get_users()'), - array('createuser.php','create_user()'), - array('deleteuser.php','delete_user()'), - array('updateuser.php','update_user()'), - array('GROUPS'), - array('creategroup.php','create_group()'), - array('addgroupmember.php', 'add_groupmember()'), - array('getgroup.php', 'get_group()')); - -echo '
    '; -foreach ($links as $link) { - if (sizeof($link)==2){ - echo '
  • '.$link[1].'
  • '; - } else { - echo '

'.$link[0].'

    '; - } +require('../../../config.php'); +require_once("$CFG->dirroot/webservice/webservice_test_client_form.php"); +require_once("$CFG->dirroot/webservice/rest/locallib.php"); + +$function = optional_param('function', '', PARAM_SAFEDIR); + +$PAGE->set_url('webservice/rest/testclient/index.php'); + +require_login(); +require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); // TODO: do we need some new capability? + +$functions = array('moodle_group_get_groups'); +$functions = array_combine($functions, $functions); + +if (!isset($functions[$function])) { + $function = ''; } -echo '
'; -end_interface(false); -?> \ No newline at end of file +if (!$function) { + $mform = new webservice_test_client_form(null, $functions); + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest')); + $mform->display(); + echo $OUTPUT->footer(); + die; +} + +$class = $function.'_form'; +require_once("$CFG->dirroot/webservice/rest/testclient/$class.php"); + +$mform = new $class(); + +if ($mform->is_cancelled()) { + redirect('index.php'); + +} else if ($data = $mform->get_data()) { + $serverurl = "$CFG->wwwroot/webservice/rest/simpleserver.php"; + $serverurl .= '?wsusername='.urlencode($data->wsusername); + $serverurl .= '&wspassword='.urlencode($data->wspassword); + $serverurl .= '&wsfunction='.urlencode($data->function); + for ($i=0; $i<10; $i++) { + if (empty($data->groupids[$i])) { + continue; + } + $serverurl .= "&groupids[$i]=".urlencode($data->groupids[$i]); + } + + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest').': '.$function); + + echo 'URL: '.s($serverurl); + echo $OUTPUT->box_start(); + echo ''; + $response = download_file_content($serverurl); + echo str_replace("\n", '
', s($response)); + echo '
'; + echo $OUTPUT->box_end(); + $mform->display(); + echo $OUTPUT->footer(); + die; + +} else { + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest').': '.$function); + $mform->display(); + echo $OUTPUT->footer(); + die; +} \ No newline at end of file diff --git a/webservice/rest/testclient/lib.php b/webservice/rest/testclient/lib.php deleted file mode 100644 index ebac6cd2dc..0000000000 --- a/webservice/rest/testclient/lib.php +++ /dev/null @@ -1,226 +0,0 @@ -'; - echo "Moodle Webservice Rest Test Client"; - echo ''; - echo ''; - echo '

Moodle Webservice Rest Test Client

'; - echo "

$title2

"; - echo '
'; - echo '
'; - if ($title) echo '

'; -} - -/** - * end interface - * - * @param bool $ret=true: show return button - */ -function end_interface ($ret = true) { - if ($ret) echo '

'; - echo '
'; - echo ''; - echo ''; -} - -/** - * print XML div area - * - * @param string $xml - * - */ -function show_xml ($xml) { - echo '
'; - echo 'Hide/Show XML'; - echo "
"; - echo '
';echo htmlentities($xml);echo '
'; - echo "
"; - echo "
"; -} - -/** - * 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 '
    '; - foreach ($obj as $r) { - - if ($check && (!isset($r->$check) || $r->$check==-1)) { - echo '
  • '; - echo "EMPTY ROW!"; - } else { - if (is_object($r)) { - echo '
  • '; - $text = array(); - $parts = get_object_vars($r); - $num = 1; - $currline = ''; - foreach ($parts as $key => $val) { - $currline.= "$key: $val, "; - if ($num >= $cols) { - $currline=substr($currline,0,-2); - $text[] = $currline; - $currline = ''; - $num = 0; - } - $num++; - } - echo implode('
    ',$text); - } else { - if ($r==-1 || !$r) { - echo '
  • '; - echo "EMPTY ROW!"; - } else { - echo '
  • '; - echo "Returned Value: $r"; - } - } - } - echo '
  • '; - } - echo '
'; -} - - -//---- 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; -} -?> diff --git a/webservice/rest/testclient/moodle_group_get_groups_form.php b/webservice/rest/testclient/moodle_group_get_groups_form.php new file mode 100644 index 0000000000..682758ef99 --- /dev/null +++ b/webservice/rest/testclient/moodle_group_get_groups_form.php @@ -0,0 +1,28 @@ +dirroot.'/lib/formslib.php'); + + +class moodle_group_get_groups_form extends moodleform { + public function definition() { + global $CFG; + + $mform = $this->_form; + + $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice')); + + //note: these values are intentionally PARAM_RAW - we want users to test any rubbish as parameters + $mform->addElement('text', 'wsusername', 'wsusername'); + $mform->addElement('text', 'wspassword', 'wspassword'); + $mform->addElement('text', 'groupids[0]', 'groupids[0]'); + $mform->addElement('text', 'groupids[1]', 'groupids[1]'); + $mform->addElement('text', 'groupids[2]', 'groupids[2]'); + $mform->addElement('text', 'groupids[3]', 'groupids[3]'); + + $mform->addElement('hidden', 'function'); + $mform->setType('function', PARAM_SAFEDIR); + $mform->setDefault('function', 'moodle_group_get_groups'); + + $this->add_action_buttons(true, get_string('test', 'webservice')); + } +} \ No newline at end of file diff --git a/webservice/rest/testclient/return.gif b/webservice/rest/testclient/return.gif deleted file mode 100644 index 96a5251c78cba473bd7394593857fa6c5f023900..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmV-~0DJ#ONk%w1VI=?-0Pz9 - -
- - - - - -
Old username:
New username:
New firstname:
-
- -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 "

Fill the form first

"; -} - -end_interface(); - -?> diff --git a/webservice/rest/version.php b/webservice/rest/version.php new file mode 100644 index 0000000000..aabe26d858 --- /dev/null +++ b/webservice/rest/version.php @@ -0,0 +1,3 @@ +version = 2009100800; diff --git a/webservice/webservice_test_client_form.php b/webservice/webservice_test_client_form.php new file mode 100644 index 0000000000..5993516a40 --- /dev/null +++ b/webservice/webservice_test_client_form.php @@ -0,0 +1,19 @@ +dirroot.'/lib/formslib.php'); + + +class webservice_test_client_form extends moodleform { + public function definition() { + global $CFG; + + $mform = $this->_form; + $functions = $this->_customdata; + + $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice')); + + $mform->addElement('select', 'function', get_string('function', 'webservice'), $functions); + + $this->add_action_buttons(false, get_string('select')); + } +} \ No newline at end of file diff --git a/webservice/wsdoc.php b/webservice/wsdoc.php index 49b7c892d8..e74ebd9e92 100644 --- a/webservice/wsdoc.php +++ b/webservice/wsdoc.php @@ -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 -- 2.39.5