Aleksander Machniak
2013-04-28 416cc7106ad571e9ed42874ceee7dfec549be2bb
Merge branch 'master' of github.com:roundcube/roundcubemail
5 files modified
221 ■■■■■ changed files
composer.json-dist 25 ●●●● patch | view | raw | blame | history
program/include/iniset.php 5 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_plugin.php 10 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_plugin_api.php 114 ●●●●● patch | view | raw | blame | history
program/steps/settings/about.inc 67 ●●●● patch | view | raw | blame | history
composer.json-dist
@@ -1,35 +1,16 @@
{
    "name": "roundcube/roundcubemail",
    "description": "The Roundcube Webmail suite",
    "license": "GPL-3.0",
    "license": "GPL-3.0+",
    "repositories": [
        {
            "type": "composer",
            "url": "http://plugins.roundcube.net/"
        },
        {
            "type": "pear",
            "url": "http://pear.php.net/"
        },
        {
            "type": "package",
            "package": {
                "name": "Net_SMTP",
                "version": "dev-master",
                "source": {
                    "url": "http://github.com/pear/Net_SMTP",
                    "type": "git",
                    "reference": "master"
                }
            }
        }
    ],
    "require": {
        "pear-pear/Mail_Mime": ">=1.8.1",
        "pear-pear/Mail_mimeDecode": ">=1.5.5",
        "Net_SMTP": "dev-master",
        "pear-pear/Net_IDNA2": ">=0.1.1",
        "pear-pear/Auth_SASL": ">=1.0.6"
        "php": ">=5.3.0",
        "roundcube/plugin-installer": ">=0.1.2"
    },
    "minimum-stability": "dev"
}
program/include/iniset.php
@@ -60,6 +60,11 @@
// register autoloader for rcmail app classes
spl_autoload_register('rcmail_autoload');
// include composer autoloader (if available)
if (file_exists('vendor/autoload.php')) {
    require 'vendor/autoload.php';
}
// backward compatybility (to be removed)
require_once INSTALL_PATH . 'program/include/bc.php';
program/lib/Roundcube/rcube_plugin.php
@@ -92,6 +92,16 @@
    abstract function init();
    /**
     * Provide information about this
     *
     * @return array Meta information about a plugin or false if not implemented
     */
    public static function info()
    {
        return false;
    }
    /**
     * Attempt to load the given plugin which is required for the current plugin
     *
     * @param string Plugin name
program/lib/Roundcube/rcube_plugin_api.php
@@ -228,6 +228,120 @@
    }
    /**
     * Get information about a specific plugin.
     * This is either provided my a plugin's info() method or extracted from a package.xml or a composer.json file
     *
     * @param string Plugin name
     * @return array Meta information about a plugin or False if plugin was not found
     */
    public function get_info($plugin_name)
    {
      static $composer_lock, $license_uris = array(
        'Apache'     => 'http://www.apache.org/licenses/LICENSE-2.0.html',
        'Apache-2'   => 'http://www.apache.org/licenses/LICENSE-2.0.html',
        'Apache-1'   => 'http://www.apache.org/licenses/LICENSE-1.0',
        'Apache-1.1' => 'http://www.apache.org/licenses/LICENSE-1.1',
        'GPL'        => 'http://www.gnu.org/licenses/gpl.html',
        'GPLv2'      => 'http://www.gnu.org/licenses/gpl-2.0.html',
        'GPL-2.0'    => 'http://www.gnu.org/licenses/gpl-2.0.html',
        'GPLv3'      => 'http://www.gnu.org/licenses/gpl-3.0.html',
        'GPL-3.0'    => 'http://www.gnu.org/licenses/gpl-3.0.html',
        'GPL-3.0+'   => 'http://www.gnu.org/licenses/gpl.html',
        'GPL-2.0+'   => 'http://www.gnu.org/licenses/gpl.html',
        'LGPL'       => 'http://www.gnu.org/licenses/lgpl.html',
        'LGPLv2'     => 'http://www.gnu.org/licenses/lgpl-2.0.html',
        'LGPLv2.1'   => 'http://www.gnu.org/licenses/lgpl-2.1.html',
        'LGPLv3'     => 'http://www.gnu.org/licenses/lgpl.html',
        'LGPL-2.0'   => 'http://www.gnu.org/licenses/lgpl-2.0.html',
        'LGPL-2.1'   => 'http://www.gnu.org/licenses/lgpl-2.1.html',
        'LGPL-3.0'   => 'http://www.gnu.org/licenses/lgpl.html',
        'LGPL-3.0+'  => 'http://www.gnu.org/licenses/lgpl.html',
        'BSD'          => 'http://opensource.org/licenses/bsd-license.html',
        'BSD-2-Clause' => 'http://opensource.org/licenses/BSD-2-Clause',
        'BSD-3-Clause' => 'http://opensource.org/licenses/BSD-3-Clause',
        'FreeBSD'      => 'http://opensource.org/licenses/BSD-2-Clause',
        'MIT'          => 'http://www.opensource.org/licenses/mit-license.php',
        'PHP'          => 'http://opensource.org/licenses/PHP-3.0',
        'PHP-3'        => 'http://www.php.net/license/3_01.txt',
        'PHP-3.0'      => 'http://www.php.net/license/3_0.txt',
        'PHP-3.01'     => 'http://www.php.net/license/3_01.txt',
      );
      $dir = dir($this->dir);
      $fn = unslashify($dir->path) . DIRECTORY_SEPARATOR . $plugin_name . DIRECTORY_SEPARATOR . $plugin_name . '.php';
      $info = false;
      if (!class_exists($plugin_name))
        include($fn);
      if (class_exists($plugin_name))
        $info = $plugin_name::info();
      // fall back to composer.json file
      if (!$info) {
        $composer = INSTALL_PATH . "/plugins/$plugin_name/composer.json";
        if (file_exists($composer) && ($json = @json_decode(file_get_contents($composer), true))) {
          list($info['vendor'], $info['name']) = explode('/', $json['name']);
          $info['license'] = $json['license'];
          if ($license_uri = $license_uris[$info['license']])
            $info['license_uri'] = $license_uri;
        }
        // read local composer.lock file (once)
        if (!isset($composer_lock)) {
          $composer_lock = @json_decode(@file_get_contents(INSTALL_PATH . "/composer.lock"), true);
          if ($composer_lock['packages']) {
            foreach ($composer_lock['packages'] as $i => $package) {
              $composer_lock['installed'][$package['name']] = $package;
            }
          }
        }
        // load additional information from local composer.lock file
        if ($lock = $composer_lock['installed'][$json['name']]) {
          $info['version'] = $lock['version'];
          $info['uri']     = $lock['homepage'] ? $lock['homepage'] : $lock['source']['uri'];
          $info['src_uri'] = $lock['dist']['uri'] ? $lock['dist']['uri'] : $lock['source']['uri'];
        }
      }
      // fall back to package.xml file
      if (!$info) {
        $package = INSTALL_PATH . "/plugins/$plugin_name/package.xml";
        if (file_exists($package) && ($file = file_get_contents($package))) {
          $doc = new DOMDocument();
          $doc->loadXML($file);
          $xpath = new DOMXPath($doc);
          $xpath->registerNamespace('rc', "http://pear.php.net/dtd/package-2.0");
          $data = array();
          // XPaths of plugin metadata elements
          $metadata = array(
            'name'    => 'string(//rc:package/rc:name)',
            'version' => 'string(//rc:package/rc:version/rc:release)',
            'license' => 'string(//rc:package/rc:license)',
            'license_uri' => 'string(//rc:package/rc:license/@uri)',
            'src_uri' => 'string(//rc:package/rc:srcuri)',
            'uri' => 'string(//rc:package/rc:uri)',
          );
          foreach ($metadata as $key => $path) {
            $info[$key] = $xpath->evaluate($path);
          }
          // dependent required plugins (can be used, but not included in config)
          $deps = $xpath->evaluate('//rc:package/rc:dependencies/rc:required/rc:package/rc:name');
          for ($i = 0; $i < $deps->length; $i++) {
            $dn = $deps->item($i)->nodeValue;
            $info['requires'][] = $dn;
          }
        }
      }
      return $info;
    }
    /**
     * Allows a plugin object to register a callback for a certain hook
     *
     * @param string $hook Hook name
program/steps/settings/about.inc
@@ -40,17 +40,28 @@
    $attrib['id'] = 'rcmpluginlist';
  $plugins = array_filter((array) $RCMAIL->config->get('plugins'));
  $plugins = array_flip($plugins);
  $plugin_info = array();
  foreach ($plugins as $name => $plugin) {
    rcube_plugin_data($name, $plugins);
  foreach ($plugins as $name) {
    if ($info = $RCMAIL->plugins->get_info($name))
      $plugin_info[$name] = $info;
  }
  if (empty($plugins)) {
  // load info from required plugins, too
  foreach ($plugin_info as $name => $info) {
    if (is_array($info['required']) && !empty($info['required'])) {
      foreach ($info['required'] as $req_name) {
        if (!isset($plugin_info[$req_name]) && ($req_info = $RCMAIL->plugins->get_info($req_name)))
          $plugin_info[$req_name] = $req_info;
      }
    }
  }
  if (empty($plugin_info)) {
    return '';
  }
  ksort($plugins, SORT_LOCALE_STRING);
  ksort($plugin_info, SORT_LOCALE_STRING);
  $table = new html_table($attrib);
@@ -60,8 +71,8 @@
  $table->add_header('license', rcube_label('license'));
  $table->add_header('source', rcube_label('source'));
  foreach ($plugins as $name => $data) {
    $uri = $data['srcuri'] ? $data['srcuri'] : $data['uri'];
  foreach ($plugin_info as $name => $data) {
    $uri = $data['src_uri'] ? $data['src_uri'] : $data['uri'];
    if ($uri && stripos($uri, 'http') !== 0) {
      $uri = 'http://' . $uri;
    }
@@ -76,48 +87,6 @@
  }
  return $table->show();
}
function rcube_plugin_data($name, &$plugins = array())
{
  // XPaths of plugin metadata elements
  $metadata = array(
    'name'    => 'string(//rc:package/rc:name)',
    'version' => 'string(//rc:package/rc:version/rc:release)',
    'license' => 'string(//rc:package/rc:license)',
    'license_uri' => 'string(//rc:package/rc:license/@uri)',
    'srcuri' => 'string(//rc:package/rc:srcuri)',
    'uri' => 'string(//rc:package/rc:uri)',
  );
  $package = INSTALL_PATH . "/plugins/$name/package.xml";
  if (file_exists($package) && ($file = file_get_contents($package))) {
    $doc = new DOMDocument();
    $doc->loadXML($file);
    $xpath = new DOMXPath($doc);
    $xpath->registerNamespace('rc', "http://pear.php.net/dtd/package-2.0");
    $data = array();
    foreach ($metadata as $key => $path) {
      $data[$key] = $xpath->evaluate($path);
    }
    $plugins[$name] = $data;
    // dependent required plugins (can be used, but not included in config)
    $deps = $xpath->evaluate('//rc:package/rc:dependencies/rc:required/rc:package/rc:name');
    $cnt  = $deps->length;
    for ($i=0; $i<$cnt; $i++) {
      $dn = $deps->item($i)->nodeValue;
      if (!array_key_exists($dn, $plugins)) {
        rcube_plugin_data($dn, $plugins);
      }
    }
  }
  else {
    unset($plugins[$name]);
  }
}