Commit 807cc462 by duwenjun

rabbitmq

parent e57c2b3c
Showing with 3471 additions and 640 deletions
......@@ -10,7 +10,6 @@
"guzzlehttp/guzzle": "^6.0",
"predis/predis": "^1.1",
"maatwebsite/excel": "~2.0.0",
"vladimir-yuldashev/laravel-queue-rabbitmq": "5.2",
"artisaninweb/laravel-soap": "0.2.*",
"hprose/hprose": "^2.0",
"barryvdh/laravel-dompdf": "^0.8.2",
......@@ -25,9 +24,6 @@
"symfony/dom-crawler": "2.8.*|3.0.*"
},
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
}
......
......@@ -157,10 +157,7 @@ return [
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
VladimirYuldashev\LaravelQueueRabbitMQ\LaravelQueueRabbitMQServiceProvider::class,
Artisaninweb\SoapWrapper\ServiceProvider::class,
Barryvdh\DomPDF\ServiceProvider::class,
Jenssegers\Mongodb\MongodbServiceProvider::class,
......
......@@ -60,7 +60,7 @@ class ClassLoader
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
......
......@@ -9,11 +9,12 @@ return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'1d1b89d124cc9cb8219922c9d5569199' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'e7223560d890eab89cda23685e711e2c' => $vendorDir . '/psy/psysh/src/Psy/functions.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'd7f4f7522f962c095f835c50e6136087' => $vendorDir . '/hprose/hprose/src/init.php',
......
......@@ -6,7 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'VladimirYuldashev\\LaravelQueueRabbitMQ' => array($vendorDir . '/vladimir-yuldashev/laravel-queue-rabbitmq/src'),
'Sabberworm\\CSS' => array($vendorDir . '/sabberworm/php-css-parser/lib'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
'PHPExcel' => array($vendorDir . '/phpoffice/phpexcel/Classes'),
......
......@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
'XdgBaseDir\\' => array($vendorDir . '/dnoegel/php-xdg-base-dir/src'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
......@@ -34,6 +35,7 @@ return array(
'Predis\\' => array($vendorDir . '/predis/predis/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'PhpAmqpLib\\' => array($vendorDir . '/php-amqplib/php-amqplib/PhpAmqpLib'),
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'),
......
.idea/
vendor/
\ No newline at end of file
language: php
sudo: false
matrix:
fast_finish: true
include:
- php: "7.1"
- php: "7.2"
- php: "7.3"
- php: "7.4"
- php: "8.0"
- php: "nightly"
allow_failures:
- php: "nightly"
- php: "7.4"
- php: "8.0"
install:
- composer self-update
- composer update
script:
- vendor/bin/phpunit
- vendor/bin/psalm
The MIT License (MIT)
Copyright (c) 2016 - 2020 Paragon Initiative Enterprises
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
This library was based on the work of Steve "Sc00bz" Thomas.
------------------------------------------------------------------------------
The MIT License (MIT)
Copyright (c) 2014 Steve Thomas
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Constant-Time Encoding
[![Build Status](https://travis-ci.org/paragonie/constant_time_encoding.svg?branch=master)](https://travis-ci.org/paragonie/constant_time_encoding)
[![Latest Stable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/stable)](https://packagist.org/packages/paragonie/constant_time_encoding)
[![Latest Unstable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/unstable)](https://packagist.org/packages/paragonie/constant_time_encoding)
[![License](https://poser.pugx.org/paragonie/constant_time_encoding/license)](https://packagist.org/packages/paragonie/constant_time_encoding)
[![Downloads](https://img.shields.io/packagist/dt/paragonie/constant_time_encoding.svg)](https://packagist.org/packages/paragonie/constant_time_encoding)
Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding),
this library aims to offer character encoding functions that do not leak
information about what you are encoding/decoding via processor cache
misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html).
Our fork offers the following enchancements:
* `mbstring.func_overload` resistance
* Unit tests
* Composer- and Packagist-ready
* Base16 encoding
* Base32 encoding
* Uses `pack()` and `unpack()` instead of `chr()` and `ord()`
## PHP Version Requirements
Version 2 of this library should work on **PHP 7** or newer. For PHP 5
support, see [the v1.x branch](https://github.com/paragonie/constant_time_encoding/tree/v1.x).
If you are adding this as a dependency to a project intended to work on both PHP 5 and PHP 7, please set the required version to `^1|^2` instead of just `^1` or `^2`.
## How to Install
```sh
composer require paragonie/constant_time_encoding
```
## How to Use
```php
use \ParagonIE\ConstantTime\Encoding;
// possibly (if applicable):
// require 'vendor/autoload.php';
$data = random_bytes(32);
echo Encoding::base64Encode($data), "\n";
echo Encoding::base32EncodeUpper($data), "\n";
echo Encoding::base32Encode($data), "\n";
echo Encoding::hexEncode($data), "\n";
echo Encoding::hexEncodeUpper($data), "\n";
```
Example output:
```
1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ====
2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1
D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1
```
If you only need a particular variant, you can just reference the
required class like so:
```php
use \ParagonIE\ConstantTime\Base64;
use \ParagonIE\ConstantTime\Base32;
$data = random_bytes(32);
echo Base64::encode($data), "\n";
echo Base32::encode($data), "\n";
```
Example output:
```
1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
```
## Support Contracts
If your company uses this library in their products or services, you may be
interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).
{
"name": "paragonie/constant_time_encoding",
"description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
"keywords": [
"base64",
"encoding",
"rfc4648",
"base32",
"base16",
"hex",
"bin2hex",
"hex2bin",
"base64_encode",
"base64_decode",
"base32_encode",
"base32_decode"
],
"license": "MIT",
"type": "library",
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com",
"role": "Maintainer"
},
{
"name": "Steve 'Sc00bz' Thomas",
"email": "steve@tobtu.com",
"homepage": "https://www.tobtu.com",
"role": "Original Developer"
}
],
"support": {
"issues": "https://github.com/paragonie/constant_time_encoding/issues",
"email": "info@paragonie.com",
"source": "https://github.com/paragonie/constant_time_encoding"
},
"require": {
"php": "^7|^8"
},
"require-dev": {
"phpunit/phpunit": "^6|^7|^8|^9",
"vimeo/psalm": "^1|^2|^3|^4"
},
"autoload": {
"psr-4": {
"ParagonIE\\ConstantTime\\": "src/"
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="true" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnError="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Constant Time Encoding Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
</phpunit>
<?xml version="1.0"?>
<psalm
useDocblockTypes="true"
totallyTyped="true"
>
<projectFiles>
<directory name="src" />
</projectFiles>
</psalm>
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Base32Hex
* [0-9][A-V]
*
* @package ParagonIE\ConstantTime
*/
abstract class Base32Hex extends Base32
{
/**
* Uses bitwise operators instead of table-lookups to turn 5-bit integers
* into 8-bit integers.
*
* @param int $src
* @return int
*/
protected static function decode5Bits(int $src): int
{
$ret = -1;
// if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
// if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
$ret += (((0x60 - $src) & ($src - 0x77)) >> 8) & ($src - 86);
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 5-bit integers
* into 8-bit integers.
*
* @param int $src
* @return int
*/
protected static function decode5BitsUpper(int $src): int
{
$ret = -1;
// if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
// if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
$ret += (((0x40 - $src) & ($src - 0x57)) >> 8) & ($src - 54);
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 5-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode5Bits(int $src): string
{
$src += 0x30;
// if ($src > 0x39) $src += 0x61 - 0x3a; // 39
$src += ((0x39 - $src) >> 8) & 39;
return \pack('C', $src);
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 5-bit integers.
*
* Uppercase variant.
*
* @param int $src
* @return string
*/
protected static function encode5BitsUpper(int $src): string
{
$src += 0x30;
// if ($src > 0x39) $src += 0x41 - 0x3a; // 7
$src += ((0x39 - $src) >> 8) & 7;
return \pack('C', $src);
}
}
\ No newline at end of file
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Base64
* [A-Z][a-z][0-9]+/
*
* @package ParagonIE\ConstantTime
*/
abstract class Base64 implements EncoderInterface
{
/**
* Encode into Base64
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws \TypeError
*/
public static function encode(string $src): string
{
return static::doEncode($src, true);
}
/**
* Encode into Base64, no = padding
*
* Base64 character set "[A-Z][a-z][0-9]+/"
*
* @param string $src
* @return string
* @throws \TypeError
*/
public static function encodeUnpadded(string $src): string
{
return static::doEncode($src, false);
}
/**
* @param string $src
* @param bool $pad Include = padding?
* @return string
* @throws \TypeError
*/
protected static function doEncode(string $src, bool $pad = true): string
{
$dest = '';
$srcLen = Binary::safeStrlen($src);
// Main loop (no padding):
for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
/** @var array<int, int> $chunk */
$chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
$b0 = $chunk[1];
$b1 = $chunk[2];
$b2 = $chunk[3];
$dest .=
static::encode6Bits( $b0 >> 2 ) .
static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
static::encode6Bits( $b2 & 63);
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
$b0 = $chunk[1];
if ($i + 1 < $srcLen) {
$b1 = $chunk[2];
$dest .=
static::encode6Bits($b0 >> 2) .
static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
static::encode6Bits(($b1 << 2) & 63);
if ($pad) {
$dest .= '=';
}
} else {
$dest .=
static::encode6Bits( $b0 >> 2) .
static::encode6Bits(($b0 << 4) & 63);
if ($pad) {
$dest .= '==';
}
}
}
return $dest;
}
/**
* decode from base64 into binary
*
* Base64 character set "./[A-Z][a-z][0-9]"
*
* @param string $encodedString
* @param bool $strictPadding
* @return string
* @throws \RangeException
* @throws \TypeError
* @psalm-suppress RedundantCondition
*/
public static function decode(string $encodedString, bool $strictPadding = false): string
{
// Remove padding
$srcLen = Binary::safeStrlen($encodedString);
if ($srcLen === 0) {
return '';
}
if ($strictPadding) {
if (($srcLen & 3) === 0) {
if ($encodedString[$srcLen - 1] === '=') {
$srcLen--;
if ($encodedString[$srcLen - 1] === '=') {
$srcLen--;
}
}
}
if (($srcLen & 3) === 1) {
throw new \RangeException(
'Incorrect padding'
);
}
if ($encodedString[$srcLen - 1] === '=') {
throw new \RangeException(
'Incorrect padding'
);
}
} else {
$encodedString = \rtrim($encodedString, '=');
$srcLen = Binary::safeStrlen($encodedString);
}
$err = 0;
$dest = '';
// Main loop (no padding):
for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
/** @var array<int, int> $chunk */
$chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, 4));
$c0 = static::decode6Bits($chunk[1]);
$c1 = static::decode6Bits($chunk[2]);
$c2 = static::decode6Bits($chunk[3]);
$c3 = static::decode6Bits($chunk[4]);
$dest .= \pack(
'CCC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff),
((($c2 << 6) | $c3 ) & 0xff)
);
$err |= ($c0 | $c1 | $c2 | $c3) >> 8;
}
// The last chunk, which may have padding:
if ($i < $srcLen) {
/** @var array<int, int> $chunk */
$chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, $srcLen - $i));
$c0 = static::decode6Bits($chunk[1]);
if ($i + 2 < $srcLen) {
$c1 = static::decode6Bits($chunk[2]);
$c2 = static::decode6Bits($chunk[3]);
$dest .= \pack(
'CC',
((($c0 << 2) | ($c1 >> 4)) & 0xff),
((($c1 << 4) | ($c2 >> 2)) & 0xff)
);
$err |= ($c0 | $c1 | $c2) >> 8;
} elseif ($i + 1 < $srcLen) {
$c1 = static::decode6Bits($chunk[2]);
$dest .= \pack(
'C',
((($c0 << 2) | ($c1 >> 4)) & 0xff)
);
$err |= ($c0 | $c1) >> 8;
} elseif ($i < $srcLen && $strictPadding) {
$err |= 1;
}
}
/** @var bool $check */
$check = ($err === 0);
if (!$check) {
throw new \RangeException(
'Base64::decode() only expects characters in the correct base64 alphabet'
);
}
return $dest;
}
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* [A-Z] [a-z] [0-9] + /
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
*
* @param int $src
* @return int
*/
protected static function decode6Bits(int $src): int
{
$ret = -1;
// if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
// if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
// if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
// if ($src == 0x2b) $ret += 62 + 1;
$ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
// if ($src == 0x2f) ret += 63 + 1;
$ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode6Bits(int $src): string
{
$diff = 0x41;
// if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
$diff += ((25 - $src) >> 8) & 6;
// if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
$diff -= ((51 - $src) >> 8) & 75;
// if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
$diff -= ((61 - $src) >> 8) & 15;
// if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
$diff += ((62 - $src) >> 8) & 3;
return \pack('C', $src + $diff);
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Base64DotSlash
* ./[A-Z][a-z][0-9]
*
* @package ParagonIE\ConstantTime
*/
abstract class Base64DotSlash extends Base64
{
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* ./ [A-Z] [a-z] [0-9]
* 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
*
* @param int $src
* @return int
*/
protected static function decode6Bits(int $src): int
{
$ret = -1;
// if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
$ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45);
// if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62);
// if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68);
// if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7);
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode6Bits(int $src): string
{
$src += 0x2e;
// if ($src > 0x2f) $src += 0x41 - 0x30; // 17
$src += ((0x2f - $src) >> 8) & 17;
// if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
$src += ((0x5a - $src) >> 8) & 6;
// if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
$src -= ((0x7a - $src) >> 8) & 75;
return \pack('C', $src);
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Base64DotSlashOrdered
* ./[0-9][A-Z][a-z]
*
* @package ParagonIE\ConstantTime
*/
abstract class Base64DotSlashOrdered extends Base64
{
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* [.-9] [A-Z] [a-z]
* 0x2e-0x39, 0x41-0x5a, 0x61-0x7a
*
* @param int $src
* @return int
*/
protected static function decode6Bits(int $src): int
{
$ret = -1;
// if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
$ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45);
// if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52);
// if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58);
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode6Bits(int $src): string
{
$src += 0x2e;
// if ($src > 0x39) $src += 0x41 - 0x3a; // 7
$src += ((0x39 - $src) >> 8) & 7;
// if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
$src += ((0x5a - $src) >> 8) & 6;
return \pack('C', $src);
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Base64UrlSafe
* [A-Z][a-z][0-9]\-_
*
* @package ParagonIE\ConstantTime
*/
abstract class Base64UrlSafe extends Base64
{
/**
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
* into 8-bit integers.
*
* Base64 character set:
* [A-Z] [a-z] [0-9] - _
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2d, 0x5f
*
* @param int $src
* @return int
*/
protected static function decode6Bits(int $src): int
{
$ret = -1;
// if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
// if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
// if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
// if ($src == 0x2c) $ret += 62 + 1;
$ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;
// if ($src == 0x5f) ret += 63 + 1;
$ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;
return $ret;
}
/**
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
* into 6-bit integers.
*
* @param int $src
* @return string
*/
protected static function encode6Bits(int $src): string
{
$diff = 0x41;
// if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
$diff += ((25 - $src) >> 8) & 6;
// if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
$diff -= ((51 - $src) >> 8) & 75;
// if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
$diff -= ((61 - $src) >> 8) & 13;
// if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
$diff += ((62 - $src) >> 8) & 49;
return \pack('C', $src + $diff);
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Binary
*
* Binary string operators that don't choke on
* mbstring.func_overload
*
* @package ParagonIE\ConstantTime
*/
abstract class Binary
{
/**
* Safe string length
*
* @ref mbstring.func_overload
*
* @param string $str
* @return int
*/
public static function safeStrlen(string $str): int
{
if (\function_exists('mb_strlen')) {
return (int) \mb_strlen($str, '8bit');
} else {
return \strlen($str);
}
}
/**
* Safe substring
*
* @ref mbstring.func_overload
*
* @staticvar boolean $exists
* @param string $str
* @param int $start
* @param int $length
* @return string
* @throws \TypeError
*/
public static function safeSubstr(
string $str,
int $start = 0,
$length = null
): string {
if ($length === 0) {
return '';
}
if (\function_exists('mb_substr')) {
return \mb_substr($str, $start, $length, '8bit');
}
// Unlike mb_substr(), substr() doesn't accept NULL for length
if ($length !== null) {
return \substr($str, $start, $length);
} else {
return \substr($str, $start);
}
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Interface EncoderInterface
* @package ParagonIE\ConstantTime
*/
interface EncoderInterface
{
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks
*
* @param string $binString (raw binary)
* @return string
*/
public static function encode(string $binString): string;
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks
*
* @param string $encodedString
* @param bool $strictPadding Error on invalid padding
* @return string (raw binary)
*/
public static function decode(string $encodedString, bool $strictPadding = false): string;
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Encoding
* @package ParagonIE\ConstantTime
*/
abstract class Encoding
{
/**
* RFC 4648 Base32 encoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32Encode(string $str): string
{
return Base32::encode($str);
}
/**
* RFC 4648 Base32 encoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32EncodeUpper(string $str): string
{
return Base32::encodeUpper($str);
}
/**
* RFC 4648 Base32 decoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32Decode(string $str): string
{
return Base32::decode($str);
}
/**
* RFC 4648 Base32 decoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32DecodeUpper(string $str): string
{
return Base32::decodeUpper($str);
}
/**
* RFC 4648 Base32 encoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32HexEncode(string $str): string
{
return Base32Hex::encode($str);
}
/**
* RFC 4648 Base32Hex encoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32HexEncodeUpper(string $str): string
{
return Base32Hex::encodeUpper($str);
}
/**
* RFC 4648 Base32Hex decoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32HexDecode(string $str): string
{
return Base32Hex::decode($str);
}
/**
* RFC 4648 Base32Hex decoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32HexDecodeUpper(string $str): string
{
return Base32Hex::decodeUpper($str);
}
/**
* RFC 4648 Base64 encoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64Encode(string $str): string
{
return Base64::encode($str);
}
/**
* RFC 4648 Base64 decoding
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64Decode(string $str): string
{
return Base64::decode($str);
}
/**
* Encode into Base64
*
* Base64 character set "./[A-Z][a-z][0-9]"
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64EncodeDotSlash(string $str): string
{
return Base64DotSlash::encode($str);
}
/**
* Decode from base64 to raw binary
*
* Base64 character set "./[A-Z][a-z][0-9]"
*
* @param string $str
* @return string
* @throws \RangeException
* @throws \TypeError
*/
public static function base64DecodeDotSlash(string $str): string
{
return Base64DotSlash::decode($str);
}
/**
* Encode into Base64
*
* Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64EncodeDotSlashOrdered(string $str): string
{
return Base64DotSlashOrdered::encode($str);
}
/**
* Decode from base64 to raw binary
*
* Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
*
* @param string $str
* @return string
* @throws \RangeException
* @throws \TypeError
*/
public static function base64DecodeDotSlashOrdered(string $str): string
{
return Base64DotSlashOrdered::decode($str);
}
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks
*
* @param string $bin_string (raw binary)
* @return string
* @throws \TypeError
*/
public static function hexEncode(string $bin_string): string
{
return Hex::encode($bin_string);
}
/**
* Convert a hexadecimal string into a binary string without cache-timing
* leaks
*
* @param string $hex_string
* @return string (raw binary)
* @throws \RangeException
*/
public static function hexDecode(string $hex_string): string
{
return Hex::decode($hex_string);
}
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks
*
* @param string $bin_string (raw binary)
* @return string
* @throws \TypeError
*/
public static function hexEncodeUpper(string $bin_string): string
{
return Hex::encodeUpper($bin_string);
}
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks
*
* @param string $bin_string (raw binary)
* @return string
*/
public static function hexDecodeUpper(string $bin_string): string
{
return Hex::decode($bin_string);
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class Hex
* @package ParagonIE\ConstantTime
*/
abstract class Hex implements EncoderInterface
{
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks
*
* @param string $binString (raw binary)
* @return string
* @throws \TypeError
*/
public static function encode(string $binString): string
{
/** @var string $hex */
$hex = '';
$len = Binary::safeStrlen($binString);
for ($i = 0; $i < $len; ++$i) {
/** @var array<int, int> $chunk */
$chunk = \unpack('C', Binary::safeSubstr($binString, $i, 1));
/** @var int $c */
$c = $chunk[1] & 0xf;
/** @var int $b */
$b = $chunk[1] >> 4;
$hex .= pack(
'CC',
(87 + $b + ((($b - 10) >> 8) & ~38)),
(87 + $c + ((($c - 10) >> 8) & ~38))
);
}
return $hex;
}
/**
* Convert a binary string into a hexadecimal string without cache-timing
* leaks, returning uppercase letters (as per RFC 4648)
*
* @param string $binString (raw binary)
* @return string
* @throws \TypeError
*/
public static function encodeUpper(string $binString): string
{
/** @var string $hex */
$hex = '';
/** @var int $len */
$len = Binary::safeStrlen($binString);
for ($i = 0; $i < $len; ++$i) {
/** @var array<int, int> $chunk */
$chunk = \unpack('C', Binary::safeSubstr($binString, $i, 2));
/** @var int $c */
$c = $chunk[1] & 0xf;
/** @var int $b */
$b = $chunk[1] >> 4;
$hex .= pack(
'CC',
(55 + $b + ((($b - 10) >> 8) & ~6)),
(55 + $c + ((($c - 10) >> 8) & ~6))
);
}
return $hex;
}
/**
* Convert a hexadecimal string into a binary string without cache-timing
* leaks
*
* @param string $encodedString
* @param bool $strictPadding
* @return string (raw binary)
* @throws \RangeException
*/
public static function decode(string $encodedString, bool $strictPadding = false): string
{
/** @var int $hex_pos */
$hex_pos = 0;
/** @var string $bin */
$bin = '';
/** @var int $c_acc */
$c_acc = 0;
/** @var int $hex_len */
$hex_len = Binary::safeStrlen($encodedString);
/** @var int $state */
$state = 0;
if (($hex_len & 1) !== 0) {
if ($strictPadding) {
throw new \RangeException(
'Expected an even number of hexadecimal characters'
);
} else {
$encodedString = '0' . $encodedString;
++$hex_len;
}
}
/** @var array<int, int> $chunk */
$chunk = \unpack('C*', $encodedString);
while ($hex_pos < $hex_len) {
++$hex_pos;
/** @var int $c */
$c = $chunk[$hex_pos];
/** @var int $c_num */
$c_num = $c ^ 48;
/** @var int $c_num0 */
$c_num0 = ($c_num - 10) >> 8;
/** @var int $c_alpha */
$c_alpha = ($c & ~32) - 55;
/** @var int $c_alpha0 */
$c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
if (($c_num0 | $c_alpha0) === 0) {
throw new \RangeException(
'Expected hexadecimal character'
);
}
/** @var int $c_val */
$c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
if ($state === 0) {
$c_acc = $c_val * 16;
} else {
$bin .= \pack('C', $c_acc | $c_val);
}
$state ^= 1;
}
return $bin;
}
}
<?php
declare(strict_types=1);
namespace ParagonIE\ConstantTime;
/**
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Class RFC4648
*
* This class conforms strictly to the RFC
*
* @package ParagonIE\ConstantTime
*/
abstract class RFC4648
{
/**
* RFC 4648 Base64 encoding
*
* "foo" -> "Zm9v"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64Encode(string $str): string
{
return Base64::encode($str);
}
/**
* RFC 4648 Base64 decoding
*
* "Zm9v" -> "foo"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64Decode(string $str): string
{
return Base64::decode($str, true);
}
/**
* RFC 4648 Base64 (URL Safe) encoding
*
* "foo" -> "Zm9v"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64UrlSafeEncode(string $str): string
{
return Base64UrlSafe::encode($str);
}
/**
* RFC 4648 Base64 (URL Safe) decoding
*
* "Zm9v" -> "foo"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base64UrlSafeDecode(string $str): string
{
return Base64UrlSafe::decode($str, true);
}
/**
* RFC 4648 Base32 encoding
*
* "foo" -> "MZXW6==="
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32Encode(string $str): string
{
return Base32::encodeUpper($str);
}
/**
* RFC 4648 Base32 encoding
*
* "MZXW6===" -> "foo"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32Decode(string $str): string
{
return Base32::decodeUpper($str, true);
}
/**
* RFC 4648 Base32-Hex encoding
*
* "foo" -> "CPNMU==="
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32HexEncode(string $str): string
{
return Base32::encodeUpper($str);
}
/**
* RFC 4648 Base32-Hex decoding
*
* "CPNMU===" -> "foo"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base32HexDecode(string $str): string
{
return Base32::decodeUpper($str, true);
}
/**
* RFC 4648 Base16 decoding
*
* "foo" -> "666F6F"
*
* @param string $str
* @return string
* @throws \TypeError
*/
public static function base16Encode(string $str): string
{
return Hex::encodeUpper($str);
}
/**
* RFC 4648 Base16 decoding
*
* "666F6F" -> "foo"
*
* @param string $str
* @return string
*/
public static function base16Decode(string $str): string
{
return Hex::decode($str, true);
}
}
\ No newline at end of file
<?php
use \ParagonIE\ConstantTime\Base32Hex;
class Base32HexTest extends PHPUnit\Framework\TestCase
{
/**
* @covers Base32Hex::encode()
* @covers Base32Hex::decode()
* @covers Base32Hex::encodeUpper()
* @covers Base32Hex::decodeUpper()
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Base32Hex::encode($random);
$this->assertSame(
$random,
Base32Hex::decode($enc)
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$unpadded,
Base32Hex::encodeUnpadded($random)
);
$this->assertSame(
$random,
Base32Hex::decode($unpadded)
);
$enc = Base32Hex::encodeUpper($random);
$this->assertSame(
$random,
Base32Hex::decodeUpper($enc)
); $unpadded = \rtrim($enc, '=');
$this->assertSame(
$unpadded,
Base32Hex::encodeUpperUnpadded($random)
);
$this->assertSame(
$random,
Base32Hex::decodeUpper($unpadded)
);
}
}
}
}
<?php
use \ParagonIE\ConstantTime\Base32;
class Base32Test extends PHPUnit\Framework\TestCase
{
/**
* @covers Base32::encode()
* @covers Base32::decode()
* @covers Base32::encodeUpper()
* @covers Base32::decodeUpper()
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Base32::encode($random);
$this->assertSame(
$random,
Base32::decode($enc)
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$unpadded,
Base32::encodeUnpadded($random)
);
$this->assertSame(
$random,
Base32::decode($unpadded)
);
$enc = Base32::encodeUpper($random);
$this->assertSame(
$random,
Base32::decodeUpper($enc)
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$unpadded,
Base32::encodeUpperUnpadded($random)
);
$this->assertSame(
$random,
Base32::decodeUpper($unpadded)
);
}
}
}
}
<?php
use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
class Base64DotSlashOrderedTest extends PHPUnit\Framework\TestCase
{
/**
* @covers Base64DotSlashOrdered::encode()
* @covers Base64DotSlashOrdered::decode()
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Base64DotSlashOrdered::encode($random);
$this->assertSame(
$random,
Base64DotSlashOrdered::decode($enc)
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$random,
Base64DotSlashOrdered::decode($unpadded)
);
$this->assertSame(
$random,
Base64DotSlashOrdered::decode($unpadded)
);
}
}
}
}
<?php
use \ParagonIE\ConstantTime\Base64DotSlash;
class Base64DotSlashTest extends PHPUnit\Framework\TestCase
{
/**
* @covers Base64DotSlash::encode()
* @covers Base64DotSlash::decode()
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Base64DotSlash::encode($random);
$this->assertSame(
$random,
Base64DotSlash::decode($enc)
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$random,
Base64DotSlash::decode($unpadded)
);
$this->assertSame(
$random,
Base64DotSlash::decode($unpadded)
);
}
}
}
}
<?php
use \ParagonIE\ConstantTime\Base64;
class Base64Test extends PHPUnit\Framework\TestCase
{
/**
* @covers Base64::encode()
* @covers Base64::decode()
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Base64::encode($random);
$this->assertSame(
$random,
Base64::decode($enc)
);
$this->assertSame(
\base64_encode($random),
$enc
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$random,
Base64::decode($unpadded)
);
$this->assertSame(
$random,
Base64::decode($unpadded)
);
}
}
$str = 'MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBM' .
'MSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQ' .
'DDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1Oi' .
'A2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNVBAYTAlBMM' .
'RwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQRVNFTDogNjEw' .
'NjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBNBgNVBBAwRgwiQWw' .
'uIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEtMzgyIEdkeW5pYQwGUG' .
'9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMwEQYDVQQEDApQcnpld29yc' .
'2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMm5vjGqHPthJCMqKpqssSISRo' .
's0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBNZfjUl7r8dIi28bSKhNlsfycXZKY' .
'RcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+uLLcJVTHCu0w9oXLGbRlGth5eNoj03C' .
'xXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYDVR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCA' .
'TwwggE4MIIBNAYJKoRoAYb3IwEBMIIBJTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJh' .
'Y2phIHRhIGplc3Qgb8Wbd2lhZGN6ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZ' .
'pa2F0IHpvc3RhxYIgd3lkYW55IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IH' .
'pnb2RuaWUgeiB3eW1hZ2FuaWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmlje' .
'm55bSBvcmF6IHRvd2FyenlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMG' .
'CCsGAQUFBwIBFjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN' .
'6eS9wb2xpdHlrYS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2' .
'tpQGdkeW5pYS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXip' .
'N4oGS3ZYmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dh' .
'IEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt' .
'3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/MD' .
'2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9DU' .
'kxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJjcar/qWZ' .
'y9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2ZKQmi+cIHJHL' .
'ONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7zXZq/cLL0If0hX' .
'oPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGLf3kHVzgM6j3VAM7oF' .
'mMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9f/1y2XuLNhBNHMAyTqpY' .
'PX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelUMj93S';
try {
Base64::decode($str, true);
$this->fail('Strict padding not enforced');
} catch (\Exception $ex) {
$this->assertSame(
Base64::decode($str),
\base64_decode($str)
);
}
}
}
<?php
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\ConstantTime\Binary;
/**
* Class Base64UrlSafeTest
*/
class Base64UrlSafeTest extends PHPUnit\Framework\TestCase
{
/**
* @covers Base64UrlSafe::encode()
* @covers Base64UrlSafe::decode()
*
* @throws Exception
* @throws TypeError
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Base64UrlSafe::encode($random);
$this->assertSame(
$random,
Base64UrlSafe::decode($enc)
);
$this->assertSame(
\strtr(\base64_encode($random), '+/', '-_'),
$enc
);
$unpadded = \rtrim($enc, '=');
$this->assertSame(
$unpadded,
Base64UrlSafe::encodeUnpadded($random)
);
$this->assertSame(
$random,
Base64UrlSafe::decode($unpadded)
);
}
}
$random = \random_bytes(1 << 20);
$enc = Base64UrlSafe::encode($random);
$this->assertTrue(Binary::safeStrlen($enc) > 65536);
$this->assertSame(
$random,
Base64UrlSafe::decode($enc)
);
$this->assertSame(
\strtr(\base64_encode($random), '+/', '-_'),
$enc
);
}
}
<?php
use \ParagonIE\ConstantTime\Base32;
use \ParagonIE\ConstantTime\Base32Hex;
use \ParagonIE\ConstantTime\Base64;
use \ParagonIE\ConstantTime\Base64DotSlash;
use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
use \ParagonIE\ConstantTime\Base64UrlSafe;
use \ParagonIE\ConstantTime\Encoding;
use \ParagonIE\ConstantTime\Hex;
class EncodingTest extends PHPUnit\Framework\TestCase
{
public function testBase32Encode()
{
$this->assertSame(
Encoding::base32Encode("\x00"),
'aa======'
);
$this->assertSame(
Encoding::base32Encode("\x00\x00"),
'aaaa===='
);
$this->assertSame(
Encoding::base32Encode("\x00\x00\x00"),
'aaaaa==='
);
$this->assertSame(
Encoding::base32Encode("\x00\x00\x00\x00"),
'aaaaaaa='
);
$this->assertSame(
Encoding::base32Encode("\x00\x00\x00\x00\x00"),
'aaaaaaaa'
);
$this->assertSame(
Encoding::base32Encode("\x00\x00\x0F\xFF\xFF"),
'aaaa7777'
);
$this->assertSame(
Encoding::base32Encode("\xFF\xFF\xF0\x00\x00"),
'7777aaaa'
);
$this->assertSame(
Encoding::base32Encode("\xce\x73\x9c\xe7\x39"),
'zzzzzzzz'
);
$this->assertSame(
Encoding::base32Encode("\xd6\xb5\xad\x6b\x5a"),
'22222222'
);
$this->assertSame(
Base32::encodeUpper("\x00"),
'AA======'
);
$this->assertSame(
Base32::encodeUpper("\x00\x00"),
'AAAA===='
);
$this->assertSame(
Base32::encodeUpper("\x00\x00\x00"),
'AAAAA==='
);
$this->assertSame(
Base32::encodeUpper("\x00\x00\x00\x00"),
'AAAAAAA='
);
$this->assertSame(
Base32::encodeUpper("\x00\x00\x00\x00\x00"),
'AAAAAAAA'
);
$this->assertSame(
Base32::encodeUpper("\x00\x00\x0F\xFF\xFF"),
'AAAA7777'
);
$this->assertSame(
Base32::encodeUpper("\xFF\xFF\xF0\x00\x00"),
'7777AAAA'
);
$this->assertSame(
Base32::encodeUpper("\xce\x73\x9c\xe7\x39"),
'ZZZZZZZZ'
);
$this->assertSame(
Base32::encodeUpper("\xd6\xb5\xad\x6b\x5a"),
'22222222'
);
}
public function testBase32Hex()
{
$this->assertSame(
Base32Hex::encode("\x00"),
'00======'
);
$this->assertSame(
Base32Hex::encode("\x00\x00"),
'0000===='
);
$this->assertSame(
Base32Hex::encode("\x00\x00\x00"),
'00000==='
);
$this->assertSame(
Base32Hex::encode("\x00\x00\x00\x00"),
'0000000='
);
$this->assertSame(
Base32Hex::encode("\x00\x00\x00\x00\x00"),
'00000000'
);
$this->assertSame(
Base32Hex::encode("\x00\x00\x0F\xFF\xFF"),
'0000vvvv'
);
$this->assertSame(
Base32Hex::encode("\xFF\xFF\xF0\x00\x00"),
'vvvv0000'
);
}
/**
* Based on test vectors from RFC 4648
*/
public function testBase32Decode()
{
$this->assertSame(
"\x00\x00\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaaaaa======')
);
$this->assertSame(
"\x00\x00\x00\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaaaaaaa====')
);
$this->assertSame(
"\x00\x00\x00\x00\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaaaaaaaa===')
);
$this->assertSame(
"\x00\x00\x00\x00\x00\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaaaaaaaaaa=')
);
$this->assertSame(
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaaaaaaaaaaa')
);
$this->assertSame(
"\x00",
Encoding::base32Decode('aa======')
);
$this->assertSame(
"\x00\x00",
Encoding::base32Decode('aaaa====')
);
$this->assertSame(
"\x00\x00\x00",
Encoding::base32Decode('aaaaa===')
);
$this->assertSame(
"\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaa=')
);
$this->assertSame(
"\x00\x00\x00\x00\x00",
Encoding::base32Decode('aaaaaaaa')
);
$this->assertSame(
"\x00\x00\x0F\xFF\xFF",
Encoding::base32Decode('aaaa7777')
);
$this->assertSame(
"\xFF\xFF\xF0\x00\x00",
Encoding::base32Decode('7777aaaa')
);
$this->assertSame(
"\xce\x73\x9c\xe7\x39",
Encoding::base32Decode('zzzzzzzz')
);
$this->assertSame(
"\xd6\xb5\xad\x6b\x5a",
Encoding::base32Decode('22222222')
);
$this->assertSame(
'foobar',
Encoding::base32Decode('mzxw6ytboi======')
);
$rand = random_bytes(9);
$enc = Encoding::base32Encode($rand);
$this->assertSame(
Encoding::base32Encode($rand),
Encoding::base32Encode(Encoding::base32Decode($enc))
);
$this->assertSame(
$rand,
Encoding::base32Decode($enc)
);
}
/**
* @covers Encoding::hexDecode()
* @covers Encoding::hexEncode()
* @covers Encoding::base32Decode()
* @covers Encoding::base32Encode()
* @covers Encoding::base64Decode()
* @covers Encoding::base64Encode()
* @covers Encoding::base64DotSlashDecode()
* @covers Encoding::base64DotSlashEncode()
* @covers Encoding::base64DotSlashOrderedDecode()
* @covers Encoding::base64DotSlashOrderedEncode()
*/
public function testBasicEncoding()
{
// Re-run the test at least 3 times for each length
for ($j = 0; $j < 3; ++$j) {
for ($i = 1; $i < 84; ++$i) {
$rand = random_bytes($i);
$enc = Encoding::hexEncode($rand);
$this->assertSame(
\bin2hex($rand),
$enc,
"Hex Encoding - Length: " . $i
);
$this->assertSame(
$rand,
Encoding::hexDecode($enc),
"Hex Encoding - Length: " . $i
);
// Uppercase variant:
$enc = Hex::encodeUpper($rand);
$this->assertSame(
\strtoupper(\bin2hex($rand)),
$enc,
"Hex Encoding - Length: " . $i
);
$this->assertSame(
$rand,
Hex::decode($enc),
"HexUpper Encoding - Length: " . $i
);
$enc = Encoding::base32Encode($rand);
$this->assertSame(
$rand,
Encoding::base32Decode($enc),
"Base32 Encoding - Length: " . $i
);
$enc = Encoding::base32EncodeUpper($rand);
$this->assertSame(
$rand,
Encoding::base32DecodeUpper($enc),
"Base32Upper Encoding - Length: " . $i
);
$enc = Encoding::base32HexEncode($rand);
$this->assertSame(
bin2hex($rand),
bin2hex(Encoding::base32HexDecode($enc)),
"Base32Hex Encoding - Length: " . $i
);
$enc = Encoding::base32HexEncodeUpper($rand);
$this->assertSame(
bin2hex($rand),
bin2hex(Encoding::base32HexDecodeUpper($enc)),
"Base32HexUpper Encoding - Length: " . $i
);
$enc = Encoding::base64Encode($rand);
$this->assertSame(
$rand,
Encoding::base64Decode($enc),
"Base64 Encoding - Length: " . $i
);
$enc = Encoding::base64EncodeDotSlash($rand);
$this->assertSame(
$rand,
Encoding::base64DecodeDotSlash($enc),
"Base64 DotSlash Encoding - Length: " . $i
);
$enc = Encoding::base64EncodeDotSlashOrdered($rand);
$this->assertSame(
$rand,
Encoding::base64DecodeDotSlashOrdered($enc),
"Base64 Ordered DotSlash Encoding - Length: " . $i
);
$enc = Base64UrlSafe::encode($rand);
$this->assertSame(
\strtr(\base64_encode($rand), '+/', '-_'),
$enc
);
$this->assertSame(
$rand,
Base64UrlSafe::decode($enc)
);
}
}
}
}
\ No newline at end of file
<?php
use \ParagonIE\ConstantTime\Hex;
class HexTest extends PHPUnit\Framework\TestCase
{
/**
* @covers Hex::encode()
* @covers Hex::decode()
* @covers Hex::encodeUpper()
*/
public function testRandom()
{
for ($i = 1; $i < 32; ++$i) {
for ($j = 0; $j < 50; ++$j) {
$random = \random_bytes($i);
$enc = Hex::encode($random);
$this->assertSame(
$random,
Hex::decode($enc)
);
$this->assertSame(
\bin2hex($random),
$enc
);
$enc = Hex::encodeUpper($random);
$this->assertSame(
$random,
Hex::decode($enc)
);
$this->assertSame(
\strtoupper(\bin2hex($random)),
$enc
);
}
}
}
}
<?php
use \ParagonIE\ConstantTime\Base32;
use \ParagonIE\ConstantTime\Base32Hex;
use \ParagonIE\ConstantTime\Base64;
use \ParagonIE\ConstantTime\Base64DotSlash;
use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
use \ParagonIE\ConstantTime\Encoding;
use \ParagonIE\ConstantTime\Hex;
/**
* Class RFC4648Test
*
* @ref https://tools.ietf.org/html/rfc4648#section-10
*/
class RFC4648Test extends PHPUnit\Framework\TestCase
{
public function testVectorBase64()
{
$this->assertSame(Base64::encode(''), '');
$this->assertSame(Base64::encode('f'), 'Zg==');
$this->assertSame(Base64::encode('fo'), 'Zm8=');
$this->assertSame(Base64::encode('foo'), 'Zm9v');
$this->assertSame(Base64::encode('foob'), 'Zm9vYg==');
$this->assertSame(Base64::encode('fooba'), 'Zm9vYmE=');
$this->assertSame(Base64::encode('foobar'), 'Zm9vYmFy');
}
public function testVectorBase32()
{
$this->assertSame(Base32::encode(''), '');
$this->assertSame(Base32::encode('f'), 'my======');
$this->assertSame(Base32::encode('fo'), 'mzxq====');
$this->assertSame(Base32::encode('foo'), 'mzxw6===');
$this->assertSame(Base32::encode('foob'), 'mzxw6yq=');
$this->assertSame(Base32::encode('fooba'), 'mzxw6ytb');
$this->assertSame(Base32::encode('foobar'), 'mzxw6ytboi======');
$this->assertSame(Base32::encodeUpper(''), '');
$this->assertSame(Base32::encodeUpper('f'), 'MY======');
$this->assertSame(Base32::encodeUpper('fo'), 'MZXQ====');
$this->assertSame(Base32::encodeUpper('foo'), 'MZXW6===');
$this->assertSame(Base32::encodeUpper('foob'), 'MZXW6YQ=');
$this->assertSame(Base32::encodeUpper('fooba'), 'MZXW6YTB');
$this->assertSame(Base32::encodeUpper('foobar'), 'MZXW6YTBOI======');
}
public function testVectorBase32Hex()
{
$this->assertSame(Base32Hex::encode(''), '');
$this->assertSame(Base32Hex::encode('f'), 'co======');
$this->assertSame(Base32Hex::encode('fo'), 'cpng====');
$this->assertSame(Base32Hex::encode('foo'), 'cpnmu===');
$this->assertSame(Base32Hex::encode('foob'), 'cpnmuog=');
$this->assertSame(Base32Hex::encode('fooba'), 'cpnmuoj1');
$this->assertSame(Base32Hex::encode('foobar'), 'cpnmuoj1e8======');
$this->assertSame(Base32Hex::encodeUpper(''), '');
$this->assertSame(Base32Hex::encodeUpper('f'), 'CO======');
$this->assertSame(Base32Hex::encodeUpper('fo'), 'CPNG====');
$this->assertSame(Base32Hex::encodeUpper('foo'), 'CPNMU===');
$this->assertSame(Base32Hex::encodeUpper('foob'), 'CPNMUOG=');
$this->assertSame(Base32Hex::encodeUpper('fooba'), 'CPNMUOJ1');
$this->assertSame(Base32Hex::encodeUpper('foobar'), 'CPNMUOJ1E8======');
}
public function testVectorBase16()
{
$this->assertSame(Hex::encode(''), '');
$this->assertSame(Hex::encode('f'), '66');
$this->assertSame(Hex::encode('fo'), '666f');
$this->assertSame(Hex::encode('foo'), '666f6f');
$this->assertSame(Hex::encode('foob'), '666f6f62');
$this->assertSame(Hex::encode('fooba'), '666f6f6261');
$this->assertSame(Hex::encode('foobar'), '666f6f626172');
$this->assertSame(Hex::encodeUpper(''), '');
$this->assertSame(Hex::encodeUpper('f'), '66');
$this->assertSame(Hex::encodeUpper('fo'), '666F');
$this->assertSame(Hex::encodeUpper('foo'), '666F6F');
$this->assertSame(Hex::encodeUpper('foob'), '666F6F62');
$this->assertSame(Hex::encodeUpper('fooba'), '666F6F6261');
$this->assertSame(Hex::encodeUpper('foobar'), '666F6F626172');
}
}
......@@ -2,7 +2,113 @@
All Notable changes to `php-amqplib` will be documented in this file
## [Unreleased]
## 2.12.2 - 2021-02-12
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/18?closed=1)
## 2.12.1 - 2020-08-24
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/17?closed=1)
## 2.12.0 - 2020-08-24
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/14?closed=1)
## 2.11.3 - 2020-05-13
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/16?closed=1)
## 2.11.2 - 2020-04-30
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/15?closed=1)
## 2.11.1 - 2020-02-24
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/13?closed=1)
## 2.11.0 - 2019-11-19
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/12?closed=1)
## 2.10.1 - 2019-10-10
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/11?closed=1)
## 2.10.0 - 2019-08-09
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/10?closed=1)
- Heartbeats are disabled by default. This reverts the following changes: [Issue](https://github.com/php-amqplib/php-amqplib/issues/563) / [PR](https://github.com/php-amqplib/php-amqplib/pull/648)
## 2.9.2 - 2019-04-24
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/9?closed=1)
## 2.9.1 - 2019-03-26
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/8?closed=1)
## 2.9.0 - 2019-03-23
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/7?closed=1)
- heartbeats are now enabled by default [Issue](https://github.com/php-amqplib/php-amqplib/issues/563) / [PR](https://github.com/php-amqplib/php-amqplib/pull/648)
## 2.8.1 - 2018-11-13
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/6?closed=1)
- `ext-sockets` is now required: [PR](https://github.com/php-amqplib/php-amqplib/pull/610)
- Fix `errno=11 Resource temporarily unavailable` error: [Issue](https://github.com/php-amqplib/php-amqplib/issues/613) / [PR](https://github.com/php-amqplib/php-amqplib/pull/615)
## 2.8.0 - 2018-10-23
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/3?closed=1)
- Drop testing and support for PHP 5.3
- Use specific exceptions instead of general `AMQPRuntimeException`: [PR](https://github.com/php-amqplib/php-amqplib/pull/600)
- Allow overriding of `LIBRARY_PROPERTIES` - [PR](https://github.com/php-amqplib/php-amqplib/pull/606)
## 2.7.2 - 2018-02-11
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/5?closed=1)
- PHP `5.3` compatibility [PR](https://github.com/php-amqplib/php-amqplib/issues/539)
## 2.7.1 - 2018-02-01
- Support PHPUnit 6 [PR](https://github.com/php-amqplib/php-amqplib/pull/530)
- Use `tcp_nodelay` for `StreamIO` [PR](https://github.com/php-amqplib/php-amqplib/pull/517)
- Pass connection timeout to `wait` method [PR](https://github.com/php-amqplib/php-amqplib/pull/512)
- Fix possible indefinite waiting for data in StreamIO [PR](https://github.com/php-amqplib/php-amqplib/pull/423), [PR](https://github.com/php-amqplib/php-amqplib/pull/534)
- Change protected method check_heartbeat to public [PR](https://github.com/php-amqplib/php-amqplib/pull/520)
- Ensure access levels are consistent for calling `check_heartbeat` [PR](https://github.com/php-amqplib/php-amqplib/pull/535)
## 2.7.0 - 2017-09-20
### Added
- Increased overall test coverage
- Bring heartbeat support to socket connection
- Add message delivery tag for publisher confirms
- Add support for serializing DateTimeImmutable objects
### Fixed
- Fixed infinite loop on reconnect - check_heartbeat
- Fixed signal handling exit example
- Fixed exchange_unbind arguments
- Fixed invalid annotation for channel_id
- Fixed socket null error on php 5.3 version
- Fixed timeout parameters on HHVM before calling stream_select
### Changed
- declare(ticks=1) no longer needed after PHP5.3 / amqplib 2.4.1
- Minor DebugHelper improvements
### Enhancements
- Add extensions requirements to README.md
- Add PHP 7.1 to Travis build
- Reduce memory usage in StreamIO::write()
- Re-enable heartbeats after reconnection
## 2.6.3 - 2016-04-11
......
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating
documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to
fairly and consistently applying these principles to every aspect of managing
this project. Project maintainers who do not follow or enforce the Code of
Conduct may be permanently removed from the project team.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting a project maintainer. All complaints will be reviewed
and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain
confidentiality with regard to the reporter of an incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.3.0, available at
[http://contributor-covenant.org/version/1/3/0/][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/3/0/
# Contributing
Contributions are **welcome** and will be fully **credited**.
We accept contributions via Pull Requests on [Github](https://github.com/videlalvaro/php-amqplib).
## Pull Requests
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
- **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date.
- **Consider our release cycle** - We try to follow semver. Randomly breaking public APIs is not an option.
- **Create topic branches** - Don't ask us to pull from your master branch.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
## Running Tests
``` bash
$ phpunit
```
**Happy coding**!
Following people contributed to this project:
Barry Pederson <bp@barryp.org> - author of original Python lib
Vadim Zaliva <lord@crocodile.org> - PHP paort
taavi013@gmail.com patches - patches
Sean Murphy http://code.google.com/u/sgmurphy/ - patches
spiderbill http://code.google.com/u/spiderbill/ - patches
<?php
namespace PhpAmqpLib\Connection;
class AMQPLazyConnection extends AMQPStreamConnection
......@@ -28,9 +29,9 @@ class AMQPLazyConnection extends AMQPStreamConnection
/**
* @return null|\PhpAmqpLib\Wire\IO\AbstractIO
*/
protected function getIO()
public function getIO()
{
if (!$this->io) {
if (empty($this->io)) {
$this->connect();
}
......
......@@ -32,9 +32,9 @@ class AMQPLazySocketConnection extends AMQPSocketConnection
/**
* @return null|\PhpAmqpLib\Wire\IO\AbstractIO
*/
protected function getIO()
public function getIO()
{
if (!$this->io) {
if (empty($this->io)) {
$this->connect();
}
......@@ -50,4 +50,4 @@ class AMQPLazySocketConnection extends AMQPSocketConnection
{
return false;
}
}
\ No newline at end of file
}
<?php
namespace PhpAmqpLib\Connection;
class AMQPSSLConnection extends AMQPStreamConnection
......@@ -11,6 +12,7 @@ class AMQPSSLConnection extends AMQPStreamConnection
* @param string $vhost
* @param array $ssl_options
* @param array $options
* @param string $ssl_protocol
*/
public function __construct(
$host,
......@@ -19,9 +21,10 @@ class AMQPSSLConnection extends AMQPStreamConnection
$password,
$vhost = '/',
$ssl_options = array(),
$options = array()
$options = array(),
$ssl_protocol = 'ssl'
) {
$ssl_context = empty($ssl_options) ? null : $this->create_ssl_context($ssl_options);
$ssl_context = empty($ssl_options) ? null : $this->createSslContext($ssl_options);
parent::__construct(
$host,
$port,
......@@ -33,18 +36,26 @@ class AMQPSSLConnection extends AMQPStreamConnection
isset($options['login_response']) ? $options['login_response'] : null,
isset($options['locale']) ? $options['locale'] : 'en_US',
isset($options['connection_timeout']) ? $options['connection_timeout'] : 3,
isset($options['read_write_timeout']) ? $options['read_write_timeout'] : 3,
isset($options['read_write_timeout']) ? $options['read_write_timeout'] : 130,
$ssl_context,
isset($options['keepalive']) ? $options['keepalive'] : false,
isset($options['heartbeat']) ? $options['heartbeat'] : 0
isset($options['heartbeat']) ? $options['heartbeat'] : 0,
isset($options['channel_rpc_timeout']) ? $options['channel_rpc_timeout'] : 0.0,
$ssl_protocol
);
}
public static function try_create_connection($host, $port, $user, $password, $vhost, $options)
{
$ssl_options = isset($options['ssl_options']) ? $options['ssl_options'] : [];
return new static($host, $port, $user, $password, $vhost, $ssl_options, $options);
}
/**
* @param array $options
* @return resource
*/
private function create_ssl_context($options)
private function createSslContext($options)
{
$ssl_context = stream_context_create();
foreach ($options as $k => $v) {
......
<?php
namespace PhpAmqpLib\Connection;
use PhpAmqpLib\Wire\IO\SocketIO;
......@@ -13,10 +14,14 @@ class AMQPSocketConnection extends AbstractConnection
* @param string $vhost
* @param bool $insist
* @param string $login_method
* @param null $login_response
* @param null $login_response @deprecated
* @param string $locale
* @param float $timeout
* @param int|float $read_timeout
* @param bool $keepalive
* @param int $write_timeout
* @param int $heartbeat
* @param float $channel_rpc_timeout
* @throws \Exception
*/
public function __construct(
$host,
......@@ -28,10 +33,17 @@ class AMQPSocketConnection extends AbstractConnection
$login_method = 'AMQPLAIN',
$login_response = null,
$locale = 'en_US',
$timeout = 3,
$keepalive = false
$read_timeout = 3,
$keepalive = false,
$write_timeout = 3,
$heartbeat = 0,
$channel_rpc_timeout = 0.0
) {
$io = new SocketIO($host, $port, $timeout, $keepalive);
if ($channel_rpc_timeout > $read_timeout) {
throw new \InvalidArgumentException('channel RPC timeout must not be greater than I/O read timeout');
}
$io = new SocketIO($host, $port, $read_timeout, $keepalive, $write_timeout, $heartbeat);
parent::__construct(
$user,
......@@ -41,7 +53,45 @@ class AMQPSocketConnection extends AbstractConnection
$login_method,
$login_response,
$locale,
$io
$io,
$heartbeat,
max($read_timeout, $write_timeout),
$channel_rpc_timeout
);
}
protected static function try_create_connection($host, $port, $user, $password, $vhost, $options)
{
$insist = isset($options['insist']) ?
$options['insist'] : false;
$login_method = isset($options['login_method']) ?
$options['login_method'] : 'AMQPLAIN';
$login_response = isset($options['login_response']) ?
$options['login_response'] : null;
$locale = isset($options['locale']) ?
$options['locale'] : 'en_US';
$read_timeout = isset($options['read_timeout']) ?
$options['read_timeout'] : 3;
$keepalive = isset($options['keepalive']) ?
$options['keepalive'] : false;
$write_timeout = isset($options['write_timeout']) ?
$options['write_timeout'] : 3;
$heartbeat = isset($options['heartbeat']) ?
$options['heartbeat'] : 0;
return new static(
$host,
$port,
$user,
$password,
$vhost,
$insist,
$login_method,
$login_response,
$locale,
$read_timeout,
$keepalive,
$write_timeout,
$heartbeat
);
}
}
<?php
namespace PhpAmqpLib\Connection;
use PhpAmqpLib\Wire\IO\StreamIO;
......@@ -13,13 +14,15 @@ class AMQPStreamConnection extends AbstractConnection
* @param string $vhost
* @param bool $insist
* @param string $login_method
* @param null $login_response
* @param null $login_response @deprecated
* @param string $locale
* @param float $connection_timeout
* @param float $read_write_timeout
* @param null $context
* @param bool $keepalive
* @param int $heartbeat
* @param float $channel_rpc_timeout
* @param string|null $ssl_protocol
*/
public function __construct(
$host,
......@@ -35,8 +38,14 @@ class AMQPStreamConnection extends AbstractConnection
$read_write_timeout = 3.0,
$context = null,
$keepalive = false,
$heartbeat = 0
$heartbeat = 0,
$channel_rpc_timeout = 0.0,
$ssl_protocol = null
) {
if ($channel_rpc_timeout > $read_write_timeout) {
throw new \InvalidArgumentException('channel RPC timeout must not be greater than I/O read-write timeout');
}
$io = new StreamIO(
$host,
$port,
......@@ -44,7 +53,8 @@ class AMQPStreamConnection extends AbstractConnection
$read_write_timeout,
$context,
$keepalive,
$heartbeat
$heartbeat,
$ssl_protocol
);
parent::__construct(
......@@ -56,10 +66,50 @@ class AMQPStreamConnection extends AbstractConnection
$login_response,
$locale,
$io,
$heartbeat
$heartbeat,
$connection_timeout,
$channel_rpc_timeout
);
// save the params for the use of __clone, this will overwrite the parent
$this->construct_params = func_get_args();
}
protected static function try_create_connection($host, $port, $user, $password, $vhost, $options)
{
$insist = isset($options['insist']) ?
$options['insist'] : false;
$login_method = isset($options['login_method']) ?
$options['login_method'] : 'AMQPLAIN';
$login_response = isset($options['login_response']) ?
$options['login_response'] : null;
$locale = isset($options['locale']) ?
$options['locale'] : 'en_US';
$connection_timeout = isset($options['connection_timeout']) ?
$options['connection_timeout'] : 3.0;
$read_write_timeout = isset($options['read_write_timeout']) ?
$options['read_write_timeout'] : 130.0;
$context = isset($options['context']) ?
$options['context'] : null;
$keepalive = isset($options['keepalive']) ?
$options['keepalive'] : false;
$heartbeat = isset($options['heartbeat']) ?
$options['heartbeat'] : 60;
return new static(
$host,
$port,
$user,
$password,
$vhost,
$insist,
$login_method,
$login_response,
$locale,
$connection_timeout,
$read_write_timeout,
$context,
$keepalive,
$heartbeat
);
}
}
<?php
namespace PhpAmqpLib\Connection\Heartbeat;
use PhpAmqpLib\Connection\AbstractConnection;
use PhpAmqpLib\Exception\AMQPRuntimeException;
/**
* Manages pcntl-based heartbeat sending for a {@link AbstractConnection}.
*/
final class PCNTLHeartbeatSender
{
/**
* @var AbstractConnection
*/
private $connection;
/**
* @param AbstractConnection $connection
* @throws AMQPRuntimeException
*/
public function __construct(AbstractConnection $connection)
{
if (!$this->isSupported()) {
throw new AMQPRuntimeException('Signal-based heartbeat sender is unsupported');
}
$this->connection = $connection;
}
public function __destruct()
{
$this->unregister();
}
/**
* @return bool
*/
private function isSupported()
{
return extension_loaded('pcntl')
&& function_exists('pcntl_async_signals')
&& (defined('AMQP_WITHOUT_SIGNALS') ? !AMQP_WITHOUT_SIGNALS : true);
}
public function register()
{
if (!$this->connection) {
throw new AMQPRuntimeException('Unable to re-register heartbeat sender');
}
if (!$this->connection->isConnected()) {
throw new AMQPRuntimeException('Unable to register heartbeat sender, connection is not active');
}
$timeout = $this->connection->getHeartbeat();
if ($timeout > 0) {
$interval = ceil($timeout / 2);
pcntl_async_signals(true);
$this->registerListener($interval);
pcntl_alarm($interval);
}
}
public function unregister()
{
$this->connection = null;
// restore default signal handler
pcntl_signal(SIGALRM, SIG_IGN);
}
/**
* @param int $interval
*/
private function registerListener($interval)
{
pcntl_signal(SIGALRM, function () use ($interval) {
if (!$this->connection) {
return;
}
if (!$this->connection->isConnected()) {
$this->unregister();
return;
}
if ($this->connection->isWriting()) {
pcntl_alarm($interval);
return;
}
if (time() > ($this->connection->getLastActivity() + $interval)) {
$this->connection->checkHeartBeat();
}
pcntl_alarm($interval);
});
}
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPBasicCancelException extends \Exception implements AMQPExceptionInterface
{
/** @var string */
/**
* @var string
* @internal Use getter getConsumerTag()
*/
public $consumerTag;
/**
......@@ -11,6 +15,15 @@ class AMQPBasicCancelException extends \Exception implements AMQPExceptionInterf
*/
public function __construct($consumerTag)
{
parent::__construct('Channel was canceled');
$this->consumerTag = $consumerTag;
}
/**
* @return string
*/
public function getConsumerTag()
{
return $this->consumerTag;
}
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPChannelClosedException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPConnectionBlockedException extends AMQPRuntimeException
{
public function __construct($message = '', $code = 0, $previous = null)
{
if (empty($message)) {
$message = 'Connection is blocked due to low resources';
}
parent::__construct($message, $code, $previous);
}
}
<?php
namespace PhpAmqpLib\Exception;
/**
* When connection was closed by server, proxy or some tunnel due to timeout or network issue.
*/
class AMQPConnectionClosedException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPDataReadException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPEmptyDeliveryTagException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
//TODO refactor usage of static methods
use PhpAmqpLib\Channel\AbstractChannel;
use PhpAmqpLib\Helper\MiscHelper;
namespace PhpAmqpLib\Exception;
/**
* @deprecated use AMQPProtocolException instead
*/
class AMQPException extends \Exception
{
/** @var string */
/** @var int */
public $amqp_reply_code;
/** @var int */
/** @var string */
public $amqp_reply_text;
/** @var \Exception */
/** @var int[] */
public $amqp_method_sig;
/** @var array */
public $args;
/**
* @param string $reply_code
* @param int $reply_text
* @param array $method_sig
* @param int $reply_code
* @param string $reply_text
* @param int[] $method_sig
*/
public function __construct($reply_code, $reply_text, $method_sig)
{
......@@ -35,12 +32,6 @@ class AMQPException extends \Exception
$this->amqp_reply_text = $reply_text; // redundant, but kept for BC
$this->amqp_method_sig = $method_sig;
$ms = MiscHelper::methodSig($method_sig);
$protocolClass = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS;
$mn = isset($protocolClass::$GLOBAL_METHOD_NAMES[$ms])
? $protocolClass::$GLOBAL_METHOD_NAMES[$ms]
: $mn = '';
$this->args = array($reply_code, $reply_text, $method_sig, $mn);
$this->args = array($reply_code, $reply_text, $method_sig, '');
}
}
<?php
namespace PhpAmqpLib\Exception;
interface AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPHeartbeatMissedException extends AMQPConnectionClosedException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPIOException extends \Exception implements AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPIOWaitException extends AMQPRuntimeException
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPInvalidArgumentException extends \RuntimeException implements AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPInvalidFrameException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPLogicException extends \LogicException implements AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
/**
* Used mostly in non-blocking methods when no data is ready for processing.
*/
class AMQPNoDataException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPNotImplementedException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPOutOfBoundsException extends \OutOfBoundsException implements AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPOutOfRangeException extends \OutOfRangeException implements AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPProtocolChannelException extends AMQPProtocolException
......
<?php
namespace PhpAmqpLib\Exception;
/**
* @deprecated
*/
class AMQPProtocolConnectionException extends AMQPProtocolException
{
}
<?php
namespace PhpAmqpLib\Exception;
//TODO refactor usage of static methods
use PhpAmqpLib\Channel\AbstractChannel;
use PhpAmqpLib\Helper\MiscHelper;
namespace PhpAmqpLib\Exception;
class AMQPProtocolException extends \Exception implements AMQPExceptionInterface
{
/** @var string */
/** @var int */
public $amqp_reply_code;
/** @var int */
/** @var string */
public $amqp_reply_text;
/** @var \Exception */
/** @var int[] */
public $amqp_method_sig;
/** @var array */
public $args;
/**
* @param string $reply_code
* @param int $reply_text
* @param array $method_sig
* @param int $reply_code
* @param string $reply_text
* @param int[] $method_sig
*/
public function __construct($reply_code, $reply_text, $method_sig)
{
......@@ -32,13 +29,6 @@ class AMQPProtocolException extends \Exception implements AMQPExceptionInterface
$this->amqp_reply_text = $reply_text; // redundant, but kept for BC
$this->amqp_method_sig = $method_sig;
$ms = MiscHelper::methodSig($method_sig);
$protocolClass = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS;
$mn = isset($protocolClass::$GLOBAL_METHOD_NAMES[$ms])
? $protocolClass::$GLOBAL_METHOD_NAMES[$ms]
: $mn = '';
$this->args = array($reply_code, $reply_text, $method_sig, $mn);
$this->args = array($reply_code, $reply_text, $method_sig);
}
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPRuntimeException extends \RuntimeException implements AMQPExceptionInterface
......
<?php
namespace PhpAmqpLib\Exception;
class AMQPSocketException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPTimeoutException extends \RuntimeException implements AMQPExceptionInterface
{
/**
* @var int|float|null
*/
private $timeout;
public function __construct($message = '', $timeout = 0, $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
$this->timeout = $timeout;
}
/**
* @param int|float|null $timeout
* @param int $code
* @return self
*/
public static function writeTimeout($timeout, $code = 0)
{
return new self('Error sending data. Connection timed out.', $timeout, $code);
}
/**
* @return int|float|null
*/
public function getTimeout()
{
return $this->timeout;
}
}
<?php
namespace PhpAmqpLib\Exchange;
final class AMQPExchangeType
{
const DIRECT = 'direct';
const FANOUT = 'fanout';
const TOPIC = 'topic';
const HEADERS = 'headers';
}
<?php
namespace PhpAmqpLib\Helper;
use InvalidArgumentException;
class Assert
{
/**
* @param mixed $argument
* @throws \InvalidArgumentException
*/
public static function isCallable($argument)
{
if (!is_callable($argument)) {
throw new InvalidArgumentException(sprintf(
'Given argument "%s" should be callable. %s type was given.',
$argument,
gettype($argument)
));
}
}
}
<?php
// phpcs:ignoreFile
namespace PhpAmqpLib\Helper;
if (class_exists('phpseclib\Math\BigInteger')) {
class BigInteger extends \phpseclib\Math\BigInteger
{
}
} elseif (class_exists('phpseclib3\Math\BigInteger')) {
class BigInteger extends \phpseclib3\Math\BigInteger
{
}
} else {
throw new \RuntimeException('Cannot find supported phpseclib/phpseclib library');
}
<?php
namespace PhpAmqpLib\Helper;
use PhpAmqpLib\Wire\Constants;
class DebugHelper
{
/**
......@@ -9,22 +12,34 @@ class DebugHelper
protected $debug;
/**
* @var string
* @var resource
*/
protected $debug_output;
/**
* @var Constants
*/
protected $PROTOCOL_CONSTANTS_CLASS;
protected $constants;
/**
* @param string $PROTOCOL_CONSTANTS_CLASS
* @param Constants $constants
*/
public function __construct($PROTOCOL_CONSTANTS_CLASS) {
public function __construct(Constants $constants)
{
$this->debug = defined('AMQP_DEBUG') ? AMQP_DEBUG : false;
$this->PROTOCOL_CONSTANTS_CLASS = $PROTOCOL_CONSTANTS_CLASS;
if (defined('AMQP_DEBUG_OUTPUT')) {
$this->debug_output = AMQP_DEBUG_OUTPUT;
} else {
$this->debug_output = fopen('php://output', 'wb');
}
$this->constants = $constants;
}
/**
* @param string $msg
*/
public function debug_msg($msg) {
public function debug_msg($msg)
{
if ($this->debug) {
$this->print_msg($msg);
}
......@@ -33,19 +48,23 @@ class DebugHelper
/**
* @param array $allowed_methods
*/
public function debug_allowed_methods($allowed_methods) {
if ($allowed_methods) {
$msg = 'waiting for ' . implode(', ', $allowed_methods);
} else {
$msg = 'waiting for any method';
public function debug_allowed_methods($allowed_methods)
{
if ($this->debug) {
if ($allowed_methods) {
$msg = 'waiting for ' . implode(', ', $allowed_methods);
} else {
$msg = 'waiting for any method';
}
$this->debug_msg($msg);
}
$this->debug_msg($msg);
}
/**
* @param string $method_sig
*/
public function debug_method_signature1($method_sig) {
public function debug_method_signature1($method_sig)
{
$this->debug_method_signature('< %s:', $method_sig);
}
......@@ -53,27 +72,29 @@ class DebugHelper
* @param string $msg
* @param string $method_sig
*/
public function debug_method_signature($msg, $method_sig) {
public function debug_method_signature($msg, $method_sig)
{
if ($this->debug) {
$protocolClass = $this->PROTOCOL_CONSTANTS_CLASS;
$this->debug_msg(sprintf(
$msg . ': %s',
MiscHelper::methodSig($method_sig),
$protocolClass::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]
));
$constants = $this->constants;
$methods = $constants::$GLOBAL_METHOD_NAMES;
$key = MiscHelper::methodSig($method_sig);
$this->debug_msg(sprintf($msg . ': %s', $key, $methods[$key]));
}
}
/**
* @param string $data
*/
public function debug_hexdump($data) {
public function debug_hexdump($data)
{
if ($this->debug) {
$this->debug_msg(sprintf(
'< [hex]: %s%s',
PHP_EOL,
MiscHelper::hexdump($data, $htmloutput = false, $uppercase = true, $return = true)
));
$this->debug_msg(
sprintf(
'< [hex]: %s%s',
PHP_EOL,
MiscHelper::hexdump($data, $htmloutput = false, $uppercase = true, $return = true)
)
);
}
}
......@@ -84,23 +105,27 @@ class DebugHelper
* @param array $mechanisms
* @param array $locales
*/
public function debug_connection_start($version_major, $version_minor, $server_properties, $mechanisms, $locales) {
public function debug_connection_start($version_major, $version_minor, $server_properties, $mechanisms, $locales)
{
if ($this->debug) {
$this->debug_msg(sprintf(
'Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s',
$version_major,
$version_minor,
MiscHelper::dump_table($server_properties),
implode(', ', $mechanisms),
implode(', ', $locales)
));
$this->debug_msg(
sprintf(
'Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s',
$version_major,
$version_minor,
MiscHelper::dump_table($server_properties),
implode(', ', $mechanisms),
implode(', ', $locales)
)
);
}
}
/**
* @param string $s
*/
protected function print_msg($s) {
echo $s . PHP_EOL;
protected function print_msg($s)
{
fwrite($this->debug_output, $s . PHP_EOL);
}
}
<?php
namespace PhpAmqpLib\Helper;
class MiscHelper
......@@ -17,26 +18,16 @@ class MiscHelper
}
/**
* @param string $bytes
*/
public static function saveBytes($bytes)
{
$fh = fopen('/tmp/bytes', 'wb');
fwrite($fh, $bytes);
fclose($fh);
}
/**
* Gets a number (either int or float) and returns an array containing its integer part as first element and its
* decimal part mutliplied by 10^6. Useful for some PHP stream functions that need seconds and microseconds as
* different arguments
*
* @param int|float $number
* @return array
* @return int[]
*/
public static function splitSecondsMicroseconds($number)
{
return array(floor($number), ($number - floor($number)) * 1000000);
return array((int)floor($number), (int)(fmod($number, 1) * 1000000));
}
/**
......@@ -117,6 +108,8 @@ class MiscHelper
}
echo $dump;
return null;
}
/**
......
......@@ -17,8 +17,13 @@ class Protocol080
* @param string $locales
* @return array
*/
public function connectionStart($version_major = 0, $version_minor = 8, $server_properties, $mechanisms = 'PLAIN', $locales = 'en_US')
{
public function connectionStart(
$version_major = 0,
$version_minor = 8,
$server_properties,
$mechanisms = 'PLAIN',
$locales = 'en_US'
) {
$writer = new AMQPWriter();
$writer->write_octet($version_major);
$writer->write_octet($version_minor);
......@@ -204,7 +209,7 @@ class Protocol080
/**
* @param int $reply_code
* @param string $reply_text
* @param array $details
* @param \PhpAmqpLib\Wire\AMQPTable|array $details
* @return array
*/
public function channelAlert($reply_code, $reply_text = '', $details = array())
......@@ -252,8 +257,14 @@ class Protocol080
* @param bool $read
* @return array
*/
public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true)
{
public function accessRequest(
$realm = '/data',
$exclusive = false,
$passive = true,
$active = true,
$write = true,
$read = true
) {
$writer = new AMQPWriter();
$writer->write_shortstr($realm);
$writer->write_bits(array($exclusive, $passive, $active, $write, $read));
......@@ -280,11 +291,20 @@ class Protocol080
* @param bool $auto_delete
* @param bool $internal
* @param bool $nowait
* @param array $arguments
* @return array
*/
public function exchangeDeclare($ticket = 1, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array())
{
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function exchangeDeclare(
$ticket = 1,
$exchange,
$type = 'direct',
$passive = false,
$durable = false,
$auto_delete = false,
$internal = false,
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($exchange);
......@@ -338,11 +358,19 @@ class Protocol080
* @param bool $exclusive
* @param bool $auto_delete
* @param bool $nowait
* @param array $arguments
* @return array
*/
public function queueDeclare($ticket = 1, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array())
{
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function queueDeclare(
$ticket = 1,
$queue = '',
$passive = false,
$durable = false,
$exclusive = false,
$auto_delete = false,
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -370,11 +398,17 @@ class Protocol080
* @param string $exchange
* @param string $routing_key
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function queueBind($ticket = 1, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array())
{
public function queueBind(
$ticket = 1,
$queue = '',
$exchange,
$routing_key = '',
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -454,7 +488,7 @@ class Protocol080
* @param string $queue
* @param string $exchange
* @param string $routing_key
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function queueUnbind($ticket = 1, $queue = '', $exchange, $routing_key = '', $arguments = array())
......@@ -513,8 +547,15 @@ class Protocol080
* @param bool $nowait
* @return array
*/
public function basicConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false)
{
public function basicConsume(
$ticket = 1,
$queue = '',
$consumer_tag = '',
$no_local = false,
$no_ack = false,
$exclusive = false,
$nowait = false
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -746,8 +787,15 @@ class Protocol080
* @param bool $nowait
* @return array
*/
public function fileConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false)
{
public function fileConsume(
$ticket = 1,
$queue = '',
$consumer_tag = '',
$no_local = false,
$no_ack = false,
$exclusive = false,
$nowait = false
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -834,8 +882,14 @@ class Protocol080
* @param string $identifier
* @return array
*/
public function filePublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $identifier)
{
public function filePublish(
$ticket = 1,
$exchange = '',
$routing_key = '',
$mandatory = false,
$immediate = false,
$identifier
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($exchange);
......@@ -871,8 +925,14 @@ class Protocol080
* @param string $identifier
* @return array
*/
public function fileDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key, $identifier)
{
public function fileDeliver(
$consumer_tag,
$delivery_tag,
$redelivered = false,
$exchange,
$routing_key,
$identifier
) {
$writer = new AMQPWriter();
$writer->write_shortstr($consumer_tag);
$writer->write_longlong($delivery_tag);
......@@ -945,8 +1005,14 @@ class Protocol080
* @param bool $nowait
* @return array
*/
public function streamConsume($ticket = 1, $queue = '', $consumer_tag = '', $no_local = false, $exclusive = false, $nowait = false)
{
public function streamConsume(
$ticket = 1,
$queue = '',
$consumer_tag = '',
$no_local = false,
$exclusive = false,
$nowait = false
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -998,8 +1064,13 @@ class Protocol080
* @param bool $immediate
* @return array
*/
public function streamPublish($ticket = 1, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false)
{
public function streamPublish(
$ticket = 1,
$exchange = '',
$routing_key = '',
$mandatory = false,
$immediate = false
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($exchange);
......@@ -1144,7 +1215,7 @@ class Protocol080
}
/**
* @param mixed $meta_data
* @param \PhpAmqpLib\Wire\AMQPTable|array $meta_data
* @return array
*/
public function tunnelRequest($meta_data)
......@@ -1155,11 +1226,11 @@ class Protocol080
}
/**
* @param mixed $integer_1
* @param int $integer_1
* @param int $integer_2
* @param int $integer_3
* @param int $integer_4
* @param mixed $operation
* @param int $operation
* @return array
*/
public function testInteger($integer_1, $integer_2, $integer_3, $integer_4, $operation)
......@@ -1187,7 +1258,7 @@ class Protocol080
/**
* @param string $string_1
* @param string $string_2
* @param mixed $operation
* @param int $operation
* @return array
*/
public function testString($string_1, $string_2, $operation)
......@@ -1211,9 +1282,9 @@ class Protocol080
}
/**
* @param mixed $table
* @param mixed $integer_op
* @param mixed $string_op
* @param \PhpAmqpLib\Wire\AMQPTable|array $table
* @param int $integer_op
* @param int $string_op
* @return array
*/
public function testTable($table, $integer_op, $string_op)
......
......@@ -17,8 +17,13 @@ class Protocol091
* @param string $locales
* @return array
*/
public function connectionStart($version_major = 0, $version_minor = 9, $server_properties, $mechanisms = 'PLAIN', $locales = 'en_US')
{
public function connectionStart(
$version_major = 0,
$version_minor = 9,
$server_properties,
$mechanisms = 'PLAIN',
$locales = 'en_US'
) {
$writer = new AMQPWriter();
$writer->write_octet($version_major);
$writer->write_octet($version_minor);
......@@ -246,8 +251,14 @@ class Protocol091
* @param bool $read
* @return array
*/
public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true)
{
public function accessRequest(
$realm = '/data',
$exclusive = false,
$passive = true,
$active = true,
$write = true,
$read = true
) {
$writer = new AMQPWriter();
$writer->write_shortstr($realm);
$writer->write_bits(array($exclusive, $passive, $active, $write, $read));
......@@ -274,11 +285,20 @@ class Protocol091
* @param bool $auto_delete
* @param bool $internal
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function exchangeDeclare($ticket = 0, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array())
{
public function exchangeDeclare(
$ticket = 0,
$exchange,
$type = 'direct',
$passive = false,
$durable = false,
$auto_delete = false,
$internal = false,
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($exchange);
......@@ -330,11 +350,17 @@ class Protocol091
* @param string $source
* @param string $routing_key
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function exchangeBind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array())
{
public function exchangeBind(
$ticket = 0,
$destination,
$source,
$routing_key = '',
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($destination);
......@@ -361,11 +387,17 @@ class Protocol091
* @param string $source
* @param string $routing_key
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function exchangeUnbind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array())
{
public function exchangeUnbind(
$ticket = 0,
$destination,
$source,
$routing_key = '',
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($destination);
......@@ -394,11 +426,19 @@ class Protocol091
* @param bool $exclusive
* @param bool $auto_delete
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function queueDeclare($ticket = 0, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array())
{
public function queueDeclare(
$ticket = 0,
$queue = '',
$passive = false,
$durable = false,
$exclusive = false,
$auto_delete = false,
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -426,11 +466,17 @@ class Protocol091
* @param string $exchange
* @param string $routing_key
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function queueBind($ticket = 0, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array())
{
public function queueBind(
$ticket = 0,
$queue = '',
$exchange,
$routing_key = '',
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -510,7 +556,7 @@ class Protocol091
* @param string $queue
* @param string $exchange
* @param string $routing_key
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function queueUnbind($ticket = 0, $queue = '', $exchange, $routing_key = '', $arguments = array())
......@@ -567,11 +613,19 @@ class Protocol091
* @param bool $no_ack
* @param bool $exclusive
* @param bool $nowait
* @param array $arguments
* @param \PhpAmqpLib\Wire\AMQPTable|array $arguments
* @return array
*/
public function basicConsume($ticket = 0, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false, $arguments = array())
{
public function basicConsume(
$ticket = 0,
$queue = '',
$consumer_tag = '',
$no_local = false,
$no_ack = false,
$exclusive = false,
$nowait = false,
$arguments = array()
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($queue);
......@@ -624,8 +678,13 @@ class Protocol091
* @param bool $immediate
* @return array
*/
public function basicPublish($ticket = 0, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false)
{
public function basicPublish(
$ticket = 0,
$exchange = '',
$routing_key = '',
$mandatory = false,
$immediate = false
) {
$writer = new AMQPWriter();
$writer->write_short($ticket);
$writer->write_shortstr($exchange);
......
<?php
namespace PhpAmqpLib\Helper;
/**
* @property-read int $SOCKET_EPIPE
* @property-read int $SOCKET_ENETDOWN
* @property-read int $SOCKET_ENETUNREACH
* @property-read int $SOCKET_ENETRESET
* @property-read int $SOCKET_ECONNABORTED
* @property-read int $SOCKET_ECONNRESET
* @property-read int $SOCKET_ECONNREFUSED
* @property-read int $SOCKET_ETIMEDOUT
* @property-read int $SOCKET_EWOULDBLOCK
* @property-read int $SOCKET_EINTR
* @property-read int $SOCKET_EAGAIN
*/
final class SocketConstants
{
/**
* @var int[]
*/
private $constants;
/** @var self */
private static $instance;
public function __construct()
{
$constants = get_defined_constants(true);
if (isset($constants['sockets'])) {
$this->constants = $constants['sockets'];
} else {
trigger_error('Sockets extension is not enabled', E_USER_WARNING);
$this->constants = array();
}
}
/**
* @param string $name
* @return int
*/
public function __get($name)
{
return isset($this->constants[$name]) ? $this->constants[$name] : 0;
}
/**
* @param string $name
* @param int $value
* @internal
*/
public function __set($name, $value)
{
}
/**
* @param string $name
* @return bool
*/
public function __isset($name)
{
return isset($this->constants[$name]);
}
/**
* @return self
*/
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
<?php
namespace PhpAmqpLib;
final class Package
{
const NAME = 'AMQPLib';
const VERSION = '2.12.2';
}
<?php
namespace PhpAmqpLib\Wire;
namespace PhpAmqpLib\Wire;
class AMQPArray extends AMQPAbstractCollection
{
......
<?php
namespace PhpAmqpLib\Wire;
use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
use PhpAmqpLib\Helper\BigInteger;
/**
* AMQP protocol decimal value.
......@@ -42,7 +44,10 @@ class AMQPDecimal
*/
public function asBCvalue()
{
return bcdiv($this->n, bcpow(10, $this->e));
$n = new BigInteger($this->n);
$e = new BigInteger('1' . str_repeat('0', $this->e));
list($q) = $n->divide($e);
return $q->toString();
}
/**
......
<?php
namespace PhpAmqpLib\Wire;
use PhpAmqpLib\Exception;
class AMQPTable extends AMQPAbstractCollection
{
......@@ -23,12 +23,16 @@ class AMQPTable extends AMQPAbstractCollection
public function set($key, $val, $type = null)
{
//https://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf, https://www.rabbitmq.com/resources/specs/amqp0-8.pdf
//Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or underlines, to a maximum length of 128 characters
//The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD signal a connection exception with reply code 503 (syntax error)
//Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits,
// or underlines, to a maximum length of 128 characters
//The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD signal a connection
// exception with reply code 503 (syntax error)
//validating length only and delegating other stuff to server, as rabbit seems to currently support numeric keys
if (!($len = strlen($key)) || ($len > 128)) {
throw new Exception\AMQPInvalidArgumentException('Table key must be non-empty string up to 128 chars in length');
throw new Exception\AMQPInvalidArgumentException(
'Table key must be non-empty string up to 128 chars in length'
);
}
$this->setValue($val, $type, $key);
}
......
<?php
namespace PhpAmqpLib\Wire;
use PhpAmqpLib\Helper\BigInteger;
class AbstractClient
{
/** @var bool */
const PLATFORM_64BIT = PHP_INT_SIZE === 8;
/** @var BigInteger[][] */
protected static $bigIntegers = array();
/**
* @var bool
*/
protected $is64bits;
protected static $isLittleEndian;
/**
* @var bool
* Converts byte-string between native and network byte order, in both directions
*
* @param string $bytes
* @return string
*/
protected $isLittleEndian;
protected function correctEndianness($bytes)
{
return self::isLittleEndian() ? $this->convertByteOrder($bytes) : $bytes;
}
public function __construct()
/**
* @param string $bytes
* @return string
*/
protected function convertByteOrder($bytes)
{
$this->is64bits = PHP_INT_SIZE == 8;
return strrev($bytes);
}
$tmp = unpack('S', "\x01\x00"); // to maintain 5.3 compatibility
$this->isLittleEndian = $tmp[1] == 1;
/**
* @param int $longInt
* @return bool
*/
protected function getLongMSB($longInt)
{
return (bool) ($longInt & 0x80000000);
}
/**
* Converts byte-string between native and network byte order, in both directions
*
* @param string $byteStr
* @return string
* @param string $bytes
* @return bool
*/
protected function getMSB($bytes)
{
return ord($bytes[0]) > 127;
}
/**
* @return bool
*/
protected function correctEndianness($byteStr)
protected static function isLittleEndian()
{
return $this->isLittleEndian ? strrev($byteStr) : $byteStr;
if (self::$isLittleEndian === null) {
$tmp = unpack('S', "\x01\x00"); // to maintain 5.3 compatibility
self::$isLittleEndian = $tmp[1] === 1;
}
return self::$isLittleEndian;
}
/**
* @param string $value
* @param int $base
* @return BigInteger
*/
protected static function getBigInteger($value, $base = 10)
{
if (!isset(self::$bigIntegers[$base])) {
self::$bigIntegers[$base] = array();
}
if (isset(self::$bigIntegers[$base][$value])) {
return self::$bigIntegers[$base][$value];
}
$integer = new BigInteger($value, $base);
self::$bigIntegers[$base][$value] = $integer;
return $integer;
}
}
<?php
namespace PhpAmqpLib\Wire;
abstract class Constants
{
const VERSION = '';
const AMQP_HEADER = '';
/**
* @var array<int, string>
*/
protected static $FRAME_TYPES = array();
/**
* @var array<int, string>
*/
protected static $CONTENT_METHODS = array();
/**
* @var array<int, string>
*/
protected static $CLOSE_METHODS = array();
/**
* @var array<string, string>
*/
public static $GLOBAL_METHOD_NAMES = array();
/**
* @return string
*/
public function getHeader()
{
return static::AMQP_HEADER;
}
/**
* @param int $type
* @return bool
*/
public function isFrameType($type)
{
return array_key_exists($type, static::$FRAME_TYPES);
}
/**
* @param int $type
* @return string
*/
public function getFrameType($type)
{
return static::$FRAME_TYPES[$type];
}
/**
* @param string $method
* @return bool
*/
public function isContentMethod($method)
{
return in_array($method, static::$CONTENT_METHODS, false);
}
/**
* @param string $method
* @return bool
*/
public function isCloseMethod($method)
{
return in_array($method, static::$CLOSE_METHODS, false);
}
}
......@@ -4,12 +4,10 @@
namespace PhpAmqpLib\Wire;
class Constants080
final class Constants080 extends Constants
{
/**
* @var string
*/
public static $AMQP_PROTOCOL_HEADER = "AMQP\x01\x01\x08\x00";
const VERSION = '8.0';
const AMQP_HEADER = "AMQP\x01\x01\x08\x00";
/**
* @var array
......
......@@ -4,12 +4,10 @@
namespace PhpAmqpLib\Wire;
class Constants091
final class Constants091 extends Constants
{
/**
* @var string
*/
public static $AMQP_PROTOCOL_HEADER = "AMQP\x00\x00\x09\x01";
const VERSION = '0.9.1';
const AMQP_HEADER = "AMQP\x00\x00\x09\x01";
/**
* @var array
......
<?php
namespace PhpAmqpLib\Wire;
use PhpAmqpLib\Channel\AMQPChannel;
/**
* Abstract base class for AMQP content. Subclasses should override
* the propertyDefinitions attribute.
*/
abstract class GenericContent
{
/** @var AMQPChannel[] */
public $delivery_info = array();
/** @var array Final property definitions */
protected $prop_types;
/** @var array Properties content */
private $properties = array();
/** @var string Compiled properties */
private $serialized_properties;
/**
* @var array
*/
protected static $propertyDefinitions = array(
'dummy' => 'shortstr'
);
/**
* @param array $properties Message property content
* @param array $propertyTypes Message property definitions
*/
public function __construct($properties, $propertyTypes = null)
{
$this->prop_types = self::$propertyDefinitions;
if (!empty($propertyTypes)) {
$this->prop_types = $propertyTypes;
}
if (!empty($properties)) {
$this->properties = array_intersect_key($properties, $this->prop_types);
}
}
/**
* Check whether a property exists in the 'properties' dictionary
* or if present - in the 'delivery_info' dictionary.
*
* @param string $name
* @return bool
*/
public function has($name)
{
return isset($this->properties[$name]) || isset($this->delivery_info[$name]);
}
/**
* Look for additional properties in the 'properties' dictionary,
* and if present - the 'delivery_info' dictionary.
*
* @param string $name
* @throws \OutOfBoundsException
* @return mixed|AMQPChannel
*/
public function get($name)
{
if (isset($this->properties[$name])) {
return $this->properties[$name];
}
if (isset($this->delivery_info[$name])) {
return $this->delivery_info[$name];
}
throw new \OutOfBoundsException(sprintf(
'No "%s" property',
$name
));
}
/**
* Returns the properties content
*
* @return array
*/
public function get_properties()
{
return $this->properties;
}
/**
* Sets a property value
*
* @param string $name The property name (one of the property definition)
* @param mixed $value The property value
* @throws \OutOfBoundsException
*/
public function set($name, $value)
{
if (!array_key_exists($name, $this->prop_types)) {
throw new \OutOfBoundsException(sprintf(
'No "%s" property',
$name
));
}
$this->properties[$name] = $value;
}
/**
* Given the raw bytes containing the property-flags and
* property-list from a content-frame-header, parse and insert
* into a dictionary stored in this object as an attribute named
* 'properties'.
*
* @param AMQPReader $reader
* NOTE: do not mutate $reader
* @return $this
*/
public function load_properties(AMQPReader $reader)
{
// Read 16-bit shorts until we get one with a low bit set to zero
$flags = array();
while (true) {
$flag_bits = $reader->read_short();
$flags[] = $flag_bits;
if (($flag_bits & 1) === 0) {
break;
}
}
$shift = 0;
$data = array();
foreach ($this->prop_types as $key => $proptype) {
if ($shift === 0) {
if (!$flags) {
break;
}
$flag_bits = array_shift($flags);
$shift = 15;
}
if ($flag_bits & (1 << $shift)) {
$data[$key] = $reader->{'read_' . $proptype}();
}
$shift -= 1;
}
$this->properties = $data;
return $this;
}
/**
* Serializes the 'properties' attribute (a dictionary) into the
* raw bytes making up a set of property flags and a property
* list, suitable for putting into a content frame header.
*
* @return string
* @todo Inject the AMQPWriter to make the method easier to test
*/
public function serialize_properties()
{
if (!empty($this->serialized_properties)) {
return $this->serialized_properties;
}
$shift = 15;
$flag_bits = 0;
$flags = array();
$raw_bytes = new AMQPWriter();
foreach ($this->prop_types as $key => $prototype) {
$val = isset($this->properties[$key]) ? $this->properties[$key] : null;
// Very important: PHP type eval is weak, use the === to test the
// value content. Zero or false value should not be removed
if ($val === null) {
$shift -= 1;
continue;
}
if ($shift === 0) {
$flags[] = $flag_bits;
$flag_bits = 0;
$shift = 15;
}
$flag_bits |= (1 << $shift);
if ($prototype != 'bit') {
$raw_bytes->{'write_' . $prototype}($val);
}
$shift -= 1;
}
$flags[] = $flag_bits;
$result = new AMQPWriter();
foreach ($flags as $flag_bits) {
$result->write_short($flag_bits);
}
$result->write($raw_bytes->getvalue());
$this->serialized_properties = $result->getvalue();
return $this->serialized_properties;
}
}
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment