MDL-36903 Pre-check the ZIP download before executing the mdeploy.php utility
authorDavid Mudrák <david@moodle.com>
Fri, 30 Nov 2012 12:12:29 +0000 (13:12 +0100)
committerDavid Mudrák <david@moodle.com>
Fri, 30 Nov 2012 15:09:58 +0000 (16:09 +0100)
This patch makes Moodle call HTTP HEAD method via cURL to see if the ZIP
is expected to be downloadable by mdeploy.php. This is mainly intended
for SSL certificates check.

admin/renderer.php
lang/en/plugin.php
lib/pluginlib.php

index de78470..5767d7f 100644 (file)
@@ -1211,8 +1211,13 @@ class core_admin_renderer extends plugin_renderer_base {
             if (empty($impediments)) {
                 $widget = $deployer->make_confirm_widget($updateinfo);
                 $box .= $this->output->render($widget);
             if (empty($impediments)) {
                 $widget = $deployer->make_confirm_widget($updateinfo);
                 $box .= $this->output->render($widget);
-            } else if (isset($impediments['notwritable'])) {
-                $box .= $this->output->help_icon('notwritable', 'core_plugin', get_string('notwritable', 'core_plugin'));
+            } else {
+                if (isset($impediments['notwritable'])) {
+                    $box .= $this->output->help_icon('notwritable', 'core_plugin', get_string('notwritable', 'core_plugin'));
+                }
+                if (isset($impediments['notdownloadable'])) {
+                    $box .= $this->output->help_icon('notdownloadable', 'core_plugin', get_string('notdownloadable', 'core_plugin'));
+                }
             }
         }
 
             }
         }
 
index e971234..4d4dd8c 100644 (file)
@@ -43,10 +43,14 @@ $string['nonehighlighted'] = 'No plugins require your attention now';
 $string['nonehighlightedinfo'] = 'Display the list of all installed plugins anyway';
 $string['noneinstalled'] = 'No plugins of this type are installed';
 $string['notes'] = 'Notes';
 $string['nonehighlightedinfo'] = 'Display the list of all installed plugins anyway';
 $string['noneinstalled'] = 'No plugins of this type are installed';
 $string['notes'] = 'Notes';
+$string['notdownloadable'] = 'Can not download the package';
+$string['notdownloadable_help'] = 'ZIP package with the update can not be downloaded automatically. Please refer to the documentation page for more help.';
+$string['notdownloadable_link'] = 'admin/mdeploy/notdownloadable';
 $string['notwritable'] = 'Plugin files not writable';
 $string['notwritable_help'] = 'You have enabled automatic updates deployment and there is available update for this plugin. However, the plugin files are not writable by the web server so the update can not be installed at the moment.
 
 Make the plugin folder and all its contents writable to be able to install the available update automatically.';
 $string['notwritable'] = 'Plugin files not writable';
 $string['notwritable_help'] = 'You have enabled automatic updates deployment and there is available update for this plugin. However, the plugin files are not writable by the web server so the update can not be installed at the moment.
 
 Make the plugin folder and all its contents writable to be able to install the available update automatically.';
+$string['notwritable_link'] = 'admin/mdeploy/notwritable';
 $string['numtotal'] = 'Installed: {$a}';
 $string['numdisabled'] = 'Disabled: {$a}';
 $string['numextension'] = 'Contributions: {$a}';
 $string['numtotal'] = 'Installed: {$a}';
 $string['numdisabled'] = 'Disabled: {$a}';
 $string['numextension'] = 'Contributions: {$a}';
index 6feda47..02a6d99 100644 (file)
@@ -1589,6 +1589,10 @@ class available_update_deployer {
             $impediments['missingdownloadmd5'] = true;
         }
 
             $impediments['missingdownloadmd5'] = true;
         }
 
+        if (!empty($info->download) and !$this->update_downloadable($info->download)) {
+            $impediments['notdownloadable'] = true;
+        }
+
         if (!$this->component_writable($info->component)) {
             $impediments['notwritable'] = true;
         }
         if (!$this->component_writable($info->component)) {
             $impediments['notwritable'] = true;
         }
@@ -1917,6 +1921,40 @@ class available_update_deployer {
         return $this->directory_writable($directory);
     }
 
         return $this->directory_writable($directory);
     }
 
+    /**
+     * Checks if the mdeploy.php will be able to fetch the ZIP from the given URL
+     *
+     * This is mainly supposed to check if the transmission over HTTPS would
+     * work. That is, if the CA certificates are present at the server.
+     *
+     * @param string $downloadurl the URL of the ZIP package to download
+     * @return bool
+     */
+    protected function update_downloadable($downloadurl) {
+        global $CFG;
+
+        $curloptions = array(
+            'CURLOPT_SSL_VERIFYHOST' => 2,      // this is the default in {@link curl} class but just in case
+            'CURLOPT_SSL_VERIFYPEER' => true,
+        );
+
+        $cacertfile = $CFG->dataroot.'/moodleorgca.crt';
+        if (is_readable($cacertfile)) {
+            // Do not use CA certs provided by the operating system. Instead,
+            // use this CA cert to verify the updates provider.
+            $curloptions['CURLOPT_CAINFO'] = $cacertfile;
+        }
+
+        $curl = new curl(array('proxy' => true));
+        $result = $curl->head($downloadurl, $curloptions);
+        $errno = $curl->get_errno();
+        if (empty($errno)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     /**
      * Checks if the directory and all its contents (recursively) is writable
      *
     /**
      * Checks if the directory and all its contents (recursively) is writable
      *