1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-30 06:59:01 +01:00

Updated dependencies

This commit is contained in:
danogentili 2016-07-29 17:19:25 +02:00
parent 7f246543f3
commit 5bfb6a3b7e
17 changed files with 2569 additions and 519 deletions

View File

@ -3,7 +3,7 @@
"description": "PHP implementation of telegram's MTProto protocol.",
"type": "project",
"require": {
"danog/phpstruct": "^0.4.2",
"danog/phpstruct": "^1.1",
"phpseclib/phpseclib": "^2.0"
},
"license": "MIT",

14
composer.lock generated
View File

@ -4,21 +4,21 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "a75dfba16d66cb4ae9913439bbdb796b",
"content-hash": "a6860b86164e69555776b8ab636fcbfb",
"hash": "f60c705a31a0dc3e563a1cb78ce2bef9",
"content-hash": "018ac32ece19a237770fd6102396f9b3",
"packages": [
{
"name": "danog/phpstruct",
"version": "0.4.2",
"version": "1.1",
"source": {
"type": "git",
"url": "https://github.com/danog/PHPStruct.git",
"reference": "da3d4f5a111823bc5518af054c41f32cce0f221e"
"reference": "ac1d7a0b1eb54d5b10dca553be816c8fb0881e47"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/danog/PHPStruct/zipball/da3d4f5a111823bc5518af054c41f32cce0f221e",
"reference": "da3d4f5a111823bc5518af054c41f32cce0f221e",
"url": "https://api.github.com/repos/danog/PHPStruct/zipball/ac1d7a0b1eb54d5b10dca553be816c8fb0881e47",
"reference": "ac1d7a0b1eb54d5b10dca553be816c8fb0881e47",
"shasum": ""
},
"require": {
@ -53,7 +53,7 @@
"struct",
"unpack"
],
"time": "2016-07-15 13:07:47"
"time": "2016-07-29 15:13:54"
},
{
"name": "phpseclib/phpseclib",

View File

@ -95,17 +95,17 @@
},
{
"name": "danog/phpstruct",
"version": "0.4.2",
"version_normalized": "0.4.2.0",
"version": "1.1",
"version_normalized": "1.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/danog/PHPStruct.git",
"reference": "da3d4f5a111823bc5518af054c41f32cce0f221e"
"reference": "ac1d7a0b1eb54d5b10dca553be816c8fb0881e47"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/danog/PHPStruct/zipball/da3d4f5a111823bc5518af054c41f32cce0f221e",
"reference": "da3d4f5a111823bc5518af054c41f32cce0f221e",
"url": "https://api.github.com/repos/danog/PHPStruct/zipball/ac1d7a0b1eb54d5b10dca553be816c8fb0881e47",
"reference": "ac1d7a0b1eb54d5b10dca553be816c8fb0881e47",
"shasum": ""
},
"require": {
@ -114,7 +114,7 @@
"require-dev": {
"phpunit/phpunit": "5.4.*"
},
"time": "2016-07-15 13:07:47",
"time": "2016-07-29 15:13:54",
"type": "library",
"installation-source": "dist",
"autoload": {

View File

@ -1 +1,2 @@
/vendor/
*swp

View File

@ -1,9 +1,20 @@
sudo: required
dist: trusty
group: edge
language: php
php:
- '7.0'
- nightly
- hhvm
- '5.6'
addons:
apt:
packages:
- python3
before_script:
- composer update --dev
script:
- phpunit --bootstrap lib/danog/PHP/Struct.php tests/danog/PHP/StructTest.php --verbose
- vendor/phpunit/phpunit/phpunit --bootstrap lib/danog/PHP/Struct.php --bootstrap lib/danog/PHP/StructException.php tests/danog/PHP/StructClass.php --bootstrap lib/danog/PHP/StructTools.php tests/danog/PHP/StructTest.php --verbose
- tests/danog/PHP/py2php.php
- tests/danog/PHP/php2py.py

View File

@ -2,9 +2,10 @@
[![Build Status](https://travis-ci.org/danog/PHPStruct.svg?branch=master)](https://travis-ci.org/danog/PHPStruct)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7b91e30ec89a4313bdb34766ea990113)](https://www.codacy.com/app/daniil-gentili-dg/PHPStruct?utm_source=github.com&utm_medium=referral&utm_content=danog/PHPStruct&utm_campaign=Badge_Grade)
[![Packagist](https://img.shields.io/packagist/l/danog/phpstruct.svg?maxAge=2592000)](https://packagist.org/packages/danog/phpstruct)
[![Packagist](https://img.shields.io/packagist/dm/danog/phpstruct.svg?maxAge=2592000)](https://packagist.org/packages/danog/phpstruct)
[![HHVM](https://img.shields.io/hhvm/danog/phpstruct.svg?maxAge=2592000)]()
[![License](https://img.shields.io/packagist/l/danog/phpstruct.svg?maxAge=2592000?style=flat-square)](https://opensource.org/licenses/MIT)
[![Packagist download count](https://img.shields.io/packagist/dm/danog/phpstruct.svg?maxAge=2592000?style=flat-square)](https://packagist.org/packages/danog/phpstruct)
[![Packagist](https://img.shields.io/packagist/v/danog/PHPStruct.svg?maxAge=2592000?style=flat-square)](https://packagist.org/packages/danog/phpstruct)
[![HHVM Status](http://hhvm.h4cc.de/badge/danog/phpstruct.svg?style=flat-square)](http://hhvm.h4cc.de/package/danog/phpstruct)
[![StyleCI](https://styleci.io/repos/62454134/shield)](https://styleci.io/repos/62454134)
Licensed under MIT.
@ -16,7 +17,18 @@ This library was created to help me develop a [client for the mtproto protocol](
The functions and the formats are exactly the ones used in python's struct
(https://docs.python.org/3/library/struct.html)
For now custom byte size may not work properly on certain machines for the i, I, f and d formats.
This library can be used to pack/unpack strings, ints, floats, chars and bools into bytes.
It has lots of advantages over PHP's native implementation of pack and unpack, such as:
* Custom byte endianness.
* Lots of useful formats that aren't present in the native implementation.
* The syntax of the format string of pack and unpack is the same as in python's struct module.
* The result of unpack is normal numerically indexed array that starts from 0 like it should.
* The result of unpack has type casted values (int for integer formats, bool for boolean formats, float for float formats and string for all of the other formats).
* The calcsize function is implemented.
* The q and Q formats can be used even on 32 bit systems (the downside is limited precision).
* Padding is supported for the @ modifier.
For now custom byte size may not work properly on certain machines for the f and d formats.
## Installation
@ -26,17 +38,28 @@ composer require danog/phpstruct
```
# Usage
Dynamic (recommended)
```
require('vendor/autoload.php');
$struct = new \danog\PHP\Struct();
$struct = new \danog\PHP\StructClass();
$pack = $struct->pack("2cxi", "ab", 44);
$unpack = $struct->unpack("2cxi", $pack);
var_dump($unpack);
$count = $struct->calcsize("2cxi");
```
Dynamic (while specifying format string during istantiation)
```
require('vendor/autoload.php');
$struct = new \danog\PHP\StructClass("2cxi");
$pack = $struct->pack("ab", 44);
$unpack = $struct->unpack($pack);
var_dump($unpack);
$count = $struct->size;
$formatstring = $struct->format;
```
This library can also be used statically:
Static
```

1317
vendor/danog/phpstruct/composer.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,27 @@
<?php
//require('vendor/autoload.php');
require 'lib/danog/PHP/StructTools.php';
require 'lib/danog/PHP/StructClass.php';
require 'lib/danog/PHP/StructException.php';
require 'lib/danog/PHP/Struct.php';
var_dump(bin2hex(pack('J', 18446744073709550590)));
var_dump(bin2hex(\danog\PHP\Struct::pack('Q', 18446744073709550590)));
//var_dump(["nv", 61, 61, false, 333, 444, 232423, 234342, 243342423424, 234234234234, 234234234234, 234234234234, 34434, 344434, 2.2343, 3.03424, "dd"]);
var_dump(\danog\PHP\Struct::unpack('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP',
\danog\PHP\Struct::pack('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP',
'n', 'v', 100, 100, false, 333, 444, 232423, 234342, 234234234234, 234234234234, 234234234234, 234234234234, 34434, 344434, 2.2343,
3.03424, 'df', 'asdfghjkl', 1283912
var_dump(\danog\PHP\Struct::calcsize('>l'));
)
));
var_dump(\danog\PHP\Struct::calcsize('n'));
// 2c x b x B x ? x h x H x i x I x l x L x q x Q x n x N x f x d x 2s x
//print(struct.unpack("2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx", struct.pack("2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx", "nv", 100, 100, False, 333, 444, 232423, 234342, 234234234234, 234234234234, 234234234234, 234234234234, 34434, 344434, 2.2343, 3.03424, "dd")));
// Dynamic usage with format definition on istantiation
$struct = new \danog\PHP\StructClass('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP');
var_dump($struct->unpack($struct->pack('n', 'v', -127, 255, true, -32767, 65535, -2147483647, 4294967295, 999999, 9999999, -9223372036854775807, 18446744073709550590, 34434, 344434, 2.2343, 3.03424, 'df', 'asdfghjkl', 1283912)));
// Dynamic usage with format definition on function call
$struct = new \danog\PHP\StructClass();
var_dump($struct->unpack('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP', $struct->pack('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP', 'n', 'v', -127, 255, true, -32767, 65535, -2147483647, 4294967295, 999999, 9999999, -9223372036854775807, 18446744073709550590, 34434, 344434, 2.2343, 3.03424, 'df', 'asdfghjkl', 1283912)));
// Static usage
var_dump(\danog\PHP\Struct::unpack('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP', \danog\PHP\Struct::pack('2cxbxBx?xhxHxixIxlxLxqxQxnxNxfxdx2sx5pP', 'n', 'v', -127, 255, true, -32767, 65535, -2147483647, 4294967295, 999999, 9999999, -922337203685, 18446744073709550590, 34434, 344434, 2.2343, 3.03424, 'df', 'asdfghjkl', 1283912)));
// S'more examples
var_dump(\danog\PHP\Struct::calcsize('f'));
var_dump(bin2hex(pack('J', 999998999999999)));
var_dump(bin2hex(\danog\PHP\Struct::pack('>Q', 999998999999999)));

View File

@ -7,233 +7,29 @@ namespace danog\PHP;
* PHP implementation of Python's struct module.
* This library was created to help me develop a [client for the mtproto protocol](https://github.com/danog/MadelineProto).
* The functions and the formats are exactly the ones used in python's struct (https://docs.python.org/3/library/struct.html)
* For now custom byte size may not work properly on certain machines for the i, I, f and d formats.
* For now custom byte size may not work properly on certain machines for the f and d formats.
*
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT license
*/
// Main class
// Struct class (for static access)
class Struct
{
/**
* Constructor.
*
* Sets modifiers and gets endianness
*/
public function __construct()
{
$this->BIG_ENDIAN = (pack('L', 1) === pack('N', 1));
$this->IS64BIT = (PHP_INT_SIZE === 8);
$this->FORMATS = [
// These formats need to be modified after/before encoding/decoding.
'p' => 'p', // “Pascal string”, meaning a short variable-length string stored in a fixed number of bytes, given by the count. The first byte stored is the length of the string, or 255, whichever is smaller. The bytes of the string follow. If the string passed in to pack() is too long (longer than the count minus 1), only the leading count-1 bytes of the string are stored. If the string is shorter than count-1, it is padded with null bytes so that exactly count bytes in all are used. Note that for unpack(), the 'p' format character consumes count bytes, but that the string returned can never contain more than 255 characters.
// These formats have automatical byte size, this must be fixed.
'i' => 'i', // should be 4 (32 bit)
'I' => 'I', // should be 4 (32 bit)
'f' => 'f', // should be 4 (32 bit)
'd' => 'd', // should be 8 (64 bit)
// These formats should work exactly as in python's struct (same byte size, etc).
'c' => 'a',
'?' => 'c',
'x' => 'x',
'b' => 'c',
'B' => 'C',
'h' => 's',
'H' => 'S',
'l' => 'l',
'L' => 'L',
's' => 'a',
];
$this->NATIVE_FORMATS = array_merge([
// These formats need to be modified after/before encoding/decoding.
'P' => $this->IS64BIT ? 'Q' : 'L', // integer or long integer, depending on the size needed to hold a pointer when it has been cast to an integer type. A NULL pointer will always be returned as the Python integer 0. When packing pointer-sized values, Python integer or long integer objects may be used. For example, the Alpha and Merced processors use 64-bit pointer values, meaning a Python long integer will be used to hold the pointer; other platforms use 32-bit pointers and will use a Python integer.
'n' => $this->IS64BIT ? 'q' : 'l',
'N' => $this->IS64BIT ? 'Q' : 'L',
], $this->FORMATS);
$this->SIZE = [
'p' => 1,
'i' => 4,
'I' => 4,
'f' => 4,
'd' => 8,
'c' => 1,
'?' => 1,
'x' => 1,
'b' => 1,
'B' => 1,
'h' => 2,
'H' => 2,
'l' => 4,
'L' => 4,
's' => 1,
];
$this->NATIVE_SIZE = [
'p' => 1,
'P' => strlen(pack($this->NATIVE_FORMATS['P'], 2323)),
'i' => strlen(pack($this->NATIVE_FORMATS['i'], 1)),
'I' => strlen(pack($this->NATIVE_FORMATS['I'], 1)),
'f' => strlen(pack($this->NATIVE_FORMATS['f'], 2.0)),
'd' => strlen(pack($this->NATIVE_FORMATS['d'], 2.0)),
'c' => strlen(pack($this->NATIVE_FORMATS['c'], 'a')),
'?' => strlen(pack($this->NATIVE_FORMATS['?'], false)),
'x' => strlen(pack($this->NATIVE_FORMATS['x'])),
'b' => strlen(pack($this->NATIVE_FORMATS['b'], 'c')),
'B' => strlen(pack($this->NATIVE_FORMATS['B'], 'c')),
'h' => strlen(pack($this->NATIVE_FORMATS['h'], -700)),
'H' => strlen(pack($this->NATIVE_FORMATS['H'], 700)),
'l' => strlen(pack($this->NATIVE_FORMATS['l'], -70000000)),
'L' => strlen(pack($this->NATIVE_FORMATS['L'], 70000000)),
's' => strlen(pack($this->NATIVE_FORMATS['s'], 'c')),
'n' => strlen(pack($this->NATIVE_FORMATS['n'], 1)),
'N' => strlen(pack($this->NATIVE_FORMATS['N'], 1)),
];
$this->TYPE = [
'p' => 'string',
'i' => 'int',
'I' => 'int',
'f' => 'float',
'd' => 'float',
'c' => 'string',
'?' => 'bool',
'x' => 'unset',
'b' => 'int',
'B' => 'int',
'h' => 'int',
'H' => 'int',
'l' => 'int',
'L' => 'int',
's' => 'string',
];
$this->NATIVE_TYPE = array_merge([
'P' => 'int', // integer or long integer, depending on the size needed to hold a pointer when it has been cast to an integer type. A NULL pointer will always be returned as the Python integer 0. When packing pointer-sized values, Python integer or long integer objects may be used. For example, the Alpha and Merced processors use 64-bit pointer values, meaning a Python long integer will be used to hold the pointer; other platforms use 32-bit pointers and will use a Python integer.
'n' => 'int',
'N' => 'int',
], $this->TYPE);
if ($this->IS64BIT) {
$this->FORMATS['q'] = 'q';
$this->FORMATS['Q'] = 'Q';
$this->NATIVE_FORMATS['q'] = 'q';
$this->NATIVE_FORMATS['Q'] = 'Q';
$this->SIZE['q'] = 8;
$this->SIZE['Q'] = 8;
$this->NATIVE_SIZE['q'] = strlen(pack($this->NATIVE_FORMATS['q'], -70000000));
$this->NATIVE_SIZE['Q'] = strlen(pack($this->NATIVE_FORMATS['Q'], 70000000));
$this->TYPE['q'] = 'int';
$this->TYPE['Q'] = 'int';
$this->NATIVE_TYPE['q'] = 'int';
$this->NATIVE_TYPE['Q'] = 'int';
}
$this->MODIFIERS = [
'<' => ['BIG_ENDIAN' => false, 'SIZE' => $this->SIZE, 'FORMATS' => $this->FORMATS, 'TYPE' => $this->TYPE],
'>' => ['BIG_ENDIAN' => true, 'SIZE' => $this->SIZE, 'FORMATS' => $this->FORMATS, 'TYPE' => $this->TYPE],
'!' => ['BIG_ENDIAN' => true, 'SIZE' => $this->SIZE, 'FORMATS' => $this->FORMATS, 'TYPE' => $this->TYPE],
'=' => ['BIG_ENDIAN' => $this->BIG_ENDIAN, 'SIZE' => $this->SIZE, 'FORMATS' => $this->FORMATS, 'TYPE' => $this->TYPE],
'@' => ['BIG_ENDIAN' => $this->BIG_ENDIAN, 'SIZE' => $this->NATIVE_SIZE, 'FORMATS' => $this->NATIVE_FORMATS, 'TYPE' => $this->NATIVE_TYPE],
];
}
/**
* ExceptionErrorHandler.
*
* Error handler for pack and unpack
*/
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 StructException($errstr, $errno);
}
/**
* pack.
*
* Packs data into bytes
*
* @param $format Format string
* @param $format Format string
* @param ...$data Parameters to encode
*
* @return Encoded data
*/
public function pack($format, ...$data)
public static function pack($format, ...$data)
{
if (!(isset($this) && get_class($this) == __CLASS__)) {
$struct = new \danog\PHP\Struct();
$struct = new \danog\PHP\StructClass($format);
return $struct->pack($format, ...$data);
}
$result = null; // Data to return
$packcommand = $this->parseformat($format, $this->array_each_strlen($data)); // Get pack parameters
set_error_handler([$this, 'ExceptionErrorHandler']);
foreach ($packcommand as $key => $command) {
try {
switch ($command['modifiers']['TYPE']) {
case 'int':
if (!is_int($data[$command['datakey']])) {
throw new StructException('Required argument is not an integer.');
}
break;
case 'float':
if (!is_float($data[$command['datakey']])) {
throw new StructException('Required argument is not a float.');
}
break;
case 'string':
if (!is_string($data[$command['datakey']])) {
throw new StructException('Required argument is not a string.');
}
break;
case 'bool':
$data[$command['datakey']] = (bool) $data[$command['datakey']];
break;
default:
break;
}
switch ($command['format']) {
case 'x':
$curresult = pack($command['phpformat'].$command['count']); // Pack current char
break;
case 'p':
$tempstring = pack('a'.($command['count'] - 1), $data[$command['datakey']]);
$curresult = pack('v', ($command['count'] - 1 > 255) ? 255 : $command['count'] - 1)[0].$tempstring;
break;
default:
$curresult = pack($command['phpformat'].$command['count'], $data[$command['datakey']]); // Pack current char
break;
}
} catch (StructException $e) {
throw new StructException('An error occurred while packing data at offset '.$key.' ('.$e->getMessage().').');
}
if ($this->BIG_ENDIAN != $command['modifiers']['BIG_ENDIAN'] && !in_array($command['format'], ['x', 'c', 'b', 'B', '?', 's', 'p'])) {
$curresult = strrev($curresult);
} // Reverse if wrong endianness
if (strlen($curresult) > $command['modifiers']['SIZE'] * $command['count']) {
if ($command['modifiers']['BIG_ENDIAN']) {
$curresult = strrev($curresult);
}
$remains = array_slice(str_split($curresult), $command['modifiers']['SIZE'], strlen($curresult) - $command['modifiers']['SIZE']);
foreach ($remains as $rem) {
if ($rem != '') {
throw new StructException('Error while trimming result at offset '.$key.' (format char '.$command['format']."): data to trim isn't empty.");
}
}
$curresult = implode('', substr($curresult, 0, $command['modifiers']['SIZE']));
if ($command['modifiers']['BIG_ENDIAN']) {
$curresult = strrev($curresult);
}
}
$result .= $curresult;
}
restore_error_handler();
if (strlen($result) != $this->calcsize($format)) {
throw new StructException('Length of generated data ('.strlen($result).') is different from length calculated using format string ('.$this->calcsize($format).').');
}
return $result;
return $struct->pack(...$data);
}
/**
@ -246,75 +42,11 @@ class Struct
*
* @return Decoded data
*/
public function unpack($format, $data)
public static function unpack($format, $data)
{
if (!(isset($this) && get_class($this) == __CLASS__)) {
$struct = new \danog\PHP\Struct();
$struct = new \danog\PHP\StructClass($format);
return $struct->unpack($format, $data);
}
if (strlen($data) != $this->calcsize($format)) {
throw new StructException('Length of given data ('.strlen($data).') is different from length calculated using format string ('.$this->calcsize($format).').');
}
$dataarray = $this->data2array($format, $data);
if ($this->array_total_strlen($dataarray) != $this->calcsize($format)) {
throw new StructException('Length of given data array ('.$this->array_total_strlen($dataarray).') is different from length calculated using format string ('.$this->calcsize($format).').');
}
$result = []; // Data to return
$packcommand = $this->parseformat($format, $this->array_each_strlen($dataarray), true); // Get unpack parameters
set_error_handler([$this, 'ExceptionErrorHandler']);
$arraycount = 0;
foreach ($packcommand as $key => $command) {
if (isset($command['modifiers']['BIG_ENDIAN']) && $this->BIG_ENDIAN != $command['modifiers']['BIG_ENDIAN'] && !in_array($command['format'], ['x', 'c', 'b', 'B', '?', 's', 'p'])) {
$dataarray[$command['datakey']] = strrev($dataarray[$command['datakey']]);
} // Reverse if wrong endianness
try {
switch ($command['format']) {
case 'p':
$templength = unpack('s', $dataarray[$command['datakey']][0].pack('x'))[1];
$result[$arraycount] = implode('', unpack('a'.$templength, substr($dataarray[$command['datakey']], 1)));
break;
case '?':
if (implode('', unpack($command['phpformat'].$command['count'], $dataarray[$command['datakey']])) == 0) {
$result[$arraycount] = false;
} else {
$result[$arraycount] = true;
}
break;
default:
$result[$arraycount] = implode('', unpack($command['phpformat'].$command['count'], $dataarray[$command['datakey']])); // Unpack current char
break;
}
} catch (StructException $e) {
throw new StructException('An error occurred while unpacking data at offset '.$key.' ('.$e->getMessage().').');
}
switch ($command['modifiers']['TYPE']) {
case 'int':
$result[$arraycount] = (int) $result[$arraycount];
break;
case 'float':
$result[$arraycount] = (float) $result[$arraycount];
break;
case 'string':
$result[$arraycount] = (string) $result[$arraycount];
break;
case 'bool':
$result[$arraycount] = (bool) $result[$arraycount];
break;
case 'unset':
unset($result[$arraycount]);
$arraycount--;
break;
default:
$result[$arraycount] = (string) $result[$arraycount];
break;
}
$arraycount++;
}
restore_error_handler();
return $result;
return $struct->unpack($data);
}
/**
@ -327,217 +59,10 @@ class Struct
*
* @return int with size of the struct.
*/
public function calcsize($format)
public static function calcsize($format)
{
if (!(isset($this) && get_class($this) == __CLASS__)) {
$struct = new \danog\PHP\Struct();
$struct = new \danog\PHP\StructClass($format);
return $struct->calcsize($format);
}
$size = 0;
$modifier = $this->MODIFIERS['@'];
$count = null;
foreach (str_split($format) as $offset => $currentformatchar) {
if (isset($this->MODIFIERS[$currentformatchar])) {
$modifier = $this->MODIFIERS[$currentformatchar]; // Set the modifiers for the current format char
} elseif (is_numeric($currentformatchar) && ((int) $currentformatchar > 0 || (int) $currentformatchar <= 9)) {
$count .= $currentformatchar; // Set the count for the current format char
} elseif (isset($modifier['SIZE'][$currentformatchar])) {
if (!isset($count) || $count == null) {
$count = 1; // Set count to 1 if something's wrong.
}
$size += $count * $modifier['SIZE'][$currentformatchar];
$count = null;
} else {
throw new StructException('Unkown format or modifier supplied ('.$currentformatchar.' at offset '.$offset.').');
}
}
return $size;
}
/**
* parseformat.
*
* Parses format string.
*
* @param $format Format string to parse
* @param $arraycount Array containing the number of chars contained in each element of the array to pack
*
* @throws StructException if format string is too long or there aren't enough parameters or if an unkown format or modifier is supplied.
*
* @return array with format and modifiers for each object to encode/decode
*/
public function parseformat($format, $arraycount, $unpack = false)
{
$datarraycount = 0; // Current element of the array to pack/unpack
$formatcharcount = 0; // Current element to pack/unpack (sometimes there isn't a correspondant element in the array)
$modifier = $this->MODIFIERS['@'];
$result = []; // Array with the results
$count = null;
$loopcount = 0;
foreach (str_split($format) as $offset => $currentformatchar) { // Current format char
if (!isset($result[$formatcharcount]) || !is_array($result[$formatcharcount])) {
$result[$formatcharcount] = []; // Create array for current element
}
if (isset($this->MODIFIERS[$currentformatchar])) { // If current format char is a modifier
$modifier = $this->MODIFIERS[$currentformatchar]; // Set the modifiers for the current format char
} elseif (is_numeric($currentformatchar) && ((int) $currentformatchar >= 0 || (int) $currentformatchar <= 9)) {
$count .= (int) $currentformatchar; // Set the count for the current format char
} elseif (isset($modifier['FORMATS'][$currentformatchar])) {
if (!isset($count) || $count == null) {
$count = 1; // Set count to 1 by default.
}
$count = (int) $count;
if ($currentformatchar == 's' || $currentformatchar == 'p') {
$loopcount = 1;
} else {
$loopcount = $count;
$count = 1;
}
for ($x = 0; $x < $loopcount; $x++) {
$result[$formatcharcount]['format'] = $currentformatchar; // Set format
$result[$formatcharcount]['phpformat'] = $modifier['FORMATS'][$currentformatchar]; // Set format
$result[$formatcharcount]['count'] = $count;
$result[$formatcharcount]['modifiers'] = ['BIG_ENDIAN' => $modifier['BIG_ENDIAN'], 'SIZE' => $modifier['SIZE'][$currentformatchar], 'TYPE' => $modifier['TYPE'][$currentformatchar]];
if ($unpack) {
if ($arraycount[$datarraycount] != $result[$formatcharcount]['count'] * $result[$formatcharcount]['modifiers']['SIZE']) {
throw new StructException('Length for format string '.$result[$formatcharcount]['format'].' at offset '.$offset.' ('.$result[$formatcharcount]['count'] * $result[$formatcharcount]['modifiers']['SIZE'].") isn't equal to the length of associated parameter (".$arraycount[$datarraycount].').');
}
$result[$formatcharcount]['datakey'] = $datarraycount;
$datarraycount++;
} else {
if ($currentformatchar != 'x') {
$result[$formatcharcount]['datakey'] = $datarraycount;
$datarraycount++;
}
}
if ($datarraycount > count($arraycount)) {
throw new StructException('Format string too long or not enough parameters at offset '.$offset.' ('.$currentformatchar.').');
}
$formatcharcount++; // Increase element count
}
$count = null;
} else {
throw new StructException('Unkown format or modifier supplied at offset '.$offset.' ('.$currentformatchar.').');
}
}
return $result;
}
public function data2array($format, $data)
{
$dataarray = [];
$dataarraykey = 0;
$datakey = 0;
$count = null;
$loopcount = 0;
$modifier = $this->MODIFIERS['@'];
foreach (str_split($format) as $offset => $currentformatchar) {
if (isset($this->MODIFIERS[$currentformatchar])) {
$modifier = $this->MODIFIERS[$currentformatchar]; // Set the modifiers for the current format char
} elseif (is_numeric($currentformatchar) && ((int) $currentformatchar > 0 || (int) $currentformatchar <= 9)) {
$count .= $currentformatchar; // Set the count for the current format char
} elseif (isset($modifier['SIZE'][$currentformatchar])) {
if (!isset($count) || $count == null) {
$count = 1; // Set count to 1 if something's wrong.
}
$count = (int) $count;
if ($currentformatchar == 's' || $currentformatchar == 'p') {
$loopcount = 1;
} else {
$loopcount = $count;
$count = 1;
}
for ($x = 0; $x < $loopcount; $x++) {
if (!isset($dataarray[$dataarraykey])) {
$dataarray[$dataarraykey] = null;
}
for ($a = 0; $a < $count * $modifier['SIZE'][$currentformatchar]; $a++) {
$dataarray[$dataarraykey] .= $data[$datakey];
$datakey++;
}
$dataarraykey++;
}
$count = null;
} else {
throw new StructException('Unkown format or modifier supplied ('.$currentformatchar.' at offset '.$offset.').');
}
}
return $dataarray;
}
/**
* array_each_strlen.
*
* Get length of each array element.
*
* @param $array Array to parse
*
* @return array with lengths
**/
public function array_each_strlen($array)
{
foreach ($array as &$value) {
$value = $this->count($value);
}
return $array;
}
/**
* array_total_strlen.
*
* Get total length of every array element.
*
* @param $array Array to parse
*
* @return int with the total length
**/
public function array_total_strlen($array)
{
$count = 0;
foreach ($array as $value) {
$count += $this->count($value);
}
return $count;
}
/**
* count.
*
* Get the length of a string or of an array
*
* @param $input String or array to parse
*
* @return int with the length
**/
public function count($input)
{
if (is_array($input)) {
return count($input);
}
return strlen($input);
}
}
/* Just an exception class */
class StructException 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);
return $struct->size;
}
}

View File

@ -0,0 +1,92 @@
<?php
namespace danog\PHP;
/**
* PHPStruct
* PHP implementation of Python's struct module.
* This library was created to help me develop a [client for the mtproto protocol](https://github.com/danog/MadelineProto).
* The functions and the formats are exactly the ones used in python's struct (https://docs.python.org/3/library/struct.html)
* For now custom byte size may not work properly on certain machines for the i, I, f and d formats.
*
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT license
*/
// Struct class (for dynamic access)
class StructClass
{
public $struct = null; // Will store an instance of the StructTools class
public $format = null; // Will contain the format
public $size = null; // Will contain the size
/**
* Constructor.
*
* Stores instance of the StructTools class and optional format/size
*/
public function __construct($format = null)
{
$this->struct = new \danog\PHP\StructTools();
if ($format !== null) {
$this->format = $format;
$this->size = $this->struct->calcsize($format);
}
}
/**
* pack.
*
* Packs data into bytes
*
* @param ...$data Parameters to encode (may contain format string)
*
* @return Encoded data
*/
public function pack(...$data)
{
if ($this->format === null) {
$format = array_shift($data);
} else {
$format = $this->format;
}
return $this->struct->pack($format, ...$data);
}
/**
* unpack.
*
* Unpacks data into an array
*
* @param $format_maybe_data Format string (may be data if class is istantiated with format string)
* @param $data Data to decode
*
* @return Decoded data
*/
public function unpack($format_maybe_data, $data = null)
{
if ($this->format === null) {
$format = $format_maybe_data;
} else {
$format = $this->format;
$data = $format_maybe_data;
}
return $this->struct->unpack($format, $data);
}
/**
* calcsize.
*
* Return the size of the struct (and hence of the string) corresponding to the given format.
*
* @param $format Format string
*
* @return int with size of the struct.
*/
public function calcsize($format = null)
{
return ($this->format !== null && $this->size !== null) ? $this->size : $this->struct->calcsize($format);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace danog\PHP;
/**
* PHPStruct
* PHP implementation of Python's struct module.
* This library was created to help me develop a [client for the mtproto protocol](https://github.com/danog/MadelineProto).
* The functions and the formats are exactly the ones used in python's struct (https://docs.python.org/3/library/struct.html)
* For now custom byte size may not work properly on certain machines for the f and d formats.
*
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT license
*/
/* Just an exception class */
class StructException 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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
#!/usr/bin/env php
<?php
require 'lib/danog/PHP/StructTools.php';
require 'lib/danog/PHP/StructClass.php';
require 'lib/danog/PHP/StructException.php';
require 'lib/danog/PHP/Struct.php';
echo \danog\PHP\Struct::pack('2cxbxBx?xhxHxixIxlxLxqxQxfxdx2xsx5pP',
'n', 'v', -127, 100, true, 333, 444, 232423, 234342, 999999999999, 999999999999, -88888888888888,
88888888888877, 2.2343,
3.03424, 'df', 'asdfghjkl', 1283912);die;

View File

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import subprocess
from struct import unpack
a = subprocess.Popen(["php", "tests/danog/PHP/php2py.php"], stdout=subprocess.PIPE).communicate()[0]
print(unpack('2cxbxBx?xhxHxixIxlxLxqxQxfxdx2xsx5pP', a))

View File

@ -0,0 +1,8 @@
#!/usr/bin/env php
<?php
require 'lib/danog/PHP/StructTools.php';
require 'lib/danog/PHP/StructClass.php';
require 'lib/danog/PHP/StructException.php';
require 'lib/danog/PHP/Struct.php';
var_dump(\danog\PHP\Struct::unpack('2cxbxBx?xhxHxixIxlxLxqxQxfxdx2xsx5pP', shell_exec('tests/danog/PHP/py2php.py')));

View File

@ -0,0 +1,4 @@
#!/usr/bin/env python3
from struct import pack
import sys
sys.stdout.buffer.write(bytes(pack('2cxbxBx?xhxHxixIxlxLxqxQxfxdx2xsx5pP', b'n', b'v', -127, 100, True, 333, 444, 232423, 234342, 999999999999, 999999999999, -88888888888888,88888888888877, 2.2343, 3.03424, b'df', b'asdfghjkl', 1283912)))