Revise CRC calls and use php's internal functions
This commit is contained in:
parent
7cd3b814bb
commit
2fdc6eabad
@ -222,7 +222,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
$makedata = preg_replace('/0000/',sprintf('%04X',strlen($makedata)-14),$makedata,1);
|
$makedata = preg_replace('/0000/',sprintf('%04X',strlen($makedata)-14),$makedata,1);
|
||||||
|
|
||||||
/* EMSI crc16 */
|
/* EMSI crc16 */
|
||||||
$makedata .= sprintf('%04X',$this->CRC16USD(substr($makedata,2)));
|
$makedata .= sprintf('%04X',crc16(substr($makedata,2)));
|
||||||
|
|
||||||
return $makedata;
|
return $makedata;
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
sscanf(substr($str,strlen($str)-4),"%04X",$l);
|
sscanf(substr($str,strlen($str)-4),"%04X",$l);
|
||||||
|
|
||||||
/* Bad EMSI CRC */
|
/* Bad EMSI CRC */
|
||||||
if ($l != ($x = $this->CRC16USD(substr($str,2,strlen($str)-6)))) {
|
if ($l != ($x = crc16(substr($str,2,strlen($str)-6)))) {
|
||||||
Log::error(sprintf('%s: ! Bad EMSI_DAT CRC: [%04X], should be: [%04X]!',__METHOD__,$l,$x));
|
Log::error(sprintf('%s: ! Bad EMSI_DAT CRC: [%04X], should be: [%04X]!',__METHOD__,$l,$x));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -688,7 +688,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
elseif ($c != self::LSZ_XONXOFF)
|
elseif ($c != self::LSZ_XONXOFF)
|
||||||
return $c&0xff;
|
return $c&0xff;
|
||||||
|
|
||||||
} while($c == self::LSZ_XONXOFF);
|
} while ($c == self::LSZ_XONXOFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We will be here only in case of DLE */
|
/* We will be here only in case of DLE */
|
||||||
@ -712,7 +712,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
$rr = $this->ls_readcanned($timeout);
|
$rr = $this->ls_readcanned($timeout);
|
||||||
// @todo to implement
|
// @todo to implement
|
||||||
$this->z_devrecv_c($rr,0);
|
$this->z_devrecv_c($rr,0);
|
||||||
} while($rr);
|
} while ($rr);
|
||||||
|
|
||||||
$this->z_devsend_c(0);
|
$this->z_devsend_c(0);
|
||||||
}
|
}
|
||||||
@ -792,12 +792,12 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
* @param int $i
|
* @param int $i
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function ls_sendhex(int $c): void
|
private function ls_sendhex(int $i): void
|
||||||
{
|
{
|
||||||
$hexdigitslower = "0123456789abcdef";
|
$str = hexstr($i);
|
||||||
|
$this->ls_txLastSent = ord(substr($str,-1));
|
||||||
|
|
||||||
$this->client->buffer_add(substr($hexdigitslower,($c&0xf0)>>4,1));
|
$this->client->buffer_add($str);
|
||||||
$this->client->buffer_add(chr($this->ls_txLastSent = ord(substr($hexdigitslower,($c&0x0f),1))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1071,26 +1071,26 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
private function ls_recvdata16(string &$data,int &$len,int $timeout): int
|
private function ls_zrecvdata16(string &$data,int &$len,int $timeout): int
|
||||||
{
|
{
|
||||||
if ($this->DEBUG)
|
if ($this->DEBUG)
|
||||||
Log::debug('+ Start',['m'=>__METHOD__,'d'=>$data]);
|
Log::debug('+ Start',['m'=>__METHOD__,'d'=>$data]);
|
||||||
|
|
||||||
$got = 0; /* Bytes total got */
|
$got = 0; /* Bytes total got */
|
||||||
$incrc = self::LSZ_INIT_CRC16; /* Calculated CRC */
|
|
||||||
$crc = 0; /* Received CRC */
|
$crc = 0; /* Received CRC */
|
||||||
$frametype = self::LSZ_ERROR; /* Type of frame - ZCRC(G|W|Q|E) */
|
$frametype = self::LSZ_ERROR; /* Type of frame - ZCRC(G|W|Q|E) */
|
||||||
$rcvdata = 1; /* Data is being received NOW (not CRC) */
|
$rcvdata = 1; /* Data is being received NOW (not CRC) */
|
||||||
|
|
||||||
while ($rcvdata && (($c = $this->ls_readzdle($timeout)) >= 0)) {
|
while ($rcvdata && (($c = $this->ls_readzdle($timeout)) >= 0)) {
|
||||||
if($c < 256) {
|
if ($this->DEBUG)
|
||||||
|
Log::debug(sprintf(' - got [%x] (%c)',$c,($c<31 ? 32 : $c)),['m'=>__METHOD__,'c'=>serialize($c)]);
|
||||||
|
|
||||||
|
if ($c < 256) {
|
||||||
$data .= chr($c&0xff);
|
$data .= chr($c&0xff);
|
||||||
|
|
||||||
if (++$got > $this->ls_MaxBlockSize)
|
if (++$got > $this->ls_MaxBlockSize)
|
||||||
return self::LSZ_BADCRC;
|
return self::LSZ_BADCRC;
|
||||||
|
|
||||||
$incrc = $this->CRC16USD_UPDATE($c,$incrc);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch($c) {
|
switch($c) {
|
||||||
case self::LSZ_CRCE:
|
case self::LSZ_CRCE:
|
||||||
@ -1100,8 +1100,6 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
$rcvdata = 0;
|
$rcvdata = 0;
|
||||||
$frametype = ($c & 0xff);
|
$frametype = ($c & 0xff);
|
||||||
|
|
||||||
$incrc = $this->CRC16USD_UPDATE($c,$incrc);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1128,6 +1126,8 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
$crc <<= 8;
|
$crc <<= 8;
|
||||||
$crc |= $c;
|
$crc |= $c;
|
||||||
|
|
||||||
|
$incrc = crc16($data.chr($frametype));
|
||||||
|
|
||||||
if ($this->DEBUG)
|
if ($this->DEBUG)
|
||||||
Log::debug(sprintf('CRC%d got %08x - calculated %08x',16,$incrc,$crc),['m'=>__METHOD__]);
|
Log::debug(sprintf('CRC%d got %08x - calculated %08x',16,$incrc,$crc),['m'=>__METHOD__]);
|
||||||
|
|
||||||
@ -1156,7 +1156,6 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
Log::debug('+ Start',['m'=>__METHOD__,'d'=>$data]);
|
Log::debug('+ Start',['m'=>__METHOD__,'d'=>$data]);
|
||||||
|
|
||||||
$got = 0; /* Bytes total got */
|
$got = 0; /* Bytes total got */
|
||||||
$incrc = self::LSZ_INIT_CRC32; /* Calculated CRC */
|
|
||||||
$crc = 0; /* Received CRC */
|
$crc = 0; /* Received CRC */
|
||||||
$frametype = self::LSZ_ERROR; /* Type of frame - ZCRC(G|W|Q|E) */
|
$frametype = self::LSZ_ERROR; /* Type of frame - ZCRC(G|W|Q|E) */
|
||||||
$rcvdata = 1; /* Data is being received NOW (not CRC) */
|
$rcvdata = 1; /* Data is being received NOW (not CRC) */
|
||||||
@ -1171,8 +1170,6 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
if (++$got > $this->ls_MaxBlockSize)
|
if (++$got > $this->ls_MaxBlockSize)
|
||||||
return self::LSZ_BADCRC;
|
return self::LSZ_BADCRC;
|
||||||
|
|
||||||
$incrc = $this->CRC32_UPDATE($c,$incrc);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch ($c) {
|
switch ($c) {
|
||||||
case self::LSZ_CRCE:
|
case self::LSZ_CRCE:
|
||||||
@ -1181,7 +1178,6 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
case self::LSZ_CRCW:
|
case self::LSZ_CRCW:
|
||||||
$rcvdata = 0;
|
$rcvdata = 0;
|
||||||
$frametype = ($c&0xff);
|
$frametype = ($c&0xff);
|
||||||
$incrc = $this->CRC32_UPDATE($c,$incrc);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1215,10 +1211,10 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
return $c;
|
return $c;
|
||||||
|
|
||||||
$crc |= ($c << 0x18);
|
$crc |= ($c << 0x18);
|
||||||
$incrc = $this->CRC32_FINISH($incrc);
|
|
||||||
|
|
||||||
|
$incrc = crc32($data.chr($frametype));
|
||||||
if ($this->DEBUG)
|
if ($this->DEBUG)
|
||||||
Log::debug(sprintf('CRC%d got %08x - calculated %08x',32,$incrc,$crc),['m'=>__METHOD__,'crc'=>$crc,'test_crc32'=>sprintf('%08x',$this->CRC32($data))]);
|
Log::debug(sprintf('CRC%d got %08x - calculated %08x',32,$incrc,$crc),['m'=>__METHOD__]);
|
||||||
|
|
||||||
if ($incrc != $crc)
|
if ($incrc != $crc)
|
||||||
return self::LSZ_BADCRC;
|
return self::LSZ_BADCRC;
|
||||||
@ -1353,7 +1349,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
if ($rxstatus)
|
if ($rxstatus)
|
||||||
return ($rxstatus==self::RX_SKIP) ? self::ZSKIP : self::ZFERR;
|
return ($rxstatus==self::RX_SKIP) ? self::ZSKIP : self::ZFERR;
|
||||||
|
|
||||||
} while(TRUE);
|
} while (TRUE);
|
||||||
|
|
||||||
return self::LSZ_OK;
|
return self::LSZ_OK;
|
||||||
}
|
}
|
||||||
@ -1990,15 +1986,10 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
if ($this->DEBUG)
|
if ($this->DEBUG)
|
||||||
Log::debug(sprintf('%s: - CRC32',__METHOD__));
|
Log::debug(sprintf('%s: - CRC32',__METHOD__));
|
||||||
|
|
||||||
$crc = self::LSZ_INIT_CRC32;
|
for ($n=0;$n<strlen($data);$n++)
|
||||||
|
|
||||||
for ($n=0;$n<strlen($data);$n++) {
|
|
||||||
$this->ls_sendchar(ord($data[$n]));
|
$this->ls_sendchar(ord($data[$n]));
|
||||||
$crc = $this->CRC32_UPDATE(ord($data[$n]),$crc);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->client->buffer_add(chr(self::ZDLE).chr($frame));
|
$this->client->buffer_add(chr(self::ZDLE).chr($frame));
|
||||||
$crc = $this->CRC32_UPDATE($frame,$crc);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*chat*
|
*chat*
|
||||||
@ -2010,7 +2001,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$crc = $this->CRC32_FINISH($crc);
|
$crc = crc32($data.chr($frame));
|
||||||
$this->ls_sendchar($crc&0xff);
|
$this->ls_sendchar($crc&0xff);
|
||||||
$crc >>= 8;
|
$crc >>= 8;
|
||||||
$this->ls_sendchar($crc&0xff);
|
$this->ls_sendchar($crc&0xff);
|
||||||
@ -2024,15 +2015,11 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
if ($this->DEBUG)
|
if ($this->DEBUG)
|
||||||
Log::debug(sprintf('%s: - CRC16',__METHOD__));
|
Log::debug(sprintf('%s: - CRC16',__METHOD__));
|
||||||
|
|
||||||
$crc = self::LSZ_INIT_CRC16;
|
|
||||||
|
|
||||||
for ($n=0;$n<strlen($data);$n++) {
|
for ($n=0;$n<strlen($data);$n++) {
|
||||||
$this->ls_sendchar(ord($data[$n]));
|
$this->ls_sendchar(ord($data[$n]));
|
||||||
$crc = $this->CRC16USD_UPDATE(ord($data[$n]),$crc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->client->buffer_add(chr(self::ZDLE).chr($frame));
|
$this->client->buffer_add(chr(self::ZDLE).chr($frame));
|
||||||
$crc = $this->CRC16USD_UPDATE($frame,$crc);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*chat*
|
*chat*
|
||||||
@ -2044,7 +2031,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$crc &= 0xffff;
|
$crc = crc16($data.chr($frame));
|
||||||
$this->ls_sendchar($crc >> 8);
|
$this->ls_sendchar($crc >> 8);
|
||||||
$this->ls_sendchar($crc&0xff);
|
$this->ls_sendchar($crc&0xff);
|
||||||
}
|
}
|
||||||
@ -2284,7 +2271,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
return $rc;
|
return $rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while(
|
} while (
|
||||||
/* Here is window, and we send more than window without ACK*/
|
/* Here is window, and we send more than window without ACK*/
|
||||||
/* Frame was ZCRCW and here is no ACK for it */
|
/* Frame was ZCRCW and here is no ACK for it */
|
||||||
/* trys less than 10 */
|
/* trys less than 10 */
|
||||||
@ -2426,7 +2413,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
$trys++;
|
$trys++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (($rc=$this->ls_zrecvhdr($this->ls_rxHdr,$this->ls_HeaderTimeout))) {
|
switch ($rc=$this->ls_zrecvhdr($this->ls_rxHdr,$this->ls_HeaderTimeout)) {
|
||||||
/* Ok, he want our file */
|
/* Ok, he want our file */
|
||||||
case self::ZRPOS:
|
case self::ZRPOS:
|
||||||
$pos = $this->ls_fetchlong($this->ls_rxHdr);
|
$pos = $this->ls_fetchlong($this->ls_rxHdr);
|
||||||
@ -2472,6 +2459,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
$crc = $this->CRC32_UPDATE($c,$crc);
|
$crc = $this->CRC32_UPDATE($c,$crc);
|
||||||
|
|
||||||
$crc = $this->CRC32_FINISH($crc);
|
$crc = $this->CRC32_FINISH($crc);
|
||||||
|
dump([__METHOD__,'crc'=>$crc,'crc32'=>crc32(file_get_contents($send->name))]);
|
||||||
if (($rc=$this->ls_zsendhhdr(self::ZCRC,$this->ls_storelong($crc))) < 0)
|
if (($rc=$this->ls_zsendhhdr(self::ZCRC,$this->ls_storelong($crc))) < 0)
|
||||||
return $rc;
|
return $rc;
|
||||||
|
|
||||||
@ -2524,15 +2512,13 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->ls_sendhex($frametype);
|
$this->ls_sendhex($frametype);
|
||||||
$crc = $this->CRC16USD_UPDATE($frametype,self::LSZ_INIT_CRC16);
|
|
||||||
|
|
||||||
/* Send whole header */
|
/* Send whole header */
|
||||||
for ($n=0;$n<count($hdr);$n++) {
|
for ($n=0;$n<count($hdr);$n++) {
|
||||||
$this->ls_sendhex($hdr[$n]);
|
$this->ls_sendhex($hdr[$n]);
|
||||||
$crc = $this->CRC16USD_UPDATE((0xff&$hdr[$n]),$crc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$crc = ($crc&0xffff);
|
$crc = crc16(chr($frametype).join('',array_map(function($item) { return chr($item); },$hdr)));
|
||||||
$this->ls_sendhex($crc >> 8);
|
$this->ls_sendhex($crc >> 8);
|
||||||
$this->ls_sendhex($crc&0xff);
|
$this->ls_sendhex($crc&0xff);
|
||||||
$this->client->buffer_add(chr(self::CR));
|
$this->client->buffer_add(chr(self::CR));
|
||||||
|
@ -49,12 +49,7 @@ class Setup extends Model
|
|||||||
|
|
||||||
public static function product_id(int $c=self::PRODUCT_ID): string
|
public static function product_id(int $c=self::PRODUCT_ID): string
|
||||||
{
|
{
|
||||||
$x = substr(static::hexdigitslower,($c&0xf000)>>12,1);
|
return hexstr($c);
|
||||||
$x .= substr(static::hexdigitslower,($c&0x0f00)>>8,1);
|
|
||||||
$x .= substr(static::hexdigitslower,($c&0x00f0)>>4,1);
|
|
||||||
$x .= substr(static::hexdigitslower,($c&0x000f),1);
|
|
||||||
|
|
||||||
return $x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RELATIONS */
|
/* RELATIONS */
|
||||||
|
@ -4,38 +4,11 @@ namespace App\Traits;
|
|||||||
|
|
||||||
trait CRC
|
trait CRC
|
||||||
{
|
{
|
||||||
private function CRC16USD(string $string): int
|
|
||||||
{
|
|
||||||
$crc = self::CRC16USD_INIT;
|
|
||||||
|
|
||||||
for ($c=0;$c<strlen($string);$c++)
|
|
||||||
$crc = $this->CRC16USD_UPDATE(ord($string[$c]),$crc);
|
|
||||||
|
|
||||||
return $crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function CRC16USD_UPDATE($b,$crc): int
|
private function CRC16USD_UPDATE($b,$crc): int
|
||||||
{
|
{
|
||||||
return (self::crc16usd_tab[(($crc >> 8) ^ $b) & 0xff] ^ (($crc & 0x00ff) << 8)) & 0xffff;
|
return (self::crc16usd_tab[(($crc >> 8) ^ $b) & 0xff] ^ (($crc & 0x00ff) << 8)) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate CRC32
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
* @param bool $finish
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
private function CRC32(string $string,bool $finish=TRUE): int
|
|
||||||
{
|
|
||||||
$crc = 0xffffffff;
|
|
||||||
|
|
||||||
for ($i=0;$i<strlen($string);$i++)
|
|
||||||
$crc = (self::crc32_tab[($crc^ord($string[$i])) & 0xff] ^ (($crc>>8) & 0x00ffffff)) & 0xffffffff;
|
|
||||||
|
|
||||||
return $finish ? $this->CRC32_FINISH($crc) : $crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function CRC32_FINISH($crc)
|
private function CRC32_FINISH($crc)
|
||||||
{
|
{
|
||||||
return ~$crc & 0xffffffff;
|
return ~$crc & 0xffffffff;
|
||||||
|
@ -54,56 +54,25 @@ if (! function_exists('hex_dump')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split out an FTN address into its parts
|
* Send a value has hex chars
|
||||||
*
|
|
||||||
* This function takes a fully qualified FTN address and splits it out into
|
|
||||||
* its components:
|
|
||||||
* Z:N/F.P@D
|
|
||||||
*/
|
*/
|
||||||
if (! function_exists('ftn_address_split')) {
|
if (! function_exists('hexstr')) {
|
||||||
function ftn_address_split(string $address,$key=NULL)
|
function hexstr(int $int)
|
||||||
{
|
{
|
||||||
if ($key AND ! in_array($key,['z','n','f','p','d']))
|
if ($int > 0xffff)
|
||||||
{
|
throw new Exception('Int too large for hexstr');
|
||||||
throw new \Exception('Unknown key :'.$key.' for '.$address);
|
|
||||||
|
$hexdigitslower = '0123456789abcdef';
|
||||||
|
$x = '';
|
||||||
|
|
||||||
|
if ($int > 0xff) {
|
||||||
|
$x .= substr($hexdigitslower,($int&0xf000)>>12,1);
|
||||||
|
$x .= substr($hexdigitslower,($int&0x0f00)>>8,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//$data = "10:12/909";
|
$x .= substr($hexdigitslower,($int&0x00f0)>>4,1);
|
||||||
//$data = "10:12/909.5";
|
$x .= substr($hexdigitslower,($int&0x000f),1);
|
||||||
//$data = "10:12/909@foo";
|
|
||||||
//$data = "10:12/909.5@foo";
|
|
||||||
$z = substr($address,0,strpos($address,':'));
|
|
||||||
|
|
||||||
if ($key == 'z')
|
return $x;
|
||||||
return $z;
|
|
||||||
|
|
||||||
$x = strpos($address,':')+1;
|
|
||||||
$n = substr($address,$x,strpos($address,'/')-$x);
|
|
||||||
|
|
||||||
if ($key == 'n')
|
|
||||||
return $n;
|
|
||||||
|
|
||||||
$x = strpos($address,'/')+1;
|
|
||||||
$f = substr($address,$x,
|
|
||||||
(strpos($address,'.') ?:
|
|
||||||
(strpos($address,'@') ?: strlen($address)))-$x);
|
|
||||||
|
|
||||||
if ($key == 'f')
|
|
||||||
return $f;
|
|
||||||
|
|
||||||
$x = strpos($address,'.');
|
|
||||||
$p = $x ? substr($address,$x+1,(strpos($address,'@') ?: strlen($address))-$x-1) : 0;
|
|
||||||
|
|
||||||
if ($key == 'p')
|
|
||||||
return $p;
|
|
||||||
|
|
||||||
// @todo We dont handle domain yet.
|
|
||||||
$x = strpos($address,'@');
|
|
||||||
$d = $x ? substr($address,$x+1) : NULL;
|
|
||||||
|
|
||||||
if ($key == 'd')
|
|
||||||
return $d;
|
|
||||||
|
|
||||||
return ['z'=>$z,'n'=>$n,'f'=>$f,'p'=>$p,'d'=>$d];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user