symfony/symfony — pull request #12488 by romainneutron (2014-11-15 16:58:08+00:00)
Title: [Process] Add commandline parameter binding support

| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets |
| License | MIT
| Doc PR | Not yet

Hello,

this is an alternative proposal to #11972.
Let me summarise which issues we have and what I propose:

We need to enforce our strategy to prevent command line injections as it's already done for SQL. At the moment, the ProcessBuilder we provide lacks of support for many use case, especially:
- pipe `|`
- redirections `>>`, `<`, `>`, etc...
- `exec` functionality (it's not a command, it must not be escaped) rel #5759, #11335

In these cases, users do not use the `ProcessBuilder` as this one does not fit their needs ; they build the commandline by themselves.
In #11972, I proposed to add a fluent command builder. However, thinking more about it, it will be a mess to write and maintain, it's mostly writing a bash parser and I think it's a big work to do in order to solve something that should be easy. Moreover, writing such commandline builder would not be easy to use (just read the few comment of this PR, think about explicit precedence).

Discussing about this topic with @nicolas-grekas brought us to this proposal that is fully BC and provides an easy way for developers to prepare and run commands just as in SQL.

What do you think about it?

Here's a sample of code that allows to build a safe and complex command:

```php
$process = new Process('ls ## | grep ## > data.log && curl -XPOST ## 2>&1 --data-binary "@data.log" >/dev/null');
$process->run(null, array('.', '\'', 'http://localhost/endpoint'));
```
would run:
```
ls '.' | grep ''\''' > data.log && curl -XPOST 'http://localhost/endpoint' 2>&1 --data-binary "@data.log" >/dev/null
```

It also can be used with named parameters:

```php
$process = new Process('ls :dir: | grep :filter: > data.log && curl -XPOST :url: 2>&1 --data-binary "@data.log" >/dev/null');
$process->run(null, array(
':dir:' => '.',
':filter:' => '\'',
':url:' => 'http://localhost/endpoint',
));
```
would run:
```
ls '.' | grep ''\''' > data.log && curl -XPOST 'http://localhost/endpoint' 2>&1 --data-binary "@data.log" >/dev/null
```

It's currently working, let me know what you think about it.
I currently propose to be straight on parameters: If parameters mismatch (missing, unused), the components throws an exception.
I also propose to use `{}` as default placeholder, it might be wrong, let me know if you have comments on this.

Last but not least, this PR still requires:
- [ ] more tests, especially for exceptions and named parameters
- [ ] documentation
- [ ] better integration with `ProcessBuilder`