diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 8ca381e..bf9c5e3 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- php-version: ["8.0", "8.1", "8.2", "8.3"]
+ php-version: ["8.1", "8.2", "8.3", "8.4"]
experimental: [false]
os: [ubuntu-latest]
coverage-extension: [pcov]
@@ -50,7 +50,7 @@ jobs:
- name: Run all tests
run: make qa
- name: Send coverage
- uses: codecov/codecov-action@v3
+ uses: codecov/codecov-action@v5
with:
flags: php-${{ matrix.php-version }}-${{ matrix.os }}
name: php-${{ matrix.php-version }}-${{ matrix.os }}
diff --git a/Makefile b/Makefile
index 3da98e3..4e26acf 100644
--- a/Makefile
+++ b/Makefile
@@ -170,7 +170,7 @@ endif
deps: ensuretarget
rm -rf ./vendor/*
($(COMPOSER) install -vvv --no-interaction)
- curl --silent --show-error --fail --location --output ./vendor/phpstan.phar https://github.com/phpstan/phpstan/releases/download/1.10.41/phpstan.phar \
+ curl --silent --show-error --fail --location --output ./vendor/phpstan.phar https://github.com/phpstan/phpstan/releases/download/2.0.4/phpstan.phar \
&& chmod +x ./vendor/phpstan.phar
# Generate source code documentation
@@ -212,8 +212,8 @@ endif
.PHONY: lint
lint:
./vendor/bin/phpcs --ignore="./vendor/" --standard=phpcs.xml src test
- ./vendor/bin/phpmd src text codesize,unusedcode,naming,design --exclude vendor
- ./vendor/bin/phpmd test text unusedcode,naming,design
+ ./vendor/bin/phpmd src text codesize,unusedcode,naming,design --exclude */vendor/*
+ ./vendor/bin/phpmd test text unusedcode,naming,design --exclude */vendor/*
php -r 'exit((int)version_compare(PHP_MAJOR_VERSION, "7", ">"));' || ./vendor/phpstan.phar analyse
# Run all tests and reports
@@ -261,7 +261,7 @@ tag:
.PHONY: test
test:
cp phpunit.xml.dist phpunit.xml
- ./vendor/bin/phpunit --migrate-configuration || true
+ #./vendor/bin/phpunit --migrate-configuration || true
XDEBUG_MODE=coverage ./vendor/bin/phpunit --stderr test
# Remove all installed files
diff --git a/VERSION b/VERSION
index 9bbe651..e265a8c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.14
+3.0.15
diff --git a/composer.json b/composer.json
index a20e13f..e65fb64 100644
--- a/composer.json
+++ b/composer.json
@@ -18,15 +18,15 @@
}
],
"require": {
- "php": ">=8.0",
+ "php": ">=8.1",
"ext-pcre": "*",
"tecnickcom/tc-lib-pdf-filter": "^2.0"
},
"require-dev": {
- "pdepend/pdepend": "2.13.0",
- "phpmd/phpmd": "2.13.0",
- "phpunit/phpunit": "10.1.2 || 9.6.13",
- "squizlabs/php_codesniffer": "3.7.2"
+ "pdepend/pdepend": "2.16.2",
+ "phpmd/phpmd": "2.15.0",
+ "phpunit/phpunit": "11.5.2 || 10.5.40",
+ "squizlabs/php_codesniffer": "3.11.2"
},
"autoload": {
"psr-4": {
diff --git a/phpstan.neon b/phpstan.neon
index bf592ce..86bd47d 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -3,7 +3,7 @@ parameters:
paths:
- src
- test
- scanDirectories:
+ excludePaths:
- vendor
ignoreErrors:
reportUnmatchedIgnoredErrors: false
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 9597570..745e082 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,27 +1,31 @@
+ stopOnFailure="false">
./test
-
-
- src
-
-
+
+
+ src
+
+
+
+
+
+
+
+
-
-
-
+
diff --git a/resources/debian/compat b/resources/debian/compat
index ec63514..f599e28 100644
--- a/resources/debian/compat
+++ b/resources/debian/compat
@@ -1 +1 @@
-9
+10
diff --git a/resources/debian/control b/resources/debian/control
index bd0b1b2..8eb6702 100644
--- a/resources/debian/control
+++ b/resources/debian/control
@@ -10,6 +10,6 @@ Vcs-Git: https://github.com/~#VENDOR#~/~#PROJECT#~.git
Package: ~#PKGNAME#~
Provides: php-~#PROJECT#~
Architecture: all
-Depends: php (>= 8.0.0), php-tecnickcom-tc-lib-pdf-filter (<< 2.0.0), php-tecnickcom-tc-lib-pdf-filter (>= 2.0.17), ${misc:Depends}
+Depends: php (>= 8.1.0), php-tecnickcom-tc-lib-pdf-filter (<< 2.0.0), php-tecnickcom-tc-lib-pdf-filter (>= 2.0.18), ${misc:Depends}
Description: PHP PDF Parser Library
PHP library to parse PDF documents.
diff --git a/resources/rpm/rpm.spec b/resources/rpm/rpm.spec
index 792299b..deed813 100644
--- a/resources/rpm/rpm.spec
+++ b/resources/rpm/rpm.spec
@@ -16,9 +16,9 @@ URL: https://github.com/%{gh_owner}/%{gh_project}
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n)
BuildArch: noarch
-Requires: php(language) >= 8.0.0
+Requires: php(language) >= 8.1.0
Requires: php-composer(%{c_vendor}/tc-lib-pdf-filter) < 2.0.0
-Requires: php-composer(%{c_vendor}/tc-lib-pdf-filter) >= 2.0.17
+Requires: php-composer(%{c_vendor}/tc-lib-pdf-filter) >= 2.0.18
Requires: php-pcre
Provides: php-composer(%{c_vendor}/%{gh_project}) = %{version}
diff --git a/src/Parser.php b/src/Parser.php
index ff7ed03..63749bf 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -32,7 +32,7 @@
* @license http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
* @link https://github.com/tecnickcom/tc-lib-pdf-parser
*
- * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
+ * @SuppressWarnings("PHPMD.ExcessiveClassComplexity")
*
* @phpstan-import-type RawObjectArray from \Com\Tecnick\Pdf\Parser\Process\RawObject
*/
@@ -230,7 +230,7 @@ protected function getObjectVal(array $obj): array
* 1: array,
* } Decoded stream data and remaining filters.
*
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings("PHPMD.CyclomaticComplexity")
*/
protected function decodeStream(array $sdic, string $stream): array
{
diff --git a/src/Process/RawObject.php b/src/Process/RawObject.php
index 97103fa..5e284fb 100644
--- a/src/Process/RawObject.php
+++ b/src/Process/RawObject.php
@@ -232,7 +232,7 @@ protected function processParenthesis(string $char, int &$offset, string &$objty
* @param string $char Symbol to process
* @param int $offset Offset
* @param string $objtype Object type
- * @param arraygetRawObject($offset);
$offset = $element[2];
- $objval[] = $element;
+ $objval[] = $element; // @phpstan-ignore parameterByRef.type
} while ($element[0] != ']');
// remove closing delimiter
@@ -289,7 +289,7 @@ protected function processAngular(string $char, int &$offset, string &$objtype,
do {
$element = $this->getRawObject($offset);
$offset = $element[2];
- $objval[] = $element;
+ $objval[] = $element; // @phpstan-ignore parameterByRef.type
} while ($element[0] != '>>');
// remove closing delimiter
diff --git a/src/Process/Xref.php b/src/Process/Xref.php
index f213258..1bf754d 100644
--- a/src/Process/Xref.php
+++ b/src/Process/Xref.php
@@ -34,7 +34,7 @@
abstract class Xref extends \Com\Tecnick\Pdf\Parser\Process\XrefStream
{
/**
- * XREF data.
+ * Default empty XREF data.
*
* @var array{
* 'trailer': array{
@@ -47,7 +47,7 @@ abstract class Xref extends \Com\Tecnick\Pdf\Parser\Process\XrefStream
* 'xref': array,
* }
*/
- protected array $xref = [
+ protected const XREF_EMPTY = [
'trailer' => [
'encrypt' => '',
'id' => [],
@@ -58,6 +58,22 @@ abstract class Xref extends \Com\Tecnick\Pdf\Parser\Process\XrefStream
'xref' => [],
];
+ /**
+ * XREF data.
+ *
+ * @var array{
+ * 'trailer': array{
+ * 'encrypt'?: string,
+ * 'id': array,
+ * 'info': string,
+ * 'root': string,
+ * 'size': int,
+ * },
+ * 'xref': array,
+ * }
+ */
+ protected array $xref = self::XREF_EMPTY;
+
/**
* Store the processed offsets
*
@@ -107,7 +123,7 @@ abstract protected function getIndirectObject(string $obj_ref, int $offset = 0,
* 'xref': array,
* } Xref and trailer data.
*
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings("PHPMD.CyclomaticComplexity")
*/
protected function getXrefData(int $offset = 0, array $xref = []): array
{
@@ -355,7 +371,7 @@ protected function getTrailerData(array $xref, array $matches): array
* 'xref': array,
* } Xref and trailer data.
*
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings("PHPMD.CyclomaticComplexity")
*/
protected function decodeXrefStream(int $startxref, array $xref): array
{
@@ -366,16 +382,13 @@ protected function decodeXrefStream(int $startxref, array $xref): array
}
$xrefcrs = $this->getIndirectObject($xrefobj[1], $startxref, true);
- if (! isset($xref['trailer']) || empty($xref['trailer'])) {
- // get only the last updated version
- $xref['trailer'] = [];
- $filltrailer = true;
- } else {
- $filltrailer = false;
- }
+ $filltrailer = empty($xref['trailer']);
+ if ($filltrailer) {
+ $xref['trailer'] = self::XREF_EMPTY['trailer'];
+ }
if (! isset($xref['xref'])) {
- $xref['xref'] = [];
+ $xref['xref'] = self::XREF_EMPTY['xref'];
}
$valid_crs = false;
@@ -405,7 +418,7 @@ protected function decodeXrefStream(int $startxref, array $xref): array
$ddata = [];
// initialize first row with zeros
$prev_row = array_fill(0, $rowlen, 0);
- $this->pngUnpredictor($sdata, $ddata, $columns, $prev_row);
+ $this->pngUnpredictor($sdata, $ddata, $columns, $prev_row); //@phpstan-ignore argument.type
// complete decoding
$sdata = [];
$this->processDdata($sdata, $ddata, $wbt);
@@ -417,12 +430,12 @@ protected function decodeXrefStream(int $startxref, array $xref): array
}
// end decoding data
- if ($prevxref !== []) {
- // get previous xref
- return $this->getXrefData($prevxref, $xref);
+ if (is_null($prevxref)) {
+ return $xref;
}
- return $xref;
+ // get previous xref
+ return $this->getXrefData($prevxref, $xref);
}
/**
diff --git a/src/Process/XrefStream.php b/src/Process/XrefStream.php
index 0f20024..4826e00 100644
--- a/src/Process/XrefStream.php
+++ b/src/Process/XrefStream.php
@@ -32,6 +32,8 @@
* @link https://github.com/tecnickcom/tc-lib-pdf-parser
*
* @phpstan-import-type RawObjectArray from \Com\Tecnick\Pdf\Parser\Process\RawObject
+ *
+ * @SuppressWarnings("PHPMD.ExcessiveClassComplexity")
*/
abstract class XrefStream extends \Com\Tecnick\Pdf\Parser\Process\RawObject
{
@@ -48,8 +50,8 @@ abstract class XrefStream extends \Com\Tecnick\Pdf\Parser\Process\RawObject
* },
* 'xref': array,
* } $xref XREF data
- * @param int $obj_num Object number
- * @param array> $sdata Stream data
+ * @param int $obj_num Object number
+ * @param array> $sdata Stream data
*/
protected function processObjIndexes(array &$xref, int &$obj_num, array $sdata): void
{
@@ -202,22 +204,22 @@ protected function minDistance(
* 'xref': array,
* } $xref XREF data
* @param array $wbt WBT data
- * @param int $index_first Index first
- * @param int $prevxref Previous XREF
+ * @param int|null $index_first Index first
+ * @param int|null $prevxref Previous XREF
* @param int $columns Number of columns
- * @param int $valid_crs Valid CRS
+ * @param bool $valid_crs Valid CRS
* @param bool $filltrailer Fill trailer
*
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings("PHPMD.CyclomaticComplexity")
*/
protected function processXrefType(
array $sarr,
array &$xref,
array &$wbt,
- int &$index_first,
- int &$prevxref,
+ ?int &$index_first,
+ ?int &$prevxref,
int &$columns,
- int &$valid_crs,
+ bool &$valid_crs,
bool $filltrailer
): void {
foreach ($sarr as $key => $val) {
@@ -262,9 +264,9 @@ protected function processXrefType(
*
* @param array $sarr Stream data
* @param int $key Key
- * @param int $prevxref Previous XREF
+ * @param int|null $prevxref Previous XREF
*/
- protected function processXrefPrev(array $sarr, int $key, int &$prevxref): void
+ protected function processXrefPrev(array $sarr, int $key, ?int &$prevxref): void
{
if ($sarr[($key + 1)][0] == 'numeric') {
// get previous xref offset
@@ -299,9 +301,9 @@ protected function processXrefDecodeParms(array $sarr, int $key, int &$columns):
/**
* Process XREF type
*
- * @param string $type Type
+ * @param string $type Type
* @param array $sarr Stream data
- * @param int $key Key
+ * @param int $key Key
* @param array{
* 'trailer': array{
* 'encrypt'?: string,
@@ -311,8 +313,8 @@ protected function processXrefDecodeParms(array $sarr, int $key, int &$columns):
* 'size': int,
* },
* 'xref': array,
- * } $xref XREF data
- * @param bool $filltrailer Fill trailer
+ * } $xref XREF data
+ * @param bool $filltrailer Fill trailer
*/
protected function processXrefTypeFt(string $type, array $sarr, int $key, array &$xref, bool $filltrailer): void
{
@@ -323,11 +325,19 @@ protected function processXrefTypeFt(string $type, array $sarr, int $key, array
switch ($type) {
case 'Size':
if ($sarr[($key + 1)][0] == 'numeric') {
- $xref['trailer']['size'] = $sarr[($key + 1)][1];
+ $xref['trailer']['size'] = (int) $sarr[($key + 1)][1];
}
break;
case 'ID':
+ if (
+ empty($sarr[($key + 1)][1][0][1])
+ || empty($sarr[($key + 1)][1][1][1])
+ || !is_string($sarr[($key + 1)][1][0][1])
+ || !is_string($sarr[($key + 1)][1][1][1])
+ ) {
+ break;
+ }
$xref['trailer']['id'] = [];
$xref['trailer']['id'][0] = $sarr[($key + 1)][1][0][1];
$xref['trailer']['id'][1] = $sarr[($key + 1)][1][1][1];
@@ -357,19 +367,26 @@ protected function processXrefTypeFt(string $type, array $sarr, int $key, array
*/
protected function processXrefObjref(string $type, array $sarr, int $key, array &$xref): void
{
- if (! isset($sarr[($key + 1)]) || ($sarr[($key + 1)][0] !== 'objref')) {
+ if (
+ empty($sarr[($key + 1)])
+ || empty($sarr[($key + 1)][1])
+ || !is_string($sarr[($key + 1)][1])
+ || ($sarr[($key + 1)][0] !== 'objref')
+ ) {
return;
}
+ $val = $sarr[($key + 1)][1];
+
switch ($type) {
case 'Root':
- $xref['trailer']['root'] = $sarr[($key + 1)][1];
+ $xref['trailer']['root'] = $val;
break;
case 'Info':
- $xref['trailer']['info'] = $sarr[($key + 1)][1];
+ $xref['trailer']['info'] = $val;
break;
case 'Encrypt':
- $xref['trailer']['encrypt'] = $sarr[($key + 1)][1];
+ $xref['trailer']['encrypt'] = $val;
break;
}
}
diff --git a/test/ParserTest.php b/test/ParserTest.php
index e2c3a26..3a134ee 100644
--- a/test/ParserTest.php
+++ b/test/ParserTest.php
@@ -18,6 +18,7 @@
use Com\Tecnick\Pdf\Parser\Parser;
use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\Attributes\DataProvider;
/**
* Filter Test
@@ -32,9 +33,7 @@
*/
class ParserTest extends TestCase
{
- /**
- * @dataProvider getParseProvider
- */
+ #[DataProvider('getParseProvider')]
public function testParse(string $filename, string $hash): void
{
$cfg = [