Fixed computation of flags, improved serialization, written basic authorization flow in testing.php (closes #21 and #22)

This commit is contained in:
Daniil Gentili 2016-11-23 20:04:29 +00:00
parent d7c098087e
commit 109c887337
5 changed files with 76 additions and 33 deletions

View File

@ -61,7 +61,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
'test_mode' => false, 'test_mode' => false,
'port' => '443', 'port' => '443',
], ],
'default_dc' => 2, 'default_dc' => 4,
], ],
'app_info' => [ 'app_info' => [
'api_id' => 25628, 'api_id' => 25628,

View File

@ -60,27 +60,22 @@ class TL extends \danog\MadelineProto\Tools
if ($tl_constructor === false) { if ($tl_constructor === false) {
throw new Exception('Could not extract type: '.$object); throw new Exception('Could not extract type: '.$object);
} }
return $this->serialize_generic($tl_constructor, $arguments);
$serialized = \danog\PHP\Struct::pack('<i', $tl_constructor['id']);
foreach ($tl_constructor['params'] as $current_argument) {
$serialized .= $this->serialize_param($current_argument['type'], $current_argument['subtype'], $arguments[$current_argument['name']]);
}
return $serialized;
} }
public function serialize_method($method, $arguments) public function serialize_method($method, $arguments)
{ {
$tl_method = $this->methods->find_by_method($method); $tl_method = $this->methods->find_by_method($method);
if ($tl_method === false) { if ($tl_method === false) {
throw new Exception('Could not extract type: '.$method); throw new Exception('Could not extract type: '.$method);
} }
return $this->serialize_generic($tl_method, $arguments);
}
$serialized = \danog\PHP\Struct::pack('<i', $tl_method['id']); public function serialize_generic($tl, $arguments)
{
$serialized = \danog\PHP\Struct::pack('<i', $tl['id']);
$flags = 0; $flags = 0;
$flags_to_send = []; foreach ($tl['params'] as $cur_flag) {
foreach ($tl_method['params'] as $cur_flag) {
if ($cur_flag['opt']) { if ($cur_flag['opt']) {
$flag_pow = pow(2, $cur_flag['pow']); $flag_pow = pow(2, $cur_flag['pow']);
switch ($cur_flag['type']) { switch ($cur_flag['type']) {
@ -88,40 +83,42 @@ class TL extends \danog\MadelineProto\Tools
case 'false': case 'false':
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) ? ($flags | $flag_pow) : ($flags & ~$flag_pow); $flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) ? ($flags | $flag_pow) : ($flags & ~$flag_pow);
unset($arguments[$cur_flag['name']]); unset($arguments[$cur_flag['name']]);
$flags_to_send[$cur_flag['name']] = false;
break; break;
case 'Bool': case 'Bool':
$flags_to_send[$cur_flag['name']] = true; $arguments[$cur_flag['name']] = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) && (($flags & $flag_pow) != 0);
if (($flags & $flag_pow) == 0) { // If source flag isn't set if (($flags & $flag_pow) == 0) unset($arguments[$cur_flag['name']]);
$flags_to_send[$cur_flag['name']] = false;
unset($arguments[$cur_flag['name']]);
}
break; break;
default: default:
$flags_to_send[$cur_flag['name']] = true;
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null) ? ($flags | $flag_pow) : ($flags & ~$flag_pow); $flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null) ? ($flags | $flag_pow) : ($flags & ~$flag_pow);
break; break;
} }
} }
} }
var_dump($flags_to_send);
$arguments['flags'] = $flags; $arguments['flags'] = $flags;
foreach ($tl_method['params'] as $current_argument) { foreach ($tl['params'] as $current_argument) {
if (!isset($arguments[$current_argument['name']])) { if (!isset($arguments[$current_argument['name']])) {
if ($current_argument['opt'] && $flags_to_send[$current_argument['name']]) { if ($current_argument['opt'] && (in_array($current_argument['type'], ['true', 'false']) || ($flags & pow(2, $current_argument['pow'])) == 0)) {
//\danog\MadelineProto\Logger::log('Skipping '.$current_argument['name'].' of type '.$current_argument['type'].'/'.$current_argument['subtype']);
continue; continue;
} }
throw new Exception('Missing required parameter ('.$current_argument['name'].')'); throw new Exception('Missing required parameter ('.$current_argument['name'].')');
} }
//\danog\MadelineProto\Logger::log('Serializing '.$current_argument['name'].' of type '.$current_argument['type'].'/'.$current_argument['subtype']);
$serialized .= $this->serialize_param($current_argument['type'], $current_argument['subtype'], $arguments[$current_argument['name']]); $serialized .= $this->serialize_param($current_argument['type'], $current_argument['subtype'], $arguments[$current_argument['name']]);
} }
return $serialized; return $serialized;
} }
public function serialize_param($type, $subtype, $value) public function serialize_param($type, $subtype = null, $value = null)
{ {
switch ($type) { switch ($type) {
case 'Bool':
if (!is_bool($value)) {
throw new Exception("serialize_param: given value isn't a boolean");
}
return $this->serialize_param('bool'.($value ? "True" : "False"));
break;
case 'int': case 'int':
if (!is_numeric($value)) { if (!is_numeric($value)) {
throw new Exception("serialize_param: given value isn't numeric"); throw new Exception("serialize_param: given value isn't numeric");
@ -179,7 +176,11 @@ class TL extends \danog\MadelineProto\Tools
return $concat; return $concat;
default: default:
throw new Exception("Couldn't serialize param with type ".$type); $tl_elem = $this->constructors->find_by_predicate($type);
if ($tl_elem === false) {
throw new Exception('Could not serialize type: '.$type);
}
return \danog\PHP\Struct::pack('<i', $tl_elem['id']);
break; break;
} }
} }
@ -199,8 +200,16 @@ class TL extends \danog\MadelineProto\Tools
if (!(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream')) { if (!(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream')) {
throw new Exception('An invalid bytes_io handle was provided.'); throw new Exception('An invalid bytes_io handle was provided.');
} }
\danog\MadelineProto\Logger::log('Extracting '.$type.'/'.$subtype.' at byte '.ftell($bytes_io)); //\danog\MadelineProto\Logger::log('Deserializing '.$type.'/'.$subtype.' at byte '.ftell($bytes_io));
switch ($type) { switch ($type) {
case 'Bool':
$id = \danog\PHP\Struct::unpack('<i', fread($bytes_io, 4)) [0];
$tl_elem = $this->constructors->find_by_id($id);
if ($tl_elem === false) {
throw new Exception('Could not extract type: '.$type.' with id '.$id);
}
$x = $tl_elem['predicate'] === 'boolTrue';
break;
case 'int': case 'int':
$x = \danog\PHP\Struct::unpack('<i', fread($bytes_io, 4)) [0]; $x = \danog\PHP\Struct::unpack('<i', fread($bytes_io, 4)) [0];
break; break;
@ -270,6 +279,27 @@ class TL extends \danog\MadelineProto\Tools
$x = ['_' => $tl_elem['predicate']]; $x = ['_' => $tl_elem['predicate']];
$done_opt = false; $done_opt = false;
foreach ($tl_elem['params'] as $arg) { foreach ($tl_elem['params'] as $arg) {
if ($arg['opt']) {
$flag_pow = pow(2, $arg['pow']);
switch ($arg['type']) {
case 'true':
case 'false':
$x[$arg['name']] = ($x['flags'] & $flag_pow) == 1;
continue 2;
break;
case 'Bool':
$default = false;
default:
$default = null;
if (($x['flags'] & $flag_pow) == 0) {
$x[$arg['name']] = $default;
//\danog\MadelineProto\Logger::log('Skipping '.$arg['name'].' of type '.$arg['type'].'/'.$arg['subtype']);
continue 2;
}
break;
}
}
$x[$arg['name']] = $this->deserialize($bytes_io, $arg['type'], $arg['subtype']); $x[$arg['name']] = $this->deserialize($bytes_io, $arg['type'], $arg['subtype']);
} }
} }

View File

@ -23,16 +23,16 @@ class TLConstructor
public function add($json_dict, $mtproto) public function add($json_dict, $mtproto)
{ {
$this->id[$this->key] = (int) $json_dict['id']; $this->id[$this->key] = (int) $json_dict['id'];
$this->predicate[$this->key] = (($mtproto && $json_dict['predicate'] == 'message') ? 'MT' : '').$json_dict['predicate']; $this->predicate[$this->key] = (string)((($mtproto && $json_dict['predicate'] == 'message') ? 'MT' : '').$json_dict['predicate']);
$this->type[$this->key] = $json_dict['type']; $this->type[$this->key] = $json_dict['type'];
$this->params[$this->key] = $json_dict['params']; $this->params[$this->key] = $json_dict['params'];
foreach ($this->params[$this->key] as &$param) { foreach ($this->params[$this->key] as &$param) {
$param['opt'] = false; $param['opt'] = false;
$param['subtype'] = null; $param['subtype'] = null;
if (preg_match('/^flags\.\d\?/', $param['type'])) { if (preg_match('/^flags\.\d*\?/', $param['type'])) {
$param['opt'] = true; $param['opt'] = true;
$param['pow'] = preg_replace(['/^flags\./', '/\?.*/'], '', $param['type']); $param['pow'] = preg_replace(['/^flags\./', '/\?.*/'], '', $param['type']);
$param['type'] = preg_replace('/^flags\.\d\?/', '', $param['type']); $param['type'] = preg_replace('/^flags\.\d*\?/', '', $param['type']);
} }
if (preg_match('/vector<.*>/i', $param['type'])) { if (preg_match('/vector<.*>/i', $param['type'])) {
if (preg_match('/vector/', $param['type'])) { if (preg_match('/vector/', $param['type'])) {

View File

@ -35,10 +35,10 @@ class TLMethod
foreach ($this->params[$this->key] as &$param) { foreach ($this->params[$this->key] as &$param) {
$param['opt'] = false; $param['opt'] = false;
$param['subtype'] = null; $param['subtype'] = null;
if (preg_match('/^flags\.\d\?/', $param['type'])) { if (preg_match('/^flags\.\d*\?/', $param['type'])) {
$param['opt'] = true; $param['opt'] = true;
$param['pow'] = preg_replace(['/^flags\./', '/\?.*/'], '', $param['type']); $param['pow'] = preg_replace(['/^flags\./', '/\?.*/'], '', $param['type']);
$param['type'] = preg_replace('/^flags\.\d\?/', '', $param['type']); $param['type'] = preg_replace('/^flags\.\d*\?/', '', $param['type']);
} }
if (preg_match('/vector<.*>/i', $param['type'])) { if (preg_match('/vector<.*>/i', $param['type'])) {
if (preg_match('/vector/', $param['type'])) { if (preg_match('/vector/', $param['type'])) {

View File

@ -17,7 +17,7 @@ $MadelineProto = new \danog\MadelineProto\API();
var_dump(strlen(var_export($MadelineProto, true))); var_dump(strlen(var_export($MadelineProto, true)));
if (file_exists('number.php')) { if (file_exists('number.php')) {
include_once 'number.php'; include_once 'number.php';
$sendCode = $MadelineProto->auth->sendCode( $sentCode = $MadelineProto->auth->sendCode(
[ [
'phone_number' => $number, 'phone_number' => $number,
'sms_type' => 5, 'sms_type' => 5,
@ -26,5 +26,18 @@ if (file_exists('number.php')) {
'lang_code' => $MadelineProto->API->settings['app_info']['lang_code'], 'lang_code' => $MadelineProto->API->settings['app_info']['lang_code'],
] ]
); );
var_dump($sendCode); var_dump($sentCode);
echo 'Enter the code you received: ';
$code = '';
for ($x = 0; $x < $sentCode['type']['length']; $x++) {
$code .= fgetc(STDIN);
}
$authorization = $MadelineProto->auth->signIn(
[
'phone_number' => $number,
'phone_code_hash' => $sentCode['phone_code_hash'],
'phone_code' => $code,
]
);
var_dump($authorization);
} }