Skip to content

Commit 4f95e0d

Browse files
authored
Merge pull request #64 from eclipxe13/version-0.5.4
Corrección de paquetes truncados al descargar y mantenimiento (v0.5.4)
2 parents 7fc5256 + b922c1e commit 4f95e0d

16 files changed

+228
-42
lines changed

.github/workflows/build.yml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ jobs:
1818
runs-on: "ubuntu-latest"
1919
steps:
2020
- name: Checkout
21-
uses: actions/checkout@v3
21+
uses: actions/checkout@v4
2222
- name: Setup PHP
2323
uses: shivammathur/setup-php@v2
2424
with:
25-
php-version: '8.2'
25+
php-version: '8.3'
2626
coverage: none
2727
tools: cs2pr, phpcs
2828
env:
@@ -35,11 +35,11 @@ jobs:
3535
runs-on: "ubuntu-latest"
3636
steps:
3737
- name: Checkout
38-
uses: actions/checkout@v3
38+
uses: actions/checkout@v4
3939
- name: Setup PHP
4040
uses: shivammathur/setup-php@v2
4141
with:
42-
php-version: '8.2'
42+
php-version: '8.3'
4343
coverage: none
4444
tools: cs2pr, php-cs-fixer
4545
env:
@@ -52,11 +52,11 @@ jobs:
5252
runs-on: "ubuntu-latest"
5353
steps:
5454
- name: Checkout
55-
uses: actions/checkout@v3
55+
uses: actions/checkout@v4
5656
- name: Setup PHP
5757
uses: shivammathur/setup-php@v2
5858
with:
59-
php-version: '8.2'
59+
php-version: '8.3'
6060
coverage: none
6161
tools: composer:v2, phpstan
6262
env:
@@ -65,29 +65,29 @@ jobs:
6565
id: composer-cache
6666
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
6767
- name: Cache dependencies
68-
uses: actions/cache@v3
68+
uses: actions/cache@v4
6969
with:
70-
path: ${{ steps.composer-cache.outputs.dir }}
71-
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
72-
restore-keys: ${{ runner.os }}-composer-
70+
path: "${{ steps.composer-cache.outputs.dir }}"
71+
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}"
72+
restore-keys: "${{ runner.os }}-composer-"
7373
- name: Install project dependencies
7474
run: composer upgrade --no-interaction --no-progress --prefer-dist
7575
- name: PHPStan
7676
run: phpstan analyse --no-progress --verbose
7777

7878
tests:
79-
name: Tests on PHP ${{ matrix.php-versions }}
79+
name: Tests on PHP ${{ matrix.php-version }}
8080
runs-on: "ubuntu-latest"
8181
strategy:
8282
matrix:
83-
php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2']
83+
php-version: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
8484
steps:
8585
- name: Checkout
86-
uses: actions/checkout@v3
86+
uses: actions/checkout@v4
8787
- name: Setup PHP
8888
uses: shivammathur/setup-php@v2
8989
with:
90-
php-version: ${{ matrix.php-versions }}
90+
php-version: ${{ matrix.php-version }}
9191
coverage: none
9292
tools: composer:v2
9393
env:
@@ -96,11 +96,11 @@ jobs:
9696
id: composer-cache
9797
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
9898
- name: Cache dependencies
99-
uses: actions/cache@v3
99+
uses: actions/cache@v4
100100
with:
101-
path: ${{ steps.composer-cache.outputs.dir }}
102-
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
103-
restore-keys: ${{ runner.os }}-composer-
101+
path: "${{ steps.composer-cache.outputs.dir }}"
102+
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}"
103+
restore-keys: "${{ runner.os }}-composer-"
104104
- name: Install project dependencies
105105
run: composer upgrade --no-interaction --no-progress --prefer-dist
106106
- name: Tests (phpunit)

.github/workflows/coverage.yml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ on:
1111
jobs:
1212

1313
tests-coverage:
14-
name: Tests on PHP 8.2 (code coverage)
14+
name: Create code coverage
1515
runs-on: "ubuntu-latest"
1616
steps:
1717
- name: Checkout
18-
uses: actions/checkout@v3
18+
uses: actions/checkout@v4
1919
- name: Setup PHP
2020
uses: shivammathur/setup-php@v2
2121
with:
22-
php-version: '8.2'
22+
php-version: '8.3'
2323
coverage: xdebug
2424
tools: composer:v2
2525
env:
@@ -28,17 +28,17 @@ jobs:
2828
id: composer-cache
2929
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
3030
- name: Cache dependencies
31-
uses: actions/cache@v3
31+
uses: actions/cache@v4
3232
with:
33-
path: ${{ steps.composer-cache.outputs.dir }}
34-
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
35-
restore-keys: ${{ runner.os }}-composer-
33+
path: "${{ steps.composer-cache.outputs.dir }}"
34+
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}"
35+
restore-keys: "${{ runner.os }}-composer-"
3636
- name: Install project dependencies
3737
run: composer upgrade --no-interaction --no-progress --prefer-dist
3838
- name: Create code coverage
3939
run: vendor/bin/phpunit --testdox --verbose --coverage-xml=build/coverage --coverage-clover=build/coverage/clover.xml --log-junit=build/coverage/junit.xml
4040
- name: Store code coverage
41-
uses: actions/upload-artifact@v3
41+
uses: actions/upload-artifact@v4
4242
if: ${{ !env.ACT }} # do not run using nektos/act
4343
with:
4444
name: code-coverage
@@ -74,28 +74,28 @@ jobs:
7474
runs-on: "ubuntu-latest"
7575
steps:
7676
- name: Checkout
77-
uses: actions/checkout@v3
77+
uses: actions/checkout@v4
7878
- name: Unshallow clone to provide blame information
7979
run: git fetch --unshallow
8080
- name: Setup PHP
8181
uses: shivammathur/setup-php@v2
8282
with:
83-
php-version: '8.2'
83+
php-version: '8.3'
8484
coverage: none
8585
tools: composer:v2
8686
- name: Get composer cache directory
8787
id: composer-cache
8888
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
8989
- name: Cache dependencies
90-
uses: actions/cache@v3
90+
uses: actions/cache@v4
9191
with:
92-
path: ${{ steps.composer-cache.outputs.dir }}
93-
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
94-
restore-keys: ${{ runner.os }}-composer-
92+
path: "${{ steps.composer-cache.outputs.dir }}"
93+
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}"
94+
restore-keys: "${{ runner.os }}-composer-"
9595
- name: Install project dependencies
9696
run: composer upgrade --no-interaction --no-progress --prefer-dist
9797
- name: Obtain code coverage
98-
uses: actions/download-artifact@v3
98+
uses: actions/download-artifact@v4
9999
with:
100100
name: code-coverage
101101
path: build/coverage

.phive/phars.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<phive xmlns="https://phar.io/phive">
3-
<phar name="php-cs-fixer" version="^3.37.1" installed="3.37.1" location="./tools/php-cs-fixer" copy="false"/>
4-
<phar name="phpcs" version="^3.7.2" installed="3.7.2" location="./tools/phpcs" copy="false"/>
5-
<phar name="phpcbf" version="^3.7.2" installed="3.7.2" location="./tools/phpcbf" copy="false"/>
6-
<phar name="phpstan" version="^1.10.40" installed="1.10.40" location="./tools/phpstan" copy="false"/>
3+
<phar name="php-cs-fixer" version="^3.54.0" installed="3.54.0" location="./tools/php-cs-fixer" copy="false"/>
4+
<phar name="phpcs" version="^3.9.1" installed="3.9.1" location="./tools/phpcs" copy="false"/>
5+
<phar name="phpcbf" version="^3.9.1" installed="3.9.1" location="./tools/phpcbf" copy="false"/>
6+
<phar name="phpstan" version="^1.10.67" installed="1.10.67" location="./tools/phpstan" copy="false"/>
77
</phive>

.php-cs-fixer.dist.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
'standardize_not_equals' => true,
3737
'concat_space' => ['spacing' => 'one'],
3838
'linebreak_after_opening_tag' => true,
39+
'fully_qualified_strict_types' => true,
3940
// symfony:risky
4041
'no_alias_functions' => true,
4142
'self_accessor' => true,

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2019 - 2023 PhpCfdi https://www.phpcfdi.com/
3+
Copyright (c) 2019 - 2024 PhpCfdi https://www.phpcfdi.com/
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"ext-json": "*",
2727
"ext-zip": "*",
2828
"ext-mbstring": "*",
29+
"ext-libxml": "*",
2930
"phpcfdi/credentials": "^1.1",
3031
"phpcfdi/rfc": "^1.1",
3132
"eclipxe/enum": "^0.2.0",

docs/CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@ que nombraremos así: ` Breaking . Feature . Fix `, donde:
1414
**Importante:** Las reglas de SEMVER no aplican si estás usando una rama (por ejemplo `main-dev`)
1515
o estás usando una versión cero (por ejemplo `0.18.4`).
1616

17+
## Versión 0.5.4 2024-04-17
18+
19+
- Se corrige un bug donde en algunas ocasiones falla al procesar la respuesta de una descarga de paquetes.
20+
21+
El método `DOMDocument::loadXML()` con `LibXML >= 1.11.0` trunca a 10,000,000 bytes el contenido de un
22+
nodo de tipo texto. Esto lleva a que el contenido de un paquete se trunque y el archivo ZIP descargado
23+
se encuentre truncado y, por lo tanto, corrupto. Se ha corregido usando la opción `LIBXML_PARSEHUGE`.
24+
Al usar `LIBXML_PARSEHUGE` se está quitando una protección natural que impide una denegación de servicio.
25+
Sin embargo, podemos considerar segura esta acción dado que solo ocurre en el contexto de respuestas
26+
recibidas del servicio de descarga masiva del SAT.
27+
28+
- Se actualiza el archivo de licencia a 2024.
29+
30+
## Mantenimiento 2024-04-17
31+
32+
- Se mejoran las pruebas del rasgo `ComplementoTrait`.
33+
- Se actualizaron los flujos de trabajo:
34+
- Se agregó PHP 8.3 a la matriz de pruebas.
35+
- Los trabajos ahora corren en PHP 8.3.
36+
- Se actualizan las acciones de GitHub a la versión 4.
37+
- Se cambia la variable `build/tests/matrix/php-versions` a singular.
38+
- Se actualizaron las herramientas de desarrollo.
39+
1740
## Mantenimiento 2023-10-30
1841

1942
- El proceso de integración continua falló al momento de verificar el estilo de código con `php-cs-fixer:3.37.1`.

phpcs.xml.dist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<?xml version="1.0"?>
1+
<?xml version="1.0" encoding="UTF-8"?>
22
<ruleset name="EngineWorks">
3-
<description>The EngineWorks (PSR-2 based) coding standard.</description>
3+
<description>The EngineWorks (PSR-12 based) coding standard.</description>
44

55
<file>src</file>
66
<file>tests</file>

src/Internal/InteractsXmlTrait.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public function readXmlDocument(string $source): DOMDocument
2525
throw new InvalidArgumentException('Cannot load an xml with empty content');
2626
}
2727
$document = new DOMDocument();
28-
$document->loadXML($source);
28+
// as of libxml2 >= 1.11.0 it will truncate huge text nodes (like the zip files in base64)
29+
$document->loadXML($source, LIBXML_PARSEHUGE);
2930
return $document;
3031
}
3132

src/Shared/ComplementoTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function label(): string
4040
return $label;
4141
}
4242
}
43-
return '';
43+
return ''; // @codeCoverageIgnore
4444
}
4545

4646
public function jsonSerialize(): string
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpCfdi\SatWsDescargaMasiva\Tests\Unit\Services\Download;
6+
7+
use LogicException;
8+
use PhpCfdi\SatWsDescargaMasiva\Services\Download\DownloadTranslator;
9+
use PhpCfdi\SatWsDescargaMasiva\Tests\TestCase;
10+
use ZipArchive;
11+
12+
final class DownloadTranslatorContentsTest extends TestCase
13+
{
14+
private const FILE_SIZE_LIMIT = 10 * 1024 * 1024; // 10 MiB
15+
16+
/** @var string */
17+
private $hugeZipFile;
18+
19+
/** @var string */
20+
private $hugeResponse;
21+
22+
protected function setUp(): void
23+
{
24+
parent::setUp();
25+
$hugeZipFile = tempnam('', '');
26+
if (false === $hugeZipFile) {
27+
throw new LogicException('Unable to create a temporary file');
28+
}
29+
30+
$this->hugeZipFile = $hugeZipFile;
31+
$this->createHugeZipFile($this->hugeZipFile);
32+
$this->hugeResponse = $this->createHugeResponse($this->hugeZipFile);
33+
if (strlen($this->hugeResponse) < self::FILE_SIZE_LIMIT) {
34+
throw new LogicException(
35+
sprintf('Unable to create a response with size bigger than %s bytes', self::FILE_SIZE_LIMIT)
36+
);
37+
}
38+
}
39+
40+
protected function tearDown(): void
41+
{
42+
unlink($this->hugeZipFile);
43+
parent::tearDown();
44+
}
45+
46+
private function createHugeZipFile(string $destination): void
47+
{
48+
$chunkSize = 2 * 1024 * 1024; // 1MB
49+
$limitSize = self::FILE_SIZE_LIMIT; // 10MB
50+
$fileCount = intval($limitSize / $chunkSize) + 1;
51+
$archive = new ZipArchive();
52+
$archive->open($destination, ZipArchive::OVERWRITE);
53+
for ($i = 1; $i < $fileCount; $i++) {
54+
/** @noinspection PhpUnhandledExceptionInspection */
55+
$archive->addFromString(sprintf('%d.txt', $i), random_bytes($chunkSize));
56+
}
57+
$archive->close();
58+
}
59+
60+
private function createHugeResponse(string $contentFile): string
61+
{
62+
$template = $this->fileContents('download/response-with-package-template.xml');
63+
$template = (string) preg_replace('/>\s+</', '><', $template);
64+
$template = str_replace('?>', "?>\n", $template);
65+
$search = '<Paquete />';
66+
$strpos = (int) strpos($template, $search);
67+
/** @noinspection PhpUnnecessaryLocalVariableInspection */
68+
$template = substr($template, 0, $strpos)
69+
. '<Paquete>' . base64_encode((string) file_get_contents($contentFile)) . '</Paquete>'
70+
. substr($template, $strpos + strlen($search));
71+
// file_put_contents('/tmp/sample-response.xml', $template);
72+
return $template;
73+
}
74+
75+
public function testCreateDownloadResultFromHugeResponse(): void
76+
{
77+
$translator = new DownloadTranslator();
78+
79+
$result = $translator->createDownloadResultFromSoapResponse($this->hugeResponse);
80+
81+
$this->assertSame(
82+
sha1_file($this->hugeZipFile),
83+
sha1($result->getPackageContent()),
84+
'Extracted package contents for huge file are not the expected',
85+
);
86+
}
87+
}

tests/Unit/Shared/ComplementoCfdiTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ public function testSample(): void
2727
{
2828
$complemento = ComplementoCfdi::valesDespensa10();
2929
$this->assertFalse($complemento->isUndefined());
30+
$this->assertTrue($complemento->{'isValesDespensa10'}());
3031
$this->assertSame('valesdedespensa', $complemento->value());
3132
$this->assertSame('Vales de despensa 1.0', $complemento->label());
3233
$this->assertEquals(new ComplementoCfdi('valesdedespensa'), $complemento);
34+
$this->assertEquals(ComplementoCfdi::create('valesdedespensa'), $complemento);
3335
}
3436
}

0 commit comments

Comments
 (0)