Show spam aliases #

This commit is contained in:
andryyy
2017-02-21 22:27:11 +01:00
parent 76426b65b2
commit 0eb932b3ab
2737 changed files with 357639 additions and 22 deletions

View File

@@ -0,0 +1,46 @@
# Plugin Installer for Roundcube
This installer ensures that plugins end up in the correct directory:
* `<roundcube-root>/plugins/plugin-name`
## Minimum setup
* create a `composer.json` file in your plugin's repository
* add the following contents
### sample composer.json for plugins
{
"name": "yourvendor/plugin-name",
"license": "the license",
"description": "tell the world what your plugin is good at",
"type": "roundcube-plugin",
"authors": [
{
"name": "<your-name>",
"email": "<your-email>"
}
],
"repositories": [
{
"type": "composer",
"url": "http://plugins.roundcube.net"
}
]
"require": {
"roundcube/plugin-installer": "*"
},
"minimum-stability": "dev-master"
}
* Submit your plugin to [plugins.roundcube.net](http://plugins.roundcube.net).
## Installation
* clone Roundcube
* `cp composer.json-dist composer.json`
* add your plugin in the `require` section of composer.json
* `composer.phar install`
Read the whole story at [plugins.roundcube.net](http://plugins.roundcube.net/about).

View File

@@ -0,0 +1,33 @@
{
"name": "roundcube/plugin-installer",
"description": "A composer-installer for Roundcube plugins.",
"type": "composer-installer",
"license": "GPL-3.0+",
"authors": [
{
"name": "Thomas Bruederli",
"email": "thomas@roundcube.net"
},
{
"name": "Till Klampaeckel",
"email": "till@php.net"
}
],
"autoload": {
"psr-0": {
"Roundcube\\Composer": "src/"
}
},
"extra": {
"class": "Roundcube\\Composer\\PluginInstaller"
},
"bin": [
"src/bin/rcubeinitdb.sh"
],
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"composer/composer": "*"
}
}

View File

@@ -0,0 +1,266 @@
<?php
namespace Roundcube\Composer;
use Composer\Installer\LibraryInstaller;
use Composer\Package\Version\VersionParser;
use Composer\Package\LinkConstraint\VersionConstraint;
use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Util\ProcessExecutor;
/**
* @category Plugins
* @package PluginInstaller
* @author Till Klampaeckel <till@php.net>
* @author Thomas Bruederli <thomas@roundcube.net>
* @license GPL-3.0+
* @version GIT: <git_id>
* @link http://github.com/roundcube/plugin-installer
*/
class PluginInstaller extends LibraryInstaller
{
const INSTALLER_TYPE = 'roundcube-plugin';
/**
* {@inheritDoc}
*/
public function getInstallPath(PackageInterface $package)
{
static $vendorDir;
if ($vendorDir === null) {
$vendorDir = $this->getVendorDir();
}
return sprintf('%s/%s', $vendorDir, $this->getPluginName($package));
}
/**
* {@inheritDoc}
*/
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
{
$this->rcubeVersionCheck($package);
parent::install($repo, $package);
// post-install: activate plugin in Roundcube config
$config_file = $this->rcubeConfigFile();
$extra = $package->getExtra();
$plugin_name = $this->getPluginName($package);
if (is_writeable($config_file) && php_sapi_name() == 'cli') {
$answer = $this->io->askConfirmation("Do you want to activate the plugin $plugin_name? [N|y] ", false);
if (true === $answer) {
$this->rcubeAlterConfig($plugin_name, true);
}
}
// initialize database schema
if (!empty($extra['roundcube']['sql-dir'])) {
if ($sqldir = realpath($this->getVendorDir() . "/$plugin_name/" . $extra['roundcube']['sql-dir'])) {
system(getcwd() . "/vendor/bin/rcubeinitdb.sh --package=$plugin_name --dir=$sqldir");
}
}
// run post-install script
if (!empty($extra['roundcube']['post-install-script'])) {
$this->rcubeRunScript($extra['roundcube']['post-install-script'], $package);
}
}
/**
* {@inheritDoc}
*/
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
{
$this->rcubeVersionCheck($target);
parent::update($repo, $initial, $target);
$extra = $target->getExtra();
// trigger updatedb.sh
if (!empty($extra['roundcube']['sql-dir'])) {
$plugin_name = $this->getPluginName($target);
if ($sqldir = realpath($this->getVendorDir() . "/$plugin_name/" . $extra['roundcube']['sql-dir'])) {
system(getcwd() . "/bin/updatedb.sh --package=$plugin_name --dir=$sqldir", $res);
}
}
// run post-update script
if (!empty($extra['roundcube']['post-update-script'])) {
$this->rcubeRunScript($extra['roundcube']['post-update-script'], $target);
}
}
/**
* {@inheritDoc}
*/
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
{
parent::uninstall($repo, $package);
// post-uninstall: deactivate plugin
$plugin_name = $this->getPluginName($package);
$this->rcubeAlterConfig($plugin_name, false);
// run post-uninstall script
$extra = $package->getExtra();
if (!empty($extra['roundcube']['post-uninstall-script'])) {
$this->rcubeRunScript($extra['roundcube']['post-uninstall-script'], $package);
}
}
/**
* {@inheritDoc}
*/
public function supports($packageType)
{
return $packageType === self::INSTALLER_TYPE;
}
/**
* Setup vendor directory to one of these two:
* ./plugins
*
* @return string
*/
public function getVendorDir()
{
$pluginDir = getcwd();
$pluginDir .= '/plugins';
return $pluginDir;
}
/**
* Extract the (valid) plugin name from the package object
*/
private function getPluginName(PackageInterface $package)
{
@list($vendor, $pluginName) = explode('/', $package->getPrettyName());
return strtr($pluginName, '-', '_');
}
/**
* Check version requirements from the "extra" block of a package
* against the local Roundcube version
*/
private function rcubeVersionCheck($package)
{
$parser = new VersionParser;
// read rcube version from iniset
$rootdir = getcwd();
$iniset = @file_get_contents($rootdir . '/program/include/iniset.php');
if (preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z-]*)?/', $iniset, $m)) {
$rcubeVersion = $parser->normalize(str_replace('-git', '.999', $m[1]));
} else {
throw new \Exception("Unable to find a Roundcube installation in $rootdir");
}
$extra = $package->getExtra();
if (!empty($extra['roundcube'])) {
foreach (array('min-version' => '>=', 'max-version' => '<=') as $key => $operator) {
if (!empty($extra['roundcube'][$key])) {
$version = $parser->normalize(str_replace('-git', '.999', $extra['roundcube'][$key]));
$constraint = new VersionConstraint($operator, $version);
if (!$constraint->versionCompare($rcubeVersion, $version, $operator)) {
throw new \Exception("Version check failed! " . $package->getName() . " requires Roundcube version $operator $version, $rcubeVersion was detected.");
}
}
}
}
}
/**
* Add or remove the given plugin to the list of active plugins in the Roundcube config.
*/
private function rcubeAlterConfig($plugin_name, $add)
{
$config_file = $this->rcubeConfigFile();
@include($config_file);
$success = false;
$varname = '$config';
if (empty($config) && !empty($rcmail_config)) {
$config = $rcmail_config;
$varname = '$rcmail_config';
}
if (is_array($config) && is_writeable($config_file)) {
$config_templ = @file_get_contents($config_file) ?: '';
$config_plugins = !empty($config['plugins']) ? ((array) $config['plugins']) : array();
$active_plugins = $config_plugins;
if ($add && !in_array($plugin_name, $active_plugins)) {
$active_plugins[] = $plugin_name;
} elseif (!$add && ($i = array_search($plugin_name, $active_plugins)) !== false) {
unset($active_plugins[$i]);
}
if ($active_plugins != $config_plugins) {
$count = 0;
$var_export = "array(\n\t'" . join("',\n\t'", $active_plugins) . "',\n);";
$new_config = preg_replace(
"/(\\$varname\['plugins'\])\s+=\s+(.+);/Uims",
"\\1 = " . $var_export,
$config_templ, -1, $count);
// 'plugins' option does not exist yet, add it...
if (!$count) {
$var_txt = "\n{$varname}['plugins'] = $var_export;\n";
$new_config = str_replace('?>', $var_txt . '?>', $config_templ, $count);
if (!$count) {
$new_config = $config_templ . $var_txt;
}
}
$success = file_put_contents($config_file, $new_config);
}
}
if ($success && php_sapi_name() == 'cli') {
$this->io->write("<info>Updated local config at $config_file</info>");
}
return $success;
}
/**
* Helper method to get an absolute path to the local Roundcube config file
*/
private function rcubeConfigFile()
{
return realpath(getcwd() . '/config/config.inc.php');
}
/**
* Run the given script file
*/
private function rcubeRunScript($script, PackageInterface $package)
{
@list($vendor, $plugin_name) = explode('/', $package->getPrettyName());
// run executable shell script
if (($scriptfile = realpath($this->getVendorDir() . "/$plugin_name/$script")) && is_executable($scriptfile)) {
system($scriptfile, $res);
}
// run PHP script in Roundcube context
else if ($scriptfile && preg_match('/\.php$/', $scriptfile)) {
$incdir = realpath(getcwd() . '/program/include');
include_once($incdir . '/iniset.php');
include($scriptfile);
}
// attempt to execute the given string as shell commands
else {
$process = new ProcessExecutor();
$exitCode = $process->execute($script);
if ($exitCode !== 0) {
throw new \RuntimeException('Error executing script: '. $process->getErrorOutput(), $exitCode);
}
}
}
}

View File

@@ -0,0 +1,130 @@
#!/usr/bin/env php
<?php
define('INSTALL_PATH', getcwd() . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
// get arguments
$opts = rcube_utils::get_opt(array(
'd' => 'dir',
'p' => 'package',
));
if (empty($opts['dir'])) {
rcube::raise_error("Database schema directory not specified (--dir).", false, true);
}
if (empty($opts['package'])) {
rcube::raise_error("Database schema package name not specified (--package).", false, true);
}
// Check if directory exists
if (!file_exists($opts['dir'])) {
rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}
$RC = rcube::get_instance();
$DB = rcube_db::factory($RC->config->get('db_dsnw'));
// Connect to database
$DB->db_connect('w');
if (!$DB->is_connected()) {
rcube::raise_error("Error connecting to database: " . $DB->is_error(), false, true);
}
$opts['dir'] = rtrim($opts['dir'], DIRECTORY_SEPARATOR);
$file = $opts['dir'] . DIRECTORY_SEPARATOR . $DB->db_provider . '.initial.sql';
if (!file_exists($file)) {
rcube::raise_error("No DDL file found for " . $DB->db_provider . " driver.", false, true);
}
$package = $opts['package'];
$error = false;
// read DDL file
if ($lines = file($file)) {
$sql = '';
foreach ($lines as $line) {
if (preg_match('/^--/', $line) || trim($line) == '')
continue;
$sql .= $line . "\n";
if (preg_match('/(;|^GO)$/', trim($line))) {
@$DB->query(fix_table_names($sql));
$sql = '';
if ($error = $DB->is_error()) {
break;
}
}
}
}
if (!$error) {
$version = date('Ymd00');
$system_table = $DB->quote_identifier($DB->table_name('system'));
$name_col = $DB->quote_identifier('name');
$value_col = $DB->quote_identifier('value');
$package_version = $package . '-version';
$DB->query("SELECT * FROM $system_table WHERE $name_col=?",
$package_version);
if ($DB->fetch_assoc()) {
$DB->query("UPDATE $system_table SET $value_col=? WHERE $name_col=?",
$version, $package_version);
}
else {
$DB->query("INSERT INTO $system_table ($name_col, $value_col) VALUES (?, ?)",
$package_version, $version);
}
$error = $DB->is_error();
}
if ($error) {
echo "[FAILED]\n";
rcube::raise_error("Error in DDL schema $file: $error", false, true);
}
echo "[OK]\n";
function fix_table_names($sql)
{
global $DB, $RC;
$prefix = $RC->config->get('db_prefix');
$engine = $DB->db_provider;
if (empty($prefix)) {
return $sql;
}
$tables = array();
$sequences = array();
// find table names
if (preg_match_all('/CREATE TABLE (\[dbo\]\.|IF NOT EXISTS )?[`"\[\]]*([^`"\[\] \r\n]+)/i', $sql, $matches)) {
foreach ($matches[2] as $table) {
$tables[$table] = $prefix . $table;
}
}
// find sequence names
if ($engine == 'postgres' && preg_match_all('/CREATE SEQUENCE (IF NOT EXISTS )?"?([^" \n\r]+)/i', $sql, $matches)) {
foreach ($matches[2] as $sequence) {
$sequences[$sequence] = $prefix . $sequence;
}
}
// replace table names
foreach ($tables as $table => $real_table) {
$sql = preg_replace("/([^a-zA-Z0-9_])$table([^a-zA-Z0-9_])/", "\\1$real_table\\2", $sql);
}
// replace sequence names
foreach ($sequences as $sequence => $real_sequence) {
$sql = preg_replace("/([^a-zA-Z0-9_])$sequence([^a-zA-Z0-9_])/", "\\1$real_sequence\\2", $sql);
}
return $sql;
}
?>