mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-03-19 19:28:15 +08:00
Experimental support for wildcards in the domain name.
This commit is contained in:
parent
ab07d102f9
commit
93e09effba
5 changed files with 276 additions and 253 deletions
|
@ -22,6 +22,8 @@ function PopupsDomainViewModel()
|
|||
this.smtpServerFocus = ko.observable(false);
|
||||
|
||||
this.name = ko.observable('');
|
||||
this.name.focused = ko.observable(false);
|
||||
|
||||
this.imapServer = ko.observable('');
|
||||
this.imapPort = ko.observable(Consts.Values.ImapDefaulPort);
|
||||
this.imapSecure = ko.observable(Enums.ServerSecure.None);
|
||||
|
@ -36,7 +38,7 @@ function PopupsDomainViewModel()
|
|||
this.imapServerFocus.subscribe(function (bValue) {
|
||||
if (bValue && '' !== this.name() && '' === this.imapServer())
|
||||
{
|
||||
this.imapServer(this.name());
|
||||
this.imapServer(this.name().replace(/[.]?[*][.]?/g, ''));
|
||||
}
|
||||
}, this);
|
||||
|
||||
|
@ -186,6 +188,14 @@ PopupsDomainViewModel.prototype.onShow = function (oDomain)
|
|||
}
|
||||
};
|
||||
|
||||
PopupsDomainViewModel.prototype.onFocus = function ()
|
||||
{
|
||||
if ('' === this.name())
|
||||
{
|
||||
this.name.focused(true);
|
||||
}
|
||||
};
|
||||
|
||||
PopupsDomainViewModel.prototype.onBuild = function ()
|
||||
{
|
||||
var self = this;
|
||||
|
@ -208,6 +218,8 @@ PopupsDomainViewModel.prototype.clearForm = function ()
|
|||
this.savingError('');
|
||||
|
||||
this.name('');
|
||||
this.name.focused(false);
|
||||
|
||||
this.imapServer('');
|
||||
this.imapPort(Consts.Values.ImapDefaulPort);
|
||||
this.imapSecure(Enums.ServerSecure.None);
|
||||
|
|
|
@ -1,247 +1,246 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Domain;
|
||||
|
||||
class DefaultDomain implements \RainLoop\Providers\Domain\DomainAdminInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $sDomainPath;
|
||||
|
||||
/**
|
||||
* @param string $sDomainPath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sDomainPath)
|
||||
{
|
||||
$this->sDomainPath = \rtrim(\trim($sDomainPath), '\\/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bBack = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function codeFileName($sName, $bBack = false)
|
||||
{
|
||||
if ($bBack && 'default' === $sName)
|
||||
{
|
||||
return '*';
|
||||
}
|
||||
else if (!$bBack && '*' === $sName)
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
$sName = \strtolower($sName);
|
||||
return $bBack ? \str_replace('_wildcard_', '*', $sName) : \str_replace('*', '_wildcard_', $sName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bDisable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Disable($sName, $bDisable)
|
||||
{
|
||||
$sFile = '';
|
||||
if (\file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sFile = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
}
|
||||
|
||||
$aResult = array();
|
||||
$aNames = \explode(',', $sFile);
|
||||
if ($bDisable)
|
||||
{
|
||||
\array_push($aNames, $sName);
|
||||
$aResult = $aNames;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($aNames as $sItem)
|
||||
{
|
||||
if ($sName !== $sItem)
|
||||
{
|
||||
$aResult[] = $sItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aResult = \array_unique($aResult);
|
||||
return false !== \file_put_contents($this->sDomainPath.'/disabled', \trim(\implode(',', $aResult), ', '));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bFindWithWildCard = false
|
||||
*
|
||||
* @return \RainLoop\Domain | null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false)
|
||||
{
|
||||
$mResult = null;
|
||||
$sName = \strtolower($sName);
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$mResult = \RainLoop\Domain::NewInstanceFromDomainConfigArray(
|
||||
$sName, @\parse_ini_file($this->sDomainPath.'/'.$sRealFileName.'.ini'));
|
||||
|
||||
if ($mResult instanceof \RainLoop\Domain)
|
||||
{
|
||||
if (\file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sDisabled = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
if (false !== $sDisabled && 0 < \strlen($sDisabled))
|
||||
{
|
||||
$mResult->SetDisabled(false !== \strpos(strtolower(','.$sDisabled.','), \strtolower(','.$sName.',')));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($bFindWithWildCard)
|
||||
{
|
||||
// TODO
|
||||
// $sNames = '';
|
||||
// $aNames = array();
|
||||
//
|
||||
// $aList = \glob($this->sDomainPath.'/*.ini');
|
||||
// foreach ($aList as $sFile)
|
||||
// {
|
||||
// $sName = \strtolower(\substr(\basename($sFile), 0, -4));
|
||||
// if ('default' === $sName || false !== strpos($sName, '_wildcard_'))
|
||||
// {
|
||||
// $aNames[] = $this->codeFileName($sName, true);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (0 < \count($aNames))
|
||||
// {
|
||||
// \rsort($sNames, SORT_STRING);
|
||||
// $sNames = \implode(' ', $aNames);
|
||||
// }
|
||||
//
|
||||
// if (0 < \strlen($sNames))
|
||||
// {
|
||||
// $sFoundedValue = '';
|
||||
// if (\RainLoop\Plugins\Helper::ValidateWildcardValues($sName, $sNames, $sFoundedValue) && 0 < \strlen($sFoundedValue))
|
||||
// {
|
||||
// $mResult = $this->Load($sFoundedValue, false);
|
||||
// }
|
||||
// }
|
||||
|
||||
$mResult = $this->Load('default', false);
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Domain $oDomain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save(\RainLoop\Domain $oDomain)
|
||||
{
|
||||
$sName = \strtolower($oDomain->Name());
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
$mResult = \file_put_contents($this->sDomainPath.'/'.$sRealFileName.'.ini', $oDomain->ToIniString());
|
||||
return \is_int($mResult) && 0 < $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName)
|
||||
{
|
||||
$bResult = true;
|
||||
$sName = \strtolower($sName);
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (0 < \strlen($sName) && \file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.ini');
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
{
|
||||
$this->Disable($sName, false);
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iOffset
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset, $iLimit = 20)
|
||||
{
|
||||
$aResult = array();
|
||||
$aWildCards = array();
|
||||
$aList = \glob($this->sDomainPath.'/*.ini');
|
||||
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = \strtolower(\substr(\basename($sFile), 0, -4));
|
||||
$sName = $this->codeFileName($sName, true);
|
||||
if (false === \strpos($sName, '*'))
|
||||
{
|
||||
$aResult[] = $sName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aWildCards[] = $sName;
|
||||
}
|
||||
}
|
||||
|
||||
\sort($aResult, SORT_STRING);
|
||||
\rsort($aWildCards, SORT_STRING);
|
||||
|
||||
$aResult = \array_merge($aResult, $aWildCards);
|
||||
|
||||
$iOffset = (0 > $iOffset) ? 0 : $iOffset;
|
||||
$iLimit = (0 > $iLimit) ? 0 : ((999 < $iLimit) ? 999 : $iLimit);
|
||||
|
||||
$aResult = \array_slice($aResult, $iOffset, $iLimit);
|
||||
|
||||
$aDisabledNames = array();
|
||||
if (0 < \count($aResult) && \file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sDisabled = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
if (false !== $sDisabled && 0 < strlen($sDisabled))
|
||||
{
|
||||
$aDisabledNames = \explode(',', strtolower($sDisabled));
|
||||
$aDisabledNames = \array_unique($aDisabledNames);
|
||||
}
|
||||
}
|
||||
|
||||
$aReturn = array();
|
||||
foreach ($aResult as $sName)
|
||||
{
|
||||
$aReturn[$sName] = !\in_array(\strtolower($sName), $aDisabledNames);
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch = ''
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function Count()
|
||||
{
|
||||
return \count($this->GetList(0, 999));
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Domain;
|
||||
|
||||
class DefaultDomain implements \RainLoop\Providers\Domain\DomainAdminInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $sDomainPath;
|
||||
|
||||
/**
|
||||
* @param string $sDomainPath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sDomainPath)
|
||||
{
|
||||
$this->sDomainPath = \rtrim(\trim($sDomainPath), '\\/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bBack = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function codeFileName($sName, $bBack = false)
|
||||
{
|
||||
if ($bBack && 'default' === $sName)
|
||||
{
|
||||
return '*';
|
||||
}
|
||||
else if (!$bBack && '*' === $sName)
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
$sName = \strtolower($sName);
|
||||
return $bBack ? \str_replace('_wildcard_', '*', $sName) : \str_replace('*', '_wildcard_', $sName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bDisable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Disable($sName, $bDisable)
|
||||
{
|
||||
$sFile = '';
|
||||
if (\file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sFile = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
}
|
||||
|
||||
$aResult = array();
|
||||
$aNames = \explode(',', $sFile);
|
||||
if ($bDisable)
|
||||
{
|
||||
\array_push($aNames, $sName);
|
||||
$aResult = $aNames;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($aNames as $sItem)
|
||||
{
|
||||
if ($sName !== $sItem)
|
||||
{
|
||||
$aResult[] = $sItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aResult = \array_unique($aResult);
|
||||
return false !== \file_put_contents($this->sDomainPath.'/disabled', \trim(\implode(',', $aResult), ', '));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bFindWithWildCard = false
|
||||
*
|
||||
* @return \RainLoop\Domain | null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false)
|
||||
{
|
||||
$mResult = null;
|
||||
|
||||
$sName = \strtolower($sName);
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$mResult = \RainLoop\Domain::NewInstanceFromDomainConfigArray(
|
||||
$sName, @\parse_ini_file($this->sDomainPath.'/'.$sRealFileName.'.ini'));
|
||||
}
|
||||
else if ($bFindWithWildCard)
|
||||
{
|
||||
$sNames = '';
|
||||
$aNames = array();
|
||||
|
||||
$aList = \glob($this->sDomainPath.'/*.ini');
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = \strtolower(\substr(\basename($sFile), 0, -4));
|
||||
if ('default' === $sName || false !== strpos($sName, '_wildcard_'))
|
||||
{
|
||||
$aNames[] = $this->codeFileName($sName, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < \count($aNames))
|
||||
{
|
||||
\rsort($aNames, SORT_STRING);
|
||||
$sNames = \implode(' ', $aNames);
|
||||
}
|
||||
|
||||
if (0 < \strlen($sNames))
|
||||
{
|
||||
$sFoundedValue = '';
|
||||
if (\RainLoop\Plugins\Helper::ValidateWildcardValues($sName, $sNames, $sFoundedValue) && 0 < \strlen($sFoundedValue))
|
||||
{
|
||||
$mResult = $this->Load($sFoundedValue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($mResult instanceof \RainLoop\Domain)
|
||||
{
|
||||
if (\file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sDisabled = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
if (false !== $sDisabled && 0 < \strlen($sDisabled))
|
||||
{
|
||||
$mResult->SetDisabled(false !== \strpos(strtolower(','.$sDisabled.','), \strtolower(','.$sName.',')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Domain $oDomain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save(\RainLoop\Domain $oDomain)
|
||||
{
|
||||
$sName = \strtolower($oDomain->Name());
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
$mResult = \file_put_contents($this->sDomainPath.'/'.$sRealFileName.'.ini', $oDomain->ToIniString());
|
||||
return \is_int($mResult) && 0 < $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName)
|
||||
{
|
||||
$bResult = true;
|
||||
$sName = \strtolower($sName);
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (0 < \strlen($sName) && \file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.ini');
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
{
|
||||
$this->Disable($sName, false);
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iOffset
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset, $iLimit = 20)
|
||||
{
|
||||
$aResult = array();
|
||||
$aWildCards = array();
|
||||
$aList = \glob($this->sDomainPath.'/*.ini');
|
||||
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = \strtolower(\substr(\basename($sFile), 0, -4));
|
||||
$sName = $this->codeFileName($sName, true);
|
||||
if (false === \strpos($sName, '*'))
|
||||
{
|
||||
$aResult[] = $sName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aWildCards[] = $sName;
|
||||
}
|
||||
}
|
||||
|
||||
\sort($aResult, SORT_STRING);
|
||||
\rsort($aWildCards, SORT_STRING);
|
||||
|
||||
$aResult = \array_merge($aResult, $aWildCards);
|
||||
|
||||
$iOffset = (0 > $iOffset) ? 0 : $iOffset;
|
||||
$iLimit = (0 > $iLimit) ? 0 : ((999 < $iLimit) ? 999 : $iLimit);
|
||||
|
||||
$aResult = \array_slice($aResult, $iOffset, $iLimit);
|
||||
|
||||
$aDisabledNames = array();
|
||||
if (0 < \count($aResult) && \file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sDisabled = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
if (false !== $sDisabled && 0 < strlen($sDisabled))
|
||||
{
|
||||
$aDisabledNames = \explode(',', strtolower($sDisabled));
|
||||
$aDisabledNames = \array_unique($aDisabledNames);
|
||||
}
|
||||
}
|
||||
|
||||
$aReturn = array();
|
||||
foreach ($aResult as $sName)
|
||||
{
|
||||
$aReturn[$sName] = !\in_array(\strtolower($sName), $aDisabledNames);
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch = ''
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function Count()
|
||||
{
|
||||
return \count($this->GetList(0, 999));
|
||||
}
|
||||
}
|
|
@ -8,9 +8,9 @@
|
|||
<form class="form-horizontal domain-form" action="#/" onsubmit="return false;">
|
||||
<div class="row" data-bind="visible: !edit()">
|
||||
<div class="span8">
|
||||
Name
|
||||
Name <span style="color: #aaa">(wildcard supported)</span>
|
||||
<br />
|
||||
<input type="text" data-bind="value: name, valueUpdate: 'afterkeydown'" />
|
||||
<input type="text" data-bind="value: name, hasfocus: name.focused, valueUpdate: 'afterkeydown'" />
|
||||
<span class="error-desc" data-bind="text: savingError"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,7 +87,7 @@
|
|||
List of users webmail is allowed to access.
|
||||
Use a space as delimiter.
|
||||
</div>
|
||||
<textarea class="input-xxlarge" style="width: 600px" rows="8" data-bind="value: whiteList"></textarea>
|
||||
<textarea class="input-xxlarge" style="width: 600px" rows="8" data-bind="value: whiteList" tabindex="-1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -4498,6 +4498,8 @@ function PopupsDomainViewModel()
|
|||
this.smtpServerFocus = ko.observable(false);
|
||||
|
||||
this.name = ko.observable('');
|
||||
this.name.focused = ko.observable(false);
|
||||
|
||||
this.imapServer = ko.observable('');
|
||||
this.imapPort = ko.observable(Consts.Values.ImapDefaulPort);
|
||||
this.imapSecure = ko.observable(Enums.ServerSecure.None);
|
||||
|
@ -4512,7 +4514,7 @@ function PopupsDomainViewModel()
|
|||
this.imapServerFocus.subscribe(function (bValue) {
|
||||
if (bValue && '' !== this.name() && '' === this.imapServer())
|
||||
{
|
||||
this.imapServer(this.name());
|
||||
this.imapServer(this.name().replace(/[.]?[*][.]?/g, ''));
|
||||
}
|
||||
}, this);
|
||||
|
||||
|
@ -4662,6 +4664,14 @@ PopupsDomainViewModel.prototype.onShow = function (oDomain)
|
|||
}
|
||||
};
|
||||
|
||||
PopupsDomainViewModel.prototype.onFocus = function ()
|
||||
{
|
||||
if ('' === this.name())
|
||||
{
|
||||
this.name.focused(true);
|
||||
}
|
||||
};
|
||||
|
||||
PopupsDomainViewModel.prototype.onBuild = function ()
|
||||
{
|
||||
var self = this;
|
||||
|
@ -4684,6 +4694,8 @@ PopupsDomainViewModel.prototype.clearForm = function ()
|
|||
this.savingError('');
|
||||
|
||||
this.name('');
|
||||
this.name.focused(false);
|
||||
|
||||
this.imapServer('');
|
||||
this.imapPort(Consts.Values.ImapDefaulPort);
|
||||
this.imapSecure(Enums.ServerSecure.None);
|
||||
|
|
4
rainloop/v/0.0.0/static/js/admin.min.js
vendored
4
rainloop/v/0.0.0/static/js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue