Issues (3627)

CoreBundle/IpLookup/AbstractLocalDataLookup.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2015 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\CoreBundle\IpLookup;
13
14
use Joomla\Http\HttpFactory;
15
use Mautic\CoreBundle\Form\Type\IpLookupDownloadDataStoreButtonType;
16
use PharData;
17
use PharFileInfo;
18
use RecursiveIteratorIterator;
19
20
/**
21
 * Class AbstractLocalDataLookup.
22
 */
23
abstract class AbstractLocalDataLookup extends AbstractLookup implements IpLookupFormInterface
24
{
25
    /**
26
     * @const TAR_CACHE_FOLDER
27
     */
28
    const TAR_CACHE_FOLDER = 'unpack';
29
30
    /**
31
     * @const TAR_TEMP_FILE
32
     */
33
    const TAR_TEMP_FILE = 'temp.tar.gz';
34
35
    /**
36
     * Path to the local data store.
37
     *
38
     * @return string
39
     */
40
    abstract public function getLocalDataStoreFilepath();
41
42
    /**
43
     * Return the URL to manually download.
44
     *
45
     * @return string
46
     */
47
    abstract public function getRemoteDateStoreDownloadUrl();
48
49
    /**
50
     * @return string
51
     */
52
    public function getConfigFormService()
53
    {
54
        return IpLookupDownloadDataStoreButtonType::class;
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     *
60
     * @return array
61
     */
62
    public function getConfigFormThemes()
63
    {
64
        return [];
65
    }
66
67
    /**
68
     * Download remote data store.
69
     *
70
     * Used by the mautic:iplookup:update_data command and form fetch button (if applicable) to update local IP data stores
71
     *
72
     * @return bool
73
     */
74
    public function downloadRemoteDataStore()
75
    {
76
        $connector = HttpFactory::getHttp();
77
        $package   = $this->getRemoteDateStoreDownloadUrl();
78
79
        try {
80
            $data = $connector->get($package);
81
        } catch (\Exception $exception) {
82
            $this->logger->error('Failed to fetch remote IP data: '.$exception->getMessage());
83
        }
84
85
        $tempTarget        = $this->cacheDir.'/'.basename($package);
86
        $tempExt           = strtolower(pathinfo($package, PATHINFO_EXTENSION));
87
        $localTarget       = $this->getLocalDataStoreFilepath();
88
        $localTargetExt    = strtolower(pathinfo($localTarget, PATHINFO_EXTENSION));
89
90
        try {
91
            $success = false;
92
93
            switch (true) {
94
                case $localTargetExt === $tempExt:
95
                    $success = (bool) file_put_contents($localTarget, $data->body);
96
97
                    break;
98
99
                case $this->endsWith($package, 'tar.gz'):
0 ignored issues
show
$this->endsWith($package, 'tar.gz') is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
100
                    /**
101
                     * If tar.gz it loops whole folder structure and copy the file which has the same basename as
102
                     * desired localTarget.
103
                     */
104
                    $tempTargetFolder = $this->cacheDir.'/'.self::TAR_CACHE_FOLDER;
105
                    $temporaryPhar    = $tempTargetFolder.'/'.self::TAR_TEMP_FILE;
106
                    if (!is_dir($tempTargetFolder)) {
107
                        // dir doesn't exist, make it
108
                        mkdir($tempTargetFolder);
109
                    }
110
                    file_put_contents($temporaryPhar, $data->body);
111
                    $pharData = new PharData($temporaryPhar);
112
                    foreach (new RecursiveIteratorIterator($pharData) as $file) {
113
                        /** @var PharFileInfo $file */
114
                        if ($file->getBasename() === basename($localTarget)) {
115
                            $success = copy($file->getPathname(), $localTarget);
116
                        }
117
                    }
118
                    @unlink($temporaryPhar);
119
120
                    break;
121
122
                case 'gz' == $tempExt:
123
                    $memLimit = $this->sizeInByte(ini_get('memory_limit'));
124
                    $freeMem  = $memLimit - memory_get_peak_usage();
125
                    //check whether there is enough memory to handle large iplookp DB
126
                    // or will throw iplookup exception
127
                    if (function_exists('gzdecode') && strlen($data->body) < ($freeMem / 3)) {
128
                        $success = (bool) file_put_contents($localTarget, gzdecode($data->body));
129
                    } elseif (function_exists('gzopen')) {
130
                        if (file_put_contents($tempTarget, $data->body)) {
131
                            $bufferSize = 4096; // read 4kb at a time
132
                            $file       = gzopen($tempTarget, 'rb');
133
                            $outFile    = fopen($localTarget, 'wb');
134
                            while (!gzeof($file)) {
135
                                fwrite($outFile, gzread($file, $bufferSize));
136
                            }
137
                            fclose($outFile);
138
                            gzclose($file);
139
                            @unlink($tempTarget);
140
                            $success = true;
141
                        }
142
                    }
143
144
                    break;
145
146
                case 'zip' == $tempExt:
147
                    file_put_contents($tempTarget, $data->body);
148
149
                    $zipper = new \ZipArchive();
150
151
                    $zipper->open($tempTarget);
152
                    $success = $zipper->extractTo($localTarget);
153
                    $zipper->close();
154
                    @unlink($tempTarget);
155
                    break;
156
            }
157
        } catch (\Exception $exception) {
158
            error_log($exception);
159
160
            $success = false;
161
        }
162
163
        return $success;
164
    }
165
166
    /**
167
     * Get the common directory for data.
168
     *
169
     * @return string|null
170
     */
171
    protected function getDataDir()
172
    {
173
        if (null !== $this->cacheDir) {
174
            if (!file_exists($this->cacheDir)) {
175
                mkdir($this->cacheDir);
176
            }
177
178
            $dataDir = $this->cacheDir.'/../ip_data';
179
180
            if (!file_exists($dataDir)) {
181
                mkdir($dataDir);
182
            }
183
184
            return $dataDir;
185
        }
186
187
        return null;
188
    }
189
190
    protected function sizeInByte($size)
191
    {
192
        $data = (int) substr($size, 0, -1);
193
        switch (strtoupper(substr($size, -1))) {
194
            case 'K':
195
                return $data * 1024;
196
            case 'M':
197
                return $data * 1024 * 1024;
198
            case 'G':
199
                return $data * 1024 * 1024 * 1024;
200
        }
201
    }
202
203
    /**
204
     * Get if the string ends with.
205
     *
206
     * @param string $haystack
207
     * @param string $needle
208
     *
209
     * @return bool
210
     */
211
    private function endsWith($haystack, $needle)
212
    {
213
        return 0 === substr_compare($haystack, $needle, -strlen($needle));
214
    }
215
}
216