Permalink
Browse files

MDL-38509 Check for writable plugin type location in install from ZIP…

… form

Standard mform validation is implemented as well as progressively
enhanced AJAX version.
  • Loading branch information...
1 parent 2459758 commit ddab904ba800d0aa7d7ae824c0847aeca394e334 @mudrd8mz mudrd8mz committed Mar 18, 2013
View
38 admin/tool/installaddon/classes/installer.php
@@ -34,6 +34,9 @@
*/
class tool_installaddon_installer {
+ /** @var tool_installaddon_installfromzip */
+ protected $installfromzipform = null;
+
/**
* Factory method returning an instance of this class.
*
@@ -80,10 +83,16 @@ public function get_installfromzip_form() {
global $CFG;
require_once(dirname(__FILE__).'/installfromzip_form.php');
+ if (!is_null($this->installfromzipform)) {
+ return $this->installfromzipform;
+ }
+
$action = new moodle_url('/admin/tool/installaddon/index.php');
$customdata = array('installer' => $this);
- return new tool_installaddon_installfromzip($action, $customdata);
+ $this->installfromzipform = new tool_installaddon_installfromzip($action, $customdata);
+
+ return $this->installfromzipform;
}
/**
@@ -105,6 +114,33 @@ public function get_plugin_types_menu() {
return $menu;
}
+ /**
+ * Is it possible to create a new plugin directory for the given plugin type?
+ *
+ * @throws coding_exception for invalid plugin types or non-existing plugin type locations
+ * @param string $plugintype
+ * @return boolean
+ */
+ public function is_plugintype_writable($plugintype) {
+
+ $plugintypepath = null;
+ foreach (get_plugin_types() as $type => $fullpath) {
+ if ($type === $plugintype) {
+ $plugintypepath = $fullpath;
+ break;
+ }
+ }
+ if (is_null($plugintypepath)) {
+ throw new coding_exception('Unknown plugin type!');
+ }
+
+ if (!is_dir($plugintypepath)) {
+ throw new coding_exception('Plugin type location does not exist!');
+ }
+
+ return is_writable($plugintypepath);
+ }
+
//// End of external API ///////////////////////////////////////////////////
/**
View
14 admin/tool/installaddon/classes/installfromzip_form.php
@@ -44,10 +44,15 @@ public function definition() {
$installer = $this->_customdata['installer'];
$options = $installer->get_plugin_types_menu();
- $mform->addElement('select', 'plugintype', get_string('installfromziptype', 'tool_installaddon'), $options);
+ $mform->addElement('select', 'plugintype', get_string('installfromziptype', 'tool_installaddon'), $options,
+ array('id' => 'tool_installaddon_installfromzip_plugintype'));
$mform->addHelpButton('plugintype', 'installfromziptype', 'tool_installaddon');
$mform->addRule('plugintype', null, 'required', null, 'client');
+ $mform->addElement('static', 'permcheck', '',
+ html_writer::span(get_string('permcheck', 'tool_installaddon'), '',
+ array('id' => 'tool_installaddon_installfromzip_permcheck')));
+
$mform->addElement('filepicker', 'zipfile', get_string('installfromzipfile', 'tool_installaddon'),
null, array('accepted_types' => '.zip'));
$mform->addHelpButton('zipfile', 'installfromzipfile', 'tool_installaddon');
@@ -69,8 +74,15 @@ public function definition() {
*/
public function validation($data, $files) {
+ $installer = $this->_customdata['installer'];
$errors = parent::validation($data, $files);
+ if (!$installer->is_plugintype_writable($data['plugintype'])) {
+ $paths = get_plugin_types(true);
+ $path = $paths[$data['plugintype']];
+ $errors['plugintype'] = get_string('permcheckresultno', 'tool_installaddon', array('path' => $path));
+ }
+
return $errors;
}
}
View
5 admin/tool/installaddon/lang/en/tool_installaddon.php
@@ -38,4 +38,9 @@
$string['installfromzipsubmit'] = 'Install add-on from the ZIP file';
$string['installfromziptype'] = 'Plugin type';
$string['installfromziptype_help'] = 'Choose the correct type of plugin you are about to install. The installation procedure may fail badly when incorrect plugin type is provided.';
+$string['permcheck'] = 'Make sure the plugin type root location is writable by the web server process';
+$string['permcheckerror'] = 'Error while checking for write permission';
+$string['permcheckprogress'] = 'Checking for write permission ...';
+$string['permcheckresultno'] = 'Plugin type location <em>{$a->path}</em> not writable';
+$string['permcheckresultyes'] = 'Plugin type location <em>{$a->path}</em> is writable';
$string['pluginname'] = 'Add-on installer';
View
79 admin/tool/installaddon/permcheck.php
@@ -0,0 +1,79 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Checks the write permission for the given plugin type
+ *
+ * @package tool_installaddon
+ * @subpackage ajax
+ * @copyright 2013 David Mudrak <david@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('AJAX_SCRIPT', true);
+
+require(dirname(__FILE__) . '/../../../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once(dirname(__FILE__).'/classes/installer.php');
+
+require_login();
+
+if (!has_capability('moodle/site:config', context_system::instance())) {
+ header('HTTP/1.1 403 Forbidden');
+ die();
+}
+
+if (!empty($CFG->disableonclickaddoninstall)) {
+ header('HTTP/1.1 403 Forbidden');
+ die();
+}
+
+if (!confirm_sesskey()) {
+ header('HTTP/1.1 403 Forbidden');
+ die();
+}
+
+$plugintype = optional_param('plugintype', null, PARAM_ALPHANUMEXT);
+if (is_null($plugintype)) {
+ header('HTTP/1.1 400 Bad Request');
+ die();
+}
+
+$plugintypepath = null;
+foreach (get_plugin_types() as $type => $fullpath) {
+ if ($type === $plugintype) {
+ $plugintypepath = $fullpath;
+ break;
+ }
+}
+if (is_null($plugintypepath)) {
+ header('HTTP/1.1 400 Bad Request');
+ die();
+}
+
+$installer = tool_installaddon_installer::instance();
+
+$response = array('path' => $plugintypepath);
+
+if ($installer->is_plugintype_writable($plugintype)) {
+ $response['writable'] = 1;
+} else {
+ $response['writable'] = 0;
+}
+
+header('Content-Type: application/json; charset: utf-8');
+echo json_encode($response);
View
6 admin/tool/installaddon/renderer.php
@@ -58,6 +58,12 @@ public function set_installer_instance(tool_installaddon_installer $installer) {
*/
public function index_page() {
+ $permcheckurl = new moodle_url('/admin/tool/installaddon/permcheck.php');
+ $this->page->requires->yui_module('moodle-tool_installaddon-permcheck', 'M.tool_installaddon.permcheck.init',
+ array(array('permcheckurl' => $permcheckurl->out())));
+ $this->page->requires->strings_for_js(
+ array('permcheckprogress', 'permcheckresultno', 'permcheckresultyes', 'permcheckerror'), 'tool_installaddon');
+
$out = $this->output->header();
$out .= $this->index_page_heading();
$out .= $this->index_page_repository();
View
105 admin/tool/installaddon/yui/permcheck/permcheck.js
@@ -0,0 +1,105 @@
+/**
+ * Check for write permission for the selected plugin type
+ *
+ * @module moodle-tool_installaddon-permcheck
+ * @author David Mudrak <david@moodle.com>
+ */
+YUI.add('moodle-tool_installaddon-permcheck', function(Y) {
+
+ M.tool_installaddon = M.tool_installaddon || {};
+
+ /**
+ * @class permcheck
+ * @static
+ */
+ M.tool_installaddon.permcheck = {
+
+ /**
+ * @method init
+ * @param {Object} config Configuration passed from the PHP
+ */
+ init : function(config) {
+ this.config = config;
+ var plugintypesel = Y.one('#tool_installaddon_installfromzip_plugintype');
+ if (plugintypesel) {
+ plugintypesel.on('change', this.check_for_permission, this);
+ }
+ },
+
+ /**
+ * @method check_for_permission
+ * @param {Event} e
+ */
+ check_for_permission : function(e) {
+ var plugintype = e.currentTarget.get('value');
+ if (plugintype == '') {
+ return;
+ }
+ Y.log('Selected plugin type: ' + plugintype, 'debug', 'moodle-tool_installaddon-permcheck');
+ Y.io(this.config.permcheckurl, {
+ 'method' : 'GET',
+ 'data' : {
+ 'sesskey' : M.cfg.sesskey,
+ 'plugintype' : plugintype
+ },
+ 'arguments' : {
+ 'plugintypeselector' : e.currentTarget,
+ 'showresult' : function(msg, status) {
+ var resultline = Y.one('#tool_installaddon_installfromzip_permcheck');
+ if (resultline) {
+ if (status === 'success') {
+ resultline.setContent('<span class="success"><img src="' + M.util.image_url('i/tick_green_big') + '" /> ' +
+ msg + '</span>');
+ } else if (status === 'progress') {
+ resultline.setContent('<span class="progress"><img src="' + M.cfg.loadingicon + '" /> ' +
+ msg + '</span>');
+ } else {
+ resultline.setContent('<span class="error"><img src="' + M.util.image_url('i/cross_red_big') + '" /> ' +
+ msg + '</span>');
+ }
+ }
+ }
+ },
+ 'on' : {
+ 'start' : function(transid, args) {
+ args.showresult(M.util.get_string('permcheckprogress', 'tool_installaddon'), 'progress');
+ },
+ 'success': function(transid, outcome, args) {
+ var response;
+ try {
+ response = Y.JSON.parse(outcome.responseText);
+ if (response.error) {
+ Y.log(response.error, 'error', 'moodle-tool_installaddon-permcheck');
+ args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon', response), 'error');
+ } else if (response.path && response.writable == 1) {
+ args.showresult(M.util.get_string('permcheckresultyes', 'tool_installaddon', response), 'success');
+ } else if (response.path && response.writable == 0) {
+ args.showresult(M.util.get_string('permcheckresultno', 'tool_installaddon', response), 'error');
+ } else {
+ Y.log(response, 'debug', 'moodle-tool_installaddon-permcheck');
+ args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon', response), 'error');
+ }
+
+ } catch (e) {
+ Y.log(e, 'error', 'moodle-tool_installaddon-permcheck');
+ args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon'), 'error');
+ }
+ },
+ 'failure': function(transid, outcome, args) {
+ Y.log(outcome.statusText, 'error', 'moodle-tool_installaddon-permcheck');
+ args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon'));
+ }
+ }
+ });
+ },
+
+ /**
+ * @property
+ * @type {Object}
+ */
+ config : null
+ };
+
+}, '@VERSION@', {
+ requires:['node', 'event', 'io-base']
+});

0 comments on commit ddab904

Please sign in to comment.