Skip to content

Commit

Permalink
Make injection protection optional (#429)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Wentzell committed Jan 6, 2021
1 parent 831712a commit f82a18e
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 14 deletions.
2 changes: 2 additions & 0 deletions docs/reference/symfony.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ This service can be configured throught the following parameters:
* ``sonata.exporter.writer.csv.escape``: defaults to ``\\``
* ``sonata.exporter.writer.csv.show_headers``: defaults to ``true``
* ``sonata.exporter.writer.csv.with_bom``: defaults to ``false``
* ``sonata.exporter.writer.csv.safe_cells``: defaults to ``false``

The JSON writer service
~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -60,6 +61,7 @@ This service can be configured throught the following parameters:

* ``sonata.exporter.writer.xls.filename``: defaults to ``php://output``
* ``sonata.exporter.writer.xls.show_headers``: defaults to ``true``
* ``sonata.exporter.writer.xls.safe_cells``: defaults to ``false``

The XML writer service
~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
8 changes: 8 additions & 0 deletions src/Bridge/Symfony/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue(false)
->info('include the byte order mark')
->end()
->booleanNode('safe_cells')
->defaultValue(false)
->info('escapes data cells that that may be interpreted as formulas in spreadsheet software')
->end()
->end()
->end()
->arrayNode('json')
Expand All @@ -91,6 +95,10 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue(true)
->info('add column names as the first line')
->end()
->booleanNode('safe_cells')
->defaultValue(false)
->info('escapes data cells that that may be interpreted as formulas in spreadsheet software')
->end()
->end()
->end()
->arrayNode('xml')
Expand Down
2 changes: 2 additions & 0 deletions src/Bridge/Symfony/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
<argument>%sonata.exporter.writer.csv.escape%</argument>
<argument>%sonata.exporter.writer.csv.show_headers%</argument>
<argument>%sonata.exporter.writer.csv.with_bom%</argument>
<argument>%sonata.exporter.writer.csv.safe_cells%</argument>
</service>
<service id="sonata.exporter.writer.json" class="Sonata\Exporter\Writer\JsonWriter" public="false">
<argument>%sonata.exporter.writer.json.filename%</argument>
</service>
<service id="sonata.exporter.writer.xls" class="Sonata\Exporter\Writer\XlsWriter" public="false">
<argument>%sonata.exporter.writer.xls.filename%</argument>
<argument>%sonata.exporter.writer.xls.show_headers%</argument>
<argument>%sonata.exporter.writer.xls.safe_cells%</argument>
</service>
<service id="sonata.exporter.writer.xml" class="Sonata\Exporter\Writer\XmlWriter" public="false">
<argument>%sonata.exporter.writer.xml.filename%</argument>
Expand Down
23 changes: 16 additions & 7 deletions src/Writer/CsvWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ final class CsvWriter implements TypedWriterInterface
*/
private $terminate;

/**
* @var bool
*/
private $safeCells;

/**
* @throws \RuntimeException
*/
Expand All @@ -75,7 +80,8 @@ public function __construct(
string $escape = '\\',
bool $showHeaders = true,
bool $withBom = false,
string $terminate = "\n"
string $terminate = "\n",
bool $safeCells = false
) {
$this->filename = $filename;
$this->delimiter = $delimiter;
Expand All @@ -85,6 +91,7 @@ public function __construct(
$this->terminate = $terminate;
$this->position = 0;
$this->withBom = $withBom;
$this->safeCells = $safeCells;

if (is_file($filename)) {
throw new \RuntimeException(sprintf('The file %s already exist', $filename));
Expand Down Expand Up @@ -138,12 +145,14 @@ public function write(array $data): void
}

// prevent csv injection
foreach ($data as $key => $value) {
$data[$key] = preg_replace(
['/^=/', '/^\+/', '/^-/', '/^@/'],
['\'=', '\'+', '\'-', '\'@'],
$value
);
if (true === $this->safeCells) {
foreach ($data as $key => $value) {
$data[$key] = preg_replace(
['/^=/', '/^\+/', '/^-/', '/^@/'],
['\'=', '\'+', '\'-', '\'@'],
$value
);
}
}

$result = @fputcsv($this->file, $data, $this->delimiter, $this->enclosure, $this->escape);
Expand Down
26 changes: 19 additions & 7 deletions src/Writer/XlsWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@ final class XlsWriter implements TypedWriterInterface
*/
private $position = 0;

/**
* @var bool
*/
private $safeCells;

/**
* @throws \RuntimeException
*/
public function __construct(string $filename, bool $showHeaders = true)
public function __construct(string $filename, bool $showHeaders = true, bool $safeCells = false)
{
$this->filename = $filename;
$this->showHeaders = $showHeaders;
$this->safeCells = $safeCells;

if (is_file($filename)) {
throw new \RuntimeException(sprintf('The file %s already exists', $filename));
Expand Down Expand Up @@ -79,12 +85,18 @@ public function write(array $data): void

fwrite($this->file, '<tr>');
// prevent xls injection
foreach ($data as $value) {
fwrite($this->file, sprintf('<td>%s</td>', preg_replace(
['/^=/', '/^\+/', '/^-/', '/^@/'],
['\'=', '\'+', '\'-', '\'@'],
$value
)));
if (true === $this->safeCells) {
foreach ($data as $value) {
fwrite($this->file, sprintf('<td>%s</td>', preg_replace(
['/^=/', '/^\+/', '/^-/', '/^@/'],
['\'=', '\'+', '\'-', '\'@'],
$value
)));
}
} else {
foreach ($data as $value) {
fwrite($this->file, sprintf('<td>%s</td>', $value));
}
}
fwrite($this->file, '</tr>');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ public function testDefault(): void
'escape' => '\\',
'show_headers' => true,
'with_bom' => false,
'safe_cells' => false,
],
'json' => [
'filename' => 'php://output',
],
'xls' => [
'filename' => 'php://output',
'show_headers' => true,
'safe_cells' => false,
],
'xml' => [
'filename' => 'php://output',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ public function testServiceParametersArePresent(): void
'sonata.exporter.writer.csv.escape',
'sonata.exporter.writer.csv.show_headers',
'sonata.exporter.writer.csv.with_bom',
'sonata.exporter.writer.csv.safe_cells',
'sonata.exporter.writer.json.filename',
'sonata.exporter.writer.xls.filename',
'sonata.exporter.writer.xls.show_headers',
'sonata.exporter.writer.xls.safe_cells',
'sonata.exporter.writer.xml.filename',
'sonata.exporter.writer.xml.main_element',
'sonata.exporter.writer.xml.child_element',
Expand Down

0 comments on commit f82a18e

Please sign in to comment.