mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 07:38:58 +01:00
Fixed bugs, improved exception erro rhandling, blah, blah, blah (#RTFC)
This commit is contained in:
parent
87e625ea9c
commit
c168890384
1
.gitignore
vendored
1
.gitignore
vendored
@ -64,3 +64,4 @@ vendor
|
|||||||
*save*
|
*save*
|
||||||
*bak
|
*bak
|
||||||
number.php
|
number.php
|
||||||
|
token.php
|
||||||
|
@ -12,16 +12,16 @@ If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class API extends Tools
|
class API extends APIFactory
|
||||||
{
|
{
|
||||||
public $API;
|
public $API;
|
||||||
public $settings;
|
public $settings;
|
||||||
|
public $namespace = '';
|
||||||
|
|
||||||
public function __construct($params = [])
|
public function __construct($params = [])
|
||||||
{
|
{
|
||||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||||
$this->API = new MTProto($params);
|
$this->API = new MTProto($params);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Running APIFactory...');
|
\danog\MadelineProto\Logger::log('Running APIFactory...');
|
||||||
foreach ($this->API->tl->methods->method_namespace as $namespace => $method) {
|
foreach ($this->API->tl->methods->method_namespace as $namespace => $method) {
|
||||||
$this->{$method} = new APIFactory($method, $this->API);
|
$this->{$method} = new APIFactory($method, $this->API);
|
||||||
@ -35,15 +35,11 @@ class API extends Tools
|
|||||||
|
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('MadelineProto is ready!');
|
\danog\MadelineProto\Logger::log('MadelineProto is ready!');
|
||||||
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __call($name, $arguments)
|
|
||||||
{
|
|
||||||
return $this->API->method_call($name, $arguments[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ class APIFactory
|
|||||||
|
|
||||||
public function __call($name, $arguments)
|
public function __call($name, $arguments)
|
||||||
{
|
{
|
||||||
|
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||||
return $this->API->method_call($this->namespace.$name, $arguments[0]);
|
return $this->API->method_call($this->namespace.$name, $arguments[0]);
|
||||||
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@ class Connection extends Tools
|
|||||||
public $sock = null;
|
public $sock = null;
|
||||||
|
|
||||||
public $protocol = null;
|
public $protocol = null;
|
||||||
|
public $ip = null;
|
||||||
|
public $port = null;
|
||||||
|
public $timeout = null;
|
||||||
|
|
||||||
public $time_delta = 0;
|
public $time_delta = 0;
|
||||||
public $temp_auth_key;
|
public $temp_auth_key;
|
||||||
@ -27,7 +30,7 @@ class Connection extends Tools
|
|||||||
public $session_id;
|
public $session_id;
|
||||||
public $seq_no = 0;
|
public $seq_no = 0;
|
||||||
|
|
||||||
public function __construct($ip, $port, $protocol = 'tcp_full')
|
public function __construct($ip, $port, $protocol, $timeout)
|
||||||
{
|
{
|
||||||
// Can use:
|
// Can use:
|
||||||
/*
|
/*
|
||||||
@ -39,12 +42,13 @@ class Connection extends Tools
|
|||||||
- udp
|
- udp
|
||||||
*/
|
*/
|
||||||
$this->protocol = $protocol;
|
$this->protocol = $protocol;
|
||||||
|
$this->timeout = $timeout;
|
||||||
$this->ip = $ip;
|
$this->ip = $ip;
|
||||||
$this->port = $port;
|
$this->port = $port;
|
||||||
switch ($this->protocol) {
|
switch ($this->protocol) {
|
||||||
case 'tcp_abridged':
|
case 'tcp_abridged':
|
||||||
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
|
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
|
||||||
stream_set_timeout($this->sock, 5);
|
stream_set_timeout($this->sock, $timeout);
|
||||||
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
|
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
|
||||||
throw new Exception("Connection: couldn't connect to socket.");
|
throw new Exception("Connection: couldn't connect to socket.");
|
||||||
}
|
}
|
||||||
@ -52,7 +56,7 @@ class Connection extends Tools
|
|||||||
break;
|
break;
|
||||||
case 'tcp_intermediate':
|
case 'tcp_intermediate':
|
||||||
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
|
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
|
||||||
stream_set_timeout($this->sock, 5);
|
stream_set_timeout($this->sock, $timeout);
|
||||||
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
|
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
|
||||||
throw new Exception("Connection: couldn't connect to socket.");
|
throw new Exception("Connection: couldn't connect to socket.");
|
||||||
}
|
}
|
||||||
@ -60,7 +64,7 @@ class Connection extends Tools
|
|||||||
break;
|
break;
|
||||||
case 'tcp_full':
|
case 'tcp_full':
|
||||||
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
|
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
|
||||||
stream_set_timeout($this->sock, 5);
|
stream_set_timeout($this->sock, $timeout);
|
||||||
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
|
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
|
||||||
throw new Exception("Connection: couldn't connect to socket.");
|
throw new Exception("Connection: couldn't connect to socket.");
|
||||||
}
|
}
|
||||||
@ -98,7 +102,7 @@ class Connection extends Tools
|
|||||||
public function close_and_reopen()
|
public function close_and_reopen()
|
||||||
{
|
{
|
||||||
$this->__destruct();
|
$this->__destruct();
|
||||||
$this->__construct($this->ip, $this->port, $this->protocol);
|
$this->__construct($this->ip, $this->port, $this->protocol, $this->timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,7 @@ class DataCenter extends Tools
|
|||||||
{
|
{
|
||||||
public $referenced_variables = ['time_delta', 'temp_auth_key', 'auth_key', 'session_id', 'seq_no'];
|
public $referenced_variables = ['time_delta', 'temp_auth_key', 'auth_key', 'session_id', 'seq_no'];
|
||||||
public $sockets;
|
public $sockets;
|
||||||
|
public $curdc = 0;
|
||||||
|
|
||||||
public function __construct($dclist, $settings)
|
public function __construct($dclist, $settings)
|
||||||
{
|
{
|
||||||
@ -36,6 +37,7 @@ class DataCenter extends Tools
|
|||||||
'protocol' => 'tcp_full',
|
'protocol' => 'tcp_full',
|
||||||
'port' => '443',
|
'port' => '443',
|
||||||
'test_mode' => true,
|
'test_mode' => true,
|
||||||
|
'timeout' => 10,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,10 +57,9 @@ class DataCenter extends Tools
|
|||||||
public function dc_connect($dc_number, $settings = [])
|
public function dc_connect($dc_number, $settings = [])
|
||||||
{
|
{
|
||||||
if (isset($this->sockets[$dc_number])) {
|
if (isset($this->sockets[$dc_number])) {
|
||||||
return false;
|
|
||||||
$this->set_curdc($dc_number);
|
$this->set_curdc($dc_number);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
$this->set_curdc($dc_number);
|
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Connecting to DC '.$dc_number.'...');
|
\danog\MadelineProto\Logger::log('Connecting to DC '.$dc_number.'...');
|
||||||
|
|
||||||
@ -71,8 +72,8 @@ class DataCenter extends Tools
|
|||||||
$path = $settings['test_mode'] ? 'apiw_test1' : 'apiw1';
|
$path = $settings['test_mode'] ? 'apiw_test1' : 'apiw1';
|
||||||
$address = 'https://'.$subdomain.'.web.telegram.org/'.$path;
|
$address = 'https://'.$subdomain.'.web.telegram.org/'.$path;
|
||||||
}
|
}
|
||||||
$this->sockets[$dc_number] = new Connection($address, $settings['port'], $settings['protocol']);
|
$this->sockets[$dc_number] = new Connection($address, $settings['port'], $settings['protocol'], $settings['timeout']);
|
||||||
|
$this->set_curdc($dc_number);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,11 +85,11 @@ class DataCenter extends Tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unset_curdc($dc_number)
|
public function unset_curdc()
|
||||||
{
|
{
|
||||||
unset($this->curdc);
|
$this->curdc = 0;
|
||||||
foreach ($this->referenced_variables as $key) {
|
foreach ($this->referenced_variables as $key) {
|
||||||
unset($this->sockets[$dc_number]->{$key});
|
unset($this->{$key});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class DebugTools
|
|||||||
public static function hex_dump(...$what)
|
public static function hex_dump(...$what)
|
||||||
{
|
{
|
||||||
foreach ($what as $w) {
|
foreach ($what as $w) {
|
||||||
var_dump(bin2hex($w));
|
\danog\MadelienProto\Logger::log(bin2hex($w));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,16 +14,6 @@ namespace danog\MadelineProto;
|
|||||||
|
|
||||||
class Exception extends \Exception
|
class Exception extends \Exception
|
||||||
{
|
{
|
||||||
public function __construct($message, $code = 0, Exception $previous = null)
|
|
||||||
{
|
|
||||||
// some code
|
|
||||||
if (isset($GLOBALS['doingphptests']) && $GLOBALS['doingphptests']) {
|
|
||||||
var_dump($message);
|
|
||||||
}
|
|
||||||
// make sure everything is assigned properly
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExceptionErrorHandler.
|
* ExceptionErrorHandler.
|
||||||
*
|
*
|
||||||
@ -35,6 +25,9 @@ class Exception extends \Exception
|
|||||||
if (error_reporting() === 0) {
|
if (error_reporting() === 0) {
|
||||||
return true; // return true to continue through the others error handlers
|
return true; // return true to continue through the others error handlers
|
||||||
}
|
}
|
||||||
throw new self($errstr.' on line '.$errline.' of file '.$errfile, $errno);
|
$e = new self($errstr, $errno);
|
||||||
|
$e->file = $errfile;
|
||||||
|
$e->line = $errline;
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class MTProto extends MTProtoTools
|
|||||||
// Set default settings
|
// Set default settings
|
||||||
$default_settings = [
|
$default_settings = [
|
||||||
'authorization' => [
|
'authorization' => [
|
||||||
'default_temp_auth_key_expires_in' => 86400,
|
'default_temp_auth_key_expires_in' => 31557600,
|
||||||
'rsa_key' => '-----BEGIN RSA PUBLIC KEY-----
|
'rsa_key' => '-----BEGIN RSA PUBLIC KEY-----
|
||||||
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
||||||
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
||||||
@ -60,8 +60,9 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||||||
'protocol' => 'tcp_full',
|
'protocol' => 'tcp_full',
|
||||||
'test_mode' => false,
|
'test_mode' => false,
|
||||||
'port' => '443',
|
'port' => '443',
|
||||||
|
'timeout' => 10
|
||||||
],
|
],
|
||||||
'default_dc' => 4,
|
'default_dc' => 2,
|
||||||
],
|
],
|
||||||
'app_info' => [
|
'app_info' => [
|
||||||
'api_id' => 25628,
|
'api_id' => 25628,
|
||||||
@ -139,10 +140,15 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||||||
public function switch_dc($new_dc, $allow_nearest_dc_switch = false)
|
public function switch_dc($new_dc, $allow_nearest_dc_switch = false)
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log('Switching to DC '.$new_dc.'...');
|
\danog\MadelineProto\Logger::log('Switching to DC '.$new_dc.'...');
|
||||||
|
/* if ($this->datacenter->curdc !== 0) {
|
||||||
|
try {
|
||||||
|
$exported_authorization = $this->method_call('auth.exportAuthorization', ['dc_id' => $new_dc]);
|
||||||
|
} catch (\danog\MadelineProto\RPCErrorException $e) { ; }
|
||||||
|
}*/
|
||||||
if ($this->datacenter->dc_connect($new_dc)) {
|
if ($this->datacenter->dc_connect($new_dc)) {
|
||||||
$this->init_authorization();
|
$this->init_authorization();
|
||||||
$this->bind_temp_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in']);
|
|
||||||
$this->write_client_info($allow_nearest_dc_switch);
|
$this->write_client_info($allow_nearest_dc_switch);
|
||||||
|
// if (isset($exported_authorization)) $this->method_call('auth.importAuthorization', $exported_authorization);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +165,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||||||
}
|
}
|
||||||
\danog\MadelineProto\Logger::log('Generating temporary authorization key...');
|
\danog\MadelineProto\Logger::log('Generating temporary authorization key...');
|
||||||
$this->datacenter->temp_auth_key = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in']);
|
$this->datacenter->temp_auth_key = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in']);
|
||||||
|
$this->bind_temp_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class AckHandler extends \danog\MadelineProto\PrimeModule
|
|||||||
{
|
{
|
||||||
// The server acknowledges that it received my message
|
// The server acknowledges that it received my message
|
||||||
if (!isset($this->outgoing_messages[$message_id])) {
|
if (!isset($this->outgoing_messages[$message_id])) {
|
||||||
throw new Exception("Couldn't find message id ".$message_id.' in the array of outgoing messages. Maybe try to increase its size?');
|
throw new \danog\MadelineProto\Exception("Couldn't find message id ".$message_id.' in the array of outgoing messages. Maybe try to increase its size?');
|
||||||
}
|
}
|
||||||
$this->outgoing_messages[$message_id]['ack'] = true;
|
$this->outgoing_messages[$message_id]['ack'] = true;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ class AckHandler extends \danog\MadelineProto\PrimeModule
|
|||||||
}
|
}
|
||||||
// I let the server know that I received its message
|
// I let the server know that I received its message
|
||||||
if (!isset($this->incoming_messages[$message_id])) {
|
if (!isset($this->incoming_messages[$message_id])) {
|
||||||
throw new Exception("Couldn't find message id ".$message_id.' in the array of incoming message ids. Maybe try to increase its size?');
|
throw new \danog\MadelineProto\Exception("Couldn't find message id ".$message_id.' in the array of incoming message ids. Maybe try to increase its size?');
|
||||||
}
|
}
|
||||||
$this->object_call('msgs_ack', ['msg_ids' => [$message_id]]);
|
$this->object_call('msgs_ack', ['msg_ids' => [$message_id]]);
|
||||||
$this->incoming_messages[$message_id]['ack'] = true;
|
$this->incoming_messages[$message_id]['ack'] = true;
|
||||||
|
@ -55,7 +55,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* Check if the client's nonce and the server's nonce are the same
|
* Check if the client's nonce and the server's nonce are the same
|
||||||
*/
|
*/
|
||||||
if ($ResPQ['nonce'] !== $nonce) {
|
if ($ResPQ['nonce'] !== $nonce) {
|
||||||
throw new Exception('wrong nonce');
|
throw new \danog\MadelineProto\Exception('wrong nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -72,7 +72,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($public_key_fingerprint)) {
|
if (!isset($public_key_fingerprint)) {
|
||||||
throw new Exception("Couldn't find our key in the server_public_key_fingerprints vector.");
|
throw new \danog\MadelineProto\Exception("Couldn't find our key in the server_public_key_fingerprints vector.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$pq_bytes = $ResPQ['pq'];
|
$pq_bytes = $ResPQ['pq'];
|
||||||
@ -92,7 +92,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!($pq->equals($p->multiply($q)) && $p->compare($q) < 0)) {
|
if (!($pq->equals($p->multiply($q)) && $p->compare($q) < 0)) {
|
||||||
throw new Exception("couldn't compute p and q.");
|
throw new \danog\MadelineProto\Exception("couldn't compute p and q.");
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Factorization '.$pq.' = '.$p.' * '.$q);
|
\danog\MadelineProto\Logger::log('Factorization '.$pq.' = '.$p.' * '.$q);
|
||||||
@ -105,38 +105,25 @@ class AuthKeyHandler extends AckHandler
|
|||||||
$q_bytes = \danog\PHP\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) {
|
|
||||||
$data = $this->tl->serialize_obj('p_q_inner_data',
|
$data_unserialized = [
|
||||||
[
|
'pq' => $pq_bytes,
|
||||||
'pq' => $pq_bytes,
|
'p' => $p_bytes,
|
||||||
'p' => $p_bytes,
|
'q' => $q_bytes,
|
||||||
'q' => $q_bytes,
|
'nonce' => $nonce,
|
||||||
'nonce' => $nonce,
|
'server_nonce' => $server_nonce,
|
||||||
'server_nonce' => $server_nonce,
|
'new_nonce' => $new_nonce,
|
||||||
'new_nonce' => $new_nonce,
|
'expires_in' => $expires_in
|
||||||
]
|
];
|
||||||
);
|
$p_q_inner_data = $this->tl->serialize_obj('p_q_inner_data'.(($expires_in < 0) ? '' : '_temp'), $data_unserialized);
|
||||||
} else {
|
|
||||||
$data = $this->tl->serialize_obj('p_q_inner_data_temp',
|
|
||||||
[
|
|
||||||
'pq' => $pq_bytes,
|
|
||||||
'p' => $p_bytes,
|
|
||||||
'q' => $q_bytes,
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'server_nonce' => $server_nonce,
|
|
||||||
'new_nonce' => $new_nonce,
|
|
||||||
'expires_in' => $expires_in,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Encrypt serialized object
|
* Encrypt serialized object
|
||||||
*/
|
*/
|
||||||
$sha_digest = sha1($data, true);
|
$sha_digest = sha1($p_q_inner_data, true);
|
||||||
$random_bytes = \phpseclib\Crypt\Random::string(255 - strlen($data) - strlen($sha_digest));
|
$random_bytes = \phpseclib\Crypt\Random::string(255 - strlen($p_q_inner_data) - strlen($sha_digest));
|
||||||
$to_encrypt = $sha_digest.$data.$random_bytes;
|
$to_encrypt = $sha_digest.$p_q_inner_data.$random_bytes;
|
||||||
$encrypted_data = $this->key->encrypt($to_encrypt);
|
$encrypted_data = $this->key->encrypt($to_encrypt);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Starting Diffie Hellman key exchange');
|
\danog\MadelineProto\Logger::log('Starting Diffie Hellman key exchange');
|
||||||
@ -176,7 +163,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* Check if the client's nonce and the server's nonce are the same
|
* Check if the client's nonce and the server's nonce are the same
|
||||||
*/
|
*/
|
||||||
if ($nonce != $server_dh_params['nonce']) {
|
if ($nonce != $server_dh_params['nonce']) {
|
||||||
throw new Exception('wrong nonce.');
|
throw new \danog\MadelineProto\Exception('wrong nonce.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -184,7 +171,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* Check if server_nonce and new server_nonce are the same
|
* Check if server_nonce and new server_nonce are the same
|
||||||
*/
|
*/
|
||||||
if ($server_nonce != $server_dh_params['server_nonce']) {
|
if ($server_nonce != $server_dh_params['server_nonce']) {
|
||||||
throw new Exception('wrong server nonce.');
|
throw new \danog\MadelineProto\Exception('wrong server nonce.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -193,7 +180,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* new nonce hash return in server_DH_params_fail
|
* new nonce hash return in server_DH_params_fail
|
||||||
*/
|
*/
|
||||||
if (isset($server_dh_params['new_nonce_hash']) && substr(sha1($new_nonce), -32) != $server_dh_params['new_nonce_hash']) {
|
if (isset($server_dh_params['new_nonce_hash']) && substr(sha1($new_nonce), -32) != $server_dh_params['new_nonce_hash']) {
|
||||||
throw new Exception('wrong new nonce hash.');
|
throw new \danog\MadelineProto\Exception('wrong new nonce hash.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -233,15 +220,15 @@ class AuthKeyHandler extends AckHandler
|
|||||||
*/
|
*/
|
||||||
$server_DH_inner_data_length = $this->tl->get_length($this->fopen_and_write('php://memory', 'rw+b', $answer));
|
$server_DH_inner_data_length = $this->tl->get_length($this->fopen_and_write('php://memory', 'rw+b', $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 Exception('answer_hash mismatch.');
|
throw new \danog\MadelineProto\Exception('answer_hash mismatch.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($nonce != $server_DH_inner_data['nonce']) {
|
if ($nonce != $server_DH_inner_data['nonce']) {
|
||||||
throw new Exception('wrong nonce');
|
throw new \danog\MadelineProto\Exception('wrong nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($server_nonce != $server_DH_inner_data['server_nonce']) {
|
if ($server_nonce != $server_DH_inner_data['server_nonce']) {
|
||||||
throw new Exception('wrong server nonce');
|
throw new \danog\MadelineProto\Exception('wrong server nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
$g = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
|
$g = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
|
||||||
@ -275,7 +262,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
*/
|
*/
|
||||||
\danog\MadelineProto\Logger::log('Executing dh_prime checks (1/3)...');
|
\danog\MadelineProto\Logger::log('Executing dh_prime checks (1/3)...');
|
||||||
if (!$dh_prime->isPrime()) {
|
if (!$dh_prime->isPrime()) {
|
||||||
throw new Exception("dh_prime isn't a safe 2048-bit prime (dh_prime isn't a prime).");
|
throw new \danog\MadelineProto\Exception("dh_prime isn't a safe 2048-bit prime (dh_prime isn't a prime).");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -289,7 +276,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
/*
|
/*
|
||||||
\danog\MadelineProto\Logger::log('Executing dh_prime checks (2/3)...');
|
\danog\MadelineProto\Logger::log('Executing dh_prime checks (2/3)...');
|
||||||
if (!$dh_prime->subtract($one)->divide($two)[0]->isPrime()) {
|
if (!$dh_prime->subtract($one)->divide($two)[0]->isPrime()) {
|
||||||
throw new Exception("dh_prime isn't a safe 2048-bit prime ((dh_prime - 1) / 2 isn't a prime).");
|
throw new \danog\MadelineProto\Exception("dh_prime isn't a safe 2048-bit prime ((dh_prime - 1) / 2 isn't a prime).");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -302,7 +289,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
if ($dh_prime->compare($twoe2047) <= 0 // 2^2047 < dh_prime or dh_prime > 2^2047 or ! dh_prime <= 2^2047
|
if ($dh_prime->compare($twoe2047) <= 0 // 2^2047 < dh_prime or dh_prime > 2^2047 or ! dh_prime <= 2^2047
|
||||||
|| $dh_prime->compare($twoe2048) >= 0 // dh_prime < 2^2048 or ! dh_prime >= 2^2048
|
|| $dh_prime->compare($twoe2048) >= 0 // dh_prime < 2^2048 or ! dh_prime >= 2^2048
|
||||||
) {
|
) {
|
||||||
throw new Exception("g isn't a safe 2048-bit prime (2^2047 < dh_prime < 2^2048 is false).");
|
throw new \danog\MadelineProto\Exception("g isn't a safe 2048-bit prime (2^2047 < dh_prime < 2^2048 is false).");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -315,7 +302,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
if ($g->compare($one) <= 0 // 1 < g or g > 1 or ! g <= 1
|
if ($g->compare($one) <= 0 // 1 < g or g > 1 or ! g <= 1
|
||||||
|| $g->compare($dh_prime->subtract($one)) >= 0 // g < dh_prime - 1 or ! g >= dh_prime - 1
|
|| $g->compare($dh_prime->subtract($one)) >= 0 // g < dh_prime - 1 or ! g >= dh_prime - 1
|
||||||
) {
|
) {
|
||||||
throw new Exception('g is invalid (1 < g < dh_prime - 1 is false).');
|
throw new \danog\MadelineProto\Exception('g is invalid (1 < g < dh_prime - 1 is false).');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -327,7 +314,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
if ($g_a->compare($one) <= 0 // 1 < g_a or g_a > 1 or ! g_a <= 1
|
if ($g_a->compare($one) <= 0 // 1 < g_a or g_a > 1 or ! g_a <= 1
|
||||||
|| $g_a->compare($dh_prime->subtract($one)) >= 0 // g_a < dh_prime - 1 or ! g_a >= dh_prime - 1
|
|| $g_a->compare($dh_prime->subtract($one)) >= 0 // g_a < dh_prime - 1 or ! g_a >= dh_prime - 1
|
||||||
) {
|
) {
|
||||||
throw new Exception('g_a is invalid (1 < g_a < dh_prime - 1 is false).');
|
throw new \danog\MadelineProto\Exception('g_a is invalid (1 < g_a < dh_prime - 1 is false).');
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
|
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
|
||||||
@ -343,7 +330,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
if ($g_b->compare($one) <= 0 // 1 < g_b or g_b > 1 or ! g_b <= 1
|
if ($g_b->compare($one) <= 0 // 1 < g_b or g_b > 1 or ! g_b <= 1
|
||||||
|| $g_b->compare($dh_prime->subtract($one)) >= 0 // g_b < dh_prime - 1 or ! g_b >= dh_prime - 1
|
|| $g_b->compare($dh_prime->subtract($one)) >= 0 // g_b < dh_prime - 1 or ! g_b >= dh_prime - 1
|
||||||
) {
|
) {
|
||||||
throw new Exception('g_b is invalid (1 < g_b < dh_prime - 1 is false).');
|
throw new \danog\MadelineProto\Exception('g_b is invalid (1 < g_b < dh_prime - 1 is false).');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Preparing client_DH_inner_data...');
|
\danog\MadelineProto\Logger::log('Preparing client_DH_inner_data...');
|
||||||
@ -425,7 +412,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* Check if the client's nonce and the server's nonce are the same
|
* Check if the client's nonce and the server's nonce are the same
|
||||||
*/
|
*/
|
||||||
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
|
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
|
||||||
throw new Exception('wrong nonce.');
|
throw new \danog\MadelineProto\Exception('wrong nonce.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -433,7 +420,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* Check if server_nonce and new server_nonce are the same
|
* Check if server_nonce and new server_nonce are the same
|
||||||
*/
|
*/
|
||||||
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
|
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
|
||||||
throw new Exception('wrong server nonce');
|
throw new \danog\MadelineProto\Exception('wrong server nonce');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -443,7 +430,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
switch ($Set_client_DH_params_answer['_']) {
|
switch ($Set_client_DH_params_answer['_']) {
|
||||||
case 'dh_gen_ok':
|
case 'dh_gen_ok':
|
||||||
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
||||||
throw new Exception('wrong new_nonce_hash1');
|
throw new \danog\MadelineProto\Exception('wrong new_nonce_hash1');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Diffie Hellman key exchange processed successfully!');
|
\danog\MadelineProto\Logger::log('Diffie Hellman key exchange processed successfully!');
|
||||||
@ -452,8 +439,9 @@ class AuthKeyHandler extends AckHandler
|
|||||||
$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);
|
||||||
|
|
||||||
if ($expires_in < 0) { //check if permanent authorization
|
if ($expires_in >= 0) { //check if permanent authorization
|
||||||
$res_authorization['expires_in'] = $expires_in;
|
$res_authorization['expires_in'] = $expires_in;
|
||||||
|
$res_authorization['p_q_inner_data_temp'] = $p_q_inner_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Auth key generated');
|
\danog\MadelineProto\Logger::log('Auth key generated');
|
||||||
@ -461,7 +449,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
return $res_authorization;
|
return $res_authorization;
|
||||||
case 'dh_gen_retry':
|
case 'dh_gen_retry':
|
||||||
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
||||||
throw new Exception('wrong new_nonce_hash_2');
|
throw new \danog\MadelineProto\Exception('wrong new_nonce_hash_2');
|
||||||
}
|
}
|
||||||
|
|
||||||
//repeat foreach
|
//repeat foreach
|
||||||
@ -469,13 +457,13 @@ class AuthKeyHandler extends AckHandler
|
|||||||
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 \danog\MadelineProto\Exception('wrong new_nonce_hash_3');
|
||||||
}
|
}
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Auth Failed');
|
\danog\MadelineProto\Logger::log('Auth Failed');
|
||||||
break 2;
|
break 2;
|
||||||
default:
|
default:
|
||||||
throw new Exception('Response Error');
|
throw new \danog\MadelineProto\Exception('Response Error');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,7 +472,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Auth Failed');
|
throw new \danog\MadelineProto\Exception('Auth Failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bind_temp_auth_key($expires_in)
|
public function bind_temp_auth_key($expires_in)
|
||||||
@ -519,6 +507,6 @@ class AuthKeyHandler extends AckHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw new Exception('An error occurred while binding temporary and permanent authorization keys.');
|
throw new \danog\MadelineProto\Exception('An error occurred while binding temporary and permanent authorization keys.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class CallHandler extends AuthKeyHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($response == null) {
|
if ($response == null) {
|
||||||
throw new Exception("Couldn't get response");
|
throw new \danog\MadelineProto\Exception("Couldn't get response");
|
||||||
}
|
}
|
||||||
switch ($response['_']) {
|
switch ($response['_']) {
|
||||||
case 'rpc_error':
|
case 'rpc_error':
|
||||||
@ -47,7 +47,7 @@ class CallHandler extends AuthKeyHandler
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception('Got rpc error '.$response['error_code'].': '.$response['error_message']);
|
throw new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -60,7 +60,7 @@ class CallHandler extends AuthKeyHandler
|
|||||||
public function method_call($method, $args, $message_id = null)
|
public function method_call($method, $args, $message_id = null)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) {
|
if (!is_array($args)) {
|
||||||
throw new Exception("Arguments aren't an array.");
|
throw new \danog\MadelineProto\Exception("Arguments aren't an array.");
|
||||||
}
|
}
|
||||||
foreach (range(1, $this->settings['max_tries']['query']) as $i) {
|
foreach (range(1, $this->settings['max_tries']['query']) as $i) {
|
||||||
try {
|
try {
|
||||||
@ -68,24 +68,32 @@ class CallHandler extends AuthKeyHandler
|
|||||||
$int_message_id = $this->send_message($this->tl->serialize_method($method, $args), $this->tl->content_related($method), $message_id);
|
$int_message_id = $this->send_message($this->tl->serialize_method($method, $args), $this->tl->content_related($method), $message_id);
|
||||||
$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 (\danog\MadelineProto\Exception $e) {
|
||||||
\danog\MadelineProto\Logger::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\Logger::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...');
|
||||||
$this->datacenter->close_and_reopen();
|
$this->datacenter->close_and_reopen();
|
||||||
continue;
|
continue;
|
||||||
|
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||||
|
if ($e->getCode() == -404) {
|
||||||
|
\danog\MadelineProto\Logger::log('Temporary authorization key expired. Regenerating and recalling method...');
|
||||||
|
$this->datacenter->temp_auth_key = null;
|
||||||
|
$this->init_authorization();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
if ($server_answer == null) {
|
if ($server_answer == null) {
|
||||||
throw new Exception('An error occurred while calling method '.$method.'.');
|
throw new \danog\MadelineProto\Exception('An error occurred while calling method '.$method.'.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $server_answer;
|
return $server_answer;
|
||||||
}
|
}
|
||||||
throw new Exception('An error occurred while calling method '.$method.'.');
|
throw new \danog\MadelineProto\Exception('An error occurred while calling method '.$method.'.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function object_call($object, $args)
|
public function object_call($object, $args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) {
|
if (!is_array($args)) {
|
||||||
throw new Exception("Arguments aren't an array.");
|
throw new \danog\MadelineProto\Exception("Arguments aren't an array.");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (range(1, $this->settings['max_tries']['query']) as $i) {
|
foreach (range(1, $this->settings['max_tries']['query']) as $i) {
|
||||||
@ -101,11 +109,11 @@ class CallHandler extends AuthKeyHandler
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
// if ($server_answer == null) {
|
// if ($server_answer == null) {
|
||||||
// throw new Exception('An error occurred while calling object '.$object.'.');
|
// throw new \danog\MadelineProto\Exception('An error occurred while calling object '.$object.'.');
|
||||||
// }
|
// }
|
||||||
// $deserialized = $this->tl->deserialize($this->fopen_and_write('php://memory', 'rw+b', $server_answer));
|
// $deserialized = $this->tl->deserialize($this->fopen_and_write('php://memory', 'rw+b', $server_answer));
|
||||||
// return $deserialized;
|
// return $deserialized;
|
||||||
}
|
}
|
||||||
throw new Exception('An error occurred while calling object '.$object.'.');
|
throw new \danog\MadelineProto\Exception('An error occurred while calling object '.$object.'.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,17 +50,17 @@ class Crypt extends CallHandler
|
|||||||
public function _ige($message, $key, $iv, $operation = 'decrypt')
|
public function _ige($message, $key, $iv, $operation = 'decrypt')
|
||||||
{
|
{
|
||||||
if (strlen($key) != 32) {
|
if (strlen($key) != 32) {
|
||||||
throw new Exception('key must be 32 bytes long (was '.strlen($key).' bytes)');
|
throw new \danog\MadelineProto\Exception('key must be 32 bytes long (was '.strlen($key).' bytes)');
|
||||||
}
|
}
|
||||||
if (strlen($iv) != 32) {
|
if (strlen($iv) != 32) {
|
||||||
throw new Exception('iv must be 32 bytes long (was '.strlen($iv).' bytes)');
|
throw new \danog\MadelineProto\Exception('iv must be 32 bytes long (was '.strlen($iv).' bytes)');
|
||||||
}
|
}
|
||||||
$cipher = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_ECB);
|
$cipher = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_ECB);
|
||||||
$cipher->setKey($key);
|
$cipher->setKey($key);
|
||||||
$cipher->paddable = false;
|
$cipher->paddable = false;
|
||||||
$blocksize = $cipher->block_size;
|
$blocksize = $cipher->block_size;
|
||||||
if ((strlen($message) % $blocksize) != 0) {
|
if ((strlen($message) % $blocksize) != 0) {
|
||||||
throw new Exception('message must be a multiple of 16 bytes (try adding '.(16 - (strlen($message) % 16)).' bytes of padding)');
|
throw new \danog\MadelineProto\Exception('message must be a multiple of 16 bytes (try adding '.(16 - (strlen($message) % 16)).' bytes of padding)');
|
||||||
}
|
}
|
||||||
$ivp = substr($iv, 0, $blocksize);
|
$ivp = substr($iv, 0, $blocksize);
|
||||||
$ivp2 = substr($iv, $blocksize);
|
$ivp2 = substr($iv, $blocksize);
|
||||||
@ -80,7 +80,7 @@ class Crypt extends CallHandler
|
|||||||
$ivp = $outdata;
|
$ivp = $outdata;
|
||||||
$ivp2 = $indata;
|
$ivp2 = $indata;
|
||||||
} else {
|
} else {
|
||||||
throw new Exception('Crypt: operation must be either \'decrypt\' or \'encrypt\'');
|
throw new \danog\MadelineProto\Exception('Crypt: operation must be either \'decrypt\' or \'encrypt\'');
|
||||||
}
|
}
|
||||||
$ciphered .= $outdata;
|
$ciphered .= $outdata;
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*
|
|
||||||
Copyright 2016 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.
|
|
||||||
MadelineProto 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\MTProtoTools;
|
|
||||||
|
|
||||||
class Exception extends \Exception
|
|
||||||
{
|
|
||||||
public function __construct($message, $code = 0, Exception $previous = null)
|
|
||||||
{
|
|
||||||
// some code
|
|
||||||
if (isset($GLOBALS['doingphptests']) && $GLOBALS['doingphptests']) {
|
|
||||||
var_dump($message);
|
|
||||||
}
|
|
||||||
// make sure everything is assigned properly
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ExceptionErrorHandler.
|
|
||||||
*
|
|
||||||
* Error handler
|
|
||||||
*/
|
|
||||||
public static function ExceptionErrorHandler($errno = 0, $errstr = null, $errfile = null, $errline = null)
|
|
||||||
{
|
|
||||||
// If error is suppressed with @, don't throw an exception
|
|
||||||
if (error_reporting() === 0) {
|
|
||||||
return true; // return true to continue through the others error handlers
|
|
||||||
}
|
|
||||||
throw new self($errstr.' on line '.$errline.' of file '.$errfile, $errno);
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,7 @@ class MessageHandler extends Crypt
|
|||||||
$int_message_id = $this->generate_message_id();
|
$int_message_id = $this->generate_message_id();
|
||||||
}
|
}
|
||||||
if (!is_int($int_message_id)) {
|
if (!is_int($int_message_id)) {
|
||||||
throw new Exception("Specified message id isn't an integer");
|
throw new \danog\MadelineProto\Exception("Specified message id isn't an integer");
|
||||||
}
|
}
|
||||||
|
|
||||||
$message_id = \danog\PHP\Struct::pack('<Q', $int_message_id);
|
$message_id = \danog\PHP\Struct::pack('<Q', $int_message_id);
|
||||||
@ -54,7 +54,7 @@ class MessageHandler extends Crypt
|
|||||||
{
|
{
|
||||||
$payload = $this->datacenter->read_message();
|
$payload = $this->datacenter->read_message();
|
||||||
if (fstat($payload)['size'] == 4) {
|
if (fstat($payload)['size'] == 4) {
|
||||||
throw new Exception('Server response error: '.abs(\danog\PHP\Struct::unpack('<i', fread($payload, 4))[0]));
|
throw new \danog\MadelineProto\RPCErrorException('Generic', \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')) {
|
||||||
@ -69,12 +69,12 @@ class MessageHandler extends Crypt
|
|||||||
|
|
||||||
$server_salt = \danog\PHP\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->datacenter->temp_auth_key['server_salt']) {
|
if ($server_salt != $this->datacenter->temp_auth_key['server_salt']) {
|
||||||
throw new Exception('Server salt mismatch (my server salt '.$this->datacenter->temp_auth_key['server_salt'].' is not equal to server server salt '.$server_salt.').');
|
throw new \danog\MadelineProto\Exception('Server salt mismatch (my server salt '.$this->datacenter->temp_auth_key['server_salt'].' is not equal to server server salt '.$server_salt.').');
|
||||||
}
|
}
|
||||||
|
|
||||||
$session_id = substr($decrypted_data, 8, 8);
|
$session_id = substr($decrypted_data, 8, 8);
|
||||||
if ($session_id != $this->datacenter->session_id) {
|
if ($session_id != $this->datacenter->session_id) {
|
||||||
throw new Exception('Session id mismatch.');
|
throw new \danog\MadelineProto\Exception('Session id mismatch.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$message_id = \danog\PHP\Struct::unpack('<Q', substr($decrypted_data, 16, 8))[0];
|
$message_id = \danog\PHP\Struct::unpack('<Q', substr($decrypted_data, 16, 8))[0];
|
||||||
@ -86,28 +86,28 @@ class MessageHandler extends Crypt
|
|||||||
$message_data_length = \danog\PHP\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 \danog\MadelineProto\Exception('message_data_length is too big');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strlen($decrypted_data) - 32) - $message_data_length > 15) {
|
if ((strlen($decrypted_data) - 32) - $message_data_length > 15) {
|
||||||
throw new Exception('difference between message_data_length and the length of the remaining decrypted buffer is too big');
|
throw new \danog\MadelineProto\Exception('difference between message_data_length and the length of the remaining decrypted buffer is too big');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message_data_length < 0) {
|
if ($message_data_length < 0) {
|
||||||
throw new Exception('message_data_length not positive');
|
throw new \danog\MadelineProto\Exception('message_data_length not positive');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message_data_length % 4 != 0) {
|
if ($message_data_length % 4 != 0) {
|
||||||
throw new Exception('message_data_length not divisible by 4');
|
throw new \danog\MadelineProto\Exception('message_data_length not divisible by 4');
|
||||||
}
|
}
|
||||||
|
|
||||||
$message_data = substr($decrypted_data, 32, $message_data_length);
|
$message_data = substr($decrypted_data, 32, $message_data_length);
|
||||||
if ($message_key != substr(sha1(substr($decrypted_data, 0, 32 + $message_data_length), true), -16)) {
|
if ($message_key != substr(sha1(substr($decrypted_data, 0, 32 + $message_data_length), true), -16)) {
|
||||||
throw new Exception('msg_key mismatch');
|
throw new \danog\MadelineProto\Exception('msg_key mismatch');
|
||||||
}
|
}
|
||||||
$this->incoming_messages[$message_id]['seq_no'] = $seq_no;
|
$this->incoming_messages[$message_id]['seq_no'] = $seq_no;
|
||||||
} else {
|
} else {
|
||||||
throw new Exception('Got unknown auth_key id');
|
throw new \danog\MadelineProto\Exception('Got unknown auth_key id');
|
||||||
}
|
}
|
||||||
$deserialized = $this->tl->deserialize($this->fopen_and_write('php://memory', 'rw+b', $message_data));
|
$deserialized = $this->tl->deserialize($this->fopen_and_write('php://memory', 'rw+b', $message_data));
|
||||||
$this->incoming_messages[$message_id]['content'] = $deserialized;
|
$this->incoming_messages[$message_id]['content'] = $deserialized;
|
||||||
|
@ -20,19 +20,19 @@ class MsgIdHandler extends MessageHandler
|
|||||||
public function check_message_id($new_message_id, $outgoing, $container = false)
|
public function check_message_id($new_message_id, $outgoing, $container = false)
|
||||||
{
|
{
|
||||||
if (((int) ((time() + $this->datacenter->time_delta - 300) * pow(2, 30)) * 4) > $new_message_id) {
|
if (((int) ((time() + $this->datacenter->time_delta - 300) * pow(2, 30)) * 4) > $new_message_id) {
|
||||||
throw new Exception('Given message id ('.$new_message_id.') is too old.');
|
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is too old.');
|
||||||
}
|
}
|
||||||
if (((int) ((time() + $this->datacenter->time_delta + 30) * pow(2, 30)) * 4) < $new_message_id) {
|
if (((int) ((time() + $this->datacenter->time_delta + 30) * pow(2, 30)) * 4) < $new_message_id) {
|
||||||
throw new Exception('Given message id ('.$new_message_id.') is too new.');
|
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is too new.');
|
||||||
}
|
}
|
||||||
if ($outgoing) {
|
if ($outgoing) {
|
||||||
if ($new_message_id % 4 != 0) {
|
if ($new_message_id % 4 != 0) {
|
||||||
throw new Exception('Given message id ('.$new_message_id.') is not divisible by 4.');
|
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is not divisible by 4.');
|
||||||
}
|
}
|
||||||
$keys = array_keys($this->outgoing_messages);
|
$keys = array_keys($this->outgoing_messages);
|
||||||
asort($keys);
|
asort($keys);
|
||||||
if ($new_message_id <= end($keys)) {
|
if ($new_message_id <= end($keys)) {
|
||||||
throw new Exception('Given message id ('.$new_message_id.') is lower than or equal than the current limit ('.end($keys).').', 1);
|
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is lower than or equal than the current limit ('.end($keys).').', 1);
|
||||||
}
|
}
|
||||||
$this->outgoing_messages[$new_message_id] = [];
|
$this->outgoing_messages[$new_message_id] = [];
|
||||||
if (count($this->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) {
|
if (count($this->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) {
|
||||||
@ -40,19 +40,19 @@ class MsgIdHandler extends MessageHandler
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ($new_message_id % 4 != 1 && $new_message_id % 4 != 3) {
|
if ($new_message_id % 4 != 1 && $new_message_id % 4 != 3) {
|
||||||
throw new Exception('message id mod 4 != 1 or 3');
|
throw new \danog\MadelineProto\Exception('message id mod 4 != 1 or 3');
|
||||||
}
|
}
|
||||||
$keys = array_keys($this->incoming_messages);
|
$keys = array_keys($this->incoming_messages);
|
||||||
if ($container) {
|
if ($container) {
|
||||||
asort($keys);
|
asort($keys);
|
||||||
if ($new_message_id >= end($keys)) {
|
if ($new_message_id >= end($keys)) {
|
||||||
throw new Exception('Given message id ('.$new_message_id.') is bigger than or equal than the current limit ('.end($keys).').');
|
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is bigger than or equal than the current limit ('.end($keys).').');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
asort($keys);
|
asort($keys);
|
||||||
foreach ($keys as $message_id) {
|
foreach ($keys as $message_id) {
|
||||||
if ($new_message_id <= $message_id) {
|
if ($new_message_id <= $message_id) {
|
||||||
throw new Exception('Given message id ('.$new_message_id.') is lower than or equal than the current limit ('.$message_id.').');
|
throw new \danog\MadelineProto\Exception('Given message id ('.$new_message_id.') is lower than or equal than the current limit ('.$message_id.').');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class ResponseHandler extends MsgIdHandler
|
|||||||
48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)',
|
48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)',
|
||||||
64 => 'invalid container.',
|
64 => 'invalid container.',
|
||||||
];
|
];
|
||||||
throw new Exception('Received bad_msg_notification for '.$response['bad_msg_id'].': '.$error_codes[$response['error_code']]);
|
throw new \danog\MadelineProto\Exception('Received bad_msg_notification for '.$response['bad_msg_id'].': '.$error_codes[$response['error_code']]);
|
||||||
break;
|
break;
|
||||||
case 'bad_server_salt':
|
case 'bad_server_salt':
|
||||||
$this->datacenter->temp_auth_key['server_salt'] = $response['new_server_salt'];
|
$this->datacenter->temp_auth_key['server_salt'] = $response['new_server_salt'];
|
||||||
|
@ -14,27 +14,4 @@ namespace danog\MadelineProto\TL;
|
|||||||
|
|
||||||
class Exception extends \Exception
|
class Exception extends \Exception
|
||||||
{
|
{
|
||||||
public function __construct($message, $code = 0, Exception $previous = null)
|
|
||||||
{
|
|
||||||
// some code
|
|
||||||
if (isset($GLOBALS['doingphptests']) && $GLOBALS['doingphptests']) {
|
|
||||||
var_dump($message);
|
|
||||||
}
|
|
||||||
// make sure everything is assigned properly
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ExceptionErrorHandler.
|
|
||||||
*
|
|
||||||
* Error handler
|
|
||||||
*/
|
|
||||||
public function ExceptionErrorHandler($errno = 0, $errstr = null, $errfile = null, $errline = null)
|
|
||||||
{
|
|
||||||
// If error is suppressed with @, don't throw an exception
|
|
||||||
if (error_reporting() === 0) {
|
|
||||||
return true; // return true to continue through the others error handlers
|
|
||||||
}
|
|
||||||
throw new self($errstr.' on line '.$errline.' of file '.$errfile, $errno);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
15
testing.php
15
testing.php
@ -14,8 +14,7 @@ If not, see <http://www.gnu.org/licenses/>.
|
|||||||
require_once 'vendor/autoload.php';
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
$MadelineProto = new \danog\MadelineProto\API();
|
$MadelineProto = new \danog\MadelineProto\API();
|
||||||
var_dump(strlen(var_export($MadelineProto, true)));
|
/*if (file_exists('number.php')) {
|
||||||
if (file_exists('number.php')) {
|
|
||||||
include_once 'number.php';
|
include_once 'number.php';
|
||||||
$sentCode = $MadelineProto->auth->sendCode(
|
$sentCode = $MadelineProto->auth->sendCode(
|
||||||
[
|
[
|
||||||
@ -40,4 +39,16 @@ if (file_exists('number.php')) {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
var_dump($authorization);
|
var_dump($authorization);
|
||||||
|
}*/
|
||||||
|
if (file_exists('token.php')) {
|
||||||
|
include_once 'token.php';
|
||||||
|
$botauthorization = $MadelineProto->auth->importBotAuthorization(
|
||||||
|
[
|
||||||
|
'bot_auth_token' => $token,
|
||||||
|
'api_id' => $MadelineProto->API->settings['app_info']['api_id'],
|
||||||
|
'api_hash' => $MadelineProto->API->settings['app_info']['api_hash'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
var_dump($botauthorization);
|
||||||
}
|
}
|
||||||
|
echo 'Size of MadelineProto instance is '.strlen(var_export($MadelineProto, true)).' bytes'.PHP_EOL;
|
||||||
|
Loading…
Reference in New Issue
Block a user