new pisilinux web sites
This commit is contained in:
@@ -0,0 +1,343 @@
|
||||
<?php namespace ZN\Email\Drivers;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Config;
|
||||
use ZN\Support;
|
||||
use ZN\DateTime\Date;
|
||||
use ZN\Email\DriverMappingAbstract;
|
||||
use ZN\Email\Exception\IMAPConnectException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ImapDriver extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Connect
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $connect;
|
||||
|
||||
/**
|
||||
* Host
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $host;
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
Support::func('imap_mail');
|
||||
|
||||
$this->connection($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Destructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
imap_close($this->connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Email
|
||||
*
|
||||
* @param string $to
|
||||
* @param string $subject
|
||||
* @param string $message
|
||||
* @param mixed $headers
|
||||
* @param mixed $settings
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function send($to, $subject, $message, $headers = NULL, $settings = NULL)
|
||||
{
|
||||
return imap_mail($to, $subject, $message, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* New
|
||||
*
|
||||
* @param array $config = []
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function new(array $config = [])
|
||||
{
|
||||
return new self($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mail
|
||||
*
|
||||
* @param int $mailId
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function mail(int $mailId)
|
||||
{
|
||||
$overview = imap_fetch_overview($this->connect, $mailId, FT_UID);
|
||||
$structure = imap_fetchstructure($this->connect, $mailId, FT_UID);
|
||||
$header = imap_headerinfo($this->connect, $overview[0]->msgno);
|
||||
|
||||
$from = $header->from[0]->mailbox . '@' . $header->from[0]->host;
|
||||
|
||||
$section = 1;
|
||||
|
||||
if( isset($structure->parts) && is_array($structure->parts) && isset($structure->parts[0]) )
|
||||
{
|
||||
$part = $structure->parts[0];
|
||||
|
||||
if( $part->subtype === 'ALTERNATIVE' )
|
||||
{
|
||||
$section = 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
$message = $this->contentDecoder($part->encoding ?? $structure->encoding, imap_fetchbody($this->connect, $mailId, $section, FT_UID));
|
||||
|
||||
return (object)
|
||||
[
|
||||
'subject' => mb_convert_encoding(imap_utf8($overview[0]->subject), 'ISO-8859-1', 'UTF-8'),
|
||||
'body' => imap_qprint($message),
|
||||
'from' => $this->cc($header->from ?? NULL),
|
||||
'replyTo' => $this->cc($header->reply_to ?? NULL),
|
||||
'cc' => $this->cc($header->cc ?? NULL),
|
||||
'bcc' => $this->cc($header->bcc ?? NULL),
|
||||
'date' => (new Date)->convert($header->Date, 'Y-m-d H:i:s'),
|
||||
'attachments' => $this->attachments($structure->parts ?? NULL, $mailId)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* List
|
||||
*
|
||||
* @param string $flag = 'all'
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function list(string $flag = 'all') : array
|
||||
{
|
||||
return imap_search($this->connect, strtoupper($flag), SE_UID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param scalar $mailId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($mailId) : bool
|
||||
{
|
||||
$return = imap_delete($this->connect, $mailId, FT_UID);
|
||||
|
||||
imap_expunge($this->connect);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move
|
||||
*
|
||||
* @param scalar $mailId
|
||||
* @param string $folder = 'Spam'
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function move($mailId, string $folder = 'Spam') : bool
|
||||
{
|
||||
if( ! in_array($folder, ['Spam', 'Trash', 'Drafts', 'Sent']) )
|
||||
{
|
||||
$folder = imap_utf7_encode($folder);
|
||||
}
|
||||
|
||||
$return = imap_mail_move($this->connect, $mailId, $folder, CP_UID);
|
||||
|
||||
imap_expunge($this->connect);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Folder
|
||||
*
|
||||
* @param string $folder
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createFolder(string $folder) : bool
|
||||
{
|
||||
return imap_createmailbox($this->connect, $this->utf7FolderEncoder($folder));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Folder
|
||||
*
|
||||
* @param string $folder
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteFolder(string $folder) : bool
|
||||
{
|
||||
return imap_deletemailbox($this->connect, $this->utf7FolderEncoder($folder));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename Folder
|
||||
*
|
||||
* @param string $folder
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function renameFolder(string $name, string $newName) : bool
|
||||
{
|
||||
$host = '{' . $this->host . '}';
|
||||
|
||||
return imap_renamemailbox($this->connect, $this->utf7FolderEncoder($name), $this->utf7FolderEncoder($newName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Status
|
||||
*
|
||||
* @param scalar $mailId
|
||||
* @param string $status
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function changeStatus($mailId, string $status) : bool
|
||||
{
|
||||
$status = ucfirst(strtolower($status));
|
||||
|
||||
if( in_array($status, ['Unread', 'Unseen']) )
|
||||
{
|
||||
return imap_clearflag_full($this->connect, $mailId, '\\Seen', ST_UID);
|
||||
}
|
||||
|
||||
if( $status === 'Read' )
|
||||
{
|
||||
$status = 'Seen';
|
||||
}
|
||||
|
||||
return imap_setflag_full($this->connect, $mailId, '\\' . $status, ST_UID);
|
||||
}
|
||||
|
||||
public function error() : string
|
||||
{
|
||||
return imap_last_error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Utf7 Folder Encoder
|
||||
*/
|
||||
protected function utf7FolderEncoder($folder) : string
|
||||
{
|
||||
return imap_utf7_encode('{' . $this->host . '}' . $folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected connection
|
||||
*/
|
||||
protected function connection(array $config = [])
|
||||
{
|
||||
if( empty($config) )
|
||||
{
|
||||
$config = Config::default('ZN\Email\EmailDefaultConfiguration')::get('Services', 'email')['imap'];
|
||||
}
|
||||
|
||||
$host = $this->host = $config['host'];
|
||||
$user = $config['user'];
|
||||
$password = $config['password'];
|
||||
$port = ':' . ($config['port'] ?? '993');
|
||||
$flags = '/' . implode('/' , $config['flags']);
|
||||
$mailbox = $config['mailbox'] ?? 'INBOX';
|
||||
|
||||
$connect = '{' . $host . $port . $flags . '}' . $mailbox;
|
||||
|
||||
if( ! $host )
|
||||
{
|
||||
throw new IMAPConnectException;
|
||||
}
|
||||
|
||||
$this->connect = imap_open($connect, $user, $password);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected attachments
|
||||
*/
|
||||
protected function attachments($parts, $mailId)
|
||||
{
|
||||
$attachments = [];
|
||||
|
||||
if( $parts ) foreach( $parts as $key => $part )
|
||||
{
|
||||
$body = imap_fetchbody($this->connect, $mailId, $key + 1, FT_UID);
|
||||
|
||||
$body = $this->contentDecoder($part->encoding, $body);
|
||||
|
||||
if( $body && ! empty($part->dparameters) )
|
||||
{
|
||||
$attachments[] =
|
||||
[
|
||||
'file' => $part->dparameters[0]->value,
|
||||
'content' => $body
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected content decoder
|
||||
*/
|
||||
protected function contentDecoder($encoding, $body)
|
||||
{
|
||||
switch( $encoding )
|
||||
{
|
||||
case 1 : $body = imap_8bit($body) ; break;
|
||||
case 2 : $body = imap_binary($body); break;
|
||||
case 3 : $body = imap_base64($body); break;
|
||||
default: $body = imap_qprint($body);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected cc
|
||||
*/
|
||||
protected function cc($cc)
|
||||
{
|
||||
$addresses = [];
|
||||
|
||||
if( is_array($cc) )
|
||||
{
|
||||
foreach( $cc as $c )
|
||||
{
|
||||
$addresses[] =
|
||||
[
|
||||
'mail' => $c->mailbox . '@' . $c->host,
|
||||
'name' => iconv_mime_decode($c->personal ?? '')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $addresses;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
<?php namespace ZN\Email\Drivers;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Email\DriverMappingAbstract;
|
||||
use ZN\Email\Exception\SMTPConnectException;
|
||||
use ZN\Email\Exception\SMTPEmptyHostNameException;
|
||||
use ZN\Email\Exception\SMTPEmptyUserPasswordException;
|
||||
use ZN\Email\Exception\SMTPFailedLoginException;
|
||||
use ZN\Email\Exception\SMTPDataFailureException;
|
||||
use ZN\Email\Exception\SMTPAuthException;
|
||||
use ZN\Email\Exception\SMTPAuthPasswordException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
|
||||
class SmtpDriver extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $lf = "\n";
|
||||
|
||||
/**
|
||||
* Keeps connection
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $connect;
|
||||
|
||||
/**
|
||||
* Keeps config variables
|
||||
*/
|
||||
protected $to,
|
||||
$subject,
|
||||
$body,
|
||||
$header,
|
||||
$host,
|
||||
$user,
|
||||
$password,
|
||||
$from,
|
||||
$port,
|
||||
$encoding,
|
||||
$timeout,
|
||||
$cc,
|
||||
$bcc,
|
||||
$auth,
|
||||
$encode,
|
||||
$keepAlive,
|
||||
$dsn,
|
||||
$tos;
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*
|
||||
* @param string $to
|
||||
* @param string $subject
|
||||
* @param string $message
|
||||
* @param mixed $headers
|
||||
* @param mixed $settings
|
||||
*/
|
||||
public function __construct($to = '', $subject = '', $body = '', $headers = '', $settings = [])
|
||||
{
|
||||
$this->to = $to;
|
||||
$this->subject = $subject;
|
||||
$this->body = $body;
|
||||
$this->header = $headers;
|
||||
$this->host = $settings['host'] ?? '';
|
||||
$this->user = $settings['user'] ?? '';
|
||||
$this->password = $settings['password'] ?? '';
|
||||
$this->from = $settings['from'] ?? '';
|
||||
$this->port = $settings['port'] ?? 587;
|
||||
$this->encoding = $settings['encoding'] ?? '';
|
||||
$this->timeout = $settings['timeout'] ?? '';
|
||||
$this->cc = $settings['cc'] ?? '';
|
||||
$this->bcc = $settings['bcc'] ?? '';
|
||||
$this->auth = $settings['authLogin'] ?? '';
|
||||
$this->encode = $settings['encode'] ?? '';
|
||||
$this->keepAlive = $settings['keepAlive'] ?? '';
|
||||
$this->dsn = $settings['dsn'] ?? '';
|
||||
$this->tos = $settings['tos'] ?? [];
|
||||
$this->lf = $settings['commandLine'] ?? $this->lf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Email
|
||||
*
|
||||
* @param string $to
|
||||
* @param string $subject
|
||||
* @param string $message
|
||||
* @param mixed $headers
|
||||
* @param mixed $settings
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function send($to, $subject, $message, $headers, $settings)
|
||||
{
|
||||
$smtp = new self($to, $subject, $message, $headers, $settings);
|
||||
|
||||
return $smtp->sendEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Email
|
||||
*
|
||||
* @return void|true
|
||||
*/
|
||||
public function sendEmail()
|
||||
{
|
||||
$connect = $this->connect();
|
||||
$sending = $this->sending();
|
||||
|
||||
return $sending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Connect
|
||||
*/
|
||||
protected function connect()
|
||||
{
|
||||
if( is_resource($this->connect) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->socketSSLConnection($errno, $errstr);
|
||||
|
||||
stream_set_timeout($this->connect, $this->timeout);
|
||||
|
||||
$this->error[] = $this->getData();
|
||||
|
||||
if( $this->encode === 'tls' )
|
||||
{
|
||||
$this->encodeSocketWithTLSMethod(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->setCommand('hello');
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected encode socket with tls method
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function encodeSocketWithTLSMethod()
|
||||
{
|
||||
$this->setCommand('hello'); $this->setCommand('starttls');
|
||||
|
||||
$crypto = stream_socket_enable_crypto($this->connect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||
|
||||
if( $crypto !== true )
|
||||
{
|
||||
throw new SMTPConnectException(NULL, $this->getData());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected socket ssl connection
|
||||
*/
|
||||
protected function socketSSLConnection(&$errno, &$errstr)
|
||||
{
|
||||
$context = stream_context_create
|
||||
([
|
||||
'ssl' =>
|
||||
[
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
]
|
||||
]);
|
||||
|
||||
$ssl = $this->encode === 'ssl' ? 'ssl://' : '';
|
||||
|
||||
$this->connect = stream_socket_client($ssl . $this->host . ":" . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context);
|
||||
|
||||
if( is_resource($this->connect) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected socket ssl without connection
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function socketSSLWithoutConnection(&$errno, &$errstr)
|
||||
{
|
||||
$this->connect = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
|
||||
|
||||
if( ! is_resource($this->connect) )
|
||||
{
|
||||
throw new SMTPConnectException(NULL, $errno.' '.$errstr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Sending
|
||||
*/
|
||||
protected function sending()
|
||||
{
|
||||
if( empty($this->host) )
|
||||
{
|
||||
throw new SMTPEmptyHostNameException; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( ! $this->connect() || ! $this->authLogin() )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$this->setCommand('from', $this->from);
|
||||
|
||||
if( ! empty($this->tos) ) foreach( $this->tos as $key => $val )
|
||||
{
|
||||
$this->setCommand('to', $key);
|
||||
}
|
||||
|
||||
if( ! empty($this->cc) ) foreach( $this->cc as $key => $val )
|
||||
{
|
||||
$this->setCommand('to', $key); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( ! empty($this->bcc) ) foreach( $this->bcc as $key => $val )
|
||||
{
|
||||
$this->setCommand('to', $key);
|
||||
}
|
||||
|
||||
$this->setCommand('data');
|
||||
|
||||
$this->setData($this->header.preg_replace('/^\./m', '..$1', $this->body));
|
||||
|
||||
$this->setData('.');
|
||||
|
||||
$this->error[] = $reply = $this->getData();
|
||||
|
||||
if( strpos($reply, '250') !== 0 )
|
||||
{
|
||||
throw new SMTPConnectException(NULL, $reply); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( $this->keepAlive )
|
||||
{
|
||||
$this->setCommand('reset'); // @codeCoverageIgnore
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->setCommand('quit');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Auth Login
|
||||
*/
|
||||
protected function authLogin()
|
||||
{
|
||||
if( ! $this->auth )
|
||||
{
|
||||
return true; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( $this->user === '' && $this->password === '' )
|
||||
{
|
||||
throw new SMTPEmptyUserPasswordException; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$this->setData('AUTH LOGIN');
|
||||
|
||||
$reply = $this->getData();
|
||||
|
||||
if( strpos($reply, '503') === 0 )
|
||||
{
|
||||
return true; // @codeCoverageIgnore
|
||||
}
|
||||
elseif( strpos($reply, '334') !== 0 )
|
||||
{
|
||||
throw new SMTPFailedLoginException(NULL, $reply); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$this->setData(base64_encode($this->user));
|
||||
|
||||
$reply = $this->getData();
|
||||
|
||||
if( strpos($reply, '334') !== 0 )
|
||||
{
|
||||
throw new SMTPAuthException(NULL, $reply); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$this->setData(base64_encode($this->password));
|
||||
|
||||
$reply = $this->getData();
|
||||
|
||||
if( strpos($reply, '235') !== 0 )
|
||||
{
|
||||
throw new SMTPAuthPasswordException(NULL, $reply); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Set Command
|
||||
*/
|
||||
protected function setCommand($cmd, $data = '')
|
||||
{
|
||||
switch( $cmd )
|
||||
{
|
||||
case 'starttls' : $this->setData('STARTTLS'); $resp = 220; break;
|
||||
case 'from' : $this->setData('MAIL FROM:<'.$data.'>'); $resp = 250; break;
|
||||
case 'data' : $this->setData('DATA'); $resp = 354; break;
|
||||
case 'reset' : $this->setData('RSET'); $resp = 250; break;
|
||||
case 'quit' : $this->setData('QUIT'); $resp = 221; break;
|
||||
case 'hello' :
|
||||
if( $this->auth || $this->encoding === '8bit' )
|
||||
{
|
||||
$this->setData('EHLO '.$this->hostname() );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->setData('HELO '.$this->hostname()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$resp = 250;
|
||||
break;
|
||||
case 'to' :
|
||||
if( $this->dsn )
|
||||
{
|
||||
$this->setData('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data); // @codeCoverageIgnore
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->setData('RCPT TO:<'.$data.'>');
|
||||
}
|
||||
$resp = 250;
|
||||
break;
|
||||
}
|
||||
|
||||
$reply = $this->getData();
|
||||
|
||||
$this->error[] = $cmd.': '.$reply; // @codeCoverageIgnore
|
||||
|
||||
if( (int) substr($reply, 0, 3) !== $resp )
|
||||
{
|
||||
throw new SMTPConnectException(NULL, $reply); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( $cmd === 'quit' )
|
||||
{
|
||||
fclose($this->connect);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Set Data
|
||||
*/
|
||||
protected function setData($data)
|
||||
{
|
||||
$data .= $this->lf;
|
||||
|
||||
for( $index = 0; $index < strlen($data); $index += $result )
|
||||
{
|
||||
$result = fwrite($this->connect, substr($data, $index));
|
||||
|
||||
if( $result === false )
|
||||
{
|
||||
break; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
if( $result === false )
|
||||
{
|
||||
throw new SMTPDataFailureException(NULL, $data); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Get Data
|
||||
*/
|
||||
protected function getData()
|
||||
{
|
||||
$data = '';
|
||||
|
||||
while( $str = fgets($this->connect, 512) )
|
||||
{
|
||||
$data .= $str;
|
||||
|
||||
if( $str[3] === ' ' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prortected Host Name
|
||||
*/
|
||||
protected function hostname()
|
||||
{
|
||||
return $_SERVER['SERVER_NAME'] ?? '[' . ($_SERVER['SERVER_ADDR'] ?? '127.0.0.1') . ']';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user