Huge performance improvements
This commit is contained in:
parent
d9ca05fa86
commit
c2ce149436
@ -230,7 +230,7 @@ trait AuthKeyHandler
|
|||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Do some checks
|
* Do some checks
|
||||||
*/
|
*/
|
||||||
$server_DH_inner_data_length = $this->get_length(new \danog\MadelineProto\Stream($answer));
|
$server_DH_inner_data_length = $this->get_length($answer);
|
||||||
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
|
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
|
||||||
throw new \danog\MadelineProto\SecurityException('answer_hash mismatch.');
|
throw new \danog\MadelineProto\SecurityException('answer_hash mismatch.');
|
||||||
}
|
}
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*
|
|
||||||
Copyright 2016-2017 Daniil Gentili
|
|
||||||
(https://daniil.it)
|
|
||||||
This file is part of MadelineProto.
|
|
||||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
The PWRTelegram API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the GNU Affero General Public License for more details.
|
|
||||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
|
||||||
If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace danog\MadelineProto;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Just a stream wrapper.
|
|
||||||
*/
|
|
||||||
class Stream
|
|
||||||
{
|
|
||||||
public $pos = 0;
|
|
||||||
|
|
||||||
public function __construct($string)
|
|
||||||
{
|
|
||||||
$this->string = $string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function read($length)
|
|
||||||
{
|
|
||||||
$d = substr($this->string, $this->pos, $length);
|
|
||||||
$this->pos += $length;
|
|
||||||
|
|
||||||
return $d;
|
|
||||||
}
|
|
||||||
}
|
|
@ -89,7 +89,7 @@ trait TL
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$name = preg_replace(['/#.*/', '/\s.*/'], '', $line);
|
$name = preg_replace(['/#.*/', '/\s.*/'], '', $line);
|
||||||
if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
|
if ($this->in_array($name, ['bytes', 'int128', 'int256', 'int512'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$clean = preg_replace([
|
$clean = preg_replace([
|
||||||
@ -132,7 +132,7 @@ trait TL
|
|||||||
$dparams = [];
|
$dparams = [];
|
||||||
}
|
}
|
||||||
$TL_dict[$type][$key][$type === 'constructors' ? 'predicate' : 'method'] = $name;
|
$TL_dict[$type][$key][$type === 'constructors' ? 'predicate' : 'method'] = $name;
|
||||||
$TL_dict[$type][$key]['id'] = \danog\PHP\Struct::unpack('<i', \danog\PHP\Struct::pack('<I', hexdec($id)))[0];
|
$TL_dict[$type][$key]['id'] = \danog\PHP\Struct::unpack('<i', pack('V', hexdec($id)))[0];
|
||||||
$TL_dict[$type][$key]['params'] = [];
|
$TL_dict[$type][$key]['params'] = [];
|
||||||
$TL_dict[$type][$key]['type'] = preg_replace(['/.+\s/', '/;/'], '', $line);
|
$TL_dict[$type][$key]['type'] = preg_replace(['/.+\s/', '/;/'], '', $line);
|
||||||
if ($layer !== null) {
|
if ($layer !== null) {
|
||||||
@ -205,7 +205,7 @@ trait TL
|
|||||||
|
|
||||||
public function get_method_namespaces()
|
public function get_method_namespaces()
|
||||||
{
|
{
|
||||||
return array_unique(array_values($this->methods->method_namespace));
|
return array_unique($this->array_values($this->methods->method_namespace));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize_bool($bool)
|
public function serialize_bool($bool)
|
||||||
@ -238,7 +238,7 @@ trait TL
|
|||||||
throw new Exception('given value ('.$object.") isn't numeric");
|
throw new Exception('given value ('.$object.") isn't numeric");
|
||||||
}
|
}
|
||||||
|
|
||||||
return \danog\PHP\Struct::pack('<I', $object);
|
return pack('V', $object);
|
||||||
case 'long':
|
case 'long':
|
||||||
if (is_object($object)) {
|
if (is_object($object)) {
|
||||||
return str_pad(strrev($object->toBytes()), 8, chr(0));
|
return str_pad(strrev($object->toBytes()), 8, chr(0));
|
||||||
@ -247,7 +247,6 @@ trait TL
|
|||||||
if (is_string($object) && strlen($object) === 8) {
|
if (is_string($object) && strlen($object) === 8) {
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_numeric($object)) {
|
if (!is_numeric($object)) {
|
||||||
throw new Exception('given value ('.$object.") isn't numeric");
|
throw new Exception('given value ('.$object.") isn't numeric");
|
||||||
}
|
}
|
||||||
@ -311,7 +310,7 @@ trait TL
|
|||||||
}
|
}
|
||||||
$auto = false;
|
$auto = false;
|
||||||
|
|
||||||
if ((!is_array($object) || (isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) && in_array($type['type'], ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
|
if ((!$this->is_array($object) || (isset($object['_']) && $this->constructors->find_by_predicate($object['_'])['type'] !== $type['type'])) && $this->in_array($type['type'], ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer'])) {
|
||||||
$object = $this->get_info($object);
|
$object = $this->get_info($object);
|
||||||
if (!isset($object[$type['type']])) {
|
if (!isset($object[$type['type']])) {
|
||||||
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
||||||
@ -392,7 +391,7 @@ trait TL
|
|||||||
$arguments['flags'] = $flags;
|
$arguments['flags'] = $flags;
|
||||||
foreach ($tl['params'] as $current_argument) {
|
foreach ($tl['params'] as $current_argument) {
|
||||||
if (!isset($arguments[$current_argument['name']])) {
|
if (!isset($arguments[$current_argument['name']])) {
|
||||||
if ($current_argument['flag'] && (in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) {
|
if ($current_argument['flag'] && ($this->in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) {
|
||||||
//\danog\MadelineProto\Logger::log(['Skipping '.$current_argument['name'].' of type '.$current_argument['type']);
|
//\danog\MadelineProto\Logger::log(['Skipping '.$current_argument['name'].' of type '.$current_argument['type']);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -423,7 +422,7 @@ trait TL
|
|||||||
}
|
}
|
||||||
throw new Exception('Missing required parameter ('.$current_argument['name'].')');
|
throw new Exception('Missing required parameter ('.$current_argument['name'].')');
|
||||||
}
|
}
|
||||||
if (!is_array($arguments[$current_argument['name']]) && $current_argument['type'] === 'InputEncryptedChat') {
|
if (!$this->is_array($arguments[$current_argument['name']]) && $current_argument['type'] === 'InputEncryptedChat') {
|
||||||
$arguments[$current_argument['name']] = $this->secret_chats[$arguments[$current_argument['name']]]['InputEncryptedChat'];
|
$arguments[$current_argument['name']] = $this->secret_chats[$arguments[$current_argument['name']]]['InputEncryptedChat'];
|
||||||
}
|
}
|
||||||
if ($current_argument['type'] === 'DataJSON') {
|
if ($current_argument['type'] === 'DataJSON') {
|
||||||
@ -439,9 +438,17 @@ trait TL
|
|||||||
|
|
||||||
public function get_length($bytes_io, $type = ['type' => ''])
|
public function get_length($bytes_io, $type = ['type' => ''])
|
||||||
{
|
{
|
||||||
|
if (is_string($bytes_io)) {
|
||||||
|
$res = fopen('php://memory', 'rw+b');
|
||||||
|
fwrite($res, $bytes_io);
|
||||||
|
fseek($res, 0);
|
||||||
|
$bytes_io = $res;
|
||||||
|
} elseif (!is_resource($bytes_io)) {
|
||||||
|
throw new Exception('An invalid bytes_io handle was provided.');
|
||||||
|
}
|
||||||
$this->deserialize($bytes_io, $type);
|
$this->deserialize($bytes_io, $type);
|
||||||
|
|
||||||
return $bytes_io->pos;
|
return ftell($bytes_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -450,46 +457,48 @@ trait TL
|
|||||||
public function deserialize($bytes_io, $type = ['type' => ''])
|
public function deserialize($bytes_io, $type = ['type' => ''])
|
||||||
{
|
{
|
||||||
if (is_string($bytes_io)) {
|
if (is_string($bytes_io)) {
|
||||||
$bytes_io = new \danog\MadelineProto\Stream($bytes_io);
|
$res = fopen('php://memory', 'rw+b');
|
||||||
} elseif (!is_object($bytes_io)) {
|
fwrite($res, $bytes_io);
|
||||||
|
fseek($res, 0);
|
||||||
|
$bytes_io = $res;
|
||||||
|
} elseif (!is_resource($bytes_io)) {
|
||||||
throw new Exception('An invalid bytes_io handle was provided.');
|
throw new Exception('An invalid bytes_io handle was provided.');
|
||||||
}
|
}
|
||||||
//\danog\MadelineProto\Logger::log(['Deserializing '.$type['type'].' at byte '.$bytes_io->pos]);
|
|
||||||
switch ($type['type']) {
|
switch ($type['type']) {
|
||||||
case 'Bool':
|
case 'Bool':
|
||||||
return $this->deserialize_bool($bytes_io->read(4));
|
return $this->deserialize_bool(stream_get_contents($bytes_io, 4));
|
||||||
case 'int':
|
case 'int':
|
||||||
return \danog\PHP\Struct::unpack('<i', $bytes_io->read(4))[0];
|
return \danog\PHP\Struct::unpack('<i', stream_get_contents($bytes_io, 4))[0];
|
||||||
case '#':
|
case '#':
|
||||||
return \danog\PHP\Struct::unpack('<I', $bytes_io->read(4))[0];
|
return unpack('V', stream_get_contents($bytes_io, 4))[1];
|
||||||
case 'long':
|
case 'long':
|
||||||
return $this->bigint || isset($type['strlong']) ? $bytes_io->read(8) : \danog\PHP\Struct::unpack('<q', $bytes_io->read(8))[0];
|
return $this->bigint || isset($type['strlong']) ? stream_get_contents($bytes_io, 8) : \danog\PHP\Struct::unpack('<q', stream_get_contents($bytes_io, 8))[0];
|
||||||
case 'double':
|
case 'double':
|
||||||
return \danog\PHP\Struct::unpack('<d', $bytes_io->read(8))[0];
|
return \danog\PHP\Struct::unpack('<d', stream_get_contents($bytes_io, 8))[0];
|
||||||
case 'int128':
|
case 'int128':
|
||||||
return $bytes_io->read(16);
|
return stream_get_contents($bytes_io, 16);
|
||||||
case 'int256':
|
case 'int256':
|
||||||
return $bytes_io->read(32);
|
return stream_get_contents($bytes_io, 32);
|
||||||
case 'int512':
|
case 'int512':
|
||||||
return $bytes_io->read(64);
|
return stream_get_contents($bytes_io, 64);
|
||||||
case 'string':
|
case 'string':
|
||||||
case 'bytes':
|
case 'bytes':
|
||||||
$l = \danog\PHP\Struct::unpack('<B', $bytes_io->read(1))[0];
|
$l = ord(stream_get_contents($bytes_io, 1));
|
||||||
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 = \danog\PHP\Struct::unpack('<I', $bytes_io->read(3).chr(0))[0];
|
$long_len = unpack('V', stream_get_contents($bytes_io, 3).chr(0))[1];
|
||||||
$x = $bytes_io->read($long_len);
|
$x = stream_get_contents($bytes_io, $long_len);
|
||||||
$resto = $this->posmod(-$long_len, 4);
|
$resto = $this->posmod(-$long_len, 4);
|
||||||
if ($resto > 0) {
|
if ($resto > 0) {
|
||||||
$bytes_io->pos += $resto;
|
stream_get_contents($bytes_io, $resto);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$x = $bytes_io->read($l);
|
$x = stream_get_contents($bytes_io, $l);
|
||||||
$resto = $this->posmod(-($l + 1), 4);
|
$resto = $this->posmod(-($l + 1), 4);
|
||||||
if ($resto > 0) {
|
if ($resto > 0) {
|
||||||
$bytes_io->pos += $resto;
|
stream_get_contents($bytes_io, $resto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!is_string($x)) {
|
if (!is_string($x)) {
|
||||||
@ -500,7 +509,7 @@ trait TL
|
|||||||
case 'true':
|
case 'true':
|
||||||
return true;
|
return true;
|
||||||
case 'Vector t':
|
case 'Vector t':
|
||||||
$id = \danog\PHP\Struct::unpack('<i', $bytes_io->read(4))[0];
|
$id = \danog\PHP\Struct::unpack('<i', stream_get_contents($bytes_io, 4))[0];
|
||||||
$constructorData = $this->constructors->find_by_id($id);
|
$constructorData = $this->constructors->find_by_id($id);
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
throw new Exception('Could not extract type: '.$type['type'].' with id '.$id);
|
throw new Exception('Could not extract type: '.$type['type'].' with id '.$id);
|
||||||
@ -515,7 +524,7 @@ trait TL
|
|||||||
throw new Exception('Invalid vector constructor: '.$constructorData['predicate']);
|
throw new Exception('Invalid vector constructor: '.$constructorData['predicate']);
|
||||||
}
|
}
|
||||||
case 'vector':
|
case 'vector':
|
||||||
$count = \danog\PHP\Struct::unpack('<i', $bytes_io->read(4))[0];
|
$count = \danog\PHP\Struct::unpack('<i', stream_get_contents($bytes_io, 4))[0];
|
||||||
$result = [];
|
$result = [];
|
||||||
$type['type'] = $type['subtype'];
|
$type['type'] = $type['subtype'];
|
||||||
for ($i = 0; $i < $count; $i++) {
|
for ($i = 0; $i < $count; $i++) {
|
||||||
@ -533,7 +542,7 @@ trait TL
|
|||||||
} else {
|
} else {
|
||||||
$constructorData = $this->constructors->find_by_predicate($type['type']);
|
$constructorData = $this->constructors->find_by_predicate($type['type']);
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
$id = \danog\PHP\Struct::unpack('<i', $bytes_io->read(4))[0];
|
$id = \danog\PHP\Struct::unpack('<i', stream_get_contents($bytes_io, 4))[0];
|
||||||
$constructorData = $this->constructors->find_by_id($id);
|
$constructorData = $this->constructors->find_by_id($id);
|
||||||
if ($constructorData === false) {
|
if ($constructorData === false) {
|
||||||
throw new Exception('Could not extract type: '.$type['type'].' with id '.$id);
|
throw new Exception('Could not extract type: '.$type['type'].' with id '.$id);
|
||||||
@ -576,7 +585,7 @@ trait TL
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id', 'key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) {
|
if ($this->in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id', 'key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) {
|
||||||
$arg['strlong'] = true;
|
$arg['strlong'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,6 +596,7 @@ trait TL
|
|||||||
$arg['datacenter'] = $type['datacenter'];
|
$arg['datacenter'] = $type['datacenter'];
|
||||||
}
|
}
|
||||||
$x[$arg['name']] = $this->deserialize($bytes_io, $arg);
|
$x[$arg['name']] = $this->deserialize($bytes_io, $arg);
|
||||||
|
|
||||||
if ($arg['name'] === 'random_bytes') {
|
if ($arg['name'] === 'random_bytes') {
|
||||||
if (strlen($x[$arg['name']]) < 15) {
|
if (strlen($x[$arg['name']]) < 15) {
|
||||||
throw new \danog\MadelineProto\SecurityException('random_bytes is too small!');
|
throw new \danog\MadelineProto\SecurityException('random_bytes is too small!');
|
||||||
|
@ -57,19 +57,19 @@ trait Tools
|
|||||||
|
|
||||||
public function is_array($elem)
|
public function is_array($elem)
|
||||||
{
|
{
|
||||||
return is_array($elem) || (is_object($elem) && get_class($elem) === 'Volatile');
|
return is_array($elem) || ($elem instanceof \Volatile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function array_replace_recursive($a, ...$b)
|
public function __call($method, $params)
|
||||||
{
|
{
|
||||||
return array_replace_recursive($this->array_cast_recursive($a), ...$this->array_cast_recursive($b));
|
return $method(...$this->array_cast_recursive($params));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function array_cast_recursive($array)
|
public function array_cast_recursive($array)
|
||||||
{
|
{
|
||||||
if ($this->is_array($array)) {
|
if ($this->is_array($array)) {
|
||||||
if (!is_array($array)) {
|
if (!is_array($array)) {
|
||||||
$array = $array;
|
$array = (array) $array;
|
||||||
}
|
}
|
||||||
foreach ($array as $key => $value) {
|
foreach ($array as $key => $value) {
|
||||||
$array[$key] = $this->array_cast_recursive($value);
|
$array[$key] = $this->array_cast_recursive($value);
|
||||||
|
Loading…
Reference in New Issue
Block a user