Issues (2687)

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.

Eccube/Controller/Install/InstallController.php (2 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
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.co.jp/
9
 *
10
 * This program is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU General Public License
12
 * as published by the Free Software Foundation; either version 2
13
 * of the License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23
 */
24
25
namespace Eccube\Controller\Install;
26
27
use Doctrine\DBAL\Migrations\Configuration\Configuration;
28
use Doctrine\DBAL\Migrations\Migration;
29
use Doctrine\DBAL\Migrations\MigrationException;
30
use Doctrine\ORM\EntityManager;
31
use Doctrine\ORM\Tools\SchemaTool;
32
use Eccube\Common\Constant;
33
use Eccube\InstallApplication;
34
use Eccube\Util\Str;
35
use Symfony\Component\Filesystem\Filesystem;
36
use Symfony\Component\Finder\Finder;
37
use Symfony\Component\Form\Form;
38
use Symfony\Component\HttpFoundation\Request;
39
use Symfony\Component\Yaml\Yaml;
40
41
class InstallController
42
{
43
44
    const MCRYPT = 'mcrypt';
45
46
    private $app;
47
    private $PDO;
48
    private $config_path;
49
    private $dist_path;
50
    private $cache_path;
51
    private $session_data;
52
    private $required_modules = array('pdo', 'phar', 'mbstring', 'zlib', 'ctype', 'session', 'JSON', 'xml', 'libxml', 'OpenSSL', 'zip', 'cURL', 'fileinfo');
53
    private $recommended_module = array('hash', self::MCRYPT);
54
55
    const SESSION_KEY = 'eccube.session.install';
56
57 7
    public function __construct()
58
    {
59 7
        $this->config_path = __DIR__ . '/../../../../app/config/eccube';
60 7
        $this->dist_path = __DIR__ . '/../../Resource/config';
61 7
        $this->cache_path = __DIR__ . '/../../../../app/cache';
62
    }
63
64 4
    private function isValid(Request $request, Form $form)
65
    {
66 4
        $session = $request->getSession();
67 4
        if ('POST' === $request->getMethod()) {
68
            $form->handleRequest($request);
69
            if ($form->isValid()) {
70
                $sessionData = $session->get(self::SESSION_KEY) ?: array();
71
                $formData = array_replace_recursive($sessionData, $form->getData());
72
                $session->set(self::SESSION_KEY, $formData);
73
74
                return true;
75
            }
76
        }
77
78 4
        return false;
79
    }
80
81 5
    private function getSessionData(Request $request)
82
    {
83 5
        return $this->session_data = $request->getSession()->get(self::SESSION_KEY);
84
    }
85
86
    // 最初からやり直す場合、SESSION情報をクリア
87 1
    public function index(InstallApplication $app, Request $request)
88
    {
89 1
        $request->getSession()->remove(self::SESSION_KEY);
90
91 1
        return $app->redirect($app->path('install_step1'));
92
    }
93
94
    // ようこそ
95 1
    public function step1(InstallApplication $app, Request $request)
96
    {
97 1
        $form = $app['form.factory']
98 1
            ->createBuilder('install_step1')
99 1
            ->getForm();
100 1
        $sessionData = $this->getSessionData($request);
101 1
        $form->setData($sessionData);
102
103 1
        if ($this->isValid($request, $form)) {
104
            return $app->redirect($app->path('install_step2'));
105
        }
106
107 1
        $this->checkModules($app);
108
109 1
        return $app['twig']->render('step1.twig', array(
110 1
                'form' => $form->createView(),
111 1
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
112
        ));
113
    }
114
115
    // 権限チェック
116 1
    public function step2(InstallApplication $app, Request $request)
117
    {
118 1
        $this->getSessionData($request);
119
120 1
        $protectedDirs = $this->getProtectedDirs();
121
122
        // 権限がある場合, キャッシュディレクトリをクリア
123 1
        if (empty($protectedDirs)) {
124 1
            $finder = Finder::create()
125 1
                ->in($this->cache_path)
126 1
                ->directories()
127 1
                ->depth(0);
128 1
            $fs = new Filesystem();
129 1
            $fs->remove($finder);
130
        }
131
132 1
        return $app['twig']->render('step2.twig', array(
133 1
                'protectedDirs' => $protectedDirs,
134 1
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
135
        ));
136
    }
137
138
    //    サイトの設定
139 1
    public function step3(InstallApplication $app, Request $request)
140
    {
141 1
        $form = $app['form.factory']
142 1
            ->createBuilder('install_step3')
143 1
            ->getForm();
144 1
        $sessionData = $this->getSessionData($request);
145
146 1
        if (empty($sessionData['shop_name'])) {
147
148 1
            $config_file = $this->config_path . '/config.yml';
149 1
            $fs = new Filesystem();
150
151 1
            if ($fs->exists($config_file)) {
152
                // すでに登録されていた場合、登録データを表示
153 1
                $this->setPDO();
154 1
                $stmt = $this->PDO->query("SELECT shop_name, email01 FROM dtb_base_info WHERE id = 1;");
155
156 1
                foreach ($stmt as $row) {
157 1
                    $sessionData['shop_name'] = $row['shop_name'];
158 1
                    $sessionData['email'] = $row['email01'];
159
                }
160
161
                // セキュリティの設定
162 1
                $config_file = $this->config_path . '/path.yml';
163 1
                $config = Yaml::parse(file_get_contents($config_file));
164 1
                $sessionData['admin_dir'] = $config['admin_route'];
165
166 1
                $config_file = $this->config_path . '/config.yml';
167 1
                $config = Yaml::parse(file_get_contents($config_file));
168
169 1
                $allowHost = $config['admin_allow_host'];
170 1 View Code Duplication
                if (count($allowHost) > 0) {
171
                    $sessionData['admin_allow_hosts'] = Str::convertLineFeed(implode("\n", $allowHost));
172
                }
173 1
                $sessionData['admin_force_ssl'] = (bool) $config['force_ssl'];
174
175
                // ロードバランサー、プロキシサーバ設定
176 1
                $sessionData['trusted_proxies_connection_only'] = (bool)$config['trusted_proxies_connection_only'];
177 1
                $trustedProxies = $config['admin_allow_host'];
178 1 View Code Duplication
                if (count($trustedProxies) > 0) {
179 1
                    $sessionData['trusted_proxies'] = Str::convertLineFeed(implode("\n", $trustedProxies));
180 1
                }
181 1
182 1
                // メール設定
183 1
                $config_file = $this->config_path . '/mail.yml';
184
                $config = Yaml::parse(file_get_contents($config_file));
185
                $mail = $config['mail'];
186
                $sessionData['mail_backend'] = $mail['transport'];
187
                $sessionData['smtp_host'] = $mail['host'];
188
                $sessionData['smtp_port'] = $mail['port'];
189
                $sessionData['smtp_username'] = $mail['username'];
190 1
                $sessionData['smtp_password'] = $mail['password'];
191 1
            } else {
192
                // 初期値にmailを設定
193
                $sessionData['mail_backend'] = 'mail';
194
            }
195
        }
196
197 1
        $form->setData($sessionData);
198 1
        if ($this->isValid($request, $form)) {
199 1
            $data = $form->getData();
200
201
            return $app->redirect($app->path('install_step4'));
202
        }
203
204 1
        return $app['twig']->render('step3.twig', array(
205
                'form' => $form->createView(),
206 1
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
207 1
        ));
208 1
    }
209
210 1
    //    データベースの設定
211
    public function step4(InstallApplication $app, Request $request)
212 1
    {
213
        $form = $app['form.factory']
214 1
            ->createBuilder('install_step4')
215 1
            ->getForm();
216
217 1
        $sessionData = $this->getSessionData($request);
218
219
        if (empty($sessionData['database'])) {
220 1
221 1
            $config_file = $this->config_path . '/database.yml';
222 1
            $fs = new Filesystem();
223 1
224 1
            if ($fs->exists($config_file)) {
225 1
                // すでに登録されていた場合、登録データを表示
226 1
                // データベース設定
227 1
                $config = Yaml::parse(file_get_contents($config_file));
228 1
                $database = $config['database'];
229
                $sessionData['database'] = $database['driver'];
230
                if ($database['driver'] != 'pdo_sqlite') {
231
                    $sessionData['database_host'] = $database['host'];
232
                    $sessionData['database_port'] = $database['port'];
233 1
                    $sessionData['database_name'] = $database['dbname'];
234
                    $sessionData['database_user'] = $database['user'];
235 1
                    $sessionData['database_password'] = $database['password'];
236
                }
237
            }
238
        }
239
240 1
        $form->setData($sessionData);
241 1
242 1
        if ($this->isValid($request, $form)) {
243
244
            return $app->redirect($app->path('install_step5'));
245
        }
246
247 1
        return $app['twig']->render('step4.twig', array(
248
                'form' => $form->createView(),
249 1
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
250 1
        ));
251 1
    }
252 1
253 1
    //    データベースの初期化
254 1
    public function step5(InstallApplication $app, Request $request)
255 1
    {
256
        set_time_limit(0);
257 1
        $this->app = $app;
258
        $form = $app['form.factory']
259
            ->createBuilder('install_step5')
260
            ->getForm();
261
        $sessionData = $this->getSessionData($request);
262
        $form->setData($sessionData);
263
264
        if ($this->isValid($request, $form)) {
265
266
            $this
267
                ->createDatabaseYamlFile($sessionData)
268
                ->createMailYamlFile($sessionData)
269
                ->createPathYamlFile($sessionData, $request);
270
271
            if (!$form['no_update']->getData()) {
272
                set_time_limit(0);
273
                $this->createConfigYamlFile($sessionData);
274
275
                $this
276
                    ->setPDO()
277
                    ->dropTables()
278
                    ->createTables()
279
                    ->doMigrate()
280
                    ->insert();
281
            } else {
282
                // データベースを初期化しない場合、auth_magicは初期化しない
283
                $this->createConfigYamlFile($sessionData, false);
284
285
                $this
286
                    ->setPDO()
287
                    ->update();
288
            }
289
290
291
            if (isset($sessionData['agree']) && $sessionData['agree'] == '1') {
292
                $host = $request->getSchemeAndHttpHost();
293
                $basePath = $request->getBasePath();
294
                $params = array(
295
                    'http_url' => $host . $basePath,
296
                    'shop_name' => $sessionData['shop_name'],
297
                );
298
299
                $this->sendAppData($params);
300
            }
301 1
            $this->addInstallStatus();
302 1
303 1
            $request->getSession()->remove(self::SESSION_KEY);
304
305
            return $app->redirect($app->path('install_complete'));
306
        }
307
308 1
        return $app['twig']->render('step5.twig', array(
309
                'form' => $form->createView(),
310 1
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
311 1
        ));
312
    }
313 1
314 1
    //    インストール完了
315
    public function complete(InstallApplication $app, Request $request)
316 1
    {
317
        $config_yml = $this->config_path . '/config.yml';
318 1
        $config = Yaml::parse(file_get_contents($config_yml));
319 1
        $config_path = $this->config_path . '/path.yml';
320 1
        $path_yml = Yaml::parse(file_get_contents($config_path));
321
322
        $config = array_replace_recursive($path_yml, $config);
323
324
325
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
326
            Request::setTrustedProxies(array_merge(array($request->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
327 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
328
            Request::setTrustedProxies($config['trusted_proxies']);
329
        }
330
331
        $host = $request->getSchemeAndHttpHost();
332 1
        $basePath = $request->getBasePath();
333
334 1
        $adminUrl = $host . $basePath . '/' . $config['admin_dir'];
335 1
336 1
        return $app['twig']->render('complete.twig', array(
337
                'admin_url' => $adminUrl,
338
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
339
        ));
340 1
    }
341
342
    private function resetNatTimer()
343
    {
344 1
        // NATの無通信タイマ対策(仮)
345 1
        echo str_repeat(' ', 4 * 1024);
346
        ob_flush();
347
        flush();
348
    }
349
350
    private function checkModules($app)
351 1
    {
352
        foreach ($this->required_modules as $module) {
353
            if (!extension_loaded($module)) {
354
                $app->addDanger('[必須] ' . $module . ' 拡張モジュールが有効になっていません。', 'install');
355 1
            }
356
        }
357
358
        if (!extension_loaded('pdo_mysql') && !extension_loaded('pdo_pgsql')) {
359
            $app->addDanger('[必須] ' . 'pdo_pgsql又はpdo_mysql 拡張モジュールを有効にしてください。', 'install');
360 1
        }
361 1
362
        foreach ($this->recommended_module as $module) {
363
            if (!extension_loaded($module)) {
364
                if ($module == self::MCRYPT && PHP_VERSION_ID >= 70100) {
365 1
                    //The mcrypt extension has been deprecated in PHP 7.1.x 
366
                    //http://php.net/manual/en/migration71.deprecated.php
367
                    continue;
368
                }
369
                $app->addInfo('[推奨] '.$module.' 拡張モジュールが有効になっていません。', 'install');
370
            }
371 1
        }
372
373 1
        if ('\\' === DIRECTORY_SEPARATOR) { // for Windows
374
            if (!extension_loaded('wincache')) {
375
                $app->addInfo('[推奨] WinCache 拡張モジュールが有効になっていません。', 'install');
376
            }
377
        } else {
378 1
            if (!extension_loaded('apc')) {
379
                $app->addInfo('[推奨] APC 拡張モジュールが有効になっていません。', 'install');
380 1
            }
381 1
        }
382
383
        if (isset($_SERVER['SERVER_SOFTWARE']) && strpos('Apache', $_SERVER['SERVER_SOFTWARE']) !== false) {
384 1
            if (!function_exists('apache_get_modules')) {
385 1
                $app->addWarning('mod_rewrite が有効になっているか不明です。', 'install');
386
            } elseif (!in_array('mod_rewrite', apache_get_modules())) {
387
                $app->addDanger('[必須] ' . 'mod_rewriteを有効にしてください。', 'install');
388
            }
389
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos('Microsoft-IIS', $_SERVER['SERVER_SOFTWARE']) !== false) {
390
            // iis
391 1
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos('nginx', $_SERVER['SERVER_SOFTWARE']) !== false) {
392
            // nginx
393
        }
394
    }
395
396
    private function setPDO()
397
    {
398
        $config_file = $this->config_path . '/database.yml';
399
        $config = Yaml::parse(file_get_contents($config_file));
400
401
        try {
402
            $this->PDO = \Doctrine\DBAL\DriverManager::getConnection($config['database'], new \Doctrine\DBAL\Configuration());
403
            $this->PDO->connect();
404
        } catch (\Exception $e) {
405
            $this->PDO->close();
406
            throw $e;
407
        }
408
409
        return $this;
410
    }
411
412 View Code Duplication
    private function dropTables()
413
    {
414
        $this->resetNatTimer();
415
416
        $em = $this->getEntityManager();
417
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
418
        $schemaTool = new SchemaTool($em);
419
420
        $schemaTool->dropSchema($metadatas);
421
422
        $em->getConnection()->executeQuery('DROP TABLE IF EXISTS doctrine_migration_versions');
423
424
        return $this;
425
    }
426
427
    /**
428
     * @return EntityManager
429
     */
430
    private function getEntityManager()
431
    {
432
        $config_file = $this->config_path . '/database.yml';
433
        $database = Yaml::parse(file_get_contents($config_file));
434
435
        $this->app->register(new \Silex\Provider\DoctrineServiceProvider(), array(
436
            'db.options' => $database['database']
437
        ));
438
439
        $this->app->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
440
            'orm.proxies_dir' => __DIR__ . '/../../app/cache/doctrine',
441
            'orm.em.options' => array(
442
                'mappings' => array(
443
                    array(
444
                        'type' => 'yml',
445
                        'namespace' => 'Eccube\Entity',
446
                        'path' => array(
447
                            __DIR__ . '/../../Resource/doctrine',
448
                            __DIR__ . '/../../Resource/doctrine/master',
449
                        ),
450
                    ),
451
                ),
452
            )
453
        ));
454
455
        return $em = $this->app['orm.em'];
456
    }
457
458 View Code Duplication
    private function createTables()
459
    {
460
        $this->resetNatTimer();
461
462
        $em = $this->getEntityManager();
463
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
464
        $schemaTool = new SchemaTool($em);
465
466
        $schemaTool->createSchema($metadatas);
467
468
        return $this;
469
    }
470
471
    private function insert()
472
    {
473
        $this->resetNatTimer();
474
475
        $config_file = $this->config_path . '/database.yml';
476
        $database = Yaml::parse(file_get_contents($config_file));
477
        $config['database'] = $database['database'];
478
479
        $config_file = $this->config_path . '/config.yml';
480
        $baseConfig = Yaml::parse(file_get_contents($config_file));
481
        $config['config'] = $baseConfig;
482
483
        $this->PDO->beginTransaction();
484
485
        try {
486
487
            $config = array(
488
                'auth_type' => '',
489
                'auth_magic' => $config['config']['auth_magic'],
490
                'password_hash_algos' => 'sha256',
491
            );
492
            $passwordEncoder = new \Eccube\Security\Core\Encoder\PasswordEncoder($config);
493
            $salt = \Eccube\Util\Str::random(32);
494
495
            $encodedPassword = $passwordEncoder->encodePassword($this->session_data['login_pass'], $salt);
496
            $sth = $this->PDO->prepare('INSERT INTO dtb_base_info (
497
                id,
498
                shop_name,
499
                email01,
500
                email02,
501
                email03,
502
                email04,
503
                update_date,
504
                option_product_tax_rule
505
            ) VALUES (
506
                1,
507
                :shop_name,
508
                :admin_mail,
509
                :admin_mail,
510
                :admin_mail,
511
                :admin_mail,
512
                current_timestamp,
513
                0);');
514
            $sth->execute(array(
515
                ':shop_name' => $this->session_data['shop_name'],
516
                ':admin_mail' => $this->session_data['email']
517
            ));
518
519
            $sth = $this->PDO->prepare("INSERT INTO dtb_member (member_id, login_id, password, salt, work, del_flg, authority, creator_id, rank, update_date, create_date,name,department) VALUES (2, :login_id, :admin_pass , :salt , '1', '0', '0', '1', '1', current_timestamp, current_timestamp,'管理者','EC-CUBE SHOP');");
520
            $sth->execute(array(':login_id' => $this->session_data['login_id'], ':admin_pass' => $encodedPassword, ':salt' => $salt));
521
522
            $this->PDO->commit();
523
        } catch (\Exception $e) {
524
            $this->PDO->rollback();
525
            throw $e;
526
        }
527
528
        return $this;
529
    }
530
531
    private function update()
532
    {
533
        $this->resetNatTimer();
534
535
        $config_file = $this->config_path . '/database.yml';
536
        $database = Yaml::parse(file_get_contents($config_file));
537
        $config['database'] = $database['database'];
538
539
        $config_file = $this->config_path . '/config.yml';
540
        $baseConfig = Yaml::parse(file_get_contents($config_file));
541
        $config['config'] = $baseConfig;
542
543
        $this->PDO->beginTransaction();
544
545
        try {
546
547
            $config = array(
548
                'auth_type' => '',
549
                'auth_magic' => $config['config']['auth_magic'],
550
                'password_hash_algos' => 'sha256',
551
            );
552
            $passwordEncoder = new \Eccube\Security\Core\Encoder\PasswordEncoder($config);
553
            $salt = \Eccube\Util\Str::random(32);
554
555
            $stmt = $this->PDO->prepare("SELECT member_id FROM dtb_member WHERE login_id = :login_id;");
556
            $stmt->execute(array(':login_id' => $this->session_data['login_id']));
557
            $rs = $stmt->fetch();
558
559
            $encodedPassword = $passwordEncoder->encodePassword($this->session_data['login_pass'], $salt);
560
561
            if ($rs) {
562
                // 同一の管理者IDであればパスワードのみ更新
563
                $sth = $this->PDO->prepare("UPDATE dtb_member set password = :admin_pass, salt = :salt, update_date = current_timestamp WHERE login_id = :login_id;");
564
                $sth->execute(array(':admin_pass' => $encodedPassword, ':salt' => $salt, ':login_id' => $this->session_data['login_id']));
565
            } else {
566
                // 新しい管理者IDが入力されたらinsert
567
                $sth = $this->PDO->prepare("INSERT INTO dtb_member (login_id, password, salt, work, del_flg, authority, creator_id, rank, update_date, create_date,name,department) VALUES (:login_id, :admin_pass , :salt , '1', '0', '0', '1', '1', current_timestamp, current_timestamp,'管理者','EC-CUBE SHOP');");
568
                $sth->execute(array(':login_id' => $this->session_data['login_id'], ':admin_pass' => $encodedPassword, ':salt' => $salt));
569
            }
570
571
            $sth = $this->PDO->prepare('UPDATE dtb_base_info set
572
                shop_name = :shop_name,
573
                email01 = :admin_mail,
574
                email02 = :admin_mail,
575
                email03 = :admin_mail,
576
                email04 = :admin_mail,
577
                update_date = current_timestamp
578
            WHERE id = 1;');
579
            $sth->execute(array(
580
                ':shop_name' => $this->session_data['shop_name'],
581
                ':admin_mail' => $this->session_data['email']
582
            ));
583
584
            $this->PDO->commit();
585
        } catch (\Exception $e) {
586
            $this->PDO->rollback();
587
            throw $e;
588
        }
589
590
        return $this;
591
    }
592
593
    private function getMigration()
594
    {
595
        $app = \Eccube\Application::getInstance();
596
        $app->initialize();
597
        $app->boot();
598
599
        $config = new Configuration($app['db']);
600
        $config->setMigrationsNamespace('DoctrineMigrations');
601
602
        $migrationDir = __DIR__ . '/../../Resource/doctrine/migration';
603
        $config->setMigrationsDirectory($migrationDir);
604
        $config->registerMigrationsFromDirectory($migrationDir);
605
606
        $migration = new Migration($config);
607
608
        return $migration;
609
    }
610
611
    private function doMigrate()
612
    {
613 1
        try {
614
            $migration = $this->getMigration();
615 1
616 1
            // DBとのコネクションを維持するためpingさせる
617
            if (is_null($this->PDO)) {
618 1
                $this->setPDO();
619
            }
620
            $this->PDO->ping();
621
622
            // nullを渡すと最新バージョンまでマイグレートする
623
            $migration->migrate(null, false);
624
        } catch (MigrationException $e) {
625
            
626
        }
627
628 1
        return $this;
629 1
    }
630 1
631
    private function getProtectedDirs()
632
    {
633
        $protectedDirs = array();
634 1
        $base = __DIR__ . '/../../../..';
635
        $dirs = array(
636
            '/html',
637
            '/app',
638
            '/app/template',
639
            '/app/cache',
640
            '/app/config',
641
            '/app/config/eccube',
642
            '/app/log',
643
            '/app/Plugin',
644
        );
645
646
        foreach ($dirs as $dir) {
647
            if (!is_writable($base . $dir)) {
648
                $protectedDirs[] = $dir;
649
            }
650
        }
651
652
        return $protectedDirs;
653
    }
654
655
    private function createConfigYamlFile($data, $auth = true)
656
    {
657
        $fs = new Filesystem();
658
        $config_file = $this->config_path . '/config.yml';
659
660
        if ($fs->exists($config_file)) {
661
            $config = Yaml::parse(file_get_contents($config_file));
662
            $fs->remove($config_file);
663
        }
664
665
        if ($auth) {
666
            $auth_magic = Str::random(32);
667
        } else {
668
            if (isset($config['auth_magic'])) {
669
                $auth_magic = $config['auth_magic'];
670
            } else {
671
                $auth_magic = Str::random(32);
672
            }
673
        }
674
675
        $allowHost = Str::convertLineFeed($data['admin_allow_hosts']);
676
        if (empty($allowHost)) {
677
            $adminAllowHosts = array();
678
        } else {
679
            $adminAllowHosts = explode("\n", $allowHost);
680
        }
681
        $trustedProxies = Str::convertLineFeed($data['trusted_proxies']);
682
        if (empty($trustedProxies)) {
683
            $adminTrustedProxies = array();
684
        } else {
685
            $adminTrustedProxies = explode("\n", $trustedProxies);
686
            // ループバックアドレスを含める
687
            $adminTrustedProxies = array_merge($adminTrustedProxies, array('127.0.0.1/8', '::1'));
688
        }
689
        if ($data['trusted_proxies_connection_only']) {
690
            // ループバックアドレスを含める
691
            $adminTrustedProxies = array('127.0.0.1/8', '::1');
692
        }
693
694
        $target = array('${AUTH_MAGIC}', '${SHOP_NAME}', '${ECCUBE_INSTALL}', '${FORCE_SSL}', '${TRUSTED_PROXIES_CONNECTION_ONLY}');
695
        $replace = array($auth_magic, $data['shop_name'], '0', $data['admin_force_ssl'], $data['trusted_proxies_connection_only']);
696
697
        $fs = new Filesystem();
698
        $content = str_replace(
699
            $target, $replace, file_get_contents($this->dist_path . '/config.yml.dist')
700
        );
701
        $fs->dumpFile($config_file, $content);
702
703
        $config = Yaml::parse(file_get_contents($config_file));
704
        $config['admin_allow_host'] = $adminAllowHosts;
705
        $config['trusted_proxies'] = $adminTrustedProxies;
706
        $yml = Yaml::dump($config);
707
        file_put_contents($config_file, $yml);
708
709
        return $this;
710
    }
711
712
    private function addInstallStatus()
713
    {
714
        $config_file = $this->config_path . '/config.yml';
715
        $config = Yaml::parse(file_get_contents($config_file));
716
        $config['eccube_install'] = 1;
717
        $yml = Yaml::dump($config);
718
        file_put_contents($config_file, $yml);
719
720
        return $this;
721
    }
722
723
    private function createDatabaseYamlFile($data)
724
    {
725
        $fs = new Filesystem();
726
        $config_file = $this->config_path . '/database.yml';
727
        if ($fs->exists($config_file)) {
728
            $fs->remove($config_file);
729
        }
730
731
        if ($data['database'] != 'pdo_sqlite') {
732
            switch ($data['database'])
733
            {
734
                case 'pdo_pgsql':
735
                    if (empty($data['db_port'])) {
736
                        $data['db_port'] = '5432';
737
                    }
738
                    $data['db_driver'] = 'pdo_pgsql';
739
                    break;
740
                case 'pdo_mysql':
741
                    if (empty($data['db_port'])) {
742
                        $data['db_port'] = '3306';
743
                    }
744
                    $data['db_driver'] = 'pdo_mysql';
745
                    break;
746
            }
747
            $target = array('${DBDRIVER}', '${DBSERVER}', '${DBNAME}', '${DBPORT}', '${DBUSER}', '${DBPASS}');
748
            $replace = array(
0 ignored issues
show
Add a comma after each item in a multi-line array
Loading history...
749
                $data['db_driver'],
750
                $data['database_host'],
751
                $data['database_name'],
752
                $data['database_port'],
753
                $data['database_user'],
754
                $data['database_password']
755
            );
756
757
            $fs = new Filesystem();
758
            $content = str_replace(
759
                $target, $replace, file_get_contents($this->dist_path . '/database.yml.dist')
760
            );
761
        } else {
762
            $content = Yaml::dump(
763
                    array(
764
                        'database' => array(
0 ignored issues
show
Add a comma after each item in a multi-line array
Loading history...
765
                            'driver' => 'pdo_sqlite',
766
                            'path' => realpath($this->config_path . '/eccube.db')
767
                        )
768
                    )
769
            );
770
        }
771
        $fs->dumpFile($config_file, $content);
772
773
        return $this;
774
    }
775
776
    private function createMailYamlFile($data)
777
    {
778
        $fs = new Filesystem();
779
        $config_file = $this->config_path . '/mail.yml';
780
        if ($fs->exists($config_file)) {
781
            $fs->remove($config_file);
782
        }
783
        $target = array('${MAIL_BACKEND}', '${MAIL_HOST}', '${MAIL_PORT}', '${MAIL_USER}', '${MAIL_PASS}');
784
        $replace = array(
785
            $data['mail_backend'],
786
            $data['smtp_host'],
787
            $data['smtp_port'],
788
            $data['smtp_username'],
789
            $data['smtp_password']
790
        );
791
792
        $fs = new Filesystem();
793
        $content = str_replace(
794
            $target, $replace, file_get_contents($this->dist_path . '/mail.yml.dist')
795
        );
796
        $fs->dumpFile($config_file, $content);
797
798
        return $this;
799
    }
800
801
    private function createPathYamlFile($data, Request $request)
802
    {
803
        $fs = new Filesystem();
804
        $config_file = $this->config_path . '/path.yml';
805
        if ($fs->exists($config_file)) {
806
            $fs->remove($config_file);
807
        }
808
809
        $ADMIN_ROUTE = $data['admin_dir'];
810
        $TEMPLATE_CODE = 'default';
811
        $USER_DATA_ROUTE = 'user_data';
812
        $ROOT_DIR = realpath(__DIR__ . '/../../../../');
813
        $ROOT_URLPATH = $request->getBasePath();
814
        $ROOT_PUBLIC_URLPATH = $ROOT_URLPATH . RELATIVE_PUBLIC_DIR_PATH;
815
816
        $target = array('${ADMIN_ROUTE}', '${TEMPLATE_CODE}', '${USER_DATA_ROUTE}', '${ROOT_DIR}', '${ROOT_URLPATH}', '${ROOT_PUBLIC_URLPATH}');
817
        $replace = array($ADMIN_ROUTE, $TEMPLATE_CODE, $USER_DATA_ROUTE, $ROOT_DIR, $ROOT_URLPATH, $ROOT_PUBLIC_URLPATH);
818
819
        $fs = new Filesystem();
820
        $content = str_replace(
821
            $target, $replace, file_get_contents($this->dist_path . '/path.yml.dist')
822
        );
823
        $fs->dumpFile($config_file, $content);
824
825
        return $this;
826
    }
827
828
    private function sendAppData($params)
829
    {
830
        $config_file = $this->config_path . '/database.yml';
831
        $db_config = Yaml::parse(file_get_contents($config_file));
832
833
        $this->setPDO();
834
        $stmt = $this->PDO->query('select version() as v');
835
836
        $version = '';
837
        foreach ($stmt as $row) {
838
            $version = $row['v'];
839
        }
840
841
        if ($db_config['database']['driver'] === 'pdo_mysql') {
842
            $db_ver = 'MySQL:' . $version;
843
        } else {
844
            $db_ver = $version;
845
        }
846
847
        $data = http_build_query(
848
            array(
849
                'site_url' => $params['http_url'],
850
                'shop_name' => $params['shop_name'],
851
                'cube_ver' => Constant::VERSION,
852
                'php_ver' => phpversion(),
853
                'db_ver' => $db_ver,
854
                'os_type' => php_uname(),
855
            )
856
        );
857
858
        $header = array(
859
            'Content-Type: application/x-www-form-urlencoded',
860
            'Content-Length: ' . strlen($data),
861
        );
862
        $context = stream_context_create(
863
            array(
864
                'http' => array(
865
                    'method' => 'POST',
866
                    'header' => $header,
867
                    'content' => $data,
868
                )
869
            )
870
        );
871
        file_get_contents('http://www.ec-cube.net/mall/use_site.php', false, $context);
872
873
        return $this;
874
    }
875
876
    /**
877
     * マイグレーション画面を表示する.
878
     *
879
     * @param InstallApplication $app
880
     * @param Request $request
881
     *
882
     * @return \Symfony\Component\HttpFoundation\Response
883
     */
884
    public function migration(InstallApplication $app, Request $request)
885
    {
886
        return $app['twig']->render('migration.twig', array(
887
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
888
        ));
889
    }
890
891
    /**
892
     * インストール済プラグインの一覧を表示する.
893
     * プラグインがインストールされていない場合は, マイグレーション実行画面へリダイレクトする.
894
     *
895
     * @param InstallApplication $app
896
     * @param Request $request
897
     *
898
     * @return \Symfony\Component\HttpFoundation\Response
899
     */
900
    public function migration_plugin(InstallApplication $app, Request $request)
901
    {
902
        $eccube = \Eccube\Application::getInstance();
903
        $eccube->initialize();
904
        $eccube->boot();
905
906
        $pluginRepository = $eccube['orm.em']->getRepository('Eccube\Entity\Plugin');
907
        $Plugins = $pluginRepository->findBy(array('del_flg' => Constant::DISABLED));
908
909
        if (empty($Plugins)) {
910
            // インストール済プラグインがない場合はマイグレーション実行画面へリダイレクト.
911
            return $app->redirect($app->path('migration_end'));
912
        } else {
913
            return $app['twig']->render('migration_plugin.twig', array(
914
                    'Plugins' => $Plugins,
915
                    'version' => Constant::VERSION,
916
                    'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
917
            ));
918
        }
919
    }
920
921
    /**
922
     * マイグレーションを実行し, 完了画面を表示させる
923
     *
924
     * @param InstallApplication $app
925
     * @param Request $request
926
     *
927
     * @return \Symfony\Component\HttpFoundation\Response
928
     */
929
    public function migration_end(InstallApplication $app, Request $request)
930
    {
931
        $this->doMigrate();
932
933
        $config_app = new \Eccube\Application(); // install用のappだとconfigが取れないので
934
        $config_app->initialize();
935
        $config_app->boot();
936
        \Eccube\Util\Cache::clear($config_app, true);
937
938
        return $app['twig']->render('migration_end.twig', array(
939
                'publicPath' => '..' . RELATIVE_PUBLIC_DIR_PATH . '/',
940
        ));
941
    }
942
}
943