Fixed bugs, improved exception erro rhandling, blah, blah, blah (#RTFC)

This commit is contained in:
Daniil Gentili 2016-11-24 12:16:06 +00:00
parent 87e625ea9c
commit c168890384
18 changed files with 131 additions and 183 deletions

1
.gitignore vendored
View File

@ -64,3 +64,4 @@ vendor
*save*
*bak
number.php
token.php

View File

@ -12,16 +12,16 @@ If not, see <http://www.gnu.org/licenses/>.
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]);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
/**

View File

@ -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});
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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']);
}
}

View File

@ -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;

View File

@ -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.');
}
}

View File

@ -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.'.');
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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('<Q', $int_message_id);
@ -54,7 +54,7 @@ class MessageHandler extends Crypt
{
$payload = $this->datacenter->read_message();
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);
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];
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);
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];
@ -86,28 +86,28 @@ class MessageHandler extends Crypt
$message_data_length = \danog\PHP\Struct::unpack('<I', substr($decrypted_data, 28, 4)) [0];
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) {
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;

View File

@ -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.').');
}
}
}

View File

@ -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'];

View File

@ -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);
}
}

View File

@ -14,8 +14,7 @@ If not, see <http://www.gnu.org/licenses/>.
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;