Removed useless dependencies, made logging class static, made access to the PHPStruct class static, added default_dc setting in the settings array

This commit is contained in:
danogentili 2016-11-15 15:39:42 +03:00
parent 37fa11e81a
commit 67de600bb8
13 changed files with 132 additions and 217 deletions

View File

@ -11,8 +11,7 @@
"phpseclib/phpseclib": "^2.0", "phpseclib/phpseclib": "^2.0",
"paragonie/constant_time_encoding": "^1|^2", "paragonie/constant_time_encoding": "^1|^2",
"paragonie/random_compat": "^2.0", "paragonie/random_compat": "^2.0",
"php": ">=5.6.0", "php": ">=5.6.0"
"icicleio/icicle": "^0.9.6"
}, },
"authors": [ "authors": [
{ {

103
composer.lock generated
View File

@ -4,21 +4,21 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "966d0bc73f86b42249ee2a37fea56e64", "hash": "8d6fcaae1bc321e5d42b8b4749ea4266",
"content-hash": "c5463d805ceb0061da4eca7c688a973e", "content-hash": "d004c37ebd93efd29d86d09824fdd71b",
"packages": [ "packages": [
{ {
"name": "danog/phpstruct", "name": "danog/phpstruct",
"version": "1.1.2.1", "version": "1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/danog/PHPStruct.git", "url": "https://github.com/danog/PHPStruct.git",
"reference": "da588a75fd4fdbd72745fd48f1241b775aee8fa9" "reference": "f050e9bedf2edd6828c4759cc56fd665895a5e90"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/danog/PHPStruct/zipball/da588a75fd4fdbd72745fd48f1241b775aee8fa9", "url": "https://api.github.com/repos/danog/PHPStruct/zipball/f050e9bedf2edd6828c4759cc56fd665895a5e90",
"reference": "da588a75fd4fdbd72745fd48f1241b775aee8fa9", "reference": "f050e9bedf2edd6828c4759cc56fd665895a5e90",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -58,93 +58,26 @@
"struct", "struct",
"unpack" "unpack"
], ],
"time": "2016-08-25 11:07:20" "time": "2016-11-14 15:09:50"
},
{
"name": "icicleio/icicle",
"version": "v0.9.6",
"source": {
"type": "git",
"url": "https://github.com/icicleio/icicle.git",
"reference": "84a3cc6f7dc38500f4ed9bdae79f458d191cb119"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icicleio/icicle/zipball/84a3cc6f7dc38500f4ed9bdae79f458d191cb119",
"reference": "84a3cc6f7dc38500f4ed9bdae79f458d191cb119",
"shasum": ""
},
"require": {
"php": "^5.5|^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6"
},
"suggest": {
"ext-ev": "Provides an event loop with better performance.",
"ext-pcntl": "Enables custom signal handling."
},
"type": "library",
"autoload": {
"psr-4": {
"Icicle\\": "src"
},
"files": [
"src/functions.php",
"src/Awaitable/functions.php",
"src/Coroutine/functions.php",
"src/Loop/functions.php",
"src/Observable/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Piotrowski",
"email": "aaron@icicle.io"
}
],
"description": "Icicle is a PHP library for writing asynchronous code using synchronous coding techniques.",
"homepage": "http://icicle.io",
"keywords": [
"Socket",
"async",
"asynchronous",
"awaitable",
"coroutine",
"event",
"generator",
"interruptible",
"multitasking",
"network",
"promise",
"server",
"stream"
],
"time": "2016-03-31 16:34:26"
}, },
{ {
"name": "paragonie/constant_time_encoding", "name": "paragonie/constant_time_encoding",
"version": "v1.0.1", "version": "v2.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/paragonie/constant_time_encoding.git", "url": "https://github.com/paragonie/constant_time_encoding.git",
"reference": "d96e63b79a7135a65659ba5b1cb02826172bfedd" "reference": "e085e08c939de49707dbf64315d178d90fbc708d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d96e63b79a7135a65659ba5b1cb02826172bfedd", "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/e085e08c939de49707dbf64315d178d90fbc708d",
"reference": "d96e63b79a7135a65659ba5b1cb02826172bfedd", "reference": "e085e08c939de49707dbf64315d178d90fbc708d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.3|^7" "php": "^7"
}, },
"require-dev": { "require-dev": {
"paragonie/random_compat": "^1.4|^2.0",
"phpunit/phpunit": "4.*|5.*" "phpunit/phpunit": "4.*|5.*"
}, },
"type": "library", "type": "library",
@ -186,20 +119,20 @@
"hex2bin", "hex2bin",
"rfc4648" "rfc4648"
], ],
"time": "2016-06-13 01:00:24" "time": "2016-07-11 20:32:06"
}, },
{ {
"name": "paragonie/random_compat", "name": "paragonie/random_compat",
"version": "v2.0.3", "version": "v2.0.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/paragonie/random_compat.git", "url": "https://github.com/paragonie/random_compat.git",
"reference": "c0125896dbb151380ab47e96c621741e79623beb" "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/c0125896dbb151380ab47e96c621741e79623beb", "url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e",
"reference": "c0125896dbb151380ab47e96c621741e79623beb", "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -234,7 +167,7 @@
"pseudorandom", "pseudorandom",
"random" "random"
], ],
"time": "2016-10-17 15:23:22" "time": "2016-11-07 23:38:38"
}, },
{ {
"name": "phpseclib/phpseclib", "name": "phpseclib/phpseclib",

View File

@ -32,8 +32,6 @@ class Connection extends Tools
- udp - udp
*/ */
$this->protocol = $protocol; $this->protocol = $protocol;
// Istantiate struct class
$this->struct = new \danog\PHP\StructTools();
switch ($this->protocol) { switch ($this->protocol) {
case 'tcp_abridged': case 'tcp_abridged':
$this->sock = fsockopen('tcp://'.$ip.':'.$port); $this->sock = fsockopen('tcp://'.$ip.':'.$port);
@ -137,13 +135,13 @@ class Connection extends Tools
if (strlen($packet_length_data) < 4) { if (strlen($packet_length_data) < 4) {
throw new Exception('Nothing in the socket!'); throw new Exception('Nothing in the socket!');
} }
$packet_length = $this->struct->unpack('<I', $packet_length_data)[0]; $packet_length = \danog\PHP\Struct::unpack('<I', $packet_length_data)[0];
$packet = $this->read($packet_length - 4); $packet = $this->read($packet_length - 4);
if (!($this->newcrc32($packet_length_data.substr($packet, 0, -4)) == $this->struct->unpack('<I', substr($packet, -4))[0])) { if (!($this->newcrc32($packet_length_data.substr($packet, 0, -4)) == \danog\PHP\Struct::unpack('<I', substr($packet, -4))[0])) {
throw new Exception('CRC32 was not correct!'); throw new Exception('CRC32 was not correct!');
} }
$this->in_seq_no++; $this->in_seq_no++;
$in_seq_no = $this->struct->unpack('<I', substr($packet, 0, 4))[0]; $in_seq_no = \danog\PHP\Struct::unpack('<I', substr($packet, 0, 4))[0];
if ($in_seq_no != $this->in_seq_no) { if ($in_seq_no != $this->in_seq_no) {
throw new Exception('Incoming seq_no mismatch'); throw new Exception('Incoming seq_no mismatch');
} }
@ -154,7 +152,7 @@ class Connection extends Tools
if (strlen($packet_length_data) < 4) { if (strlen($packet_length_data) < 4) {
throw new Exception('Nothing in the socket!'); throw new Exception('Nothing in the socket!');
} }
$packet_length = $this->struct->unpack('<I', $packet_length_data)[0]; $packet_length = \danog\PHP\Struct::unpack('<I', $packet_length_data)[0];
$packet = $this->sock->read($packet_length); $packet = $this->sock->read($packet_length);
$payload = $this->fopen_and_write('php://memory', 'rw+b', $packet); $payload = $this->fopen_and_write('php://memory', 'rw+b', $packet);
break; break;
@ -168,7 +166,7 @@ class Connection extends Tools
$packet_length <<= 2; $packet_length <<= 2;
} else { } else {
$packet_length_data = $this->sock->read(3); $packet_length_data = $this->sock->read(3);
$packet_length = $this->struct->unpack('<I', $packet_length_data.pack('x'))[0] << 2; $packet_length = \danog\PHP\Struct::unpack('<I', $packet_length_data.pack('x'))[0] << 2;
} }
$packet = $this->sock->read($packet_length); $packet = $this->sock->read($packet_length);
$payload = $this->fopen_and_write('php://memory', 'rw+b', $packet); $payload = $this->fopen_and_write('php://memory', 'rw+b', $packet);
@ -183,12 +181,12 @@ class Connection extends Tools
switch ($this->protocol) { switch ($this->protocol) {
case 'tcp_full': case 'tcp_full':
$this->out_seq_no++; $this->out_seq_no++;
$step1 = $this->struct->pack('<II', (strlen($message) + 12), $this->out_seq_no).$message; $step1 = \danog\PHP\Struct::pack('<II', (strlen($message) + 12), $this->out_seq_no).$message;
$step2 = $step1.$this->struct->pack('<I', $this->newcrc32($step1)); $step2 = $step1.\danog\PHP\Struct::pack('<I', $this->newcrc32($step1));
$this->write($step2); $this->write($step2);
break; break;
case 'tcp_intermediate': case 'tcp_intermediate':
$step1 = $this->struct->pack('<I', strlen($message)).$message; $step1 = \danog\PHP\Struct::pack('<I', strlen($message)).$message;
$this->write($step1); $this->write($step1);
break; break;
case 'tcp_abridged': case 'tcp_abridged':
@ -196,7 +194,7 @@ class Connection extends Tools
if ($len < 127) { if ($len < 127) {
$step1 = chr($len).$message; $step1 = chr($len).$message;
} else { } else {
$step1 = chr(127).substr($this->struct->pack('<I', $len), 0, 3).$message; $step1 = chr(127).substr(\danog\PHP\Struct::pack('<I', $len), 0, 3).$message;
} }
$this->write($step1); $this->write($step1);
break; break;

View File

@ -36,13 +36,15 @@ class DataCenter extends Tools
]; ];
} }
} }
$this->dc_connect(2); $this->dc_connect($settings['default_dc']);
} }
public function dc_disconnect($dc_number) public function dc_disconnect($dc_number)
{ {
if (isset($this->sockets[$dc_number])) { if (isset($this->sockets[$dc_number])) {
\danog\MadelineProto\Logging::log("Disconnecting from DC ".$dc_number."...");
unset($this->sockets[$dc_number]); unset($this->sockets[$dc_number]);
unset($this->curdc);
} }
} }
@ -51,6 +53,8 @@ class DataCenter extends Tools
if (isset($this->sockets[$dc_number])) { if (isset($this->sockets[$dc_number])) {
return; return;
} }
\danog\MadelineProto\Logging::log("Connecting to DC ".$dc_number."...");
if ($settings == []) { if ($settings == []) {
$settings = $this->settings[$dc_number]; $settings = $this->settings[$dc_number];
} }

View File

@ -17,9 +17,9 @@ namespace danog\MadelineProto;
class Logging class Logging
{ {
public $mode = null; public static $mode = null;
public $optional = null; public static $optional = null;
public static $constructed = false;
/* /*
* Constructor function * Constructor function
* Accepts various logging modes: * Accepts various logging modes:
@ -28,49 +28,32 @@ class Logging
* 2 - Log to file defined in second parameter * 2 - Log to file defined in second parameter
* 3 - Echo logs * 3 - Echo logs
*/ */
public function __construct($mode, $optional = null) public static function constructor($mode, $optional = null)
{ {
$this->mode = (string) $mode; if ($mode == null) {
$this->optional = $optional; throw new Exception("No mode was specified!");
}
public function __invoke(...$params)
{
foreach ($params as $param) {
switch ($this->mode) {
case '1':
error_log($param);
break;
case '2':
error_log($param, 3, $this->optional);
break;
case '3':
echo $param.PHP_EOL;
break;
default:
break;
}
} }
self::$mode = (string) $mode;
self::$optional = $optional;
self::$constructed = true;
} }
public function log(...$params) public static function log(...$params)
{ {
if ($this->mode == null) { if (!self::$constructed) {
$mode = array_pop($params); throw new Exception("The constructor function wasn't called! Please call the constructor function before using this method.");
} else {
$mode = $this->mode;
} }
foreach ($params as $param) { foreach ($params as $param) {
if (!is_string($param)) { if (!is_string($param)) {
$param = var_export($param, true); $param = var_export($param, true);
} }
$param = str_pad(basename(debug_backtrace()[0]['file'], '.php').': ', 16).(($mode == 3) ? "\t" : '').$param; $param = str_pad(basename(debug_backtrace()[0]['file'], '.php').': ', 16).((self::$mode == 3) ? "\t" : '').$param;
switch ($mode) { switch (self::$mode) {
case '1': case '1':
error_log($param); error_log($param);
break; break;
case '2': case '2':
error_log($param, 3, $this->optional); error_log($param, 3, self::$optional);
break; break;
case '3': case '3':
echo $param.PHP_EOL; echo $param.PHP_EOL;

View File

@ -64,6 +64,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
'test_mode' => true, 'test_mode' => true,
'port' => '443', 'port' => '443',
], ],
'default_dc' => 2
], ],
'app_info' => [ 'app_info' => [
'api_id' => 25628, 'api_id' => 25628,
@ -106,24 +107,19 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
} }
} }
$this->settings = $settings; $this->settings = $settings;
// Istantiate logging class // Set up logging class
$this->log = new Logging($this->settings['logging']['logging'], $this->settings['logging']['logging_param']); \danog\MadelineProto\Logging::constructor($this->settings['logging']['logging'], $this->settings['logging']['logging_param']);
// Connect to servers // Connect to servers
$this->log->log('Connecting to server...'); \danog\MadelineProto\Logging::log('Connecting to server...');
$this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']); $this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
$this->connection->dc_connect(2);
// Load rsa key // Load rsa key
$this->log->log('Loading RSA key...'); \danog\MadelineProto\Logging::log('Loading RSA key...');
$this->key = new RSA($settings['authorization']['rsa_key']); $this->key = new RSA($settings['authorization']['rsa_key']);
// Istantiate struct class
$this->log->log('Initializing StructTools...');
$this->struct = new \danog\PHP\StructTools();
// Istantiate TL class // Istantiate TL class
$this->log->log('Translating tl schemas...'); \danog\MadelineProto\Logging::log('Translating tl schemas...');
$this->tl = new TL\TL($this->settings['tl_schema']['src']); $this->tl = new TL\TL($this->settings['tl_schema']['src']);
$this->seq_no = 0; $this->seq_no = 0;
@ -134,10 +130,10 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
if ($this->settings['authorization']['temp_auth_key'] == null || $this->settings['authorization']['auth_key'] == null) { if ($this->settings['authorization']['temp_auth_key'] == null || $this->settings['authorization']['auth_key'] == null) {
if ($this->settings['authorization']['auth_key'] == null) { if ($this->settings['authorization']['auth_key'] == null) {
$this->log->log('Generating permanent authorization key...'); \danog\MadelineProto\Logging::log('Generating permanent authorization key...');
$this->settings['authorization']['auth_key'] = $this->create_auth_key(-1); $this->settings['authorization']['auth_key'] = $this->create_auth_key(-1);
} }
$this->log->log('Generating temporary authorization key...'); \danog\MadelineProto\Logging::log('Generating temporary authorization key...');
$this->settings['authorization']['temp_auth_key'] = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in']); $this->settings['authorization']['temp_auth_key'] = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in']);
} }
$this->write_client_info(); $this->write_client_info();
@ -154,21 +150,25 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
public function write_client_info() public function write_client_info()
{ {
$this->log->log('Writing client info...'); \danog\MadelineProto\Logging::log('Writing client info...');
$nearestDc = $this->method_call('invokeWithLayer', [ $nearestDc = $this->method_call(
'layer' => $this->settings['tl_schema']['layer'], 'invokeWithLayer',
'query' => $this->tl->serialize_method('initConnection', [
array_merge( 'layer' => $this->settings['tl_schema']['layer'],
$this->settings['app_info'], 'query' => $this->tl->serialize_method('initConnection',
['query' => $this->tl->serialize_method('help.getNearestDc', [])] array_merge(
) $this->settings['app_info'],
), ['query' => $this->tl->serialize_method('help.getNearestDc', [])]
]); )
$this->log->log('Current dc is '.$nearestDc['this_dc'].', nearest dc is '.$nearestDc['nearest_dc'].' in '.$nearestDc['country'].'.'); ),
]
);
\danog\MadelineProto\Logging::log('Current dc is '.$nearestDc['this_dc'].', nearest dc is '.$nearestDc['nearest_dc'].' in '.$nearestDc['country'].'.');
if ($nearestDc['nearest_dc'] != $nearestDc['this_dc']) { if ($nearestDc['nearest_dc'] != $nearestDc['this_dc']) {
$this->log->log('Switching to dc '.$nearestDc['nearest_dc'].'...'); \danog\MadelineProto\Logging::log('Switching to dc '.$nearestDc['nearest_dc'].'...');
$this->connection->dc_connect($nearestDc['nearest_dc']); $this->connection->dc_connect($nearestDc['nearest_dc']);
$this->settings['connection_settings']['default_dc'] = $nearestDc['nearest_dc'];
} }
} }

View File

@ -23,7 +23,7 @@ class AuthKeyHandler extends AckHandler
public function create_auth_key($expires_in = -1) public function create_auth_key($expires_in = -1)
{ {
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id_total) { foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id_total) {
$this->log->log('Requesting pq'); \danog\MadelineProto\Logging::log('Requesting pq');
/** /**
* *********************************************************************** * ***********************************************************************
@ -94,14 +94,14 @@ class AuthKeyHandler extends AckHandler
throw new Exception("couldn't compute p and q."); throw new Exception("couldn't compute p and q.");
} }
$this->log->log('Factorization '.$pq.' = '.$p.' * '.$q); \danog\MadelineProto\Logging::log('Factorization '.$pq.' = '.$p.' * '.$q);
/* /*
* *********************************************************************** * ***********************************************************************
* Serialize object for req_DH_params * Serialize object for req_DH_params
*/ */
$p_bytes = $this->struct->pack('>I', (string) $p); $p_bytes = \danog\PHP\Struct::pack('>I', (string) $p);
$q_bytes = $this->struct->pack('>I', (string) $q); $q_bytes = \danog\PHP\Struct::pack('>I', (string) $q);
$new_nonce = \phpseclib\Crypt\Random::string(32); $new_nonce = \phpseclib\Crypt\Random::string(32);
if ($expires_in < 0) { if ($expires_in < 0) {
@ -138,7 +138,7 @@ class AuthKeyHandler extends AckHandler
$to_encrypt = $sha_digest.$data.$random_bytes; $to_encrypt = $sha_digest.$data.$random_bytes;
$encrypted_data = $this->key->encrypt($to_encrypt); $encrypted_data = $this->key->encrypt($to_encrypt);
$this->log->log('Starting Diffie Hellman key exchange'); \danog\MadelineProto\Logging::log('Starting Diffie Hellman key exchange');
/* /*
* *********************************************************************** * ***********************************************************************
* Starting Diffie Hellman key exchange, Server authentication * Starting Diffie Hellman key exchange, Server authentication
@ -254,14 +254,14 @@ class AuthKeyHandler extends AckHandler
$server_time = $server_DH_inner_data['server_time']; $server_time = $server_DH_inner_data['server_time'];
$this->timedelta = $server_time - time(); $this->timedelta = $server_time - time();
$this->log->log(sprintf('Server-client time delta = %.1f s', $this->timedelta)); \danog\MadelineProto\Logging::log(sprintf('Server-client time delta = %.1f s', $this->timedelta));
/* /*
* *********************************************************************** * ***********************************************************************
* Define some needed numbers for BigInteger * Define some needed numbers for BigInteger
*/ */
$this->log->log('Executing dh_prime checks...'); \danog\MadelineProto\Logging::log('Executing dh_prime checks...');
$one = new \phpseclib\Math\BigInteger(1); $one = new \phpseclib\Math\BigInteger(1);
$two = new \phpseclib\Math\BigInteger(2); $two = new \phpseclib\Math\BigInteger(2);
$twoe2047 = new \phpseclib\Math\BigInteger('16158503035655503650357438344334975980222051334857742016065172713762327569433945446598600705761456731844358980460949009747059779575245460547544076193224141560315438683650498045875098875194826053398028819192033784138396109321309878080919047169238085235290822926018152521443787945770532904303776199561965192760957166694834171210342487393282284747428088017663161029038902829665513096354230157075129296432088558362971801859230928678799175576150822952201848806616643615613562842355410104862578550863465661734839271290328348967522998634176499319107762583194718667771801067716614802322659239302476074096777926805529798115328'); $twoe2047 = new \phpseclib\Math\BigInteger('16158503035655503650357438344334975980222051334857742016065172713762327569433945446598600705761456731844358980460949009747059779575245460547544076193224141560315438683650498045875098875194826053398028819192033784138396109321309878080919047169238085235290822926018152521443787945770532904303776199561965192760957166694834171210342487393282284747428088017663161029038902829665513096354230157075129296432088558362971801859230928678799175576150822952201848806616643615613562842355410104862578550863465661734839271290328348967522998634176499319107762583194718667771801067716614802322659239302476074096777926805529798115328');
@ -420,9 +420,9 @@ class AuthKeyHandler extends AckHandler
throw new Exception('wrong new_nonce_hash1'); throw new Exception('wrong new_nonce_hash1');
} }
$this->log->log('Diffie Hellman key exchange processed successfully'); \danog\MadelineProto\Logging::log('Diffie Hellman key exchange processed successfully');
$res_authorization['server_salt'] = $this->struct->unpack('<q', substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0))[0]; $res_authorization['server_salt'] = \danog\PHP\Struct::unpack('<q', substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0))[0];
$res_authorization['auth_key'] = $auth_key_str; $res_authorization['auth_key'] = $auth_key_str;
$res_authorization['id'] = substr($auth_key_sha, -8); $res_authorization['id'] = substr($auth_key_sha, -8);
@ -430,7 +430,7 @@ class AuthKeyHandler extends AckHandler
$res_authorization['expires_in'] = $expires_in; $res_authorization['expires_in'] = $expires_in;
} }
$this->log->log('Auth key generated'); \danog\MadelineProto\Logging::log('Auth key generated');
$this->timedelta = 0; $this->timedelta = 0;
return $res_authorization; return $res_authorization;
@ -440,14 +440,14 @@ class AuthKeyHandler extends AckHandler
} }
//repeat foreach //repeat foreach
$this->log->log('Retrying Auth'); \danog\MadelineProto\Logging::log('Retrying Auth');
break; break;
case 'dh_gen_fail': case 'dh_gen_fail':
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) { if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
throw new Exception('wrong new_nonce_hash_3'); throw new Exception('wrong new_nonce_hash_3');
} }
$this->log->log('Auth Failed'); \danog\MadelineProto\Logging::log('Auth Failed');
break 2; break 2;
default: default:
throw new Exception('Response Error'); throw new Exception('Response Error');
@ -461,11 +461,11 @@ class AuthKeyHandler extends AckHandler
public function bind_temp_auth_key($expires_in) public function bind_temp_auth_key($expires_in)
{ {
$nonce = $this->struct->unpack('<q', \phpseclib\Crypt\Random::string(8))[0]; $nonce = \danog\PHP\Struct::unpack('<q', \phpseclib\Crypt\Random::string(8))[0];
$expires_at = time() + $expires_in; $expires_at = time() + $expires_in;
$temp_auth_key_id = $this->struct->unpack('<q', $this->settings['authorization']['temp_auth_key']['id'])[0]; $temp_auth_key_id = \danog\PHP\Struct::unpack('<q', $this->settings['authorization']['temp_auth_key']['id'])[0];
$perm_auth_key_id = $this->struct->unpack('<q', $this->settings['authorization']['auth_key']['id'])[0]; $perm_auth_key_id = \danog\PHP\Struct::unpack('<q', $this->settings['authorization']['auth_key']['id'])[0];
$temp_session_id = $this->struct->unpack('<q', $this->settings['authorization']['session_id'])[0]; $temp_session_id = \danog\PHP\Struct::unpack('<q', $this->settings['authorization']['session_id'])[0];
$message_data = $this->tl->serialize_obj('bind_auth_key_inner', $message_data = $this->tl->serialize_obj('bind_auth_key_inner',
[ [
'nonce' => $nonce, 'nonce' => $nonce,
@ -476,16 +476,16 @@ class AuthKeyHandler extends AckHandler
] ]
); );
$int_message_id = $this->generate_message_id(); $int_message_id = $this->generate_message_id();
$message_id = $this->struct->pack('<Q', $int_message_id); $message_id = \danog\PHP\Struct::pack('<Q', $int_message_id);
$seq_no = 0; $seq_no = 0;
$encrypted_data = \phpseclib\Crypt\Random::string(16).$message_id.$this->struct->pack('<II', $seq_no, strlen($message_data)).$message_data; $encrypted_data = \phpseclib\Crypt\Random::string(16).$message_id.\danog\PHP\Struct::pack('<II', $seq_no, strlen($message_data)).$message_data;
$message_key = substr(sha1($encrypted_data, true), -16); $message_key = substr(sha1($encrypted_data, true), -16);
$padding = \phpseclib\Crypt\Random::string($this->posmod(-strlen($encrypted_data), 16)); $padding = \phpseclib\Crypt\Random::string($this->posmod(-strlen($encrypted_data), 16));
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->settings['authorization']['auth_key']['auth_key']); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->settings['authorization']['auth_key']['auth_key']);
$encrypted_message = $this->settings['authorization']['auth_key']['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv); $encrypted_message = $this->settings['authorization']['auth_key']['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
if ($this->method_call('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], $message_id)) { if ($this->method_call('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], $message_id)) {
$this->log->log('Successfully binded temporary and permanent authorization keys.'); \danog\MadelineProto\Logging::log('Successfully binded temporary and permanent authorization keys.');
$this->write_client_info(); $this->write_client_info();
return true; return true;

View File

@ -25,7 +25,7 @@ class CallHandler extends AuthKeyHandler
$response = null; $response = null;
$count = 0; $count = 0;
while ($response == null && $count++ < $this->settings['max_tries']['response']) { while ($response == null && $count++ < $this->settings['max_tries']['response']) {
$this->log->log('Getting response (try number '.$count.' for '.$optional_name.')...'); \danog\MadelineProto\Logging::log('Getting response (try number '.$count.' for '.$optional_name.')...');
$last_received = $this->recv_message(); $last_received = $this->recv_message();
$this->handle_message($last_sent, $last_received); $this->handle_message($last_sent, $last_received);
if (isset($this->outgoing_messages[$last_sent]['response']) && isset($this->incoming_messages[$this->outgoing_messages[$last_sent]['response']]['content'])) { if (isset($this->outgoing_messages[$last_sent]['response']) && isset($this->incoming_messages[$this->outgoing_messages[$last_sent]['response']]['content'])) {
@ -54,7 +54,7 @@ class CallHandler extends AuthKeyHandler
$this->outgoing_messages[$int_message_id]['content'] = ['method' => $method, 'args' => $args]; $this->outgoing_messages[$int_message_id]['content'] = ['method' => $method, 'args' => $args];
$server_answer = $this->wait_for_response($int_message_id, $method); $server_answer = $this->wait_for_response($int_message_id, $method);
} catch (Exception $e) { } catch (Exception $e) {
$this->log->log('An error occurred while calling method '.$method.': '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Recreating connection and retrying to call method...'); \danog\MadelineProto\Logging::log('An error occurred while calling method '.$method.': '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Recreating connection and retrying to call method...');
unset($this->connection); unset($this->connection);
$this->connection = new \danog\MadelineProto\DataCenter($this->settings['connection'], $this->settings['connection_settings']); $this->connection = new \danog\MadelineProto\DataCenter($this->settings['connection'], $this->settings['connection_settings']);
continue; continue;
@ -76,7 +76,7 @@ class CallHandler extends AuthKeyHandler
$this->outgoing_messages[$int_message_id]['content'] = ['object' => $object, 'args' => $args]; $this->outgoing_messages[$int_message_id]['content'] = ['object' => $object, 'args' => $args];
// $server_answer = $this->wait_for_response($int_message_id); // $server_answer = $this->wait_for_response($int_message_id);
} catch (Exception $e) { } catch (Exception $e) {
$this->log->log('An error occurred while calling object '.$object.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().'. Recreating connection and retrying to call object...'); \danog\MadelineProto\Logging::log('An error occurred while calling object '.$object.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().'. Recreating connection and retrying to call object...');
unset($this->connection); unset($this->connection);
$this->connection = new \danog\MadelineProto\DataCenter($this->settings['connection'], $this->settings['connection_settings']); $this->connection = new \danog\MadelineProto\DataCenter($this->settings['connection'], $this->settings['connection_settings']);
continue; continue;

View File

@ -26,12 +26,12 @@ class MessageHandler extends Crypt
if ($int_message_id == null) { if ($int_message_id == null) {
$int_message_id = $this->generate_message_id(); $int_message_id = $this->generate_message_id();
} }
$message_id = $this->struct->pack('<Q', $int_message_id); $message_id = \danog\PHP\Struct::pack('<Q', $int_message_id);
if (($this->settings['authorization']['temp_auth_key']['auth_key'] == null) || ($this->settings['authorization']['temp_auth_key']['server_salt'] == null)) { if (($this->settings['authorization']['temp_auth_key']['auth_key'] == null) || ($this->settings['authorization']['temp_auth_key']['server_salt'] == null)) {
$message = $this->string2bin('\x00\x00\x00\x00\x00\x00\x00\x00').$message_id.$this->struct->pack('<I', strlen($message_data)).$message_data; $message = $this->string2bin('\x00\x00\x00\x00\x00\x00\x00\x00').$message_id.\danog\PHP\Struct::pack('<I', strlen($message_data)).$message_data;
} else { } else {
$seq_no = $this->generate_seq_no($content_related); $seq_no = $this->generate_seq_no($content_related);
$encrypted_data = $this->struct->pack('<q', $this->settings['authorization']['temp_auth_key']['server_salt']).$this->settings['authorization']['session_id'].$message_id.$this->struct->pack('<II', $seq_no, strlen($message_data)).$message_data; $encrypted_data = \danog\PHP\Struct::pack('<q', $this->settings['authorization']['temp_auth_key']['server_salt']).$this->settings['authorization']['session_id'].$message_id.\danog\PHP\Struct::pack('<II', $seq_no, strlen($message_data)).$message_data;
$message_key = substr(sha1($encrypted_data, true), -16); $message_key = substr(sha1($encrypted_data, true), -16);
$padding = \phpseclib\Crypt\Random::string($this->posmod(-strlen($encrypted_data), 16)); $padding = \phpseclib\Crypt\Random::string($this->posmod(-strlen($encrypted_data), 16));
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->settings['authorization']['temp_auth_key']['auth_key']); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->settings['authorization']['temp_auth_key']['auth_key']);
@ -50,11 +50,11 @@ class MessageHandler extends Crypt
{ {
$payload = $this->connection->read_message(); $payload = $this->connection->read_message();
if (fstat($payload)['size'] == 4) { if (fstat($payload)['size'] == 4) {
throw new Exception('Server response error: '.abs($this->struct->unpack('<i', fread($payload, 4))[0])); throw new Exception('Server response error: '.abs(\danog\PHP\Struct::unpack('<i', fread($payload, 4))[0]));
} }
$auth_key_id = fread($payload, 8); $auth_key_id = fread($payload, 8);
if ($auth_key_id == $this->string2bin('\x00\x00\x00\x00\x00\x00\x00\x00')) { if ($auth_key_id == $this->string2bin('\x00\x00\x00\x00\x00\x00\x00\x00')) {
list($message_id, $message_length) = $this->struct->unpack('<QI', fread($payload, 12)); list($message_id, $message_length) = \danog\PHP\Struct::unpack('<QI', fread($payload, 12));
$this->check_message_id($message_id, false); $this->check_message_id($message_id, false);
$message_data = fread($payload, $message_length); $message_data = fread($payload, $message_length);
} elseif ($auth_key_id == $this->settings['authorization']['temp_auth_key']['id']) { } elseif ($auth_key_id == $this->settings['authorization']['temp_auth_key']['id']) {
@ -63,7 +63,7 @@ class MessageHandler extends Crypt
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->settings['authorization']['temp_auth_key']['auth_key'], 'from server'); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->settings['authorization']['temp_auth_key']['auth_key'], 'from server');
$decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv); $decrypted_data = $this->ige_decrypt($encrypted_data, $aes_key, $aes_iv);
$server_salt = $this->struct->unpack('<q', substr($decrypted_data, 0, 8))[0]; $server_salt = \danog\PHP\Struct::unpack('<q', substr($decrypted_data, 0, 8))[0];
if ($server_salt != $this->settings['authorization']['temp_auth_key']['server_salt']) { if ($server_salt != $this->settings['authorization']['temp_auth_key']['server_salt']) {
// throw new Exception('Server salt mismatch (my server salt '.$this->settings['authorization']['temp_auth_key']['server_salt'].' is not equal to server server salt '.$server_salt.').'); // throw new Exception('Server salt mismatch (my server salt '.$this->settings['authorization']['temp_auth_key']['server_salt'].' is not equal to server server salt '.$server_salt.').');
} }
@ -73,13 +73,13 @@ class MessageHandler extends Crypt
throw new Exception('Session id mismatch.'); throw new Exception('Session id mismatch.');
} }
$message_id = $this->struct->unpack('<Q', substr($decrypted_data, 16, 8))[0]; $message_id = \danog\PHP\Struct::unpack('<Q', substr($decrypted_data, 16, 8))[0];
$this->check_message_id($message_id, false); $this->check_message_id($message_id, false);
$seq_no = $this->struct->unpack('<I', substr($decrypted_data, 24, 4)) [0]; $seq_no = \danog\PHP\Struct::unpack('<I', substr($decrypted_data, 24, 4)) [0];
// Dunno how to handle any incorrect sequence numbers // Dunno how to handle any incorrect sequence numbers
$message_data_length = $this->struct->unpack('<I', substr($decrypted_data, 28, 4)) [0]; $message_data_length = \danog\PHP\Struct::unpack('<I', substr($decrypted_data, 28, 4)) [0];
if ($message_data_length > strlen($decrypted_data)) { if ($message_data_length > strlen($decrypted_data)) {
throw new Exception('message_data_length is too big'); throw new Exception('message_data_length is too big');

View File

@ -62,13 +62,13 @@ class ResponseHandler extends MsgIdHandler
case 'new_session_created': case 'new_session_created':
$this->settings['authorization']['temp_auth_key']['server_salt'] = $response['server_salt']; $this->settings['authorization']['temp_auth_key']['server_salt'] = $response['server_salt'];
$this->ack_incoming_message_id($last_received); // Acknowledge that I received the server's response $this->ack_incoming_message_id($last_received); // Acknowledge that I received the server's response
$this->log->log('new session created'); \danog\MadelineProto\Logging::log('new session created');
$this->log->log($response); \danog\MadelineProto\Logging::log($response);
break; break;
case 'msg_container': case 'msg_container':
$responses = []; $responses = [];
$this->log->log('Received container.'); \danog\MadelineProto\Logging::log('Received container.');
$this->log->log($response['messages']); \danog\MadelineProto\Logging::log($response['messages']);
foreach ($response['messages'] as $message) { foreach ($response['messages'] as $message) {
$this->check_message_id($message['msg_id'], false, true); $this->check_message_id($message['msg_id'], false, true);
$this->incoming_messages[$message['msg_id']] = ['seq_no' => $message['seqno'], 'content' => $message['body']]; $this->incoming_messages[$message['msg_id']] = ['seq_no' => $message['seqno'], 'content' => $message['body']];
@ -87,8 +87,8 @@ class ResponseHandler extends MsgIdHandler
return end($responses); return end($responses);
break; break;
default: default:
$this->log->log('Received multiple responses, returning last one'); \danog\MadelineProto\Logging::log('Received multiple responses, returning last one');
$this->log->log($responses); \danog\MadelineProto\Logging::log($responses);
return end($responses); return end($responses);
break; break;
@ -106,8 +106,8 @@ class ResponseHandler extends MsgIdHandler
} }
break; break;
case 'http_wait': case 'http_wait':
$this->log->log('Received http wait.'); \danog\MadelineProto\Logging::log('Received http wait.');
$this->log->log($response); \danog\MadelineProto\Logging::log($response);
break; break;
case 'gzip_packed': case 'gzip_packed':
$this->incoming_messages[$last_received]['content'] = gzdecode($response); $this->incoming_messages[$last_received]['content'] = gzdecode($response);

View File

@ -80,7 +80,7 @@ class PrimeModule extends Tools
{ {
$pqstr = (string) $pq; $pqstr = (string) $pq;
$this->log->log('Trying to use the python factorization module'); \danog\MadelineProto\Logging::log('Trying to use the python factorization module');
if (function_exists('shell_exec')) { if (function_exists('shell_exec')) {
try { try {
$res = json_decode(shell_exec('python '.__DIR__.'/getpq.py '.$pqstr)); $res = json_decode(shell_exec('python '.__DIR__.'/getpq.py '.$pqstr));
@ -91,7 +91,7 @@ class PrimeModule extends Tools
} }
} }
$this->log->log('Trying to use the wolfram alpha factorization module'); \danog\MadelineProto\Logging::log('Trying to use the wolfram alpha factorization module');
$query = 'Do prime factorization of '.$pqstr; $query = 'Do prime factorization of '.$pqstr;
$params = [ $params = [
'async' => true, 'async' => true,
@ -120,7 +120,7 @@ class PrimeModule extends Tools
return $res; return $res;
} }
$this->log->log('Trying to use the native factorization module'); \danog\MadelineProto\Logging::log('Trying to use the native factorization module');
$res = $this->find_small_multiplier_lopatin((int) $pqstr); $res = $this->find_small_multiplier_lopatin((int) $pqstr);
$res = [$res, $pqstr / $res]; $res = [$res, $pqstr / $res];
if ($res[1] != 1) { if ($res[1] != 1) {

View File

@ -26,7 +26,6 @@ class RSA extends TL\TL
$this->key->loadKey($key); $this->key->loadKey($key);
$this->n = $this->key->modulus; $this->n = $this->key->modulus;
$this->e = $this->key->exponent; $this->e = $this->key->exponent;
$this->struct = new \danog\PHP\StructTools();
$this->fp_bytes = substr(sha1($this->serialize_param('bytes', null, $this->n->toBytes()).$this->serialize_param('bytes', null, $this->e->toBytes()), true), -8); $this->fp_bytes = substr(sha1($this->serialize_param('bytes', null, $this->n->toBytes()).$this->serialize_param('bytes', null, $this->e->toBytes()), true), -8);
$this->fp = new \phpseclib\Math\BigInteger(strrev($this->fp_bytes), -256); $this->fp = new \phpseclib\Math\BigInteger(strrev($this->fp_bytes), -256);
} }

View File

@ -16,7 +16,6 @@ class TL extends \danog\MadelineProto\Tools
{ {
public function __construct($filename) public function __construct($filename)
{ {
$this->struct = new \danog\PHP\StructTools();
if (is_array($filename)) { if (is_array($filename)) {
$TL_dict = ['constructors' => [], 'methods' => []]; $TL_dict = ['constructors' => [], 'methods' => []];
foreach ($filename as $file) { foreach ($filename as $file) {
@ -52,7 +51,7 @@ class TL extends \danog\MadelineProto\Tools
} else { } else {
throw new Exception('Could not extract type: '.$type_); throw new Exception('Could not extract type: '.$type_);
} }
$bytes_io .= $this->struct->pack('<i', $tl_constructor->id); $bytes_io .= \danog\PHP\Struct::pack('<i', $tl_constructor->id);
foreach ($tl_constructor->params as $arg) { foreach ($tl_constructor->params as $arg) {
$bytes_io .= $this->serialize_param($arg['type'], $arg['subtype'], $kwargs[$arg['name']]); $bytes_io .= $this->serialize_param($arg['type'], $arg['subtype'], $kwargs[$arg['name']]);
} }
@ -88,7 +87,7 @@ class TL extends \danog\MadelineProto\Tools
} else { } else {
throw new Exception('Could not extract type: '.$type_); throw new Exception('Could not extract type: '.$type_);
} }
$bytes_io .= $this->struct->pack('<i', $tl_method->id); $bytes_io .= \danog\PHP\Struct::pack('<i', $tl_method->id);
foreach ($tl_method->params as $arg) { foreach ($tl_method->params as $arg) {
if (!isset($kwargs[$arg['name']])) { if (!isset($kwargs[$arg['name']])) {
if ($arg['name'] == 'flags') { if ($arg['name'] == 'flags') {
@ -117,7 +116,7 @@ class TL extends \danog\MadelineProto\Tools
throw new Exception('Given value is too long.'); throw new Exception('Given value is too long.');
} }
return $this->struct->pack('<i', $value); return \danog\PHP\Struct::pack('<i', $value);
break; break;
case '#': case '#':
if (!is_numeric($value)) { if (!is_numeric($value)) {
@ -127,14 +126,14 @@ class TL extends \danog\MadelineProto\Tools
throw new Exception('Given value is too long.'); throw new Exception('Given value is too long.');
} }
return $this->struct->pack('<I', $value); return \danog\PHP\Struct::pack('<I', $value);
break; break;
case 'long': case 'long':
if (!is_numeric($value)) { if (!is_numeric($value)) {
throw new Exception("serialize_param: given value isn't numeric"); throw new Exception("serialize_param: given value isn't numeric");
} }
return $this->struct->pack('<q', $value); return \danog\PHP\Struct::pack('<q', $value);
break; break;
case 'int128': case 'int128':
case 'int256': case 'int256':
@ -145,19 +144,19 @@ class TL extends \danog\MadelineProto\Tools
return $value; return $value;
break; break;
case 'double': case 'double':
return $this->struct->pack('<d', $value); return \danog\PHP\Struct::pack('<d', $value);
break; break;
case 'string': case 'string':
case 'bytes': case 'bytes':
$l = strlen($value); $l = strlen($value);
$concat = ''; $concat = '';
if ($l <= 253) { if ($l <= 253) {
$concat .= $this->struct->pack('<b', $l); $concat .= \danog\PHP\Struct::pack('<b', $l);
$concat .= $value; $concat .= $value;
$concat .= pack('@'.$this->posmod((-$l - 1), 4)); $concat .= pack('@'.$this->posmod((-$l - 1), 4));
} else { } else {
$concat .= $this->string2bin('\xfe'); $concat .= $this->string2bin('\xfe');
$concat .= substr($this->struct->pack('<i', $l), 0, 3); $concat .= substr(\danog\PHP\Struct::pack('<i', $l), 0, 3);
$concat .= $value; $concat .= $value;
$concat .= pack('@'.$this->posmod(-$l, 4)); $concat .= pack('@'.$this->posmod(-$l, 4));
} }
@ -167,9 +166,9 @@ class TL extends \danog\MadelineProto\Tools
case '!X': case '!X':
return $value; return $value;
case 'Vector t': case 'Vector t':
$concat = $this->struct->pack('<i', $this->constructor_type['vector']->id); $concat = \danog\PHP\Struct::pack('<i', $this->constructor_type['vector']->id);
$concat .= $this->struct->pack('<l', count($value)); $concat .= \danog\PHP\Struct::pack('<l', count($value));
foreach ($value as $curv) { foreach ($value as $curv) {
$concat .= $this->serialize_param($subtype, null, $curv); $concat .= $this->serialize_param($subtype, null, $curv);
} }
@ -198,16 +197,16 @@ class TL extends \danog\MadelineProto\Tools
} }
switch ($type_) { switch ($type_) {
case 'int': case 'int':
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0]; $x = \danog\PHP\Struct::unpack('<i', fread($bytes_io, 4)) [0];
break; break;
case '#': case '#':
$x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0]; $x = \danog\PHP\Struct::unpack('<I', fread($bytes_io, 4)) [0];
break; break;
case 'long': case 'long':
$x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0]; $x = \danog\PHP\Struct::unpack('<q', fread($bytes_io, 8)) [0];
break; break;
case 'double': case 'double':
$x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0]; $x = \danog\PHP\Struct::unpack('<d', fread($bytes_io, 8)) [0];
break; break;
case 'int128': case 'int128':
$x = fread($bytes_io, 16); $x = fread($bytes_io, 16);
@ -217,12 +216,12 @@ class TL extends \danog\MadelineProto\Tools
break; break;
case 'string': case 'string':
case 'bytes': case 'bytes':
$l = $this->struct->unpack('<B', fread($bytes_io, 1)) [0]; $l = \danog\PHP\Struct::unpack('<B', fread($bytes_io, 1)) [0];
if ($l > 254) { if ($l > 254) {
throw new Exception('Length is too big'); throw new Exception('Length is too big');
} }
if ($l == 254) { if ($l == 254) {
$long_len = $this->struct->unpack('<I', fread($bytes_io, 3).$this->string2bin('\x00')) [0]; $long_len = \danog\PHP\Struct::unpack('<I', fread($bytes_io, 3).$this->string2bin('\x00')) [0];
$x = fread($bytes_io, $long_len); $x = fread($bytes_io, $long_len);
$resto = $this->posmod(-$long_len, 4); $resto = $this->posmod(-$long_len, 4);
if ($resto > 0) { if ($resto > 0) {
@ -243,7 +242,7 @@ class TL extends \danog\MadelineProto\Tools
if ($subtype == null) { if ($subtype == null) {
throw new Exception("deserialize: subtype isn't null"); throw new Exception("deserialize: subtype isn't null");
} }
$count = $this->struct->unpack('<l', fread($bytes_io, 4)) [0]; $count = \danog\PHP\Struct::unpack('<l', fread($bytes_io, 4)) [0];
$x = []; $x = [];
foreach ($this->range($count) as $i) { foreach ($this->range($count) as $i) {
$x[] = $this->deserialize($bytes_io, $subtype); $x[] = $this->deserialize($bytes_io, $subtype);
@ -254,7 +253,7 @@ class TL extends \danog\MadelineProto\Tools
$tl_elem = $this->constructor_type[$type_]; $tl_elem = $this->constructor_type[$type_];
} else { } else {
$Idata = fread($bytes_io, 4); $Idata = fread($bytes_io, 4);
$i = $this->struct->unpack('<i', $Idata) [0]; $i = \danog\PHP\Struct::unpack('<i', $Idata) [0];
if (isset($this->constructor_id[$i])) { if (isset($this->constructor_id[$i])) {
$tl_elem = $this->constructor_id[$i]; $tl_elem = $this->constructor_id[$i];
} else { } else {