mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 05:58:58 +01:00
More type improvements
This commit is contained in:
parent
4f69701cfc
commit
118cf244b1
@ -51,7 +51,7 @@ abstract class AbstractAPIFactory extends AsyncConstruct
|
||||
/**
|
||||
* Method list.
|
||||
*
|
||||
* @var string[]
|
||||
* @var array<string, callable>
|
||||
*/
|
||||
protected array $methods = [];
|
||||
|
||||
|
@ -56,6 +56,7 @@ class AnnotationsBuilder
|
||||
$this->reflectionClasses = $reflectionClasses;
|
||||
$this->logger = $logger;
|
||||
$this->namespace = $namespace;
|
||||
/** @psalm-suppress InvalidArgument */
|
||||
$this->TL = new TL(new class($logger) {
|
||||
public function __construct($logger)
|
||||
{
|
||||
|
@ -157,8 +157,9 @@ class DoHConnector implements Connector
|
||||
|
||||
// This is reached if either all URIs failed or the maximum number of attempts is reached.
|
||||
/** @noinspection PhpUndefinedVariableInspection */
|
||||
|
||||
throw $e;
|
||||
if ($e) {
|
||||
throw $e;
|
||||
}
|
||||
})());
|
||||
}
|
||||
}
|
||||
|
@ -39,10 +39,16 @@ class DocsBuilder
|
||||
use \danog\MadelineProto\DocsBuilder\Methods;
|
||||
use \danog\MadelineProto\DocsBuilder\Constructors;
|
||||
public $td = false;
|
||||
public function __construct($logger, $settings)
|
||||
protected array $settings;
|
||||
protected string $index;
|
||||
protected Logger $logger;
|
||||
protected TL $TL;
|
||||
protected array $tdDescriptions;
|
||||
public function __construct(Logger $logger, array $settings)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
|
||||
/** @psalm-suppress InvalidArgument */
|
||||
$this->TL = new TL(new class($logger) {
|
||||
public function __construct($logger)
|
||||
{
|
||||
@ -119,8 +125,8 @@ class DocsBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($this->td_descriptions['types'][$otype])) {
|
||||
$header = "{$this->td_descriptions['types'][$otype]}\n\n$header";
|
||||
if (isset($this->tdDescriptions['types'][$otype])) {
|
||||
$header = "{$this->tdDescriptions['types'][$otype]}\n\n$header";
|
||||
}
|
||||
$header = \sprintf(
|
||||
$this->templates['Type'],
|
||||
|
@ -84,22 +84,22 @@ trait Methods
|
||||
$param[$type_or_subtype] = '['.StrTools::markdownEscape($param[$type_or_subtype]).'](../'.$type_or_bare_type.'/'.$param[$type_or_subtype].'.md)';
|
||||
$params .= "'".$param['name']."' => ".(isset($param['subtype']) ? '\\['.$param[$type_or_subtype].'\\]' : $param[$type_or_subtype]).', ';
|
||||
}
|
||||
if (!isset($this->td_descriptions['methods'][$method])) {
|
||||
if (!isset($this->tdDescriptions['methods'][$method])) {
|
||||
$this->addToLang('method_'.$method);
|
||||
if (\danog\MadelineProto\Lang::$lang['en']['method_'.$method] !== '') {
|
||||
$this->td_descriptions['methods'][$method]['description'] = \danog\MadelineProto\Lang::$lang['en']['method_'.$method];
|
||||
$this->tdDescriptions['methods'][$method]['description'] = \danog\MadelineProto\Lang::$lang['en']['method_'.$method];
|
||||
}
|
||||
}
|
||||
$md_method = '['.$phpMethod.']('.$method.'.md)';
|
||||
$this->docs_methods[$method] = '$MadelineProto->'.$md_method.'(\\['.$params.'\\]) === [$'.StrTools::markdownEscape($type).'](../types/'.$php_type.'.md)<a name="'.$method.'"></a>
|
||||
|
||||
';
|
||||
if (isset($this->td_descriptions['methods'][$method])) {
|
||||
$desc = \Parsedown::instance()->line(\trim(\explode("\n", $this->td_descriptions['methods'][$method]['description'])[0], '.'));
|
||||
if (isset($this->tdDescriptions['methods'][$method])) {
|
||||
$desc = \Parsedown::instance()->line(\trim(\explode("\n", $this->tdDescriptions['methods'][$method]['description'])[0], '.'));
|
||||
$dom = new \DOMDocument();
|
||||
$dom->loadHTML(\mb_convert_encoding($desc, 'HTML-ENTITIES', 'UTF-8'));
|
||||
$desc = $dom->textContent;
|
||||
$this->human_docs_methods[$this->td_descriptions['methods'][$method]['description'].': '.$method] = '* <a href="'.$method.'.html" name="'.$method.'">'.$desc.': '.$method.'</a>
|
||||
$this->human_docs_methods[$this->tdDescriptions['methods'][$method]['description'].': '.$method] = '* <a href="'.$method.'.html" name="'.$method.'">'.$desc.': '.$method.'</a>
|
||||
|
||||
';
|
||||
}
|
||||
@ -112,7 +112,7 @@ trait Methods
|
||||
| Name | Type | Required |
|
||||
|----------|---------------|----------|
|
||||
';
|
||||
if (isset($this->td_descriptions['methods'][$method]) && !empty($data['params'])) {
|
||||
if (isset($this->tdDescriptions['methods'][$method]) && !empty($data['params'])) {
|
||||
$table = '### Parameters:
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -164,13 +164,13 @@ trait Methods
|
||||
$human_ptype = 'File path or '.$ptype;
|
||||
}
|
||||
$type_or_bare_type = \ctype_upper(Tools::end(\explode('.', $param[$type_or_subtype]))[0]) || \in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53']) ? 'types' : 'constructors';
|
||||
if (!isset($this->td_descriptions['methods'][$method]['params'][$param['name']])) {
|
||||
if (isset($this->td_descriptions['methods'][$method]['description'])) {
|
||||
$this->td_descriptions['methods'][$method]['params'][$param['name']] = \danog\MadelineProto\Lang::$lang['en']['method_'.$method.'_param_'.$param['name'].'_type_'.$param['type']] ?? '';
|
||||
if (!isset($this->tdDescriptions['methods'][$method]['params'][$param['name']])) {
|
||||
if (isset($this->tdDescriptions['methods'][$method]['description'])) {
|
||||
$this->tdDescriptions['methods'][$method]['params'][$param['name']] = \danog\MadelineProto\Lang::$lang['en']['method_'.$method.'_param_'.$param['name'].'_type_'.$param['type']] ?? '';
|
||||
}
|
||||
}
|
||||
if (isset($this->td_descriptions['methods'][$method])) {
|
||||
$table .= '|'.StrTools::markdownEscape($param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.StrTools::markdownEscape($human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.$this->td_descriptions['methods'][$method]['params'][$param['name']].' | '.(isset($param['pow']) || ($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type'] || ($id = $this->TL->getConstructors($this->td)->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type'] ? 'Optional' : 'Yes').'|';
|
||||
if (isset($this->tdDescriptions['methods'][$method])) {
|
||||
$table .= '|'.StrTools::markdownEscape($param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.StrTools::markdownEscape($human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.$this->tdDescriptions['methods'][$method]['params'][$param['name']].' | '.(isset($param['pow']) || ($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type'] || ($id = $this->TL->getConstructors($this->td)->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type'] ? 'Optional' : 'Yes').'|';
|
||||
} else {
|
||||
$table .= '|'.StrTools::markdownEscape($param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.StrTools::markdownEscape($human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || ($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type'] || ($id = $this->TL->getConstructors($this->td)->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type'] ? 'Optional' : 'Yes').'|';
|
||||
}
|
||||
@ -200,7 +200,7 @@ trait Methods
|
||||
$pwr_params = "parseMode - string\n";
|
||||
}
|
||||
}
|
||||
$description = isset($this->td_descriptions['methods'][$method]) ? $this->td_descriptions['methods'][$method]['description'] : $method.' parameters, return type and example';
|
||||
$description = isset($this->tdDescriptions['methods'][$method]) ? $this->tdDescriptions['methods'][$method]['description'] : $method.' parameters, return type and example';
|
||||
$symFile = \str_replace('.', '_', $method);
|
||||
$redir = $symFile !== $method ? "\nredirect_from: /API_docs/methods/{$symFile}.html" : '';
|
||||
$description = \rtrim(\explode("\n", $description)[0], ':');
|
||||
@ -208,7 +208,7 @@ trait Methods
|
||||
if ($this->td) {
|
||||
$header .= "YOU CANNOT USE THIS METHOD IN MADELINEPROTO\n\n\n\n\n";
|
||||
}
|
||||
$header .= isset($this->td_descriptions['methods'][$method]) ? $this->td_descriptions['methods'][$method]['description'].PHP_EOL.PHP_EOL : '';
|
||||
$header .= isset($this->tdDescriptions['methods'][$method]) ? $this->tdDescriptions['methods'][$method]['description'].PHP_EOL.PHP_EOL : '';
|
||||
$table .= '
|
||||
|
||||
';
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace danog\MadelineProto\Ipc\Wrapper;
|
||||
|
||||
use Amp\ByteStream\InputStream as AmpInputStream;
|
||||
use Amp\ByteStream\PendingReadError;
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
|
@ -36,7 +36,7 @@ class Obj
|
||||
* @param string $name
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return \Generator
|
||||
* @return \Generator<mixed, mixed, mixed, mixed>
|
||||
*/
|
||||
public function __call(string $name, array $arguments = []): \Generator
|
||||
{
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace danog\MadelineProto\Ipc\Wrapper;
|
||||
|
||||
use Amp\ByteStream\ClosedException;
|
||||
use Amp\ByteStream\OutputStream as AmpOutputStream;
|
||||
use Amp\ByteStream\StreamException;
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
|
@ -22,6 +22,7 @@ namespace danog\MadelineProto\Loop\Update;
|
||||
use danog\Loop\ResumableSignalLoop;
|
||||
use danog\MadelineProto\Loop\InternalLoop;
|
||||
use danog\MadelineProto\MTProto;
|
||||
use danog\MadelineProto\MTProtoTools\UpdatesState;
|
||||
|
||||
/**
|
||||
* Update feed loop.
|
||||
@ -55,6 +56,10 @@ class FeedLoop extends ResumableSignalLoop
|
||||
* @var UpdateLoop
|
||||
*/
|
||||
private ?UpdateLoop $updater = null;
|
||||
/**
|
||||
* Update state
|
||||
*/
|
||||
private ?UpdatesState $state = null;
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
@ -267,14 +267,14 @@ trait AuthKeyHandler
|
||||
$server_time = $server_DH_inner_data['server_time'];
|
||||
$connection->time_delta = $server_time - \time();
|
||||
$this->logger->logger(\sprintf('Server-client time delta = %.1f s', $connection->time_delta), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->checkPG($dh_prime, $g);
|
||||
$this->checkG($g_a, $dh_prime);
|
||||
Crypt::checkPG($dh_prime, $g);
|
||||
Crypt::checkG($g_a, $dh_prime);
|
||||
for ($retry_id = 0; $retry_id <= $this->settings->getAuth()->getMaxAuthTries(); $retry_id++) {
|
||||
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$this->logger->logger('Generating g_b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$g_b = $g->powMod($b, $dh_prime);
|
||||
$this->checkG($g_b, $dh_prime);
|
||||
Crypt::checkG($g_b, $dh_prime);
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of g_b
|
||||
@ -401,87 +401,6 @@ trait AuthKeyHandler
|
||||
throw new \danog\MadelineProto\SecurityException('Auth Failed');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check validity of g_a parameters.
|
||||
*
|
||||
* @param BigInteger $g_a
|
||||
* @param BigInteger $p
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkG(BigInteger $g_a, BigInteger $p): bool
|
||||
{
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of g_a
|
||||
* 1 < g_a < p - 1
|
||||
*/
|
||||
$this->logger->logger('Executing g_a check (1/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($g_a->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g_a->compare($p->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException('g_a is invalid (1 < g_a < p - 1 is false).');
|
||||
}
|
||||
$this->logger->logger('Executing g_a check (2/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($g_a->compare(\danog\MadelineProto\Magic::$twoe1984) < 0 || $g_a->compare($p->subtract(\danog\MadelineProto\Magic::$twoe1984)) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException('g_a is invalid (2^1984 < g_a < p - 2^1984 is false).');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Check validity of p and g parameters.
|
||||
*
|
||||
* @param BigInteger $p
|
||||
* @param BigInteger $g
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkPG(BigInteger $p, BigInteger $g): bool
|
||||
{
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of dh_prime
|
||||
* Is it a prime?
|
||||
*/
|
||||
$this->logger->logger('Executing p/g checks (1/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if (!$p->isPrime()) {
|
||||
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime (p isn't a prime).");
|
||||
}
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of p
|
||||
* Is (p - 1) / 2 a prime?
|
||||
*
|
||||
* Almost always fails
|
||||
*/
|
||||
/*
|
||||
$this->logger->logger('Executing p/g checks (2/3)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if (!$p->subtract(\danog\MadelineProto\Magic::$one)->divide(\danog\MadelineProto\Magic::$two)[0]->isPrime()) {
|
||||
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime ((p - 1) / 2 isn't a prime).");
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of p
|
||||
* 2^2047 < p < 2^2048
|
||||
*/
|
||||
$this->logger->logger('Executing p/g checks (2/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($p->compare(\danog\MadelineProto\Magic::$twoe2047) <= 0 || $p->compare(\danog\MadelineProto\Magic::$twoe2048) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false).");
|
||||
}
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of g
|
||||
* 1 < g < p - 1
|
||||
*/
|
||||
$this->logger->logger('Executing g check...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($g->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g->compare($p->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Get diffie-hellman configuration.
|
||||
*
|
||||
@ -498,7 +417,7 @@ trait AuthKeyHandler
|
||||
}
|
||||
$dh_config['p'] = new BigInteger((string) $dh_config['p'], 256);
|
||||
$dh_config['g'] = new BigInteger($dh_config['g']);
|
||||
$this->checkPG($dh_config['p'], $dh_config['g']);
|
||||
Crypt::checkPG($dh_config['p'], $dh_config['g']);
|
||||
return $this->dh_config = $dh_config;
|
||||
}
|
||||
/**
|
||||
|
@ -19,6 +19,9 @@
|
||||
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use danog\MadelineProto\Logger;
|
||||
use tgseclib\Math\BigInteger;
|
||||
|
||||
abstract class Crypt
|
||||
{
|
||||
/**
|
||||
@ -117,4 +120,85 @@ abstract class Crypt
|
||||
$cipher->setIV($iv);
|
||||
return @$cipher->decrypt($message);
|
||||
}
|
||||
/**
|
||||
* Check validity of g_a parameters.
|
||||
*
|
||||
* @param BigInteger $g_a
|
||||
* @param BigInteger $p
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkG(BigInteger $g_a, BigInteger $p): bool
|
||||
{
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of g_a
|
||||
* 1 < g_a < p - 1
|
||||
*/
|
||||
Logger::log('Executing g_a check (1/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($g_a->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g_a->compare($p->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException('g_a is invalid (1 < g_a < p - 1 is false).');
|
||||
}
|
||||
Logger::log('Executing g_a check (2/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($g_a->compare(\danog\MadelineProto\Magic::$twoe1984) < 0 || $g_a->compare($p->subtract(\danog\MadelineProto\Magic::$twoe1984)) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException('g_a is invalid (2^1984 < g_a < p - 2^1984 is false).');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Check validity of p and g parameters.
|
||||
*
|
||||
* @param BigInteger $p
|
||||
* @param BigInteger $g
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function checkPG(BigInteger $p, BigInteger $g): bool
|
||||
{
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of dh_prime
|
||||
* Is it a prime?
|
||||
*/
|
||||
Logger::log('Executing p/g checks (1/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if (!$p->isPrime()) {
|
||||
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime (p isn't a prime).");
|
||||
}
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of p
|
||||
* Is (p - 1) / 2 a prime?
|
||||
*
|
||||
* Almost always fails
|
||||
*/
|
||||
/*
|
||||
$this->logger->logger('Executing p/g checks (2/3)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if (!$p->subtract(\danog\MadelineProto\Magic::$one)->divide(\danog\MadelineProto\Magic::$two)[0]->isPrime()) {
|
||||
throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime ((p - 1) / 2 isn't a prime).");
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of p
|
||||
* 2^2047 < p < 2^2048
|
||||
*/
|
||||
Logger::log('Executing p/g checks (2/2)...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($p->compare(\danog\MadelineProto\Magic::$twoe2047) <= 0 || $p->compare(\danog\MadelineProto\Magic::$twoe2048) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false).");
|
||||
}
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Check validity of g
|
||||
* 1 < g < p - 1
|
||||
*/
|
||||
Logger::log('Executing g check...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
if ($g->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g->compare($p->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
|
||||
throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ use Amp\Http\Status;
|
||||
use Amp\Producer;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\FileCallbackInterface;
|
||||
use danog\MadelineProto\Ipc\Client;
|
||||
use danog\MadelineProto\Settings;
|
||||
use danog\MadelineProto\Stream\Common\BufferedRawStream;
|
||||
use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
@ -225,7 +227,9 @@ trait FilesLogic
|
||||
if (\is_resource($file) || (\is_object($file) && $file instanceof InputStream)) {
|
||||
return yield from $this->uploadFromStream($file, 0, '', $fileName, $cb, $encrypted);
|
||||
}
|
||||
if (!$this->settings->getFiles()->getAllowAutomaticUpload()) {
|
||||
/** @var Settings */
|
||||
$settings = $this instanceof Client ? yield $this->getSettings() : $this->settings;
|
||||
if (!$settings->getFiles()->getAllowAutomaticUpload()) {
|
||||
return yield from $this->uploadFromUrl($file, 0, $fileName, $cb, $encrypted);
|
||||
}
|
||||
$file = Tools::absolute($file);
|
||||
|
@ -32,8 +32,6 @@ use tgseclib\Math\BigInteger;
|
||||
*/
|
||||
class PasswordCalculator
|
||||
{
|
||||
use AuthKeyHandler;
|
||||
|
||||
/**
|
||||
* The algorithm to use for calculating the hash of new passwords (a PasswordKdfAlgo object).
|
||||
*
|
||||
@ -107,7 +105,7 @@ class PasswordCalculator
|
||||
case 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow':
|
||||
$object['current_algo']['g'] = new BigInteger($object['current_algo']['g']);
|
||||
$object['current_algo']['p'] = new BigInteger((string) $object['current_algo']['p'], 256);
|
||||
$this->checkPG($object['current_algo']['p'], $object['current_algo']['g']);
|
||||
Crypt::checkPG($object['current_algo']['p'], $object['current_algo']['g']);
|
||||
$object['current_algo']['gForHash'] = \str_pad($object['current_algo']['g']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
$object['current_algo']['pForHash'] = \str_pad($object['current_algo']['p']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
break;
|
||||
@ -137,7 +135,7 @@ class PasswordCalculator
|
||||
case 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow':
|
||||
$object['new_algo']['g'] = new BigInteger($object['new_algo']['g']);
|
||||
$object['new_algo']['p'] = new BigInteger((string) $object['new_algo']['p'], 256);
|
||||
$this->checkPG($object['new_algo']['p'], $object['new_algo']['g']);
|
||||
Crypt::checkPG($object['new_algo']['p'], $object['new_algo']['g']);
|
||||
$object['new_algo']['gForHash'] = \str_pad($object['new_algo']['g']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
$object['new_algo']['pForHash'] = \str_pad($object['new_algo']['p']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
break;
|
||||
@ -211,7 +209,7 @@ class PasswordCalculator
|
||||
$kg_x = $k->multiply($g_x)->powMod(Magic::$one, $p);
|
||||
$a = new BigInteger(\danog\MadelineProto\Tools::random(2048 / 8), 256);
|
||||
$A = $g->powMod($a, $p);
|
||||
$this->checkG($A, $p);
|
||||
Crypt::checkG($A, $p);
|
||||
$AForHash = \str_pad($A->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
$b_kg_x = $B->powMod(Magic::$one, $p)->subtract($kg_x);
|
||||
$u = new BigInteger(\hash('sha256', $AForHash.$BForHash, true), 256);
|
||||
|
@ -636,7 +636,21 @@ trait PeerHandler
|
||||
/**
|
||||
* @return (((mixed|string)[]|mixed|string)[]|int|mixed|string)[]
|
||||
*
|
||||
* @psalm-return array{InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}, Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}, DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}}, NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}}, InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}}, InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}}, bot_api_id: int|mixed, type: string}
|
||||
* @psalm-return array{
|
||||
* InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed},
|
||||
* Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed},
|
||||
* DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
|
||||
* NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
|
||||
* InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
|
||||
* InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
|
||||
* bot_api_id: int|string,
|
||||
* user_id?: int,
|
||||
* chat_id?: int,
|
||||
* channel_id?: int,
|
||||
* InputUser?: {_: string, user_id?: int, access_hash?: mixed, min?: bool},
|
||||
* InputChannel?: {_: string, channel_id: int, access_hash: mixed, min: bool},
|
||||
* type: string
|
||||
* }
|
||||
*/
|
||||
private function genAll($constructor, $folder_id = null): array
|
||||
{
|
||||
|
@ -504,6 +504,7 @@ class ReferenceDatabase implements TLCallback
|
||||
$local_id = \danog\MadelineProto\Tools::packSignedInt($location['local_id']);
|
||||
return $locationType.$dc_id.$volume_id.$local_id;
|
||||
}
|
||||
throw new \danog\MadelineProto\Exception("Invalid location type specified!");
|
||||
}
|
||||
public function __debugInfo()
|
||||
{
|
||||
|
@ -86,6 +86,11 @@ class MyTelegramOrgWrapper
|
||||
public function __construct($settings)
|
||||
{
|
||||
$this->settings = Settings::parseFromLegacy($settings);
|
||||
if (!$this->settings instanceof Settings) {
|
||||
$settings = new Settings;
|
||||
$settings->merge($this->settings);
|
||||
$this->settings = $settings;
|
||||
}
|
||||
$this->__wakeup();
|
||||
}
|
||||
/**
|
||||
|
@ -21,6 +21,7 @@ namespace danog\MadelineProto\SecretChats;
|
||||
|
||||
use danog\MadelineProto\Loop\Update\UpdateLoop;
|
||||
use danog\MadelineProto\MTProto;
|
||||
use danog\MadelineProto\MTProtoTools\Crypt;
|
||||
|
||||
/**
|
||||
* Manages secret chats.
|
||||
@ -60,7 +61,7 @@ trait AuthKeyHandler
|
||||
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new \tgseclib\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$params['g_a'] = new \tgseclib\Math\BigInteger((string) $params['g_a'], 256);
|
||||
$this->checkG($params['g_a'], $dh_config['p']);
|
||||
Crypt::checkG($params['g_a'], $dh_config['p']);
|
||||
$key = ['auth_key' => \str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
|
||||
//$this->logger->logger($key);
|
||||
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
|
||||
@ -68,7 +69,7 @@ trait AuthKeyHandler
|
||||
$key['visualization_46'] = \substr(\hash('sha256', $key['auth_key'], true), 20);
|
||||
$this->secret_chats[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputEncryptedChat' => ['_' => 'inputEncryptedChat', 'chat_id' => $params['id'], 'access_hash' => $params['access_hash']], 'in_seq_no_x' => 1, 'out_seq_no_x' => 0, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => \time(), 'incoming' => [], 'outgoing' => [], 'created' => \time(), 'rekeying' => [0], 'key_x' => 'from server', 'mtproto' => 1];
|
||||
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
|
||||
$this->checkG($g_b, $dh_config['p']);
|
||||
Crypt::checkG($g_b, $dh_config['p']);
|
||||
yield from $this->methodCallAsyncRead('messages.acceptEncryption', ['peer' => $params['id'], 'g_b' => $g_b->toBytes(), 'key_fingerprint' => $key['fingerprint']], ['datacenter' => $this->datacenter->curdc]);
|
||||
yield from $this->notifyLayer($params['id']);
|
||||
$this->logger->logger('Secret chat '.$params['id'].' accepted successfully!', \danog\MadelineProto\Logger::NOTICE);
|
||||
@ -93,7 +94,7 @@ trait AuthKeyHandler
|
||||
$a = new \tgseclib\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$this->logger->logger('Generating g_a...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$g_a = $dh_config['g']->powMod($a, $dh_config['p']);
|
||||
$this->checkG($g_a, $dh_config['p']);
|
||||
Crypt::checkG($g_a, $dh_config['p']);
|
||||
$res = yield from $this->methodCallAsyncRead('messages.requestEncryption', ['user_id' => $user, 'g_a' => $g_a->toBytes()], ['datacenter' => $this->datacenter->curdc]);
|
||||
$this->temp_requested_secret_chats[$res['id']] = $a;
|
||||
$this->updaters[UpdateLoop::GENERIC]->resume();
|
||||
@ -116,7 +117,7 @@ trait AuthKeyHandler
|
||||
}
|
||||
$dh_config = (yield from $this->getDhConfig());
|
||||
$params['g_a_or_b'] = new \tgseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
|
||||
$this->checkG($params['g_a_or_b'], $dh_config['p']);
|
||||
Crypt::checkG($params['g_a_or_b'], $dh_config['p']);
|
||||
$key = ['auth_key' => \str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
|
||||
unset($this->temp_requested_secret_chats[$params['id']]);
|
||||
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
|
||||
@ -159,7 +160,7 @@ trait AuthKeyHandler
|
||||
$a = new \tgseclib\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$this->logger->logger('Generating g_a...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$g_a = $dh_config['g']->powMod($a, $dh_config['p']);
|
||||
$this->checkG($g_a, $dh_config['p']);
|
||||
Crypt::checkG($g_a, $dh_config['p']);
|
||||
$e = \danog\MadelineProto\Tools::random(8);
|
||||
$this->temp_rekeyed_secret_chats[$e] = $a;
|
||||
$this->secret_chats[$chat]['rekeying'] = [1, $e];
|
||||
@ -194,7 +195,7 @@ trait AuthKeyHandler
|
||||
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new \tgseclib\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||
$params['g_a'] = new \tgseclib\Math\BigInteger((string) $params['g_a'], 256);
|
||||
$this->checkG($params['g_a'], $dh_config['p']);
|
||||
Crypt::checkG($params['g_a'], $dh_config['p']);
|
||||
$key = ['auth_key' => \str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
|
||||
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
|
||||
$key['visualization_orig'] = $this->secret_chats[$chat]['key']['visualization_orig'];
|
||||
@ -202,7 +203,7 @@ trait AuthKeyHandler
|
||||
$this->temp_rekeyed_secret_chats[$params['exchange_id']] = $key;
|
||||
$this->secret_chats[$chat]['rekeying'] = [2, $params['exchange_id']];
|
||||
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
|
||||
$this->checkG($g_b, $dh_config['p']);
|
||||
Crypt::checkG($g_b, $dh_config['p']);
|
||||
yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAcceptKey', 'g_b' => $g_b->toBytes(), 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]], ['datacenter' => $this->datacenter->curdc]);
|
||||
$this->updaters[UpdateLoop::GENERIC]->resume();
|
||||
}
|
||||
@ -223,7 +224,7 @@ trait AuthKeyHandler
|
||||
$this->logger->logger('Committing rekeying of secret chat '.$chat.'...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$dh_config = (yield from $this->getDhConfig());
|
||||
$params['g_b'] = new \tgseclib\Math\BigInteger((string) $params['g_b'], 256);
|
||||
$this->checkG($params['g_b'], $dh_config['p']);
|
||||
Crypt::checkG($params['g_b'], $dh_config['p']);
|
||||
$key = ['auth_key' => \str_pad($params['g_b']->powMod($this->temp_rekeyed_secret_chats[$params['exchange_id']], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
|
||||
$key['fingerprint'] = \substr(\sha1($key['auth_key'], true), -8);
|
||||
$key['visualization_orig'] = $this->secret_chats[$chat]['key']['visualization_orig'];
|
||||
|
@ -191,6 +191,7 @@ class SessionPaths
|
||||
/**
|
||||
* Get IPC state.
|
||||
*
|
||||
* @psalm-suppress InvalidReturnType
|
||||
* @return Promise<?IpcState>
|
||||
*/
|
||||
public function getIpcState(): Promise
|
||||
@ -222,6 +223,7 @@ class SessionPaths
|
||||
/**
|
||||
* Get light state.
|
||||
*
|
||||
* @psalm-suppress InvalidReturnType
|
||||
* @return Promise<LightState>
|
||||
*/
|
||||
public function getLightState(): Promise
|
||||
|
@ -40,6 +40,12 @@ trait RawStream
|
||||
}
|
||||
public function end(string $finalData = ''): Promise
|
||||
{
|
||||
return \danog\MadelineProto\Tools::call($this->endGenerator($finalData));
|
||||
if (\method_exists($this, 'endGenerator')) {
|
||||
return \danog\MadelineProto\Tools::call($this->endGenerator($finalData));
|
||||
} else {
|
||||
$promise = $this->write($finalData);
|
||||
$promise->onResolve(fn () => $this->disconnect());
|
||||
return $promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ trait TD
|
||||
} else {
|
||||
switch (\end($mtproto)) {
|
||||
case 'choose_chat_id_from_botapi':
|
||||
$newparams[$td] = (yield from $this->getInfo($params[$mtproto[0]]))['bot_api_id'] == $this->authorization['user']['id'] ? $this->getId($params['from_id']) : (yield from $this->getInfo($params[$mtproto[0]])['bot_api_id']);
|
||||
$newparams[$td] = (yield from $this->getInfo($params[$mtproto[0]]))['bot_api_id'] == $this->authorization['user']['id'] ? $this->getId($params['from_id']) : (yield from $this->getInfo($params[$mtproto[0]]))['bot_api_id'];
|
||||
break;
|
||||
case 'choose_incoming_or_sent':
|
||||
$newparams[$td] = ['_' => $params['out'] ? 'messageIsSuccessfullySent' : 'messageIsIncoming'];
|
||||
|
@ -427,7 +427,7 @@ abstract class Tools extends StrTools
|
||||
* @param mixed $default
|
||||
*
|
||||
* @psalm-param Promise<TReturn>|TGenerator $promise Promise to which the timeout is applied.
|
||||
* @psalm-param TReturnAlt $timeout
|
||||
* @psalm-param TReturnAlt $default
|
||||
*
|
||||
* @return Promise<TReturn|TReturnAlt>
|
||||
*
|
||||
|
@ -20,6 +20,7 @@
|
||||
namespace danog\MadelineProto\VoIP;
|
||||
|
||||
use danog\MadelineProto\Loop\Update\UpdateLoop;
|
||||
use danog\MadelineProto\MTProtoTools\Crypt;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
@ -104,7 +105,7 @@ trait AuthKeyHandler
|
||||
$a = \tgseclib\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_g_a'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$g_a = $dh_config['g']->powMod($a, $dh_config['p']);
|
||||
$this->checkG($g_a, $dh_config['p']);
|
||||
Crypt::checkG($g_a, $dh_config['p']);
|
||||
$controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED);
|
||||
$controller->storage = ['a' => $a, 'g_a' => \str_pad($g_a->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
|
||||
$res = yield from $this->methodCallAsyncRead('phone.requestCall', ['user_id' => $user, 'g_a_hash' => \hash('sha256', $g_a->toBytes(), true), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_p2p' => true, 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]);
|
||||
@ -134,7 +135,7 @@ trait AuthKeyHandler
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_b'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = \tgseclib\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
|
||||
$g_b = $dh_config['g']->powMod($b, $dh_config['p']);
|
||||
$this->checkG($g_b, $dh_config['p']);
|
||||
Crypt::checkG($g_b, $dh_config['p']);
|
||||
try {
|
||||
$res = yield from $this->methodCallAsyncRead('phone.acceptCall', ['peer' => $call, 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
@ -172,7 +173,7 @@ trait AuthKeyHandler
|
||||
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$dh_config = (yield from $this->getDhConfig());
|
||||
$params['g_b'] = new \tgseclib\Math\BigInteger((string) $params['g_b'], 256);
|
||||
$this->checkG($params['g_b'], $dh_config['p']);
|
||||
Crypt::checkG($params['g_b'], $dh_config['p']);
|
||||
$key = \str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
try {
|
||||
$res = (yield from $this->methodCallAsyncRead('phone.confirmCall', ['key_fingerprint' => \substr(\sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]))['phone_call'];
|
||||
@ -224,7 +225,7 @@ trait AuthKeyHandler
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['invalid_g_a']);
|
||||
}
|
||||
$params['g_a_or_b'] = new \tgseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
|
||||
$this->checkG($params['g_a_or_b'], $dh_config['p']);
|
||||
Crypt::checkG($params['g_a_or_b'], $dh_config['p']);
|
||||
$key = \str_pad($params['g_a_or_b']->powMod($this->calls[$params['id']]->storage['b'], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
|
||||
if (\substr(\sha1($key, true), -8) != $params['key_fingerprint']) {
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_invalid']);
|
||||
|
Loading…
Reference in New Issue
Block a user