mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-30 20:49:20 +03:00
Handle Domain::$name as lowercase punycode due to IDN complexity
This commit is contained in:
parent
56ede16833
commit
7999894bda
7 changed files with 89 additions and 129 deletions
|
|
@ -115,11 +115,10 @@ class Http
|
|||
if (!\strlen($sHost)) {
|
||||
$sName = static::GetServer('SERVER_NAME', '');
|
||||
$iPort = (int) static::GetServer('SERVER_PORT', 80);
|
||||
|
||||
$sHost = (\in_array($iPort, array(80, 433))) ? $sName : $sName.':'.$iPort;
|
||||
}
|
||||
|
||||
if ($bWithoutWWW && 'www.' === \substr(\strtolower($sHost), 0, 4)) {
|
||||
if ($bWithoutWWW && \str_starts_with($sHost, 'www.')) {
|
||||
$sHost = \substr($sHost, 4);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -685,19 +685,6 @@ abstract class Utils
|
|||
return \sha1($sAdditionalSalt . \random_bytes(16));
|
||||
}
|
||||
|
||||
public static function ValidateDomain(string $sDomain, bool $bSimple = false) : bool
|
||||
{
|
||||
$aMatch = array();
|
||||
if ($bSimple) {
|
||||
return \preg_match('/.+(\.[a-zA-Z]+)$/', $sDomain, $aMatch) && !empty($aMatch[1]);
|
||||
}
|
||||
|
||||
return \preg_match('/.+(\.[a-zA-Z]+)$/', $sDomain, $aMatch) && !empty($aMatch[1]) && \in_array($aMatch[1], \explode(' ',
|
||||
'.academy .actor .agency .audio .bar .beer .bike .blue .boutique .cab .camera .camp .capital .cards .careers .cash .catering .center .cheap .city .cleaning .clinic .clothing .club .coffee .community .company .computer .construction .consulting .contractors .cool .credit .dance .dating .democrat .dental .diamonds .digital .direct .directory .discount .domains .education .email .energy .equipment .estate .events .expert .exposed .fail .farm .fish .fitness .florist .fund .futbol .gallery .gift .glass .graphics .guru .help .holdings .holiday .host .hosting .house .institute .international .kitchen .land .life .lighting .limo .link .management .market .marketing .media .menu .moda .partners .parts .photo .photography .photos .pics .pink .press .productions .pub .red .rentals .repair .report .rest .sexy .shoes .social .solar .solutions .space .support .systems .tattoo .tax .technology .tips .today .tools .town .toys .trade .training .university .uno .vacations .vision .vodka .voyage .watch .webcam .wiki .work .works .wtf .zone .aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .xxx .xyz '.
|
||||
'.ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cs .cu .cv .cx .cy .cz .dd .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru . .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .za .zm .zw'
|
||||
));
|
||||
}
|
||||
|
||||
public static function ValidateIP(string $sIp) : bool
|
||||
{
|
||||
return !empty($sIp) && $sIp === \filter_var($sIp, FILTER_VALIDATE_IP);
|
||||
|
|
@ -726,9 +713,6 @@ abstract class Utils
|
|||
{
|
||||
$aParts = \explode('@', $sStr);
|
||||
$sDomain = \array_pop($aParts);
|
||||
if ($bLowerCase) {
|
||||
$sDomain = \mb_strtolower($sDomain);
|
||||
}
|
||||
if (\strlen($sDomain) && \preg_match('/[^\x20-\x7E]/', $sDomain)) {
|
||||
try
|
||||
{
|
||||
|
|
@ -736,6 +720,9 @@ abstract class Utils
|
|||
}
|
||||
catch (\Throwable $oException) {}
|
||||
}
|
||||
if ($bLowerCase) {
|
||||
$sDomain = \strtolower($sDomain);
|
||||
}
|
||||
$aParts[] = $sDomain;
|
||||
return \implode('@', $aParts);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,55 +33,44 @@ trait UserAuth
|
|||
$this->Plugins()->RunHook('login.credentials.step-1', array(&$sEmail));
|
||||
|
||||
if (!\str_contains($sEmail, '@')) {
|
||||
$this->logWrite('The email address "' . $sEmail . '" is not complete', \LOG_INFO, 'LOGIN');
|
||||
|
||||
$bAdded = false;
|
||||
|
||||
$this->logWrite("The email address '{$sEmail}' is incomplete", \LOG_INFO, 'LOGIN');
|
||||
$oDomain = null;
|
||||
if ($this->Config()->Get('login', 'determine_user_domain', false)) {
|
||||
$sUserHost = \trim($this->Http()->GetHost(true, true));
|
||||
$this->logWrite('Determined user domain: ' . $sUserHost, \LOG_INFO, 'LOGIN');
|
||||
$sUserHost = \strtolower(\idn_to_ascii($this->Http()->GetHost(false, true)));
|
||||
$this->logWrite("Determined user domain: {$sUserHost}", \LOG_INFO, 'LOGIN');
|
||||
|
||||
$aDomainParts = \explode('.', $sUserHost);
|
||||
$iLimit = \min(\count($aDomainParts), 14);
|
||||
|
||||
$oDomainProvider = $this->DomainProvider();
|
||||
while (0 < $iLimit--) {
|
||||
$sLine = \implode('.', $aDomainParts);
|
||||
|
||||
$oDomain = $oDomainProvider->Load($sLine, false);
|
||||
if ($oDomain) {
|
||||
$bAdded = true;
|
||||
$this->logWrite('Check "' . $sLine . '": OK (' . $sEmail . ' > ' . $sEmail . '@' . $sLine . ')',
|
||||
\LOG_INFO, 'LOGIN');
|
||||
|
||||
$sEmail .= '@' . $sLine;
|
||||
$this->logWrite("Check '{$sLine}': OK", \LOG_INFO, 'LOGIN');
|
||||
break;
|
||||
} else {
|
||||
$this->logWrite('Check "' . $sLine . '": NO', \LOG_INFO, 'LOGIN');
|
||||
$this->logWrite("Check '{$sLine}': NO", \LOG_INFO, 'LOGIN');
|
||||
}
|
||||
|
||||
\array_shift($aDomainParts);
|
||||
}
|
||||
|
||||
if (!$bAdded) {
|
||||
if (!$oDomain) {
|
||||
$oDomain = $oDomainProvider->Load($sUserHost, true);
|
||||
if ($oDomain) {
|
||||
$bAdded = true;
|
||||
$this->logWrite('Check "' . $sUserHost . '" with wildcard: OK (' . $sEmail . ' > ' . $sEmail . '@' . $sUserHost . ')',
|
||||
\LOG_INFO, 'LOGIN');
|
||||
|
||||
$sEmail .= '@' . $sUserHost;
|
||||
$this->logWrite("Check '{$sUserHost}' with wildcard: OK", \LOG_INFO, 'LOGIN');
|
||||
} else {
|
||||
$this->logWrite('Check "' . $sUserHost . '" with wildcard: NO', \LOG_INFO, 'LOGIN');
|
||||
$this->logWrite("Check '{$sUserHost}' with wildcard: NO", \LOG_INFO, 'LOGIN');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bAdded) {
|
||||
$this->logWrite('Domain was not found!', \LOG_INFO, 'LOGIN');
|
||||
if (!$oDomain) {
|
||||
$this->logWrite("Domain '{$sUserHost}' was not determined!", \LOG_INFO, 'LOGIN');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bAdded) {
|
||||
if (!$oDomain) {
|
||||
$sDefDomain = \trim($this->Config()->Get('login', 'default_domain', ''));
|
||||
if (\strlen($sDefDomain)) {
|
||||
if ('HTTP_HOST' === $sDefDomain || 'SERVER_NAME' === $sDefDomain) {
|
||||
|
|
@ -89,10 +78,8 @@ trait UserAuth
|
|||
} else if ('gethostname' === $sDefDomain) {
|
||||
$sDefDomain = \gethostname();
|
||||
}
|
||||
$this->logWrite('Default domain "' . $sDefDomain . '" was used. (' . $sEmail . ' > ' . $sEmail . '@' . $sDefDomain . ')',
|
||||
\LOG_INFO, 'LOGIN');
|
||||
|
||||
$sEmail .= '@' . $sDefDomain;
|
||||
$this->logWrite("Default domain '{$sDefDomain}' will be used.", \LOG_INFO, 'LOGIN');
|
||||
} else {
|
||||
$this->logWrite('Default domain not configured.', \LOG_INFO, 'LOGIN');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<?php
|
||||
/**
|
||||
* Domain name is handled in lowercase punycode.
|
||||
* Because internationalized domain names can have uppercase or titlecase characters.
|
||||
*/
|
||||
|
||||
namespace RainLoop\Model;
|
||||
|
||||
|
|
@ -20,8 +24,7 @@ class Domain implements \JsonSerializable
|
|||
|
||||
function __construct(string $sName)
|
||||
{
|
||||
$this->Name = $sName;
|
||||
|
||||
$this->Name = \strtolower(\idn_to_ascii($sName));
|
||||
$this->IMAP = new \MailSo\Imap\Settings;
|
||||
$this->SMTP = new \MailSo\Smtp\Settings;
|
||||
$this->Sieve = new \MailSo\Sieve\Settings;
|
||||
|
|
@ -96,7 +99,7 @@ class Domain implements \JsonSerializable
|
|||
|
||||
public function SetAliasName(string $sAliasName) : void
|
||||
{
|
||||
$this->aliasName = $sAliasName;
|
||||
$this->aliasName = \strtolower(\idn_to_ascii($sAliasName));
|
||||
}
|
||||
|
||||
public function ValidateWhiteList(string $sEmail, string $sLogin = '') : bool
|
||||
|
|
@ -232,14 +235,14 @@ class Domain implements \JsonSerializable
|
|||
{
|
||||
$aResult = array(
|
||||
// '@Object' => 'Object/Domain',
|
||||
'name' => $this->Name,
|
||||
'name' => \idn_to_utf8($this->Name),
|
||||
'IMAP' => $this->IMAP,
|
||||
'SMTP' => $this->SMTP,
|
||||
'Sieve' => $this->Sieve,
|
||||
'whiteList' => $this->whiteList
|
||||
);
|
||||
if ($this->aliasName) {
|
||||
$aResult['aliasName'] = $this->aliasName;
|
||||
$aResult['aliasName'] = \idn_to_utf8($this->aliasName);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ abstract class Autoconfig
|
|||
public static function discover(string $emailaddress) : ?array
|
||||
{
|
||||
$domain = \MailSo\Base\Utils::GetDomainFromEmail($emailaddress);
|
||||
// $domain = \strtolower(\idn_to_ascii($domain));
|
||||
// First try
|
||||
$autoconfig = static::resolve($domain, $emailaddress);
|
||||
if ($autoconfig) {
|
||||
|
|
@ -89,7 +90,7 @@ abstract class Autoconfig
|
|||
private static function publicsuffixes() : array
|
||||
{
|
||||
$oCache = \RainLoop\Api::Actions()->Cacher();
|
||||
$list = $oCache->Get('public_suffix_list') ?: null;
|
||||
$list = $oCache->Get('public_suffix_list');
|
||||
if ($list) {
|
||||
$list = \json_decode($list, true);
|
||||
if ($list[1] < \time()) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<?php
|
||||
/**
|
||||
* Domain names are handled in lowercase punycode.
|
||||
* Because internationalized domain names can have uppercase or titlecase characters.
|
||||
*/
|
||||
|
||||
namespace RainLoop\Providers\Domain;
|
||||
|
||||
|
|
@ -6,7 +10,7 @@ use MailSo\Cache\CacheClient;
|
|||
|
||||
class DefaultDomain implements DomainInterface
|
||||
{
|
||||
const CACHE_KEY = '/WildCard/DomainCache/';
|
||||
const CACHE_KEY = '/WildCardDomainsCache/';
|
||||
|
||||
protected string $sDomainPath;
|
||||
|
||||
|
|
@ -20,30 +24,26 @@ class DefaultDomain implements DomainInterface
|
|||
|
||||
private static function decodeFileName(string $sName) : string
|
||||
{
|
||||
return ('default' === $sName)
|
||||
? '*'
|
||||
: \str_replace('_wildcard_', '*', \MailSo\Base\Utils::IdnToUtf8($sName, true));
|
||||
return ('default' === $sName) ? '*' : \str_replace('_wildcard_', '*', $sName);
|
||||
}
|
||||
|
||||
private static function encodeFileName(string $sName) : string
|
||||
{
|
||||
return ('*' === $sName)
|
||||
? 'default'
|
||||
: \str_replace('*', '_wildcard_', \MailSo\Base\Utils::IdnToAscii($sName, true));
|
||||
return ('*' === $sName) ? 'default' : \str_replace('*', '_wildcard_', \strtolower(\idn_to_ascii($sName)));
|
||||
}
|
||||
|
||||
private function getWildcardDomainsLine() : string
|
||||
{
|
||||
if ($this->oCacher) {
|
||||
$sResult = $this->oCacher->Get(static::CACHE_KEY);
|
||||
if (\strlen($sResult)) {
|
||||
if (\is_string($sResult)) {
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
||||
$aNames = array();
|
||||
|
||||
// $aList = \glob($this->sDomainPath.'/*.{ini,json}', GLOB_BRACE);
|
||||
// $aList = \glob($this->sDomainPath.'/*.{ini,json,alias}', GLOB_BRACE);
|
||||
$aList = \glob($this->sDomainPath.'/*.json');
|
||||
foreach ($aList as $sFile) {
|
||||
$sName = \substr(\basename($sFile), 0, -5);
|
||||
|
|
@ -72,16 +72,14 @@ class DefaultDomain implements DomainInterface
|
|||
$sResult = \implode(' ', \array_unique($aNames));
|
||||
}
|
||||
|
||||
if ($this->oCacher) {
|
||||
$this->oCacher->Set(static::CACHE_KEY, $sResult);
|
||||
}
|
||||
$this->oCacher && $this->oCacher->Set(static::CACHE_KEY, $sResult);
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public function Load(string $sName, bool $bFindWithWildCard = false, bool $bCheckDisabled = true, bool $bCheckAliases = true) : ?\RainLoop\Model\Domain
|
||||
{
|
||||
$sName = \MailSo\Base\Utils::IdnToUtf8($sName, true);
|
||||
$sName = \strtolower(\idn_to_ascii($sName));
|
||||
if ($bCheckDisabled && \in_array($sName, $this->getDisabled())) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -130,7 +128,7 @@ class DefaultDomain implements DomainInterface
|
|||
|
||||
public function SaveAlias(string $sName, string $sAlias) : bool
|
||||
{
|
||||
$sAlias = \MailSo\Base\Utils::IdnToUtf8($sAlias, true);
|
||||
$sAlias = \strtolower(\idn_to_ascii($sAlias));
|
||||
$sRealFileName = static::encodeFileName($sName);
|
||||
\RainLoop\Utils::saveFile($this->sDomainPath.'/'.$sRealFileName.'.alias', $sAlias);
|
||||
$this->oCacher && $this->oCacher->Delete(static::CACHE_KEY);
|
||||
|
|
@ -147,7 +145,7 @@ class DefaultDomain implements DomainInterface
|
|||
// RainLoop use comma, we use newline
|
||||
$sItem = \strtok($sFile, ",\n");
|
||||
while (false !== $sItem) {
|
||||
$aDisabled[] = \MailSo\Base\Utils::IdnToUtf8($sItem, true);
|
||||
$aDisabled[] = \strtolower(\idn_to_ascii($sItem));
|
||||
$sItem = \strtok(",\n");
|
||||
}
|
||||
return $aDisabled;
|
||||
|
|
@ -156,7 +154,7 @@ class DefaultDomain implements DomainInterface
|
|||
|
||||
public function Disable(string $sName, bool $bDisable) : bool
|
||||
{
|
||||
$sName = \MailSo\Base\Utils::IdnToUtf8($sName, true);
|
||||
$sName = \strtolower(\idn_to_ascii($sName));
|
||||
if ($sName) {
|
||||
$aResult = $this->getDisabled();
|
||||
if ($bDisable) {
|
||||
|
|
@ -209,20 +207,23 @@ class DefaultDomain implements DomainInterface
|
|||
if ($bAlias) {
|
||||
if ($bIncludeAliases) {
|
||||
$aAliases[$sName] = array(
|
||||
'name' => $sName,
|
||||
'name' => \idn_to_utf8($sName),
|
||||
'punycode' => $sName,
|
||||
'disabled' => \in_array($sName, $aDisabledNames),
|
||||
'alias' => true
|
||||
);
|
||||
}
|
||||
} else if (false !== \strpos($sName, '*')) {
|
||||
$aWildCards[$sName] = array(
|
||||
'name' => $sName,
|
||||
'name' => \idn_to_utf8($sName),
|
||||
'punycode' => $sName,
|
||||
'disabled' => \in_array($sName, $aDisabledNames),
|
||||
'alias' => false
|
||||
);
|
||||
} else {
|
||||
$aResult[$sName] = array(
|
||||
'name' => $sName,
|
||||
'name' => \idn_to_utf8($sName),
|
||||
'punycode' => $sName,
|
||||
'disabled' => \in_array($sName, $aDisabledNames),
|
||||
'alias' => false
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ abstract class IDN
|
|||
{
|
||||
public static function anyToAscii(string $string) : string
|
||||
{
|
||||
if (\preg_match('#[:/]#', $string)) {
|
||||
if (\strspn($string, ':/')) {
|
||||
return static::uri($string, true);
|
||||
}
|
||||
if (\strpos($string, '@')) {
|
||||
if (\str_contains($string, '@')) {
|
||||
return static::emailAddress($string, true);
|
||||
}
|
||||
return \idn_to_ascii($string);
|
||||
|
|
@ -20,91 +20,73 @@ abstract class IDN
|
|||
|
||||
public static function anyToUtf8(string $string) : string
|
||||
{
|
||||
if (\preg_match('#[:/]#', $string)) {
|
||||
if (\strspn($string, ':/')) {
|
||||
return static::uri($string, false);
|
||||
}
|
||||
if (\strpos($string, '@')) {
|
||||
if (\str_contains($string, '@')) {
|
||||
return static::emailAddress($string, false);
|
||||
}
|
||||
return \idn_to_utf8($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts IDN domain part to lowercased punycode
|
||||
*/
|
||||
public static function emailToAscii(string $address) : string
|
||||
{
|
||||
return static::emailAddress($address, true);
|
||||
}
|
||||
|
||||
public static function emailToUtf8(string $address) : string
|
||||
private static function domain(string $domain, bool $toAscii) : string
|
||||
{
|
||||
return static::emailAddress($address, false);
|
||||
}
|
||||
|
||||
public static function uriToAscii(string $address) : string
|
||||
{
|
||||
return static::uri($address, true);
|
||||
}
|
||||
|
||||
public static function uriToUtf8(string $address) : string
|
||||
{
|
||||
return static::uri($address, false);
|
||||
return $toAscii ? \strtolower(\idn_to_ascii($domain)) : \idn_to_utf8($domain);
|
||||
/*
|
||||
$domain = \explode('.', $domain);
|
||||
foreach ($domain as $k => $v) {
|
||||
$conv = $toAscii ? \idn_to_ascii($v) : \idn_to_utf8($v);
|
||||
if ($conv) $domain[$k] = $conv;
|
||||
}
|
||||
return \implode('.', $domain);
|
||||
*/
|
||||
}
|
||||
|
||||
private static function emailAddress(string $address, bool $toAscii) : string
|
||||
{
|
||||
if (\str_contains($address, '@')) {
|
||||
$local = \explode('@', $address);
|
||||
$domain = \array_pop($local);
|
||||
$local = \implode('@', $local);
|
||||
$arr = \explode('.', $domain);
|
||||
foreach ($arr as $k => $v) {
|
||||
$conv = $toAscii ? \idn_to_ascii($v) : \idn_to_utf8($v);
|
||||
if ($conv) $arr[$k] = $conv;
|
||||
}
|
||||
return $local . '@' . \implode('.', $arr);
|
||||
if (!\str_contains($address, '@')) {
|
||||
throw new \RuntimeException("Invalid email address: {$address}");
|
||||
}
|
||||
return $toAscii ? \idn_to_ascii($address) : \idn_to_utf8($address);
|
||||
$local = \explode('@', $address);
|
||||
$domain = static::domain(\array_pop($local), $toAscii);
|
||||
return \implode('@', $local) . '@' . $domain;
|
||||
}
|
||||
|
||||
private static function uri(string $address, bool $toAscii) : string
|
||||
{
|
||||
if (\preg_match('#[:\./]#', $address)) {
|
||||
$parsed = \parse_url($address);
|
||||
if (isset($parsed['host'])) {
|
||||
$arr = \explode('.', $parsed['host']);
|
||||
foreach ($arr as $k => $v) {
|
||||
$conv = $toAscii ? \idn_to_ascii($v) : \idn_to_utf8($v);
|
||||
if ($conv) $arr[$k] = $conv;
|
||||
}
|
||||
$parsed['host'] = \implode('.', $arr);
|
||||
$parsed = \parse_url($address);
|
||||
if (isset($parsed['host'])) {
|
||||
$parsed['host'] = static::domain($parsed['host'], $toAscii);
|
||||
|
||||
$url = '//';
|
||||
if (!empty($parsed['scheme'])) { $url = $parsed['scheme'] . (\strtolower($parsed['scheme']) === 'mailto' ? ':' : '://'); }
|
||||
$url = empty($parsed['scheme']) ? '//'
|
||||
: $parsed['scheme'] . (\strtolower($parsed['scheme']) === 'mailto' ? ':' : '://');
|
||||
/*
|
||||
if (!empty($parsed['user']) || !empty($parsed['pass'])) {
|
||||
$ret_url .= $parts_arr['user'];
|
||||
if (!empty($parts_arr['pass'])) {
|
||||
$ret_url .= ':' . $parts_arr['pass'];
|
||||
}
|
||||
$ret_url .= '@';
|
||||
if (!empty($parsed['user']) || !empty($parsed['pass'])) {
|
||||
$ret_url .= $parts_arr['user'];
|
||||
if (!empty($parts_arr['pass'])) {
|
||||
$ret_url .= ':' . $parts_arr['pass'];
|
||||
}
|
||||
$ret_url .= '@';
|
||||
}
|
||||
*/
|
||||
if (!empty($parsed['host'])) { $url .= $parsed['host']; }
|
||||
if (!empty($parsed['port'])) { $url .= ':'.$parsed['port']; }
|
||||
if (!empty($parsed['path'])) { $url .= $parsed['path']; }
|
||||
if (!empty($parsed['query'])) { $url .= '?'.$parsed['query']; }
|
||||
if (!empty($parsed['fragment'])) { $url .= '#'.$parsed['fragment']; }
|
||||
return $url;
|
||||
}
|
||||
|
||||
// parse_url seems to have failed, try without it
|
||||
$arr = \explode('.', $address);
|
||||
foreach ($arr as $k => $v) {
|
||||
$conv = $toAscii ? \idn_to_ascii($v) : \idn_to_utf8($v);
|
||||
if ($conv) $arr[$k] = $conv;
|
||||
}
|
||||
return \implode('.', $arr);
|
||||
if (!empty($parsed['host'])) { $url .= $parsed['host']; }
|
||||
if (!empty($parsed['port'])) { $url .= ':'.$parsed['port']; }
|
||||
if (!empty($parsed['path'])) { $url .= $parsed['path']; }
|
||||
if (!empty($parsed['query'])) { $url .= '?'.$parsed['query']; }
|
||||
if (!empty($parsed['fragment'])) { $url .= '#'.$parsed['fragment']; }
|
||||
return $url;
|
||||
}
|
||||
return $toAscii ? \idn_to_ascii($address) : \idn_to_utf8($address);
|
||||
|
||||
// parse_url seems to have failed, try without it
|
||||
return static::domain($address, $toAscii);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue