Skip to content

Commit

Permalink
More type improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Oct 3, 2020
1 parent 4f69701 commit 118cf24
Show file tree
Hide file tree
Showing 22 changed files with 178 additions and 127 deletions.
2 changes: 1 addition & 1 deletion src/danog/MadelineProto/AbstractAPIFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ abstract class AbstractAPIFactory extends AsyncConstruct
/**
* Method list.
*
* @var string[]
* @var array<string, callable>
*/
protected array $methods = [];

Expand Down
1 change: 1 addition & 0 deletions src/danog/MadelineProto/AnnotationsBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function __construct(Logger $logger, array $settings, string $output, arr
$this->reflectionClasses = $reflectionClasses;
$this->logger = $logger;
$this->namespace = $namespace;
/** @psalm-suppress InvalidArgument */
$this->TL = new TL(new class($logger) {
public function __construct($logger)
{
Expand Down
5 changes: 3 additions & 2 deletions src/danog/MadelineProto/DoHConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ public function connect(string $uri, ?ConnectContext $socketContext = null, ?Can

// This is reached if either all URIs failed or the maximum number of attempts is reached.
/** @noinspection PhpUndefinedVariableInspection */

throw $e;
if ($e) {
throw $e;
}
})());
}
}
12 changes: 9 additions & 3 deletions src/danog/MadelineProto/DocsBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -119,8 +125,8 @@ public function mkDocs(): void
}
}
}
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'],
Expand Down
26 changes: 13 additions & 13 deletions src/danog/MadelineProto/DocsBuilder/Methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,22 @@ public function mkMethods(): void
$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>
';
}
Expand All @@ -112,7 +112,7 @@ public function mkMethods(): void
| 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 |
Expand Down Expand Up @@ -164,13 +164,13 @@ public function mkMethods(): void
$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').'|';
}
Expand Down Expand Up @@ -200,15 +200,15 @@ public function mkMethods(): void
$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], ':');
$header = $this->template('Method', $method, $description, $redir, StrTools::markdownEscape($method));
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 .= '
';
Expand Down
1 change: 1 addition & 0 deletions src/danog/MadelineProto/Ipc/Wrapper/InputStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/danog/MadelineProto/Ipc/Wrapper/Obj.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function __construct(Wrapper $wrapper, array $methods)
* @param string $name
* @param array $arguments
*
* @return \Generator
* @return \Generator<mixed, mixed, mixed, mixed>
*/
public function __call(string $name, array $arguments = []): \Generator
{
Expand Down
2 changes: 2 additions & 0 deletions src/danog/MadelineProto/Ipc/Wrapper/OutputStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
5 changes: 5 additions & 0 deletions src/danog/MadelineProto/Loop/Update/FeedLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProtoTools\UpdatesState;

/**
* Update feed loop.
Expand Down Expand Up @@ -55,6 +56,10 @@ class FeedLoop extends ResumableSignalLoop
* @var UpdateLoop
*/
private ?UpdateLoop $updater = null;
/**
* Update state
*/
private ?UpdatesState $state = null;
/**
* Constructor.
*
Expand Down
89 changes: 4 additions & 85 deletions src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,14 @@ public function createAuthKey(int $expires_in, string $datacenter): \Generator
$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
Expand Down Expand Up @@ -401,87 +401,6 @@ public function createAuthKey(int $expires_in, string $datacenter): \Generator
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.
*
Expand All @@ -498,7 +417,7 @@ public function getDhConfig(): \Generator
}
$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;
}
/**
Expand Down
84 changes: 84 additions & 0 deletions src/danog/MadelineProto/MTProtoTools/Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

namespace danog\MadelineProto\MTProtoTools;

use danog\MadelineProto\Logger;
use tgseclib\Math\BigInteger;

abstract class Crypt
{
/**
Expand Down Expand Up @@ -117,4 +120,85 @@ public static function igeDecrypt(string $message, string $key, string $iv): str
$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;
}
}
Loading

0 comments on commit 118cf24

Please sign in to comment.