vendor updates

This commit is contained in:
Andy Miller
2018-04-17 17:49:31 -06:00
parent 688d517dd9
commit 288d46c995
84 changed files with 5450 additions and 475 deletions

618
composer.lock generated

File diff suppressed because it is too large Load Diff

2
vendor/autoload.php vendored
View File

@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitf3438a4bfc092aad40a104edf0a3eb02::getLoader(); return ComposerAutoloaderInitda370287ab6d5b8a28188afe08f659c5::getLoader();

9
vendor/bacon/bacon-qr-code/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
composer.lock
vendor
nbproject
.idea
.buildpath
.project
.DS_Store
.*.sw*
.*.un~

14
vendor/bacon/bacon-qr-code/.travis.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm
install:
- travis_retry composer install --no-interaction
- composer info -i
script: vendor/bin/phpunit --bootstrap tests/bootstrap.php --configuration tests/phpunit.xml tests

View File

@@ -0,0 +1,29 @@
{
"name": "bacon/bacon-qr-code",
"description": "BaconQrCode is a QR code generator for PHP.",
"license" : "BSD-2-Clause",
"homepage": "https://github.com/Bacon/BaconQrCode",
"require": {
"php": "^5.4|^7.0",
"ext-iconv": "*"
},
"suggest": {
"ext-gd": "to generate QR code images"
},
"authors": [
{
"name": "Ben Scholzen 'DASPRiD'",
"email": "mail@dasprids.de",
"homepage": "http://www.dasprids.de",
"role": "Developer"
}
],
"autoload": {
"psr-0": {
"BaconQrCode": "src/"
}
},
"require-dev": {
"phpunit/phpunit": "^4.8"
}
}

View File

@@ -343,7 +343,7 @@ class Version
new EcBlocks(20, new EcBlock(2, 78)), new EcBlocks(20, new EcBlock(2, 78)),
new EcBlocks(18, new EcBlock(4, 31)), new EcBlocks(18, new EcBlock(4, 31)),
new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)), new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)),
new EcBlocks(26, new EcBlock(4, 13)), new EcBlocks(26, new EcBlock(4, 13), new EcBlock(1, 14)),
); );
break; break;

View File

@@ -99,7 +99,7 @@ class Eps extends AbstractRenderer
public function drawBlock($x, $y, $colorId) public function drawBlock($x, $y, $colorId)
{ {
$this->setColor($colorId); $this->setColor($colorId);
$this->eps .= $x . " " . ($this->finalHeight - $y) . " " . $this->blockSize . " " . $this->blockSize . " F\n"; $this->eps .= $x . " " . ($this->finalHeight - $y - $this->blockSize) . " " . $this->blockSize . " " . $this->blockSize . " F\n";
} }
/** /**

View File

@@ -0,0 +1,201 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class BitArrayTest extends TestCase
{
public function testGetSet()
{
$array = new BitArray(33);
for ($i = 0; $i < 33; $i++) {
$this->assertFalse($array->get($i));
$array->set($i);
$this->assertTrue($array->get($i));
}
}
public function testGetNextSet1()
{
$array = new BitArray(32);
for ($i = 0; $i < $array->getSize(); $i++) {
$this->assertEquals($i, 32, '', $array->getNextSet($i));
}
$array = new BitArray(33);
for ($i = 0; $i < $array->getSize(); $i++) {
$this->assertEquals($i, 33, '', $array->getNextSet($i));
}
}
public function testGetNextSet2()
{
$array = new BitArray(33);
for ($i = 0; $i < $array->getSize(); $i++) {
$this->assertEquals($i, $i <= 31 ? 31 : 33, '', $array->getNextSet($i));
}
$array = new BitArray(33);
for ($i = 0; $i < $array->getSize(); $i++) {
$this->assertEquals($i, 32, '', $array->getNextSet($i));
}
}
public function testGetNextSet3()
{
$array = new BitArray(63);
$array->set(31);
$array->set(32);
for ($i = 0; $i < $array->getSize(); $i++) {
if ($i <= 31) {
$expected = 31;
} elseif ($i <= 32) {
$expected = 32;
} else {
$expected = 63;
}
$this->assertEquals($i, $expected, '', $array->getNextSet($i));
}
}
public function testGetNextSet4()
{
$array = new BitArray(63);
$array->set(33);
$array->set(40);
for ($i = 0; $i < $array->getSize(); $i++) {
if ($i <= 33) {
$expected = 33;
} elseif ($i <= 40) {
$expected = 40;
} else {
$expected = 63;
}
$this->assertEquals($i, $expected, '', $array->getNextSet($i));
}
}
public function testGetNextSet5()
{
if (defined('MT_RAND_PHP')) {
mt_srand(0xdeadbeef, MT_RAND_PHP);
} else {
mt_srand(0xdeadbeef);
}
for ($i = 0; $i < 10; $i++) {
$array = new BitArray(mt_rand(1, 100));
$numSet = mt_rand(0, 19);
for ($j = 0; $j < $numSet; $j++) {
$array->set(mt_rand(0, $array->getSize() - 1));
}
$numQueries = mt_rand(0, 19);
for ($j = 0; $j < $numQueries; $j++) {
$query = mt_rand(0, $array->getSize() - 1);
$expected = $query;
while ($expected < $array->getSize() && !$array->get($expected)) {
$expected++;
}
$actual = $array->getNextSet($query);
if ($actual !== $expected) {
$array->getNextSet($query);
}
$this->assertEquals($expected, $actual);
}
}
}
public function testSetBulk()
{
$array = new BitArray(64);
$array->setBulk(32, 0xFFFF0000);
for ($i = 0; $i < 48; $i++) {
$this->assertFalse($array->get($i));
}
for ($i = 48; $i < 64; $i++) {
$this->assertTrue($array->get($i));
}
}
public function testClear()
{
$array = new BitArray(32);
for ($i = 0; $i < 32; $i++) {
$array->set($i);
}
$array->clear();
for ($i = 0; $i < 32; $i++) {
$this->assertFalse($array->get($i));
}
}
public function testGetArray()
{
$array = new BitArray(64);
$array->set(0);
$array->set(63);
$ints = $array->getBitArray();
$this->assertEquals(1, $ints[0]);
$this->assertEquals(0x80000000, $ints[1]);
}
public function testIsRange()
{
$array = new BitArray(64);
$this->assertTrue($array->isRange(0, 64, false));
$this->assertFalse($array->isRange(0, 64, true));
$array->set(32);
$this->assertTrue($array->isRange(32, 33, true));
$array->set(31);
$this->assertTrue($array->isRange(31, 33, true));
$array->set(34);
$this->assertFalse($array->isRange(31, 35, true));
for ($i = 0; $i < 31; $i++) {
$array->set($i);
}
$this->assertTrue($array->isRange(0, 33, true));
for ($i = 33; $i < 64; $i++) {
$array->set($i);
}
$this->assertTrue($array->isRange(0, 64, true));
$this->assertFalse($array->isRange(0, 64, false));
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class BitMatrixTest extends TestCase
{
public function testGetSet()
{
$matrix = new BitMatrix(33);
$this->assertEquals(33, $matrix->getHeight());
for ($y = 0; $y < 33; $y++) {
for ($x = 0; $x < 33; $x++) {
if ($y * $x % 3 === 0) {
$matrix->set($x, $y);
}
}
}
for ($y = 0; $y < 33; $y++) {
for ($x = 0; $x < 33; $x++) {
$this->assertEquals($x * $y % 3 === 0, $matrix->get($x, $y));
}
}
}
public function testSetRegion()
{
$matrix = new BitMatrix(5);
$matrix->setRegion(1, 1, 3, 3);
for ($y = 0; $y < 5; $y++) {
for ($x = 0; $x < 5; $x++) {
$this->assertEquals($y >= 1 && $y <= 3 && $x >= 1 && $x <= 3, $matrix->get($x, $y));
}
}
}
public function testRectangularMatrix()
{
$matrix = new BitMatrix(75, 20);
$this->assertEquals(75, $matrix->getWidth());
$this->assertEquals(20, $matrix->getHeight());
$matrix->set(10, 0);
$matrix->set(11, 1);
$matrix->set(50, 2);
$matrix->set(51, 3);
$matrix->flip(74, 4);
$matrix->flip(0, 5);
$this->assertTrue($matrix->get(10, 0));
$this->assertTrue($matrix->get(11, 1));
$this->assertTrue($matrix->get(50, 2));
$this->assertTrue($matrix->get(51, 3));
$this->assertTrue($matrix->get(74, 4));
$this->assertTrue($matrix->get(0, 5));
$matrix->flip(50, 2);
$matrix->flip(51, 3);
$this->assertFalse($matrix->get(50, 2));
$this->assertFalse($matrix->get(51, 3));
}
public function testRectangularSetRegion()
{
$matrix = new BitMatrix(320, 240);
$this->assertEquals(320, $matrix->getWidth());
$this->assertEquals(240, $matrix->getHeight());
$matrix->setRegion(105, 22, 80, 12);
for ($y = 0; $y < 240; $y++) {
for ($x = 0; $x < 320; $x++) {
$this->assertEquals($y >= 22 && $y < 34 && $x >= 105 && $x < 185, $matrix->get($x, $y));
}
}
}
public function testGetRow()
{
$matrix = new BitMatrix(102, 5);
for ($x = 0; $x < 102; $x++) {
if ($x & 3 === 0) {
$matrix->set($x, 2);
}
}
$array1 = $matrix->getRow(2, null);
$this->assertEquals(102, $array1->getSize());
$array2 = new BitArray(60);
$array2 = $matrix->getRow(2, $array2);
$this->assertEquals(102, $array2->getSize());
$array3 = new BitArray(200);
$array3 = $matrix->getRow(2, $array3);
$this->assertEquals(200, $array3->getSize());
for ($x = 0; $x < 102; $x++) {
$on = ($x & 3 === 0);
$this->assertEquals($on, $array1->get($x));
$this->assertEquals($on, $array2->get($x));
$this->assertEquals($on, $array3->get($x));
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class BitUtilsTest extends TestCase
{
public function testUnsignedRightShift()
{
$this->assertEquals(1, BitUtils::unsignedRightShift(1, 0));
$this->assertEquals(1, BitUtils::unsignedRightShift(10, 3));
$this->assertEquals(536870910, BitUtils::unsignedRightShift(-10, 3));
}
public function testNumberOfTrailingZeros()
{
$this->assertEquals(32, BitUtils::numberOfTrailingZeros(0));
$this->assertEquals(1, BitUtils::numberOfTrailingZeros(10));
$this->assertEquals(0, BitUtils::numberOfTrailingZeros(15));
$this->assertEquals(2, BitUtils::numberOfTrailingZeros(20));
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class ErrorCorrectionLevelTest extends TestCase
{
public function testCreationThrowsNoException()
{
new ErrorCorrectionLevel(ErrorCorrectionLevel::M);
new ErrorCorrectionLevel(ErrorCorrectionLevel::L);
new ErrorCorrectionLevel(ErrorCorrectionLevel::H);
new ErrorCorrectionLevel(ErrorCorrectionLevel::Q);
}
public function testBitsMatchConstants()
{
$this->assertEquals(0x0, ErrorCorrectionLevel::M);
$this->assertEquals(0x1, ErrorCorrectionLevel::L);
$this->assertEquals(0x2, ErrorCorrectionLevel::H);
$this->assertEquals(0x3, ErrorCorrectionLevel::Q);
}
public function testInvalidErrorCorrectionLevelThrowsException()
{
$this->setExpectedException(
'BaconQrCode\Exception\UnexpectedValueException',
'Value not a const in enum BaconQrCode\Common\ErrorCorrectionLevel'
);
new ErrorCorrectionLevel(4);
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class FormatInformationTest extends TestCase
{
protected $maskedTestFormatInfo = 0x2bed;
protected $unmaskedTestFormatInfo;
public function setUp()
{
$this->unmaskedTestFormatInfo = $this->maskedTestFormatInfo ^ 0x5412;
}
public function testBitsDiffering()
{
$this->assertEquals(0, FormatInformation::numBitsDiffering(1, 1));
$this->assertEquals(1, FormatInformation::numBitsDiffering(0, 2));
$this->assertEquals(2, FormatInformation::numBitsDiffering(1, 2));
$this->assertEquals(32, FormatInformation::numBitsDiffering(-1, 0));
}
public function testDecode()
{
$expected = FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo,
$this->maskedTestFormatInfo
);
$this->assertNotNull($expected);
$this->assertEquals(7, $expected->getDataMask());
$this->assertEquals(ErrorCorrectionLevel::Q, $expected->getErrorCorrectionLevel()->get());
$this->assertEquals(
$expected,
FormatInformation::decodeFormatInformation(
$this->unmaskedTestFormatInfo,
$this->maskedTestFormatInfo
)
);
}
public function testDecodeWithBitDifference()
{
$expected = FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo,
$this->maskedTestFormatInfo
);
$this->assertEquals(
$expected,
FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo ^ 0x1,
$this->maskedTestFormatInfo ^ 0x1
)
);
$this->assertEquals(
$expected,
FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo ^ 0x3,
$this->maskedTestFormatInfo ^ 0x3
)
);
$this->assertEquals(
$expected,
FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo ^ 0x7,
$this->maskedTestFormatInfo ^ 0x7
)
);
$this->assertNull(
FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo ^ 0xf,
$this->maskedTestFormatInfo ^ 0xf
)
);
}
public function testDecodeWithMisRead()
{
$expected = FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo,
$this->maskedTestFormatInfo
);
$this->assertEquals(
$expected,
FormatInformation::decodeFormatInformation(
$this->maskedTestFormatInfo ^ 0x3,
$this->maskedTestFormatInfo ^ 0xf
)
);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class ModeTest extends TestCase
{
public function testCreationThrowsNoException()
{
new Mode(Mode::TERMINATOR);
new Mode(Mode::NUMERIC);
new Mode(Mode::ALPHANUMERIC);
new Mode(Mode::BYTE);
new Mode(Mode::KANJI);
}
public function testBitsMatchConstants()
{
$this->assertEquals(0x0, Mode::TERMINATOR);
$this->assertEquals(0x1, Mode::NUMERIC);
$this->assertEquals(0x2, Mode::ALPHANUMERIC);
$this->assertEquals(0x4, Mode::BYTE);
$this->assertEquals(0x8, Mode::KANJI);
}
public function testInvalidModeThrowsException()
{
$this->setExpectedException(
'BaconQrCode\Exception\UnexpectedValueException',
'Value not a const in enum BaconQrCode\Common\Mode'
);
new Mode(10);
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
use SplFixedArray;
class ReedSolomonTest extends TestCase
{
public static function tabProvider()
{
return array(
array(2, 0x7, 1, 1, 1),
array(3, 0xb, 1, 1, 2),
array(4, 0x13, 1, 1, 4),
array(5, 0x25, 1, 1, 6),
array(6, 0x43, 1, 1, 8),
array(7, 0x89, 1, 1, 10),
array(8, 0x11d, 1, 1, 32),
);
}
/**
* @dataProvider tabProvider
* @param integer $symbolSize
* @param integer $generatorPoly
* @param integer $firstRoot
* @param integer $primitive
* @param integer $numRoots
* @return void
*/
public function testCodec($symbolSize, $generatorPoly, $firstRoot, $primitive, $numRoots)
{
if (defined('MT_RAND_PHP')) {
mt_srand(0xdeadbeef, MT_RAND_PHP);
} else {
mt_srand(0xdeadbeef);
}
$blockSize = (1 << $symbolSize) - 1;
$dataSize = $blockSize - $numRoots;
$codec = new ReedSolomonCodec($symbolSize, $generatorPoly, $firstRoot, $primitive, $numRoots, 0);
for ($errors = 0; $errors <= $numRoots / 2; $errors++) {
// Load block with random data and encode
$block = SplFixedArray::fromArray(array_fill(0, $blockSize, 0), false);
for ($i = 0; $i < $dataSize; $i++) {
$block[$i] = mt_rand(0, $blockSize);
}
// Make temporary copy
$tBlock = clone $block;
$parity = SplFixedArray::fromArray(array_fill(0, $numRoots, 0), false);
$errorLocations = SplFixedArray::fromArray(array_fill(0, $blockSize, 0), false);
$erasures = array();
// Create parity
$codec->encode($block, $parity);
// Copy parity into test blocks
for ($i = 0; $i < $numRoots; $i++) {
$block[$i + $dataSize] = $parity[$i];
$tBlock[$i + $dataSize] = $parity[$i];
}
// Seed with errors
for ($i = 0; $i < $errors; $i++) {
$errorValue = mt_rand(1, $blockSize);
do {
$errorLocation = mt_rand(0, $blockSize);
} while ($errorLocations[$errorLocation] !== 0);
$errorLocations[$errorLocation] = 1;
if (mt_rand(0, 1)) {
$erasures[] = $errorLocation;
}
$tBlock[$errorLocation] ^= $errorValue;
}
$erasures = SplFixedArray::fromArray($erasures, false);
// Decode the errored block
$foundErrors = $codec->decode($tBlock, $erasures);
if ($errors > 0 && $foundErrors === null) {
$this->assertEquals($block, $tBlock, 'Decoder failed to correct errors');
}
$this->assertEquals($errors, $foundErrors, 'Found errors do not equal expected errors');
for ($i = 0; $i < $foundErrors; $i++) {
if ($errorLocations[$erasures[$i]] === 0) {
$this->fail(sprintf('Decoder indicates error in location %d without error', $erasures[$i]));
}
}
$this->assertEquals($block, $tBlock, 'Decoder did not correct errors');
}
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Common;
use PHPUnit_Framework_TestCase as TestCase;
class VersionTest extends TestCase
{
public static function versionProvider()
{
$array = array();
for ($i = 1; $i <= 40; $i++) {
$array[] = array($i, 4 * $i + 17);
}
return $array;
}
public static function decodeInformationProvider()
{
return array(
array(7, 0x07c94),
array(12, 0x0c762),
array(17, 0x1145d),
array(22, 0x168c9),
array(27, 0x1b08e),
array(32, 0x209d5),
);
}
/**
* @dataProvider versionProvider
* @param integer $versionNumber
* @param integer $dimension
*/
public function testVersionForNumber($versionNumber, $dimension)
{
$version = Version::getVersionForNumber($versionNumber);
$this->assertNotNull($version);
$this->assertEquals($versionNumber, $version->getVersionNumber());
$this->assertNotNull($version->getAlignmentPatternCenters());
if ($versionNumber > 1) {
$this->assertTrue(count($version->getAlignmentPatternCenters()) > 0);
}
$this->assertEquals($dimension, $version->getDimensionForVersion());
$this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::H)));
$this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::L)));
$this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::M)));
$this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::Q)));
$this->assertNotNull($version->buildFunctionPattern());
}
/**
* @dataProvider versionProvider
* @param integer $versionNumber
* @param integer $dimension
*/
public function testGetProvisionalVersionForDimension($versionNumber, $dimension)
{
$this->assertEquals(
$versionNumber,
Version::getProvisionalVersionForDimension($dimension)->getVersionNumber()
);
}
/**
* @dataProvider decodeInformationProvider
* @param integer $expectedVersion
* @param integer $mask
*/
public function testDecodeVersionInformation($expectedVersion, $mask)
{
$version = Version::decodeVersionInformation($mask);
$this->assertNotNull($version);
$this->assertEquals($expectedVersion, $version->getVersionNumber());
}
}

View File

@@ -0,0 +1,468 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Encoder;
use BaconQrCode\Common\BitArray;
use BaconQrCode\Common\ErrorCorrectionLevel;
use BaconQrCode\Common\Mode;
use BaconQrCode\Common\Version;
use PHPUnit_Framework_TestCase as TestCase;
use ReflectionClass;
use ReflectionMethod;
use SplFixedArray;
class EncoderTest extends TestCase
{
protected $methods = array();
public function setUp()
{
// Hack to be able to test protected methods
$reflection = new ReflectionClass('BaconQrCode\Encoder\Encoder');
foreach ($reflection->getMethods(ReflectionMethod::IS_STATIC) as $method) {
$method->setAccessible(true);
$this->methods[$method->getName()] = $method;
}
}
public function testGetAlphanumericCode()
{
// The first ten code points are numbers.
for ($i = 0; $i < 10; $i++) {
$this->assertEquals($i, $this->methods['getAlphanumericCode']->invoke(null, ord('0') + $i));
}
// The next 26 code points are capital alphabet letters.
for ($i = 10; $i < 36; $i++) {
// The first ten code points are numbers
$this->assertEquals($i, $this->methods['getAlphanumericCode']->invoke(null, ord('A') + $i - 10));
}
// Others are symbol letters.
$this->assertEquals(36, $this->methods['getAlphanumericCode']->invoke(null, ' '));
$this->assertEquals(37, $this->methods['getAlphanumericCode']->invoke(null, '$'));
$this->assertEquals(38, $this->methods['getAlphanumericCode']->invoke(null, '%'));
$this->assertEquals(39, $this->methods['getAlphanumericCode']->invoke(null, '*'));
$this->assertEquals(40, $this->methods['getAlphanumericCode']->invoke(null, '+'));
$this->assertEquals(41, $this->methods['getAlphanumericCode']->invoke(null, '-'));
$this->assertEquals(42, $this->methods['getAlphanumericCode']->invoke(null, '.'));
$this->assertEquals(43, $this->methods['getAlphanumericCode']->invoke(null, '/'));
$this->assertEquals(44, $this->methods['getAlphanumericCode']->invoke(null, ':'));
// Should return -1 for other letters.
$this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, 'a'));
$this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, '#'));
$this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, "\0"));
}
public function testChooseMode()
{
// Numeric mode
$this->assertSame(Mode::NUMERIC, $this->methods['chooseMode']->invoke(null, '0')->get());
$this->assertSame(Mode::NUMERIC, $this->methods['chooseMode']->invoke(null, '0123456789')->get());
// Alphanumeric mode
$this->assertSame(Mode::ALPHANUMERIC, $this->methods['chooseMode']->invoke(null, 'A')->get());
$this->assertSame(Mode::ALPHANUMERIC, $this->methods['chooseMode']->invoke(null, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:')->get());
// 8-bit byte mode
$this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, 'a')->get());
$this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, '#')->get());
$this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, '')->get());
// AIUE in Hiragana in SHIFT-JIS
$this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\x8\xa\x8\xa\x8\xa\x8\xa6")->get());
// Nihon in Kanji in SHIFT-JIS
$this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\x9\xf\x9\x7b")->get());
// Sou-Utso-Byou in Kanji in SHIFT-JIS
$this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\xe\x4\x9\x5\x9\x61")->get());
}
public function testEncode()
{
$qrCode = Encoder::encode('ABCDEF', new ErrorCorrectionLevel(ErrorCorrectionLevel::H));
$expected = "<<\n"
. " mode: ALPHANUMERIC\n"
. " ecLevel: H\n"
. " version: 1\n"
. " maskPattern: 0\n"
. " matrix:\n"
. " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n"
. " 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0\n"
. " 0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1\n"
. " 1 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0\n"
. " 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0\n"
. " 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0\n"
. " 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0\n"
. " 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0\n"
. " 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1\n"
. " 1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0\n"
. " 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 0 1 1\n"
. " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1\n"
. ">>\n";
$this->assertEquals($expected, $qrCode->__toString());
}
public function testSimpleUtf8Eci()
{
$qrCode = Encoder::encode('hello', new ErrorCorrectionLevel(ErrorCorrectionLevel::H), 'utf-8');
$expected = "<<\n"
. " mode: BYTE\n"
. " ecLevel: H\n"
. " version: 1\n"
. " maskPattern: 3\n"
. " matrix:\n"
. " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n"
. " 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 1 1 0 0 1 1 1 1 0 0 0 1 1 0 1 0 0 0 0\n"
. " 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 0\n"
. " 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 1 1 1\n"
. " 1 1 0 0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 1 0\n"
. " 0 0 0 0 1 0 1 1 1 1 0 0 0 0 0 1 0 0 1 0 0\n"
. " 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 0\n"
. " 1 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0\n"
. " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 0\n"
. " 1 0 1 1 1 0 1 0 1 1 0 0 0 1 0 0 1 0 0 0 0\n"
. " 1 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0\n"
. " 1 1 1 1 1 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0\n"
. ">>\n";
$this->assertEquals($expected, $qrCode->__toString());
}
public function testAppendModeInfo()
{
$bits = new BitArray();
$this->methods['appendModeInfo']->invoke(null, new Mode(Mode::NUMERIC), $bits);
$this->assertEquals(' ...X', $bits->__toString());
}
public function testAppendLengthInfo()
{
// 1 letter (1/1), 10 bits.
$bits = new BitArray();
$this->methods['appendLengthInfo']->invoke(
null,
1,
Version::getVersionForNumber(1),
new Mode(Mode::NUMERIC),
$bits
);
$this->assertEquals(' ........ .X', $bits->__toString());
// 2 letters (2/1), 11 bits.
$bits = new BitArray();
$this->methods['appendLengthInfo']->invoke(
null,
2,
Version::getVersionForNumber(10),
new Mode(Mode::ALPHANUMERIC),
$bits
);
$this->assertEquals(' ........ .X.', $bits->__toString());
// 255 letters (255/1), 16 bits.
$bits = new BitArray();
$this->methods['appendLengthInfo']->invoke(
null,
255,
Version::getVersionForNumber(27),
new Mode(Mode::BYTE),
$bits
);
$this->assertEquals(' ........ XXXXXXXX', $bits->__toString());
// 512 letters (1024/2), 12 bits.
$bits = new BitArray();
$this->methods['appendLengthInfo']->invoke(
null,
512,
Version::getVersionForNumber(40),
new Mode(Mode::KANJI),
$bits
);
$this->assertEquals(' ..X..... ....', $bits->__toString());
}
public function testAppendBytes()
{
// Should use appendNumericBytes.
// 1 = 01 = 0001 in 4 bits.
$bits = new BitArray();
$this->methods['appendBytes']->invoke(
null,
'1',
new Mode(Mode::NUMERIC),
$bits,
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->assertEquals(' ...X', $bits->__toString());
// Should use appendAlphaNumericBytes.
// A = 10 = 0xa = 001010 in 6 bits.
$bits = new BitArray();
$this->methods['appendBytes']->invoke(
null,
'A',
new Mode(Mode::ALPHANUMERIC),
$bits,
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->assertEquals(' ..X.X.', $bits->__toString());
// Should use append8BitBytes.
// 0x61, 0x62, 0x63
$bits = new BitArray();
$this->methods['appendBytes']->invoke(
null,
'abc',
new Mode(Mode::BYTE),
$bits,
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->assertEquals(' .XX....X .XX...X. .XX...XX', $bits->__toString());
// Should use appendKanjiBytes.
// 0x93, 0x5f
$bits = new BitArray();
$this->methods['appendBytes']->invoke(
null,
"\x93\x5f",
new Mode(Mode::KANJI),
$bits,
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->assertEquals(' .XX.XX.. XXXXX', $bits->__toString());
// Lower letters such as 'a' cannot be encoded in alphanumeric mode.
$this->setExpectedException(
'BaconQrCode\Exception\WriterException',
'Invalid alphanumeric code'
);
$this->methods['appendBytes']->invoke(
null,
"a",
new Mode(Mode::ALPHANUMERIC),
$bits,
Encoder::DEFAULT_BYTE_MODE_ECODING
);
}
public function testTerminateBits()
{
$bits = new BitArray();
$this->methods['terminateBits']->invoke(null, 0, $bits);
$this->assertEquals('', $bits->__toString());
$bits = new BitArray();
$this->methods['terminateBits']->invoke(null, 1, $bits);
$this->assertEquals(' ........', $bits->__toString());
$bits = new BitArray();
$bits->appendBits(0, 3);
$this->methods['terminateBits']->invoke(null, 1, $bits);
$this->assertEquals(' ........', $bits->__toString());
$bits = new BitArray();
$bits->appendBits(0, 5);
$this->methods['terminateBits']->invoke(null, 1, $bits);
$this->assertEquals(' ........', $bits->__toString());
$bits = new BitArray();
$bits->appendBits(0, 8);
$this->methods['terminateBits']->invoke(null, 1, $bits);
$this->assertEquals(' ........', $bits->__toString());
$bits = new BitArray();
$this->methods['terminateBits']->invoke(null, 2, $bits);
$this->assertEquals(' ........ XXX.XX..', $bits->__toString());
$bits = new BitArray();
$bits->appendBits(0, 1);
$this->methods['terminateBits']->invoke(null, 3, $bits);
$this->assertEquals(' ........ XXX.XX.. ...X...X', $bits->__toString());
}
public function testGetNumDataBytesAndNumEcBytesForBlockId()
{
// Version 1-H.
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 26, 9, 1, 0);
$this->assertEquals(9, $numDataBytes);
$this->assertEquals(17, $numEcBytes);
// Version 3-H. 2 blocks.
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 70, 26, 2, 0);
$this->assertEquals(13, $numDataBytes);
$this->assertEquals(22, $numEcBytes);
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 70, 26, 2, 1);
$this->assertEquals(13, $numDataBytes);
$this->assertEquals(22, $numEcBytes);
// Version 7-H. (4 + 1) blocks.
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 196, 66, 5, 0);
$this->assertEquals(13, $numDataBytes);
$this->assertEquals(26, $numEcBytes);
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 196, 66, 5, 4);
$this->assertEquals(14, $numDataBytes);
$this->assertEquals(26, $numEcBytes);
// Version 40-H. (20 + 61) blocks.
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 0);
$this->assertEquals(15, $numDataBytes);
$this->assertEquals(30, $numEcBytes);
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 20);
$this->assertEquals(16, $numDataBytes);
$this->assertEquals(30, $numEcBytes);
list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 80);
$this->assertEquals(16, $numDataBytes);
$this->assertEquals(30, $numEcBytes);
}
public function testInterleaveWithEcBytes()
{
$dataBytes = SplFixedArray::fromArray(array(32, 65, 205, 69, 41, 220, 46, 128, 236), false);
$in = new BitArray();
foreach ($dataBytes as $dataByte) {
$in->appendBits($dataByte, 8);
}
$outBits = $this->methods['interleaveWithEcBytes']->invoke(null, $in, 26, 9, 1);
$expected = SplFixedArray::fromArray(array(
// Data bytes.
32, 65, 205, 69, 41, 220, 46, 128, 236,
// Error correction bytes.
42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61,
), false);
$out = $outBits->toBytes(0, count($expected));
$this->assertEquals($expected, $out);
}
public function testAppendNumericBytes()
{
// 1 = 01 = 0001 in 4 bits.
$bits = new BitArray();
$this->methods['appendNumericBytes']->invoke(null, '1', $bits);
$this->assertEquals(' ...X', $bits->__toString());
// 12 = 0xc = 0001100 in 7 bits.
$bits = new BitArray();
$this->methods['appendNumericBytes']->invoke(null, '12', $bits);
$this->assertEquals(' ...XX..', $bits->__toString());
// 123 = 0x7b = 0001111011 in 10 bits.
$bits = new BitArray();
$this->methods['appendNumericBytes']->invoke(null, '123', $bits);
$this->assertEquals(' ...XXXX. XX', $bits->__toString());
// 1234 = "123" + "4" = 0001111011 + 0100 in 14 bits.
$bits = new BitArray();
$this->methods['appendNumericBytes']->invoke(null, '1234', $bits);
$this->assertEquals(' ...XXXX. XX.X..', $bits->__toString());
// Empty
$bits = new BitArray();
$this->methods['appendNumericBytes']->invoke(null, '', $bits);
$this->assertEquals('', $bits->__toString());
}
public function testAppendAlphanumericBytes()
{
$bits = new BitArray();
$this->methods['appendAlphanumericBytes']->invoke(null, 'A', $bits);
$this->assertEquals(' ..X.X.', $bits->__toString());
$bits = new BitArray();
$this->methods['appendAlphanumericBytes']->invoke(null, 'AB', $bits);
$this->assertEquals(' ..XXX..X X.X', $bits->__toString());
$bits = new BitArray();
$this->methods['appendAlphanumericBytes']->invoke(null, 'ABC', $bits);
$this->assertEquals(' ..XXX..X X.X..XX. .', $bits->__toString());
// Empty
$bits = new BitArray();
$this->methods['appendAlphanumericBytes']->invoke(null, '', $bits);
$this->assertEquals('', $bits->__toString());
// Invalid data
$this->setExpectedException('BaconQrCode\Exception\WriterException', 'Invalid alphanumeric code');
$bits = new BitArray();
$this->methods['appendAlphanumericBytes']->invoke(null, 'abc', $bits);
}
public function testAppend8BitBytes()
{
// 0x61, 0x62, 0x63
$bits = new BitArray();
$this->methods['append8BitBytes']->invoke(null, 'abc', $bits, Encoder::DEFAULT_BYTE_MODE_ECODING);
$this->assertEquals(' .XX....X .XX...X. .XX...XX', $bits->__toString());
// Empty
$bits = new BitArray();
$this->methods['append8BitBytes']->invoke(null, '', $bits, Encoder::DEFAULT_BYTE_MODE_ECODING);
$this->assertEquals('', $bits->__toString());
}
public function testAppendKanjiBytes()
{
// Numbers are from page 21 of JISX0510:2004
$bits = new BitArray();
$this->methods['appendKanjiBytes']->invoke(null, "\x93\x5f", $bits);
$this->assertEquals(' .XX.XX.. XXXXX', $bits->__toString());
$this->methods['appendKanjiBytes']->invoke(null, "\xe4\xaa", $bits);
$this->assertEquals(' .XX.XX.. XXXXXXX. X.X.X.X. X.', $bits->__toString());
}
public function testGenerateEcBytes()
{
// Numbers are from http://www.swetake.com/qr/qr3.html and
// http://www.swetake.com/qr/qr9.html
$dataBytes = SplFixedArray::fromArray(array(32, 65, 205, 69, 41, 220, 46, 128, 236), false);
$ecBytes = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 17);
$expected = SplFixedArray::fromArray(array(42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61), false);
$this->assertEquals($expected, $ecBytes);
$dataBytes = SplFixedArray::fromArray(array(67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214), false);
$ecBytes = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 18);
$expected = SplFixedArray::fromArray(array(175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187), false);
$this->assertEquals($expected, $ecBytes);
// High-order zero coefficient case.
$dataBytes = SplFixedArray::fromArray(array(32, 49, 205, 69, 42, 20, 0, 236, 17), false);
$ecBytes = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 17);
$expected = SplFixedArray::fromArray(array(0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213), false);
$this->assertEquals($expected, $ecBytes);
}
}

View File

@@ -0,0 +1,281 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Encoder;
use PHPUnit_Framework_TestCase as TestCase;
class MaskUtilTest extends TestCase
{
public static function dataMaskBitProvider()
{
return array(
array(
0,
array(
array(1, 0, 1, 0, 1, 0),
array(0, 1, 0, 1, 0, 1),
array(1, 0, 1, 0, 1, 0),
array(0, 1, 0, 1, 0, 1),
array(1, 0, 1, 0, 1, 0),
array(0, 1, 0, 1, 0, 1),
)
),
array(
1,
array(
array(1, 1, 1, 1, 1, 1),
array(0, 0, 0, 0, 0, 0),
array(1, 1, 1, 1, 1, 1),
array(0, 0, 0, 0, 0, 0),
array(1, 1, 1, 1, 1, 1),
array(0, 0, 0, 0, 0, 0),
)
),
array(
2,
array(
array(1, 0, 0, 1, 0, 0),
array(1, 0, 0, 1, 0, 0),
array(1, 0, 0, 1, 0, 0),
array(1, 0, 0, 1, 0, 0),
array(1, 0, 0, 1, 0, 0),
array(1, 0, 0, 1, 0, 0),
)
),
array(
3,
array(
array(1, 0, 0, 1, 0, 0),
array(0, 0, 1, 0, 0, 1),
array(0, 1, 0, 0, 1, 0),
array(1, 0, 0, 1, 0, 0),
array(0, 0, 1, 0, 0, 1),
array(0, 1, 0, 0, 1, 0),
)
),
array(
4,
array(
array(1, 1, 1, 0, 0, 0),
array(1, 1, 1, 0, 0, 0),
array(0, 0, 0, 1, 1, 1),
array(0, 0, 0, 1, 1, 1),
array(1, 1, 1, 0, 0, 0),
array(1, 1, 1, 0, 0, 0),
)
),
array(
5,
array(
array(1, 1, 1, 1, 1, 1),
array(1, 0, 0, 0, 0, 0),
array(1, 0, 0, 1, 0, 0),
array(1, 0, 1, 0, 1, 0),
array(1, 0, 0, 1, 0, 0),
array(1, 0, 0, 0, 0, 0),
)
),
array(
6,
array(
array(1, 1, 1, 1, 1, 1),
array(1, 1, 1, 0, 0, 0),
array(1, 1, 0, 1, 1, 0),
array(1, 0, 1, 0, 1, 0),
array(1, 0, 1, 1, 0, 1),
array(1, 0, 0, 0, 1, 1),
)
),
array(
7,
array(
array(1, 0, 1, 0, 1, 0),
array(0, 0, 0, 1, 1, 1),
array(1, 0, 0, 0, 1, 1),
array(0, 1, 0, 1, 0, 1),
array(1, 1, 1, 0, 0, 0),
array(0, 1, 1, 1, 0, 0),
)
),
);
}
/**
* @dataProvider dataMaskBitProvider
* @param integer $maskPattern
* @param array $expected
* @return void
*/
public function testGetDatMaskBit($maskPattern, array $expected)
{
for ($x = 0; $x < 6; $x++) {
for ($y = 0; $y < 6; $y++) {
if (($expected[$y][$x] === 1) !== MaskUtil::getDataMaskBit($maskPattern, $x, $y)) {
$this->fail('Data mask bit did not match');
}
}
}
}
public function testApplyMaskPenaltyRule1()
{
$matrix = new ByteMatrix(4, 1);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 0);
$matrix->set(2, 0, 0);
$matrix->set(3, 0, 0);
$this->assertEquals(0, MaskUtil::applyMaskPenaltyRule1($matrix));
// Horizontal
$matrix = new ByteMatrix(6, 1);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 0);
$matrix->set(2, 0, 0);
$matrix->set(3, 0, 0);
$matrix->set(4, 0, 0);
$matrix->set(5, 0, 1);
$this->assertEquals(3, MaskUtil::applyMaskPenaltyRule1($matrix));
$matrix->set(5, 0, 0);
$this->assertEquals(4, MaskUtil::applyMaskPenaltyRule1($matrix));
// Vertical
$matrix = new ByteMatrix(1, 6);
$matrix->set(0, 0, 0);
$matrix->set(0, 1, 0);
$matrix->set(0, 2, 0);
$matrix->set(0, 3, 0);
$matrix->set(0, 4, 0);
$matrix->set(0, 5, 1);
$this->assertEquals(3, MaskUtil::applyMaskPenaltyRule1($matrix));
$matrix->set(0, 5, 0);
$this->assertEquals(4, MaskUtil::applyMaskPenaltyRule1($matrix));
}
public function testApplyMaskPenaltyRule2()
{
$matrix = new ByteMatrix(1, 1);
$matrix->set(0, 0, 0);
$this->assertEquals(0, MaskUtil::applyMaskPenaltyRule2($matrix));
$matrix = new ByteMatrix(2, 2);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 0);
$matrix->set(0, 1, 0);
$matrix->set(1, 1, 1);
$this->assertEquals(0, MaskUtil::applyMaskPenaltyRule2($matrix));
$matrix = new ByteMatrix(2, 2);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 0);
$matrix->set(0, 1, 0);
$matrix->set(1, 1, 0);
$this->assertEquals(3, MaskUtil::applyMaskPenaltyRule2($matrix));
$matrix = new ByteMatrix(3, 3);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 0);
$matrix->set(2, 0, 0);
$matrix->set(0, 1, 0);
$matrix->set(1, 1, 0);
$matrix->set(2, 1, 0);
$matrix->set(0, 2, 0);
$matrix->set(1, 2, 0);
$matrix->set(2, 2, 0);
$this->assertEquals(3 * 4, MaskUtil::applyMaskPenaltyRule2($matrix));
}
public function testApplyMaskPenalty3()
{
// Horizontal 00001011101
$matrix = new ByteMatrix(11, 1);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 0);
$matrix->set(2, 0, 0);
$matrix->set(3, 0, 0);
$matrix->set(4, 0, 1);
$matrix->set(5, 0, 0);
$matrix->set(6, 0, 1);
$matrix->set(7, 0, 1);
$matrix->set(8, 0, 1);
$matrix->set(9, 0, 0);
$matrix->set(10, 0, 1);
$this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
// Horizontal 10111010000
$matrix = new ByteMatrix(11, 1);
$matrix->set(0, 0, 1);
$matrix->set(1, 0, 0);
$matrix->set(2, 0, 1);
$matrix->set(3, 0, 1);
$matrix->set(4, 0, 1);
$matrix->set(5, 0, 0);
$matrix->set(6, 0, 1);
$matrix->set(7, 0, 0);
$matrix->set(8, 0, 0);
$matrix->set(9, 0, 0);
$matrix->set(10, 0, 0);
$this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
// Vertical 00001011101
$matrix = new ByteMatrix(1, 11);
$matrix->set(0, 0, 0);
$matrix->set(0, 1, 0);
$matrix->set(0, 2, 0);
$matrix->set(0, 3, 0);
$matrix->set(0, 4, 1);
$matrix->set(0, 5, 0);
$matrix->set(0, 6, 1);
$matrix->set(0, 7, 1);
$matrix->set(0, 8, 1);
$matrix->set(0, 9, 0);
$matrix->set(0, 10, 1);
$this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
// Vertical 10111010000
$matrix = new ByteMatrix(1, 11);
$matrix->set(0, 0, 1);
$matrix->set(0, 1, 0);
$matrix->set(0, 2, 1);
$matrix->set(0, 3, 1);
$matrix->set(0, 4, 1);
$matrix->set(0, 5, 0);
$matrix->set(0, 6, 1);
$matrix->set(0, 7, 0);
$matrix->set(0, 8, 0);
$matrix->set(0, 9, 0);
$matrix->set(0, 10, 0);
$this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
}
public function testApplyMaskPenaltyRule4()
{
// Dark cell ratio = 0%
$matrix = new ByteMatrix(1, 1);
$matrix->set(0, 0, 0);
$this->assertEquals(100, MaskUtil::applyMaskPenaltyRule4($matrix));
// Dark cell ratio = 5%
$matrix = new ByteMatrix(2, 1);
$matrix->set(0, 0, 0);
$matrix->set(0, 0, 1);
$this->assertEquals(0, MaskUtil::applyMaskPenaltyRule4($matrix));
// Dark cell ratio = 66.67%
$matrix = new ByteMatrix(6, 1);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 1);
$matrix->set(2, 0, 1);
$matrix->set(3, 0, 1);
$matrix->set(4, 0, 1);
$matrix->set(5, 0, 0);
$this->assertEquals(30, MaskUtil::applyMaskPenaltyRule4($matrix));
}
}

View File

@@ -0,0 +1,336 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Encoder;
use BaconQrCode\Common\BitArray;
use BaconQrCode\Common\ErrorCorrectionLevel;
use BaconQrCode\Common\Version;
use PHPUnit_Framework_TestCase as TestCase;
use ReflectionClass;
use ReflectionMethod;
class MatrixUtilTest extends TestCase
{
protected $methods = array();
public function setUp()
{
// Hack to be able to test protected methods
$reflection = new ReflectionClass('BaconQrCode\Encoder\MatrixUtil');
foreach ($reflection->getMethods(ReflectionMethod::IS_STATIC) as $method) {
$method->setAccessible(true);
$this->methods[$method->getName()] = $method;
}
}
public function testToString()
{
$matrix= new ByteMatrix(3, 3);
$matrix->set(0, 0, 0);
$matrix->set(1, 0, 1);
$matrix->set(2, 0, 0);
$matrix->set(0, 1, 1);
$matrix->set(1, 1, 0);
$matrix->set(2, 1, 1);
$matrix->set(0, 2, -1);
$matrix->set(1, 2, -1);
$matrix->set(2, 2, -1);
$expected = " 0 1 0\n 1 0 1\n \n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testClearMatrix()
{
$matrix = new ByteMatrix(2, 2);
MatrixUtil::clearMatrix($matrix);
$this->assertEquals(-1, $matrix->get(0, 0));
$this->assertEquals(-1, $matrix->get(1, 0));
$this->assertEquals(-1, $matrix->get(0, 1));
$this->assertEquals(-1, $matrix->get(1, 1));
}
public function testEmbedBasicPatterns1()
{
$matrix = new ByteMatrix(21, 21);
MatrixUtil::clearMatrix($matrix);
$this->methods['embedBasicPatterns']->invoke(
null,
Version::getVersionForNumber(1),
$matrix
);
$expected = " 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n"
. " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 \n"
. " 0 \n"
. " 1 \n"
. " 0 \n"
. " 1 \n"
. " 0 0 0 0 0 0 0 0 1 \n"
. " 1 1 1 1 1 1 1 0 \n"
. " 1 0 0 0 0 0 1 0 \n"
. " 1 0 1 1 1 0 1 0 \n"
. " 1 0 1 1 1 0 1 0 \n"
. " 1 0 1 1 1 0 1 0 \n"
. " 1 0 0 0 0 0 1 0 \n"
. " 1 1 1 1 1 1 1 0 \n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testEmbedBasicPatterns2()
{
$matrix = new ByteMatrix(25, 25);
MatrixUtil::clearMatrix($matrix);
$this->methods['embedBasicPatterns']->invoke(
null,
Version::getVersionForNumber(2),
$matrix
);
$expected = " 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n"
. " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 \n"
. " 0 \n"
. " 1 \n"
. " 0 \n"
. " 1 \n"
. " 0 \n"
. " 1 \n"
. " 0 \n"
. " 1 1 1 1 1 1 \n"
. " 0 0 0 0 0 0 0 0 1 1 0 0 0 1 \n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 \n"
. " 1 0 0 0 0 0 1 0 1 0 0 0 1 \n"
. " 1 0 1 1 1 0 1 0 1 1 1 1 1 \n"
. " 1 0 1 1 1 0 1 0 \n"
. " 1 0 1 1 1 0 1 0 \n"
. " 1 0 0 0 0 0 1 0 \n"
. " 1 1 1 1 1 1 1 0 \n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testEmbedTypeInfo()
{
$matrix = new ByteMatrix(21, 21);
MatrixUtil::clearMatrix($matrix);
$this->methods['embedTypeInfo']->invoke(
null,
new ErrorCorrectionLevel(ErrorCorrectionLevel::M),
5,
$matrix
);
$expected = " 0 \n"
. " 1 \n"
. " 1 \n"
. " 1 \n"
. " 0 \n"
. " 0 \n"
. " \n"
. " 1 \n"
. " 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0\n"
. " \n"
. " \n"
. " \n"
. " \n"
. " \n"
. " 0 \n"
. " 0 \n"
. " 0 \n"
. " 0 \n"
. " 0 \n"
. " 0 \n"
. " 1 \n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testEmbedVersionInfo()
{
$matrix = new ByteMatrix(21, 21);
MatrixUtil::clearMatrix($matrix);
$this->methods['maybeEmbedVersionInfo']->invoke(
null,
Version::getVersionForNumber(7),
$matrix
);
$expected = " 0 0 1 \n"
. " 0 1 0 \n"
. " 0 1 0 \n"
. " 0 1 1 \n"
. " 1 1 1 \n"
. " 0 0 0 \n"
. " \n"
. " \n"
. " \n"
. " \n"
. " 0 0 0 0 1 0 \n"
. " 0 1 1 1 1 0 \n"
. " 1 0 0 1 1 0 \n"
. " \n"
. " \n"
. " \n"
. " \n"
. " \n"
. " \n"
. " \n"
. " \n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testEmbedDataBits()
{
$matrix = new ByteMatrix(21, 21);
MatrixUtil::clearMatrix($matrix);
$this->methods['embedBasicPatterns']->invoke(
null,
Version::getVersionForNumber(1),
$matrix
);
$bits = new BitArray();
$this->methods['embedDataBits']->invoke(
null,
$bits,
-1,
$matrix
);
$expected = " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
. " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testBuildMatrix()
{
$bytes = array(
32, 65, 205, 69, 41, 220, 46, 128, 236, 42, 159, 74, 221, 244, 169,
239, 150, 138, 70, 237, 85, 224, 96, 74, 219 , 61
);
$bits = new BitArray();
foreach ($bytes as $byte) {
$bits->appendBits($byte, 8);
}
$matrix = new ByteMatrix(21, 21);
MatrixUtil::buildMatrix(
$bits,
new ErrorCorrectionLevel(ErrorCorrectionLevel::H),
Version::getVersionForNumber(1),
3,
$matrix
);
$expected = " 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n"
. " 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n"
. " 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1\n"
. " 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1\n"
. " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0\n"
. " 0 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 0 0\n"
. " 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0\n"
. " 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0\n"
. " 1 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0\n"
. " 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1\n"
. " 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1\n"
. " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0\n"
. " 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0\n"
. " 1 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1\n"
. " 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0\n"
. " 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0\n"
. " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0\n"
. " 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0\n";
$this->assertEquals($expected, $matrix->__toString());
}
public function testFindMsbSet()
{
$this->assertEquals(0, $this->methods['findMsbSet']->invoke(null, 0));
$this->assertEquals(1, $this->methods['findMsbSet']->invoke(null, 1));
$this->assertEquals(8, $this->methods['findMsbSet']->invoke(null, 0x80));
$this->assertEquals(32, $this->methods['findMsbSet']->invoke(null, 0x80000000));
}
public function testCalculateBchCode()
{
// Encoding of type information.
// From Appendix C in JISX0510:2004 (p 65)
$this->assertEquals(0xdc, $this->methods['calculateBchCode']->invoke(null, 5, 0x537));
// From http://www.swetake.com/qr/qr6.html
$this->assertEquals(0x1c2, $this->methods['calculateBchCode']->invoke(null, 0x13, 0x537));
// From http://www.swetake.com/qr/qr11.html
$this->assertEquals(0x214, $this->methods['calculateBchCode']->invoke(null, 0x1b, 0x537));
// Encoding of version information.
// From Appendix D in JISX0510:2004 (p 68)
$this->assertEquals(0xc94, $this->methods['calculateBchCode']->invoke(null, 7, 0x1f25));
$this->assertEquals(0x5bc, $this->methods['calculateBchCode']->invoke(null, 8, 0x1f25));
$this->assertEquals(0xa99, $this->methods['calculateBchCode']->invoke(null, 9, 0x1f25));
$this->assertEquals(0x4d3, $this->methods['calculateBchCode']->invoke(null, 10, 0x1f25));
$this->assertEquals(0x9a6, $this->methods['calculateBchCode']->invoke(null, 20, 0x1f25));
$this->assertEquals(0xd75, $this->methods['calculateBchCode']->invoke(null, 30, 0x1f25));
$this->assertEquals(0xc69, $this->methods['calculateBchCode']->invoke(null, 40, 0x1f25));
}
public function testMakeVersionInfoBits()
{
// From Appendix D in JISX0510:2004 (p 68)
$bits = new BitArray();
$this->methods['makeVersionInfoBits']->invoke(null, Version::getVersionForNumber(7), $bits);
$this->assertEquals(' ...XXXXX ..X..X.X ..', $bits->__toString());
}
public function testMakeTypeInfoBits()
{
// From Appendix D in JISX0510:2004 (p 68)
$bits = new BitArray();
$this->methods['makeTypeInfoBits']->invoke(null, new ErrorCorrectionLevel(ErrorCorrectionLevel::M), 5, $bits);
$this->assertEquals(' X......X X..XXX.', $bits->__toString());
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Encoder;
use BaconQrCode\Common\ErrorCorrectionLevel;
use BaconQrCode\Renderer\Text\Html;
use BaconQrCode\Writer;
use PHPUnit_Framework_TestCase as TestCase;
class HtmlTest extends TestCase
{
/**
* @var Html
*/
protected $renderer;
/**
* @var Writer
*/
protected $writer;
public function setUp()
{
$this->renderer = new Html();
$this->writer = new Writer($this->renderer);
}
public function testBasicRender()
{
$content = 'foobar';
$expected =
'<pre style="font-family: monospace; line-height: 0.65em; letter-spacing: -1px" class="">' .
" \n" .
" ███████ █████ ███████ \n" .
" █ █ █ █ █ █ \n" .
" █ ███ █ ██ █ ███ █ \n" .
" █ ███ █ ███ █ ███ █ \n" .
" █ ███ █ █ █ █ ███ █ \n" .
" █ █ ██ █ █ \n" .
" ███████ █ █ █ ███████ \n" .
" █████ \n" .
" ██ ██ █ ██ █ █ █ \n" .
" ██ ██ █ █ ██ \n" .
" ████████ █ ██ █ ██ \n" .
" ██ █ █ \n" .
" ██ ███ █ █ █ █ \n" .
" █ ███ █ █ \n" .
" ███████ ██ ██████ \n" .
" █ █ ████ ██ \n" .
" █ ███ █ ██ ██ ██ █ ██ \n" .
" █ ███ █ ██ ██ █ ██ \n" .
" █ ███ █ █ █ ██ ██ \n" .
" █ █ ███ ███ ████ \n" .
" ███████ ████ ██ \n" .
" \n" .
'</pre>'
;
$qrCode = Encoder::encode(
$content,
new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->assertEquals($expected, $this->renderer->render($qrCode));
}
public function testSetStyle()
{
$content = 'foobar';
$qrCode = Encoder::encode(
$content,
new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->renderer->setStyle('bar');
$this->assertEquals('bar', $this->renderer->getStyle());
$this->assertStringMatchesFormat('%astyle="bar"%a', $this->renderer->render($qrCode));
}
public function testSetClass()
{
$content = 'foobar';
$qrCode = Encoder::encode(
$content,
new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->renderer->setClass('bar');
$this->assertEquals('bar', $this->renderer->getClass());
$this->assertStringMatchesFormat('%aclass="bar"%a', $this->renderer->render($qrCode));
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
namespace BaconQrCode\Encoder;
use BaconQrCode\Common\ErrorCorrectionLevel;
use BaconQrCode\Renderer\Text\Plain;
use BaconQrCode\Writer;
use PHPUnit_Framework_TestCase as TestCase;
class PlainTest extends TestCase
{
/**
* @var Plain
*/
protected $renderer;
/**
* @var Writer
*/
protected $writer;
public function setUp()
{
$this->renderer = new Plain();
$this->writer = new Writer($this->renderer);
}
public function testBasicRender()
{
$content = 'foobar';
$expected =
" \n" .
" ███████ █████ ███████ \n" .
" █ █ █ █ █ █ \n" .
" █ ███ █ ██ █ ███ █ \n" .
" █ ███ █ ███ █ ███ █ \n" .
" █ ███ █ █ █ █ ███ █ \n" .
" █ █ ██ █ █ \n" .
" ███████ █ █ █ ███████ \n" .
" █████ \n" .
" ██ ██ █ ██ █ █ █ \n" .
" ██ ██ █ █ ██ \n" .
" ████████ █ ██ █ ██ \n" .
" ██ █ █ \n" .
" ██ ███ █ █ █ █ \n" .
" █ ███ █ █ \n" .
" ███████ ██ ██████ \n" .
" █ █ ████ ██ \n" .
" █ ███ █ ██ ██ ██ █ ██ \n" .
" █ ███ █ ██ ██ █ ██ \n" .
" █ ███ █ █ █ ██ ██ \n" .
" █ █ ███ ███ ████ \n" .
" ███████ ████ ██ \n" .
" \n"
;
$qrCode = Encoder::encode(
$content,
new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->assertEquals($expected, $this->renderer->render($qrCode));
}
public function testBasicRenderNoMargins()
{
$content = 'foobar';
$expected =
"███████ █████ ███████\n" .
"█ █ █ █ █ █\n" .
"█ ███ █ ██ █ ███ █\n" .
"█ ███ █ ███ █ ███ █\n" .
"█ ███ █ █ █ █ ███ █\n" .
"█ █ ██ █ █\n" .
"███████ █ █ █ ███████\n" .
" █████ \n" .
"██ ██ █ ██ █ █ █\n" .
" ██ ██ █ █ ██ \n" .
" ████████ █ ██ █ ██\n" .
" ██ █ █\n" .
" ██ ███ █ █ █ █\n" .
" █ ███ █ █ \n" .
"███████ ██ ██████ \n" .
"█ █ ████ ██ \n" .
"█ ███ █ ██ ██ ██ █ ██\n" .
"█ ███ █ ██ ██ █ ██ \n" .
"█ ███ █ █ █ ██ ██\n" .
"█ █ ███ ███ ████\n" .
"███████ ████ ██ \n"
;
$qrCode = Encoder::encode(
$content,
new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->renderer->setMargin(0);
$this->assertEquals(0, $this->renderer->getMargin());
$this->assertEquals($expected, $this->renderer->render($qrCode));
}
public function testBasicRenderCustomChar()
{
$content = 'foobar';
$expected =
"-----------------------\n" .
"-#######-#####-#######-\n" .
"-#-----#--#-#--#-----#-\n" .
"-#-###-#--##---#-###-#-\n" .
"-#-###-#--###--#-###-#-\n" .
"-#-###-#---#-#-#-###-#-\n" .
"-#-----#----##-#-----#-\n" .
"-#######-#-#-#-#######-\n" .
"---------#####---------\n" .
"-##-##-#--##-#-#-----#-\n" .
"----##----##-#-#-##----\n" .
"--########-#--##-#--##-\n" .
"-----------##------#-#-\n" .
"--##--###--#---#--#--#-\n" .
"---------#-###----#-#--\n" .
"-#######--##-######----\n" .
"-#-----#---####---##---\n" .
"-#-###-#-##-##-##-#-##-\n" .
"-#-###-#-##-##--#-##---\n" .
"-#-###-#---#---#-##-##-\n" .
"-#-----#-###--###-####-\n" .
"-#######-####---##-----\n" .
"-----------------------\n"
;
$qrCode = Encoder::encode(
$content,
new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
Encoder::DEFAULT_BYTE_MODE_ECODING
);
$this->renderer->setFullBlock('#');
$this->renderer->setEmptyBlock('-');
$this->assertEquals('#', $this->renderer->getFullBlock());
$this->assertEquals('-', $this->renderer->getEmptyBlock());
$this->assertEquals($expected, $this->renderer->render($qrCode));
}
}

View File

@@ -0,0 +1,10 @@
<?php
/**
* BaconQrCode
*
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
* @copyright 2013 Ben 'DASPRiD' Scholzen
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
*/
require_once __DIR__ . '/../autoload_register.php';

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./bootstrap.php" colors="true">
<testsuite name="BaconQrCode">
<directory>.</directory>
</testsuite>
<filter>
<whitelist>
<directory suffix=".php">../src/</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -379,9 +379,9 @@ class ClassLoader
$subPath = substr($subPath, 0, $lastPos); $subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\'; $search = $subPath.'\\';
if (isset($this->prefixDirsPsr4[$search])) { if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) { foreach ($this->prefixDirsPsr4[$search] as $dir) {
$length = $this->prefixLengthsPsr4[$first][$search]; if (file_exists($file = $dir . $pathEnd)) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file; return $file;
} }
} }

View File

@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInitf3438a4bfc092aad40a104edf0a3eb02 class ComposerAutoloaderInitda370287ab6d5b8a28188afe08f659c5
{ {
private static $loader; private static $loader;
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitf3438a4bfc092aad40a104edf0a3eb02
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderInitf3438a4bfc092aad40a104edf0a3eb02', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInitda370287ab6d5b8a28188afe08f659c5', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitf3438a4bfc092aad40a104edf0a3eb02', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInitda370287ab6d5b8a28188afe08f659c5', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php'; require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitf3438a4bfc092aad40a104edf0a3eb02::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInitda370287ab6d5b8a28188afe08f659c5::getInitializer($loader));
} else { } else {
$map = require __DIR__ . '/autoload_namespaces.php'; $map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) { foreach ($map as $namespace => $path) {

View File

@@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInitf3438a4bfc092aad40a104edf0a3eb02 class ComposerStaticInitda370287ab6d5b8a28188afe08f659c5
{ {
public static $prefixLengthsPsr4 = array ( public static $prefixLengthsPsr4 = array (
'R' => 'R' =>
@@ -55,9 +55,9 @@ class ComposerStaticInitf3438a4bfc092aad40a104edf0a3eb02
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitf3438a4bfc092aad40a104edf0a3eb02::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInitda370287ab6d5b8a28188afe08f659c5::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitf3438a4bfc092aad40a104edf0a3eb02::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitda370287ab6d5b8a28188afe08f659c5::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitf3438a4bfc092aad40a104edf0a3eb02::$prefixesPsr0; $loader->prefixesPsr0 = ComposerStaticInitda370287ab6d5b8a28188afe08f659c5::$prefixesPsr0;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@@ -1,4 +1,52 @@
[ [
{
"name": "bacon/bacon-qr-code",
"version": "1.0.3",
"version_normalized": "1.0.3.0",
"source": {
"type": "git",
"url": "https://github.com/Bacon/BaconQrCode.git",
"reference": "5a91b62b9d37cee635bbf8d553f4546057250bee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/5a91b62b9d37cee635bbf8d553f4546057250bee",
"reference": "5a91b62b9d37cee635bbf8d553f4546057250bee",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": "^5.4|^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
},
"suggest": {
"ext-gd": "to generate QR code images"
},
"time": "2017-10-17T09:59:25+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"BaconQrCode": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Ben Scholzen 'DASPRiD'",
"email": "mail@dasprids.de",
"homepage": "http://www.dasprids.de",
"role": "Developer"
}
],
"description": "BaconQrCode is a QR code generator for PHP.",
"homepage": "https://github.com/Bacon/BaconQrCode"
},
{ {
"name": "composer/semver", "name": "composer/semver",
"version": "1.4.2", "version": "1.4.2",
@@ -63,6 +111,115 @@
"versioning" "versioning"
] ]
}, },
{
"name": "fguillot/picofeed",
"version": "v0.1.37",
"version_normalized": "0.1.37.0",
"source": {
"type": "git",
"url": "https://github.com/miniflux/picoFeed.git",
"reference": "402b7f07629577e7929625e78bc88d3d5831a22d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/miniflux/picoFeed/zipball/402b7f07629577e7929625e78bc88d3d5831a22d",
"reference": "402b7f07629577e7929625e78bc88d3d5831a22d",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"php": ">=5.3.0",
"zendframework/zendxml": "^1.0"
},
"require-dev": {
"phpdocumentor/reflection-docblock": "2.0.4",
"phpunit/phpunit": "4.8.26",
"symfony/yaml": "2.8.7"
},
"suggest": {
"ext-curl": "PicoFeed will use cURL if present"
},
"time": "2017-11-02T03:20:36+00:00",
"bin": [
"picofeed"
],
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"PicoFeed": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frédéric Guillot"
}
],
"description": "Modern library to handle RSS/Atom feeds",
"homepage": "https://github.com/miniflux/picoFeed",
"abandoned": true
},
{
"name": "robthree/twofactorauth",
"version": "1.6.1",
"version_normalized": "1.6.1.0",
"source": {
"type": "git",
"url": "https://github.com/RobThree/TwoFactorAuth.git",
"reference": "a77e7d822343bb88112baef808839cfae7bc5abb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/a77e7d822343bb88112baef808839cfae7bc5abb",
"reference": "a77e7d822343bb88112baef808839cfae7bc5abb",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "@stable"
},
"time": "2017-11-06T17:55:56+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"RobThree\\Auth\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Janssen",
"homepage": "http://robiii.me",
"role": "Developer"
}
],
"description": "Two Factor Authentication",
"homepage": "https://github.com/RobThree/TwoFactorAuth",
"keywords": [
"Authentication",
"MFA",
"Multi Factor Authentication",
"Two Factor Authentication",
"authenticator",
"authy",
"php",
"tfa"
]
},
{ {
"name": "zendframework/zendxml", "name": "zendframework/zendxml",
"version": "1.0.2", "version": "1.0.2",
@@ -109,157 +266,5 @@
"xml", "xml",
"zf2" "zf2"
] ]
},
{
"name": "fguillot/picofeed",
"version": "v0.1.35",
"version_normalized": "0.1.35.0",
"source": {
"type": "git",
"url": "https://github.com/miniflux/picoFeed.git",
"reference": "3a27b47de31eedec075c719f961783c5db7a7b08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/miniflux/picoFeed/zipball/3a27b47de31eedec075c719f961783c5db7a7b08",
"reference": "3a27b47de31eedec075c719f961783c5db7a7b08",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"php": ">=5.3.0",
"zendframework/zendxml": "^1.0"
},
"require-dev": {
"phpdocumentor/reflection-docblock": "2.0.4",
"phpunit/phpunit": "4.8.26",
"symfony/yaml": "2.8.7"
},
"suggest": {
"ext-curl": "PicoFeed will use cURL if present"
},
"time": "2017-06-20T22:54:47+00:00",
"bin": [
"picofeed"
],
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"PicoFeed": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frédéric Guillot"
}
],
"description": "Modern library to handle RSS/Atom feeds",
"homepage": "https://github.com/miniflux/picoFeed"
},
{
"name": "robthree/twofactorauth",
"version": "1.6",
"version_normalized": "1.6.0.0",
"source": {
"type": "git",
"url": "https://github.com/RobThree/TwoFactorAuth.git",
"reference": "5093ab230cd8f1296d792afb6a49545f37e7fd5a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/5093ab230cd8f1296d792afb6a49545f37e7fd5a",
"reference": "5093ab230cd8f1296d792afb6a49545f37e7fd5a",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "@stable"
},
"time": "2017-02-17T15:24:54+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"RobThree\\Auth\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Janssen",
"homepage": "http://robiii.me",
"role": "Developer"
}
],
"description": "Two Factor Authentication",
"homepage": "https://github.com/RobThree/TwoFactorAuth",
"keywords": [
"Authentication",
"MFA",
"Multi Factor Authentication",
"Two Factor Authentication",
"authenticator",
"authy",
"php",
"tfa"
]
},
{
"name": "bacon/bacon-qr-code",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/Bacon/BaconQrCode.git",
"reference": "031a2ce68c5794064b49d11775b2daf45c96e21c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/031a2ce68c5794064b49d11775b2daf45c96e21c",
"reference": "031a2ce68c5794064b49d11775b2daf45c96e21c",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-gd": "to generate QR code images"
},
"time": "2016-01-09T22:55:35+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"BaconQrCode": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Ben Scholzen 'DASPRiD'",
"email": "mail@dasprids.de",
"homepage": "http://www.dasprids.de",
"role": "Developer"
}
],
"description": "BaconQrCode is a QR code generator for PHP.",
"homepage": "https://github.com/Bacon/BaconQrCode"
} }
] ]

View File

@@ -4,7 +4,7 @@ return array(
'%.*%' => array( '%.*%' => array(
'test_url' => 'http://www.nytimes.com/2011/05/15/world/middleeast/15prince.html', 'test_url' => 'http://www.nytimes.com/2011/05/15/world/middleeast/15prince.html',
'body' => array( 'body' => array(
'//div[@class="articleBody"]', '//p[contains(@class, "story-content")] | //div[@class="image"]',
), ),
) )
) )

View File

@@ -0,0 +1,16 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://24.hu/belfold/2017/10/20/millios-lehuzasok-miatt-razziaztak-egy-budapesti-barban-videoval/',
'body' => array(
'//div[@class="post-title-wrapper"]/h1',
'//div[@class="post-header-wrapper has-img"]/img',
'//div[@class="post-body"]'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,19 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://444.hu/2017/10/20/tulszamlazo-helyen-utottek-rajta-budapest-belvarosaban',
'body' => array(
'//div[@id="headline"]/h1',
'//article'
),
'strip' => array(
'//article/footer',
'//article/div[@class="jeti-roadblock ad"]',
'//figcaption',
'//noscript',
'//ul[@class="widget-stream-items"]'
)
),
),
);

View File

@@ -0,0 +1,16 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://888.hu/article-a-budapesti-szocik-nem-szeretik-a-videki-szocikat',
'body' => array(
'//div[@id="cikkholder"]/h1',
'//div[@class="maincontent8"]'
),
'strip' => array(
'//div[@class="AdW"]',
'//h1[@class="olvastadmar"]'
)
),
),
);

View File

@@ -0,0 +1,18 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.atv.hu/belfold/20171020-tobb-millio-forintot-csalt-ki-egy-idos-ferfitol-a-budapesti-no',
'body' => array(
'//article'
),
'strip' => array(
'//span[@class="date"]',
'//div[@class="fb-like db_iframe_widget"]',
'//div[@class="ad-wrapper dashed-border"]',
'//div[@class="footer-meta-wrapper"]',
'//div[@class="image-wrapper "]'
)
),
),
);

View File

@@ -0,0 +1,14 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://coinwelt.de/2017/08/bitcache-kreierer-kim-dotcom-bietet-arbeitsplaetze-fuer-blockchain-goetter/',
'body' => array(
'//div[@class="post-inner"]//div[@class="entry"]',
),
'strip' => array(
'//div[contains(@class, "shariff")]',
),
),
),
);

View File

@@ -2,27 +2,17 @@
return array( return array(
'grabber' => array( 'grabber' => array(
'%.*%' => array( '%.*%' => array(
'test_url' => 'http://www.crash.net/motogp/interview/247550/1/exclusive-andrea-dovizioso-interview.html', 'test_url' => 'http://www.crash.net/motogp/news/885102/1/dovizioso-mugello-win-was-catalyst-for-title-challenge',
'body' => array( 'body' => array(
'//div[@id="content"]', '//*[@id="block-system-main"]',
), ),
'strip' => array( 'strip' => array(
'//script', '//script',
'//style', '//style',
'//*[@title="Social Networking"]', '//*[@class="social-bar"]',
'//*[@class="crash-ad2"]', '//*[@id="below-headline-image-ad"]',
'//*[@class="clearfix"]', '//*[@class="advert-"]',
'//*[@class="crash-ad2"]',
'//*[contains(@id, "divCB"]',
'//*[@class="pnlComment"]',
'//*[@class="comments-tabs"]',
'//*[contains(@class, "ad-twocol"]',
'//*[@class="stories-list"]',
'//*[contains(@class, "btn")]',
'//*[@class="content"]',
'//h3',
), ),
), ),
), ),
); );

View File

@@ -0,0 +1,15 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.gamechannel.hu/cikk/hirblock/a-legacy-of-kain-feltamasztasara-keszul-a-crystal-dynamics',
'body' => array(
'//div[@class="post"]/div[@class="entry"]'
),
'strip' => array(
'//div[@class="valaszto"]',
'//center/blockquote' // as we can't grab iframe here
)
),
),
);

View File

@@ -0,0 +1,17 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://www.gamestar.hu/hir/horizon-zero-dawn-the-frozen-wilds-vedjegy-239019.html',
'body' => array(
'//article/header/h1',
'//div[@class="section section-2-3"]/div[@class="image"]/img',
'//article/p[@class="lead"]',
'//article/div[@class="content"]'
),
'strip' => array(
'//div[@class="ad ad-article-inside"]'
)
),
),
);

View File

@@ -0,0 +1,22 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://gondola.hu/hirek/213754-A_budapesti_fejlesztesek_kerdese_mar_nem_zsakbamacska.html',
'body' => array(
'//div[@id="cikk"]/div[@class="cim"]',
'//br[1]',
'//div[@class="alcim"]',
'//div[@class="lead"]',
'//div[@class="szoveg"]'
),
'strip' => array(
'//div[@class="ikonok"]',
'//div[@class="linkekblokk"]',
'//div[@id="billboardbanner"]',
'//div[@class="szerzo"]',
'//div[@class="kulcsszavak"]'
)
),
),
);

View File

@@ -6,6 +6,7 @@ return array(
'body' => array( 'body' => array(
'//div[@class="meldung_wrapper"]', '//div[@class="meldung_wrapper"]',
'//div[@class="artikel_content"]', '//div[@class="artikel_content"]',
'//div[@class="article-content"]',
), ),
), ),
), ),

View File

@@ -0,0 +1,14 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://hirek.prim.hu/cikk/2017/10/02/atadtak_a_6_fenntarthatosagi_sajtodijat',
'body' => array(
'//div[@class="boxbody article_box"]/h2',
'//div[@class="text_body"]'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,17 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://hvg.hu/brandchannel/mastercardbch_20171006_Egyetlen_mobillal_erintettuk_Budapest_legjobb_gasztrohelyeit',
'body' => array(
'//div[@class="article-title article-title"]',
'//div[@class="article-cover-img"]',
'//div[@class="article-main"]'
),
'strip' => array(
'//figcaption',
'//div[@class="article-info byline"]'
)
),
),
);

View File

@@ -0,0 +1,18 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://www.idokep.hu/hirek/4-es-erossegu-tajfun-tart-japan-fele',
'body' => array(
'//div[@class="cikk-title"]/h3',
'//div[@class="lead"]',
'//div[@class="atvett_tartalom"]',
'//div[@class="cikk-tartalom"]'
),
'strip' => array(
'//div[@class="cimkes-doboz"]',
'//div[@class="komment-wrap"]'
)
),
),
);

View File

@@ -0,0 +1,29 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://index.hu/mindekozben/poszt/2017/10/20/art_deco_budapest_varosnezo_zsebkonyv_bolla_zoltan/',
'body' => array(
'//div[@class="mindenkozben_post_content content"]',
'//div[@id="content"]'
),
'strip' => array(
'//div[@class="topszponzor_wrapper"]',
'//ul[@class="cikk-cimkek"]',
'//div[@class="author-share-date-container"]',
'//div[@class="pp-list"]',
'//div[@class="social-stripe cikk-bottom-box"]',
'//div[@class="cikk-bottom-text-ad"]',
'//a[@name="hozzaszolasok"]',
'//div[@class="cikk-vegi-ajanlo-reklamok-container"]',
'//div[@id="comments"]',
'//div[@class="comments"]',
'//div[@class="linkpreview-box bekezdes_utan"]',
'//div[@class="lapozo"]',
'//div[@class="szelso-jobb"]',
'//div[@class="social cikk-bottom-box"]',
'//input'
)
),
),
);

View File

@@ -0,0 +1,25 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://inforadio.hu/belfold/2017/10/20/fontos_valtozas_vegleg_lezarnak_tobb_villamosatjarot_budapesten/',
'body' => array(
'//div[@class="content-title"]',
'//div[@class="szelso-jobb-lead_container"]',
'//div[@class="cikk-torzs"]'
),
'strip' => array(
'//div[@id="microsite_microsite"]',
'//div[@class="cikk-bottom-text-ad"]',
'//div[@class="social-stripe_container"]',
'//div[@class="facebook-like-box"]',
'//div[@class="rovat sargabg rovatdobozcim"]',
'//div[@class="m-okosradio_magazin arenaMagazineItem"]',
'//header[@class="m-okosradio_header"]',
'//div[@class="m-okosradio_elo"]',
'//div[@class="m-okosradio_container"]',
'//form'
)
),
),
);

View File

@@ -0,0 +1,17 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.kisalfold.hu/szorakozas/egy_15_eves_srac_szuntetheti_meg_a_wc-parat_budapesten/2536699/',
'body' => array(
'//header[@class="single-article__header"]/h1',
'//header[@class="single-article__header"]/h2',
'//figure[@class="single-article__image"]/img',
'//div[@class="single-article__content"]/div[@id="single-article__lead"]',
'//div[@id="article_text"]'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,14 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://kiszamolo.hu/30-eve-volt-a-fekete-hetfo/',
'body' => array(
'//article/h2',
'//article/div[@class="entry clearfix"]/p'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,16 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.linux-magazin.de/Ausgaben/2017/09/AWS-Alternativen',
'body' => array(
'//div[@class="attribute-content"]/div[@class="attribute-intro"]',
'(//div[@class="attribute-image"])[1]',
'//div[@itemprop="articleBody"]',
),
'strip' => array(
'//p[@class="attribute-advice"]',
)
)
)
);

View File

@@ -0,0 +1,11 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.maclife.de/news/neue-farbe-iphone-8-kommt-blush-gold-10094817.html',
'body' => array(
'//div[contains(@class, "article_wrapper")]/p | //div[contains(@class, "article_wrapper")]/h2 | //div[@class="gallery"]//figure | //div[contains(@class, "gallery_single")]//figure',
)
)
)
);

View File

@@ -0,0 +1,21 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.magyarkurir.hu/hirek/a-vilagszerte-ismert-dicsoito-csapat-hillsong-young-free-lep-fel-budapesten',
'body' => array(
'//div[@class="behuzas"]'
),
'strip' => array(
'//div[@class="ikonsav"]',
'//p[@class="copyright"]',
'//div[@class="cimkek"]',
'//div[@id="footerbanner"]',
'//div[@class="rovat sargabg rovatdobozcim"]',
'//div[@class="rovatdoboz"]',
'//a[contains(., "Own")]',
'//a[@class="fblink"]'
)
),
),
);

View File

@@ -0,0 +1,14 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://mno.hu/kulfold/elnokot-valasztanak-szloveniaban-2422840',
'body' => array(
'//div[@class="header"]/h1',
'//div[@class="content hircikk clearfix"]/p'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,18 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.nlcafe.hu/ezvan/20171021/nyugdijas-drogdilert-fogtak-a-ferencvarosi-rendorok/',
'body' => array(
'//div[@class="single-title"]',
'//div[@class="single-excerpt"]',
'//div[@class="single-post-container-content"]/p',
'//div[@class="single-post-container-content"]/div'
),
'strip' => array(
'//div[@class="widget-container related-articles bigdata-widget related-full"]',
'//div[@class="banner-container clear-banner-row clearfix"]'
)
),
),
);

View File

@@ -0,0 +1,13 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://www.onlinekosten.de/news/android-8-0-die-neuen-features-im-ueberblick_209619.html?utm_source=rss&utm_medium=feed&utm_campaign=android-8-0-die-neuen-features-im-ueberblick',
'body' => array(
'//p[@class="cms-widget_article_lead"]',
'//img[@class="bec_img"]',
'//div[@class="cms-widget_article_body"]',
),
)
)
);

View File

@@ -0,0 +1,14 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.origo.hu/itthon/20171019-hamisan-tanuskodott-az-ugyved-ezert-nem-praktizalhat.html',
'body' => array(
'//header[@id="article-head"]/h1',
'//article[@id="article-center"]'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,16 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.pcgameshardware.de/Dragon-Age-Thema-259929/News/Plaene-fuer-Teil-4-und-5-der-Serie-1235682/',
'body' => array(
'//p[@class="introText"]',
'//figure[contains(@class, "articleBigTeaser")]',
'//div[@id="articleTextBody"]//p | //div[@id="articleTextBody"]//h2[@class="anchorHeadline"]',
),
'strip' => array(
'//p[@class="introText"]//time',
)
)
)
);

View File

@@ -0,0 +1,15 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.portfolio.hu/gazdasag/mennybe-vagy-pokolba-megy-ma-a-cseh-trump.265833.html',
'body' => array(
'//div[@id="cikk"]/h1',
'//div[@class="smscontent"]'
),
'strip' => array(
'//div[@class="traderhirdetes ga_viewanalytics"]'
)
),
),
);

View File

@@ -4,7 +4,10 @@ return array(
'%.*%' => array( '%.*%' => array(
'test_url' => 'http://www.spiegel.de/politik/ausland/afrika-angola-geht-gegen-islam-vor-und-schliesst-moscheen-a-935788.html', 'test_url' => 'http://www.spiegel.de/politik/ausland/afrika-angola-geht-gegen-islam-vor-und-schliesst-moscheen-a-935788.html',
'body' => array( 'body' => array(
'//div[contains(@class, "article-section")]', '//div[@class="spArticleContent"]/p | //div[@class="spArticleContent"]//img[@class="spResponsiveImage "]',
),
'strip' => array(
'//div[@class="author-details"]',
), ),
), ),
), ),

View File

@@ -5,7 +5,7 @@ return array(
'test_url' => 'http://techcrunch.com/2013/08/31/indias-visa-maze/', 'test_url' => 'http://techcrunch.com/2013/08/31/indias-visa-maze/',
'body' => array( 'body' => array(
'//div[contains(@class, "media-container")]', '//div[contains(@class, "media-container")]',
'//div[@class="body-copy"]', '//div[contains(@class, "article-entry")]',
), ),
'strip' => array( 'strip' => array(
'//*[contains(@class, "module-crunchbase")]', '//*[contains(@class, "module-crunchbase")]',

View File

@@ -0,0 +1,18 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://www.theregister.co.uk/2017/10/21/purism_cleanses_laptops_of_intel_management_engine/',
'body' => array(
'//div[@id="article"]',
),
'strip' => array(
'//div[@class="byline_and_share"]',
'//div[@class="social_btns alt_colour dcl"]',
'//div[@class="promo_article"]',
'//div[@id="article_body_btm"]',
'//p[@class="wptl btm"]'
)
),
),
);

View File

@@ -0,0 +1,16 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://www.theverge.com/2017/10/20/16512178/alphabet-project-loon-puerto-rico-lte-balloons-disaster-relief-connectivity',
'body' => array(
'//div[@class="c-entry-hero__header-wrap"]',
'//span[@class="e-image__inner"]',
'//div[@class="c-entry-content"]',
),
'strip' => array(
'//div[@class="c-entry-hero__meta"]',
)
),
),
);

View File

@@ -0,0 +1,18 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://totalcar.hu/tesztek/2017/10/21/veteran_fiat-abarth_1000tc_1968/',
'body' => array(
'//div[@class="content-title"]',
'//div[@class="lead-container"]/div[@class="lead"]',
'//div[@class="cikk-torzs"]'
),
'strip' => array(
'//span[@class="gallery_title newline"]',
'//div[@class="social-stripe cikk-bottom-box"]',
'//div[@class="cikk-bottom-text-ad"]'
)
),
),
);

View File

@@ -0,0 +1,15 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.tozsdeforum.hu/szemelyes-penzugyek/napi-penzugyek/ezek-a-legnepszerubb-turistacelpontok-voltal-mar-mindenhol-87181.html',
'body' => array(
'//header/h1',
'//div[@class="title_img"]',
'//article/div[@class="tf-post"]/div[@class="p"]/p|//article/div[@class="tf-post"]/div[@class="p"]/h3|//article/div[@class="tf-post"]/div[@class="p"]/blockquote'
),
'strip' => array(
)
),
),
);

View File

@@ -0,0 +1,17 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://travelo.hu/csaladbarat/2017/10/20/mar_csak_egy_het_es_kezdodik_az_oszi_szunet/',
'body' => array(
'//div[@id="content"]/h1',
'//div[@id="kopf"]',
'//div[@id="szoveg"]'
),
'strip' => array(
'//div[@class="goAdverticum"]',
'//h1[@class="border"]'
)
),
),
);

View File

@@ -0,0 +1,20 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://tutorialzine.com/2017/10/15-interesting-javascript-and-css-libraries-for-october-2017',
'body' => array(
'//article'
),
'strip' => array(
'//div[@class="article__header"]',
'//div[@class="article__share"]',
'//div[@class="article__footer"]',
'//div[@id="article__related-articles"]',
'//div[@class="webappstudio-animation"]',
'//div[@class="ad-container adsbygoogle hidden-xs hidden-sm"]',
'//script'
)
),
),
);

View File

@@ -0,0 +1,20 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'http://www.vezess.hu/hirek/2017/10/20/audi-a7-2018-bemutato/',
'body' => array(
'//article[@id="news"]/h1',
'//article[@id="news"]/h2',
'//article[@id="news"]/p[@class="lead"]',
'//article[@id="news"]/p[@class="main-pic responsive-img-container"]',
'//div[@class="article-body"]'
),
'strip' => array(
'//div[@class="info-bar"]',
'//ul[@class="breadcrumb"]',
'//div[@class="embed-link ce_widget"]'
)
),
),
);

View File

@@ -0,0 +1,19 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://zarojel.hu/meg-egyszer-a-foldi-ugyrol-is/',
'body' => array(
'//div[@class="entry-category"]/h1',
'//div[@class="entry-content"]/div[@class="vc_row wpb_row vc_row-fluid"]'
),
'strip' => array(
'//ins[@class="adsbygoogle"]',
'//script',
'//figcaption',
'//p[contains(text(),"Kapcsolódó")]',
'//div[@class="wpb_wrapper"]/p[@class="entry-title"]'
)
),
),
);

View File

@@ -0,0 +1,17 @@
<?php
return array(
'grabber' => array(
'%.*%' => array(
'test_url' => 'https://zoom.hu/2017/10/20/mar-nem-nyomoznak-a-vegrehajtok-botranyai-miatt',
'body' => array(
'//div[@class="title-wrapper"]/h1',
'//div[@class="entry-excerpt"]',
'//div[@class="thumbnail-wrapper"]',
'//div[@id="entry-content-id"]'
),
'strip' => array(
'//div[@class="place first normal"]'
)
),
),
);

189
vendor/robthree/twofactorauth/.gitignore vendored Normal file
View File

@@ -0,0 +1,189 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Composer
/vendor
# .vs
.vs/

View File

@@ -0,0 +1,18 @@
language: php
dist: trusty
matrix:
include:
- php: 5.3
dist: precise
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm
script:
- if [[ "$TRAVIS_PHP_VERSION" == '5.6' ]]; then phpunit --coverage-text tests ; fi

View File

@@ -10,7 +10,7 @@ PHP library for [two-factor (or multi-factor) authentication](http://en.wikipedi
## Requirements ## Requirements
* Tested on PHP 5.3, 5.4, 5.5 and 5.6, 7 and HHVM * Tested on PHP 5.3, 5.4, 5.5 and 5.6, 7.0, 7.1 and HHVM
* [cURL](http://php.net/manual/en/book.curl.php) when using the provided `GoogleQRCodeProvider` (default), `QRServerProvider` or `QRicketProvider` but you can also provide your own QR-code provider. * [cURL](http://php.net/manual/en/book.curl.php) when using the provided `GoogleQRCodeProvider` (default), `QRServerProvider` or `QRicketProvider` but you can also provide your own QR-code provider.
* [random_bytes()](http://php.net/manual/en/function.random-bytes.php), [MCrypt](http://php.net/manual/en/book.mcrypt.php), [OpenSSL](http://php.net/manual/en/book.openssl.php) or [Hash](http://php.net/manual/en/book.hash.php) depending on which built-in RNG you use (TwoFactorAuth will try to 'autodetect' and use the best available); however: feel free to provide your own (CS)RNG. * [random_bytes()](http://php.net/manual/en/function.random-bytes.php), [MCrypt](http://php.net/manual/en/book.mcrypt.php), [OpenSSL](http://php.net/manual/en/book.openssl.php) or [Hash](http://php.net/manual/en/book.hash.php) depending on which built-in RNG you use (TwoFactorAuth will try to 'autodetect' and use the best available); however: feel free to provide your own (CS)RNG.

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Name>TwoFactorAuth</Name>
<ProjectGuid>{e569f53a-a604-4579-91ce-4e35b27da47b}</ProjectGuid>
<RootNamespace>TwoFactorAuth</RootNamespace>
<OutputType>Library</OutputType>
<ProjectTypeGuids>{A0786B88-2ADB-4C21-ABE8-AA2D79766269}</ProjectTypeGuids>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
<Server>PHPDev</Server>
<PublishEvent>None</PublishEvent>
<PHPDevAutoPort>True</PHPDevAutoPort>
<PHPDevPort>41315</PHPDevPort>
<PHPDevHostName>localhost</PHPDevHostName>
<IISProjectUrl>http://localhost:41315/</IISProjectUrl>
<Runtime>PHP</Runtime>
<RuntimeVersion>7.0</RuntimeVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<IncludeDebugInformation>true</IncludeDebugInformation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<IncludeDebugInformation>false</IncludeDebugInformation>
</PropertyGroup>
<ItemGroup>
<Compile Include="demo\demo.php" />
<Compile Include="demo\loader.php" />
<Compile Include="lib\Providers\Qr\BaseHTTPQRCodeProvider.php" />
<Compile Include="lib\Providers\Qr\GoogleQRCodeProvider.php" />
<Compile Include="lib\Providers\Qr\IQRCodeProvider.php" />
<Compile Include="lib\Providers\Qr\QRException.php" />
<Compile Include="lib\Providers\Qr\QRicketProvider.php" />
<Compile Include="lib\Providers\Qr\QRServerProvider.php" />
<Compile Include="lib\Providers\Rng\CSRNGProvider.php" />
<Compile Include="lib\Providers\Rng\IRNGProvider.php" />
<Compile Include="lib\Providers\Rng\MCryptRNGProvider.php" />
<Compile Include="lib\Providers\Rng\OpenSSLRNGProvider.php" />
<Compile Include="lib\Providers\Rng\HashRNGProvider.php" />
<Compile Include="lib\Providers\Rng\RNGException.php" />
<Compile Include="lib\Providers\Time\ConvertUnixTimeDotComTimeProvider.php" />
<Compile Include="lib\Providers\Time\HttpTimeProvider.php" />
<Compile Include="lib\Providers\Time\ITimeProvider.php" />
<Compile Include="lib\Providers\Time\LocalMachineTimeProvider.php" />
<Compile Include="lib\Providers\Time\TimeException.php" />
<Compile Include="lib\TwoFactorAuth.php" />
<Compile Include=".gitignore" />
<Compile Include="README.md" />
<Compile Include="lib\TwoFactorAuthException.php" />
<Compile Include="tests\TwoFactorAuthTest.php" />
</ItemGroup>
<ItemGroup>
<Folder Include="lib\" />
<Folder Include="lib\Providers\" />
<Folder Include="lib\Providers\Time\" />
<Folder Include="lib\Providers\Qr\" />
<Folder Include="lib\Providers\Rng\" />
<Folder Include="demo\" />
<Folder Include="tests\" />
</ItemGroup>
<ItemGroup>
<Content Include=".travis.yml" />
<Content Include="composer.json" />
<Content Include="composer.lock" />
<Content Include="logo.png" />
<Content Include="multifactorauthforeveryone.png" />
<Content Include="LICENSE" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
{
"name": "robthree/twofactorauth",
"description": "Two Factor Authentication",
"version": "1.6.1",
"type": "library",
"keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
"homepage": "https://github.com/RobThree/TwoFactorAuth",
"license": "MIT",
"authors": [
{
"name": "Rob Janssen",
"homepage": "http://robiii.me",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/RobThree/TwoFactorAuth/issues",
"source": "https://github.com/RobThree/TwoFactorAuth"
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "@stable"
},
"autoload": {
"psr-4": {
"RobThree\\Auth\\": "lib"
}
},
"autoload-dev": {
"psr-4": {
"RobThree\\Auth\\Test\\": "tests"
}
}
}

980
vendor/robthree/twofactorauth/composer.lock generated vendored Normal file
View File

@@ -0,0 +1,980 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "9647de85f54ba6db237f5ff42ff85a1f",
"packages": [],
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2015-06-14T21:17:01+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03T12:10:50+00:00"
},
{
"name": "phpspec/prophecy",
"version": "v1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"sebastian/recursion-context": "^1.0|^2.0"
},
"require-dev": {
"phpspec/phpspec": "^2.0",
"phpunit/phpunit": "^4.8 || ^5.6.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2016-11-21T14:58:47+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"phpunit/php-file-iterator": "~1.3",
"phpunit/php-text-template": "~1.2",
"phpunit/php-token-stream": "~1.3",
"sebastian/environment": "^1.3.2",
"sebastian/version": "~1.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.2.1",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2015-10-06T15:47:00+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2016-10-03T07:40:28+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2015-06-21T13:50:34+00:00"
},
{
"name": "phpunit/php-timer",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4|~5"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2016-05-12T18:03:57+00:00"
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.9",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2016-11-15T14:06:22+00:00"
},
{
"name": "phpunit/phpunit",
"version": "4.8.35",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87",
"reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpspec/prophecy": "^1.3.1",
"phpunit/php-code-coverage": "~2.1",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.2.2",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.8.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2017-02-06T05:18:07+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2015-10-02T06:51:40+00:00"
},
{
"name": "sebastian/comparator",
"version": "1.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2 || ~2.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2017-01-29T09:50:25+00:00"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2015-12-08T07:14:41+00:00"
},
{
"name": "sebastian/environment",
"version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2016-08-18T05:49:44+00:00"
},
{
"name": "sebastian/exporter",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2016-06-17T09:04:28+00:00"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"time": "2015-10-12T03:26:01+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2015-11-11T19:50:13+00:00"
},
{
"name": "sebastian/version",
"version": "1.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2015-06-21T13:59:46+00:00"
},
{
"name": "symfony/yaml",
"version": "v2.8.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/322a8c2dfbca15ad6b1b27e182899f98ec0e0153",
"reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2017-01-21T16:40:50+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"phpunit/phpunit": 0
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.3.0"
},
"platform-dev": []
}

View File

@@ -0,0 +1,35 @@
<!doctype html>
<html>
<head>
<title>Demo</title>
</head>
<body>
<ol>
<?php
require_once 'loader.php';
Loader::register('../lib','RobThree\\Auth');
use \RobThree\Auth\TwoFactorAuth;
$tfa = new TwoFactorAuth('MyApp');
echo '<li>First create a secret and associate it with a user';
$secret = $tfa->createSecret(160); // Though the default is an 80 bits secret (for backwards compatibility reasons) we recommend creating 160+ bits secrets (see RFC 4226 - Algorithm Requirements)
echo '<li>Next create a QR code and let the user scan it:<br><img src="' . $tfa->getQRCodeImageAsDataUri('My label', $secret) . '"><br>...or display the secret to the user for manual entry: ' . chunk_split($secret, 4, ' ');
$code = $tfa->getCode($secret);
echo '<li>Next, have the user verify the code; at this time the code displayed by a 2FA-app would be: <span style="color:#00c">' . $code . '</span> (but that changes periodically)';
echo '<li>When the code checks out, 2FA can be / is enabled; store (encrypted?) secret with user and have the user verify a code each time a new session is started.';
echo '<li>When aforementioned code (' . $code . ') was entered, the result would be: ' . (($tfa->verifyCode($secret, $code) === true) ? '<span style="color:#0c0">OK</span>' : '<span style="color:#c00">FAIL</span>');
?>
</ol>
<p>Note: Make sure your server-time is <a href="http://en.wikipedia.org/wiki/Network_Time_Protocol">NTP-synced</a>! Depending on the $discrepancy allowed your time cannot drift too much from the users' time!</p>
<?php
try {
$tfa->ensureCorrectTime();
echo 'Your hosts time seems to be correct / within margin';
} catch (RobThree\Auth\TwoFactorAuthException $ex) {
echo '<b>Warning:</b> Your hosts time seems to be off: ' . $ex->getMessage();
}
?>
</body>
</html>

View File

@@ -0,0 +1,50 @@
<?php
//http://www.leaseweblabs.com/2014/04/psr-0-psr-4-autoloading-classes-php/
class Loader
{
protected static $parentPath = null;
protected static $paths = null;
protected static $files = null;
protected static $nsChar = '\\';
protected static $initialized = false;
protected static function initialize()
{
if (static::$initialized) return;
static::$initialized = true;
static::$parentPath = __FILE__;
for ($i=substr_count(get_class(), static::$nsChar);$i>=0;$i--) {
static::$parentPath = dirname(static::$parentPath);
}
static::$paths = array();
static::$files = array(__FILE__);
}
public static function register($path,$namespace) {
if (!static::$initialized) static::initialize();
static::$paths[$namespace] = trim($path,DIRECTORY_SEPARATOR);
}
public static function load($class) {
if (class_exists($class,false)) return;
if (!static::$initialized) static::initialize();
foreach (static::$paths as $namespace => $path) {
if (!$namespace || $namespace.static::$nsChar === substr($class, 0, strlen($namespace.static::$nsChar))) {
$fileName = substr($class,strlen($namespace.static::$nsChar)-1);
$fileName = str_replace(static::$nsChar, DIRECTORY_SEPARATOR, ltrim($fileName,static::$nsChar));
$fileName = static::$parentPath.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$fileName.'.php';
if (file_exists($fileName)) {
include $fileName;
return true;
}
}
}
return false;
}
}
spl_autoload_register(array('Loader', 'load'));

View File

@@ -6,7 +6,7 @@ class ConvertUnixTimeDotComTimeProvider implements ITimeProvider
{ {
public function getTime() { public function getTime() {
$json = @json_decode( $json = @json_decode(
@file_get_contents('http://www.convert-unix-time.com/api?timestamp=now') @file_get_contents('http://www.convert-unix-time.com/api?timestamp=now&r=' . uniqid(null, true))
); );
if ($json === null || !is_int($json->timestamp)) if ($json === null || !is_int($json->timestamp))
throw new \TimeException('Unable to retrieve time from convert-unix-time.com'); throw new \TimeException('Unable to retrieve time from convert-unix-time.com');

View File

@@ -26,7 +26,8 @@ class HttpTimeProvider implements ITimeProvider
'request_fulluri' => true, 'request_fulluri' => true,
'header' => array( 'header' => array(
'Connection: close', 'Connection: close',
'User-agent: TwoFactorAuth HttpTimeProvider (https://github.com/RobThree/TwoFactorAuth)' 'User-agent: TwoFactorAuth HttpTimeProvider (https://github.com/RobThree/TwoFactorAuth)',
'Cache-Control: no-cache'
) )
) )
); );

BIN
vendor/robthree/twofactorauth/logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,381 @@
<?php
require_once 'lib/TwoFactorAuth.php';
require_once 'lib/TwoFactorAuthException.php';
require_once 'lib/Providers/Qr/IQRCodeProvider.php';
require_once 'lib/Providers/Qr/BaseHTTPQRCodeProvider.php';
require_once 'lib/Providers/Qr/GoogleQRCodeProvider.php';
require_once 'lib/Providers/Qr/QRException.php';
require_once 'lib/Providers/Rng/IRNGProvider.php';
require_once 'lib/Providers/Rng/RNGException.php';
require_once 'lib/Providers/Rng/CSRNGProvider.php';
require_once 'lib/Providers/Rng/MCryptRNGProvider.php';
require_once 'lib/Providers/Rng/OpenSSLRNGProvider.php';
require_once 'lib/Providers/Rng/HashRNGProvider.php';
require_once 'lib/Providers/Rng/RNGException.php';
require_once 'lib/Providers/Time/ITimeProvider.php';
require_once 'lib/Providers/Time/LocalMachineTimeProvider.php';
require_once 'lib/Providers/Time/HttpTimeProvider.php';
require_once 'lib/Providers/Time/ConvertUnixTimeDotComTimeProvider.php';
require_once 'lib/Providers/Time/TimeException.php';
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
use RobThree\Auth\Providers\Rng\IRNGProvider;
use RobThree\Auth\Providers\Time\ITimeProvider;
class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testConstructorThrowsOnInvalidDigits() {
new TwoFactorAuth('Test', 0);
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testConstructorThrowsOnInvalidPeriod() {
new TwoFactorAuth('Test', 6, 0);
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testConstructorThrowsOnInvalidAlgorithm() {
new TwoFactorAuth('Test', 6, 30, 'xxx');
}
public function testGetCodeReturnsCorrectResults() {
$tfa = new TwoFactorAuth('Test');
$this->assertEquals('543160', $tfa->getCode('VMR466AB62ZBOKHE', 1426847216));
$this->assertEquals('538532', $tfa->getCode('VMR466AB62ZBOKHE', 0));
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testCreateSecretThrowsOnInsecureRNGProvider() {
$rng = new TestRNGProvider();
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
$tfa->createSecret();
}
public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG() {
$rng = new TestRNGProvider();
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
}
public function testCreateSecretDoesNotThrowOnSecureRNGProvider() {
$rng = new TestRNGProvider(true);
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret());
}
public function testCreateSecretGeneratesDesiredAmountOfEntropy() {
$rng = new TestRNGProvider(true);
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
$this->assertEquals('A', $tfa->createSecret(5));
$this->assertEquals('AB', $tfa->createSecret(6));
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
}
public function testEnsureCorrectTimeDoesNotThrowForCorrectTime() {
$tpr1 = new TestTimeProvider(123);
$tpr2 = new TestTimeProvider(128);
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
$tfa->ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testEnsureCorrectTimeThrowsOnIncorrectTime() {
$tpr1 = new TestTimeProvider(123);
$tpr2 = new TestTimeProvider(124);
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
$tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw
}
public function testEnsureDefaultTimeProviderReturnsCorrectTime() {
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
$tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls
}
public function testEnsureAllTimeProvidersReturnCorrectTime() {
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
$tfa->ensureCorrectTime(array(
new RobThree\Auth\Providers\Time\ConvertUnixTimeDotComTimeProvider(),
new RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default
new RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'),
new RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'),
));
}
public function testVerifyCodeWorksCorrectly() {
$tfa = new TwoFactorAuth('Test', 6, 30);
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190));
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy
}
public function testTotpUriIsCorrect() {
$qr = new TestQrProvider();
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('test/test', $data['mimetype']);
$this->assertEquals('base64', $data['encoding']);
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize() {
$qr = new TestQrProvider();
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr);
$tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0);
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testGetCodeThrowsOnInvalidBase32String1() {
$tfa = new TwoFactorAuth('Test');
$tfa->getCode('FOO1BAR8BAZ9'); //1, 8 & 9 are invalid chars
}
/**
* @expectedException \RobThree\Auth\TwoFactorAuthException
*/
public function testGetCodeThrowsOnInvalidBase32String2() {
$tfa = new TwoFactorAuth('Test');
$tfa->getCode('mzxw6==='); //Lowercase
}
public function testKnownBase32DecodeTestVectors() {
// We usually don't test internals (e.g. privates) but since we rely heavily on base32 decoding and don't want
// to expose this method nor do we want to give people the possibility of implementing / providing their own base32
// decoding/decoder (as we do with Rng/QR providers for example) we simply test the private base32Decode() method
// with some known testvectors **only** to ensure base32 decoding works correctly following RFC's so there won't
// be any bugs hiding in there. We **could** 'fool' ourselves by calling the public getCode() method (which uses
// base32decode internally) and then make sure getCode's output (in digits) equals expected output since that would
// mean the base32Decode() works as expected but that **could** hide some subtle bug(s) in decoding the base32 string.
// "In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, "don't
// expose your privates!"). Most of the time, you should be able to test a class by exercising its public methods."
// Dave Thomas and Andy Hunt -- "Pragmatic Unit Testing
$tfa = new TwoFactorAuth('Test');
$method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode');
$method->setAccessible(true);
// Test vectors from: https://tools.ietf.org/html/rfc4648#page-12
$this->assertEquals('', $method->invoke($tfa, ''));
$this->assertEquals('f', $method->invoke($tfa, 'MY======'));
$this->assertEquals('fo', $method->invoke($tfa, 'MZXQ===='));
$this->assertEquals('foo', $method->invoke($tfa, 'MZXW6==='));
$this->assertEquals('foob', $method->invoke($tfa, 'MZXW6YQ='));
$this->assertEquals('fooba', $method->invoke($tfa, 'MZXW6YTB'));
$this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI======'));
}
public function testKnownBase32DecodeUnpaddedTestVectors() {
// See testKnownBase32DecodeTestVectors() for the rationale behind testing the private base32Decode() method.
// This test ensures that strings without the padding-char ('=') are also decoded correctly.
// https://tools.ietf.org/html/rfc4648#page-4:
// "In some circumstances, the use of padding ("=") in base-encoded data is not required or used."
$tfa = new TwoFactorAuth('Test');
$method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode');
$method->setAccessible(true);
// Test vectors from: https://tools.ietf.org/html/rfc4648#page-12
$this->assertEquals('', $method->invoke($tfa, ''));
$this->assertEquals('f', $method->invoke($tfa, 'MY'));
$this->assertEquals('fo', $method->invoke($tfa, 'MZXQ'));
$this->assertEquals('foo', $method->invoke($tfa, 'MZXW6'));
$this->assertEquals('foob', $method->invoke($tfa, 'MZXW6YQ'));
$this->assertEquals('fooba', $method->invoke($tfa, 'MZXW6YTB'));
$this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI'));
}
public function testKnownTestVectors_sha1() {
//Known test vectors for SHA1: https://tools.ietf.org/html/rfc6238#page-15
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ'; //== base32encode('12345678901234567890')
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha1');
$this->assertEquals('94287082', $tfa->getCode($secret, 59));
$this->assertEquals('07081804', $tfa->getCode($secret, 1111111109));
$this->assertEquals('14050471', $tfa->getCode($secret, 1111111111));
$this->assertEquals('89005924', $tfa->getCode($secret, 1234567890));
$this->assertEquals('69279037', $tfa->getCode($secret, 2000000000));
$this->assertEquals('65353130', $tfa->getCode($secret, 20000000000));
}
public function testKnownTestVectors_sha256() {
//Known test vectors for SHA256: https://tools.ietf.org/html/rfc6238#page-15
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA'; //== base32encode('12345678901234567890123456789012')
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha256');
$this->assertEquals('46119246', $tfa->getCode($secret, 59));
$this->assertEquals('68084774', $tfa->getCode($secret, 1111111109));
$this->assertEquals('67062674', $tfa->getCode($secret, 1111111111));
$this->assertEquals('91819424', $tfa->getCode($secret, 1234567890));
$this->assertEquals('90698825', $tfa->getCode($secret, 2000000000));
$this->assertEquals('77737706', $tfa->getCode($secret, 20000000000));
}
public function testKnownTestVectors_sha512() {
//Known test vectors for SHA512: https://tools.ietf.org/html/rfc6238#page-15
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNA'; //== base32encode('1234567890123456789012345678901234567890123456789012345678901234')
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha512');
$this->assertEquals('90693936', $tfa->getCode($secret, 59));
$this->assertEquals('25091201', $tfa->getCode($secret, 1111111109));
$this->assertEquals('99943326', $tfa->getCode($secret, 1111111111));
$this->assertEquals('93441116', $tfa->getCode($secret, 1234567890));
$this->assertEquals('38618901', $tfa->getCode($secret, 2000000000));
$this->assertEquals('47863826', $tfa->getCode($secret, 20000000000));
}
/**
* @requires function random_bytes
*/
public function testCSRNGProvidersReturnExpectedNumberOfBytes() {
$rng = new \RobThree\Auth\Providers\Rng\CSRNGProvider();
foreach ($this->getRngTestLengths() as $l)
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
$this->assertEquals(true, $rng->isCryptographicallySecure());
}
/**
* @requires function hash_algos
* @requires function hash
*/
public function testHashRNGProvidersReturnExpectedNumberOfBytes() {
$rng = new \RobThree\Auth\Providers\Rng\HashRNGProvider();
foreach ($this->getRngTestLengths() as $l)
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
$this->assertEquals(false, $rng->isCryptographicallySecure());
}
/**
* @requires function mcrypt_create_iv
*/
public function testMCryptRNGProvidersReturnExpectedNumberOfBytes() {
$rng = new \RobThree\Auth\Providers\Rng\MCryptRNGProvider();
foreach ($this->getRngTestLengths() as $l)
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
$this->assertEquals(true, $rng->isCryptographicallySecure());
}
/**
* @requires function openssl_random_pseudo_bytes
*/
public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
$rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(true);
foreach ($this->getRngTestLengths() as $l)
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
$this->assertEquals(true, $rng->isCryptographicallySecure());
}
/**
* @requires function openssl_random_pseudo_bytes
*/
public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
$rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(false);
foreach ($this->getRngTestLengths() as $l)
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
$this->assertEquals(false, $rng->isCryptographicallySecure());
}
private function getRngTestLengths() {
return array(1, 16, 32, 256);
}
private function DecodeDataUri($datauri) {
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
return array(
'mimetype' => $m['mimetype'],
'encoding' => $m['encoding'],
'data' => base64_decode($m['data'])
);
}
return null;
}
}
class TestRNGProvider implements IRNGProvider {
private $isSecure;
function __construct($isSecure = false) {
$this->isSecure = $isSecure;
}
public function getRandomBytes($bytecount) {
$result = '';
for ($i=0; $i<$bytecount; $i++)
$result.=chr($i);
return $result;
}
public function isCryptographicallySecure() {
return $this->isSecure;
}
}
class TestQrProvider implements IQRCodeProvider {
public function getQRCodeImage($qrtext, $size) {
return $qrtext . '@' . $size;
}
public function getMimeType() {
return 'test/test';
}
}
class TestTimeProvider implements ITimeProvider {
private $time;
function __construct($time) {
$this->time = $time;
}
public function getTime() {
return $this->time;
}
}

View File

@@ -0,0 +1,5 @@
composer.lock
vendor
.buildpath
.project
.settings

View File

@@ -0,0 +1,43 @@
sudo: false
language: php
branches:
except:
- /^release-.*$/
- /^ghgfk-.*$/
cache:
directories:
- $HOME/.composer/cache
matrix:
allow_failures:
- php: hhvm
matrix:
fast_finish: true
include:
- php: 5.3
- php: 5.4
- php: 5.5
env:
- EXECUTE_CS_CHECK=true
- php: 5.6
- php: 7
- php: hhvm
allow_failures:
- php: hhvm
before_install:
- composer self-update
install:
- travis_retry composer install --no-interaction --ignore-platform-reqs
script:
- ./vendor/bin/phpunit -c ./tests
- if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/phpcs --standard=PSR2 --ignore=tests/Bootstrap.php library tests ; fi
notifications:
irc: "irc.freenode.org#zftalk.dev"
email: false

View File

@@ -0,0 +1,40 @@
{
"name": "zendframework/zendxml",
"description": "Utility library for XML usage, best practices, and security in PHP",
"type": "library",
"license": "BSD-3-Clause",
"keywords": [
"zf2",
"xml",
"security"
],
"homepage": "http://packages.zendframework.com/",
"autoload": {
"psr-0": {
"ZendXml\\": "library/"
}
},
"autoload-dev": {
"psr-4": {
"ZendTest\\Xml\\": "tests/ZendXmlTest/"
}
},
"repositories": [
{
"type": "composer",
"url": "http://packages.zendframework.com/"
}
],
"require": {
"php": "^5.3.3 || ^7.0"
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"require-dev": {
"phpunit/phpunit": "^3.7 || ^4.0",
"squizlabs/php_codesniffer": "^1.5"
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @package Zend
*/
/**
* Set error reporting to the level to which Zend Framework code must comply.
*/
error_reporting( E_ALL | E_STRICT );
if (class_exists('PHPUnit_Runner_Version', true)) {
$phpUnitVersion = PHPUnit_Runner_Version::id();
if ('@package_version@' !== $phpUnitVersion && version_compare($phpUnitVersion, '3.7.0', '<')) {
echo 'This version of PHPUnit (' .
PHPUnit_Runner_Version::id() .
') is not supported for ZendXml unit tests - use v 3.7.0 or higher.'
. PHP_EOL
;
exit(1);
}
unset($phpUnitVersion);
}
/**
* Setup autoloading
*/
// Try to use Composer autoloader
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
include_once __DIR__ . '/../vendor/autoload.php';
}
// ... or use a simple SPL autoloader
else{
// update include path
set_include_path(implode(PATH_SEPARATOR, array(
__DIR__.'/../src',
__DIR__,
get_include_path()
)));
/**
* @link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md#example-implementation
*/
spl_autoload_register(function ($className) {
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
require $fileName;
});
}
/**
* Code coverage option
*/
if (defined('TESTS_GENERATE_REPORT') && TESTS_GENERATE_REPORT === true) {
$codeCoverageFilter = new PHP_CodeCoverage_Filter();
$lastArg = end($_SERVER['argv']);
if (is_dir($zfCoreTests . '/' . $lastArg)) {
$codeCoverageFilter->addDirectoryToWhitelist($zfCoreLibrary . '/' . $lastArg);
} elseif (is_file($zfCoreTests . '/' . $lastArg)) {
$codeCoverageFilter->addDirectoryToWhitelist(dirname($zfCoreLibrary . '/' . $lastArg));
} else {
$codeCoverageFilter->addDirectoryToWhitelist($zfCoreLibrary);
}
/*
* Omit from code coverage reports the contents of the tests directory
*/
$codeCoverageFilter->addDirectoryToBlacklist($zfCoreTests, '');
$codeCoverageFilter->addDirectoryToBlacklist(PEAR_INSTALL_DIR, '');
$codeCoverageFilter->addDirectoryToBlacklist(PHP_LIBDIR, '');
unset($codeCoverageFilter);
}
/*
* Unset global variables that are no longer needed.
*/
unset($phpUnitVersion);

View File

@@ -0,0 +1,125 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace ZendTest\Xml;
use ZendXml\Security as XmlSecurity;
use ZendXml\Exception;
use DOMDocument;
use ReflectionMethod;
use SimpleXMLElement;
/**
* @group ZF2015-06
*/
class MultibyteTest extends \PHPUnit_Framework_TestCase
{
public function multibyteEncodings()
{
return array(
'UTF-16LE' => array('UTF-16LE', pack('CC', 0xff, 0xfe), 3),
'UTF-16BE' => array('UTF-16BE', pack('CC', 0xfe, 0xff), 3),
'UTF-32LE' => array('UTF-32LE', pack('CCCC', 0xff, 0xfe, 0x00, 0x00), 4),
'UTF-32BE' => array('UTF-32BE', pack('CCCC', 0x00, 0x00, 0xfe, 0xff), 4),
);
}
public function getXmlWithXXE()
{
return <<<XML
<?xml version="1.0" encoding="{ENCODING}"?>
<!DOCTYPE methodCall [
<!ENTITY pocdata SYSTEM "file:///etc/passwd">
]>
<methodCall>
<methodName>retrieved: &pocdata;</methodName>
</methodCall>
XML;
}
/**
* Invoke ZendXml\Security::heuristicScan with the provided XML.
*
* @param string $xml
* @return void
* @throws Exception\RuntimeException
*/
public function invokeHeuristicScan($xml)
{
$r = new ReflectionMethod('ZendXml\Security', 'heuristicScan');
$r->setAccessible(true);
return $r->invoke(null, $xml);
}
/**
* @dataProvider multibyteEncodings
* @group heuristicDetection
*/
public function testDetectsMultibyteXXEVectorsUnderFPMWithEncodedStringMissingBOM($encoding, $bom, $bomLength)
{
$xml = $this->getXmlWithXXE();
$xml = str_replace('{ENCODING}', $encoding, $xml);
$xml = iconv('UTF-8', $encoding, $xml);
$this->assertNotSame(0, strncmp($xml, $bom, $bomLength));
$this->setExpectedException('ZendXml\Exception\RuntimeException', 'ENTITY');
$this->invokeHeuristicScan($xml);
}
/**
* @dataProvider multibyteEncodings
*/
public function testDetectsMultibyteXXEVectorsUnderFPMWithEncodedStringUsingBOM($encoding, $bom)
{
$xml = $this->getXmlWithXXE();
$xml = str_replace('{ENCODING}', $encoding, $xml);
$orig = iconv('UTF-8', $encoding, $xml);
$xml = $bom . $orig;
$this->setExpectedException('ZendXml\Exception\RuntimeException', 'ENTITY');
$this->invokeHeuristicScan($xml);
}
public function getXmlWithoutXXE()
{
return <<<XML
<?xml version="1.0" encoding="{ENCODING}"?>
<methodCall>
<methodName>retrieved: &pocdata;</methodName>
</methodCall>
XML;
}
/**
* @dataProvider multibyteEncodings
*/
public function testDoesNotFlagValidMultibyteXmlAsInvalidUnderFPM($encoding)
{
$xml = $this->getXmlWithoutXXE();
$xml = str_replace('{ENCODING}', $encoding, $xml);
$xml = iconv('UTF-8', $encoding, $xml);
try {
$result = $this->invokeHeuristicScan($xml);
$this->assertNull($result);
} catch (\Exception $e) {
$this->fail('Security scan raised exception when it should not have');
}
}
/**
* @dataProvider multibyteEncodings
* @group mixedEncoding
*/
public function testDetectsXXEWhenXMLDocumentEncodingDiffersFromFileEncoding($encoding, $bom)
{
$xml = $this->getXmlWithXXE();
$xml = str_replace('{ENCODING}', 'UTF-8', $xml);
$xml = iconv('UTF-8', $encoding, $xml);
$xml = $bom . $xml;
$this->setExpectedException('ZendXml\Exception\RuntimeException', 'ENTITY');
$this->invokeHeuristicScan($xml);
}
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace ZendTest\Xml;
use ZendXml\Security as XmlSecurity;
use ZendXml\Exception;
use DOMDocument;
use SimpleXMLElement;
class SecurityTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException ZendXml\Exception\RuntimeException
*/
public function testScanForXEE()
{
$xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE results [<!ENTITY harmless "completely harmless">]>
<results>
<result>This result is &harmless;</result>
</results>
XML;
$this->setExpectedException('ZendXml\Exception\RuntimeException');
$result = XmlSecurity::scan($xml);
}
public function testScanForXXE()
{
$file = tempnam(sys_get_temp_dir(), 'ZendXml_Security');
file_put_contents($file, 'This is a remote content!');
$xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE root
[
<!ENTITY foo SYSTEM "file://$file">
]>
<results>
<result>&foo;</result>
</results>
XML;
try {
$result = XmlSecurity::scan($xml);
} catch (Exception\RuntimeException $e) {
unlink($file);
return;
}
$this->fail('An expected exception has not been raised.');
}
public function testScanSimpleXmlResult()
{
$result = XmlSecurity::scan($this->getXml());
$this->assertTrue($result instanceof SimpleXMLElement);
$this->assertEquals($result->result, 'test');
}
public function testScanDom()
{
$dom = new DOMDocument('1.0');
$result = XmlSecurity::scan($this->getXml(), $dom);
$this->assertTrue($result instanceof DOMDocument);
$node = $result->getElementsByTagName('result')->item(0);
$this->assertEquals($node->nodeValue, 'test');
}
public function testScanInvalidXml()
{
$xml = <<<XML
<foo>test</bar>
XML;
$result = XmlSecurity::scan($xml);
$this->assertFalse($result);
}
public function testScanInvalidXmlDom()
{
$xml = <<<XML
<foo>test</bar>
XML;
$dom = new DOMDocument('1.0');
$result = XmlSecurity::scan($xml, $dom);
$this->assertFalse($result);
}
public function testScanFile()
{
$file = tempnam(sys_get_temp_dir(), 'ZendXml_Security');
file_put_contents($file, $this->getXml());
$result = XmlSecurity::scanFile($file);
$this->assertTrue($result instanceof SimpleXMLElement);
$this->assertEquals($result->result, 'test');
unlink($file);
}
public function testScanXmlWithDTD()
{
$xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE results [
<!ELEMENT results (result+)>
<!ELEMENT result (#PCDATA)>
]>
<results>
<result>test</result>
</results>
XML;
$dom = new DOMDocument('1.0');
$result = XmlSecurity::scan($xml, $dom);
$this->assertTrue($result instanceof DOMDocument);
$this->assertTrue($result->validate());
}
protected function getXml()
{
return <<<XML
<?xml version="1.0"?>
<results>
<result>test</result>
</results>
XML;
}
}

View File

@@ -0,0 +1,27 @@
<phpunit bootstrap="./Bootstrap.php" colors="true">
<testsuites>
<testsuite name="ZendXml Test Suite">
<directory>./ZendXmlTest</directory>
<exclude>./ZendXmlTest/TestAsset</exclude>
</testsuite>
</testsuites>
<groups>
<exclude>
</exclude>
</groups>
<listeners>
</listeners>
<filter>
<blacklist>
<directory suffix=".php">./ZendXmlTest</directory>
<directory>../vendor</directory>
</blacklist>
</filter>
<php>
</php>
</phpunit>