]> git.openstreetmap.org Git - nominatim.git/blob - lib-php/Shell.php
Merge pull request #3122 from miku0/sanitizer-final
[nominatim.git] / lib-php / Shell.php
1 <?php
2 /**
3  * SPDX-License-Identifier: GPL-2.0-only
4  *
5  * This file is part of Nominatim. (https://nominatim.org)
6  *
7  * Copyright (C) 2022 by the Nominatim developer community.
8  * For a full list of authors see the git log.
9  */
10
11 namespace Nominatim;
12
13 class Shell
14 {
15     public function __construct($sBaseCmd, ...$aParams)
16     {
17         if (!$sBaseCmd) {
18             throw new \Exception('Command missing in new() call');
19         }
20         $this->baseCmd = $sBaseCmd;
21         $this->aParams = array();
22         $this->aEnv = null; // null = use the same environment as the current PHP process
23
24         $this->stdoutString = null;
25
26         foreach ($aParams as $sParam) {
27             $this->addParams($sParam);
28         }
29     }
30
31     public function addParams(...$aParams)
32     {
33         foreach ($aParams as $sParam) {
34             if (isset($sParam) && $sParam !== null && $sParam !== '') {
35                 array_push($this->aParams, $sParam);
36             }
37         }
38         return $this;
39     }
40
41     public function addEnvPair($sKey, $sVal)
42     {
43         if (isset($sKey) && $sKey && isset($sVal)) {
44             if (!isset($this->aEnv)) {
45                 $this->aEnv = $_ENV;
46             }
47             $this->aEnv = array_merge($this->aEnv, array($sKey => $sVal), $_ENV);
48         }
49         return $this;
50     }
51
52     public function escapedCmd()
53     {
54         $aEscaped = array_map(function ($sParam) {
55             return $this->escapeParam($sParam);
56         }, array_merge(array($this->baseCmd), $this->aParams));
57
58         return join(' ', $aEscaped);
59     }
60
61     public function run($bExitOnFail = false)
62     {
63         $sCmd = $this->escapedCmd();
64         // $aEnv does not need escaping, proc_open seems to handle it fine
65
66         $aFDs = array(
67                  0 => array('pipe', 'r'),
68                  1 => STDOUT,
69                  2 => STDERR
70                 );
71         $aPipes = null;
72         $hProc = @proc_open($sCmd, $aFDs, $aPipes, null, $this->aEnv);
73         if (!is_resource($hProc)) {
74             throw new \Exception('Unable to run command: ' . $sCmd);
75         }
76
77         fclose($aPipes[0]); // no stdin
78
79         $iStat = proc_close($hProc);
80
81         if ($iStat != 0 && $bExitOnFail) {
82             exit($iStat);
83         }
84
85         return $iStat;
86     }
87
88     private function escapeParam($sParam)
89     {
90         return (preg_match('/^-*\w+$/', $sParam)) ? $sParam : escapeshellarg($sParam);
91     }
92 }