mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-27 09:34:38 +01:00
330 lines
16 KiB
PHP
Executable File
330 lines
16 KiB
PHP
Executable File
<?php
|
||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||
require_once ('libpy2php.php');
|
||
require_once ('os_path.php');
|
||
require_once ('crypt.php');
|
||
require_once ('prime.php');
|
||
require_once ('TL.php');
|
||
require_once ('Struct.php');
|
||
|
||
/**
|
||
* Function to get hex crc32
|
||
* :param data: Data to encode
|
||
*/
|
||
function newcrc32($data) {
|
||
return hexdec(hash("crc32b", $data));
|
||
}
|
||
|
||
/**
|
||
* Function to dump the hex version of a string.
|
||
* :param what: What to dump
|
||
*/
|
||
function hex_dump($what) { var_dump(bin2hex($what)); };
|
||
|
||
/**
|
||
* Function slice a certain string. Works just like array_slice, only with a string.
|
||
* :param data: data to slice
|
||
* :param offset: If offset is non-negative, the sequence will start at that offset in the string. If offset is negative, the sequence will start that far from the end of the string.
|
||
* :param length: If length is given and is positive, then the sequence will have up to that many chars in it. If the string is shorter than the length, then only the available string chars will be present. If length is given and is negative then the sequence will stop that many chars from the end of the string. If it is omitted, then the sequence will have everything from offset up until the end of the string.
|
||
*/
|
||
function file_slice($data, $offset, $length) {
|
||
$size = strlen($data);
|
||
if($offset < 0) $offset = $size + $offset;
|
||
if($length < 0) $length = $size + $length;
|
||
if($length == null) $length = $size;
|
||
if($offset == null) $offset = 0;
|
||
$packet_sliced = "";
|
||
while ($length != 0) { if($offset == $size) break; $packet_sliced .= $data[$offset]; $offset++; $length--; }
|
||
return $packet_sliced;
|
||
}
|
||
|
||
|
||
/**
|
||
* len.
|
||
*
|
||
* Get the length of a string or of an array
|
||
*
|
||
* @param $input String or array to parse
|
||
*
|
||
* @return int with the length
|
||
**/
|
||
function len($input)
|
||
{
|
||
if (is_array($input)) {
|
||
return count($input);
|
||
}
|
||
|
||
return strlen($input);
|
||
}
|
||
|
||
/**
|
||
* Function to visualize byte streams. Split into bytes, print to console.
|
||
* :param bs: BYTE STRING
|
||
*/
|
||
function vis($bs) {
|
||
$bs = str_split($bs);
|
||
$symbols_in_one_line = 8;
|
||
$n = floor(len($bs) / $symbols_in_one_line);
|
||
$i = 0;
|
||
foreach (pyjslib_range($n) as $i) {
|
||
echo join($i * $symbols_in_one_line . ' | ' . ' ',
|
||
array_map(function($el) { return "%02X" % $el; }, array_slice($bs,$i*$symbols_in_one_line, ($i+1)*$symbols_in_one_line))
|
||
) . PHP_EOL;
|
||
}
|
||
if (!(len($bs) % $symbols_in_one_line) == 0) {
|
||
echo join((($i + 1) * $symbols_in_one_line) . ' | ' . ' ',
|
||
array_map(function($el) { return "%02X" % $el; }, array_slice($bs, ($i+1)*$symbols_in_one_line), null)
|
||
) . PHP_EOL;
|
||
}
|
||
}
|
||
vis("jndjN");
|
||
/**
|
||
* bytes_to_long(string) : long
|
||
* Convert a byte string to a long integer.
|
||
* This is (essentially) the inverse of long_to_bytes().
|
||
*/
|
||
function bytes_to_long($s) {
|
||
$acc = 0;
|
||
$length = strlen($s);
|
||
if (($length % 4)) {
|
||
$extra = (4 - ($length % 4));
|
||
$s = (($b('') * $extra) + $s);
|
||
$length = ($length + $extra);
|
||
}
|
||
foreach( pyjslib_range(0, $length, 4) as $i ) {
|
||
$acc = ($acc << 32 + $GLOBALS["struct"]->unpack('I', array_slice($s, $i, ($i + 4) - $i))[0]);
|
||
}
|
||
return $acc;
|
||
}
|
||
|
||
function fread_all($handle) {
|
||
$pos = ftell($handle);
|
||
fseek($handle, 0);
|
||
$content = fread($handle, fstat($handle)["size"]);
|
||
fseek($handle, $pos);
|
||
return $content;
|
||
}
|
||
function fopen_and_write($filename, $mode, $data) {
|
||
$handle = fopen($filename, $mode);
|
||
fwrite($handle, $data);
|
||
rewind($handle);
|
||
return $handle;
|
||
}
|
||
/**
|
||
* long_to_bytes(n:long, blocksize:int) : string
|
||
* Convert a long integer to a byte string.
|
||
* If optional blocksize is given and greater than zero, pad the front of the
|
||
* byte string with binary zeros so that the length is a multiple of
|
||
* blocksize.
|
||
*/
|
||
function long_to_bytes($n,$blocksize=0) {
|
||
$s = $b('');
|
||
$n = long($n);
|
||
while (($n > 0)) {
|
||
$s = ($GLOBALS["struct"]->pack('I', $n & 4294967295) + $s);
|
||
$n = $n >> 32;
|
||
}
|
||
foreach( pyjslib_range(strlen($s)) as $i ) {
|
||
if (($s[$i] != $b('')[0])) {
|
||
break;
|
||
}
|
||
}
|
||
$s = array_slice($s, $i, null);
|
||
if (($blocksize > 0) && (strlen($s) % $blocksize)) {
|
||
$s = ((($blocksize - (strlen($s) % $blocksize)) * $b('')) + $s);
|
||
}
|
||
return $s;
|
||
}
|
||
/**
|
||
* Manages TCP Transport. encryption and message frames
|
||
*/
|
||
class Session {
|
||
function __construct($ip, $port, $auth_key = null, $server_salt = null) {
|
||
$this->sock = fsockopen("tcp://".$ip.":".$port);
|
||
$this->number = 0;
|
||
$this->timedelta = 0;
|
||
$this->session_id = random_bytes(8);
|
||
$this->auth_key = $auth_key;
|
||
$this->auth_key_id = $this->auth_key ? array_slice(sha1($this->auth_key, true), -8, null) : null;
|
||
stream_set_timeout($this->sock, 5);
|
||
$this->MAX_RETRY = 5;
|
||
$this->AUTH_MAX_RETRY = 5;
|
||
}
|
||
function __destruct() {
|
||
fclose($this->sock);
|
||
}
|
||
/**
|
||
* Forming the message frame and sending message to server
|
||
* :param message: byte string to send
|
||
*/
|
||
function send_message($message_data) {
|
||
$message_id = $GLOBALS["struct"]->pack('<Q', (pyjslib_int(((time() + $this->timedelta) * pow(2, 30))) * 4));
|
||
|
||
if (($this->auth_key == null) || ($this->server_salt == null)) {
|
||
$message = ' |