diff --git a/.github/workflows/test-bacon.yml b/.github/workflows/test-bacon.yml new file mode 100644 index 0000000..98c45dd --- /dev/null +++ b/.github/workflows/test-bacon.yml @@ -0,0 +1,30 @@ +name: Test Bacon QR Code Provider + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] + + steps: + - uses: actions/checkout@v2 + + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + tools: composer + coverage: xdebug + ini-values: error_reporting=E_ALL + + - uses: ramsey/composer-install@v1 + + - run: composer require bacon/bacon-qr-code + + - run: composer lint + - run: composer test testsDependency/BaconQRCodeTest.php diff --git a/lib/Providers/Qr/BaconQrCodeProvider.php b/lib/Providers/Qr/BaconQrCodeProvider.php index 4d5cf01..65fb977 100644 --- a/lib/Providers/Qr/BaconQrCodeProvider.php +++ b/lib/Providers/Qr/BaconQrCodeProvider.php @@ -125,12 +125,19 @@ class BaconQrCodeProvider implements IQRCodeProvider { if (is_string($colour) && $colour[0] == '#') { $hexToRGB = function ($input) { + // ensure input no longer has a # for more predictable division + // PHP 8.1 does not like implicitly casting a float to an int + $input = trim($input, '#'); + + if (strlen($input) != 3 && strlen($input) != 6) { + throw new \RuntimeException('Colour should be a 3 or 6 character value after the #'); + } + // split the array into three chunks - $split = str_split(trim($input, '#'), strlen($input) / 3); + $split = str_split($input, strlen($input) / 3); // cope with three character hex reference - // three characters plus a # = 4 - if (strlen($input) == 4) { + if (strlen($input) == 3) { array_walk($split, function (&$character) { $character = str_repeat($character, 2); }); diff --git a/lib/Providers/Qr/HandlesDataUri.php b/lib/Providers/Qr/HandlesDataUri.php new file mode 100644 index 0000000..c9f8571 --- /dev/null +++ b/lib/Providers/Qr/HandlesDataUri.php @@ -0,0 +1,24 @@ +[\w\.\-\+\/]+);(?P\w+),(?P.*)/', $datauri, $m) === 1) { + return array( + 'mimetype' => $m['mimetype'], + 'encoding' => $m['encoding'], + 'data' => base64_decode($m['data']) + ); + } + + return null; + } +} diff --git a/tests/Providers/Qr/IQRCodeProviderTest.php b/tests/Providers/Qr/IQRCodeProviderTest.php index 579cb51..bf52d6e 100644 --- a/tests/Providers/Qr/IQRCodeProviderTest.php +++ b/tests/Providers/Qr/IQRCodeProviderTest.php @@ -5,26 +5,11 @@ namespace Tests\Providers\Qr; use PHPUnit\Framework\TestCase; use RobThree\Auth\TwoFactorAuth; use RobThree\Auth\TwoFactorAuthException; +use RobThree\Auth\Providers\Qr\HandlesDataUri; class IQRCodeProviderTest extends TestCase { - /** - * @param string $datauri - * - * @return null|array - */ - private function DecodeDataUri($datauri) - { - if (preg_match('/data:(?P[\w\.\-\/]+);(?P\w+),(?P.*)/', $datauri, $m) === 1) { - return array( - 'mimetype' => $m['mimetype'], - 'encoding' => $m['encoding'], - 'data' => base64_decode($m['data']) - ); - } - - return null; - } + use HandlesDataUri; /** * @return void diff --git a/testsDependency/BaconQRCodeTest.php b/testsDependency/BaconQRCodeTest.php new file mode 100644 index 0000000..e46f13d --- /dev/null +++ b/testsDependency/BaconQRCodeTest.php @@ -0,0 +1,61 @@ +expectException(\RuntimeException::class); + + $qr = new BaconQrCodeProvider(1, '#000', '#FFF', 'svg'); + } else { + $qr = new BaconQrCodeProvider(1, '#000', '#FFF', 'svg'); + + $tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr); + + $data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE')); + $this->assertEquals('image/svg+xml', $data['mimetype']); + } + } + + public function testBadTextColour() + { + $this->expectException(\RuntimeException::class); + + new BaconQrCodeProvider(1, 'not-a-colour', '#FFF'); + } + + public function testBadBackgroundColour() + { + $this->expectException(\RuntimeException::class); + + new BaconQrCodeProvider(1, '#000', 'not-a-colour'); + } + + public function testBadTextColourHexRef() + { + $this->expectException(\RuntimeException::class); + + new BaconQrCodeProvider(1, '#AAAA', '#FFF'); + } + + public function testBadBackgroundColourHexRef() + { + $this->expectException(\RuntimeException::class); + + new BaconQrCodeProvider(1, '#000', '#AAAA'); + } + + +}