mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Release plugins as tar.gz because PharData is more common then ZipArchive
This commit is contained in:
parent
756bf86640
commit
b9b0a550d6
47 changed files with 214 additions and 159 deletions
|
|
@ -1 +0,0 @@
|
||||||
1.2
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class AddXOriginatingIpHeaderPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class AddXOriginatingIpHeaderPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'X-Originating-IP',
|
||||||
|
VERSION = '2.0',
|
||||||
|
DESCRIPTION = 'Adds X-Originating-IP header to outgoing message, containing sender\'s IP address.';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.build-message', 'FilterBuildMessage');
|
$this->addHook('filter.build-message', 'FilterBuildMessage');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.1
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
|
|
||||||
class AutoDomainGrabPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class AutoDomainGrabPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
private $imap_prefix = "mail.";
|
private $imap_prefix = "mail.";
|
||||||
private $smtp_prefix = "mail.";
|
private $smtp_prefix = "mail.";
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
class BlackListPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class BlackListPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'Black list',
|
||||||
|
VERSION = '2.0',
|
||||||
|
CATEGORY = 'Login',
|
||||||
|
DESCRIPTION = 'Simple black list plugin (with wildcard and exceptions functionality).';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.login-credentials', 'FilterLoginCredentials');
|
$this->addHook('filter.login-credentials', 'FilterLoginCredentials');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class ChangeSmtpEhloMessagePlugin extends \RainLoop\Plugins\AbstractPlugin
|
class ChangeSmtpEhloMessagePlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.smtp-credentials', 'FilterSmtpCredentials');
|
$this->addHook('filter.smtp-credentials', 'FilterSmtpCredentials');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
0.1
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class ContactGroupExcelPastePlugin extends \RainLoop\Plugins\AbstractPlugin
|
class ContactGroupExcelPastePlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addJs('js/excel_contact_group.js');
|
$this->addJs('js/excel_contact_group.js');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class ContactsSuggestionsExamplePlugin extends \RainLoop\Plugins\AbstractPlugin
|
class ContactsSuggestionsExamplePlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('main.fabrica', 'MainFabrica');
|
$this->addHook('main.fabrica', 'MainFabrica');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class CustomAdminSettingsTabPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class CustomAdminSettingsTabPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class CustomAuthExamplePlugin extends \RainLoop\Plugins\AbstractPlugin
|
class CustomAuthExamplePlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'Login',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.login-credentials', 'FilterLoginСredentials');
|
$this->addHook('filter.login-credentials', 'FilterLoginСredentials');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
class CustomLoginMappingPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class CustomLoginMappingPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'Custom Login Mapping',
|
||||||
|
VERSION = '2.0',
|
||||||
|
CATEGORY = 'Login',
|
||||||
|
DESCRIPTION = 'Plugin which allows you to set up custom username by email address.';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.login-credentials', 'FilterLoginСredentials');
|
$this->addHook('filter.login-credentials', 'FilterLoginСredentials');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.1
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class CustomSettingsTabPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class CustomSettingsTabPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class CustomSystemFoldersPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class CustomSystemFoldersPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class DemoAccountPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class DemoAccountPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'Login',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2013 https://github.com/sharq88
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add ability to paste multi row email addresses from excel.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
0.1
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
class ParseExcelListPlugin extends \RainLoop\Plugins\AbstractPlugin
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function Init() : void
|
|
||||||
{
|
|
||||||
$this->addJs('js/parse_excel_list.js'); // add js file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
(function(window, $) {
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$(window.document).on('keyup', '.b-compose .b-header .inputosaurus-input input[type="text"]:first', function() {
|
|
||||||
|
|
||||||
var
|
|
||||||
$this = $(this),
|
|
||||||
value = $this.val()
|
|
||||||
;
|
|
||||||
|
|
||||||
if (value && value.match(/@/ig).length >= 2)
|
|
||||||
{
|
|
||||||
$this.val($this.val().replace(/\n| /ig, ','));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}(window, $))
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.1
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'Contacts suggestions (LDAP)',
|
||||||
|
VERSION = '2.0',
|
||||||
|
CATEGORY = 'Security',
|
||||||
|
DESCRIPTION = 'Plugin that adds functionality to get contacts from LDAP on compose page.';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('main.fabrica', 'MainFabrica');
|
$this->addHook('main.fabrica', 'MainFabrica');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -6,6 +6,16 @@ use RainLoop\Plugins\Property;
|
||||||
|
|
||||||
class LdapIdentitiesPlugin extends AbstractPlugin
|
class LdapIdentitiesPlugin extends AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'LDAP Identities',
|
||||||
|
VERSION = '2.0',
|
||||||
|
AUTHOR = 'FWest98',
|
||||||
|
URL = 'https://github.com/FWest98',
|
||||||
|
RELEASE = '2020-11-11',
|
||||||
|
REQUIRED = '2.1.0',
|
||||||
|
CATEGORY = 'Accounts',
|
||||||
|
DESCRIPTION = 'Plugin that adds functionality to import account identities from LDAP.';
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
include_once __DIR__ . '/LdapIdentities.php';
|
include_once __DIR__ . '/LdapIdentities.php';
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
class OverrideSmtpCredentialsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class OverrideSmtpCredentialsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'Override Smtp Credentials',
|
||||||
|
VERSION = '2.0',
|
||||||
|
CATEGORY = 'Filters',
|
||||||
|
DESCRIPTION = 'Plugin which allows you to override smtp credentials specified users.';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.smtp-credentials', 'FilterSmtpCredentials');
|
$this->addHook('filter.smtp-credentials', 'FilterSmtpCredentials');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
class ProxyauthLoginExamplePlugin extends \RainLoop\Plugins\AbstractPlugin
|
class ProxyauthLoginExamplePlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('event.login-post-login-provide', 'EventLoginPostLoginProvide');
|
$this->addHook('event.login-post-login-provide', 'EventLoginPostLoginProvide');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.1
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
class SnowfallOnLoginScreenPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class SnowfallOnLoginScreenPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'Snowfall on login screen',
|
||||||
|
VERSION = '2.0',
|
||||||
|
CATEGORY = 'Fun',
|
||||||
|
DESCRIPTION = 'Snowfall on login screen plugin (just for fun).';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addJs('js/snowfall.js');
|
$this->addJs('js/snowfall.js');
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
1.0
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
class WhiteListPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class WhiteListPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = 'White list',
|
||||||
|
VERSION = '2.0',
|
||||||
|
CATEGORY = 'Login',
|
||||||
|
DESCRIPTION = 'Simple white list plugin (with wildcard and exceptions functionality).';
|
||||||
|
|
||||||
public function Init() : void
|
public function Init() : void
|
||||||
{
|
{
|
||||||
$this->addHook('filter.login-credentials', 'FilterLoginCredentials');
|
$this->addHook('filter.login-credentials', 'FilterLoginCredentials');
|
||||||
|
|
|
||||||
50
release.php
50
release.php
|
|
@ -2,6 +2,54 @@
|
||||||
<?php
|
<?php
|
||||||
chdir(__DIR__);
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
$options = getopt('', ['aur','docker','plugins']);
|
||||||
|
|
||||||
|
if (isset($options['plugins'])) {
|
||||||
|
$destPath = "build/dist/releases/plugins/";
|
||||||
|
is_dir($destPath) || mkdir($destPath, 0777, true);
|
||||||
|
$manifest = [];
|
||||||
|
require 'snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php';
|
||||||
|
foreach (glob('plugins/*', GLOB_NOSORT | GLOB_ONLYDIR) as $dir) {
|
||||||
|
require "{$dir}/index.php";
|
||||||
|
$name = basename($dir);
|
||||||
|
$class = new ReflectionClass(str_replace('-', '', $name) . 'Plugin');
|
||||||
|
$manifest_item = [];
|
||||||
|
foreach ($class->getConstants() as $key => $value) {
|
||||||
|
$manifest_item[\strtolower($key)] = $value;
|
||||||
|
}
|
||||||
|
$version = $manifest_item['version'];
|
||||||
|
if (0 < floatval($version)) {
|
||||||
|
echo "+ {$name} {$version}\n";
|
||||||
|
$manifest_item['type'] = 'plugin';
|
||||||
|
$manifest_item['id'] = $name;
|
||||||
|
$manifest_item['file'] = "{$dir}-{$version}.tgz";
|
||||||
|
ksort($manifest_item);
|
||||||
|
$manifest[$name] = $manifest_item;
|
||||||
|
$tar_destination = "{$destPath}{$name}-{$version}.tar";
|
||||||
|
$tgz_destination = "{$destPath}{$name}-{$version}.tgz";
|
||||||
|
@unlink($tgz_destination);
|
||||||
|
@unlink("{$tar_destination}.gz");
|
||||||
|
$tar = new PharData($tar_destination);
|
||||||
|
$tar->buildFromDirectory('./plugins/', "@{$name}@");
|
||||||
|
$tar->compress(Phar::GZ);
|
||||||
|
unlink($tar_destination);
|
||||||
|
rename("{$tar_destination}.gz", $tgz_destination);
|
||||||
|
} else {
|
||||||
|
echo "- {$name} {$version}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($manifest);
|
||||||
|
$manifest = json_encode(array_values($manifest));
|
||||||
|
$manifest = str_replace('{"', "\n\t{\n\t\t\"", $manifest);
|
||||||
|
$manifest = str_replace('"}', "\"\n\t}", $manifest);
|
||||||
|
$manifest = str_replace('}]', "}\n]", $manifest);
|
||||||
|
$manifest = str_replace('","', "\",\n\t\t\"", $manifest);
|
||||||
|
$manifest = str_replace('\/', '/', $manifest);
|
||||||
|
file_put_contents("{$destPath}packages.json", $manifest);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
$gulp = trim(`which gulp`);
|
$gulp = trim(`which gulp`);
|
||||||
if (!$gulp) {
|
if (!$gulp) {
|
||||||
exit('gulp not installed, run as root: npm install --global gulp-cli');
|
exit('gulp not installed, run as root: npm install --global gulp-cli');
|
||||||
|
|
@ -12,8 +60,6 @@ if (!$rollup) {
|
||||||
exit('rollup not installed, run as root: npm install --global rollup');
|
exit('rollup not installed, run as root: npm install --global rollup');
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = getopt('', ['aur','docker']);
|
|
||||||
|
|
||||||
// Arch User Repository
|
// Arch User Repository
|
||||||
// https://aur.archlinux.org/packages/snappymail/
|
// https://aur.archlinux.org/packages/snappymail/
|
||||||
$options['aur'] = isset($options['aur']);
|
$options['aur'] = isset($options['aur']);
|
||||||
|
|
|
||||||
|
|
@ -989,7 +989,7 @@ class Actions
|
||||||
|
|
||||||
$aAttachmentsActions = array();
|
$aAttachmentsActions = array();
|
||||||
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::ATTACHMENTS_ACTIONS)) {
|
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::ATTACHMENTS_ACTIONS)) {
|
||||||
if (!!\class_exists('ZipArchive')) {
|
if (\class_exists('ZipArchive')) {
|
||||||
$aAttachmentsActions[] = 'zip';
|
$aAttachmentsActions[] = 'zip';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,14 +489,14 @@ trait Admin
|
||||||
|
|
||||||
private function snappyMailRepo() : string
|
private function snappyMailRepo() : string
|
||||||
{
|
{
|
||||||
return 'https://snappymail.eu/repository/';
|
return 'https://snappymail.eu/repository/v2/';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function rainLoopUpdatable() : bool
|
private function rainLoopUpdatable() : bool
|
||||||
{
|
{
|
||||||
return file_exists(APP_INDEX_ROOT_PATH.'index.php') &&
|
return \file_exists(APP_INDEX_ROOT_PATH.'index.php') &&
|
||||||
is_writable(APP_INDEX_ROOT_PATH.'index.php') &&
|
\is_writable(APP_INDEX_ROOT_PATH.'index.php') &&
|
||||||
is_writable(APP_INDEX_ROOT_PATH.'snappymail/') &&
|
\is_writable(APP_INDEX_ROOT_PATH.'snappymail/') &&
|
||||||
APP_VERSION !== APP_DEV_VERSION
|
APP_VERSION !== APP_DEV_VERSION
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
@ -684,23 +684,23 @@ trait Admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$bResult = false;
|
$bResult = '' !== $sResultId && static::deletePackageDir($sResultId);
|
||||||
if ('' !== $sResultId)
|
if ($bResult) {
|
||||||
{
|
$this->pluginEnable($sResultId, false);
|
||||||
$bResult = \MailSo\Base\Utils::RecRmDir(APP_PLUGINS_PATH.$sResultId);
|
|
||||||
if ($bResult)
|
|
||||||
{
|
|
||||||
$this->pluginEnable($sResultId, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->DefaultResponse(__FUNCTION__, $bResult);
|
return $this->DefaultResponse(__FUNCTION__, $bResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function deletePackageDir(string $sId) : bool
|
||||||
|
{
|
||||||
|
return !\is_dir(APP_PLUGINS_PATH.$sId) || \MailSo\Base\Utils::RecRmDir(APP_PLUGINS_PATH.$sId);
|
||||||
|
}
|
||||||
|
|
||||||
private function downloadRemotePackageByUrl(string $sUrl) : string
|
private function downloadRemotePackageByUrl(string $sUrl) : string
|
||||||
{
|
{
|
||||||
$bResult = false;
|
$bResult = false;
|
||||||
$sTmp = APP_PRIVATE_DATA.\md5(\microtime(true).$sUrl).'.zip';
|
$sTmp = APP_PRIVATE_DATA.\md5(\microtime(true).$sUrl) . \substr($sUrl, -4);
|
||||||
$pDest = \fopen($sTmp, 'w+b');
|
$pDest = \fopen($sTmp, 'w+b');
|
||||||
if ($pDest)
|
if ($pDest)
|
||||||
{
|
{
|
||||||
|
|
@ -757,40 +757,19 @@ trait Admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sTmp = '';
|
|
||||||
$bResult = false;
|
$bResult = false;
|
||||||
if ('' !== $sRealFile)
|
$sTmp = $sRealFile ? $this->downloadRemotePackageByUrl($this->snappyMailRepo().$sRealFile) : null;
|
||||||
|
if ($sTmp)
|
||||||
{
|
{
|
||||||
$sTmp = $this->downloadRemotePackageByUrl($this->snappyMailRepo().$sRealFile);
|
$oArchive = new \PharData($sTmp, 0, $sRealFile);
|
||||||
}
|
if (!\is_dir(APP_PLUGINS_PATH.$sId) || static::deletePackageDir($sId)) {
|
||||||
|
$bResult = $oArchive->extractTo(APP_PLUGINS_PATH);
|
||||||
if ('' !== $sTmp)
|
if (!$bResult) {
|
||||||
{
|
$this->Logger()->Write('Cannot extract package files: '.$oArchive->getStatusString(), \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||||
$oArchive = new \ZipArchive();
|
|
||||||
$oArchive->open($sTmp);
|
|
||||||
if ('plugin' === $sType)
|
|
||||||
{
|
|
||||||
$bResult = true;
|
|
||||||
if (\is_dir(APP_PLUGINS_PATH.$sId))
|
|
||||||
{
|
|
||||||
$bResult = \MailSo\Base\Utils::RecRmDir(APP_PLUGINS_PATH.$sId);
|
|
||||||
if (!$bResult)
|
|
||||||
{
|
|
||||||
$this->Logger()->Write('Cannot remove previous plugin folder: '.$sId, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($bResult)
|
|
||||||
{
|
|
||||||
$bResult = $oArchive->extractTo(APP_PLUGINS_PATH);
|
|
||||||
if (!$bResult)
|
|
||||||
{
|
|
||||||
$this->Logger()->Write('Cannot extract package files: '.$oArchive->getStatusString(), \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->Logger()->Write('Cannot remove previous plugin folder: '.$sId, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||||
}
|
}
|
||||||
$oArchive->close();
|
|
||||||
|
|
||||||
\unlink($sTmp);
|
\unlink($sTmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,17 @@ namespace RainLoop\Plugins;
|
||||||
|
|
||||||
abstract class AbstractPlugin
|
abstract class AbstractPlugin
|
||||||
{
|
{
|
||||||
|
const
|
||||||
|
NAME = '',
|
||||||
|
AUTHOR = 'SnappyMail',
|
||||||
|
URL = 'https://snappymail.eu/',
|
||||||
|
VERSION = '0.0',
|
||||||
|
RELEASE = '2020-11-01',
|
||||||
|
REQUIRED = '2.0.0',
|
||||||
|
CATEGORY = 'General',
|
||||||
|
LICENSE = 'MIT',
|
||||||
|
DESCRIPTION = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \RainLoop\Plugins\Manager
|
* @var \RainLoop\Plugins\Manager
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -112,35 +112,17 @@ class Manager
|
||||||
public function CreatePluginByName(string $sName) : ?\RainLoop\Plugins\AbstractPlugin
|
public function CreatePluginByName(string $sName) : ?\RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
$oPlugin = null;
|
$oPlugin = null;
|
||||||
if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
|
|
||||||
\file_exists(APP_PLUGINS_PATH.$sName.'/index.php'))
|
|
||||||
{
|
|
||||||
$sClassName = $this->convertPluginFolderNameToClassName($sName);
|
|
||||||
|
|
||||||
if (!\class_exists($sClassName))
|
$sClassName = $this->loadPluginByName($sName);
|
||||||
{
|
if ($sClassName) {
|
||||||
include APP_PLUGINS_PATH.$sName.'/index.php';
|
$oPlugin = new $sClassName();
|
||||||
}
|
$oPlugin
|
||||||
|
->SetName($sName)
|
||||||
if (\class_exists($sClassName))
|
->SetPath(APP_PLUGINS_PATH.$sName)
|
||||||
{
|
->SetVersion($sClassName::VERSION)
|
||||||
$oPlugin = new $sClassName();
|
->SetPluginManager($this)
|
||||||
if ($oPlugin instanceof \RainLoop\Plugins\AbstractPlugin)
|
->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap()))
|
||||||
{
|
;
|
||||||
$oPlugin
|
|
||||||
->SetName($sName)
|
|
||||||
->SetPath(APP_PLUGINS_PATH.$sName)
|
|
||||||
->SetVersion(\file_exists(APP_PLUGINS_PATH.$sName.'/VERSION') ?
|
|
||||||
\file_get_contents(APP_PLUGINS_PATH.$sName.'/VERSION') : '')
|
|
||||||
->SetPluginManager($this)
|
|
||||||
->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap()))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$oPlugin = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $oPlugin;
|
return $oPlugin;
|
||||||
|
|
@ -156,15 +138,11 @@ class Manager
|
||||||
foreach ($aGlob as $sPathName)
|
foreach ($aGlob as $sPathName)
|
||||||
{
|
{
|
||||||
$sName = \basename($sPathName);
|
$sName = \basename($sPathName);
|
||||||
if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
|
$sClassName = $this->loadPluginByName($sName);
|
||||||
\file_exists($sPathName.'/index.php'))
|
$aList[] = array(
|
||||||
{
|
$sName,
|
||||||
$aList[] = array(
|
$sClassName::VERSION
|
||||||
$sName,
|
);
|
||||||
\file_exists($sPathName.'/VERSION') ?
|
|
||||||
\file_get_contents($sPathName.'/VERSION') : '0.0'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -184,6 +162,21 @@ class Manager
|
||||||
return \implode($aParts).'Plugin';
|
return \implode($aParts).'Plugin';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function loadPluginByName(string $sName) : ?string
|
||||||
|
{
|
||||||
|
if (\preg_match('/^[a-z0-9\-]+$/', $sName)
|
||||||
|
&& \file_exists(APP_PLUGINS_PATH.$sName.'/index.php'))
|
||||||
|
{
|
||||||
|
$sClassName = $this->convertPluginFolderNameToClassName($sName);
|
||||||
|
if (!\class_exists($sClassName)) {
|
||||||
|
include APP_PLUGINS_PATH.$sName.'/index.php';
|
||||||
|
}
|
||||||
|
if (\class_exists($sClassName) && \is_subclass_of($sClassName, 'RainLoop\\Plugins\\AbstractPlugin')) {
|
||||||
|
return $sClassName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function Actions() : \RainLoop\Actions
|
public function Actions() : \RainLoop\Actions
|
||||||
{
|
{
|
||||||
return $this->oActions;
|
return $this->oActions;
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a class="btn" data-bind="command: saveNewAdminPasswordCommand, css: { 'btn-success': adminPasswordUpdateSuccess, 'btn-danger': adminPasswordUpdateError }">
|
<a class="btn" data-bind="command: saveNewAdminPasswordCommand, css: { 'btn-success': adminPasswordUpdateSuccess, 'btn-danger': adminPasswordUpdateError }">
|
||||||
<i class="fontastic" data-bind="css: {'icon-white': adminPasswordUpdateSuccess() || adminPasswordUpdateError() }">🔑></i>
|
<i class="fontastic" data-bind="css: {'icon-white': adminPasswordUpdateSuccess() || adminPasswordUpdateError() }">🔑</i>
|
||||||
<span data-i18n="TAB_SECURITY/BUTTON_UPDATE_PASSWORD"></span>
|
<span data-i18n="TAB_SECURITY/BUTTON_UPDATE_PASSWORD"></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue