Issues (15)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Ares.php (7 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Defr;
4
5
use Defr\Ares\AresException;
6
use Defr\Ares\AresRecord;
7
use Defr\Ares\AresRecords;
8
use Defr\Ares\TaxRecord;
9
use InvalidArgumentException;
10
11
/**
12
 * Class Ares.
13
 *
14
 * @author Dennis Fridrich <[email protected]>
15
 */
16
class Ares
17
{
18
    const URL_BAS = 'http://wwwinfo.mfcr.cz/cgi-bin/ares/darv_bas.cgi?ico=%s';
19
    const URL_RES = 'http://wwwinfo.mfcr.cz/cgi-bin/ares/darv_res.cgi?ICO=%s';
20
    const URL_TAX = 'http://wwwinfo.mfcr.cz/cgi-bin/ares/ares_es.cgi?ico=%s&filtr=0';
21
    const URL_FIND = 'http://wwwinfo.mfcr.cz/cgi-bin/ares/ares_es.cgi?obch_jm=%s&obec=%s&filtr=0';
22
23
    /**
24
     * @var string
25
     */
26
    private $cacheStrategy = 'YW';
27
28
    /**
29
     * @var string
30
     */
31
    private $cacheDir = null;
32
33
    /**
34
     * @var bool
35
     */
36
    private $debug;
37
38
    /**
39
     * @var string
40
     */
41
    private $balancer = null;
42
43
    /**
44
     * @var array
45
     */
46
    private $contextOptions = [
47
        'ssl' => [
48
            'verify_peer' => false,
49
            'verify_peer_name' => false,
50
        ],
51
    ];
52
53
    /**
54
     * @var string
55
     */
56
    private $lastUrl;
57
58
    /**
59
     * @param null $cacheDir
60
     * @param bool $debug
61
     */
62 5
    public function __construct($cacheDir = null, $debug = false, $balancer = null)
63
    {
64 5
        if (null === $cacheDir) {
65 5
            $cacheDir = sys_get_temp_dir();
66 5
        }
67
68 5
        if (null !== $balancer) {
69
            $this->balancer = $balancer;
70
        }
71
72 5
        $this->cacheDir = $cacheDir.'/defr/ares';
73 5
        $this->debug = $debug;
74
75
        // Create cache dirs if they doesn't exist
76 5
        if (!is_dir($this->cacheDir)) {
77 1
            mkdir($this->cacheDir, 0777, true);
78 1
        }
79 5
    }
80
81
    /**
82
     * @param string $balancer
83
     *
84
     * @return $this
85
     */
86 1
    public function setBalancer($balancer)
87
    {
88 1
        $this->balancer = $balancer;
89
90 1
        return $this;
91
    }
92
93
    /**
94
     * @param string $url
95
     *
96
     * @return string
97
     */
98 3
    private function wrapUrl($url)
99
    {
100 3
        if ($this->balancer) {
101 1
            $url = sprintf('%s?url=%s', $this->balancer, urlencode($url));
102 1
        }
103
104 3
        $this->lastUrl = $url;
105
106 3
        return $url;
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    public function getLastUrl()
113
    {
114
        return $this->lastUrl;
115
    }
116
117
    /**
118
     * @param $id
119
     *
120
     * @throws InvalidArgumentException
121
     * @throws Ares\AresException
122
     *
123
     * @return AresRecord
124
     */
125 5
    public function findByIdentificationNumber($id)
126
    {
127 5
        $id = Lib::toInteger($id);
128 5
        $this->ensureIdIsInteger($id);
129
130 5
        if (empty($id)) {
131 2
            throw new AresException('IČ firmy musí být zadáno.');
132
        }
133
134 3
        $cachedFileName = $id.'_'.date($this->cacheStrategy).'.php';
135 3
        $cachedFile = $this->cacheDir.'/bas_'.$cachedFileName;
136 3
        $cachedRawFile = $this->cacheDir.'/bas_raw_'.$cachedFileName;
137
138 3
        if (is_file($cachedFile)) {
139
            return unserialize(file_get_contents($cachedFile));
140
        }
141
142
        // Sestaveni URL
143 3
        $url = $this->wrapUrl(sprintf(self::URL_BAS, $id));
144
145
        try {
146 3
            $aresRequest = file_get_contents($url, null, stream_context_create($this->contextOptions));
147 2
            if ($this->debug) {
148
                file_put_contents($cachedRawFile, $aresRequest);
149
            }
150 2
            $aresResponse = simplexml_load_string($aresRequest);
151
152 2
            if ($aresResponse) {
153 2
                $ns = $aresResponse->getDocNamespaces();
154 2
                $data = $aresResponse->children($ns['are']);
155 2
                $elements = $data->children($ns['D'])->VBAS;
0 ignored issues
show
The property VBAS does not seem to exist in SimpleXMLElement.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
156
157 2
                $ico = (int) $elements->ICO;
158 2
                if ($ico !== $id) {
159
                    throw new AresException('IČ firmy nebylo nalezeno.');
160
                }
161
162 2
                $record = new AresRecord();
163
164 2
                $record->setCompanyId(strval($elements->ICO));
165 2
                $record->setTaxId(strval($elements->DIC));
166 2
                $record->setCompanyName(strval($elements->OF));
167 2
                $record->setStreet(strval($elements->AA->NU));
168
169 2
                if (strval($elements->AA->CO)) {
170 1
                    $record->setStreetHouseNumber(strval($elements->AA->CD));
171 1
                    $record->setStreetOrientationNumber(strval($elements->AA->CO));
172 1
                } else {
173 1
                    $record->setStreetHouseNumber(strval($elements->AA->CD));
174
                }
175
176 2
                if (strval($elements->AA->N) === 'Praha') { //Praha
177 1
                    $record->setTown(strval($elements->AA->NMC).' - '.strval($elements->AA->NCO));
178 2
                } elseif (strval($elements->AA->NCO) !== strval($elements->AA->N)) { //Ostrava
179 1
                    $record->setTown(strval($elements->AA->N).' - '.strval($elements->AA->NCO));
180 1
                } else {
181
                    $record->setTown(strval($elements->AA->N));
182
                }
183
184 2
                $record->setZip(strval($elements->AA->PSC));
185 2
            } else {
186
                throw new AresException('Databáze ARES není dostupná.');
187
            }
188 3
        } catch (\Exception $e) {
189 1
            throw new AresException($e->getMessage());
190
        }
191
192 2
        file_put_contents($cachedFile, serialize($record));
193
194 2
        return $record;
195
    }
196
197
    /**
198
     * @param $id
199
     *
200
     * @throws InvalidArgumentException
201
     * @throws Ares\AresException
202
     *
203
     * @return AresRecord
204
     */
205
    public function findInResById($id)
206
    {
207
        $id = Lib::toInteger($id);
208
        $this->ensureIdIsInteger($id);
209
210
        // Sestaveni URL
211
        $url = $this->wrapUrl(sprintf(self::URL_RES, $id));
212
213
        $cachedFileName = $id.'_'.date($this->cacheStrategy).'.php';
214
        $cachedFile = $this->cacheDir.'/res_'.$cachedFileName;
215
        $cachedRawFile = $this->cacheDir.'/res_raw_'.$cachedFileName;
216
217
        if (is_file($cachedFile)) {
218
            return unserialize(file_get_contents($cachedFile));
219
        }
220
221
        try {
222
            $aresRequest = file_get_contents($url, null, stream_context_create($this->contextOptions));
223
            if ($this->debug) {
224
                file_put_contents($cachedRawFile, $aresRequest);
225
            }
226
            $aresResponse = simplexml_load_string($aresRequest);
227
228
            if ($aresResponse) {
229
                $ns = $aresResponse->getDocNamespaces();
230
                $data = $aresResponse->children($ns['are']);
231
                $elements = $data->children($ns['D'])->Vypis_RES;
0 ignored issues
show
The property Vypis_RES does not seem to exist in SimpleXMLElement.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
232
233
                if (strval($elements->ZAU->ICO) === $id) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strval($elements->ZAU->ICO) (string) and $id (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
234
                    $record = new AresRecord();
235
                    $record->setCompanyId(strval($id));
236
                    $record->setTaxId($this->findVatById($id));
237
                    $record->setCompanyName(strval($elements->ZAU->OF));
238
                    $record->setStreet(strval($elements->SI->NU));
239
                    $record->setStreetHouseNumber(strval($elements->SI->CD));
240
                    $record->setStreetOrientationNumber(strval($elements->SI->CO));
241
                    $record->setTown(strval($elements->SI->N));
242
                    $record->setZip(strval($elements->SI->PSC));
243
                } else {
244
                    throw new AresException('IČ firmy nebylo nalezeno.');
245
                }
246
            } else {
247
                throw new AresException('Databáze ARES není dostupná.');
248
            }
249
        } catch (\Exception $e) {
250
            throw new AresException($e->getMessage());
251
        }
252
        file_put_contents($cachedFile, serialize($record));
253
254
        return $record;
255
    }
256
257
    /**
258
     * @param $id
259
     *
260
     * @throws InvalidArgumentException
261
     * @throws \Exception
262
     *
263
     * @return string
264
     */
265
    public function findVatById($id)
266
    {
267
        $id = Lib::toInteger($id);
268
269
        $this->ensureIdIsInteger($id);
270
271
        // Sestaveni URL
272
        $url = $this->wrapUrl(sprintf(self::URL_TAX, $id));
273
274
        $cachedFileName = $id.'_'.date($this->cacheStrategy).'.php';
275
        $cachedFile = $this->cacheDir.'/tax_'.$cachedFileName;
276
        $cachedRawFile = $this->cacheDir.'/tax_raw_'.$cachedFileName;
277
278
        if (is_file($cachedFile)) {
279
            return unserialize(file_get_contents($cachedFile));
280
        }
281
282
        try {
283
            $vatRequest = file_get_contents($url, null, stream_context_create($this->contextOptions));
284
            if ($this->debug) {
285
                file_put_contents($cachedRawFile, $vatRequest);
286
            }
287
            $vatResponse = simplexml_load_string($vatRequest);
288
289
            if ($vatResponse) {
290
                $record = new TaxRecord();
0 ignored issues
show
The call to TaxRecord::__construct() misses a required argument $taxId.

This check looks for function calls that miss required arguments.

Loading history...
291
                $ns = $vatResponse->getDocNamespaces();
292
                $data = $vatResponse->children($ns['are']);
293
                $elements = $data->children($ns['dtt'])->V->S;
294
295
                if (strval($elements->ico) === $id) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strval($elements->ico) (string) and $id (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
296
                    $record->setTaxId(str_replace('dic=', 'CZ', strval($elements->p_dph)));
0 ignored issues
show
The method setTaxId() does not seem to exist on object<Defr\Ares\TaxRecord>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
297
                } else {
298
                    throw new AresException('DIČ firmy nebylo nalezeno.');
299
                }
300
            } else {
301
                throw new AresException('Databáze MFČR není dostupná.');
302
            }
303
        } catch (\Exception $e) {
304
            throw new \Exception($e->getMessage());
305
        }
306
        file_put_contents($cachedFile, serialize($record));
307
308
        return $record;
309
    }
310
311
    /**
312
     * @param $name
313
     * @param null $city
314
     *
315
     * @throws InvalidArgumentException
316
     * @throws \Exception
317
     *
318
     * @return array|AresRecord[]|AresRecords
319
     */
320
    public function findByName($name, $city = null)
321
    {
322
        if (strlen($name) < 3) {
323
            throw new InvalidArgumentException('Zadejte minimálně 3 znaky pro hledání.');
324
        }
325
326
        $url = $this->wrapUrl(sprintf(
327
            self::URL_FIND,
328
            urlencode(Lib::stripDiacritics($name)),
329
            urlencode(Lib::stripDiacritics($city))
330
        ));
331
332
        $cachedFileName = date($this->cacheStrategy).'_'.md5($name.$city).'.php';
333
        $cachedFile = $this->cacheDir.'/find_'.$cachedFileName;
334
        $cachedRawFile = $this->cacheDir.'/find_raw_'.$cachedFileName;
335
336
        if (is_file($cachedFile)) {
337
            return unserialize(file_get_contents($cachedFile));
338
        }
339
340
        $aresRequest = file_get_contents($url, null, stream_context_create($this->contextOptions));
341
        if ($this->debug) {
342
            file_put_contents($cachedRawFile, $aresRequest);
343
        }
344
        $aresResponse = simplexml_load_string($aresRequest);
345
        if (!$aresResponse) {
346
            throw new AresException('Databáze ARES není dostupná.');
347
        }
348
349
        $ns = $aresResponse->getDocNamespaces();
350
        $data = $aresResponse->children($ns['are']);
351
        $elements = $data->children($ns['dtt'])->V->S;
352
353
        if (!count($elements)) {
354
            throw new AresException('Nic nebylo nalezeno.');
355
        }
356
357
        $records = new AresRecords();
358
        foreach ($elements as $element) {
359
            $record = new AresRecord();
360
            $record->setCompanyId(strval($element->ico));
361
            $record->setTaxId(
362
                ($element->dph ? str_replace('dic=', 'CZ', strval($element->p_dph)) : '')
363
            );
364
            $record->setCompanyName(strval($element->ojm));
365
            //'adresa' => strval($element->jmn));
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
366
            $records[] = $record;
367
        }
368
        file_put_contents($cachedFile, serialize($records));
369
370
        return $records;
371
    }
372
373
    /**
374
     * @param string $cacheStrategy
375
     */
376
    public function setCacheStrategy($cacheStrategy)
377
    {
378
        $this->cacheStrategy = $cacheStrategy;
379
    }
380
381
    /**
382
     * @param bool $debug
383
     */
384
    public function setDebug($debug)
385
    {
386
        $this->debug = $debug;
387
    }
388
389
    /**
390
     * @param int $id
391
     */
392 5
    private function ensureIdIsInteger($id)
393
    {
394 5
        if (!is_int($id)) {
395
            throw new InvalidArgumentException('IČ firmy musí být číslo.');
396
        }
397 5
    }
398
}
399