Passed
Push — master ( 842f16...60595a )
by Rubén
12:20 queued 11s
created

modules/web/Controllers/ConfigBackupController.php (5 issues)

1
<?php
2
/**
3
 * sysPass
4
 *
5
 * @author    nuxsmin
6
 * @link      https://syspass.org
7
 * @copyright 2012-2019, Rubén Domínguez nuxsmin@$syspass.org
8
 *
9
 * This file is part of sysPass.
10
 *
11
 * sysPass is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * sysPass is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 *  along with sysPass.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace SP\Modules\Web\Controllers;
26
27
use Exception;
28
use SP\Core\Acl\Acl;
29
use SP\Core\Acl\UnauthorizedPageException;
30
use SP\Core\Context\SessionContext;
31
use SP\Core\Events\Event;
32
use SP\Core\Events\EventMessage;
33
use SP\Core\Exceptions\SessionTimeout;
34
use SP\Core\Exceptions\SPException;
35
use SP\Http\JsonResponse;
36
use SP\Modules\Web\Controllers\Traits\ConfigTrait;
37
use SP\Services\Backup\FileBackupService;
38
use SP\Services\Export\XmlExportService;
39
use SP\Services\Export\XmlVerifyService;
40
use SP\Storage\File\FileHandler;
41
42
/**
43
 * Class ConfigBackupController
44
 *
45
 * @package SP\Modules\Web\Controllers
46
 */
47
final class ConfigBackupController extends SimpleControllerBase
48
{
49
    use ConfigTrait;
50
51
    /**
52
     * @return bool
53
     * @throws SPException
54
     */
55
    public function fileBackupAction()
56
    {
57
        $this->checkSecurityToken($this->previousSk, $this->request);
58
59
        if ($this->config->getConfigData()->isDemoEnabled()) {
60
            return $this->returnJsonResponse(JsonResponse::JSON_WARNING, __u('Ey, this is a DEMO!!'));
61
        }
62
63
        try {
64
            SessionContext::close();
65
66
            $this->dic->get(FileBackupService::class)
67
                ->doBackup(BACKUP_PATH);
68
69
            $this->eventDispatcher->notifyEvent('run.backup.end',
70
                new Event($this, EventMessage::factory()
71
                    ->addDescription(__u('Application and database backup completed successfully')))
72
            );
73
74
            return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Backup process finished'));
75
        } catch (Exception $e) {
76
            processException($e);
77
78
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
79
80
            return $this->returnJsonResponseException($e);
81
        }
82
    }
83
84
    /**
85
     * @return bool
86
     */
87
    public function xmlExportAction()
88
    {
89
        $exportPassword = $this->request->analyzeEncrypted('exportPwd');
90
        $exportPasswordR = $this->request->analyzeEncrypted('exportPwdR');
91
92
        if (!empty($exportPassword) && $exportPassword !== $exportPasswordR) {
93
            return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Passwords do not match'));
94
        }
95
96
        try {
97
            $this->eventDispatcher->notifyEvent('run.export.start',
98
                new Event($this, EventMessage::factory()
99
                    ->addDescription(__u('sysPass XML export')))
100
            );
101
102
            SessionContext::close();
103
104
            $export = $this->dic->get(XmlExportService::class);
105
            $export->doExport(BACKUP_PATH, $exportPassword);
106
107
            $this->eventDispatcher->notifyEvent('run.export.end',
108
                new Event($this, EventMessage::factory()
109
                    ->addDescription(__u('Export process finished')))
110
            );
111
112
            $verify = $this->dic->get(XmlVerifyService::class);
113
114
            if ($export->isEncrypted()) {
115
                $verifyResult = $verify->verifyEncrypted($export->getExportFile(), $exportPassword);
116
            } else {
117
                $verifyResult = $verify->verify($export->getExportFile());
118
            }
119
120
            $nodes = $verifyResult->getNodes();
121
122
            $this->eventDispatcher->notifyEvent('run.export.verify',
123
                new Event($this, EventMessage::factory()
124
                    ->addDescription(__u('Verification of exported data finished'))
125
                    ->addDetail(__u('Version'), $verifyResult->getVersion())
126
                    ->addDetail(__u('Encrypted'), $verifyResult->isEncrypted() ? __u('Yes') : __u('No'))
127
                    ->addDetail(__u('Accounts'), $nodes['Account'])
128
                    ->addDetail(__u('Clients'), $nodes['Client'])
129
                    ->addDetail(__u('Categories'), $nodes['Category'])
130
                    ->addDetail(__u('Tags'), $nodes['Tag'])
131
                )
132
            );
133
134
            // Create the XML archive after verifying the export integrity
135
            $export->createArchive();
136
137
            return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Export process finished'));
138
        } catch (Exception $e) {
139
            processException($e);
140
141
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
142
143
            return $this->returnJsonResponseException($e);
144
        }
145
    }
146
147
    /**
148
     * @return bool
149
     * @throws SPException
150
     */
151
    public function downloadExportAction()
152
    {
153
        $this->checkSecurityToken($this->previousSk, $this->request);
154
155
        try {
156
            SessionContext::close();
157
158
            $filePath = XmlExportService::getExportFilename(BACKUP_PATH, $this->configData->getExportHash(), true);
159
160
            $file = new FileHandler($filePath);
161
            $file->checkFileExists();
162
163
            $this->eventDispatcher->notifyEvent('download.exportFile',
164
                new Event($this, EventMessage::factory()
165
                    ->addDescription(__u('File downloaded'))
166
                    ->addDetail(__u('File'), str_replace(APP_ROOT, '', $file->getFile())))
167
            );
168
169
            $response = $this->router->response();
170
            $response->header('Cache-Control', 'max-age=60, must-revalidate');
171
            $response->header('Content-length', $file->getFileSize());
172
            $response->header('Content-type', $file->getFileType());
173
            $response->header('Content-Description', ' sysPass file');
174
            $response->header('Content-transfer-encoding', 'chunked');
175
            $response->header('Content-Disposition', 'attachment; filename="' . basename($file->getFile()) . '"');
176
            $response->header('Set-Cookie', 'fileDownload=true; path=/');
177
            $response->send();
178
179
            $file->readChunked();
180
        } catch (Exception $e) {
181
            processException($e);
182
183
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
184
        }
185
186
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type boolean.
Loading history...
187
    }
188
189
    /**
190
     * @return bool
191
     * @throws SPException
192
     */
193
    public function downloadBackupAppAction()
194
    {
195
        $this->checkSecurityToken($this->previousSk, $this->request);
196
197
        if ($this->configData->isDemoEnabled()) {
198
            return __('Ey, this is a DEMO!!');
0 ignored issues
show
Bug Best Practice introduced by
The expression return __('Ey, this is a DEMO!!') returns the type string which is incompatible with the documented return type boolean.
Loading history...
199
        }
200
201
        try {
202
            SessionContext::close();
203
204
            $filePath = FileBackupService::getAppBackupFilename(BACKUP_PATH, $this->configData->getBackupHash(), true);
205
206
            $file = new FileHandler($filePath);
207
            $file->checkFileExists();
208
209
            $this->eventDispatcher->notifyEvent('download.backupAppFile',
210
                new Event($this, EventMessage::factory()
211
                    ->addDescription(__u('File downloaded'))
212
                    ->addDetail(__u('File'), str_replace(APP_ROOT, '', $file->getFile())))
213
            );
214
215
            $response = $this->router->response();
216
            $response->header('Cache-Control', 'max-age=60, must-revalidate');
217
            $response->header('Content-length', $file->getFileSize());
218
            $response->header('Content-type', $file->getFileType());
219
            $response->header('Content-Description', ' sysPass file');
220
            $response->header('Content-transfer-encoding', 'chunked');
221
            $response->header('Content-Disposition', 'attachment; filename="' . basename($file->getFile()) . '"');
222
            $response->header('Set-Cookie', 'fileDownload=true; path=/');
223
            $response->send();
224
225
            $file->readChunked();
226
        } catch (Exception $e) {
227
            processException($e);
228
229
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
230
        }
231
232
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type boolean.
Loading history...
233
    }
234
235
    /**
236
     * @return bool
237
     * @throws SPException
238
     */
239
    public function downloadBackupDbAction()
240
    {
241
        $this->checkSecurityToken($this->previousSk, $this->request);
242
243
        if ($this->configData->isDemoEnabled()) {
244
            return __('Ey, this is a DEMO!!');
0 ignored issues
show
Bug Best Practice introduced by
The expression return __('Ey, this is a DEMO!!') returns the type string which is incompatible with the documented return type boolean.
Loading history...
245
        }
246
247
        try {
248
            SessionContext::close();
249
250
            $filePath = FileBackupService::getDbBackupFilename(BACKUP_PATH, $this->configData->getBackupHash(), true);
251
252
            $file = new FileHandler($filePath);
253
            $file->checkFileExists();
254
255
            $this->eventDispatcher->notifyEvent('download.backupDbFile',
256
                new Event($this, EventMessage::factory()
257
                    ->addDescription(__u('File downloaded'))
258
                    ->addDetail(__u('File'), str_replace(APP_ROOT, '', $file->getFile())))
259
            );
260
261
            $response = $this->router->response();
262
            $response->header('Cache-Control', 'max-age=60, must-revalidate');
263
            $response->header('Content-length', $file->getFileSize());
264
            $response->header('Content-type', $file->getFileType());
265
            $response->header('Content-Description', ' sysPass file');
266
            $response->header('Content-transfer-encoding', 'chunked');
267
            $response->header('Content-Disposition', 'attachment; filename="' . basename($file->getFile()) . '"');
268
            $response->header('Set-Cookie', 'fileDownload=true; path=/');
269
            $response->send();
270
271
            $file->readChunked();
272
        } catch (Exception $e) {
273
            processException($e);
274
275
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
276
        }
277
278
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type boolean.
Loading history...
279
    }
280
281
    /**
282
     * initialize
283
     *
284
     * @throws SessionTimeout
285
     */
286
    protected function initialize()
287
    {
288
        try {
289
            $this->checks();
290
            $this->checkAccess(Acl::CONFIG_BACKUP);
291
        } catch (UnauthorizedPageException $e) {
292
            $this->eventDispatcher->notifyEvent('exception', new Event($e));
293
294
            $this->returnJsonResponseException($e);
295
        }
296
    }
297
}