mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 07:18:57 +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*
|
||||
*bak
|
||||
number.php
|
||||
token.php
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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])) {
|
||||
$this->set_curdc($dc_number);
|
||||
return false;
|
||||
$this->set_curdc($dc_number);
|
||||
}
|
||||
$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});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
[
|
||||
|
||||
$data_unserialized = [
|
||||
'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,
|
||||
]
|
||||
);
|
||||
}
|
||||
'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.');
|
||||
}
|
||||
}
|
||||
|
@ -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.'.');
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
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;
|
||||
|
@ -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.').');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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'];
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
15
testing.php
15
testing.php
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user