From c16889038440cd6a455fd0abfa193eabc22aa65c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 24 Nov 2016 12:16:06 +0000 Subject: [PATCH] Fixed bugs, improved exception erro rhandling, blah, blah, blah (#RTFC) --- .gitignore | 1 + src/danog/MadelineProto/API.php | 10 +-- src/danog/MadelineProto/APIFactory.php | 2 + src/danog/MadelineProto/Connection.php | 14 +-- src/danog/MadelineProto/DataCenter.php | 15 ++-- src/danog/MadelineProto/DebugTools.php | 2 +- src/danog/MadelineProto/Exception.php | 15 +--- src/danog/MadelineProto/MTProto.php | 13 ++- .../MadelineProto/MTProtoTools/AckHandler.php | 4 +- .../MTProtoTools/AuthKeyHandler.php | 90 ++++++++----------- .../MTProtoTools/CallHandler.php | 26 ++++-- .../MadelineProto/MTProtoTools/Crypt.php | 8 +- .../MadelineProto/MTProtoTools/Exception.php | 40 --------- .../MTProtoTools/MessageHandler.php | 20 ++--- .../MTProtoTools/MsgIdHandler.php | 14 +-- .../MTProtoTools/ResponseHandler.php | 2 +- src/danog/MadelineProto/TL/Exception.php | 23 ----- testing.php | 15 +++- 18 files changed, 131 insertions(+), 183 deletions(-) delete mode 100644 src/danog/MadelineProto/MTProtoTools/Exception.php diff --git a/.gitignore b/.gitignore index 181a1c87e..6ac6e683d 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ vendor *save* *bak number.php +token.php diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php index ba9f52149..24ddffc91 100644 --- a/src/danog/MadelineProto/API.php +++ b/src/danog/MadelineProto/API.php @@ -12,16 +12,16 @@ If not, see . namespace danog\MadelineProto; -class API extends Tools +class API extends APIFactory { public $API; public $settings; + public $namespace = ''; public function __construct($params = []) { set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']); $this->API = new MTProto($params); - \danog\MadelineProto\Logger::log('Running APIFactory...'); foreach ($this->API->tl->methods->method_namespace as $namespace => $method) { $this->{$method} = new APIFactory($method, $this->API); @@ -35,15 +35,11 @@ class API extends Tools \danog\MadelineProto\Logger::log('MadelineProto is ready!'); + restore_error_handler(); } public function __destruct() { restore_error_handler(); } - - public function __call($name, $arguments) - { - return $this->API->method_call($name, $arguments[0]); - } } diff --git a/src/danog/MadelineProto/APIFactory.php b/src/danog/MadelineProto/APIFactory.php index 2aba4df96..1b8bb8a4c 100644 --- a/src/danog/MadelineProto/APIFactory.php +++ b/src/danog/MadelineProto/APIFactory.php @@ -25,6 +25,8 @@ class APIFactory public function __call($name, $arguments) { + set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']); return $this->API->method_call($this->namespace.$name, $arguments[0]); + restore_error_handler(); } } diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php index 33eafc643..40b655058 100644 --- a/src/danog/MadelineProto/Connection.php +++ b/src/danog/MadelineProto/Connection.php @@ -20,6 +20,9 @@ class Connection extends Tools public $sock = null; public $protocol = null; + public $ip = null; + public $port = null; + public $timeout = null; public $time_delta = 0; public $temp_auth_key; @@ -27,7 +30,7 @@ class Connection extends Tools public $session_id; public $seq_no = 0; - public function __construct($ip, $port, $protocol = 'tcp_full') + public function __construct($ip, $port, $protocol, $timeout) { // Can use: /* @@ -39,12 +42,13 @@ class Connection extends Tools - udp */ $this->protocol = $protocol; + $this->timeout = $timeout; $this->ip = $ip; $this->port = $port; switch ($this->protocol) { case 'tcp_abridged': $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')) { throw new Exception("Connection: couldn't connect to socket."); } @@ -52,7 +56,7 @@ class Connection extends Tools break; case 'tcp_intermediate': $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')) { throw new Exception("Connection: couldn't connect to socket."); } @@ -60,7 +64,7 @@ class Connection extends Tools break; case 'tcp_full': $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')) { throw new Exception("Connection: couldn't connect to socket."); } @@ -98,7 +102,7 @@ class Connection extends Tools public function close_and_reopen() { $this->__destruct(); - $this->__construct($this->ip, $this->port, $this->protocol); + $this->__construct($this->ip, $this->port, $this->protocol, $this->timeout); } /** diff --git a/src/danog/MadelineProto/DataCenter.php b/src/danog/MadelineProto/DataCenter.php index 78afc13e9..b5802dbd8 100644 --- a/src/danog/MadelineProto/DataCenter.php +++ b/src/danog/MadelineProto/DataCenter.php @@ -19,6 +19,7 @@ class DataCenter extends Tools { public $referenced_variables = ['time_delta', 'temp_auth_key', 'auth_key', 'session_id', 'seq_no']; public $sockets; + public $curdc = 0; public function __construct($dclist, $settings) { @@ -36,6 +37,7 @@ class DataCenter extends Tools 'protocol' => 'tcp_full', 'port' => '443', 'test_mode' => true, + 'timeout' => 10, ]; } } @@ -55,10 +57,9 @@ class DataCenter extends Tools public function dc_connect($dc_number, $settings = []) { if (isset($this->sockets[$dc_number])) { - return false; $this->set_curdc($dc_number); + return false; } - $this->set_curdc($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'; $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; } @@ -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) { - unset($this->sockets[$dc_number]->{$key}); + unset($this->{$key}); } } diff --git a/src/danog/MadelineProto/DebugTools.php b/src/danog/MadelineProto/DebugTools.php index a26032c40..d4515bcc8 100644 --- a/src/danog/MadelineProto/DebugTools.php +++ b/src/danog/MadelineProto/DebugTools.php @@ -22,7 +22,7 @@ class DebugTools public static function hex_dump(...$what) { foreach ($what as $w) { - var_dump(bin2hex($w)); + \danog\MadelienProto\Logger::log(bin2hex($w)); } } diff --git a/src/danog/MadelineProto/Exception.php b/src/danog/MadelineProto/Exception.php index 3e4b86b7b..bb99f442f 100644 --- a/src/danog/MadelineProto/Exception.php +++ b/src/danog/MadelineProto/Exception.php @@ -14,16 +14,6 @@ namespace danog\MadelineProto; 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. * @@ -35,6 +25,9 @@ class Exception extends \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); + $e = new self($errstr, $errno); + $e->file = $errfile; + $e->line = $errline; + throw $e; } } diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 8dbc01661..b089ba8a6 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -24,7 +24,7 @@ class MTProto extends MTProtoTools // Set default settings $default_settings = [ 'authorization' => [ - 'default_temp_auth_key_expires_in' => 86400, + 'default_temp_auth_key_expires_in' => 31557600, 'rsa_key' => '-----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS @@ -60,8 +60,9 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB 'protocol' => 'tcp_full', 'test_mode' => false, 'port' => '443', + 'timeout' => 10 ], - 'default_dc' => 4, + 'default_dc' => 2, ], 'app_info' => [ 'api_id' => 25628, @@ -139,10 +140,15 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB public function switch_dc($new_dc, $allow_nearest_dc_switch = false) { \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)) { $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); +// 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...'); $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']); } } diff --git a/src/danog/MadelineProto/MTProtoTools/AckHandler.php b/src/danog/MadelineProto/MTProtoTools/AckHandler.php index d21e22db2..8da662677 100644 --- a/src/danog/MadelineProto/MTProtoTools/AckHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AckHandler.php @@ -21,7 +21,7 @@ class AckHandler extends \danog\MadelineProto\PrimeModule { // The server acknowledges that it received my message 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; } @@ -33,7 +33,7 @@ class AckHandler extends \danog\MadelineProto\PrimeModule } // I let the server know that I received its message 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->incoming_messages[$message_id]['ack'] = true; diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index a69054e9a..f9268af2b 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -55,7 +55,7 @@ class AuthKeyHandler extends AckHandler * Check if the client's nonce and the server's nonce are the same */ 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)) { - 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']; @@ -92,7 +92,7 @@ class AuthKeyHandler extends AckHandler } 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); @@ -105,38 +105,25 @@ class AuthKeyHandler extends AckHandler $q_bytes = \danog\PHP\Struct::pack('>I', (string) $q); $new_nonce = \phpseclib\Crypt\Random::string(32); - if ($expires_in < 0) { - $data = $this->tl->serialize_obj('p_q_inner_data', - [ - 'pq' => $pq_bytes, - 'p' => $p_bytes, - 'q' => $q_bytes, - 'nonce' => $nonce, - 'server_nonce' => $server_nonce, - 'new_nonce' => $new_nonce, - ] - ); - } 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, - ] - ); - } + + $data_unserialized = [ + 'pq' => $pq_bytes, + 'p' => $p_bytes, + 'q' => $q_bytes, + 'nonce' => $nonce, + 'server_nonce' => $server_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); /* * *********************************************************************** * Encrypt serialized object */ - $sha_digest = sha1($data, true); - $random_bytes = \phpseclib\Crypt\Random::string(255 - strlen($data) - strlen($sha_digest)); - $to_encrypt = $sha_digest.$data.$random_bytes; + $sha_digest = sha1($p_q_inner_data, true); + $random_bytes = \phpseclib\Crypt\Random::string(255 - strlen($p_q_inner_data) - strlen($sha_digest)); + $to_encrypt = $sha_digest.$p_q_inner_data.$random_bytes; $encrypted_data = $this->key->encrypt($to_encrypt); \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 */ 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 */ 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 */ 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)); 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']) { - throw new Exception('wrong nonce'); + throw new \danog\MadelineProto\Exception('wrong 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']); @@ -275,7 +262,7 @@ class AuthKeyHandler extends AckHandler */ \danog\MadelineProto\Logger::log('Executing dh_prime checks (1/3)...'); 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)...'); 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 || $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 || $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 || $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) { @@ -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 || $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...'); @@ -425,7 +412,7 @@ class AuthKeyHandler extends AckHandler * Check if the client's nonce and the server's nonce are the same */ 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 */ 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['_']) { case 'dh_gen_ok': 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!'); @@ -452,8 +439,9 @@ class AuthKeyHandler extends AckHandler $res_authorization['auth_key'] = $auth_key_str; $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['p_q_inner_data_temp'] = $p_q_inner_data; } \danog\MadelineProto\Logger::log('Auth key generated'); @@ -461,7 +449,7 @@ class AuthKeyHandler extends AckHandler return $res_authorization; case 'dh_gen_retry': 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 @@ -469,13 +457,13 @@ class AuthKeyHandler extends AckHandler break; case 'dh_gen_fail': 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'); break 2; default: - throw new Exception('Response Error'); + throw new \danog\MadelineProto\Exception('Response Error'); 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) @@ -519,6 +507,6 @@ class AuthKeyHandler extends AckHandler 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.'); } } diff --git a/src/danog/MadelineProto/MTProtoTools/CallHandler.php b/src/danog/MadelineProto/MTProtoTools/CallHandler.php index 385f88f92..2bce324c7 100644 --- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php @@ -33,7 +33,7 @@ class CallHandler extends AuthKeyHandler } } if ($response == null) { - throw new Exception("Couldn't get response"); + throw new \danog\MadelineProto\Exception("Couldn't get response"); } switch ($response['_']) { case 'rpc_error': @@ -47,7 +47,7 @@ class CallHandler extends AuthKeyHandler break; 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; @@ -60,7 +60,7 @@ class CallHandler extends AuthKeyHandler public function method_call($method, $args, $message_id = null) { 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) { 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); $this->outgoing_messages[$int_message_id]['content'] = ['method' => $method, 'args' => $args]; $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...'); $this->datacenter->close_and_reopen(); 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) { - 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; } - 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) { 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) { @@ -101,11 +109,11 @@ class CallHandler extends AuthKeyHandler return; // 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)); // return $deserialized; } - throw new Exception('An error occurred while calling object '.$object.'.'); + throw new \danog\MadelineProto\Exception('An error occurred while calling object '.$object.'.'); } } diff --git a/src/danog/MadelineProto/MTProtoTools/Crypt.php b/src/danog/MadelineProto/MTProtoTools/Crypt.php index bb655f602..9f6b7c21d 100644 --- a/src/danog/MadelineProto/MTProtoTools/Crypt.php +++ b/src/danog/MadelineProto/MTProtoTools/Crypt.php @@ -50,17 +50,17 @@ class Crypt extends CallHandler public function _ige($message, $key, $iv, $operation = 'decrypt') { 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) { - 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->setKey($key); $cipher->paddable = false; $blocksize = $cipher->block_size; 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); $ivp2 = substr($iv, $blocksize); @@ -80,7 +80,7 @@ class Crypt extends CallHandler $ivp = $outdata; $ivp2 = $indata; } 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; } diff --git a/src/danog/MadelineProto/MTProtoTools/Exception.php b/src/danog/MadelineProto/MTProtoTools/Exception.php deleted file mode 100644 index ce46b1269..000000000 --- a/src/danog/MadelineProto/MTProtoTools/Exception.php +++ /dev/null @@ -1,40 +0,0 @@ -. -*/ - -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); - } -} diff --git a/src/danog/MadelineProto/MTProtoTools/MessageHandler.php b/src/danog/MadelineProto/MTProtoTools/MessageHandler.php index 19279c73e..ce844fd29 100644 --- a/src/danog/MadelineProto/MTProtoTools/MessageHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/MessageHandler.php @@ -27,7 +27,7 @@ class MessageHandler extends Crypt $int_message_id = $this->generate_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('datacenter->read_message(); if (fstat($payload)['size'] == 4) { - throw new Exception('Server response error: '.abs(\danog\PHP\Struct::unpack('string2bin('\x00\x00\x00\x00\x00\x00\x00\x00')) { @@ -69,12 +69,12 @@ class MessageHandler extends Crypt $server_salt = \danog\PHP\Struct::unpack('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); 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(' 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) { - 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) { - throw new Exception('message_data_length not positive'); + throw new \danog\MadelineProto\Exception('message_data_length not positive'); } 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); 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; } 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)); $this->incoming_messages[$message_id]['content'] = $deserialized; diff --git a/src/danog/MadelineProto/MTProtoTools/MsgIdHandler.php b/src/danog/MadelineProto/MTProtoTools/MsgIdHandler.php index a56dd910c..4e9b1f8c7 100644 --- a/src/danog/MadelineProto/MTProtoTools/MsgIdHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/MsgIdHandler.php @@ -20,19 +20,19 @@ class MsgIdHandler extends MessageHandler 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) { - 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) { - 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 ($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); asort($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] = []; if (count($this->outgoing_messages) > $this->settings['msg_array_limit']['outgoing']) { @@ -40,19 +40,19 @@ class MsgIdHandler extends MessageHandler } } else { 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); if ($container) { asort($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 { asort($keys); foreach ($keys as $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.').'); } } } diff --git a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php index 2320a7fc5..7fe25d99c 100644 --- a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php @@ -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)', 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; case 'bad_server_salt': $this->datacenter->temp_auth_key['server_salt'] = $response['new_server_salt']; diff --git a/src/danog/MadelineProto/TL/Exception.php b/src/danog/MadelineProto/TL/Exception.php index 5651f363e..e2d31d5a4 100644 --- a/src/danog/MadelineProto/TL/Exception.php +++ b/src/danog/MadelineProto/TL/Exception.php @@ -14,27 +14,4 @@ namespace danog\MadelineProto\TL; 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); - } } diff --git a/testing.php b/testing.php index c718ba9a1..5e72371f1 100755 --- a/testing.php +++ b/testing.php @@ -14,8 +14,7 @@ If not, see . require_once 'vendor/autoload.php'; $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'; $sentCode = $MadelineProto->auth->sendCode( [ @@ -40,4 +39,16 @@ if (file_exists('number.php')) { ] ); 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;